<commit_before>/**
 * tracingtool.js
 *
 * requirements:
 *	 tools.js
 *	 ui.js
 *	 slider.js
 *   stack.js
 */

/**
 */

/**
 * Constructor for the tracing tool.
 */
function TracingTool()
{
  this.prototype = new Navigator();

  var self = this;
  var tracingLayer = null;
  var stack = null;
  var bindings = {};

	this.resize = function( width, height )
	{
        self.prototype.resize( width, height );
		return;
	}

  var setupSubTools = function()
  {
    // TODO: replace with project.js strings
    if ( self.prototype.stack == null ) {
      var box = $( '

' );
      [ { name : "skeleton", alt : "skeleton" },
        { name : "synapse", alt : "synapse" },
        { name : "goactive", alt : "go to active element" },
        { name : "skelsplitting", alt : "split skeleton" },
        { name : "skelrerooting", alt : "reroot skeleton" },
        { name : "togglelabels", alt : "toggle labels" },
        { name : "3dview", alt : "3d view" } ].map(
        function( button ) {
          var a = document.createElement('a');
          a.setAttribute('class', 'button');
          a.setAttribute('id', 'trace_button_' + button.name);
          a.onclick = function( e ) {
            tracingLayer.svgOverlay.tracingCommand(button.name);
            return false;
          };
          var img = document.createElement('img');
          img.setAttribute('title', button.alt);
          img.setAttribute('alt', button.alt);
          img.setAttribute('src', 'widgets/themes/kde/trace_' + button.name + '.png');
          a.appendChild(img);
          box.append(a);
        }
      );
      $( "#toolbar_nav" ).prepend( box );
    }
  }

  var createTracingLayer = function( parentStack )
  {
    stack = parentStack;
    tracingLayer = new TracingLayer( parentStack );
    //this.prototype.mouseCatcher = tracingLayer.svgOverlay.getView();
    self.prototype.setMouseCatcher( tracingLayer.svgOverlay.view );
    parentStack.addLayer( "TracingLayer", tracingLayer );

    // Call register AFTER changing the mouseCatcher
    self.prototype.register( parentStack, "edit_button_trace" );

    // NOW set the mode TODO cleanup this initialization problem
    tracingLayer.svgOverlay.set_tracing_mode( "skeletontracing" );
    tracingLayer.svgOverlay.updateNodes();

    // view is the mouseCatcher now
    var view = tracingLayer.svgOverlay.view;

    var proto_onmousedown = view.onmousedown;
    view.onmousedown = function( e ) {
      switch ( ui.getMouseButton( e ) )
      {
        case 1:
          tracingLayer.svgOverlay.whenclicked( e );
          break;
        case 2:
          proto_onmousedown( e );
          ui.registerEvent( "onmousemove", updateStatusBar );
          ui.registerEvent( "onmouseup",
            function onmouseup (e) {
              ui.releaseEvents();
              ui.removeEvent( "onmousemove", updateStatusBar );
              ui.removeEvent( "onmouseup", onmouseup );
              // Recreate nodes by feching them from the database for the new field of view
              tracingLayer.svgOverlay.updateNodes();
            });
          break;
        default:
          proto_onmousedown( e );
          break;
      }
      return;
    };

    var proto_changeSlice = self.prototype.changeSlice;
    self.prototype.changeSlice =
      function( val ) {
        proto_changeSlice( val );
        tracingLayer.svgOverlay.updateNodes();
      };
  }

	/**
	 * install this tool in a stack.
	 * register all GUI control elements and event handlers
	 */
	this.register = function( parentStack )
	{
    setupSubTools();

    if (tracingLayer && stack) {
      if (stack !== parentStack) {
        // If the tracing layer exists and it belongs to a different stack, replace it
        stack.removeLayer( tracingLayer );
        createTracingLayer( parentStack );
      } else {
        reactivateBindings();
      }
    } else {
      createTracingLayer( parentStack );
    }

    return;
  }

  /** Inactivate only onmousedown, given that the others are injected when onmousedown is called.
   * Leave alone onmousewheel: it is different in every browser, and it cannot do any harm to have it active. */
  var inactivateBindings = function() {
    var c = self.prototype.mouseCatcher;
    ['onmousedown'].map(
      function ( fn ) {
        if (c[fn]) {
          bindings[fn] = c[fn];
          delete c[fn];
        }
      });
  }

  var reactivateBindings = function() {
    var c = self.prototype.mouseCatcher;
    for (var b in bindings) {
      if (bindings.hasOwnProperty(b)) {
        c[b.name] = b;
      }
    }
  };

	/**
	 * unregister all stack related mouse and keyboard controls
	 */
	this.unregister = function()
	{
    // do it before calling the prototype destroy that sets stack to null
    if (self.prototype.stack) {
      inactivateBindings();
    }
    // Do NOT unregister: would remove the mouseCatcher layer
    // and the annotations would disappear
    //self.prototype.unregister();
    return;
	}

	/**
	 * unregister all project related GUI control connections and event
	 * handlers, toggle off tool activity signals (like buttons)
	 */
	this.destroy = function()
	{
    // Synchronize data with database
    tracingLayer.svgOverlay.updateNodeCoordinatesinDB();

    // the prototype destroy calls the prototype's unregister, not self.unregister
    // do it before calling the prototype destroy that sets stack to null
    self.prototype.stack.removeLayer( "TracingLayer" );
    self.prototype.destroy( "edit_button_trace" );
    $( "#tracingbuttons" ).remove();
    tracingLayer.svgOverlay.destroy();
    //
    for (var b in bindings) {
      if (bindings.hasOwnProperty(b)) {
        delete bindings[b];
      }
    }
    return;
	};

  var updateStatusBar = function( e ) {
    var m = ui.getMouse(e, true);
    var offX, offY, pos_x, pos_y;
    if (m) {
      // add right move of svgOverlay to the m.offsetX
      offX = m.offsetX + tracingLayer.svgOverlay.offleft;
      // add down move of svgOverlay to the m.offsetY
      offY = m.offsetY + tracingLayer.svgOverlay.offtop;

      // TODO pos_x and pos_y never change
      pos_x = stack.translation.x + (stack.x + (offX - stack.viewWidth / 2) / stack.scale) * stack.resolution.x;
      pos_y = stack.translation.x + (stack.y + (offY - stack.viewHeight / 2) / stack.scale) * stack.resolution.y;
      statusBar.replaceLast("[" + pos_x.toFixed(3) + ", " + pos_y.toFixed(3) + "]" + " stack.x,y: " + stack.x + ", " + stack.y);
    }
    return true;
  };

    var actions = [];

    this.addAction = function ( action ) {
	actions.push( action );
    }

    this.getActions = function () {
	return actions;
    }

    var arrowKeyCodes = {
	left: 37,
	up: 38,
	right: 39,
	down: 40
    };

    this.addAction( new Action({
	helpText: "Zoom in",
	keyShortcuts: {
	    '+': [ 43, 107, 61, 187 ]
	},
	run: function (e) {
	    self.prototype.slider_s.move(1);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Zoom out",
	keyShortcuts: {
	    '-': [ 45, 109, 189 ]
	},
	run: function (e) {
	    self.prototype.slider_s.move(-1);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move up 1 slice in z (or 10 with Shift held)",
	keyShortcuts: {
	    ',': [ 44, 188 ]
	},
	run: function (e) {
	    self.prototype.slider_z.move(-(e.shiftKey ? 10 : 1));
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move down 1 slice in z (or 10 with Shift held)",
	keyShortcuts: {
	    '.': [ 46, 190 ]
	},
	run: function (e) {
	    self.prototype.slider_z.move((e.shiftKey ? 10 : 1));
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move left (towards negative x)",
	keyShortcuts: {
	    "\u2190": [ arrowKeyCodes.left ]
	},
	run: function (e) {
	    self.prototype.input_x.value = parseInt(self.prototype.input_x.value, 10) - (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
	    self.prototype.input_x.onchange(e);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move right (towards positive x)",
	keyShortcuts: {
	    "\u2192": [ arrowKeyCodes.right ],
	},
	run: function (e) {
	    self.prototype.input_x.value = parseInt(self.prototype.input_x.value, 10) + (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
	    self.prototype.input_x.onchange(e);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move up (towards negative y)",
	keyShortcuts: {
	    "\u2191": [ arrowKeyCodes.up ]
	},
	run: function (e) {
	    self.prototype.input_y.value = parseInt(self.prototype.input_y.value, 10) - (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
	    self.prototype.input_y.onchange(e);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Move down (towards positive y)",
	keyShortcuts: {
	    "\u2193": [ arrowKeyCodes.down ]
	},
	run: function (e) {
	    self.prototype.input_y.value = parseInt(self.prototype.input_y.value, 10) + (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
	    self.prototype.input_y.onchange(e);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Go to active node",
	buttonID: [ 'trace_button_goactive' ],
	keyShortcuts: {
	    "A": [ 65 ]
	},
	run: function (e) {
	    var atn = SkeletonAnnotations.getActiveNode();
	    if (atn != null) {
		project.moveTo(
		    tracingLayer.svgOverlay.pix2physZ(atn.z),
		    tracingLayer.svgOverlay.pix2physY(atn.y),
		    tracingLayer.svgOverlay.pix2physX(atn.x));
	    } else {
		alert("No active node to go to!");
	    }
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Deselect the active node",
	keyShortcuts:  {
	    "M": [ 77 ]
	},
	run: function (e) {
	    activateNode(null);
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Go to the parent of the active node (?)",
	keyShortcuts: {
	    "P": [ 80 ]
	},
	run: function (e) {
	    project.tracingCommand('goparent');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Go to last edited node in this skeleton",
	keyShortcuts: {
	    "E": [ 69 ]
	},
	run: function (e) {
	    project.tracingCommand('golastedited');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Split this skeleton at the active node",
	buttonID: [ 'trace_button_skelsplitting' ],
	keyShortcuts: {
	    "5": [ 53 ]
	},
	run: function (e) {
	    project.tracingCommand('skeletonsplitting');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Re-root this skeleton at the active node",
	buttonID: [ 'trace_button_skelrerooting' ],
	keyShortcuts: {
	    "6": [ 54 ]
	},
	run: function (e) {
	    project.tracingCommand('skeletonreroot');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Toggle the display of labels",
	buttonID: [ 'trace_button_togglelabels' ],
	keyShortcuts: {
	    "7": [ 55 ]
	},
	run: function (e) {
	    project.tracingCommand('togglelabels');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Export to SWC",
	buttonID: [ 'trace_button_exportswc' ],
	keyShortcuts: {
	    "S": [ 83 ]
	},
	run: function (e) {
	    project.tracingCommand('exportswc');
	    return false;
	}
    }) );

    this.addAction( new Action({
	helpText: "Tag the active node",
	keyShortcuts: {
	    "T": [ 84 ]
	},
	run: function (e) {
	    if (!(e.ctrlKey || e.metaKey)) {
		project.tracingCommand('tagging');
	    }
	    return true;
	}
    }) );

    this.addAction( new Action({
	helpText: "Select the nearest node to the mouse cursor",
	keyShortcuts: {
	    "G": [ 71 ]
	},
	run: function (e) {
	    if (!(e.ctrlKey || e.metaKey)) {
		project.activateNearestNode();
	    }
	    return true;
	}
    }) );

    var keyCodeToAction = getKeyCodeToActionMap(actions);

    setButtonClicksFromActions(actions);

    /** This function should return true if there was any action
        linked to the key code, or false otherwise. */

    this.handleKeyPress = function( e ) {
        var keyAction = keyCodeToAction[e.keyCode];
        if (keyAction) {
	    keyAction.run(e || event);
	    return true;
	} else {
            return false;
	}
    }

    this.getMouseHelp = function( e ) {
	var result = '
';
	result += 'click on a node: make that node active
'
        result += 'ctrl-click in space: deselect the active node
';
        result += 'ctrl-shift-click on a node: delete that node
';
        result += 'shift-click in space: create a synapse (if there was an active treenode)
';
        result += 'shift-click in space: create a post-synaptic node (if there was an active synapse)
';
        result += 'shift-click on a treenode: join two skeletons (if there was an active treenode)
';
        result += '
';
	return result;
    }

}
<commit_msg>Fix the whitespace in tracingtool.js<commit_after>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

/**
 * tracingtool.js
 *
 * requirements:
 *	 tools.js
 *	 ui.js
 *	 slider.js
 *   stack.js
 */

/**
 */

/**
 * Constructor for the tracing tool.
 */
function TracingTool()
{
  this.prototype = new Navigator();

  var self = this;
  var tracingLayer = null;
  var stack = null;
  var bindings = {};

	this.resize = function( width, height )
	{
        self.prototype.resize( width, height );
		return;
	}

  var setupSubTools = function()
  {
    // TODO: replace with project.js strings
    if ( self.prototype.stack == null ) {
      var box = $( '

' );
      [ { name : "skeleton", alt : "skeleton" },
        { name : "synapse", alt : "synapse" },
        { name : "goactive", alt : "go to active element" },
        { name : "skelsplitting", alt : "split skeleton" },
        { name : "skelrerooting", alt : "reroot skeleton" },
        { name : "togglelabels", alt : "toggle labels" },
        { name : "3dview", alt : "3d view" } ].map(
        function( button ) {
          var a = document.createElement('a');
          a.setAttribute('class', 'button');
          a.setAttribute('id', 'trace_button_' + button.name);
          a.onclick = function( e ) {
            tracingLayer.svgOverlay.tracingCommand(button.name);
            return false;
          };
          var img = document.createElement('img');
          img.setAttribute('title', button.alt);
          img.setAttribute('alt', button.alt);
          img.setAttribute('src', 'widgets/themes/kde/trace_' + button.name + '.png');
          a.appendChild(img);
          box.append(a);
        }
      );
      $( "#toolbar_nav" ).prepend( box );
    }
  }

  var createTracingLayer = function( parentStack )
  {
    stack = parentStack;
    tracingLayer = new TracingLayer( parentStack );
    //this.prototype.mouseCatcher = tracingLayer.svgOverlay.getView();
    self.prototype.setMouseCatcher( tracingLayer.svgOverlay.view );
    parentStack.addLayer( "TracingLayer", tracingLayer );

    // Call register AFTER changing the mouseCatcher
    self.prototype.register( parentStack, "edit_button_trace" );

    // NOW set the mode TODO cleanup this initialization problem
    tracingLayer.svgOverlay.set_tracing_mode( "skeletontracing" );
    tracingLayer.svgOverlay.updateNodes();

    // view is the mouseCatcher now
    var view = tracingLayer.svgOverlay.view;

    var proto_onmousedown = view.onmousedown;
    view.onmousedown = function( e ) {
      switch ( ui.getMouseButton( e ) )
      {
        case 1:
          tracingLayer.svgOverlay.whenclicked( e );
          break;
        case 2:
          proto_onmousedown( e );
          ui.registerEvent( "onmousemove", updateStatusBar );
          ui.registerEvent( "onmouseup",
            function onmouseup (e) {
              ui.releaseEvents();
              ui.removeEvent( "onmousemove", updateStatusBar );
              ui.removeEvent( "onmouseup", onmouseup );
              // Recreate nodes by feching them from the database for the new field of view
              tracingLayer.svgOverlay.updateNodes();
            });
          break;
        default:
          proto_onmousedown( e );
          break;
      }
      return;
    };

    var proto_changeSlice = self.prototype.changeSlice;
    self.prototype.changeSlice =
      function( val ) {
        proto_changeSlice( val );
        tracingLayer.svgOverlay.updateNodes();
      };
  }

	/**
	 * install this tool in a stack.
	 * register all GUI control elements and event handlers
	 */
	this.register = function( parentStack )
	{
    setupSubTools();

    if (tracingLayer && stack) {
      if (stack !== parentStack) {
        // If the tracing layer exists and it belongs to a different stack, replace it
        stack.removeLayer( tracingLayer );
        createTracingLayer( parentStack );
      } else {
        reactivateBindings();
      }
    } else {
      createTracingLayer( parentStack );
    }

    return;
  }

  /** Inactivate only onmousedown, given that the others are injected when onmousedown is called.
   * Leave alone onmousewheel: it is different in every browser, and it cannot do any harm to have it active. */
  var inactivateBindings = function() {
    var c = self.prototype.mouseCatcher;
    ['onmousedown'].map(
      function ( fn ) {
        if (c[fn]) {
          bindings[fn] = c[fn];
          delete c[fn];
        }
      });
  }

  var reactivateBindings = function() {
    var c = self.prototype.mouseCatcher;
    for (var b in bindings) {
      if (bindings.hasOwnProperty(b)) {
        c[b.name] = b;
      }
    }
  };

	/**
	 * unregister all stack related mouse and keyboard controls
	 */
	this.unregister = function()
	{
    // do it before calling the prototype destroy that sets stack to null
    if (self.prototype.stack) {
      inactivateBindings();
    }
    // Do NOT unregister: would remove the mouseCatcher layer
    // and the annotations would disappear
    //self.prototype.unregister();
    return;
	}

	/**
	 * unregister all project related GUI control connections and event
	 * handlers, toggle off tool activity signals (like buttons)
	 */
	this.destroy = function()
	{
    // Synchronize data with database
    tracingLayer.svgOverlay.updateNodeCoordinatesinDB();

    // the prototype destroy calls the prototype's unregister, not self.unregister
    // do it before calling the prototype destroy that sets stack to null
    self.prototype.stack.removeLayer( "TracingLayer" );
    self.prototype.destroy( "edit_button_trace" );
    $( "#tracingbuttons" ).remove();
    tracingLayer.svgOverlay.destroy();
    //
    for (var b in bindings) {
      if (bindings.hasOwnProperty(b)) {
        delete bindings[b];
      }
    }
    return;
	};

  var updateStatusBar = function( e ) {
    var m = ui.getMouse(e, true);
    var offX, offY, pos_x, pos_y;
    if (m) {
      // add right move of svgOverlay to the m.offsetX
      offX = m.offsetX + tracingLayer.svgOverlay.offleft;
      // add down move of svgOverlay to the m.offsetY
      offY = m.offsetY + tracingLayer.svgOverlay.offtop;

      // TODO pos_x and pos_y never change
      pos_x = stack.translation.x + (stack.x + (offX - stack.viewWidth / 2) / stack.scale) * stack.resolution.x;
      pos_y = stack.translation.x + (stack.y + (offY - stack.viewHeight / 2) / stack.scale) * stack.resolution.y;
      statusBar.replaceLast("[" + pos_x.toFixed(3) + ", " + pos_y.toFixed(3) + "]" + " stack.x,y: " + stack.x + ", " + stack.y);
    }
    return true;
  };

  var actions = [];

  this.addAction = function ( action ) {
    actions.push( action );
  }

  this.getActions = function () {
    return actions;
  }

  var arrowKeyCodes = {
    left: 37,
    up: 38,
    right: 39,
    down: 40
  };

  this.addAction( new Action({
    helpText: "Zoom in",
    keyShortcuts: {
      '+': [ 43, 107, 61, 187 ]
    },
    run: function (e) {
      self.prototype.slider_s.move(1);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Zoom out",
    keyShortcuts: {
      '-': [ 45, 109, 189 ]
    },
    run: function (e) {
      self.prototype.slider_s.move(-1);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move up 1 slice in z (or 10 with Shift held)",
    keyShortcuts: {
      ',': [ 44, 188 ]
    },
    run: function (e) {
      self.prototype.slider_z.move(-(e.shiftKey ? 10 : 1));
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move down 1 slice in z (or 10 with Shift held)",
    keyShortcuts: {
      '.': [ 46, 190 ]
    },
    run: function (e) {
      self.prototype.slider_z.move((e.shiftKey ? 10 : 1));
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move left (towards negative x)",
    keyShortcuts: {
      "\u2190": [ arrowKeyCodes.left ]
    },
    run: function (e) {
      self.prototype.input_x.value = parseInt(self.prototype.input_x.value, 10) - (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
      self.prototype.input_x.onchange(e);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move right (towards positive x)",
    keyShortcuts: {
      "\u2192": [ arrowKeyCodes.right ],
    },
    run: function (e) {
      self.prototype.input_x.value = parseInt(self.prototype.input_x.value, 10) + (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
      self.prototype.input_x.onchange(e);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move up (towards negative y)",
    keyShortcuts: {
      "\u2191": [ arrowKeyCodes.up ]
    },
    run: function (e) {
      self.prototype.input_y.value = parseInt(self.prototype.input_y.value, 10) - (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
      self.prototype.input_y.onchange(e);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Move down (towards positive y)",
    keyShortcuts: {
      "\u2193": [ arrowKeyCodes.down ]
    },
    run: function (e) {
      self.prototype.input_y.value = parseInt(self.prototype.input_y.value, 10) + (e.shiftKey ? 100 : (e.altKey ? 1 : 10));
      self.prototype.input_y.onchange(e);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Go to active node",
    buttonID: [ 'trace_button_goactive' ],
    keyShortcuts: {
      "A": [ 65 ]
    },
    run: function (e) {
      var atn = SkeletonAnnotations.getActiveNode();
      if (atn != null) {
	project.moveTo(
	  tracingLayer.svgOverlay.pix2physZ(atn.z),
	  tracingLayer.svgOverlay.pix2physY(atn.y),
	  tracingLayer.svgOverlay.pix2physX(atn.x));
      } else {
	alert("No active node to go to!");
      }
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Deselect the active node",
    keyShortcuts:  {
      "M": [ 77 ]
    },
    run: function (e) {
      activateNode(null);
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Go to the parent of the active node (?)",
    keyShortcuts: {
      "P": [ 80 ]
    },
    run: function (e) {
      project.tracingCommand('goparent');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Go to last edited node in this skeleton",
    keyShortcuts: {
      "E": [ 69 ]
    },
    run: function (e) {
      project.tracingCommand('golastedited');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Split this skeleton at the active node",
    buttonID: [ 'trace_button_skelsplitting' ],
    keyShortcuts: {
      "5": [ 53 ]
    },
    run: function (e) {
      project.tracingCommand('skeletonsplitting');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Re-root this skeleton at the active node",
    buttonID: [ 'trace_button_skelrerooting' ],
    keyShortcuts: {
      "6": [ 54 ]
    },
    run: function (e) {
      project.tracingCommand('skeletonreroot');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Toggle the display of labels",
    buttonID: [ 'trace_button_togglelabels' ],
    keyShortcuts: {
      "7": [ 55 ]
    },
    run: function (e) {
      project.tracingCommand('togglelabels');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Export to SWC",
    buttonID: [ 'trace_button_exportswc' ],
    keyShortcuts: {
      "S": [ 83 ]
    },
    run: function (e) {
      project.tracingCommand('exportswc');
      return false;
    }
  }) );

  this.addAction( new Action({
    helpText: "Tag the active node",
    keyShortcuts: {
      "T": [ 84 ]
    },
    run: function (e) {
      if (!(e.ctrlKey || e.metaKey)) {
	project.tracingCommand('tagging');
      }
      return true;
    }
  }) );

  this.addAction( new Action({
    helpText: "Select the nearest node to the mouse cursor",
    keyShortcuts: {
      "G": [ 71 ]
    },
    run: function (e) {
      if (!(e.ctrlKey || e.metaKey)) {
	project.activateNearestNode();
      }
      return true;
    }
  }) );

  var keyCodeToAction = getKeyCodeToActionMap(actions);

  setButtonClicksFromActions(actions);

  /** This function should return true if there was any action
      linked to the key code, or false otherwise. */

  this.handleKeyPress = function( e ) {
    var keyAction = keyCodeToAction[e.keyCode];
    if (keyAction) {
      keyAction.run(e || event);
      return true;
    } else {
      return false;
    }
  }

  this.getMouseHelp = function( e ) {
    var result = '
';
    result += 'click on a node: make that node active
'
    result += 'ctrl-click in space: deselect the active node
';
    result += 'ctrl-shift-click on a node: delete that node
';
    result += 'shift-click in space: create a synapse (if there was an active treenode)
';
    result += 'shift-click in space: create a post-synaptic node (if there was an active synapse)
';
    result += 'shift-click on a treenode: join two skeletons (if there was an active treenode)
';
    result += '
';
    return result;
  }

}
<|endoftext|>


<commit_before>var Fluxxor = require('fluxxor');
var Immutable = require('immutable');
var Cursor = require('immutable/contrib/cursor');

var BATCH_SIZE = 300;
var EMIT_INTERVAL = 300;

var constants = {
  ADD_LOG: 'ADD_LOG',
  ADD_RESOURCE: 'ADD_RESOURCE',
  ADD_ERROR: 'ADD_ERROR',
  SET_RESOURCE_RUNNING: 'SET_RESOURCE_RUNNING',
  SET_RESOURCE_ERRORED: 'SET_RESOURCE_ERRORED',
  TOGGLE_RESOURCE_LOGS: 'TOGGLE_RESOURCE_LOGS',
}

function LogsModel() {
  this.carriageReturned = false;
  this.lines = Immutable.fromJS([[[]]]);
  this.batchCursor = Cursor.from(this.lines, function(newLines) {
    this.lines = newLines;
  }.bind(this));
  this.linesCursor = this.batchCursor.last();
  this.carriage = 0;

  this.addLog = function(line) {
    var sequence = ansiparse(line);

    for (var i = 0; i < sequence.length; i++) {
      if (sequence[i].cr) {
        this.carriage = 0;
      } else if (sequence[i].linebreak) {
        this.pushLine(Immutable.List())
        this.refreshCursor();
        this.carriage = 0;
        this.changed = true;
      } else if (sequence[i].text) {
        var textLen = sequence[i].text.length;
        var carriage = this.carriage;
        var cursor = this.cursor.update(function(line) {
          return line.slice(carriage);
        });
        this.cursor = this.cursor.update(function(line) {
          return line.slice(0, carriage);
        });
        this.pushSequence(sequence[i]);
        this.carriage++;

        cursor.forEach(function(e, i) {
          if(e.text.length >= textLen) {
            e.text = e.text.substr(textLen);
            textLen -= e.text.length;
            this.pushSequence(e);
            return false;
          }
        }, this);

        this.refreshLineCursor();
        this.changed = true;
      }
    };
  };

  this.addError = function(message) {
    this.pushLine(Immutable.List())
    this.refreshCursor();
    this.pushSequence({
      text: message,
      error: true,
    });
    this.refreshLineCursor();
    this.carriageReturned = false;
    this.changed = true;
  };

  this.refreshLineCursor = function() {
    this.linesCursor = this.linesCursor.set(this.linesCursor.count() - 1, this.cursor);
  };

  this.refreshCursor = function() {
    this.cursor = this.linesCursor.last();
  };

  this.pushLine = function(line) {
    if (this.linesCursor.count() >= BATCH_SIZE) {
      this.batchCursor = this.batchCursor.set(this.batchCursor.count() - 1, this.linesCursor);
      this.batchCursor = this.batchCursor.update(function(batches) {
        return batches.push(Immutable.List.of(line));
      });
      this.linesCursor = this.batchCursor.last();
    } else {
      this.linesCursor = this.linesCursor.update(function(lines) {
        return lines.push(line);
      });
    }
  };

  this.pushSequence = function(sequence) {
    this.cursor = this.cursor.update(function(line) {
      return line.push(sequence);
    });
  };

  this.refreshCursor();
  this.changed = false;
}

var LogStore = Fluxxor.createStore({
  initialize: function() {
    this.logs = {};
    this.bindActions(
      constants.ADD_LOG, this.onAddLog,
      constants.ADD_ERROR, this.onAddError
    );
    setInterval(this.emitEvents.bind(this), EMIT_INTERVAL);
  },

  getLogs: function(type) {
    if (this.logs[type] === undefined) {
      this.logs[type] = new LogsModel();
    }
    return this.logs[type];
  },

  onAddLog: function(data) {
    this.getLogs(data.type).addLog(data.line);
  },

  onAddError: function(data) {
    this.getLogs(data.type).addError(data.line);
  },

  emitEvents: function() {
    var shouldEmit = false;

    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        if (this.logs[k].changed) {
          shouldEmit = true;
          break;
        }
      }
    }

    if (shouldEmit) {
      this.emit("change");

      for (var k in this.logs) {
        if (this.logs.hasOwnProperty(k)) {
          this.logs[k].changed = false
        }
      }
    }
  },

  getState: function() {
    var state = {};
    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        state[k] = this.logs[k].lines;
      }
    }
    return Immutable.fromJS(state);
  },
});

var ResourceStore = Fluxxor.createStore({
  initialize: function() {
    this.resources = {};
    this.bindActions(
      constants.ADD_RESOURCE, this.onAddResource,
      constants.SET_RESOURCE_RUNNING, this.onSetResourceRunning,
      constants.SET_RESOURCE_ERRORED, this.onSetResourceErrored,
      constants.TOGGLE_RESOURCE_LOGS, this.onToggleResourceLogs
    );
  },

  addResource: function(type, resource) {
    if (this.resources[type] === undefined) {
      this.resources[type] = Immutable.Map();
    }
    resource.kind = type;
    var newResource = Immutable.fromJS(resource);
    if (this.resources[type].has(resource.name)) {
      newResource = this.resources[type].get(resource.name).merge(newResource);
    }
    this.setResource(type, resource.name, newResource);
    this.emit("change");
    return this.resources[type].get(resource.name);
  },

  updateResource: function(type, name, attributes) {
    attributes.name = name;
    this.addResource(type, attributes);
  },

  setResource: function(type, name, resource) {
    this.resources[type] = this.resources[type].set(name, resource);
  },

  onAddResource: function(data) {
    this.addResource(data.type, data.resource);
  },

  onSetResourceRunning: function(data) {
    this.updateResource(data.type, data.name, { running: data.value });
  },

  onSetResourceErrored: function(data) {
    this.updateResource(data.type, data.name, { errored: data.value });
  },

  onToggleResourceLogs: function(data) {
    var resource = this.resources[data.type].get(data.name);
    this.updateResource(data.type, data.name, { showLogs: !resource.get('showLogs') });
  },

  getState: function() {
    return Immutable.fromJS(this.resources);
  },
});

var actions = {
  addLog: function(type, line) {
    this.dispatch(constants.ADD_LOG, { type: type, line: line });
  },

  addError: function(type, line) {
    this.dispatch(constants.ADD_ERROR, { type: type, line: line });
  },

  addResource: function(type, resource) {
    this.dispatch(constants.ADD_RESOURCE, { type: type, resource: resource });
  },

  setResourceRunning: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_RUNNING, { type: type, name: name, value: value });
  },

  setResourceErrored: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_ERRORED, { type: type, name: name, value: value });
  },

  toggleResourceLogs: function(type, name) {
    this.dispatch(constants.TOGGLE_RESOURCE_LOGS, { type: type, name: name });
  },
}

var stores = {
  LogStore: new LogStore(),
  ResourceStore: new ResourceStore(),
};

module.exports = new Fluxxor.Flux(stores, actions);
<commit_msg>Add linebreak when parsing output<commit_after>var Fluxxor = require('fluxxor');
var Immutable = require('immutable');
var Cursor = require('immutable/contrib/cursor');

var BATCH_SIZE = 300;
var EMIT_INTERVAL = 300;

var constants = {
  ADD_LOG: 'ADD_LOG',
  ADD_RESOURCE: 'ADD_RESOURCE',
  ADD_ERROR: 'ADD_ERROR',
  SET_RESOURCE_RUNNING: 'SET_RESOURCE_RUNNING',
  SET_RESOURCE_ERRORED: 'SET_RESOURCE_ERRORED',
  TOGGLE_RESOURCE_LOGS: 'TOGGLE_RESOURCE_LOGS',
}

function LogsModel() {
  this.carriageReturned = false;
  this.lines = Immutable.fromJS([[[]]]);
  this.batchCursor = Cursor.from(this.lines, function(newLines) {
    this.lines = newLines;
  }.bind(this));
  this.linesCursor = this.batchCursor.last();
  this.carriage = 0;

  this.addLog = function(line) {
    var sequence = ansiparse(line);

    for (var i = 0; i < sequence.length; i++) {
      if (sequence[i].cr) {
        this.carriage = 0;
      } else if (sequence[i].linebreak) {
        this.pushLine(Immutable.List.of(sequence[i]))
        this.refreshCursor();
        this.carriage = 0;
        this.changed = true;
      } else if (sequence[i].text) {
        var textLen = sequence[i].text.length;
        var carriage = this.carriage;
        var cursor = this.cursor.update(function(line) {
          return line.slice(carriage);
        });
        this.cursor = this.cursor.update(function(line) {
          return line.slice(0, carriage);
        });
        this.pushSequence(sequence[i]);
        this.carriage++;

        cursor.forEach(function(e, i) {
          if(e.text.length >= textLen) {
            e.text = e.text.substr(textLen);
            textLen -= e.text.length;
            this.pushSequence(e);
            return false;
          }
        }, this);

        this.refreshLineCursor();
        this.changed = true;
      }
    };
  };

  this.addError = function(message) {
    this.pushLine(Immutable.List())
    this.refreshCursor();
    this.pushSequence({
      text: message,
      error: true,
    });
    this.refreshLineCursor();
    this.carriageReturned = false;
    this.changed = true;
  };

  this.refreshLineCursor = function() {
    this.linesCursor = this.linesCursor.set(this.linesCursor.count() - 1, this.cursor);
  };

  this.refreshCursor = function() {
    this.cursor = this.linesCursor.last();
  };

  this.pushLine = function(line) {
    if (this.linesCursor.count() >= BATCH_SIZE) {
      this.batchCursor = this.batchCursor.set(this.batchCursor.count() - 1, this.linesCursor);
      this.batchCursor = this.batchCursor.update(function(batches) {
        return batches.push(Immutable.List.of(line));
      });
      this.linesCursor = this.batchCursor.last();
    } else {
      this.linesCursor = this.linesCursor.update(function(lines) {
        return lines.push(line);
      });
    }
  };

  this.pushSequence = function(sequence) {
    this.cursor = this.cursor.update(function(line) {
      return line.push(sequence);
    });
  };

  this.refreshCursor();
  this.changed = false;
}

var LogStore = Fluxxor.createStore({
  initialize: function() {
    this.logs = {};
    this.bindActions(
      constants.ADD_LOG, this.onAddLog,
      constants.ADD_ERROR, this.onAddError
    );
    setInterval(this.emitEvents.bind(this), EMIT_INTERVAL);
  },

  getLogs: function(type) {
    if (this.logs[type] === undefined) {
      this.logs[type] = new LogsModel();
    }
    return this.logs[type];
  },

  onAddLog: function(data) {
    this.getLogs(data.type).addLog(data.line);
  },

  onAddError: function(data) {
    this.getLogs(data.type).addError(data.line);
  },

  emitEvents: function() {
    var shouldEmit = false;

    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        if (this.logs[k].changed) {
          shouldEmit = true;
          break;
        }
      }
    }

    if (shouldEmit) {
      this.emit("change");

      for (var k in this.logs) {
        if (this.logs.hasOwnProperty(k)) {
          this.logs[k].changed = false
        }
      }
    }
  },

  getState: function() {
    var state = {};
    for (var k in this.logs) {
      if (this.logs.hasOwnProperty(k)) {
        state[k] = this.logs[k].lines;
      }
    }
    return Immutable.fromJS(state);
  },
});

var ResourceStore = Fluxxor.createStore({
  initialize: function() {
    this.resources = {};
    this.bindActions(
      constants.ADD_RESOURCE, this.onAddResource,
      constants.SET_RESOURCE_RUNNING, this.onSetResourceRunning,
      constants.SET_RESOURCE_ERRORED, this.onSetResourceErrored,
      constants.TOGGLE_RESOURCE_LOGS, this.onToggleResourceLogs
    );
  },

  addResource: function(type, resource) {
    if (this.resources[type] === undefined) {
      this.resources[type] = Immutable.Map();
    }
    resource.kind = type;
    var newResource = Immutable.fromJS(resource);
    if (this.resources[type].has(resource.name)) {
      newResource = this.resources[type].get(resource.name).merge(newResource);
    }
    this.setResource(type, resource.name, newResource);
    this.emit("change");
    return this.resources[type].get(resource.name);
  },

  updateResource: function(type, name, attributes) {
    attributes.name = name;
    this.addResource(type, attributes);
  },

  setResource: function(type, name, resource) {
    this.resources[type] = this.resources[type].set(name, resource);
  },

  onAddResource: function(data) {
    this.addResource(data.type, data.resource);
  },

  onSetResourceRunning: function(data) {
    this.updateResource(data.type, data.name, { running: data.value });
  },

  onSetResourceErrored: function(data) {
    this.updateResource(data.type, data.name, { errored: data.value });
  },

  onToggleResourceLogs: function(data) {
    var resource = this.resources[data.type].get(data.name);
    this.updateResource(data.type, data.name, { showLogs: !resource.get('showLogs') });
  },

  getState: function() {
    return Immutable.fromJS(this.resources);
  },
});

var actions = {
  addLog: function(type, line) {
    this.dispatch(constants.ADD_LOG, { type: type, line: line });
  },

  addError: function(type, line) {
    this.dispatch(constants.ADD_ERROR, { type: type, line: line });
  },

  addResource: function(type, resource) {
    this.dispatch(constants.ADD_RESOURCE, { type: type, resource: resource });
  },

  setResourceRunning: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_RUNNING, { type: type, name: name, value: value });
  },

  setResourceErrored: function(type, name, value) {
    this.dispatch(constants.SET_RESOURCE_ERRORED, { type: type, name: name, value: value });
  },

  toggleResourceLogs: function(type, name) {
    this.dispatch(constants.TOGGLE_RESOURCE_LOGS, { type: type, name: name });
  },
}

var stores = {
  LogStore: new LogStore(),
  ResourceStore: new ResourceStore(),
};

module.exports = new Fluxxor.Flux(stores, actions);
<|endoftext|>


<commit_before>// This file is concerned with altering the Firefox 4+ Add-ons Manager window,
// for those sorts of functionality we want that the API does not handle.  (As
// opposed to addons4.jsm which is responsible for what the API does handle.)
(function() {
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://greasemonkey/addons4.js");

var sortersContainer;
var sortExecuteOrderButton;
var stringBundle;
var userScriptViewId = 'addons://list/user-script';

window.addEventListener('load', init, false);
window.addEventListener('unload', unload, false);

// Patch the default createItem() to add our custom property.
_createItemOrig = createItem;
createItem = function GM_createItem(aObj, aIsInstall, aIsRemote) {
  var item = _createItemOrig(aObj, aIsInstall, aIsRemote);
  if ('user-script' == aObj.type) {
   // Save a reference to this richlistitem on the Addon object, so we can
   // fix the 'executionIndex' attribute if/when it changes.
   aObj.richlistitem = item;
   setRichlistitemExecutionIndex(aObj);
  }
  return item;
};

// Patch the default loadView() to suppress the detail view for user scripts.
_loadViewOrig = gViewController.loadView.bind(gViewController);
gViewController.loadView = function(aViewId) {
  if (userScriptViewId == gViewController.currentViewId
      && 0 === aViewId.indexOf('addons://detail/')
  ) {
    return false;
  }
  _loadViewOrig(aViewId);
}

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var observer = {
  notifyEvent: function(script, event, data) {
    if (userScriptViewId != gViewController.currentViewId) return;

    var addon = ScriptAddonFactoryByScript(script);
    switch (event) {
      case 'install':
        gListView.addItem(addon);
        break;
      case "edit-enabled":
        addon.userDisabled = !data;
        var item = gListView.getListItemForID(addon.id);
        item.setAttribute('active', data);
        break;
      case 'modified':
        ScriptAddonReplaceScript(script);

        var oldAddon = ScriptAddonFactoryByScript({'id': data});
        var item = createItem(addon);
        var oldItem = gListView.getListItemForID(oldAddon.id);
        oldItem.parentNode.replaceChild(item, oldItem);
        break;
    }
  }
};

// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ //

function addonIsInstalledScript(aAddon) {
  if (!aAddon) return false;
  if ('user-script' != aAddon.type) return false;
  if (aAddon._script.needsUninstall) return false;
  return true;
};

function sortedByExecOrder() {
  return document.getElementById('greasemonkey-sort-bar')
    .getElementsByAttribute('sortBy', 'executionIndex')[0]
    .hasAttribute('checkState');
};

function init() {
  GM_getConfig().addObserver(observer);

  gViewController.commands.cmd_userscript_edit = {
      isEnabled: addonIsInstalledScript,
      doCommand: function(aAddon) { GM_openInEditor(aAddon._script); }
    };
  gViewController.commands.cmd_userscript_show = {
      isEnabled: addonIsInstalledScript,
      doCommand: function(aAddon) { GM_openFolder(aAddon._script.file); }
    };

  gViewController.commands.cmd_userscript_execute_first = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, -9999); }
    };
  gViewController.commands.cmd_userscript_execute_sooner = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, -1); }
    };
  gViewController.commands.cmd_userscript_execute_later = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, 1); }
    };
  gViewController.commands.cmd_userscript_execute_last = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, 9999); }
    };

  document.getElementById('addonitem-popup').addEventListener(
      'popupshowing', onContextPopupShowing, false);

  window.addEventListener('ViewChanged', onViewChanged, false);
  onViewChanged(); // initialize on load as well as when it changes later

  document.getElementById('greasemonkey-sort-bar').addEventListener(
      'command', onSortersClicked, false);
  applySort();
};

function onContextPopupShowing(aEvent) {
  var popup = aEvent.target;
  var selectedItem = gListView._listBox.selectedItem ||
    gSearchView._listBox.selectedItem;
  var selectedIsUserScript = (selectedItem &&
      'user-script' == selectedItem.getAttribute('type')
      );

  for (var i = 0, menuitem = null; menuitem = popup.children[i]; i++) {
    var menuitemIsUserScript = ('user-script' == menuitem.getAttribute('type'));
    menuitem.collapsed = selectedIsUserScript != menuitemIsUserScript;
  }
};

function onSortersClicked(aEvent) {
  if ('button' != aEvent.target.tagName) return;
  var button = aEvent.target;

  var checkState = button.getAttribute('checkState');

  // Remove checkState from all buttons.
  var buttons = document.getElementById('greasemonkey-sort-bar')
      .getElementsByTagName('button');
  for (var i = 0, el = null; el = buttons[i]; i++) {
    el.removeAttribute('checkState');
  }

  // Toggle state of this button.
  if ('2' == checkState) {
    button.setAttribute('checkState', '1');
  } else {
    button.setAttribute('checkState', '2');
  }

  applySort();
};

function applySort() {
  // Find checked button.
  var buttons = document.getElementById('greasemonkey-sort-bar')
    .getElementsByTagName('button');
  for (var i = 0, button = null; button = buttons[i]; i++) {
    if (button.hasAttribute('checkState')) break;
  }

  var ascending = '1' != button.getAttribute('checkState');
  var sortBy=button.getAttribute('sortBy').split(',');

  var list = document.getElementById('addon-list');
  var elements = Array.slice(list.childNodes, 0);
  sortElements(elements, sortBy, ascending);
  while (list.listChild) list.removeChild(list.lastChild);
  elements.forEach(function(el) { list.appendChild(el); });
};

function onViewChanged(aEvent) {
  var emptyWarning = document.getElementById('user-script-list-empty');
  if (userScriptViewId == gViewController.currentViewId) {
    document.documentElement.className += ' greasemonkey';
    emptyWarning.collapsed = !!GM_getConfig().scripts.length;
  } else {
    document.documentElement.className = document.documentElement.className
        .replace(/ greasemonkey/g, '');
  }
};

function selectScriptExecOrder() {
  if (sortedByExecOrder()) return;

  var button = document.getElementById('greasemonkey-sort-bar')
    .getElementsByAttribute('sortBy', 'executionIndex')[0];
  // Sort the script list by execution order
  onSortersClicked({'target': button});
};

function reorderScriptExecution(aAddon, moveBy) {
  selectScriptExecOrder();
  GM_getConfig().move(aAddon._script, moveBy);
  AddonManager.getAddonsByTypes(['user-script'], function(aAddons) {
      // Fix all the 'executionOrder' attributes.
      for (var i = 0, addon = null; addon = aAddons[i]; i++) {
        setRichlistitemExecutionIndex(addon);
      }
      // Re-sort the list, with these fixed attributes.
      applySort();
      // Ensure the selected element is still visible.
      var richlistbox = document.getElementById('addon-list');
      richlistbox.ensureElementIsVisible(richlistbox.currentItem);
    });
};

function setRichlistitemExecutionIndex(aAddon) {
  aAddon.richlistitem.setAttribute('executionIndex',
      // String format with leading zeros, so it will sort properly.
      ('0000' + aAddon.executionIndex).substr(-5));
};

function unload() {
  var GM_config = GM_getConfig();
  // Since .getAddonsByTypes() is asynchronous, AddonManager gets destroyed
  // by the time the callback runs.  Cache this value we need from it.
  var pending_uninstall = AddonManager.PENDING_UNINSTALL;

  AddonManager.getAddonsByTypes(['user-script'], function(aAddons) {
      for (var i = 0, addon = null; addon = aAddons[i]; i++) {
        if (addon.pendingOperations & pending_uninstall) {
          // Todo: This without dipping into private members.
          GM_config.uninstall(addon._script);
        }
      }
      // Guarantee that the config.xml is saved to disk.
      // Todo: This without dipping into private members.
      GM_config._save(true);
    });

  GM_config.removeObserver(observer);
};
})();

function GM_openUserscriptsOrg(){
  var chromeWin = GM_getBrowserWindow();
  chromeWin.gBrowser.selectedTab = chromeWin.gBrowser.addTab(
      'http://userscripts.org');
}
<commit_msg>Code style.<commit_after>// This file is concerned with altering the Firefox 4+ Add-ons Manager window,
// for those sorts of functionality we want that the API does not handle.  (As
// opposed to addons4.jsm which is responsible for what the API does handle.)
(function() {
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://greasemonkey/addons4.js");

var sortersContainer;
var sortExecuteOrderButton;
var stringBundle;
var userScriptViewId = 'addons://list/user-script';

window.addEventListener('load', init, false);
window.addEventListener('unload', unload, false);

// Patch the default createItem() to add our custom property.
_createItemOrig = createItem;
createItem = function GM_createItem(aObj, aIsInstall, aIsRemote) {
  var item = _createItemOrig(aObj, aIsInstall, aIsRemote);
  if ('user-script' == aObj.type) {
   // Save a reference to this richlistitem on the Addon object, so we can
   // fix the 'executionIndex' attribute if/when it changes.
   aObj.richlistitem = item;
   setRichlistitemExecutionIndex(aObj);
  }
  return item;
};

// Patch the default loadView() to suppress the detail view for user scripts.
_loadViewOrig = gViewController.loadView.bind(gViewController);
gViewController.loadView = function(aViewId) {
  if (userScriptViewId == gViewController.currentViewId
      && 0 === aViewId.indexOf('addons://detail/')
  ) {
    return false;
  }
  _loadViewOrig(aViewId);
}

// Set up an "observer" on the config, to keep the displayed items up to date
// with their actual state.
var observer = {
  notifyEvent: function(script, event, data) {
    if (userScriptViewId != gViewController.currentViewId) return;

    var addon = ScriptAddonFactoryByScript(script);
    switch (event) {
      case 'install':
        gListView.addItem(addon);
        break;
      case "edit-enabled":
        addon.userDisabled = !data;
        var item = gListView.getListItemForID(addon.id);
        item.setAttribute('active', data);
        break;
      case 'modified':
        ScriptAddonReplaceScript(script);

        var oldAddon = ScriptAddonFactoryByScript({'id': data});
        var item = createItem(addon);
        var oldItem = gListView.getListItemForID(oldAddon.id);
        oldItem.parentNode.replaceChild(item, oldItem);
        break;
    }
  }
};

// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ //

function addonIsInstalledScript(aAddon) {
  if (!aAddon) return false;
  if ('user-script' != aAddon.type) return false;
  if (aAddon._script.needsUninstall) return false;
  return true;
};

function sortedByExecOrder() {
  return document.getElementById('greasemonkey-sort-bar')
    .getElementsByAttribute('sortBy', 'executionIndex')[0]
    .hasAttribute('checkState');
};

function init() {
  GM_getConfig().addObserver(observer);

  gViewController.commands.cmd_userscript_edit = {
      isEnabled: addonIsInstalledScript,
      doCommand: function(aAddon) { GM_openInEditor(aAddon._script); }
    };
  gViewController.commands.cmd_userscript_show = {
      isEnabled: addonIsInstalledScript,
      doCommand: function(aAddon) { GM_openFolder(aAddon._script.file); }
    };

  gViewController.commands.cmd_userscript_execute_first = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, -9999); }
    };
  gViewController.commands.cmd_userscript_execute_sooner = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, -1); }
    };
  gViewController.commands.cmd_userscript_execute_later = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, 1); }
    };
  gViewController.commands.cmd_userscript_execute_last = {
      isEnabled: function() { return true; },
      doCommand: function(aAddon) { reorderScriptExecution(aAddon, 9999); }
    };

  document.getElementById('addonitem-popup').addEventListener(
      'popupshowing', onContextPopupShowing, false);

  window.addEventListener('ViewChanged', onViewChanged, false);
  onViewChanged(); // initialize on load as well as when it changes later

  document.getElementById('greasemonkey-sort-bar').addEventListener(
      'command', onSortersClicked, false);
  applySort();
};

function onContextPopupShowing(aEvent) {
  var popup = aEvent.target;
  var selectedItem = gListView._listBox.selectedItem ||
      gSearchView._listBox.selectedItem;
  var selectedIsUserScript = selectedItem &&
      'user-script' == selectedItem.getAttribute('type');

  for (var i = 0, menuitem = null; menuitem = popup.children[i]; i++) {
    var menuitemIsUserScript = ('user-script' == menuitem.getAttribute('type'));
    menuitem.collapsed = selectedIsUserScript != menuitemIsUserScript;
  }
};

function onSortersClicked(aEvent) {
  if ('button' != aEvent.target.tagName) return;
  var button = aEvent.target;

  var checkState = button.getAttribute('checkState');

  // Remove checkState from all buttons.
  var buttons = document.getElementById('greasemonkey-sort-bar')
      .getElementsByTagName('button');
  for (var i = 0, el = null; el = buttons[i]; i++) {
    el.removeAttribute('checkState');
  }

  // Toggle state of this button.
  if ('2' == checkState) {
    button.setAttribute('checkState', '1');
  } else {
    button.setAttribute('checkState', '2');
  }

  applySort();
};

function applySort() {
  // Find checked button.
  var buttons = document.getElementById('greasemonkey-sort-bar')
    .getElementsByTagName('button');
  for (var i = 0, button = null; button = buttons[i]; i++) {
    if (button.hasAttribute('checkState')) break;
  }

  var ascending = '1' != button.getAttribute('checkState');
  var sortBy=button.getAttribute('sortBy').split(',');

  var list = document.getElementById('addon-list');
  var elements = Array.slice(list.childNodes, 0);
  sortElements(elements, sortBy, ascending);
  while (list.listChild) list.removeChild(list.lastChild);
  elements.forEach(function(el) { list.appendChild(el); });
};

function onViewChanged(aEvent) {
  var emptyWarning = document.getElementById('user-script-list-empty');
  if (userScriptViewId == gViewController.currentViewId) {
    document.documentElement.className += ' greasemonkey';
    emptyWarning.collapsed = !!GM_getConfig().scripts.length;
  } else {
    document.documentElement.className = document.documentElement.className
        .replace(/ greasemonkey/g, '');
  }
};

function selectScriptExecOrder() {
  if (sortedByExecOrder()) return;

  var button = document.getElementById('greasemonkey-sort-bar')
    .getElementsByAttribute('sortBy', 'executionIndex')[0];
  // Sort the script list by execution order
  onSortersClicked({'target': button});
};

function reorderScriptExecution(aAddon, moveBy) {
  selectScriptExecOrder();
  GM_getConfig().move(aAddon._script, moveBy);
  AddonManager.getAddonsByTypes(['user-script'], function(aAddons) {
      // Fix all the 'executionOrder' attributes.
      for (var i = 0, addon = null; addon = aAddons[i]; i++) {
        setRichlistitemExecutionIndex(addon);
      }
      // Re-sort the list, with these fixed attributes.
      applySort();
      // Ensure the selected element is still visible.
      var richlistbox = document.getElementById('addon-list');
      richlistbox.ensureElementIsVisible(richlistbox.currentItem);
    });
};

function setRichlistitemExecutionIndex(aAddon) {
  aAddon.richlistitem.setAttribute('executionIndex',
      // String format with leading zeros, so it will sort properly.
      ('0000' + aAddon.executionIndex).substr(-5));
};

function unload() {
  var GM_config = GM_getConfig();
  // Since .getAddonsByTypes() is asynchronous, AddonManager gets destroyed
  // by the time the callback runs.  Cache this value we need from it.
  var pending_uninstall = AddonManager.PENDING_UNINSTALL;

  AddonManager.getAddonsByTypes(['user-script'], function(aAddons) {
      for (var i = 0, addon = null; addon = aAddons[i]; i++) {
        if (addon.pendingOperations & pending_uninstall) {
          // Todo: This without dipping into private members.
          GM_config.uninstall(addon._script);
        }
      }
      // Guarantee that the config.xml is saved to disk.
      // Todo: This without dipping into private members.
      GM_config._save(true);
    });

  GM_config.removeObserver(observer);
};
})();

function GM_openUserscriptsOrg(){
  var chromeWin = GM_getBrowserWindow();
  chromeWin.gBrowser.selectedTab = chromeWin.gBrowser.addTab(
      'http://userscripts.org');
}
<|endoftext|>


<commit_before>// eslint-disable-next-line import/no-extraneous-dependencies
import Chance from "chance";

const chance = new Chance(88888);

const name = "Fiona Hamilton";
const jobTitle = "Legal Editor";
const image =
  "https://feeds.thetimes.co.uk/web/imageserver/imageserver/image/methode%2Ftimes%2Fprod%2Fweb%2Fbin%2F0694e84e-04ff-11e7-976a-0b4b9a1a67a3.jpg";
const twitter = "jdoe";

const article = () => ({
  id: chance.guid(),
  title: chance.sentence(),
  label: "Science",
  publicationName: "TIMES",
  publishedTime: new Date("2015-03-19T23:06:34.000Z"),
  leadAsset: {
    title: "British trio stopped on the way to join Isis",
    crop: {
      url:
        "http://nu-cps-imgsrv-tnl-dev-webapp.elb.tnl-dev.ntch.co.uk/imageserver/image/90cfa89f4ebe003ab967e64b9c79c9afa520c273.jpg?crop=620%2C413%2C0%2C0"
    }
  },
  teaser: [
    {
      name: "p",
      children: [
        {
          name: "text",
          children: [
            {
              text:
                "A tip-off from desperate parents led Turkish police to swoop on three British teenagers as they allegedly travelled to join Islamic State, "
            }
          ]
        },
        {
          name: "em",
          children: [
            {
              name: "text",
              children: [
                {
                  text: "The Times"
                }
              ]
            }
          ],
          attributes: {}
        },
        {
          name: "text",
          children: [
            {
              text: " has learnt."
            }
          ]
        }
      ],
      attributes: {}
    },
    {
      name: "p",
      children: [
        {
          name: "text",
          children: [
            {
              text:
                "Two 17-year-old Muslim schoolboys from the Pakistani community in Brent, northwest London, and a 19-year-old man were intercepted in Istanbul at the weekend and swiftly returned to England. They were questioned by counterterrorism officials last night."
            }
          ]
        }
      ],
      attributes: {}
    }
  ]
});

const biography = [
  {
    name: "text",
    children: [
      {
        text: "Lorem "
      }
    ]
  },
  {
    name: "b",
    attributes: {},
    children: [
      {
        name: "text",
        children: [
          {
            text: "ipsum"
          }
        ]
      }
    ]
  },
  {
    name: "text",
    children: [
      {
        text: " testbr "
      }
    ]
  },
  {
    name: "br",
    attributes: {}
  },
  {
    name: "text",
    children: [
      {
        text: "More text "
      }
    ]
  },
  {
    name: "i",
    attributes: {},
    children: [
      {
        name: "text",
        children: [
          {
            text: " last "
          }
        ]
      }
    ]
  }
];

const listOfArticles = n => {
  const list = [];
  for (let i = 0; i < n; i += 1) {
    list.push(article());
  }
  return list;
};

const articles = n => ({
  count: n,
  list: listOfArticles(n)
});

export default n => ({
  name,
  jobTitle,
  biography,
  image,
  twitter,
  articles: articles(n)
});
<commit_msg>fix: update fructose fixtures<commit_after>// eslint-disable-next-line import/no-extraneous-dependencies
import Chance from "chance";

const chance = new Chance(88888);

const name = "Fiona Hamilton";
const jobTitle = "Legal Editor";
const image =
  "https://feeds.thetimes.co.uk/web/imageserver/imageserver/image/methode%2Ftimes%2Fprod%2Fweb%2Fbin%2F0694e84e-04ff-11e7-976a-0b4b9a1a67a3.jpg";
const twitter = "jdoe";

const article = () => ({
  id: chance.guid(),
  title: chance.sentence(),
  label: "Science",
  publicationName: "TIMES",
  publishedTime: new Date("2015-03-19T23:06:34.000Z"),
  leadAsset: {
    title: "British trio stopped on the way to join Isis",
    crop: {
      url:
        "http://nu-cps-imgsrv-tnl-dev-webapp.elb.tnl-dev.ntch.co.uk/imageserver/image/90cfa89f4ebe003ab967e64b9c79c9afa520c273.jpg?crop=620%2C413%2C0%2C0"
    }
  },
  teaser: [
    {
      name: "p",
      children: [
        {
          name: "text",
          attributes: {
            value:
              "A tip-off from desperate parents led Turkish police to swoop on three British teenagers as they allegedly travelled to join Islamic State, "
          },
          children: []
        },
        {
          name: "em",
          children: [
            {
              name: "text",
              attributes: {
                value: "The Times"
              },
              children: []
            }
          ],
          attributes: {}
        },
        {
          name: "text",
          attributes: {
            value: " has learnt."
          },
          children: []
        }
      ],
      attributes: {}
    },
    {
      name: "p",
      children: [
        {
          name: "text",
          attributes: {
            value:
              "Two 17-year-old Muslim schoolboys from the Pakistani community in Brent, northwest London, and a 19-year-old man were intercepted in Istanbul at the weekend and swiftly returned to England. They were questioned by counterterrorism officials last night."
          },
          children: []
        }
      ],
      attributes: {}
    }
  ]
});

const biography = [
  {
    name: "text",
    attributes: {
      value: "Lorem "
    },
    children: []
  },
  {
    name: "b",
    attributes: {},
    children: [
      {
        name: "text",
        attributes: {
          value: "ipsum"
        },
        children: []
      }
    ]
  },
  {
    name: "text",
    attributes: {
      value: " testbr "
    },
    children: []
  },
  {
    name: "br",
    attributes: {},
    children: []
  },
  {
    name: "text",
    attributes: {
      value: "More text "
    },
    children: []
  },
  {
    name: "i",
    attributes: {},
    children: [
      {
        name: "text",
        attributes: {
          value: " last "
        },
        children: []
      }
    ]
  }
];

const listOfArticles = n => {
  const list = [];
  for (let i = 0; i < n; i += 1) {
    list.push(article());
  }
  return list;
};

const articles = n => ({
  count: n,
  list: listOfArticles(n)
});

export default n => ({
  name,
  jobTitle,
  biography,
  image,
  twitter,
  articles: articles(n)
});
<|endoftext|>


<commit_before>import React from 'react';
import { Form, Input, Collapse } from 'antd';
import Crop from '../components/crop';
import getImageInfo from './info';
import { FormForFullLayout, CollapsePanel } from './utils';

export default ({ form, multi, item }) => {
  form.getFieldDecorator(`${item.id}.id`, { initialValue: item.id });
  form.getFieldDecorator(`${item.id}.url`, { initialValue: item.url });
  form.getFieldDecorator(`${item.id}.width`, { initialValue: item.width });
  form.getFieldDecorator(`${item.id}.height`, { initialValue: item.height });

  return (
    <Form>
      <Form.Item {...FormForFullLayout}>
        {form.getFieldDecorator(`${item.id}.crop`, {
          initialValue: item.crop,
        })(<Crop url={item.url} height={item.height} width={item.width} />)}
      </Form.Item>
      <Collapse defaultActiveKey={['data']}>
        <CollapsePanel header="Bild" key="data">
          {form.getFieldDecorator(`${item.id}.source`, {
            initialValue: item.source,
          })(
            <Form.Item label="Quelle" {...FormForFullLayout}>
              <Input placeholder="Quelle" />
            </Form.Item>,
          )}
          <Form.Item key="caption" label="Bezeichnung" {...FormForFullLayout}>
            {form.getFieldDecorator(`${item.id}.caption`, {
              initialValue: item.caption,
            })(<Input.TextArea rows={3} placeholder="Bezeichnung" />)}
          </Form.Item>
        </CollapsePanel>
        {!multi && getImageInfo(item)}
      </Collapse>
    </Form>
  );
};
<commit_msg>small fix<commit_after>import React from 'react';
import { Form, Input, Collapse } from 'antd';
import Crop from '../components/crop';
import getImageInfo from './info';
import { FormForFullLayout, CollapsePanel } from './utils';

export default ({ form, item }) => {
  form.getFieldDecorator(`${item.id}.id`, { initialValue: item.id });
  form.getFieldDecorator(`${item.id}.url`, { initialValue: item.url });
  form.getFieldDecorator(`${item.id}.width`, { initialValue: item.width });
  form.getFieldDecorator(`${item.id}.height`, { initialValue: item.height });

  return (
    <Form>
      <Form.Item {...FormForFullLayout}>
        {form.getFieldDecorator(`${item.id}.crop`, {
          initialValue: item.crop,
        })(<Crop url={item.url} height={item.height} width={item.width} />)}
      </Form.Item>
      <Collapse defaultActiveKey={['data']}>
        <CollapsePanel header="Bild" key="data">
          {form.getFieldDecorator(`${item.id}.source`, {
            initialValue: item.source,
          })(
            <Form.Item label="Quelle" {...FormForFullLayout}>
              <Input placeholder="Quelle" />
            </Form.Item>,
          )}
          <Form.Item key="caption" label="Bezeichnung" {...FormForFullLayout}>
            {form.getFieldDecorator(`${item.id}.caption`, {
              initialValue: item.caption,
            })(<Input.TextArea rows={3} placeholder="Bezeichnung" />)}
          </Form.Item>
        </CollapsePanel>
        {getImageInfo(item)}
      </Collapse>
    </Form>
  );
};
<|endoftext|>


<commit_before>var DESCRIPTORS = require('../internals/descriptors');
var fails = require('../internals/fails');
var createElement = require('../internals/document-create-element');

// Thank's IE8 for his funny defineProperty
module.exports = !DESCRIPTORS && !fails(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(createElement('div'), 'a', {
    get: function () { return 7; }
  }).a != 7;
});
<commit_msg>fix a typo and rephrase<commit_after>var DESCRIPTORS = require('../internals/descriptors');
var fails = require('../internals/fails');
var createElement = require('../internals/document-create-element');

// Thanks to IE8 for its funny defineProperty
module.exports = !DESCRIPTORS && !fails(function () {
  // eslint-disable-next-line es/no-object-defineproperty -- required for testing
  return Object.defineProperty(createElement('div'), 'a', {
    get: function () { return 7; }
  }).a != 7;
});
<|endoftext|>


<commit_before>module.exports = {
  extends: [
    './rules/best-practices',
    './rules/errors',
    './rules/node',
    './rules/style',
    './rules/variables'
  ].map(require.resolve),
  env: {
    browser: true,
    node: true,
    amd: false,
    mocha: false,
    jasmine: false
  },
  rules: {
    'comma-dangle': ['error', 'never'],
    'prefer-numeric-literals': 'off',
    'no-restricted-properties': ['error', {
      object: 'arguments',
      property: 'callee',
      message: 'arguments.callee is deprecated',
    }, {
      property: '__defineGetter__',
      message: 'Please use Object.defineProperty instead.',
    }, {
      property: '__defineSetter__',
      message: 'Please use Object.defineProperty instead.',
    }],
  }
};
<commit_msg>[eslint config] [base] [fix] disable `no-var` in legacy entry point<commit_after>module.exports = {
  extends: [
    './rules/best-practices',
    './rules/errors',
    './rules/node',
    './rules/style',
    './rules/variables'
  ].map(require.resolve),
  env: {
    browser: true,
    node: true,
    amd: false,
    mocha: false,
    jasmine: false
  },
  rules: {
    'comma-dangle': ['error', 'never'],
    'prefer-numeric-literals': 'off',
    'no-restricted-properties': ['error', {
      object: 'arguments',
      property: 'callee',
      message: 'arguments.callee is deprecated',
    }, {
      property: '__defineGetter__',
      message: 'Please use Object.defineProperty instead.',
    }, {
      property: '__defineSetter__',
      message: 'Please use Object.defineProperty instead.',
    }],
    'no-var': 'off'
  }
};
<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | staff_admin | admin', function(hooks) {
  setupApplicationTest(hooks);

  test('is logged in', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.dom('a#account_menu_link').hasText('ADMIN');
  });

  test('visiting homepage', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.equal(currentURL(), '/');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Info');
  });

  // the following pages require authentication. Redirects to homepage otherwise
  test('visiting settings', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/settings');

    assert.equal(currentURL(), '/settings');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Settings');
  });

  test('visiting providers', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/providers');

    assert.equal(currentURL(), '/providers');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Members');
  });

  test('visiting repositories', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/repositories');

    assert.equal(currentURL(), '/repositories');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Repositories');
  });

  test('visiting prefixes', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes');

    assert.equal(currentURL(), '/prefixes');
    assert.dom('h2.work').hasText('DataCite');
  });

  test('visiting prefix 10.5072', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes/10.5072');

    assert.equal(currentURL(), '/prefixes/10.5072');
    assert.dom('div.alert-warning').includesText('The page was not found.');
  });

  test('visiting dois', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/dois');

    assert.equal(currentURL(), '/dois');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('DOIs');
  });

  // test('visiting specific doi', async function(assert) {
  //   await authenticateSession({
  //     uid: 'admin',
  //     name: 'Admin',
  //     role_id: 'staff_admin'
  //   });
  //   await visit('/dois');

  //   // first DOI in list
  //   await click('h3.work:first-child a');

  //   assert.dom('button#edit-doi').includesText('Update DOI (Form)');
  //   assert.dom('button#modify-doi').includesText('Update DOI (File Upload)');
  // });
});
<commit_msg>update tests<commit_after>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | staff_admin | admin', function(hooks) {
  setupApplicationTest(hooks);

  test('is logged in', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.dom('a#account_menu_link').hasText('ADMIN');
  });

  test('visiting homepage', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.equal(currentURL(), '/');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Info');
  });

  // the following pages require authentication. Redirects to homepage otherwise
  test('visiting settings', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/settings');

    assert.equal(currentURL(), '/settings');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Settings');
  });

  test('visiting providers', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/providers');

    assert.equal(currentURL(), '/providers');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Members');
  });

  test('visiting repositories', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/repositories');

    assert.equal(currentURL(), '/repositories');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('li.nav-link.active a').hasText('Repositories');
  });

  test('visiting prefixes', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes');

    assert.equal(currentURL(), '/prefixes');
    assert.dom('h2.work').hasText('DataCite');
  });

  test('visiting prefix 10.5072', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes/10.5072');

    assert.equal(currentURL(), '/prefixes/10.5072');
    assert.dom('div.alert-warning').includesText('The page was not found.');
  });

  // test('visiting dois', async function(assert) {
  //   await authenticateSession({
  //     uid: 'admin',
  //     name: 'Admin',
  //     role_id: 'staff_admin'
  //   });
  //   await visit('/dois');

  //   assert.equal(currentURL(), '/dois');
  //   assert.dom('h2.work').hasText('DataCite');
  //   assert.dom('li.nav-link.active a').hasText('DOIs');
  // });

  // test('visiting specific doi', async function(assert) {
  //   await authenticateSession({
  //     uid: 'admin',
  //     name: 'Admin',
  //     role_id: 'staff_admin'
  //   });
  //   await visit('/dois');

  //   // first DOI in list
  //   await click('h3.work:first-child a');

  //   assert.dom('button#edit-doi').includesText('Update DOI (Form)');
  //   assert.dom('button#modify-doi').includesText('Update DOI (File Upload)');
  // });
});
<|endoftext|>


<commit_before>// Karma configuration
const _ = require('lodash');
const webpack_config = _.clone(require('../frontend_build/src/webpack.config.base'));
const path = require('path');
const webpack = require('webpack');

webpack_config.plugins.push(
  new webpack.DefinePlugin({
    __coreAPISpec: '{}',
    'process.env': {
      NODE_ENV: '"production"',
    },
  })
);
webpack_config.devtool = '#inline-source-map';

// html5media plugin requires this
webpack_config.module.rules.push({
  test: /html5media\/dist\/api\/1\.1\.8\/html5media/,
  use: [
    {
      loader: 'imports-loader?this=>window',
    },
  ],
});

const aliases = require('../frontend_build/src/apiSpecExportTools').coreAliases();
aliases.testUtils = path.resolve(__dirname, './testUtils');
aliases['vue-test'] = path.resolve(__dirname, './vueLocal');

webpack_config.resolve.alias = aliases;

module.exports = function(config) {
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load
    files: [
      // Detailed pattern to include a file. Similarly other options can be used
      { pattern: './node_modules/core-js/client/core.js', watched: false },
      'kolibri/**/assets/test/**/*.js',
    ],

    // list of files to exclude
    exclude: ['kolibri/**/assets/test/util/*.*'],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'kolibri/**/assets/test/**/*.js': ['webpack', 'sourcemap'],
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['spec'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['ChromeHeadless'],

    webpack: webpack_config,

    webpackMiddleware: {
      // suppress all webpack building information to make test logs more readable.
      noInfo: true,
    },

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,
  });
};
<commit_msg>Fix test webpack config<commit_after>// Karma configuration
const _ = require('lodash');
const webpack_config = _.clone(require('../frontend_build/src/webpack.config.base'));
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

webpack_config.plugins.push(
  new webpack.DefinePlugin({
    __coreAPISpec: '{}',
    'process.env': {
      NODE_ENV: '"production"',
    },
  })
);

webpack_config.plugins.push(new ExtractTextPlugin("styles.css"));

webpack_config.devtool = 'none';

// html5media plugin requires this
webpack_config.module.rules.push({
  test: /html5media\/dist\/api\/1\.1\.8\/html5media/,
  use: [
    {
      loader: 'imports-loader?this=>window',
    },
  ],
});

webpack_config.stats = 'none';

const aliases = require('../frontend_build/src/apiSpecExportTools').coreAliases();
aliases.testUtils = path.resolve(__dirname, './testUtils');
aliases['vue-test'] = path.resolve(__dirname, './vueLocal');

webpack_config.resolve.alias = aliases;

module.exports = function(config) {
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load
    files: [
      // Detailed pattern to include a file. Similarly other options can be used
      { pattern: './node_modules/core-js/client/core.js', watched: false },
      'kolibri/**/assets/test/**/*.js',
    ],

    // list of files to exclude
    exclude: ['kolibri/**/assets/test/util/*.*'],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'kolibri/**/assets/test/**/*.js': ['webpack', 'sourcemap'],
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['spec'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['ChromeHeadless'],

    webpack: webpack_config,

    webpackMiddleware: {
      // suppress all webpack building information to make test logs more readable.
      noInfo: true,
    },

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,
  });
};
<|endoftext|>


<commit_before>var React = require('react'),
    Parent = React.createFactory(require('../../../src/components/parent.jsx')),
    TestUtils = require('react/addons').addons.TestUtils;

describe('Parent', function() {
  var component;

  beforeEach(function() {
    component = React.render(Parent(), this.container);
  });

  it('should set initial foo', function() {
    expect(component.state.foo).to.equal('bar');
  });

  it('should set initial stuff', function() {
    expect(component.state.stuff).to.equal('tomato');
  });

  it('should change foo when asked to', function() {
    component.changeFoo('baz');
    expect(component.state.foo).to.equal('baz');
  });

  it('should do stuff when asked to', function() {
    component.doStuff();
    expect(component.state.stuff).to.equal('potato');
  });
});

<commit_msg>Stub the render method to do nothing<commit_after>var React = require('react'),
    Parent = React.createFactory(require('../../../src/components/parent.jsx')),
    TestUtils = require('react/addons').addons.TestUtils,
    TestHelpers = require('../../helpers.js');

describe('Parent', function() {
  var component;

  beforeEach(function() {
    TestHelpers.stubMethod(this.sandbox, Parent, 'render', null);

    component = React.render(Parent(), this.container);
  });

  it('should set initial foo', function() {
    expect(component.state.foo).to.equal('bar');
  });

  it('should set initial stuff', function() {
    expect(component.state.stuff).to.equal('tomato');
  });

  it('should change foo when asked to', function() {
    component.changeFoo('baz');
    expect(component.state.foo).to.equal('baz');
  });

  it('should do stuff when asked to', function() {
    component.doStuff();
    expect(component.state.stuff).to.equal('potato');
  });
});

<|endoftext|>


<commit_before>import Ember from 'ember';

const { Controller } = Ember;

export default Controller.extend({
  sampleDefinition: {
    "schema": {
      "type": "object",
      "title": "Team Member 1 - First Shift TPM",
      "required": [
        "confirm"
      ],
      "properties": {
        "1": {
          "title": "Station 5",
          "description": "Inspect & clean prox sensors, locator pins, clamps, damaged wiring, slag, inspect bowl feeder, and sweep station",
          "type": "boolean",
          "default": false
        },
        "2": {
          "title": "Station 10",
          "description": "Inspect & clean prox sensors, locator pins, clamps, damaged wiring & slag sweep station",
          "type": "boolean",
          "default": false
        },
        "3": {
          "title": "10 R1 MIG Wire Barrel",
          "description": "Inspect wire barrel for damage and check to see if the barrel has sufficent wire if not notify tl to get barrel exchanged",
          "type": "boolean",
          "default": false
        },
        "4": {
          "title": "Air Gauges",
          "description": "Verify air pressure is reading 75 - 95 psi , wipe off dust",
          "type": "boolean",
          "default": false
        },
        "confirm": {
          "title": "Everything OK",
          "description": "Did you have any issues with this TPM?",
          "type": "boolean",
          "default": false
        }
      }
    },
    "form": [
      {
        "key": "confirm",
        "type": "radios"
      }
    ]
  },

  sampleModel: {},

  actions: {
    sendToServer() {
      alert('fake sent');
    }
  }
});
<commit_msg>Add expanded test data<commit_after>import Ember from 'ember';

const { Controller } = Ember;

export default Controller.extend({
  sampleDefinition: {
    "schema": {
      "type": "object",
      "title": "RH Apron Rail - Lift Assist",
      "required": [],
      "properties": {
        "1": {
          "title": "Operator Control and Material Handler",
          "description": "Air clean fixture base",
          "type": "boolean",
          "default": false
        },
        "2": {
          "title": "Operator Control and Material Handler",
          "description": "Inspect and repair switches and tooling",
          "type": "boolean",
          "default": false
        },
        "3": {
          "title": "Operator Control and Material Handler",
          "description": "Inspect and repair air lines",
          "type": "boolean",
          "default": false
        },
        "4": {
          "title": "Operator Control and Material Handler",
          "description": "Verify all operator controls are working properly",
          "type": "boolean",
          "default": false
        },
        "5": {
          "title": "Operator Control and Material Handler",
          "description": "Check grippers for damage and wear",
          "type": "boolean",
          "default": false
        },
        "6": {
          "title": "Braking Assembly",
          "description": "Verify cylinders are in good working condition (no leaks)",
          "type": "boolean",
          "default": false
        },
        "7": {
          "title": "Braking Assembly (Lower Brake)",
          "description": "Measure and record in millimeters the brake pad and brake disk thickness",
          "type": "string"
        },
        "8": {
          "title": "Braking Assembly (Middle Brake)",
          "description": "Measure and record in millimeters the brake pad and brake disk thickness",
          "type": "string"
        },
        "9": {
          "title": "Braking Assembly (Top Brake)",
          "description": "Measure and record in millimeters the brake pad and brake disk thickness",
          "type": "string"
        },
        "10": {
          "title": "Comments",
          "type": "string"
        }
      }
    },
    "form": [{
      "key": "10",
      "type": "textarea"
    }]
  },

  sampleModel: {},

  actions: {
    sendToServer() {
      alert('fake sent');
    }
  }
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017, Ivan Mironchik
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 */

export default {
  devServer: {
    noInfo: true
  }
};
<commit_msg>Remove noInfo<commit_after>/**
 * Copyright (c) 2017, Ivan Mironchik
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 */

export default {};
<|endoftext|>


<commit_before>mapkob = Object.create(null);

/**
 * Generic function to prepare input for consumption
 *
 * Type can be one of:
 *  - "newline delim": Take a string where sentences are delimited by newlines
 *  -
 *
 * @param {Object} data The input data
 * @param {String} type The type of input
 * @returns {Array} An array of strings, sentences delimited by undefined
 */
mapkob.prepareInput = function(data, type) {

  // newline delim
  var splitRe = new RegExp("([\n\r\.]+)")
  if (type === "newline delim") {
    var sentences = data.split(splitRe);
    var delimited = [];
    sentences.map(function(sentence, i) {
      delimited.push(sentence);
      if (i < sentences.length - 1) {
        delimited.push(undefined)
      }
    });

    return delimited.map(function(sentence) {
      return sentence === undefined ? [undefined] : sentence.split(" ");
    }).reduce(function(x,y) {return x.concat(y)})
  }
  return
}

/**
 * A Row mapkob row constructor
 *
 * @param {Object} input A simple object
 * @returns {Object} A maokob row
 */
mapkob.Row = function(input) {
  this.row = input;
  this.stateSpace = Object.keys(input);
  return this;
}

mapkob.TransitionMatrix = function(words) {
  var uniqueWords = mapkob.unique(words.concat(undefined));
  this.stateSpace = uniqueWords;

  var matrix = {};
  uniqueWords.map(function(word) {matrix[word] = {};});
  words.map(function(word, i) {
    var nextWord = words[i + 1];

    if (matrix[word][nextWord] === undefined) {
      matrix[word][nextWord] = 1;
    } else {
      matrix[word][nextWord] += 1;
    }
  })
  this.matrix = matrix;
  return this;
}

/**
 * Returns a list of unique elements
 *
 * @param {Array} input The array of elements
 * @returns {Array} The deduped array
 */
mapkob.unique = function(input) {
  var output = [];
  input.map(function(element) {
    if (output.indexOf(element) === -1) {
      output.push(element)}});
  return output;
}

/**
 * Returns the row of a matrix
 *
 * @param {String} row The row by name to look up
 * @returns {Object} The row of the matrix
 */
mapkob.TransitionMatrix.prototype.getRow = function(row) {
  var row = new mapkob.Row(this.matrix[row]);
  return row;
}

/**
 * Calculates the sum of the rows
 *
 * @returns {Number} The sum of the values
 */
mapkob.Row.prototype.sum = function() {
  return this.stateSpace.map(function(state) {
    return this.row[state];
  }, this).reduce(function(x, y) {
    return x + y;
  })
}

/**
 * Calculates relative frequencies of a row
 *
 * @returns {Object} A row
 */
mapkob.Row.prototype.probabilities = function() {
  var sum = this.sum();
  var probs = {};
  this.stateSpace.map(function(state) {probs[state] = this.row[state] / sum}, this);
  return new mapkob.Row(probs)
}

/**
 * A row with the cumulative sums
 *
 * @returns {Object} A row
 */
mapkob.Row.prototype.cumSum = function() {
  var sums = {};
  var sum = 0;
  this.stateSpace.map(function(state) {
    sum += this.row[state];
    sums[state] = sum;
  }, this);
  return new mapkob.Row(sums);
}

/**
 * Returns an array with the row's values
 *
 * @returns {Array} The rows values
 */
mapkob.Row.prototype.values = function() {
  return this.stateSpace.map(function(state) {
    return this.row[state]
  }, this);
}

/**
 * Picks the state with the largest CDF that is smaller or equal to p
 * Technically the first one where the next is larger or the array ends
 *
 * @returns {String} A state string
 */
mapkob.Row.prototype.pickState = function(p) {
  cdf = this.values();
  for (var col in cdf) {
    if (p <= cdf[col] && (cdf[col + 1] == undefined || cdf[col + 1] > p)) {
      return this.stateSpace[col];
    }
  }
}

/**
 * Generates a Markov chain
 *
 * @returns {String} A Computer generated string
 */
mapkob.TransitionMatrix.prototype.generateChain = function() {
  var stateI = Math.floor(Math.random() * this.stateSpace.length);
  var currentState = this.stateSpace[stateI];
  var output = [];

  while (currentState !== "undefined" && currentState !== undefined) {
    output.push(currentState);
    var cumSums = this.getRow(currentState).probabilities().cumSum();
    var r = Math.random();
    currentState = cumSums.pickState(r);
  }
  return output.join(" ");
}
<commit_msg>Add array of sentences array<commit_after>mapkob = Object.create(null);

/**
 * Generic function to prepare input for consumption
 *
 * Type can be one of:
 *  - "newline delim": Take a string where sentences are delimited by newlines
 *  -
 *
 * @param {Object} data The input data
 * @param {String} type The type of input
 * @returns {Array} An array of strings, sentences delimited by undefined
 */
mapkob.prepareInput = function(data, type) {
  function splitSentenceArray(a) {
    var delimited = [];
    a.map(function(sentence, i) {
      delimited.push(sentence);
      if (i < sentences.length - 1) {
        delimited.push(undefined)
      }
    });
    return delimited
  }

  function flattenSentenceArray(a) {
    return a.map(function(sentence) {
      return sentence === undefined ? [undefined] : sentence.split(" ");
    }).reduce(function(x,y) {return x.concat(y)})
  }

  // newline delim
  var splitRe = new RegExp("([\n\r\.]+)")
  if (type === "newline delim") {
    var sentences = data.split(splitRe);
    var delimited = splitSentenceArray(sentences);
    return flattenSentenceArray(delimited);

  }

  // sentence array
  if (type === "sentence array") {
    var delimited = splitSentenceArray(sentences);
    return flattenSentenceArray(delimited);
  }
  return
}

/**
 * A Row mapkob row constructor
 *
 * @param {Object} input A simple object
 * @returns {Object} A maokob row
 */
mapkob.Row = function(input) {
  this.row = input;
  this.stateSpace = Object.keys(input);
  return this;
}

mapkob.TransitionMatrix = function(words) {
  var uniqueWords = mapkob.unique(words.concat(undefined));
  this.stateSpace = uniqueWords;

  var matrix = {};
  uniqueWords.map(function(word) {matrix[word] = {};});
  words.map(function(word, i) {
    var nextWord = words[i + 1];

    if (matrix[word][nextWord] === undefined) {
      matrix[word][nextWord] = 1;
    } else {
      matrix[word][nextWord] += 1;
    }
  })
  this.matrix = matrix;
  return this;
}

/**
 * Returns a list of unique elements
 *
 * @param {Array} input The array of elements
 * @returns {Array} The deduped array
 */
mapkob.unique = function(input) {
  var output = [];
  input.map(function(element) {
    if (output.indexOf(element) === -1) {
      output.push(element)}});
  return output;
}

/**
 * Returns the row of a matrix
 *
 * @param {String} row The row by name to look up
 * @returns {Object} The row of the matrix
 */
mapkob.TransitionMatrix.prototype.getRow = function(row) {
  var row = new mapkob.Row(this.matrix[row]);
  return row;
}

/**
 * Calculates the sum of the rows
 *
 * @returns {Number} The sum of the values
 */
mapkob.Row.prototype.sum = function() {
  return this.stateSpace.map(function(state) {
    return this.row[state];
  }, this).reduce(function(x, y) {
    return x + y;
  })
}

/**
 * Calculates relative frequencies of a row
 *
 * @returns {Object} A row
 */
mapkob.Row.prototype.probabilities = function() {
  var sum = this.sum();
  var probs = {};
  this.stateSpace.map(function(state) {probs[state] = this.row[state] / sum}, this);
  return new mapkob.Row(probs)
}

/**
 * A row with the cumulative sums
 *
 * @returns {Object} A row
 */
mapkob.Row.prototype.cumSum = function() {
  var sums = {};
  var sum = 0;
  this.stateSpace.map(function(state) {
    sum += this.row[state];
    sums[state] = sum;
  }, this);
  return new mapkob.Row(sums);
}

/**
 * Returns an array with the row's values
 *
 * @returns {Array} The rows values
 */
mapkob.Row.prototype.values = function() {
  return this.stateSpace.map(function(state) {
    return this.row[state]
  }, this);
}

/**
 * Picks the state with the largest CDF that is smaller or equal to p
 * Technically the first one where the next is larger or the array ends
 *
 * @returns {String} A state string
 */
mapkob.Row.prototype.pickState = function(p) {
  cdf = this.values();
  for (var col in cdf) {
    if (p <= cdf[col] && (cdf[col + 1] == undefined || cdf[col + 1] > p)) {
      return this.stateSpace[col];
    }
  }
}

/**
 * Generates a Markov chain
 *
 * @returns {String} A Computer generated string
 */
mapkob.TransitionMatrix.prototype.generateChain = function() {
  var stateI = Math.floor(Math.random() * this.stateSpace.length);
  var currentState = this.stateSpace[stateI];
  var output = [];

  while (currentState !== "undefined" && currentState !== undefined) {
    output.push(currentState);
    var cumSums = this.getRow(currentState).probabilities().cumSum();
    var r = Math.random();
    currentState = cumSums.pickState(r);
  }
  return output.join(" ");
}
<|endoftext|>