Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  
  <base href="http://polygit.org/polymer+:master/components/">
  <link href="polymer/polymer.html" rel="import">
</head>
<body>
  <dom-module id="my-element">
      <template>
          <style>
              :host {
                  display: block;
              }
          </style>
          <h2>Hello [[id]]</h2>
          <ul>
              <li>propString: [[propString]]</li>
              <li>
                  propArray:
                  <ol>
                      <template is="dom-repeat" items="[[propArray]]">
                          <li>[[item]]</li>
                      </template>
                  </ol>
              </li>
              <li>
                  propObject:
                  <ul>
                      <li>name: [[propObject.name]]</li>
                      <li>surname: [[propObject.surname]]</li>
                  </ul>
              </li>
          </ul>
      </template>
      <script>
          if (!String.prototype.endsWith) {
              String.prototype.endsWith = function(searchString, position) {
                  var subjectString = this.toString();
                  if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
                      position = subjectString.length;
                  }
                  position -= searchString.length;
                  var lastIndex = subjectString.lastIndexOf(searchString, position);
                  return lastIndex !== -1 && lastIndex === position;
              };
          }
          (function() {
              var SyncBehaviorInstances = [];
              var SyncBehaviorLock = false;
              SyncBehavior = {
                  attached: function() {
                      // Add instance
                      SyncBehaviorInstances.push(this);
                      // Add listeners
                      for(var property in this.properties) {
                          if('notify' in this.properties[property] && this.properties[property].notify) {
                              // Watch all properties with notify = true
                              var eventHanler = this._eventHandlerForPropertyType(this.properties[property].type.name);
                              this.listen(this, Polymer.CaseMap.camelToDashCase(property) + '-changed', eventHanler);
                          }
                      }
                  },
                  detached: function() {
                      // Remove instance
                      var index = SyncBehaviorInstances.indexOf(this);
                      if(index >= 0) {
                          SyncBehaviorInstances.splice(index, 1);
                      }
                      // Remove listeners
                      for(var property in this.properties) {
                          if('notify' in this.properties[property] && this.properties[property].notify) {
                              // Watch all properties with notify = true
                              var eventHanler = this._eventHandlerForPropertyType(this.properties[property].type.name);
                              this.unlisten(this, Polymer.CaseMap.camelToDashCase(property) + '-changed', eventHanler);
                          }
                      }
                  },
                  _eventHandlerForPropertyType: function(propertyType) {
                      switch(propertyType) {
                          case 'Array':
                              return '__syncArray';
                          case 'Object':
                              return '__syncObject';
                          default:
                              return '__syncPrimitive';
                      }
                  },
                  __syncArray: function(event, details) {
                      if(SyncBehaviorLock) {
                          return; // Prevent cycles
                      }
                      SyncBehaviorLock = true; // Lock
                      var target = event.target;
                      var prop = Polymer.CaseMap.dashToCamelCase(event.type.substr(0, event.type.length - 8));
                      if(details.path === undefined) {
                          // New array -> assign by reference
                          SyncBehaviorInstances.forEach(function(instance) {
                              if(instance !== target) {
                                  instance.set(prop, details.value);
                              }
                          });
                      } else if(details.path.endsWith('.splices')) {
                          // Array mutation -> apply notifySplices
                          var splices = details.value.indexSplices;
                          // for all other instances: assign reference if not the same, otherwise call 'notifySplices'
                          SyncBehaviorInstances.forEach(function(instance) {
                              if(instance !== target) {
                                  var instanceReference = instance.get(prop);
                                  var targetReference = target.get(prop);
                                  if(instanceReference !== targetReference) {
                                      instance.set(prop, targetReference);
                                  } else {
                                      instance.notifySplices(prop, splices);
                                  }
                              }
                          });
                      }
                      SyncBehaviorLock = false; // Unlock
                  },
                  __syncObject: function(event, details) {
                      var target = event.target;
                      var prop = Polymer.CaseMap.dashToCamelCase(event.type.substr(0, event.type.length - 8));
                      if(details.path === undefined) {
                          // New object -> assign by reference
                          SyncBehaviorInstances.forEach(function(instance) {
                              if(instance !== target) {
                                  instance.set(prop, details.value);
                              }
                          });
                      } else {
                          // Property change -> assign by reference if not the same, otherwise call 'notifyPath'
                          SyncBehaviorInstances.forEach(function(instance) {
                              if(instance !== target) {
                                  var instanceReference = instance.get(prop);
                                  var targetReference = target.get(prop);
                                  if(instanceReference !== targetReference) {
                                      instance.set(prop, targetReference);
                                  } else {
                                      instance.notifyPath(details.path, details.value);
                                  }
                              }
                          });
                      }
                  },
                  __syncPrimitive: function(event, details) {
                      var target = event.target;
                      var value = details.value;
                      var prop = Polymer.CaseMap.dashToCamelCase(event.type.substr(0, event.type.length - 8));
                      SyncBehaviorInstances.forEach(function(instance) {
                          if(instance !== target) {
                              instance.set(prop, value);
                          }
                      });
                  },
              };
          })();
          Polymer({
              is: 'my-element',
              behaviors: [
                  SyncBehavior,
              ],
              properties: {
                  id: {
                      type: String,
                  },
                  propString: {
                      type: String,
                      notify: true,
                      value: 'default value',
                  },
                  propArray: {
                      type: Array,
                      notify: true,
                      value: function() {
                          return ['a', 'b', 'c'];
                      },
                  },
                  propObject: {
                      type: Object,
                      notify: true,
                      value: function() {
                          return {'name': 'John', 'surname': 'Doe'};
                      },
                  },
              },
              pushToArray: function(item) {
                  this.push('propArray', item);
              },
              pushToNewArray: function(item) {
                  this.set('propArray', [item]);
              },
              popFromArray: function() {
                  this.pop('propArray');
              },
              setObjectName: function(name) {
                  this.set('propObject.name', name);
              },
              setNewObjectName: function(name) {
                  this.set('propObject', {'name': name, 'surname': 'unknown'});
              },
          });
      </script>
  </dom-module>
  
  <template is="dom-bind">
    <h4>Primitive type</h4>
    propString: <input type="text" value="{{propString::input}}" />
    <h4>Array type</h4>
    Push to propArray: <input type="text" id="propArrayItem" /> <button onclick="_propArrayItem()">Push</button> <button onclick="_propNewArrayItem()">Push to NEW array</button> <button onclick="_propPopArrayItem()">Delete last element</button>
    <h4>Object type</h4>
    Set 'name' of propObject: <input type="text" id="propObjectName" /> <button onclick="_propObjectName()">Set</button> <button onclick="_propNewObjectName()">Set to NEW object</button> <br />
    <script>
      function _propArrayItem() {
        one.pushToArray(propArrayItem.value);
      }
      function _propNewArrayItem() {
        one.pushToNewArray(propArrayItem.value);
      }
      function _propPopArrayItem() {
        one.popFromArray();
      }
      function _propObjectName() {
        one.setObjectName(propObjectName.value);
      }
      function _propNewObjectName() {
        one.setNewObjectName(propObjectName.value);
      }
    </script>
    <my-element id="one" prop-string="{{propString}}"></my-element>
    <my-element id="two"></my-element>
    <my-element id="three"></my-element>
    <my-element id="four"></my-element>
  </template>
</body>
</html>
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
anonymouspro
0viewers