A topic that I've seen posted quite a few times is "How do I get a custom symbol to change other symbols on the display?"  Without the knowledge of what's available to you, it can seem like a tricky or impossible task.  Once you know how to do it, it actually becomes quite easy. To get you started, I've written a couple of fun/useless symbols to show you the basics.  I may expand/improve the list in the future because I'm constantly learning new things about PI Vision Extensibility.

 

The Big Red Button

 

What does it do?

delete.gif

It deletes everything on your display when clicked.  It should go without saying but please don't use this on any production displays.

How does it work?

It uses the displayProvider to select all of the symbols in the display and subsequently loops though and deletes all selected symbols.

The code

HTML:

<div id="bigredbutton" ng-click="pressed()"> DELETE </div>

JS:

window.PIVisualization = window.PIVisualization || {};
(function (PV) {
     'use strict';

     function symbolVis() { }
     PV.deriveVisualizationFromBase(symbolVis);
     symbolVis.prototype.init = function (scope, elem, displayProvider, $rootScope)
          scope.pressed = function(){
               displayProvider.selectAll();
               displayProvider.getSelectedSymbols().forEach(function(sym){
                    displayProvider.removeSymbol(sym);
               });
          }
     }

     var def = {
          typeName: 'bigredbutton',
          datasourceBehavior: PV.Extensibility.Enums.DatasourceBehaviors.Single,
          visObjectType: symbolVis,
          inject: [ 'displayProvider', '$rootScope'],
          getDefaultConfig: function(){
               return{
                    DataShape: 'Value',
                    Height: 150,
                    Width: 150
               };
          }
     };
     PV.symbolCatalog.register(def);
})(window.PIVisualization);

 

The Add DataStream Button

What does it do?

AddData.gif

When the add button is hit, it searches the display for all symbols that support multiple data streams.  It then adds whatever tag or attribute is in the textbox as a datastream to each of the found symbols.

How does it work?

It uses the displayProvider to select all of the symbols in the display and subsequently loops though, checks if the DatasourceBehavior allows multiple data sources, pushes the new data source, and then deselects the symbol.

The code

HTML:

<div id='add-data-source-container'>
     <input type='text' class='text-input' ng-model='newdatasource.text' placeholder='pi:\\servername\tagname'/>
     <button class='submit-button' ng-click="add()"> Add </button>
</div>

JS:

Note: Everything except the init function is the same as the previous symbol.  For brevity, just the init function is shown.

scope.newdatasource = {
     text: ""
};

scope.add = function(){
     displayProvider.selectAll();
     displayProvider.getSelectedSymbols().forEach(function(sym){
          //check if this symbol supports multiple datasources
          if(displayProvider.getRuntimeSymbolData(sym).def.datasourceBehavior == PV.Extensibility.Enums.DatasourceBehaviors.Multiple){
               //add the datasource from the textbox
               displayProvider.getSymbolByName(sym).DataSources.push(scope.newdatasource.text);
          }
          //deselect this symbol
          displayProvider.toggleSymbolSelection(sym);
     });
}

 

The Chatting Symbols

What does it do?

SymbolComm.gif

The name of a receiver symbol (which must be of the same type) is entered into the top box along with a message in the bottom box.  Upon clicking "Send", that message is displayed in the destination's bottom box along with who sent it (in the top box).

How does it work?

This symbol is starting to show some real power.  We're modifying the receiver's scope to change its values in real time.

Before we get to the code

There is a behavior in Angular which makes reading another DOM element's scope impossible unless debugInfoEnabled is set to true.  In order for this symbol to work, you will need to edit a line in PIVisualization.app.js changing:

$compileProvider.debugInfoEnabled(enable);

to

$compileProvider.debugInfoEnabled(true);

Be aware that this may cause a performance decrease.

The code

HTML:

<div id='sayhi-source-container'>
     <input type='text' class='text-input receiver' ng-model='message.receiver' ng-click='receiverboxclicked()' placeholder='symbol name of receiver'/>
     <input type='text' class='text-input message' ng-model='message.text' placeholder='type message to receiver'/>
     <button class='submit-button' ng-click="sayhi()"> Send </button>
</div>

JS:

Note: Everything except the init function is the same as the the big red button symbol. For brevity, just the init function is shown.

var name = this.runtime.name;

scope.message = {
     receiver: "",
     text: ""
};

scope.receiverboxclicked = function(){
     scope.message.receiver = scope.message.receiver.replace(' says:','');
     scope.message.text = '';
}

scope.sayhi = function(){
     var receiver = $('#'+scope.message.receiver);
     if(receiver.length > 0){
          var receiver_scope = receiver.scope();
          if(receiver_scope.message){
               receiver_scope.message.receiver = name + " says:";
               receiver_scope.message.text = scope.message.text;
          }
          else{
               alert(name + "'s receiver, " + scope.message.receiver + ", is not of type 'sayhi' ");
          }
     }
     else{
          alert(name + "'s receiver," +scope.message.receiver + ", does not exist");
     }
}

 

The Disable Display Selection Switch (new)

GIF.gif

What does it do?

It disables selection of symbols on the display (and also disables the right click menu)

How does it work?

We're modifying every symbol's behavior by modifying something common to all of the symbols - the display provider

The code

(styling for switch omitted)

HTML:

<div style="color: white"> Selection </div>
<label class="switch">
     <input type="checkbox" ng-model="config.Enabled" ng-change="toggled()">
     <span class="slider round"></span>
</label>

 

JS:

symbolVis.prototype.init = function (scope, elem, displayProvider){
     var originalDisplayProvider = displayProvider['selectSymbol'];
     function allowClick(){
          if(scope.config.Enabled){
               displayProvider['selectSymbol'] = originalDisplayProvider;
          }
          else{
               displayProvider['selectSymbol'] = function(){};
          }
     }

     setTimeout(function() { 
          allowClick();
     }, 1000);

     scope.toggled = function(){
          allowClick();
     }
}
var def = {
     typeName: 'disableselection',
     datasourceBehavior: PV.Extensibility.Enums.DatasourceBehaviors.Single,
     visObjectType: symbolVis,
     iconUrl: 'Scripts/app/editor/symbols/ext/Icons/toggleswitch.png',
     inject: ['displayProvider'],
     getDefaultConfig: function(){
          return{
               DataShape: 'Value',
               Enabled: true,
               Height: 70,
               Width: 70,
               BackgroundColor: 'rgb(0,0,0)',
               TextColor: 'rgb(0,255,0)',
          };
     }
};