Javascript inject in Perspective... have fun

and pain point!! (my op case in point)

Another question, JS hack or otherwise, is: how can I use JS to set the value of a component prop?

It may seem like a dumb thing to do, but I'm having nothing but issues defaulting BIJC's Calendar component to show a date in a binding, or the type of view to display. It's driving me insane. I figure I can force it in the same way that my focus example works above works...

I've been using JS injection to allow inserting text at the cursor within a Text Area:

def transform(self, value, quality, timestamp):
	return "<img style='display: none' src='/favicon.ico' onload=\" \
		const view = [...window.__client.page.views._data.values()].find(view => view.value.mountPath == this.parentNode.parentNode.parentNode.getAttributeNode('data-component-path').value.split('.')[0]).value; \
		const notesTextArea = document.getElementById('" + value + "'); \
		function getSelected() { \
			const selectionStart = notesTextArea.selectionStart; \
			view.custom.write('selectionStart', selectionStart); \
			const selectionEnd = notesTextArea.selectionEnd; \
			view.custom.write('selectionEnd', selectionEnd); \
		} \
		function reportSel() { \
			setCursorAt = view.custom.read('setCursorAt'); \
			if (setCursorAt > -1) { \
				notesTextArea.blur(); \
				notesTextArea.setSelectionRange(setCursorAt, setCursorAt); \
				notesTextArea.focus(); \
				getSelected(); \
				view.custom.write('setCursorAt', -1); \
			} \
			if (view.custom.read('runJS')) \
				setTimeout(() => { reportSel(); }, 10); \
		} \
		notesTextArea.onclick = getSelected; \
		notesTextArea.onkeyup = getSelected; \
		notesTextArea.oncontextmenu = getSelected; \
		notesTextArea.onmouseout = getSelected; \
		view.custom.write('runJS', true); \
		reportSel(); \"></img>"

You can see how view.custom.write() is used to set a custom property on the view.

As far as the question of trying to focus components "on load," that's something I've struggled with and put a request in for a proper event handler:

1 Like

It's possible; the easiest way I know is by sending a message, then using a message handler to write to the property.

To send a message from a client using JavaScript:

// type MessageScope = 'view' | 'page' | 'session'

__client.connection.send('send-message', {
    'type': 'MyMessageType',
    'payload': { 'key': 'value' },
    'scope': 'page'
})

If you need to do this in Periscope's JavaScripting contexts, you can also use the helper function:

perspective.sendMessage(type, payload, scope)
3 Likes

untested, but you could probably use @bmusson Js script to trigger this

function = '''(domId)=>{
		window.addEventListener("load", (event) => {
		 const element = document.getElementById(domId);
				console.log(element)
				if (element){
					console.log('focusing element');
					element.focus();
				}
		});		
	}'''

1 Like

Interesting solution!

I myself had been pretty bummed that Ignition didn't support Serial Port communication from the Client PC, but later realized it was mostly a limitation of the browsers.

Now knowing that, I set out to attempt to make use of the Web Serial API of Chromium, using Javascript.

It's a bit unrefined as the Javascript in the OnClick, could be placed in a separate .JS file, but I'll share it as a proof of concept in honor of this thread!

Also, apologies for the params on the View, they could've been in an array, but this was an attempt to try out to make it configurable, as we were trying to make it a base component to use across our projects.

Web Serial API Test.zip (13.6 KB)

Quick note, as a limitation of the Web Serial API, the requestPort is only allowed on a secure HTTPS connection.
So attempting to use this functionality on an HTTP connection, you'll get the console error in the browser of "Cannot read properties of undefined (reading 'requestPort')"

3 Likes

Hello everyone, may I ask if the Javascript injection method is feasible in IgnitionScada8.3? Has anyone tested it?

Markdown injection certainly works

Thank you very much. The markdown method has been successfully tested, but we were unable to test the global injection method in version 8.3 temporarily. Is there a problem with my method?

you can test it with this i think, it was pretty easy to follow

I haven’t tried it on 8.3; I’m not doing anything with 8.3 yet besides supporting modules.

Thank you for your replies. In version 8.1, I used: "C:\Program Files\Inductive Automation\Ignition\data\modules\com.inductiveautomation.perspective\injectables" The injection of the "head_top.txt" file into the test was successful, but there were some changes in the file path in version 8.3. I tried to insert it into the path: "C:\Program Files\Inductive Automation\Ignition\data\config\resources\core\com.inductiveautomation.perspective\injectables" Injecting the same "head_top.txt" file into the system did not work. I wonder if there is a problem with my method?

If I had to guess, I'd bet this "injectables" folder got ignored for the 8.3 configuration changes and the path is still data\modules\com.inductiveautomation.perspective\injectables :man_shrugging:

I'm going to quote this post from Paul here:

Specifically this part:

Anything you do use this for should be considered unsupported.

2 Likes

Okay, thank you for your reply

1 Like

That's correct from the code.

2 Likes

:man_mage:

I attempted to manually create this file path and it has been successfully tested. Thank you very much

2 Likes

I wonder if it gets backed up with gwbk..