<commit_before>/*ListNode.js
 * class for collections of user created objects
 */

define([
  'jquery',
  'underscore',
  'paper',
  'models/data/Instance',
  'utils/PFloat',
  'utils/PConstraint',
  'utils/TrigFunc'

], function($, _, paper, Instance, PFloat, PConstraint, TrigFunc) {

  var ListNode = Instance.extend({
    defaults: _.extend({}, Instance.prototype.defaults, {
      name: 'list',
      type: 'collection',
      open: false, //indicates whether list is open or not;
      bbox_dimensions: null,
    }),

    initialize: function() {
      Instance.prototype.initialize.apply(this, arguments);
      this.members = [];
      this.offsets = [];

      var memberCount = new PFloat(0);
      memberCount.setNull(false);
      this.set('memberCount', memberCount);

      this.get('translationDelta').setNull(false);
      this.get('scalingDelta').setNull(false);
      this.get('rotationDelta').setNull(false);
      this.get('fillColor').setNull(false);
      this.get('strokeColor').setNull(false);
      this.get('stroke_width').setNull(false);
    },

    /*setValue
    passes modifications onto members
     */
    setValue: function(data, mode, modifier) {

      for (var i = 0; i < this.members.length; i++) {
        this.members[i].setValue(data, mode, modifier);
      }
      for (var p in data) {
        if (data.hasOwnProperty(p)) {
          this.trigger('change:' + p);
        }
      }
      this.setNull(false);
    },

    printMembers: function() {
      var ids = [];
      for (var i = 0; i < this.members.length; i++) {

        if (this.members[i].get('type') === 'collection') {
          this.members[i].printMembers();
        }
        ids = ids.concat(this.members[i].get('id'));
      }
      console.log('total members for', this.get('id'), ids.length, ids);
    },

    /* addMember, removeMember
     * methods for adding and removing members from the list
     * accepts both arrays and single objects as arguments */
    addMember: function(data) {

      if (data instanceof Array) {
        for (var i = 0; i < data.length; i++) {

          // this.listenTo(data[i], 'delete', this.deleteMember);
          this.members.push(data[i]);
          // this.listenTo(data[i],'modified',this.modified);
        }
      } else {
        //this.listenTo(data,'modified',this.modified);
        this.members.push(data);
      }

      var memberCount = {
        val: this.members.length,
        operator: 'set'
      };
      this.get('memberCount').setValue(memberCount);
      //this.computeCentroid();

    },

    computeCentroid: function() {
      var sumX = 0;
      var sumY = 0;
      this.members.forEach(function(m) {
        var pos = m._temp_matrix.translation;

        sumX += pos.x;
        sumY += pos.y;
      });

      return {
        x: sumX / this.members.length,
        y: sumY / this.members.length
      };

    },

    // sets the geom visibility to false
    hide: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].hide();
      }
    },

    show: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].show();
      }
    },

    bringToFront: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].bringToFront();
      }
    },

    addMemberToOpen: function(data) {
      if (this.get('open')) {
        var addedToList = false;
        for (var i = 0; i < this.members.length; i++) {
          var added = this.members[i].addMemberToOpen(data);
          if (added) {
            addedToList = true;
          }
        }
        if (addedToList) {
          if (data.get('type') === 'collection') {
            for (var j = 0; j < data.members.length; j++) {
              var removed = this.removeMember(data.members[j]);
            }
          }
          return true;
        } else {
          this.addMember(data);
          return true;
        }
      }
      return false;
    },

    /* removeAllMembers;
     * removes all members from this list
     */
    removeAllMembers: function() {
      var removed = [];
      for (var i = this.members.length - 1; i >= 0; i--) {
        var removedMember = this.removeMember(this.members[i]);
        if (removedMember) {
          removed.push(removedMember);
        }
      }
      return removed;
    },

    /* deleteMember
     * callback triggered when a member is deleted by some other entity
     */
    deleteMember: function(target) {
      this.stopListening(target);
      this.removeMember(target);
      this.computeCentroid();
    },

    removeMember: function(data) {
      var index = $.inArray(data, this.members);
      if (index > -1) {
        var member = this.members.splice(index, 1)[0];
       var memberCount = {
          val: this.members.length,
          operator: 'set'
        };
        this.get('memberCount').setValue(memberCount);
        //this.stopListening(member);
        return member;
      }

    },

    /*recRemoveMember
     * attempts to remove an item recursively
     * returns item if item is removed,
     */
    recRemoveMember: function(data) {
      var removedItems = [];
      var modified = [];
      var orphans = [];
      var selfRemoved = this.removeMember(data);
      if (selfRemoved) {
        orphans = data.removeAllMembers();
        this.addMember(orphans);
        removedItems.push(selfRemoved);
        modified.push(this);
      } else {
        for (var i = 0; i < this.members.length; i++) {
          var r = this.members[i].recRemoveMember(data);
          removedItems = removedItems.concat(r.removed);
          modified = modified.concat(r.modified);
          orphans = orphans.concat(r.orphans);
        }
      }
      return {
        removed: removedItems,
        modified: modified,
        orphans: orphans
      };

    },

    /* hasMember, getMember
     * recursive methods for checking if instance exists in
     * list or sublist and accessing said parent list */

    hasMember: function(member, top, last) {
      if (!top) {
        if (this === member) {
          return last;
        }
      }
      for (var i = 0; i < this.members.length; i++) {
        var member_found = this.members[i].hasMember(member, false, this);
        if (member_found) {
          return member_found;
        }
      }
    },

    getMember: function(member) {

      for (var i = 0; i < this.members.length; i++) {
        var m = this.members[i].getMember(member);
        if (m) {
          if (this.get('open')) {
            return m;
          } else {
            return this;
          }
        }
      }
      return null;
    },

getLiteralSubprops: function(key, subprop) {
     var subprops = [];
     for (var i = 0; i < this.members.length; i++) {
      var sp = this.members[i].getLiteralSubprops(key, subprop);
      subprops = subprops.concat(sp);
     }
     return subprops;
    },

    getLastMember: function() {
      if (this.members.length > 0) {
        return this.members[this.members.length - 1];
      }
    },

    getFirstMember: function() {
      if (this.members.length > 0) {
        return this.members[0];
      }
    },

    getMemberAt: function(index) {
      if (this.members.length > index) {
        return this.members[index];
      }
    },

    /* getListMembers
     * returns all members of this list which are themselves lists
     */
    getListMembers: function() {
      return this.members.filter(function(member) {
        return member.get('type') === 'collection';
      });
    },

    //returns all non-list members
    getInstanceMembers: function(memberList) {
      if (!memberList) {
        memberList = [];
      }
      for (var i = 0; i < this.members.length; i++) {
        if (this.members[i].get('type') !== 'collection') {
          memberList.push(this.members[i]);
        } else {
          this.members[i].getInstanceMembers(memberList);
        }

      }
      return memberList;
    },

    propertyModified: function(event) {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].trigger('modified', this.members[i]);
      }
    },

    getMemberNumber: function() {
      return this.getValueFor('memberCount');
    },

    getMemberIndex: function(member) {
      return _.indexOf(this.members, member);
    },

    setIndex: function(index, member) {
      var old_index = this.getMemberIndex(member);
      if (index > 0) {
        var spliced_member = this.members.splice(old_index, 1)[0];

        this.members.splice(index, 0, spliced_member);

       //TODO: create something that specifies child order here
        return true;
      }
      return false;
    },
    /*closeMembers
     * recursively closes all members
     *of this list
     */
    closeAllMembers: function() {
      for (var i = 0; i < this.members.length; i++) {
        if (this.members[i].get('type') === 'collection') {
          this.members[i].closeAllMembers();
          this.members[i].set('open', false);
        }
      }
    },

    toggleOpen: function(item) {
      if (this.hasMember(item, true) || this === item) {
        if (!this.get('open')) {
          this.set('open', true);
          return [this];
        } else {
          var toggledLists = [];
          for (var i = 0; i < this.members.length; i++) {
            var toggled = this.members[i].toggleOpen(item);
            if (toggled) {
              toggledLists = toggledLists.concat(toggled);
            }
          }
          return toggledLists;
        }
      }
      return null;
    },

    toggleClosed: function(item) {
      if (this.hasMember(item, true) || this === item) {
        var toggledLists = [];
        for (var i = 0; i < this.members.length; i++) {
          var toggled = this.members[i].toggleClosed(item);
          if (toggled) {
            toggledLists = toggledLists.concat(toggled);
          }
        }
        if (toggledLists.length > 0) {
          return toggledLists;
        } else {
          if (this.get('open')) {
            this.set('open', false);
            return [this];
          }
        }
      }
      return null;
    },

    compile: function() {

    },

    //triggered on change of select property, removes bbox
    selectionChange: function() {
      Instance.prototype.selectionChange.call(this, arguments);
      if (!this.get('selected').getValue()) {
        this.get('ui').visible = false;
      }
    },

    render: function() {
      this.renderBoundingBox();

    },

    renderBoundingBox: function() {
      this.set('bbox_dimensions', {
        topLeft: null,
        bottomRight: null,
      });

      for (var k = 0; k < this.members.length; k++) {
        this.calculateBoundingBox(this.members[k]);
      }

      var bbox_dimensions = this.get('bbox_dimensions');
      if (bbox_dimensions.bottomRight) {
        var width = bbox_dimensions.bottomRight.x - bbox_dimensions.topLeft.x;
        var height = bbox_dimensions.bottomRight.y - bbox_dimensions.topLeft.y;
        var x = bbox_dimensions.topLeft.x + width / 2;
        var y = bbox_dimensions.topLeft.y + height / 2;

        var bbox = this.get('bbox');
        if (!bbox) {

          bbox = new paper.Path.Rectangle(bbox_dimensions.topLeft, new paper.Size(width, height));
          bbox.data.instance = this;
          this.set('bbox', bbox);
          this.set('geom', bbox);
          bbox.sendToBack();

        } else {
          bbox.scale(width / bbox.bounds.width, height / bbox.bounds.height);
          bbox.position.x = x;
          bbox.position.y = y;

        }
        var selection_clone = this.get('selection_clone');

        if (!selection_clone) {
          this.createSelectionClone();
          selection_clone = this.get('selection_clone');
        } else {
          selection_clone.scale(width / selection_clone.bounds.width, height / selection_clone.bounds.height);
          selection_clone.position.x = x;
          selection_clone.position.y = y;
        }

        this.updateScreenBounds(bbox);
      }

    },

    calculateBoundingBox: function(member) {
      if (member.get('screen_top_left') && member.get('screen_bottom_right')) {
        var bbox_dimensions = this.get('bbox_dimensions');
        var i_topLeft = member.get('screen_top_left').getValue();
        var i_bottomRight = member.get('screen_bottom_right').getValue();

        if (!bbox_dimensions.topLeft) {
          bbox_dimensions.topLeft = i_topLeft;
        } else {
          if (i_topLeft.x < bbox_dimensions.topLeft.x) {
            bbox_dimensions.topLeft.x = i_topLeft.x;
          }
          if (i_topLeft.y < bbox_dimensions.topLeft.y) {
            bbox_dimensions.topLeft.y = i_topLeft.y;
          }
        }

        if (!bbox_dimensions.bottomRight) {
          bbox_dimensions.bottomRight = i_bottomRight;
        } else {
          if (i_bottomRight.x > bbox_dimensions.bottomRight.x) {
            bbox_dimensions.bottomRight.x = i_bottomRight.x;
          }
          if (i_bottomRight.y > bbox_dimensions.bottomRight.y) {
            bbox_dimensions.bottomRight.y = i_bottomRight.y;
          }
        }
      }

    },

    toJSON: function() {
      var data = Instance.prototype.toJSON.call(this, arguments);
      var memberIds = [];
      _.each(this.members, function(item) {
        memberIds.push(item.get('id'));
      });
      data.members = memberIds;

      return data;
    },

    getShapeClone: function() {
      var clone = new paper.Group(this.members.map(function(instance) {
        return instance.getShapeClone();
      }));
      return clone;
    },

    createSelectionClone: function() {
      if (this.get('selection_clone')) {
        this.get('selection_clone').remove();
        this.set('selection_clone', null);
      }
      var selection_clone = this.get('bbox').clone();
      var targetLayer = paper.project.layers.filter(function(layer) {
        return layer.name === 'ui_layer';
      })[0];
      targetLayer.addChild(selection_clone);
      selection_clone.data.instance = this;
      selection_clone.fillColor = null;
      selection_clone.strokeWidth = 3;
      selection_clone.selected = false;
      this.set('selection_clone', selection_clone);
    },

    getRange: function() {
      return this.members.length;
    }

  });

  return ListNode;

});<commit_msg>fixed render issue with lists<commit_after>/*ListNode.js
 * class for collections of user created objects
 */

define([
  'jquery',
  'underscore',
  'paper',
  'models/data/Instance',
  'utils/PFloat',
  'utils/PConstraint',
  'utils/TrigFunc'

], function($, _, paper, Instance, PFloat, PConstraint, TrigFunc) {

  var ListNode = Instance.extend({
    defaults: _.extend({}, Instance.prototype.defaults, {
      name: 'list',
      type: 'collection',
      open: false, //indicates whether list is open or not;
      bbox_dimensions: null,
    }),

    initialize: function() {
      Instance.prototype.initialize.apply(this, arguments);
      this.members = [];
      this.offsets = [];

      var memberCount = new PFloat(0);
      memberCount.setNull(false);
      this.set('memberCount', memberCount);

      this.get('translationDelta').setNull(false);
      this.get('scalingDelta').setNull(false);
      this.get('rotationDelta').setNull(false);
      this.get('fillColor').setNull(false);
      this.get('strokeColor').setNull(false);
      this.get('stroke_width').setNull(false);
    },

    /*setValue
    passes modifications onto members
     */
    setValue: function(data, mode, modifier) {

      for (var i = 0; i < this.members.length; i++) {
        this.members[i].setValue(data, mode, modifier);
      }
      for (var p in data) {
        if (data.hasOwnProperty(p)) {
          this.trigger('change:' + p);
        }
      }
      this.setNull(false);
    },

    printMembers: function() {
      var ids = [];
      for (var i = 0; i < this.members.length; i++) {

        if (this.members[i].get('type') === 'collection') {
          this.members[i].printMembers();
        }
        ids = ids.concat(this.members[i].get('id'));
      }
      console.log('total members for', this.get('id'), ids.length, ids);
    },

    /* addMember, removeMember
     * methods for adding and removing members from the list
     * accepts both arrays and single objects as arguments */
    addMember: function(data) {

      if (data instanceof Array) {
        for (var i = 0; i < data.length; i++) {

          // this.listenTo(data[i], 'delete', this.deleteMember);
          this.members.push(data[i]);
           this.listenTo(data[i],'modified',this.render);
        }
      } else {
        this.listenTo(data,'modified',this.render);
        this.members.push(data);
      }

      var memberCount = {
        val: this.members.length,
        operator: 'set'
      };
      this.get('memberCount').setValue(memberCount);
      //this.computeCentroid();

    },

    computeCentroid: function() {
      var sumX = 0;
      var sumY = 0;
      this.members.forEach(function(m) {
        var pos = m._temp_matrix.translation;

        sumX += pos.x;
        sumY += pos.y;
      });

      return {
        x: sumX / this.members.length,
        y: sumY / this.members.length
      };

    },

    // sets the geom visibility to false
    hide: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].hide();
      }
    },

    show: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].show();
      }
    },

    bringToFront: function() {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].bringToFront();
      }
    },

    addMemberToOpen: function(data) {
      if (this.get('open')) {
        var addedToList = false;
        for (var i = 0; i < this.members.length; i++) {
          var added = this.members[i].addMemberToOpen(data);
          if (added) {
            addedToList = true;
          }
        }
        if (addedToList) {
          if (data.get('type') === 'collection') {
            for (var j = 0; j < data.members.length; j++) {
              var removed = this.removeMember(data.members[j]);
            }
          }
          return true;
        } else {
          this.addMember(data);
          return true;
        }
      }
      return false;
    },

    /* removeAllMembers;
     * removes all members from this list
     */
    removeAllMembers: function() {
      var removed = [];
      for (var i = this.members.length - 1; i >= 0; i--) {
        var removedMember = this.removeMember(this.members[i]);
        if (removedMember) {
          removed.push(removedMember);
        }
      }
      return removed;
    },

    /* deleteMember
     * callback triggered when a member is deleted by some other entity
     */
    deleteMember: function(target) {
      this.stopListening(target);
      this.removeMember(target);
      this.computeCentroid();
    },

    removeMember: function(data) {
      var index = $.inArray(data, this.members);
      if (index > -1) {
        var member = this.members.splice(index, 1)[0];
       var memberCount = {
          val: this.members.length,
          operator: 'set'
        };
        this.get('memberCount').setValue(memberCount);
        //this.stopListening(member);
        return member;
      }

    },

    /*recRemoveMember
     * attempts to remove an item recursively
     * returns item if item is removed,
     */
    recRemoveMember: function(data) {
      var removedItems = [];
      var modified = [];
      var orphans = [];
      var selfRemoved = this.removeMember(data);
      if (selfRemoved) {
        orphans = data.removeAllMembers();
        this.addMember(orphans);
        removedItems.push(selfRemoved);
        modified.push(this);
      } else {
        for (var i = 0; i < this.members.length; i++) {
          var r = this.members[i].recRemoveMember(data);
          removedItems = removedItems.concat(r.removed);
          modified = modified.concat(r.modified);
          orphans = orphans.concat(r.orphans);
        }
      }
      return {
        removed: removedItems,
        modified: modified,
        orphans: orphans
      };

    },

    /* hasMember, getMember
     * recursive methods for checking if instance exists in
     * list or sublist and accessing said parent list */

    hasMember: function(member, top, last) {
      if (!top) {
        if (this === member) {
          return last;
        }
      }
      for (var i = 0; i < this.members.length; i++) {
        var member_found = this.members[i].hasMember(member, false, this);
        if (member_found) {
          return member_found;
        }
      }
    },

    getMember: function(member) {

      for (var i = 0; i < this.members.length; i++) {
        var m = this.members[i].getMember(member);
        if (m) {
          if (this.get('open')) {
            return m;
          } else {
            return this;
          }
        }
      }
      return null;
    },

getLiteralSubprops: function(key, subprop) {
     var subprops = [];
     for (var i = 0; i < this.members.length; i++) {
      var sp = this.members[i].getLiteralSubprops(key, subprop);
      subprops = subprops.concat(sp);
     }
     return subprops;
    },

    getLastMember: function() {
      if (this.members.length > 0) {
        return this.members[this.members.length - 1];
      }
    },

    getFirstMember: function() {
      if (this.members.length > 0) {
        return this.members[0];
      }
    },

    getMemberAt: function(index) {
      if (this.members.length > index) {
        return this.members[index];
      }
    },

    /* getListMembers
     * returns all members of this list which are themselves lists
     */
    getListMembers: function() {
      return this.members.filter(function(member) {
        return member.get('type') === 'collection';
      });
    },

    //returns all non-list members
    getInstanceMembers: function(memberList) {
      if (!memberList) {
        memberList = [];
      }
      for (var i = 0; i < this.members.length; i++) {
        if (this.members[i].get('type') !== 'collection') {
          memberList.push(this.members[i]);
        } else {
          this.members[i].getInstanceMembers(memberList);
        }

      }
      return memberList;
    },

    propertyModified: function(event) {
      for (var i = 0; i < this.members.length; i++) {
        this.members[i].trigger('modified', this.members[i]);
      }
    },

    getMemberNumber: function() {
      return this.getValueFor('memberCount');
    },

    getMemberIndex: function(member) {
      return _.indexOf(this.members, member);
    },

    setIndex: function(index, member) {
      var old_index = this.getMemberIndex(member);
      if (index > 0) {
        var spliced_member = this.members.splice(old_index, 1)[0];

        this.members.splice(index, 0, spliced_member);

       //TODO: create something that specifies child order here
        return true;
      }
      return false;
    },
    /*closeMembers
     * recursively closes all members
     *of this list
     */
    closeAllMembers: function() {
      for (var i = 0; i < this.members.length; i++) {
        if (this.members[i].get('type') === 'collection') {
          this.members[i].closeAllMembers();
          this.members[i].set('open', false);
        }
      }
    },

    toggleOpen: function(item) {
      if (this.hasMember(item, true) || this === item) {
        if (!this.get('open')) {
          this.set('open', true);
          return [this];
        } else {
          var toggledLists = [];
          for (var i = 0; i < this.members.length; i++) {
            var toggled = this.members[i].toggleOpen(item);
            if (toggled) {
              toggledLists = toggledLists.concat(toggled);
            }
          }
          return toggledLists;
        }
      }
      return null;
    },

    toggleClosed: function(item) {
      if (this.hasMember(item, true) || this === item) {
        var toggledLists = [];
        for (var i = 0; i < this.members.length; i++) {
          var toggled = this.members[i].toggleClosed(item);
          if (toggled) {
            toggledLists = toggledLists.concat(toggled);
          }
        }
        if (toggledLists.length > 0) {
          return toggledLists;
        } else {
          if (this.get('open')) {
            this.set('open', false);
            return [this];
          }
        }
      }
      return null;
    },

    compile: function() {

    },

    //triggered on change of select property, removes bbox
    selectionChange: function() {
      Instance.prototype.selectionChange.call(this, arguments);
      if (!this.get('selected').getValue()) {
        this.get('ui').visible = false;
      }
    },

    render: function() {
      this.renderBoundingBox();

    },

    renderBoundingBox: function() {
      this.set('bbox_dimensions', {
        topLeft: null,
        bottomRight: null,
      });

      for (var k = 0; k < this.members.length; k++) {
        this.calculateBoundingBox(this.members[k]);
      }

      var bbox_dimensions = this.get('bbox_dimensions');
      if (bbox_dimensions.bottomRight) {
        var width = bbox_dimensions.bottomRight.x - bbox_dimensions.topLeft.x;
        var height = bbox_dimensions.bottomRight.y - bbox_dimensions.topLeft.y;
        var x = bbox_dimensions.topLeft.x + width / 2;
        var y = bbox_dimensions.topLeft.y + height / 2;

        var bbox = this.get('bbox');
        if (!bbox) {

          bbox = new paper.Path.Rectangle(bbox_dimensions.topLeft, new paper.Size(width, height));
          bbox.data.instance = this;
          this.set('bbox', bbox);
          this.set('geom', bbox);
          bbox.sendToBack();

        } else {
          bbox.scale(width / bbox.bounds.width, height / bbox.bounds.height);
          bbox.position.x = x;
          bbox.position.y = y;

        }
        var selection_clone = this.get('selection_clone');

        if (!selection_clone) {
          this.createSelectionClone();
          selection_clone = this.get('selection_clone');
        } else {
          selection_clone.scale(width / selection_clone.bounds.width, height / selection_clone.bounds.height);
          selection_clone.position.x = x;
          selection_clone.position.y = y;
        }

        this.updateScreenBounds(bbox);
      }

    },

    calculateBoundingBox: function(member) {
      if (member.get('screen_top_left') && member.get('screen_bottom_right')) {
        var bbox_dimensions = this.get('bbox_dimensions');
        var i_topLeft = member.get('screen_top_left').getValue();
        var i_bottomRight = member.get('screen_bottom_right').getValue();

        if (!bbox_dimensions.topLeft) {
          bbox_dimensions.topLeft = i_topLeft;
        } else {
          if (i_topLeft.x < bbox_dimensions.topLeft.x) {
            bbox_dimensions.topLeft.x = i_topLeft.x;
          }
          if (i_topLeft.y < bbox_dimensions.topLeft.y) {
            bbox_dimensions.topLeft.y = i_topLeft.y;
          }
        }

        if (!bbox_dimensions.bottomRight) {
          bbox_dimensions.bottomRight = i_bottomRight;
        } else {
          if (i_bottomRight.x > bbox_dimensions.bottomRight.x) {
            bbox_dimensions.bottomRight.x = i_bottomRight.x;
          }
          if (i_bottomRight.y > bbox_dimensions.bottomRight.y) {
            bbox_dimensions.bottomRight.y = i_bottomRight.y;
          }
        }
      }

    },

    toJSON: function() {
      var data = Instance.prototype.toJSON.call(this, arguments);
      var memberIds = [];
      _.each(this.members, function(item) {
        memberIds.push(item.get('id'));
      });
      data.members = memberIds;

      return data;
    },

    getShapeClone: function() {
      var clone = new paper.Group(this.members.map(function(instance) {
        return instance.getShapeClone();
      }));
      return clone;
    },

    createSelectionClone: function() {
      if (this.get('selection_clone')) {
        this.get('selection_clone').remove();
        this.set('selection_clone', null);
      }
      var selection_clone = this.get('bbox').clone();
      var targetLayer = paper.project.layers.filter(function(layer) {
        return layer.name === 'ui_layer';
      })[0];
      targetLayer.addChild(selection_clone);
      selection_clone.data.instance = this;
      selection_clone.fillColor = null;
      selection_clone.strokeWidth = 3;
      selection_clone.selected = false;
      this.set('selection_clone', selection_clone);
    },

    getRange: function() {
      return this.members.length;
    }

  });

  return ListNode;

});<|endoftext|>


<commit_before>// --
// Core.Agent.CustomerSearch.js - provides the special module functions for the customer search
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.Agent.CustomerSearch.js,v 1.5 2010-07-21 06:04:33 cg Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.Agent = Core.Agent || {};

/**
 * @namespace
 * @exports TargetNS as Core.Agent.CustomerSearch
 * @description
 *      This namespace contains the special module functions for the customer search.
 */
Core.Agent.CustomerSearch = (function (TargetNS) {
    var BackupData = {
        CustomerInfo: '',
        CustomerEmail: '',
        CustomerKey: ''
    };

    /**
     * @function
     * @private
     * @return nothing
     *      This function get customer data for customer info table
     */
    function GetCustomerInfo(CustomerUserID) {
        var Data = {
            Action: 'AgentCustomerSearch',
            Subaction: 'CustomerInfo',
            CustomerUserID: CustomerUserID || 1
        };
        Core.AJAX.FunctionCall(Core.Config.Get('Baselink'), Data, function (Response) {
            // set CustomerID
            $('#CustomerID').val(Response.CustomerID);
            $('#ShowCustomerID').html(Response.CustomerID);

            // show customer info
            $('#CustomerInfo .Content').html(Response.CustomerTableHTMLString);

            // only execute this part, if in AgentTicketEmail or AgentTicketPhone
            if (Core.Config.Get('Action') === 'AgentTicketEmail' || Core.Config.Get('Action') === 'AgentTicketPhone') {
                // reset service
                $('#ServiceID').attr('selectedIndex', 0);
                // update services (trigger ServiceID change event)
                Core.AJAX.FormUpdate($('#CustomerID').closest('form'), 'AJAXUpdate', 'ServiceID', ['Dest', 'SelectedCustomerUser', 'NextStateID', 'PriorityID', 'ServiceID', 'SLAID', 'OwnerAll', 'ResponsibleAll', 'TicketFreeText1', 'TicketFreeText2', 'TicketFreeText3', 'TicketFreeText4', 'TicketFreeText5', 'TicketFreeText6', 'TicketFreeText7', 'TicketFreeText8', 'TicketFreeText9', 'TicketFreeText10', 'TicketFreeText11', 'TicketFreeText12', 'TicketFreeText13', 'TicketFreeText14', 'TicketFreeText15', 'TicketFreeText16'], ['NewUserID', 'NewResponsibleID', 'NextStateID', 'PriorityID', 'ServiceID', 'SLAID', 'TicketFreeText1', 'TicketFreeText2', 'TicketFreeText3', 'TicketFreeText4', 'TicketFreeText5', 'TicketFreeText6', 'TicketFreeText7', 'TicketFreeText8', 'TicketFreeText9', 'TicketFreeText10', 'TicketFreeText11', 'TicketFreeText12', 'TicketFreeText13', 'TicketFreeText14', 'TicketFreeText15', 'TicketFreeText16']);
            }
        });
    }

    /**
     * @function
     * @private
     * @return nothing
     *      This function get customer tickets
     */
    function GetCustomerTickets(CustomerUserID, CustomerID) {
        // check if customer tickets should be shown
        if (isNaN(parseInt(Core.Config.Get('Autocomplete.ShowCustomerTickets'), 10))) {
            return;
        }

        var Data = {
            Action: 'AgentCustomerSearch',
            Subaction: 'CustomerTickets',
            CustomerUserID: CustomerUserID,
            CustomerID: CustomerID
        };

        /**
         * @function
         * @private
         * @return nothing
         *      This function replace and show customer ticket links
         */
        function ReplaceCustomerTicketLinks() {
            $('#CustomerTickets').find('.AriaRoleMain').removeAttr('role').removeClass('AriaRoleMain');

            // Replace overview mode links (S, M, L view), pagination links with AJAX
            $('#CustomerTickets').find('.OverviewZoom a, .Pagination a').click(function () {
                // Cut out BaseURL and query string from the URL
                var Link = $(this).attr('href'),
                    URLComponents;

                URLComponents = Link.split('?', 2);

                Core.AJAX.FunctionCall(URLComponents[0], URLComponents[1], function (Response) {
                    // show customer tickets
                    if ($('#CustomerTickets').length) {
                        $('#CustomerTickets').html(Response.CustomerTicketsHTMLString);
                        ReplaceCustomerTicketLinks();
                    }
                });
                return false;
            });

            // Init accordion of overview article preview
            Core.UI.Accordion.Init($('.Preview > ul'), 'li h3 a', '.HiddenBlock');
        }

        Core.AJAX.FunctionCall(Core.Config.Get('Baselink'), Data, function (Response) {
            // show customer tickets
            if ($('#CustomerTickets').length) {
                $('#CustomerTickets').html(Response.CustomerTicketsHTMLString);
                ReplaceCustomerTicketLinks();
            }
        });
    }

    /**
     * @function
     * @param {jQueryObject} $Element The jQuery object of the input field with autocomplete
     * @param {Boolean} ActiveAutoComplete Set to false, if autocomplete should only be started by click on a button next to the input field
     * @return nothing
     *      This function initializes the special module functions
     */
    TargetNS.Init = function ($Element, ActiveAutoComplete) {
        // get customer tickets for AgentTicketCustomer
        if (Core.Config.Get('Action') === 'AgentTicketCustomer') {
            GetCustomerTickets($('#CustomerUserID').val(), $('#CustomerID').val());
        }

        // get customer tickets for AgentTicketPhone and AgentTicketEmail
        if (Core.Config.Get('Action') === 'AgentTicketEmail' || Core.Config.Get('Action') === 'AgentTicketPhone') {
            GetCustomerTickets($('#SelectedCustomerUser').val());
        }

        if (typeof ActiveAutoComplete === 'undefined') {
            ActiveAutoComplete = true;
        }
        else {
            ActiveAutoComplete = !!ActiveAutoComplete;
        }

        // just save the initial state of the customer info
        if ($('#CustomerInfo').length) {
            BackupData.CustomerInfo = $('#CustomerInfo .Content').html();
        }

        if (isJQueryObject($Element)) {
            $Element.autocomplete({
                minLength: ActiveAutoComplete ? Core.Config.Get('Autocomplete.MinQueryLength') : 500,
                delay: Core.Config.Get('Autocomplete.QueryDelay'),
                source: function (Request, Response) {
                    var URL = Core.Config.Get('Baselink'), Data = {
                        Action: 'AgentCustomerSearch',
                        Term: Request.term,
                        MaxResults: Core.Config.Get('Autocomplete.MaxResultsDisplayed')
                    };
                    Core.AJAX.FunctionCall(URL, Data, function (Result) {
                        var Data = [];
                        $.each(Result, function () {
                            Data.push({
                                label: this.CustomerValue + " (" + this.CustomerKey + ")",
                                value: this.CustomerValuePlain
                            });
                        });
                        Response(Data);
                    });
                },
                select: function (Event, UI) {
                    var CustomerKey = UI.item.label.replace(/.*\((.*)\)$/, '$1');
                    BackupData.CustomerKey = CustomerKey;
                    BackupData.CustomerEmail = UI.item.value;

                    $Element.val(UI.item.value);

                    // set hidden field SelectedCustomerUser
                    $('#SelectedCustomerUser').val(CustomerKey);

                    // needed for AgentTicketCustomer.pm
                    if ($('#CustomerUserID').length) {
                        $('#CustomerUserID').val(CustomerKey);
                        if ($('#CustomerUserOption').length) {
                            $('#CustomerUserOption').val(CustomerKey);
                        }
                        else {
                            $('<input type="hidden" name="CustomerUserOption" id="CustomerUserOption">').val(CustomerKey).appendTo($Element.closest('form'));
                        }
                    }

                    // get customer tickets
                    GetCustomerTickets(CustomerKey);

                    // get customer data for customer info table
                    GetCustomerInfo(CustomerKey);

                    return false;
                }
            });
            $Element.blur(function () {
                var FieldValue = $(this).val();
                if (FieldValue !== BackupData.CustomerEmail && FieldValue !== BackupData.CustomerKey) {
                    $('#SelectedCustomerUser').val('');
                    $('#CustomerUserID').val('');
                    $('#CustomerID').val('');
                    $('#CustomerUserOption').val('');
                    $('#ShowCustomerID').html('');

                    // reset customer info table
                    $('#CustomerInfo .Content').html(BackupData.CustomerInfo);
                }
            });
            if (!ActiveAutoComplete) {
                $Element.after('<button id="' + $Element.attr('id') + 'Search" type="button">' + Core.Config.Get('Autocomplete.SearchButtonText') + '</button>');
                $('#' + $Element.attr('id') + 'Search').click(function () {
                    $Element.autocomplete("option", "minLength", 0);
                    $Element.autocomplete("search");
                    $Element.autocomplete("option", "minLength", 500);
                });
            }
        }
    };

    return TargetNS;
}(Core.Agent.CustomerSearch || {}));<commit_msg>Added javascript for table adjustment to the customer table loaded after autocompletion customer search.<commit_after>// --
// Core.Agent.CustomerSearch.js - provides the special module functions for the customer search
// Copyright (C) 2001-2010 OTRS AG, http://otrs.org/\n";
// --
// $Id: Core.Agent.CustomerSearch.js,v 1.6 2010-07-22 13:02:03 mn Exp $
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.Agent = Core.Agent || {};

/**
 * @namespace
 * @exports TargetNS as Core.Agent.CustomerSearch
 * @description
 *      This namespace contains the special module functions for the customer search.
 */
Core.Agent.CustomerSearch = (function (TargetNS) {
    var BackupData = {
        CustomerInfo: '',
        CustomerEmail: '',
        CustomerKey: ''
    };

    /**
     * @function
     * @private
     * @return nothing
     *      This function get customer data for customer info table
     */
    function GetCustomerInfo(CustomerUserID) {
        var Data = {
            Action: 'AgentCustomerSearch',
            Subaction: 'CustomerInfo',
            CustomerUserID: CustomerUserID || 1
        };
        Core.AJAX.FunctionCall(Core.Config.Get('Baselink'), Data, function (Response) {
            // set CustomerID
            $('#CustomerID').val(Response.CustomerID);
            $('#ShowCustomerID').html(Response.CustomerID);

            // show customer info
            $('#CustomerInfo .Content').html(Response.CustomerTableHTMLString);

            // only execute this part, if in AgentTicketEmail or AgentTicketPhone
            if (Core.Config.Get('Action') === 'AgentTicketEmail' || Core.Config.Get('Action') === 'AgentTicketPhone') {
                // reset service
                $('#ServiceID').attr('selectedIndex', 0);
                // update services (trigger ServiceID change event)
                Core.AJAX.FormUpdate($('#CustomerID').closest('form'), 'AJAXUpdate', 'ServiceID', ['Dest', 'SelectedCustomerUser', 'NextStateID', 'PriorityID', 'ServiceID', 'SLAID', 'OwnerAll', 'ResponsibleAll', 'TicketFreeText1', 'TicketFreeText2', 'TicketFreeText3', 'TicketFreeText4', 'TicketFreeText5', 'TicketFreeText6', 'TicketFreeText7', 'TicketFreeText8', 'TicketFreeText9', 'TicketFreeText10', 'TicketFreeText11', 'TicketFreeText12', 'TicketFreeText13', 'TicketFreeText14', 'TicketFreeText15', 'TicketFreeText16'], ['NewUserID', 'NewResponsibleID', 'NextStateID', 'PriorityID', 'ServiceID', 'SLAID', 'TicketFreeText1', 'TicketFreeText2', 'TicketFreeText3', 'TicketFreeText4', 'TicketFreeText5', 'TicketFreeText6', 'TicketFreeText7', 'TicketFreeText8', 'TicketFreeText9', 'TicketFreeText10', 'TicketFreeText11', 'TicketFreeText12', 'TicketFreeText13', 'TicketFreeText14', 'TicketFreeText15', 'TicketFreeText16']);
            }
        });
    }

    /**
     * @function
     * @private
     * @return nothing
     *      This function get customer tickets
     */
    function GetCustomerTickets(CustomerUserID, CustomerID) {
        // check if customer tickets should be shown
        if (isNaN(parseInt(Core.Config.Get('Autocomplete.ShowCustomerTickets'), 10))) {
            return;
        }

        var Data = {
            Action: 'AgentCustomerSearch',
            Subaction: 'CustomerTickets',
            CustomerUserID: CustomerUserID,
            CustomerID: CustomerID
        };

        /**
         * @function
         * @private
         * @return nothing
         *      This function replace and show customer ticket links
         */
        function ReplaceCustomerTicketLinks() {
            $('#CustomerTickets').find('.AriaRoleMain').removeAttr('role').removeClass('AriaRoleMain');

            // Replace overview mode links (S, M, L view), pagination links with AJAX
            $('#CustomerTickets').find('.OverviewZoom a, .Pagination a').click(function () {
                // Cut out BaseURL and query string from the URL
                var Link = $(this).attr('href'),
                    URLComponents;

                URLComponents = Link.split('?', 2);

                Core.AJAX.FunctionCall(URLComponents[0], URLComponents[1], function (Response) {
                    // show customer tickets
                    if ($('#CustomerTickets').length) {
                        $('#CustomerTickets').html(Response.CustomerTicketsHTMLString);
                        ReplaceCustomerTicketLinks();
                    }
                });
                return false;
            });

            // Init accordion of overview article preview
            Core.UI.Accordion.Init($('.Preview > ul'), 'li h3 a', '.HiddenBlock');

            // Init table functions
            Core.UI.InitTableHead($('#FixedTable thead'), $('#FixedTable tbody'));
            Core.UI.StaticTableControl($('#OverviewControl').add($('#OverviewBody')));
        }

        Core.AJAX.FunctionCall(Core.Config.Get('Baselink'), Data, function (Response) {
            // show customer tickets
            if ($('#CustomerTickets').length) {
                $('#CustomerTickets').html(Response.CustomerTicketsHTMLString);
                ReplaceCustomerTicketLinks();
            }
        });
    }

    /**
     * @function
     * @param {jQueryObject} $Element The jQuery object of the input field with autocomplete
     * @param {Boolean} ActiveAutoComplete Set to false, if autocomplete should only be started by click on a button next to the input field
     * @return nothing
     *      This function initializes the special module functions
     */
    TargetNS.Init = function ($Element, ActiveAutoComplete) {
        // get customer tickets for AgentTicketCustomer
        if (Core.Config.Get('Action') === 'AgentTicketCustomer') {
            GetCustomerTickets($('#CustomerUserID').val(), $('#CustomerID').val());
        }

        // get customer tickets for AgentTicketPhone and AgentTicketEmail
        if (Core.Config.Get('Action') === 'AgentTicketEmail' || Core.Config.Get('Action') === 'AgentTicketPhone') {
            GetCustomerTickets($('#SelectedCustomerUser').val());
        }

        if (typeof ActiveAutoComplete === 'undefined') {
            ActiveAutoComplete = true;
        }
        else {
            ActiveAutoComplete = !!ActiveAutoComplete;
        }

        // just save the initial state of the customer info
        if ($('#CustomerInfo').length) {
            BackupData.CustomerInfo = $('#CustomerInfo .Content').html();
        }

        if (isJQueryObject($Element)) {
            $Element.autocomplete({
                minLength: ActiveAutoComplete ? Core.Config.Get('Autocomplete.MinQueryLength') : 500,
                delay: Core.Config.Get('Autocomplete.QueryDelay'),
                source: function (Request, Response) {
                    var URL = Core.Config.Get('Baselink'), Data = {
                        Action: 'AgentCustomerSearch',
                        Term: Request.term,
                        MaxResults: Core.Config.Get('Autocomplete.MaxResultsDisplayed')
                    };
                    Core.AJAX.FunctionCall(URL, Data, function (Result) {
                        var Data = [];
                        $.each(Result, function () {
                            Data.push({
                                label: this.CustomerValue + " (" + this.CustomerKey + ")",
                                value: this.CustomerValuePlain
                            });
                        });
                        Response(Data);
                    });
                },
                select: function (Event, UI) {
                    var CustomerKey = UI.item.label.replace(/.*\((.*)\)$/, '$1');
                    BackupData.CustomerKey = CustomerKey;
                    BackupData.CustomerEmail = UI.item.value;

                    $Element.val(UI.item.value);

                    // set hidden field SelectedCustomerUser
                    $('#SelectedCustomerUser').val(CustomerKey);

                    // needed for AgentTicketCustomer.pm
                    if ($('#CustomerUserID').length) {
                        $('#CustomerUserID').val(CustomerKey);
                        if ($('#CustomerUserOption').length) {
                            $('#CustomerUserOption').val(CustomerKey);
                        }
                        else {
                            $('<input type="hidden" name="CustomerUserOption" id="CustomerUserOption">').val(CustomerKey).appendTo($Element.closest('form'));
                        }
                    }

                    // get customer tickets
                    GetCustomerTickets(CustomerKey);

                    // get customer data for customer info table
                    GetCustomerInfo(CustomerKey);

                    return false;
                }
            });
            $Element.blur(function () {
                var FieldValue = $(this).val();
                if (FieldValue !== BackupData.CustomerEmail && FieldValue !== BackupData.CustomerKey) {
                    $('#SelectedCustomerUser').val('');
                    $('#CustomerUserID').val('');
                    $('#CustomerID').val('');
                    $('#CustomerUserOption').val('');
                    $('#ShowCustomerID').html('');

                    // reset customer info table
                    $('#CustomerInfo .Content').html(BackupData.CustomerInfo);
                }
            });
            if (!ActiveAutoComplete) {
                $Element.after('<button id="' + $Element.attr('id') + 'Search" type="button">' + Core.Config.Get('Autocomplete.SearchButtonText') + '</button>');
                $('#' + $Element.attr('id') + 'Search').click(function () {
                    $Element.autocomplete("option", "minLength", 0);
                    $Element.autocomplete("search");
                    $Element.autocomplete("option", "minLength", 500);
                });
            }
        }
    };

    return TargetNS;
}(Core.Agent.CustomerSearch || {}));<|endoftext|>


<commit_before>/**
 * plugin.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/*global tinymce:true */

tinymce.PluginManager.add('managedblocks', function(editor, url) {
	var cssId, managedBlocksMenuItem, enabled;

	// We don't support older browsers like IE6/7 and they don't provide prototypes for DOM objects
	if (!window.NodeList) {
		return;
	}

	function toggleActiveState() {
		var self = this;

		self.active(enabled);

		editor.on('ManagedBlocks', function() {
			self.active(editor.dom.hasClass(editor.getBody(), 'ttp-managedblocks'));
		});

	}

	function logicalBlock(element) {
		var checkOnTable = editor.dom.getParent(element, 'th,tr,td');
		if (checkOnTable == null) {
			var elementP = editor.dom.getParent(element, 'p,ul,ol'); // если элемент находится внутри P, то мы просто берем сразу родительский элемент
			return function() {
				editor.fire('ttp-selectblock', [elementP], false);
			};
		} else {
			return function() { editor.execCommand('mceTableSelectCells'); };
		}
	}

	function removeClass(currentClasses, className, callback) {
		var re = new RegExp(' ' + className + ' ', 'g');
		return callback((' ' + currentClasses + ' ').replace(re, " ").trim());
	}

	editor.addCommand('ttpChooseLogicalBlock', function() {

		//Временное решение для выбора сразу нескольких элементов P
		var sP = editor.dom.getParent(editor.selection.getStart(), 'p');
		var eP = editor.dom.getParent(editor.selection.getEnd(), 'p');
		var section = editor.selection.getNode().childNodes;

		var startSelect = false;
		for(var i=0;i<section.length;i++){
			if(section[i]==sP){
				startSelect = true;
			}
			if(section[i]==eP){
				logicalBlock(section[i])();
				return;
			}

			if(startSelect){
				logicalBlock(section[i])();
			}
		}

		//Изначальный блок, до него не доходит, если мы выбрали несколько блоков
		logicalBlock(editor.selection.getNode())();
	});

	editor.addCommand('mceManagedBlocks', function() {
		var dom = editor.dom, linkElm;

		if (!cssId) {
			cssId = dom.uniqueId();
			linkElm = dom.create('link', {
				id: cssId,
				rel: 'stylesheet',
				href: url + '/css/managedblocks.css'
			});

			editor.getDoc().getElementsByTagName('head')[0].appendChild(linkElm);
		}

		// Toggle on/off managed blocks while computing previews
		editor.on("PreviewFormats AfterPreviewFormats", function(e) {
			if (enabled) {
				dom.toggleClass(editor.getBody(), 'ttp-managedblocks', e.type == "afterpreviewformats");
			}
		});

		dom.toggleClass(editor.getBody(), 'ttp-managedblocks');
		enabled = editor.dom.hasClass(editor.getBody(), 'ttp-managedblocks');

		if (managedBlocksMenuItem) {
			managedBlocksMenuItem.active(dom.hasClass(editor.getBody(), 'mce-managedblocks'));
		}

		editor.fire('ManagedBlocks');
	});

	function reduceToFilterListAndMax(prevState, element) {
		var max = prevState[0];
		var arr = prevState[1];
		if (element.hasAttribute("data-ttpid")) {
			var possibleId = parseInt(element.getAttribute("data-ttpid"));
			if (possibleId > max) {
				return [possibleId, arr];
			}

			return prevState;
		}

		return [max, arr.concat(element)];
	}

	function produceProcessingContainer(mk, initValueId) {
		var nextId = initValueId;

		return function(block) {
			var clearBlock = removeClass(block.className, 'ttp-chosenblock', function(clazz) {
				var copy = block.cloneNode(true);
				copy.className = clazz;
				return copy;
			});

			var bl;
			var content;
			switch (block.nodeName) {
				case 'TD':
					content = [].slice.call(clearBlock.children);

					bl = clearBlock;
					while (bl.firstChild) bl.removeChild(bl.firstChild);
					editor.dom.addClass(bl, 'ttp-processingblock');
					break;
				default:
					content = [clearBlock];

					bl = mk('div', {'data-ttpid': nextId++, 'class': 'ttp-processingblock'});
					break;
			};

			var or = mk('div', {'class': 'origin viewed'});

			content.forEach(function(node) {
				or.appendChild(node);
			})

			bl.appendChild(or);
			return [block, bl];
		};
	}

	editor.addCommand('ttpProcessingBlocks', function() {
		var blocks = editor.$(".ttp-chosenblock, .ttp-processingblock");
		blocks.reduce = Array.prototype.reduce;

		var maxAndFilterList = blocks.reduce(reduceToFilterListAndMax, [0, []]);
		var nextId = maxAndFilterList[0] + 1;
		var procBlocks = maxAndFilterList[1];

		var mk = editor.dom.create.bind(editor.dom);
		procBlocks.map(produceProcessingContainer(mk, nextId))
				  .forEach(function(tupl) {
					  var block = tupl[0];
					  var container = tupl[1];

					  editor.dom.replace(container, block, false);
					  editor.execCommand('mceDisableEditableBlock', false, [container]);
				  });
	});

	editor.addButton('managedblocks', {
		title: 'Show managed blocks',
		cmd: 'mceManagedBlocks',
		onPostRender: toggleActiveState,
		icon: true,
		image: 'https://pdfimages.wondershare.com/pdfelement-mac/guide/icon-11-convert.png'
	});

	editor.addButton('ttpchooselogicalblock', {
		title: 'Choose logical block',
		cmd: 'ttpChooseLogicalBlock',
			icon: true,
		image: 'https://d30y9cdsu7xlg0.cloudfront.net/png/37722-200.png'

	});

	editor.addMenuItem('managedblocks', {
		text: 'Show managed blocks',
		cmd: 'mceManagedBlocks',
		onPostRender: toggleActiveState,
		selectable: true,
		context: 'view',
		prependToContext: true
	});

	editor.on('init', function() {
		if (editor.settings.managedblocks_default_state) {
			editor.execCommand('mceManagedBlocks', false, null, {skip_focus: true});
		}
	});

	editor.on('remove', function() {
		editor.dom.removeClass(editor.getBody(), 'ttp-managedblocks');
	});

	editor.on('ttp-selectblock', function(selectedblocks) {
		var d = editor.dom;
		selectedblocks.forEach(function(block) {
			if (!d.hasClass(block, 'ttp-processingblock') && !d.hasClass(block, 'ttp-processedblock')) {
				editor.dom.addClass(block, 'ttp-chosenblock');
			}
		});
	});
});
<commit_msg>FixBug: Processing for cells in table didn't set attribute data-ttpid<commit_after>/**
 * plugin.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/*global tinymce:true */

tinymce.PluginManager.add('managedblocks', function(editor, url) {
	var cssId, managedBlocksMenuItem, enabled;

	// We don't support older browsers like IE6/7 and they don't provide prototypes for DOM objects
	if (!window.NodeList) {
		return;
	}

	function toggleActiveState() {
		var self = this;

		self.active(enabled);

		editor.on('ManagedBlocks', function() {
			self.active(editor.dom.hasClass(editor.getBody(), 'ttp-managedblocks'));
		});

	}

	function logicalBlock(element) {
		var checkOnTable = editor.dom.getParent(element, 'th,tr,td');
		if (checkOnTable == null) {
			var elementP = editor.dom.getParent(element, 'p,ul,ol'); // если элемент находится внутри P, то мы просто берем сразу родительский элемент
			return function() {
				editor.fire('ttp-selectblock', [elementP], false);
			};
		} else {
			return function() { editor.execCommand('mceTableSelectCells'); };
		}
	}

	function removeClass(currentClasses, className, callback) {
		var re = new RegExp(' ' + className + ' ', 'g');
		return callback((' ' + currentClasses + ' ').replace(re, " ").trim());
	}

	editor.addCommand('ttpChooseLogicalBlock', function() {

		//Временное решение для выбора сразу нескольких элементов P
		var sP = editor.dom.getParent(editor.selection.getStart(), 'p');
		var eP = editor.dom.getParent(editor.selection.getEnd(), 'p');
		var section = editor.selection.getNode().childNodes;

		var startSelect = false;
		for(var i=0;i<section.length;i++){
			if(section[i]==sP){
				startSelect = true;
			}
			if(section[i]==eP){
				logicalBlock(section[i])();
				return;
			}

			if(startSelect){
				logicalBlock(section[i])();
			}
		}

		//Изначальный блок, до него не доходит, если мы выбрали несколько блоков
		logicalBlock(editor.selection.getNode())();
	});

	editor.addCommand('mceManagedBlocks', function() {
		var dom = editor.dom, linkElm;

		if (!cssId) {
			cssId = dom.uniqueId();
			linkElm = dom.create('link', {
				id: cssId,
				rel: 'stylesheet',
				href: url + '/css/managedblocks.css'
			});

			editor.getDoc().getElementsByTagName('head')[0].appendChild(linkElm);
		}

		// Toggle on/off managed blocks while computing previews
		editor.on("PreviewFormats AfterPreviewFormats", function(e) {
			if (enabled) {
				dom.toggleClass(editor.getBody(), 'ttp-managedblocks', e.type == "afterpreviewformats");
			}
		});

		dom.toggleClass(editor.getBody(), 'ttp-managedblocks');
		enabled = editor.dom.hasClass(editor.getBody(), 'ttp-managedblocks');

		if (managedBlocksMenuItem) {
			managedBlocksMenuItem.active(dom.hasClass(editor.getBody(), 'mce-managedblocks'));
		}

		editor.fire('ManagedBlocks');
	});

	function reduceToFilterListAndMax(prevState, element) {
		var max = prevState[0];
		var arr = prevState[1];
		if (element.hasAttribute("data-ttpid")) {
			var possibleId = parseInt(element.getAttribute("data-ttpid"));
			if (possibleId > max) {
				return [possibleId, arr];
			}

			return prevState;
		}

		return [max, arr.concat(element)];
	}

	function produceProcessingContainer(mk, initValueId) {
		var nextId = initValueId;

		return function(block) {
			var clearBlock = removeClass(block.className, 'ttp-chosenblock', function(clazz) {
				var copy = block.cloneNode(true);
				copy.className = clazz;
				return copy;
			});

			var bl;
			var content;
			switch (block.nodeName) {
				case 'TD':
					content = [].slice.call(clearBlock.children);
					bl = clearBlock;
					while (bl.firstChild) bl.removeChild(bl.firstChild); // remove children
					break;
				default:
					content = [clearBlock];
					bl = mk('div', {});
					break;
			};

			editor.dom.addClass(bl, 'ttp-processingblock');
			editor.dom.setAttrib(bl, 'data-ttpid', nextId++);

			var or = mk('div', {'class': 'origin viewed'});
			content.forEach(function(node) {
				or.appendChild(node);
			})

			bl.appendChild(or);
			return [block, bl];
		};
	}

	editor.addCommand('ttpProcessingBlocks', function() {
		var blocks = editor.$(".ttp-chosenblock, .ttp-processingblock");
		blocks.reduce = Array.prototype.reduce;

		var maxAndFilterList = blocks.reduce(reduceToFilterListAndMax, [0, []]);
		var nextId = maxAndFilterList[0] + 1;
		var procBlocks = maxAndFilterList[1];

		var mk = editor.dom.create.bind(editor.dom);
		procBlocks.map(produceProcessingContainer(mk, nextId))
				  .forEach(function(tupl) {
					  var block = tupl[0];
					  var container = tupl[1];

					  editor.dom.replace(container, block, false);
					  editor.execCommand('mceDisableEditableBlock', false, [container]);
				  });
	});

	editor.addButton('managedblocks', {
		title: 'Show managed blocks',
		cmd: 'mceManagedBlocks',
		onPostRender: toggleActiveState,
		icon: true,
		image: 'https://pdfimages.wondershare.com/pdfelement-mac/guide/icon-11-convert.png'
	});

	editor.addButton('ttpchooselogicalblock', {
		title: 'Choose logical block',
		cmd: 'ttpChooseLogicalBlock',
			icon: true,
		image: 'https://d30y9cdsu7xlg0.cloudfront.net/png/37722-200.png'

	});

	editor.addMenuItem('managedblocks', {
		text: 'Show managed blocks',
		cmd: 'mceManagedBlocks',
		onPostRender: toggleActiveState,
		selectable: true,
		context: 'view',
		prependToContext: true
	});

	editor.on('init', function() {
		if (editor.settings.managedblocks_default_state) {
			editor.execCommand('mceManagedBlocks', false, null, {skip_focus: true});
		}
	});

	editor.on('remove', function() {
		editor.dom.removeClass(editor.getBody(), 'ttp-managedblocks');
	});

	editor.on('ttp-selectblock', function(selectedblocks) {
		var d = editor.dom;
		selectedblocks.forEach(function(block) {
			if (!d.hasClass(block, 'ttp-processingblock') && !d.hasClass(block, 'ttp-processedblock')) {
				editor.dom.addClass(block, 'ttp-chosenblock');
			}
		});
	});
});
<|endoftext|>


<commit_before>var data = [35, 33, 42, 10, 14, 19, 20, 40];

var barWidth = 40;
var width = (barWidth + 10) * data.length;
var height = 350;

//Array size
var arrElementWidth = 50;
var arrElementHeight = 50;

//Animation
var cmd = [];
var currentCmd = 0;

//Max value in dataset
var maxValue = Math.max.apply(null, data);

var arrayList = new ArrayList(data);

//PH - Code TODO get code from another source
var codeContent = [
    "",
    "function Arraylist(a) {",
    "    for(var gap = a.length / 2; gap > 0;",
    "        gap = gap === 2 ? 1 : parseInt(gap / 2.2)) {",
    "",
    "        for(var i = gap; i < a.length; i++) {",
    "            var tmp = a[i];",
    "",
    "            for(var j = i; j >= gap && tmp < a[j - gap]; j-= gap) {",
    "                a[j] = a[j - gap];",
    "            }",
    "            a[j] = tmp;",
    "        }",
    "    }",
    "    return a;",
    "}"
];

var code = d3.select("#code-text");
var drawingArea = d3.select(".drawingArea").append("svg:svg");
var arrayGroup;

createArray(data);

function createArray(array) {
    $("g").empty();
    data = arrayList.theItems;

    width = (barWidth + 10) * data.length;

    drawingArea.attr("width", width).attr("height", height);
    arrayGroup = drawingArea.append("g");

    //Create unsorted array
    arrayGroup.selectAll("rect")
        .data(arrayList.theItems)
        .enter()
        .append("svg:rect")
        .attr("x", function (d, index) { return index * (width / data.length); })
        .attr("y", function (d) { return 0; })
        .attr("height", arrElementHeight)
        .attr("width", arrElementWidth - 5)
        .attr("fill", "red")
        .attr("class", function (d, i) { return "element" + i });

    arrayGroup.selectAll("text")
        .data(arrayList.theItems)
        .enter()
        .append("text")
        .text(function (d) { return d; })
        .attr("x", function (d, index) { return index * (width / data.length) + arrElementWidth / 3; })
        .attr("y", 30)
        .attr("width", barWidth)
        .attr("class", function (d, i) { return "element" + i });
}

function redraw() {
    width = (barWidth + 10) * data.length;

    drawingArea.attr("width", width).attr("height", height);

    arrayGroup.selectAll("rect")
        .data(arrayList.theItems)
        .enter()
        .append("svg:rect")
        .attr("x", function (d, index) { return index * (width / data.length); })
        .attr("y", function (d) { return 0; })
        .attr("height", arrElementHeight)
        .attr("width", arrElementWidth - 5)
        .attr("fill", "red")
        .attr("class", function (d, i) { return "element" + i });

    arrayGroup.selectAll("text")
        .data(arrayList.theItems)
        .enter()
        .append("text")
        .text(function (d) { return d; })
        .attr("x", function (d, index) { return index * (width / data.length) + arrElementWidth / 3; })
        .attr("y", 30)
        .attr("width", barWidth)
        .attr("class", function (d, i) { return "element" + i });
}

$( document ).ready(function() {
    initCode();
});

function highlight(a, b, color) {
    color = color || "rgb(0, 255, 0)";
    arrayGroup.selectAll("rect").filter(".element" + a)
        .transition()
        .duration(500)
        .attr("fill", "rgb(0,0,255)");
    arrayGroup.selectAll("rect").filter(".element" + b)
        .transition()
        .duration(500)
        .attr("fill", color);
}

function clearHighlight() {
    arrayGroup.selectAll("rect")
        .transition()
        .duration(500)
        .attr("fill", "rgb(255, 0, 127)");
}

function runCommand() {
    unHighlightCode();
    switch(cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4))) {
        case "swap":
            eval(cmd[currentCmd]);
            break;
        case "subl":
            eval(cmd[currentCmd]);
            break;
        case "merg":
            eval(cmd[currentCmd]);
            break;
        case "high":
            eval(cmd[currentCmd]);
            break;
        case "code":
            eval(cmd[currentCmd]);
            break;
        case "clea":
            eval(cmd[currentCmd]);
            break;
        default:
            console.log("Unknown command" + cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4)));
    }
    currentCmd++;
}

function play() {
    setTimeout(function(){
        runCommand();
        //Run next command if there is one
        if(currentCmd < cmd.length) play();
    }, 1000);
}

function initCode() {
    code.selectAll("span")
        .data(codeContent)
        .enter()
        .append("span")
        .attr("id", function(d, i) { return "codeLine" + i})
        .text(function (d) { return d })
        .append("br");

    //Restart code highlightning
    hljs.initHighlighting.called = false;
    hljs.initHighlighting();
}

function codeLineHighlight(lineNr) {
    code.selectAll("span").filter("#codeLine" + lineNr)
        .transition()
        .duration(500)
        .style("background-color", "yellow");
}

function unHighlightCode() {
    code.selectAll("span")
        .transition()
        .duration(500)
        .style("background-color", "transparent");
}
<commit_msg>arraylist before craziness<commit_after>var data = [35, 33, 40];

var barWidth = 40;
var width = (barWidth + 10) * data.length;
var height = 350;

//Array size
var arrElementWidth = 50;
var arrElementHeight = 50;

//Animation
var cmd = [];
var currentCmd = 0;

//Max value in dataset
var maxValue = Math.max.apply(null, data);

var arrayList = new ArrayList(data);

//PH - Code TODO get code from another source
var codeContent = [
    "",
    "function Arraylist(a) {",
    "    for(var gap = a.length / 2; gap > 0;",
    "        gap = gap === 2 ? 1 : parseInt(gap / 2.2)) {",
    "",
    "        for(var i = gap; i < a.length; i++) {",
    "            var tmp = a[i];",
    "",
    "            for(var j = i; j >= gap && tmp < a[j - gap]; j-= gap) {",
    "                a[j] = a[j - gap];",
    "            }",
    "            a[j] = tmp;",
    "        }",
    "    }",
    "    return a;",
    "}"
];

var code = d3.select("#code-text");
var drawingArea = d3.select(".drawingArea").append("svg:svg");
var theSizeBlock = drawingArea.append("g");

theSizeBlock.append("rect")
    .attr("width", arrayList.theSize * ((width+12.5) / arrayList.theItems.length))
    .attr("height", arrElementHeight + 40 + 10)
    .attr("fill", "lime");

theSizeBlock.append("text")
    .attr("y", 25)
    .attr("x", 10)
    .text("theSize");

var mainArray = drawingArea.append("g");

createArray(getElements(), 0, true);

function createArray(data, y, addLabels) {
    //$("g").empty();

    width = (barWidth + 10) * data.length;

    drawingArea.transition()
        .duration(250)
        .attr("width", width + 150)
        .attr("height", height);
    //arrayGroup = drawingArea.insert("g",":first-child");
    arrayGroup = mainArray;

    //Create unsorted array
    arrayGroup.selectAll("rect:not([class])")
        .data(data)
        .enter()
        .insert("svg:rect", ":first-child")
        .attr("x", function (d, index) { return index * ((width+20) / data.length) + 5; })
        .attr("y", function (d) { return 40; })
        .attr("transform", "translate(0," + y + ")")
        .attr("height", arrElementHeight)
        .attr("width", arrElementWidth - 5)
        .attr("fill", "red")
        .attr("class", function (d, i) { return "element" + i });

    //if(addLabels) {
        arrayGroup.selectAll("text")
            .data(data)
            .enter()
            .append("text")
            .text(function (d) { return ""; })
            .attr("x", function (d, index) { return index * (width / data.length) + arrElementWidth / 3 + 5; })
            .attr("y", 30+40)
            .attr("transform", "translate(0," + y + ")")
            .attr("width", barWidth)
            .attr("class", function (d, i) { return "element" + i });
    //}

    return arrayGroup;
}

function getElements() {
    var displayArr = [];
    for(var i = 0; i < arrayList.capacity; i++) {
        if(arrayList.theItems[i] == undefined) {
            displayArr[i] = "";
        } else {
            displayArr[i] = arrayList.theItems[i];
        }
    }
    console.log(displayArr);
    return displayArr;
}

function add(index, element) {
    mainArray.selectAll("text").filter(".element" + index)
        .attr("opacity", "0")
        .text(element)
        .transition()
        .duration(500)
        .attr("opacity", "1");
}

function move(to, from) {
    var fromText = mainArray.selectAll("text").filter(".element" + from).text();
    mainArray.selectAll("text").filter(".element" + to)
        .text(fromText);
}

function set(index, element) {
    mainArray.selectAll("text").filter(".element" + index)
        .transition()
        .duration(250)
        .attr("opacity", "0")
        .transition()
        .duration(500)
        .text(element)
        .attr("opacity", "1")
}

function extendCapacity(newCapacity) {
    var newArray = Array.apply(0, new Array(newCapacity)).map( function() { return ''; });
    var oldArray = mainArray.selectAll("rect");
    createArray(newArray, 100, false);

    mainArray.selectAll("text")
        .transition()
        .delay(250)
        .duration(500)
        .attr("transform", "translate(0, 100)");

    oldArray.transition()
        .delay(750)
        .duration(250)
        .attr("opacity", "0")
        .transition()
        .delay(1000)
        .duration(0)
        .remove();

    mainArray.selectAll("*")
        .transition()
        .delay(750)
        .duration(250)
        .attr("transform", "translate(0,0)")
}

function updateTheSize(newSize, length) {
    theSizeBlock.selectAll("rect")
        .transition()
        .duration(500)
        .attr("width", newSize * ((width+12.5) / length) + 5);
}

$( document ).ready(function() {
    initCode();
});

function highlight(a, b, color) {
    color = color || "rgb(0, 255, 0)";
    mainArray.selectAll("rect").filter(".element" + a)
        .transition()
        .duration(500)
        .attr("fill", "rgb(0,0,255)");
    mainArray.selectAll("rect").filter(".element" + b)
        .transition()
        .duration(500)
        .attr("fill", color);
}

function clearHighlight() {
    mainArray.selectAll("rect")
        .transition()
        .duration(500)
        .attr("fill", "rgb(255, 0, 127)");
}

function runCommand() {
    unHighlightCode();
    switch(cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4))) {
        case "swap":
            eval(cmd[currentCmd]);
            break;
        case "subl":
            eval(cmd[currentCmd]);
            break;
        case "merg":
            eval(cmd[currentCmd]);
            break;
        case "high":
            eval(cmd[currentCmd]);
            break;
        case "code":
            eval(cmd[currentCmd]);
            break;
        case "clea":
            eval(cmd[currentCmd]);
            break;
        default:
            console.log("Unknown command" + cmd[currentCmd].substring(0, Math.min(cmd[currentCmd].length, 4)));
    }
    currentCmd++;
}

function play() {
    setTimeout(function(){
        eval(commands[currentCmd]);
        currentCmd++;
        //Run next command if there is one
        if(currentCmd < commands.length) play();
    }, 1000);
}

function initCode() {
    code.selectAll("span")
        .data(codeContent)
        .enter()
        .append("span")
        .attr("id", function(d, i) { return "codeLine" + i})
        .text(function (d) { return d })
        .append("br");

    //Restart code highlightning
    hljs.initHighlighting.called = false;
    hljs.initHighlighting();
}

function codeLineHighlight(lineNr) {
    code.selectAll("span").filter("#codeLine" + lineNr)
        .transition()
        .duration(500)
        .style("background-color", "yellow");
}

function unHighlightCode() {
    code.selectAll("span")
        .transition()
        .duration(500)
        .style("background-color", "transparent");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 */
'use strict';

/**
 * @ngdoc controller
 * @name workspace.export.controller:ExportWorkspaceDialogController
 * @description This class is handling the controller for the dialog box about the export of workspace
 * @author Florent Benoit
 */
export class ExportWorkspaceDialogController {

  /**
   * Default constructor that is using resource
   * @ngInject for Dependency injection
   */
  constructor($q, $filter, lodash, cheRemote, cheNotification, $http, cheRecipeTemplate, $mdDialog, $log, $window, $scope) {
    this.$q = $q;
    this.$filter = $filter;
    this.$http = $http;
    this.lodash = lodash;
    this.cheRemote = cheRemote;
    this.cheNotification = cheNotification;
    this.cheRecipeTemplate = cheRecipeTemplate;
    this.$mdDialog = $mdDialog;
    this.$log = $log;
    this.$window = $window;
    this.editorOptions = {
      lineWrapping : true,
      lineNumbers: false,
      matchBrackets: true,
      readOnly: 'nocursor',
      mode: 'application/json'
    };
    this.privateCloudUrl = '';
    this.privateCloudLogin = '';
    this.privateCloudPassword = '';
    this.importInProgress = false;

    this.copyOfConfig = this.getCopyOfConfig();
    this.exportConfigContent = this.$filter('json')(angular.fromJson(this.copyOfConfig), 2);

    $scope.selectedIndex = this.destination === 'file' ? 0 : 1;
  }

  /**
   * It will hide the dialog box.
   */
  hide() {
    this.$mdDialog.hide();
  }

  /**
   * Returns copy of workspace's config without unnecessary properties
   * @returns {*}
   */
  getCopyOfConfig() {
    let copyOfConfig = angular.copy(this.workspaceDetails.config);

    return this.removeLinks(copyOfConfig);
  }

  /**
   * Recursively remove 'links' property from object
   *
   * @param object {Object} object to iterate
   * @returns {*}
   */
  removeLinks(object) {
    delete object.links;

    return this.lodash.forEach(object, (value) => {
      if (angular.isObject(value)) {
        return this.removeLinks(value);
      } else {
        return value;
      }
    })
  }

  /**
   * Provide ability to download workspace's config
   */
  downloadConfig() {
    this.$window.open('data:text/csv,' + encodeURIComponent(this.exportConfigContent));
  }

  /**
   * Start the process to export to the private Cloud
   */
  exportToPrivateCloud() {
    this.exportInCloudSteps = '';
    this.importInProgress = true;
    let login = this.cheRemote.newAuth(this.privateCloudUrl, this.privateCloudLogin, this.privateCloudPassword);

    login.then((authData) => {
      let copyOfConfig = angular.copy(this.copyOfConfig);
      copyOfConfig.name = 'import-' + copyOfConfig.name;

      // get content of the recipe
      let environments = copyOfConfig.environments;
      let defaultEnvName = copyOfConfig.defaultEnv;
      let defaultEnvironment = environments[defaultEnvName];

      let machineSource = defaultEnvironment.machines[0].source;
      let recipeLocation = machineSource.location;
      if (recipeLocation) {

        // get content of recipe
        this.$http.get(recipeLocation).then((response) => {

          let recipeScriptContent = response.data;
          this.exportToPrivateCloudRecipeContent(recipeScriptContent, copyOfConfig, authData);

        }, (error) => {
          this.handleError(error);
        });

      } else {
        // use content from machine source
        this.exportToPrivateCloudRecipeContent(machineSource.content, copyOfConfig, authData);
      }
    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Export the given workspace using authentication data provided and using specified recipe content
   * @param recipeScriptContent the content of the machine configuration
   * @param workspaceConfig the workspace configuration to use
   * @param authData the data including token to deal with remote server
   */
  exportToPrivateCloudRecipeContent(recipeScriptContent, workspaceConfig, authData) {
    let environments = workspaceConfig.environments;
    let defaultEnvName = workspaceConfig.defaultEnv;
    let defaultEnvironment = environments[defaultEnvName];

    defaultEnvironment.machines[0].source.content = recipeScriptContent;
    let remoteWorkspaceAPI = this.cheRemote.newWorkspace(authData);
    this.exportInCloudSteps += 'Creating remote workspace...';
    let createWorkspacePromise = remoteWorkspaceAPI.createWorkspaceFromConfig(null, workspaceConfig);
    createWorkspacePromise.then((remoteWorkspace) => {
      this.exportInCloudSteps += 'ok !
';

      if (remoteWorkspace.config.projects && remoteWorkspace.config.projects.length > 0) {
        this.startRemoteWorkspace(remoteWorkspaceAPI, remoteWorkspace, authData);
      } else {
        this.finishWorkspaceExporting(remoteWorkspace);
      }
    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Start remote workspace.
   *
   * @param remoteWorkspaceAPI remote workspace API
   * @param remoteWorkspace workspace to start
   * @param authData remote url and token data
   */
  startRemoteWorkspace(remoteWorkspaceAPI, remoteWorkspace, authData) {
    this.exportInCloudSteps += 'Starting remote workspace...';

    // compute WS url
    let remoteURL = authData.url;
    let remoteWsURL = remoteURL.replace('http', 'ws') + '/api/ws/';

    let startWorkspacePromise = remoteWorkspaceAPI.startWorkspace(remoteWsURL, remoteWorkspace.id, remoteWorkspace.config.defaultEnv);

    startWorkspacePromise.then((workspace) => {
      let wsAgentLink = this.lodash.find(workspace.runtime.links, (link) => {
        return link.rel === 'wsagent';
      });

      // grab token for machine
      let tokenPromise = remoteWorkspaceAPI.getMachineToken(remoteWorkspace.id);
      tokenPromise.then((machineTokenResult) => {
        // ask with machine token
        let agentAuthData = {url: wsAgentLink.href, token: machineTokenResult.machineToken};
        let remoteProjectAPI = this.cheRemote.newProject(agentAuthData);

        this.exportInCloudSteps += 'ok !
';
        // ok now we've to import each project with a location into the remote workspace
        let importProjectsPromise = this.importProjectsIntoWorkspace(remoteProjectAPI, remoteWorkspace);
        importProjectsPromise.then(() => {
          this.finishWorkspaceExporting(remoteWorkspace);
        }, (error) => {
          this.handleError(error);
        })
      }, (error) => {
        this.handleError(error);
      });

    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Import all projects with a given source location into the remote workspace
   *
   * @param remoteProjectAPI the remote project API
   * @param workspace the remote workspace
   */
  importProjectsIntoWorkspace(remoteProjectAPI, workspace) {
    var projectPromises = [];

    workspace.config.projects.forEach((project) => {
      if (project.source && project.source.location && project.source.location.length > 0) {
        let deferred = this.$q.defer();
        let deferredPromise = deferred.promise;
        projectPromises.push(deferredPromise);
        let importProjectPromise = remoteProjectAPI.importProject(project.name, project.source);

        importProjectPromise.then(() => {
          this.exportInCloudSteps += 'Importing project ' + project.name + '...
';
          let updateProjectPromise = remoteProjectAPI.updateProject(project.name, project);
          updateProjectPromise.then(() => {
            deferred.resolve(workspace);
          }, (error) => {
            deferred.reject(error);
          });
        }, (error) => {
          deferred.reject(error);
        });
      }
    });
    return this.$q.all(projectPromises);
  }

  /**
   * Finilize the Workspace exporting - show proper messages, close popup.
   *
   * @param remoteWorkspace the remote exported workspace
   */
  finishWorkspaceExporting(remoteWorkspace) {
    this.exportInCloudSteps += 'Export of workspace ' + remoteWorkspace.config.name + 'finished
';
    this.cheNotification.showInfo('Successfully exported the workspace to ' + remoteWorkspace.config.name + ' on ' + this.privateCloudUrl);
    this.hide();
  }

  /**
   * Notify user about the error.
   * @param error the error message to display
   */
  handleError(error) {
    this.importInProgress = false;
    var message;
    if (error.data) {
      if (error.data.message) {
        message = error.data.message;
      } else {
        message = error.data;
      }
    } else if(error.config && error.config.url) {
      message = 'unable to connect to ' + error.config.url;
    }
    this.cheNotification.showError('Exporting workspace failed: ' + message);
    this.$log.error('error', message, error);
  }

}
<commit_msg>fix workspace editor options for UD<commit_after>/*
 * Copyright (c) 2015-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 */
'use strict';

/**
 * @ngdoc controller
 * @name workspace.export.controller:ExportWorkspaceDialogController
 * @description This class is handling the controller for the dialog box about the export of workspace
 * @author Florent Benoit
 */
export class ExportWorkspaceDialogController {

  /**
   * Default constructor that is using resource
   * @ngInject for Dependency injection
   */
  constructor($q, $filter, lodash, cheRemote, cheNotification, $http, cheRecipeTemplate, $mdDialog, $log, $window, $scope) {
    this.$q = $q;
    this.$filter = $filter;
    this.$http = $http;
    this.lodash = lodash;
    this.cheRemote = cheRemote;
    this.cheNotification = cheNotification;
    this.cheRecipeTemplate = cheRecipeTemplate;
    this.$mdDialog = $mdDialog;
    this.$log = $log;
    this.$window = $window;
    this.editorOptions = {
      lineWrapping : true,
      lineNumbers: false,
      matchBrackets: true,
      readOnly: true,
      mode: 'application/json'
    };
    this.privateCloudUrl = '';
    this.privateCloudLogin = '';
    this.privateCloudPassword = '';
    this.importInProgress = false;

    this.copyOfConfig = this.getCopyOfConfig();
    this.exportConfigContent = this.$filter('json')(angular.fromJson(this.copyOfConfig), 2);

    $scope.selectedIndex = this.destination === 'file' ? 0 : 1;
  }

  /**
   * It will hide the dialog box.
   */
  hide() {
    this.$mdDialog.hide();
  }

  /**
   * Returns copy of workspace's config without unnecessary properties
   * @returns {*}
   */
  getCopyOfConfig() {
    let copyOfConfig = angular.copy(this.workspaceDetails.config);

    return this.removeLinks(copyOfConfig);
  }

  /**
   * Recursively remove 'links' property from object
   *
   * @param object {Object} object to iterate
   * @returns {*}
   */
  removeLinks(object) {
    delete object.links;

    return this.lodash.forEach(object, (value) => {
      if (angular.isObject(value)) {
        return this.removeLinks(value);
      } else {
        return value;
      }
    })
  }

  /**
   * Provide ability to download workspace's config
   */
  downloadConfig() {
    this.$window.open('data:text/csv,' + encodeURIComponent(this.exportConfigContent));
  }

  /**
   * Start the process to export to the private Cloud
   */
  exportToPrivateCloud() {
    this.exportInCloudSteps = '';
    this.importInProgress = true;
    let login = this.cheRemote.newAuth(this.privateCloudUrl, this.privateCloudLogin, this.privateCloudPassword);

    login.then((authData) => {
      let copyOfConfig = angular.copy(this.copyOfConfig);
      copyOfConfig.name = 'import-' + copyOfConfig.name;

      // get content of the recipe
      let environments = copyOfConfig.environments;
      let defaultEnvName = copyOfConfig.defaultEnv;
      let defaultEnvironment = environments[defaultEnvName];

      let machineSource = defaultEnvironment.machines[0].source;
      let recipeLocation = machineSource.location;
      if (recipeLocation) {

        // get content of recipe
        this.$http.get(recipeLocation).then((response) => {

          let recipeScriptContent = response.data;
          this.exportToPrivateCloudRecipeContent(recipeScriptContent, copyOfConfig, authData);

        }, (error) => {
          this.handleError(error);
        });

      } else {
        // use content from machine source
        this.exportToPrivateCloudRecipeContent(machineSource.content, copyOfConfig, authData);
      }
    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Export the given workspace using authentication data provided and using specified recipe content
   * @param recipeScriptContent the content of the machine configuration
   * @param workspaceConfig the workspace configuration to use
   * @param authData the data including token to deal with remote server
   */
  exportToPrivateCloudRecipeContent(recipeScriptContent, workspaceConfig, authData) {
    let environments = workspaceConfig.environments;
    let defaultEnvName = workspaceConfig.defaultEnv;
    let defaultEnvironment = environments[defaultEnvName];

    defaultEnvironment.machines[0].source.content = recipeScriptContent;
    let remoteWorkspaceAPI = this.cheRemote.newWorkspace(authData);
    this.exportInCloudSteps += 'Creating remote workspace...';
    let createWorkspacePromise = remoteWorkspaceAPI.createWorkspaceFromConfig(null, workspaceConfig);
    createWorkspacePromise.then((remoteWorkspace) => {
      this.exportInCloudSteps += 'ok !
';

      if (remoteWorkspace.config.projects && remoteWorkspace.config.projects.length > 0) {
        this.startRemoteWorkspace(remoteWorkspaceAPI, remoteWorkspace, authData);
      } else {
        this.finishWorkspaceExporting(remoteWorkspace);
      }
    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Start remote workspace.
   *
   * @param remoteWorkspaceAPI remote workspace API
   * @param remoteWorkspace workspace to start
   * @param authData remote url and token data
   */
  startRemoteWorkspace(remoteWorkspaceAPI, remoteWorkspace, authData) {
    this.exportInCloudSteps += 'Starting remote workspace...';

    // compute WS url
    let remoteURL = authData.url;
    let remoteWsURL = remoteURL.replace('http', 'ws') + '/api/ws/';

    let startWorkspacePromise = remoteWorkspaceAPI.startWorkspace(remoteWsURL, remoteWorkspace.id, remoteWorkspace.config.defaultEnv);

    startWorkspacePromise.then((workspace) => {
      let wsAgentLink = this.lodash.find(workspace.runtime.links, (link) => {
        return link.rel === 'wsagent';
      });

      // grab token for machine
      let tokenPromise = remoteWorkspaceAPI.getMachineToken(remoteWorkspace.id);
      tokenPromise.then((machineTokenResult) => {
        // ask with machine token
        let agentAuthData = {url: wsAgentLink.href, token: machineTokenResult.machineToken};
        let remoteProjectAPI = this.cheRemote.newProject(agentAuthData);

        this.exportInCloudSteps += 'ok !
';
        // ok now we've to import each project with a location into the remote workspace
        let importProjectsPromise = this.importProjectsIntoWorkspace(remoteProjectAPI, remoteWorkspace);
        importProjectsPromise.then(() => {
          this.finishWorkspaceExporting(remoteWorkspace);
        }, (error) => {
          this.handleError(error);
        })
      }, (error) => {
        this.handleError(error);
      });

    }, (error) => {
      this.handleError(error);
    });
  }

  /**
   * Import all projects with a given source location into the remote workspace
   *
   * @param remoteProjectAPI the remote project API
   * @param workspace the remote workspace
   */
  importProjectsIntoWorkspace(remoteProjectAPI, workspace) {
    var projectPromises = [];

    workspace.config.projects.forEach((project) => {
      if (project.source && project.source.location && project.source.location.length > 0) {
        let deferred = this.$q.defer();
        let deferredPromise = deferred.promise;
        projectPromises.push(deferredPromise);
        let importProjectPromise = remoteProjectAPI.importProject(project.name, project.source);

        importProjectPromise.then(() => {
          this.exportInCloudSteps += 'Importing project ' + project.name + '...
';
          let updateProjectPromise = remoteProjectAPI.updateProject(project.name, project);
          updateProjectPromise.then(() => {
            deferred.resolve(workspace);
          }, (error) => {
            deferred.reject(error);
          });
        }, (error) => {
          deferred.reject(error);
        });
      }
    });
    return this.$q.all(projectPromises);
  }

  /**
   * Finilize the Workspace exporting - show proper messages, close popup.
   *
   * @param remoteWorkspace the remote exported workspace
   */
  finishWorkspaceExporting(remoteWorkspace) {
    this.exportInCloudSteps += 'Export of workspace ' + remoteWorkspace.config.name + 'finished
';
    this.cheNotification.showInfo('Successfully exported the workspace to ' + remoteWorkspace.config.name + ' on ' + this.privateCloudUrl);
    this.hide();
  }

  /**
   * Notify user about the error.
   * @param error the error message to display
   */
  handleError(error) {
    this.importInProgress = false;
    var message;
    if (error.data) {
      if (error.data.message) {
        message = error.data.message;
      } else {
        message = error.data;
      }
    } else if(error.config && error.config.url) {
      message = 'unable to connect to ' + error.config.url;
    }
    this.cheNotification.showError('Exporting workspace failed: ' + message);
    this.$log.error('error', message, error);
  }

}
<|endoftext|>


<commit_before>import Section from '../section'

const Logo = ({ href, name }) => (

    <img key={name} src={`/static/images/logos/${name}.png`} />

)
const Logos = () => (

    <Logo name="zeit" href="https://zeit.co/" />
    <Logo name="circle-ci" href="https://circleci.com/" />
    <Logo name="sentry" href="https://getsentry.io/" />
    <Logo name="git-hub" href="https://github.com/" />
    <Logo name="google" href="https://google.com/" />
    <Logo name="facebook" href="https://facebook.com/" />

)
export default () => (

Loved by the community

Designers, developers, project managers. They all use Kap.

      <Logos />

)
<commit_msg>🎉 Font  size<commit_after>import Section from '../section'

const Logo = ({ href, name }) => (

    <img key={name} src={`/static/images/logos/${name}.png`} />

)
const Logos = () => (

    <Logo name="zeit" href="https://zeit.co/" />
    <Logo name="circle-ci" href="https://circleci.com/" />
    <Logo name="sentry" href="https://getsentry.io/" />
    <Logo name="git-hub" href="https://github.com/" />
    <Logo name="google" href="https://google.com/" />
    <Logo name="facebook" href="https://facebook.com/" />

)
export default () => (

Loved by the community

Designers, developers, project managers. They all use Kap.

      <Logos />

)
<|endoftext|>


<commit_before>/*
 * This file contains all the authentication logic for the Khan Academy Contest Judging System
 */
window.Authentication_Logic = (function() {
	if (!Firebase || !jQuery || !Contest_Judging_System) {
		console.log("[Authentication_Logic] Firebase and jQuery are both required!");
		return;
	}

	return {
		doesUserExist: function(authData, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			var knownUsers = { };

			usersRef.orderByKey().on("child_added", function(snapshot) {
				knownUsers[snapshot.key()] = snapshot.val();
			});

			usersRef.once("value", function() {
				/* If this user's UID was found in knownUsers... */
				if (knownUsers.hasOwnProperty(authData.uid)) {
					/* ...pass true to our callback! */
					callback(true);
				} else {
					/* ...pass false into our callback. */
					callback(true);
				}
			});
		},
		createUser: function(userData) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			usersRef.child(userData.uid).set({
				name: userData.google.displayName,
				permLevel: 1
			});
		},
		logUserIn: function(callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");

			fbRef.authWithOAuthPopup("google", function(error, authData) {
				/* If an error occurred, log the error to the console, and pass false to our callback. */
				if (error) {
					console.log(error);
					callback(false);
				}

				Authentication_Logic.doesUserExist(authData, function(doTheyExist) {
					if (doTheyExist) {
						Contest_Judging_System.setCookie("loggedInUID", authData.uid);
					} else {
						/* The user doesn't exist. Sign them up? */
						Authentication_Logic.createUser(authData);
						Contest_Judging_System.setCookie("loggedInUID", authData.uid);
					}
				});
			});
		},
		userHasCorrectPermissions: function(uid, requiredPerms, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			var thisUser = { };

			usersRef.orderByKey().equalTo(uid).on("child_added", function(snapshot) {
				thisUser = snapshot.val();
			});

			usersRef.once("value", function() {
				/* Pass a boolean value to our callback. The boolean is determined based on whether or not the user has the permission level that is required for a certain task. */
				callback(thisUser.permLevel === requiredPerms);
			});
		},
		getPermLevel: function(uid, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");
			var thisUserRef = usersRef.child(uid);

			var permLevel = -1;

			thisUserRef.orderByKey().equalTo("permLevel").on("child_added", function(data) {
				permLevel = data.val().permLevel;
			});

			thisUserRef.once("value", function() {
				callback(permLevel);
			});
		}
	};
})();<commit_msg>Removed Authentication_Logic from the window object<commit_after>/*
 * This file contains all the authentication logic for the Khan Academy Contest Judging System
 */
var Authentication_Logic = (function() {
	if (!Firebase || !jQuery || !Contest_Judging_System) {
		console.log("[Authentication_Logic] Firebase and jQuery are both required!");
		return;
	}

	return {
		doesUserExist: function(authData, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			var knownUsers = { };

			usersRef.orderByKey().on("child_added", function(snapshot) {
				knownUsers[snapshot.key()] = snapshot.val();
			});

			usersRef.once("value", function() {
				/* If this user's UID was found in knownUsers... */
				if (knownUsers.hasOwnProperty(authData.uid)) {
					/* ...pass true to our callback! */
					callback(true);
				} else {
					/* ...pass false into our callback. */
					callback(true);
				}
			});
		},
		createUser: function(userData) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			usersRef.child(userData.uid).set({
				name: userData.google.displayName,
				permLevel: 1
			});
		},
		logUserIn: function(callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");

			fbRef.authWithOAuthPopup("google", function(error, authData) {
				/* If an error occurred, log the error to the console, and pass false to our callback. */
				if (error) {
					console.log(error);
					callback(false);
				}

				Authentication_Logic.doesUserExist(authData, function(doTheyExist) {
					if (doTheyExist) {
						Contest_Judging_System.setCookie("loggedInUID", authData.uid);
					} else {
						/* The user doesn't exist. Sign them up? */
						Authentication_Logic.createUser(authData);
						Contest_Judging_System.setCookie("loggedInUID", authData.uid);
					}
				});
			});
		},
		userHasCorrectPermissions: function(uid, requiredPerms, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");

			var thisUser = { };

			usersRef.orderByKey().equalTo(uid).on("child_added", function(snapshot) {
				thisUser = snapshot.val();
			});

			usersRef.once("value", function() {
				/* Pass a boolean value to our callback. The boolean is determined based on whether or not the user has the permission level that is required for a certain task. */
				callback(thisUser.permLevel === requiredPerms);
			});
		},
		getPermLevel: function(uid, callback) {
			var fbRef = new Firebase("https://contest-judging-sys.firebaseio.com");
			var usersRef = fbRef.child("users");
			var thisUserRef = usersRef.child(uid);

			var permLevel = -1;

			thisUserRef.orderByKey().equalTo("permLevel").on("child_added", function(data) {
				permLevel = data.val().permLevel;
			});

			thisUserRef.once("value", function() {
				callback(permLevel);
			});
		}
	};
})();<|endoftext|>