Musson Industrial's Embr-Periscope Module

Embr-Periscope

An Ignition module that includes design extensions and enhancements for Perspective.

A periscope provides a new perspective by allowing users to see over, around, or through obstacles, offering a unique view otherwise obstructed.

NOTE: This modules is still in pre-release. All versions before v1.0.0 should be considered unstable.

Components

Embedded View +

This component is a enhancement of the default Embedded View component with server-side property mapping. In testing, this reduced property transit time on a locally hosted gateway from ~100ms per view layer to ~0.220ms.

Flex Repeater +

This component is a enhancement of the default Flex Repeater component with server-side property mapping.

Additionally, it supports per-instance view paths, sharing of common parameters into all views, manually specified instance keys, and component functions for removing, adding, and inserting instances.

Swiper

Swiper is the most modern free and open source mobile touch slider with hardware accelerated transitions and amazing native behavior.

This component merges Swiper's functionality with that of a Flex Repeater.

Docs

https://docs.mussonindustrial.com/ignition/embr-periscope

Sponsorship

If you benefit from this module for commercial use, we ask you to consider sponsoring our efforts through GitHub sponsors . Your support will allow us to continue development of open-source modules and tools that benefit the entire community (plus there are some bonuses for sponsors :slightly_smiling_face:).

Download

Embr-Periscope-0.4.1.modl
The latest release can always been found on GitHub:

12 Likes

Here's a gun, don't shoot yourself with it. This uses the same function constructor as my Chart.js module.

system.perspective.runJavaScriptBlocking(function, [args])

Runs a JavaScript function in the client's page and returns the result, blocking for the result. function is a literal string containing a single arrow function. args is an optional dictionary, where the keys correspond to the names of the function arguments.

system.perspective.runJavaScriptAsync(function, [args], [callback])

Same as above, but calls a callback with the result (non-blocking).


Examples

Blocking Example

# Button [onActionPerformed]
def runAction(self, event):
	code = '''(count) =>
	console.log(`The current count is ${count}`);
	return count + 1;
	'''
	
	count = 0
	
	for i in range(500):
		
		count = system.perspective.runJavaScriptBlocking(code, { 
			'count': count
		})
		
		self.props.text = count

Async Example

# Button [onActionPerformed]
def runAction(self, event):
	code = '''(count) =>
	const start = window.performance.now();
	
	sum = 0
	for (let i = 0; i < count; i++) {
		sum += i;
		console.log(i);
	}
	
	const end = window.performance.now();
	return {
		sum,
		duration: end - start
	}
	'''
		
	count = 500000
		
	def cb(result):
		message = 'Total: {sum}, Duration: {duration:.2f}ms'.format(**result)
		self.props.text = message
		
	system.perspective.runJavaScriptAsync(code, { 'count': count }, cb)

Function Globals

All functions have access to the Perspective client store through a globally scoped variable client.

Function Globals Example

# Button [onActionPerformed]
def runAction(self, event):
	code = '''() =>
	return client.projectName;
	'''
	
	self.props.text = system.perspective.runJavaScriptBlocking(code)

Lightly tested.

Embr-Periscope-0.4.2-BETA.modl (2.0 MB)

5 Likes

runJavaScriptAsync and runJavaScriptBlocking are fully merged.

Embr-Periscope-0.4.3.modl
(Oops, changed timeout units without updating the value. A 30 second timeout became a 30,000 second timeout :upside_down_face:)
Embr-Periscope-0.4.4.modl

Improvements:

  • Support for async JavaScript function defintions. You can either directly specify your function definition as async:
 async (param1, param2) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(param1 + param2)
    }, 3000)
  })

  return await promise
}	

Or you can return a promise:

(param1, param2) => {
  const promise = new Promise((resolve) => {
    setTimeout(() => {
      resolve(param1 + param2)
    }, 3000)
  })
  return promise
}

Either way, once the promise is resolved the gateway will be notified (unblocking or running the callback, depending on which version you called).

  • If any errors are thrown in your JavaScript, the stack trace is displayed in the designer.
  • Support for specifying sessionId/pageId for execution on arbitrary pages.

Documentation site will be updated soon.

(For the folks paying attention, this idea will be the basis accessing methods of the Chart.js object in my embr-charts module. You will have access to a ClientChartProxy object that you can manipulate fairly directly, calling methods/updating properties.)

4 Likes