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)
1 Like

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();
				}
		});		
	}'''

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')"

2 Likes