<commit_before>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at http://www.mozillapopcorn.org/butter-license.txt */

define( [ "core/eventmanager", "./toggler", "./logo-spinner", "./context-button", "./header" ],
        function( EventManagerWrapper, Toggler, LogoSpinner, ContextButton, Header ){

  var TRANSITION_DURATION = 500,
      BUTTER_CSS_FILE = "{css}/butter.ui.css";

  function Area( id, element ){
    var _element,
        _components = [],
        _this = this;

    EventManagerWrapper( _this );

    this.element = _element = element || document.createElement( "div" );
    _element.id = id;
    this.items = {};

    this.addComponent = function( element, options ){
      var component = new Component( element, options );
      _components.push( component );
      _element.appendChild( component.element );
    };

    this.setContentState = function( state ){
      for( var i=0, l=_components.length; i<l; ++i ){
        _components[ i ].setState( state );
      }
    };
  }

  function Component( element, options ){
    options = options || {};
    var _onTransitionIn = options.transitionIn || function(){},
        _onTransitionInComplete = options.transitionInComplete || function(){},
        _onTransitionOut = options.transitionOut || function(){},
        _onTransitionOutComplete = options.transitionOutComplete || function(){},
        _validStates = options.states || [],
        _enabled = false;

    this.element = element;

    this.setState = function( state ){
      if( ( !_validStates || _validStates.indexOf( state ) > -1 ) && !_enabled ){
        _enabled = true;
        _onTransitionIn();
        setTimeout( _onTransitionInComplete, TRANSITION_DURATION );
      }
      else if( _enabled ){
        _onTransitionOut();
        setTimeout( _onTransitionOutComplete, TRANSITION_DURATION );
        _enabled = false;
      }
    };
  }

  function loadIcons( icons, resourcesDir ){
    var icon, img, div;

    for( icon in icons ){
      if( icons.hasOwnProperty( icon ) ){
        img = new Image();
        img.id = icon + "-icon";
        img.src = resourcesDir + icons[ icon ];

        // We can't use "display: none", since that makes it
        // invisible, and thus not load.  Opera also requires
        // the image be in the DOM before it will load.
        div = document.createElement( "div" );
        div.setAttribute( "data-butter-exclude", "true" );
        div.className = "butter-image-preload";

        div.appendChild( img );
        document.body.appendChild( div );
      }
    }
  }

  var __unwantedKeyPressElements = [
    "TEXTAREA",
    "INPUT",
    "VIDEO",
    "AUDIO"
  ];

  var NUDGE_INCREMENT_SMALL = 0.25,
      NUDGE_INCREMENT_LARGE = 1;

  function UI( butter, options ){

    var _areas = {},
        _contentState = [],
        _state = true,
        _logoSpinner,
        _this = this;

    EventManagerWrapper( _this );

    _areas.main = new Area( "butter-tray" );

    this.contentStateLocked = false;

    var _element = _areas.main.element,
        _toggler = new Toggler( butter, _element );

    _element.setAttribute( "data-butter-exclude", "true" );
    _element.className = "butter-tray";

    _areas.work = new Area( "work" );
    _areas.statusbar = new Area( "status-bar" );
    _areas.tools = new Area( "tools" );

    var logoContainer = document.createElement( "div" );
    logoContainer.id = "butter-loading-container";
    _logoSpinner = LogoSpinner( logoContainer );
    _element.appendChild( logoContainer );

    _element.appendChild( _areas.statusbar.element );
    _element.appendChild( _areas.work.element );
    _element.appendChild( _areas.tools.element );

    if( options.ui.enabled !== false ){
      document.body.classList.add( "butter-header-spacing" );
      document.body.classList.add( "butter-tray-spacing" );
      document.body.appendChild( _element );
      butter.listen( "mediaadded", function( e ){
        e.data.createView();
      });
    }

    this.load = function( onReady ){
      if( options.ui.enabled !== false ){
        butter.loader.load(
          [
            {
              type: "css",
              url: BUTTER_CSS_FILE
            }
          ],
          function(){
            // icon preloading needs css to be loaded first
            loadIcons( options.icons, options.dirs.resources || "" );
            onReady();
          }
        );
      }
      else{
        onReady();
      }
    };

    this.registerStateToggleFunctions = function( state, events ){
      _this.listen( "contentstatechanged", function( e ){
        if( e.data.oldState === state ){
          events.transitionOut( e );
        }
        if( e.data.newState === state ){
          events.transitionIn( e );
        }
      });
    };

    this.pushContentState = function( state ){
      if( _this.contentStateLocked ){
        return;
      }
      var oldState = _this.contentState;
      _contentState.push( state );
      _element.setAttribute( "data-butter-content-state", _this.contentState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( state );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: _this.contentState
      });
    };

    this.popContentState = function(){
      if( _this.contentStateLocked ){
        return;
      }
      var oldState = _contentState.pop(),
          newState = _this.contentState;
      _element.setAttribute( "data-butter-content-state", newState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( newState );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: newState
      });
      return oldState;
    };

    this.setContentState = function( newState ){
      var oldState = _contentState.pop();
      _contentState = [ newState ];
      _element.setAttribute( "data-butter-content-state", newState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( newState );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: newState
      });
      return oldState;
    };

    Object.defineProperties( this, {
      contentState: {
        configurable: false,
        enumerable: true,
        get: function(){
          if( _contentState.length > 0 ){
            return _contentState[ _contentState.length - 1 ];
          }
          return null;
        }
      },
      element: {
        configurable: false,
        enumerable: true,
        get: function(){
          return _element;
        }
      },
      areas: {
        configurable: false,
        enumerable: true,
        get: function(){
          return _areas;
        }
      },
      visible: {
        enumerable: true,
        get: function(){
          return _state;
        },
        set: function( val ){
          if( _state !== val ){
            _state = val;
            if( _state ){
              document.body.classList.remove( "minimized" );
              _element.setAttribute( "ui-state", "visible" );
              _this.dispatch( "uivisibilitychanged", true );
            }
            else {
              document.body.classList.add( "minimized" );
              _element.setAttribute( "ui-state", "hidden" );
              _this.dispatch( "uivisibilitychanged", false );
            } //if
          } //if
        }
      }
    });

    var orderedTrackEvents = butter.orderedTrackEvents = [],
        sortTrackEvents = function( a, b ) {
          return a.popcornOptions.start > b .popcornOptions.start;
        };

    butter.listen( "trackeventadded", function( e ) {
      orderedTrackEvents.push( e.data );
      orderedTrackEvents.sort( sortTrackEvents );
    }); // listen

    butter.listen( "trackeventremoved", function( e ) {
      var index = orderedTrackEvents.indexOf( e.data );
      if( index > -1 ){
        orderedTrackEvents.splice( index, 1 );
      } // if
    }); // listen

    butter.listen( "trackeventupdated", function( e ) {
      orderedTrackEvents.sort( sortTrackEvents );
    }); // listen

    var orderedTracks = butter.orderedTracks = [],
        sortTracks = function( a, b ) {
          return a.order > b.order;
        };

    butter.listen( "trackadded", function( e ) {
      e.data.listen( "trackorderchanged", function( e ) {
        orderedTracks.sort( sortTracks );
      }); // listen
      orderedTracks.push( e.data );
      orderedTracks.sort( sortTracks );
    }); // listen

    butter.listen( "trackremoved", function( e ) {
      var index = orderedTracks.indexOf( e.data );
      if( index > -1 ){
        orderedTracks.splice( index, 1 );
      } // if
    }); // listen

    var processKey = {
      32: function( e ) { // space key
        if( butter.currentMedia.ended ){
          butter.currentMedia.paused = false;
        }
        else{
          butter.currentMedia.paused = !butter.currentMedia.paused;
        }
      }, // space key
      37: function( e ) { // left key
        var inc = e.shiftKey ? NUDGE_INCREMENT_LARGE : NUDGE_INCREMENT_SMALL;
        if( butter.selectedEvents.length ) {
          e.preventDefault();
          for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
            butter.selectedEvents[ i ].moveFrameLeft( inc, e.ctrlKey || e.metaKey );
          } // for
        } else {
          butter.currentTime -= inc;
        } // if
      }, // left key
      38: function( e ) { // up key
        var track,
            trackEvent,
            nextTrack;
        for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
          trackEvent = butter.selectedEvents[ i ];
          track = trackEvent.track;
          nextTrack = orderedTracks[ orderedTracks.indexOf( track ) - 1 ];
          if( nextTrack ) {
            track.removeTrackEvent( trackEvent );
            nextTrack.addTrackEvent( trackEvent );
          } // if
        } // for
      }, // up key
      39: function( e ) { // right key
        e.preventDefault();
        var inc = e.shiftKey ? NUDGE_INCREMENT_LARGE : NUDGE_INCREMENT_SMALL;
        if( butter.selectedEvents.length ) {
          for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
            butter.selectedEvents[ i ].moveFrameRight( inc, e.ctrlKey || e.metaKey );
          } // for
        } else {
          butter.currentTime += inc;
        } // if
      }, // right key
      40: function( e ) { // down key
        var track,
            trackEvent,
            nextTrack;
        for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
          trackEvent = butter.selectedEvents[ i ];
          track = trackEvent.track;
          nextTrack = orderedTracks[ orderedTracks.indexOf( track ) + 1 ];
          if( nextTrack ) {
            track.removeTrackEvent( trackEvent );
            nextTrack.addTrackEvent( trackEvent );
          } // if
        } // for
      }, // down key
      27: function( e ) { // esc key
        for( var i = 0; i < butter.selectedEvents.length; i++ ) {
          butter.selectedEvents[ i ].selected = false;
        } // for
        butter.selectedEvents = [];
      }, // esc key
      8: function( e ) { // del key
        if( butter.selectedEvents.length ) {
          e.preventDefault();
          for( var i = 0; i < butter.selectedEvents.length; i++ ) {
            butter.selectedEvents[ i ].track.removeTrackEvent( butter.selectedEvents[ i ] );
          } // for
          butter.selectedEvents = [];
        } // if
      }, // del key
      9: function( e ) { // tab key
        if( orderedTrackEvents.length && butter.selectedEvents.length <= 1 ){
          e.preventDefault();
          var index = 0,
              direction = e.shiftKey ? -1 : 1;
          if( orderedTrackEvents.indexOf( butter.selectedEvents[ 0 ] ) > -1 ){
            index = orderedTrackEvents.indexOf( butter.selectedEvents[ 0 ] );
            if( orderedTrackEvents[ index+direction ] ){
              index+=direction;
            } else if( !e.shiftKey ){
              index = 0;
            } else {
              index = orderedTrackEvents.length - 1;
            } // if
          } // if
          for( var i = 0; i < butter.selectedEvents.length; i++ ) {
            butter.selectedEvents[ i ].selected = false;
          } // for
          butter.selectedEvents = [];
          orderedTrackEvents[ index ].selected = true;
          butter.selectedEvents.push( orderedTrackEvents[ index ] );
        } // if
      } // tab key
    };

    window.addEventListener( "keydown", function( e ){
      var key = e.which || e.keyCode;
      // this allows backspace and del to do the same thing on windows and mac keyboards
      key = key === 46 ? 8 : key;
      if( processKey[ key ] && __unwantedKeyPressElements.indexOf( e.target.nodeName ) === -1 ){
        processKey[ key ]( e );
      } // if
    }, false );

    this.TRANSITION_DURATION = TRANSITION_DURATION;

    _toggler.visible = false;
    _this.visible = false;

    this.loadIndicator = {
      start: function(){
        _logoSpinner.start();
        logoContainer.style.display = "block";
      },
      stop: function(){
        _logoSpinner.stop(function(){
          logoContainer.style.display = "none";
        });
      }
    };

    _this.loadIndicator.start();

    butter.listen( "ready", function(){
      _this.loadIndicator.stop();
      _this.visible = true;
      _toggler.visible = true;
      ContextButton( butter );
      if( options.ui.enabled !== false ){
        Header( butter, options );
      }
    });

    _this.dialogDir = butter.config.dirs.dialogs || "";

   } //UI

  UI.__moduleName = "ui";

  return UI;

});
<commit_msg>[#1290] Prevented up/down keys moving template page when track events selected. Prevented spacebar from moving page down<commit_after>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at http://www.mozillapopcorn.org/butter-license.txt */

define( [ "core/eventmanager", "./toggler", "./logo-spinner", "./context-button", "./header" ],
        function( EventManagerWrapper, Toggler, LogoSpinner, ContextButton, Header ){

  var TRANSITION_DURATION = 500,
      BUTTER_CSS_FILE = "{css}/butter.ui.css";

  function Area( id, element ){
    var _element,
        _components = [],
        _this = this;

    EventManagerWrapper( _this );

    this.element = _element = element || document.createElement( "div" );
    _element.id = id;
    this.items = {};

    this.addComponent = function( element, options ){
      var component = new Component( element, options );
      _components.push( component );
      _element.appendChild( component.element );
    };

    this.setContentState = function( state ){
      for( var i=0, l=_components.length; i<l; ++i ){
        _components[ i ].setState( state );
      }
    };
  }

  function Component( element, options ){
    options = options || {};
    var _onTransitionIn = options.transitionIn || function(){},
        _onTransitionInComplete = options.transitionInComplete || function(){},
        _onTransitionOut = options.transitionOut || function(){},
        _onTransitionOutComplete = options.transitionOutComplete || function(){},
        _validStates = options.states || [],
        _enabled = false;

    this.element = element;

    this.setState = function( state ){
      if( ( !_validStates || _validStates.indexOf( state ) > -1 ) && !_enabled ){
        _enabled = true;
        _onTransitionIn();
        setTimeout( _onTransitionInComplete, TRANSITION_DURATION );
      }
      else if( _enabled ){
        _onTransitionOut();
        setTimeout( _onTransitionOutComplete, TRANSITION_DURATION );
        _enabled = false;
      }
    };
  }

  function loadIcons( icons, resourcesDir ){
    var icon, img, div;

    for( icon in icons ){
      if( icons.hasOwnProperty( icon ) ){
        img = new Image();
        img.id = icon + "-icon";
        img.src = resourcesDir + icons[ icon ];

        // We can't use "display: none", since that makes it
        // invisible, and thus not load.  Opera also requires
        // the image be in the DOM before it will load.
        div = document.createElement( "div" );
        div.setAttribute( "data-butter-exclude", "true" );
        div.className = "butter-image-preload";

        div.appendChild( img );
        document.body.appendChild( div );
      }
    }
  }

  var __unwantedKeyPressElements = [
    "TEXTAREA",
    "INPUT",
    "VIDEO",
    "AUDIO"
  ];

  var NUDGE_INCREMENT_SMALL = 0.25,
      NUDGE_INCREMENT_LARGE = 1;

  function UI( butter, options ){

    var _areas = {},
        _contentState = [],
        _state = true,
        _logoSpinner,
        _this = this;

    EventManagerWrapper( _this );

    _areas.main = new Area( "butter-tray" );

    this.contentStateLocked = false;

    var _element = _areas.main.element,
        _toggler = new Toggler( butter, _element );

    _element.setAttribute( "data-butter-exclude", "true" );
    _element.className = "butter-tray";

    _areas.work = new Area( "work" );
    _areas.statusbar = new Area( "status-bar" );
    _areas.tools = new Area( "tools" );

    var logoContainer = document.createElement( "div" );
    logoContainer.id = "butter-loading-container";
    _logoSpinner = LogoSpinner( logoContainer );
    _element.appendChild( logoContainer );

    _element.appendChild( _areas.statusbar.element );
    _element.appendChild( _areas.work.element );
    _element.appendChild( _areas.tools.element );

    if( options.ui.enabled !== false ){
      document.body.classList.add( "butter-header-spacing" );
      document.body.classList.add( "butter-tray-spacing" );
      document.body.appendChild( _element );
      butter.listen( "mediaadded", function( e ){
        e.data.createView();
      });
    }

    this.load = function( onReady ){
      if( options.ui.enabled !== false ){
        butter.loader.load(
          [
            {
              type: "css",
              url: BUTTER_CSS_FILE
            }
          ],
          function(){
            // icon preloading needs css to be loaded first
            loadIcons( options.icons, options.dirs.resources || "" );
            onReady();
          }
        );
      }
      else{
        onReady();
      }
    };

    this.registerStateToggleFunctions = function( state, events ){
      _this.listen( "contentstatechanged", function( e ){
        if( e.data.oldState === state ){
          events.transitionOut( e );
        }
        if( e.data.newState === state ){
          events.transitionIn( e );
        }
      });
    };

    this.pushContentState = function( state ){
      if( _this.contentStateLocked ){
        return;
      }
      var oldState = _this.contentState;
      _contentState.push( state );
      _element.setAttribute( "data-butter-content-state", _this.contentState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( state );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: _this.contentState
      });
    };

    this.popContentState = function(){
      if( _this.contentStateLocked ){
        return;
      }
      var oldState = _contentState.pop(),
          newState = _this.contentState;
      _element.setAttribute( "data-butter-content-state", newState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( newState );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: newState
      });
      return oldState;
    };

    this.setContentState = function( newState ){
      var oldState = _contentState.pop();
      _contentState = [ newState ];
      _element.setAttribute( "data-butter-content-state", newState );
      for( var a in _areas ){
        if( _areas.hasOwnProperty( a ) ){
          _areas[ a ].setContentState( newState );
        }
      }
      _this.dispatch( "contentstatechanged", {
        oldState: oldState,
        newState: newState
      });
      return oldState;
    };

    Object.defineProperties( this, {
      contentState: {
        configurable: false,
        enumerable: true,
        get: function(){
          if( _contentState.length > 0 ){
            return _contentState[ _contentState.length - 1 ];
          }
          return null;
        }
      },
      element: {
        configurable: false,
        enumerable: true,
        get: function(){
          return _element;
        }
      },
      areas: {
        configurable: false,
        enumerable: true,
        get: function(){
          return _areas;
        }
      },
      visible: {
        enumerable: true,
        get: function(){
          return _state;
        },
        set: function( val ){
          if( _state !== val ){
            _state = val;
            if( _state ){
              document.body.classList.remove( "minimized" );
              _element.setAttribute( "ui-state", "visible" );
              _this.dispatch( "uivisibilitychanged", true );
            }
            else {
              document.body.classList.add( "minimized" );
              _element.setAttribute( "ui-state", "hidden" );
              _this.dispatch( "uivisibilitychanged", false );
            } //if
          } //if
        }
      }
    });

    var orderedTrackEvents = butter.orderedTrackEvents = [],
        sortTrackEvents = function( a, b ) {
          return a.popcornOptions.start > b .popcornOptions.start;
        };

    butter.listen( "trackeventadded", function( e ) {
      orderedTrackEvents.push( e.data );
      orderedTrackEvents.sort( sortTrackEvents );
    }); // listen

    butter.listen( "trackeventremoved", function( e ) {
      var index = orderedTrackEvents.indexOf( e.data );
      if( index > -1 ){
        orderedTrackEvents.splice( index, 1 );
      } // if
    }); // listen

    butter.listen( "trackeventupdated", function( e ) {
      orderedTrackEvents.sort( sortTrackEvents );
    }); // listen

    var orderedTracks = butter.orderedTracks = [],
        sortTracks = function( a, b ) {
          return a.order > b.order;
        };

    butter.listen( "trackadded", function( e ) {
      e.data.listen( "trackorderchanged", function( e ) {
        orderedTracks.sort( sortTracks );
      }); // listen
      orderedTracks.push( e.data );
      orderedTracks.sort( sortTracks );
    }); // listen

    butter.listen( "trackremoved", function( e ) {
      var index = orderedTracks.indexOf( e.data );
      if( index > -1 ){
        orderedTracks.splice( index, 1 );
      } // if
    }); // listen

    var processKey = {
      32: function( e ) { // space key
        e.preventDefault();

        if( butter.currentMedia.ended ){
          butter.currentMedia.paused = false;
        }
        else{
          butter.currentMedia.paused = !butter.currentMedia.paused;
        }
      }, // space key
      37: function( e ) { // left key
        var inc = e.shiftKey ? NUDGE_INCREMENT_LARGE : NUDGE_INCREMENT_SMALL;
        if( butter.selectedEvents.length ) {
          e.preventDefault();
          for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
            butter.selectedEvents[ i ].moveFrameLeft( inc, e.ctrlKey || e.metaKey );
          } // for
        } else {
          butter.currentTime -= inc;
        } // if
      }, // left key
      38: function( e ) { // up key
        var track,
            trackEvent,
            nextTrack;

        if( butter.selectedEvents.length ) {
          e.preventDefault();
        }

        for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
          trackEvent = butter.selectedEvents[ i ];
          track = trackEvent.track;
          nextTrack = orderedTracks[ orderedTracks.indexOf( track ) - 1 ];
          if( nextTrack ) {
            track.removeTrackEvent( trackEvent );
            nextTrack.addTrackEvent( trackEvent );
          } // if
        } // for
      }, // up key
      39: function( e ) { // right key
        e.preventDefault();
        var inc = e.shiftKey ? NUDGE_INCREMENT_LARGE : NUDGE_INCREMENT_SMALL;
        if( butter.selectedEvents.length ) {
          for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
            butter.selectedEvents[ i ].moveFrameRight( inc, e.ctrlKey || e.metaKey );
          } // for
        } else {
          butter.currentTime += inc;
        } // if
      }, // right key
      40: function( e ) { // down key
        var track,
            trackEvent,
            nextTrack;

        if( butter.selectedEvents.length ) {
          e.preventDefault();
        }

        for( var i = 0, seLength = butter.selectedEvents.length; i < seLength; i++ ) {
          trackEvent = butter.selectedEvents[ i ];
          track = trackEvent.track;
          nextTrack = orderedTracks[ orderedTracks.indexOf( track ) + 1 ];
          if( nextTrack ) {
            track.removeTrackEvent( trackEvent );
            nextTrack.addTrackEvent( trackEvent );
          } // if
        } // for
      }, // down key
      27: function( e ) { // esc key
        for( var i = 0; i < butter.selectedEvents.length; i++ ) {
          butter.selectedEvents[ i ].selected = false;
        } // for
        butter.selectedEvents = [];
      }, // esc key
      8: function( e ) { // del key
        if( butter.selectedEvents.length ) {
          e.preventDefault();
          for( var i = 0; i < butter.selectedEvents.length; i++ ) {
            butter.selectedEvents[ i ].track.removeTrackEvent( butter.selectedEvents[ i ] );
          } // for
          butter.selectedEvents = [];
        } // if
      }, // del key
      9: function( e ) { // tab key
        if( orderedTrackEvents.length && butter.selectedEvents.length <= 1 ){
          e.preventDefault();
          var index = 0,
              direction = e.shiftKey ? -1 : 1;
          if( orderedTrackEvents.indexOf( butter.selectedEvents[ 0 ] ) > -1 ){
            index = orderedTrackEvents.indexOf( butter.selectedEvents[ 0 ] );
            if( orderedTrackEvents[ index+direction ] ){
              index+=direction;
            } else if( !e.shiftKey ){
              index = 0;
            } else {
              index = orderedTrackEvents.length - 1;
            } // if
          } // if
          for( var i = 0; i < butter.selectedEvents.length; i++ ) {
            butter.selectedEvents[ i ].selected = false;
          } // for
          butter.selectedEvents = [];
          orderedTrackEvents[ index ].selected = true;
          butter.selectedEvents.push( orderedTrackEvents[ index ] );
        } // if
      } // tab key
    };

    window.addEventListener( "keydown", function( e ){
      var key = e.which || e.keyCode;
      // this allows backspace and del to do the same thing on windows and mac keyboards
      key = key === 46 ? 8 : key;
      if( processKey[ key ] && __unwantedKeyPressElements.indexOf( e.target.nodeName ) === -1 ){
        processKey[ key ]( e );
      } // if
    }, false );

    this.TRANSITION_DURATION = TRANSITION_DURATION;

    _toggler.visible = false;
    _this.visible = false;

    this.loadIndicator = {
      start: function(){
        _logoSpinner.start();
        logoContainer.style.display = "block";
      },
      stop: function(){
        _logoSpinner.stop(function(){
          logoContainer.style.display = "none";
        });
      }
    };

    _this.loadIndicator.start();

    butter.listen( "ready", function(){
      _this.loadIndicator.stop();
      _this.visible = true;
      _toggler.visible = true;
      ContextButton( butter );
      if( options.ui.enabled !== false ){
        Header( butter, options );
      }
    });

    _this.dialogDir = butter.config.dirs.dialogs || "";

   } //UI

  UI.__moduleName = "ui";

  return UI;

});
<|endoftext|>


<commit_before>$(document).ready(function() {
    $('.ontology-select').select2({placeholder: "Filter by ontology"})
        .on('select2:select', function (e) {
            $("#ontology-id").append($('<option/>', {
                value: e.params.data.id.toLowerCase(),
                text : e.params.data.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        })
        .on('select2:unselect', function (e) {

            $("#ontology-id").find("[value=\"" + e.params.data.id.toLowerCase() + "\"]").remove();
            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });

    $('.type-select').select2({placeholder: "Filter by type"})
        .on('select2:select', function (e) {
            $("#ontology-type-id").append($('<option/>', {
                value: e.params.data.id.toLowerCase(),
                text : e.params.data.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        })
        .on('select2:unselect', function (e) {

            $("#ontology-type-id").find("[value=\"" + e.params.data.id.toLowerCase() + "\"]").remove();
            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });

    $('.typeahead').typeahead('val', $('#query-id').val(), false).typeahead('close');

    ontologyList = new Object();
    $('#ontology-select-id option').each(function(){
        ontologyList[this.value]=$(this).attr('data-ontology-title');
    });

    try {
        loadResults();
    } catch (err) {

    }

});

function setSelectOptions (selectId, data) {

    var data = $('.ontology-select').select2('data')
    alert(data.text);

    //
    // $('#start').val(0);
    // $("#filter_form").submit();
}

var ontologyList;
//var ontologyTitle;

function clearFilter() {
    $('#ontology-select-id').val('');
    $('#ontology-id').val('');
    $('#ontology-type-id').val('');
    $('#ontology-select-type-id').val('');
    $('#group-id').attr('checked', false);
    $('#exact-id').attr('checked', false);
    $('#obsolete-id').attr('checked', false);
    $('#filter_form').submit();

}

function loadResults() {

    var query =$('#filter_form').serialize()
    //console.log("Loading results for " + query);

    solrSearch(query)

}

function solrSearch(queryTerm) {
    //console.log("Solr search request received for " + queryTerm);
    $.getJSON('api/search?' + queryTerm)
        .done(function (data) {
            processData(data);
        });
}

function clickPrev() {
    if (! $( ".prev-button" ).first().hasClass( "disabled" )) {
        var start = $('.start-display').first().text() - 11;
        $('#start').val(start);
        $('#filter_form').submit();
    }
}

function clickNext() {

    if (!$( ".next-button" ).first().hasClass( "disabled" )) {
        var end = $('.end-display').first().text();
        $('#start').val(end);
        $('#filter_form').removeAttr('onsubmit').submit();
    }
}

function processData(data) {
    var docs = data.response.docs;

    // render results stats and pagination
    var start = data.response.start;
    var end = data.response.numFound > 10 ? start + 10 : data.response.numFound;
    var total = data.response.numFound;

    if (total == 0) {
        $('.search-results-count').text("No results!")
        $('.bottom-nav').hide();
        // hide spinner
        $('#searching').hide();
        $('#search-results-summary').show();

        return;
    }
    $('.start-display').each(function () {
        $(this).text(start + 1);
    });

    $('.end-display').each(function () {
        $(this).text(end);
    });

    $('.total-display').each(function () {
        $(this).text(total);
    });

    if (start > 0) {
        $('.prev-button').each(function () {
            $(this).removeClass('disabled')
        });
    }
    if (end < total) {
        $('.next-button').each(function () {
            $(this).removeClass('disabled');
        });
    }

    // hide spinner
    $('#searching').hide();
    // show summary
    $('#search-results-summary').show();

    // render search results
    var searchResult = $('#search-results');
    $.each(docs, function(index, row) {

        var isOntology = (row.type == 'ontology');
        var link;

        if (isOntology) {
            link = getOntologyLink(row.label, row.ontology_name);
        }
        else {
            link = getTermLink(row.label,row.ontology_name, row.type, row.iri);
        }

        var description = row.description;
        if (description != undefined) {
            description = row.description[0];

            if (description.length > 300) {
                description = description.substr(0, 500) + '…';
            }
        }

        var resultHtml = $('

');
        resultHtml = resultHtml.append(link);
        resultHtml = resultHtml.append('  ');

        var shortId = row.obo_id;
        if (shortId == undefined) {
            shortId = row.short_form;
        }

        var termShortId;
        if (isOntology) {
            termShortId = $("
" + row.ontology_prefix + "
");
        }
        else {
            termShortId= $("
" + shortId + "
");
        }

        resultHtml = resultHtml.append(termShortId);

        resultHtml = resultHtml.append('
');
        resultHtml = resultHtml.append($('').text(row.iri));
        resultHtml = resultHtml.append('
');
        if (description != undefined) {
            resultHtml = resultHtml.append($('').text(description));
            resultHtml = resultHtml.append('
');
        }

        if (!isOntology) {
            resultHtml = resultHtml.append('Ontology: ');

            var ontologyTitle = ontologyList[row.ontology_name];
            var ontologyLink = $('',{
                class: 'nounderline',
                text: ontologyTitle,
                href: 'ontologies/' + row.ontology_name
            });
            resultHtml = resultHtml.append(ontologyLink);
            resultHtml = resultHtml.append(' ');
            var ontologies = $("
" + row.ontology_prefix + "
");
            resultHtml = resultHtml.append(ontologies);
            resultHtml = resultHtml.append('
');

            if (data.expanded != undefined) {
                if (data.expanded[row.iri] != undefined) {
                    resultHtml = resultHtml.append('Also in: ');

                    $.each (data.expanded[row.iri].docs, function (expandedIndex, expandedRow) {
                        var exLink = getTermLink(expandedRow.ontology_prefix, expandedRow.ontology_name,expandedRow.type, expandedRow.iri )

                        var ontoLink = $("")
                            .append($("").text(exLink.text()))
                        resultHtml.append(ontoLink);
                    })

                }
            }
        }

        resultHtml = resultHtml.append('
');
        resultHtml = resultHtml.append('
');

        searchResult.append(resultHtml);
    });

    var facets = data.facet_counts.facet_fields;

    var typeSummary = $('#type-summary');
    var ontologySummary = $('#ontology-summary');

    renderTypesFacetField(facets.type, typeSummary);
    renderOntologyFacetField(facets.ontology_prefix, ontologySummary);
    //renderFacetField(facets.is_defining_ontology, "Defining ontology", searchSummary);
    //renderFacetField(facets.is_obsolete, "Is Obsolete", searchSummary);
    //renderFacetField(facets.subset, "Susbsets", searchSummary);

    // IE hack to force closing of autocomplete after search result drawn
    $('.typeahead').typeahead('close');

}

function getOntologyLink (label, ontology ) {
    return $('',{
        class: 'search-results-label nounderline',
        text: label,
        title: label,
        href: 'ontologies/' + ontology
    });
}

function getTermLink (label, ontology, type, uri ) {
    var encodedUri = encodeURIComponent(uri);
    var _type = getUrlType(type);

    return $('',{
        class: 'search-results-label nounderline',
        text: label,
        title: label,
        href: 'ontologies/' + ontology + "/" + _type + "?iri=" + encodedUri
    });
}

function renderTypesFacetField (facetArray, searchSummary) {
    if (facetArray != undefined) {

        var numberOfFacets = 0;
        var fieldList = $('

');

        for (var x = 0 ; x < facetArray.length; x = x + 2) {
            var name = facetArray[x];
            var count = facetArray[x + 1];

            if (count > 0) {
                fieldList.append('<button type=\'button\' id="'+name+'" class="type_list list-group-item">'+name+ '' + count + '</button>');
                numberOfFacets++;
            }

        }

        if (numberOfFacets > 0) {
            searchSummary.append(fieldList);
        }

        $(".type_list").on('click', function(e){
            //$('#ontology-select-id').val('');
            $("#ontology-type-id").append($('<option/>', {
                value: e.target.id.toLowerCase(),
                text : e.target.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });
    }
}

function renderOntologyFacetField (facetArray, searchSummary) {

    if (facetArray != undefined) {

        var numberOfFacets = 0;

        var fieldList = $('

');

        for (var x = 0 ; x < facetArray.length; x = x + 2) {
            var name = facetArray[x];
            var count = facetArray[x + 1];

            if (count > 0) {
                fieldList.append('<button type=\'button\' id="'+name+'" class="onto_list list-group-item" title="'+ontologyList[name.toLowerCase()]+'">'+name+ '' + count + '</button>');
                numberOfFacets++;
            }

        }

        if (numberOfFacets > 0) {
            searchSummary.append(fieldList);
        }

        //Register click event for ontology list
        $(".onto_list").on('click', function(e){
            //$('#ontology-select-id').val('');
            $("#ontology-id").append($('<option/>', {
                value: e.target.id.toLowerCase(),
                text : e.target.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });
    }
}

function resetPage() {
    $('#start').val(0);
}<commit_msg>Correct final search page record count (fix #279); fix 'Prev' navigation<commit_after>$(document).ready(function() {
    $('.ontology-select').select2({placeholder: "Filter by ontology"})
        .on('select2:select', function (e) {
            $("#ontology-id").append($('<option/>', {
                value: e.params.data.id.toLowerCase(),
                text : e.params.data.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        })
        .on('select2:unselect', function (e) {

            $("#ontology-id").find("[value=\"" + e.params.data.id.toLowerCase() + "\"]").remove();
            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });

    $('.type-select').select2({placeholder: "Filter by type"})
        .on('select2:select', function (e) {
            $("#ontology-type-id").append($('<option/>', {
                value: e.params.data.id.toLowerCase(),
                text : e.params.data.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        })
        .on('select2:unselect', function (e) {

            $("#ontology-type-id").find("[value=\"" + e.params.data.id.toLowerCase() + "\"]").remove();
            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });

    $('.typeahead').typeahead('val', $('#query-id').val(), false).typeahead('close');

    ontologyList = new Object();
    $('#ontology-select-id option').each(function(){
        ontologyList[this.value]=$(this).attr('data-ontology-title');
    });

    try {
        loadResults();
    } catch (err) {

    }

});

function setSelectOptions (selectId, data) {

    var data = $('.ontology-select').select2('data')
    alert(data.text);

    //
    // $('#start').val(0);
    // $("#filter_form").submit();
}

var ontologyList;
//var ontologyTitle;

function clearFilter() {
    $('#ontology-select-id').val('');
    $('#ontology-id').val('');
    $('#ontology-type-id').val('');
    $('#ontology-select-type-id').val('');
    $('#group-id').attr('checked', false);
    $('#exact-id').attr('checked', false);
    $('#obsolete-id').attr('checked', false);
    $('#filter_form').submit();

}

function loadResults() {

    var query =$('#filter_form').serialize()
    //console.log("Loading results for " + query);

    solrSearch(query)

}

function solrSearch(queryTerm) {
    //console.log("Solr search request received for " + queryTerm);
    $.getJSON('api/search?' + queryTerm)
        .done(function (data) {
            processData(data);
        });
}

function clickPrev() {
    if (! $( ".prev-button" ).first().hasClass( "disabled" )) {
        var start = Math.max($('.start-display').first().text() - 11, 0);
        $('#start').val(start);
        $('#filter_form').removeAttr('onsubmit').submit();
    }
}

function clickNext() {
    if (!$( ".next-button" ).first().hasClass( "disabled" )) {
        var end = $('.end-display').first().text();
        $('#start').val(end);
        $('#filter_form').removeAttr('onsubmit').submit();
    }
}

function processData(data) {
    var docs = data.response.docs;

    // render results stats and pagination
    var start = data.response.start;
    // var end = data.response.numFound > 10 ? start + 10 : data.response.numFound;
    var end = start + ((data.response.numFound - start) >= 10 ? 10 : ((data.response.numFound - start) % 10));
    var total = data.response.numFound;

    if (total == 0) {
        $('.search-results-count').text("No results!")
        $('.bottom-nav').hide();
        // hide spinner
        $('#searching').hide();
        $('#search-results-summary').show();

        return;
    }
    $('.start-display').each(function () {
        $(this).text(start + 1);
    });

    $('.end-display').each(function () {
        $(this).text(end);
    });

    $('.total-display').each(function () {
        $(this).text(total);
    });

    if (start > 0) {
        $('.prev-button').each(function () {
            $(this).removeClass('disabled')
        });
    }
    if (end < total) {
        $('.next-button').each(function () {
            $(this).removeClass('disabled');
        });
    }

    // hide spinner
    $('#searching').hide();
    // show summary
    $('#search-results-summary').show();

    // render search results
    var searchResult = $('#search-results');
    $.each(docs, function(index, row) {

        var isOntology = (row.type == 'ontology');
        var link;

        if (isOntology) {
            link = getOntologyLink(row.label, row.ontology_name);
        }
        else {
            link = getTermLink(row.label,row.ontology_name, row.type, row.iri);
        }

        var description = row.description;
        if (description != undefined) {
            description = row.description[0];

            if (description.length > 300) {
                description = description.substr(0, 500) + '…';
            }
        }

        var resultHtml = $('

');
        resultHtml = resultHtml.append(link);
        resultHtml = resultHtml.append('  ');

        var shortId = row.obo_id;
        if (shortId == undefined) {
            shortId = row.short_form;
        }

        var termShortId;
        if (isOntology) {
            termShortId = $("
" + row.ontology_prefix + "
");
        }
        else {
            termShortId= $("
" + shortId + "
");
        }

        resultHtml = resultHtml.append(termShortId);

        resultHtml = resultHtml.append('
');
        resultHtml = resultHtml.append($('').text(row.iri));
        resultHtml = resultHtml.append('
');
        if (description != undefined) {
            resultHtml = resultHtml.append($('').text(description));
            resultHtml = resultHtml.append('
');
        }

        if (!isOntology) {
            resultHtml = resultHtml.append('Ontology: ');

            var ontologyTitle = ontologyList[row.ontology_name];
            var ontologyLink = $('',{
                class: 'nounderline',
                text: ontologyTitle,
                href: 'ontologies/' + row.ontology_name
            });
            resultHtml = resultHtml.append(ontologyLink);
            resultHtml = resultHtml.append(' ');
            var ontologies = $("
" + row.ontology_prefix + "
");
            resultHtml = resultHtml.append(ontologies);
            resultHtml = resultHtml.append('
');

            if (data.expanded != undefined) {
                if (data.expanded[row.iri] != undefined) {
                    resultHtml = resultHtml.append('Also in: ');

                    $.each (data.expanded[row.iri].docs, function (expandedIndex, expandedRow) {
                        var exLink = getTermLink(expandedRow.ontology_prefix, expandedRow.ontology_name,expandedRow.type, expandedRow.iri )

                        var ontoLink = $("")
                            .append($("").text(exLink.text()))
                        resultHtml.append(ontoLink);
                    })

                }
            }
        }

        resultHtml = resultHtml.append('
');
        resultHtml = resultHtml.append('
');

        searchResult.append(resultHtml);
    });

    var facets = data.facet_counts.facet_fields;

    var typeSummary = $('#type-summary');
    var ontologySummary = $('#ontology-summary');

    renderTypesFacetField(facets.type, typeSummary);
    renderOntologyFacetField(facets.ontology_prefix, ontologySummary);
    //renderFacetField(facets.is_defining_ontology, "Defining ontology", searchSummary);
    //renderFacetField(facets.is_obsolete, "Is Obsolete", searchSummary);
    //renderFacetField(facets.subset, "Susbsets", searchSummary);

    // IE hack to force closing of autocomplete after search result drawn
    $('.typeahead').typeahead('close');

}

function getOntologyLink (label, ontology ) {
    return $('',{
        class: 'search-results-label nounderline',
        text: label,
        title: label,
        href: 'ontologies/' + ontology
    });
}

function getTermLink (label, ontology, type, uri ) {
    var encodedUri = encodeURIComponent(uri);
    var _type = getUrlType(type);

    return $('',{
        class: 'search-results-label nounderline',
        text: label,
        title: label,
        href: 'ontologies/' + ontology + "/" + _type + "?iri=" + encodedUri
    });
}

function renderTypesFacetField (facetArray, searchSummary) {
    if (facetArray != undefined) {

        var numberOfFacets = 0;
        var fieldList = $('

');

        for (var x = 0 ; x < facetArray.length; x = x + 2) {
            var name = facetArray[x];
            var count = facetArray[x + 1];

            if (count > 0) {
                fieldList.append('<button type=\'button\' id="'+name+'" class="type_list list-group-item">'+name+ '' + count + '</button>');
                numberOfFacets++;
            }

        }

        if (numberOfFacets > 0) {
            searchSummary.append(fieldList);
        }

        $(".type_list").on('click', function(e){
            //$('#ontology-select-id').val('');
            $("#ontology-type-id").append($('<option/>', {
                value: e.target.id.toLowerCase(),
                text : e.target.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });
    }
}

function renderOntologyFacetField (facetArray, searchSummary) {

    if (facetArray != undefined) {

        var numberOfFacets = 0;

        var fieldList = $('

');

        for (var x = 0 ; x < facetArray.length; x = x + 2) {
            var name = facetArray[x];
            var count = facetArray[x + 1];

            if (count > 0) {
                fieldList.append('<button type=\'button\' id="'+name+'" class="onto_list list-group-item" title="'+ontologyList[name.toLowerCase()]+'">'+name+ '' + count + '</button>');
                numberOfFacets++;
            }

        }

        if (numberOfFacets > 0) {
            searchSummary.append(fieldList);
        }

        //Register click event for ontology list
        $(".onto_list").on('click', function(e){
            //$('#ontology-select-id').val('');
            $("#ontology-id").append($('<option/>', {
                value: e.target.id.toLowerCase(),
                text : e.target.id.toLowerCase(),
                selected : 'selected'
            }));

            //always restart start when faceting
            $('#start').val(0);
            $("#filter_form").submit();
        });
    }
}

function resetPage() {
    $('#start').val(0);
}<|endoftext|>


<commit_before>// Storyberg
// -----------
// [Documentation](https://github.com/Storyberg/Docs/wiki/Javascript-Library).

var Provider = require('../provider')
  , extend   = require('extend')
  , isEmail  = require('is-email')
  , load     = require('load-script');

module.exports = Provider.extend({

  key : 'apiKey',

  options : {
    apiKey : null
  },

  initialize : function (options, ready) {
    window._sbq = window._sbq || [];
    window._sbk = options.apiKey;
    load('//storyberg.com/analytics.js');

    // Storyberg creates a queue, so it's ready immediately.
    ready();
  },

  identify : function (userId, traits) {
    // Don't do anything if we just have traits, because Vero
    // requires a `userId`.
    if (!userId) return;

    traits || (traits = {});

    // Storyberg takes the `userId` as part of the traits object
    traits.user_id = userId;

    // If there wasn't already an email and the userId is one, use it.
    if (!traits.email && isEmail(userId)) traits.email = userId;

    window._sbq.push(['identify', traits]);
  },

  track : function (event, properties) {
    properties || (properties = {});

    // Storyberg takes the `userId` as part of the properties object
    properties.name = event;

    window._sbq.push(['event', properties]);
  }

});
<commit_msg>Updated comment<commit_after>// Storyberg
// -----------
// [Documentation](https://github.com/Storyberg/Docs/wiki/Javascript-Library).

var Provider = require('../provider')
  , extend   = require('extend')
  , isEmail  = require('is-email')
  , load     = require('load-script');

module.exports = Provider.extend({

  key : 'apiKey',

  options : {
    apiKey : null
  },

  initialize : function (options, ready) {
    window._sbq = window._sbq || [];
    window._sbk = options.apiKey;
    load('//storyberg.com/analytics.js');

    // Storyberg creates a queue, so it's ready immediately.
    ready();
  },

  identify : function (userId, traits) {
    // Don't do anything if we just have traits, because Storyberg
    // requires a `userId`.
    if (!userId) return;

    traits || (traits = {});

    // Storyberg takes the `userId` as part of the traits object
    traits.user_id = userId;

    // If there wasn't already an email and the userId is one, use it.
    if (!traits.email && isEmail(userId)) traits.email = userId;

    window._sbq.push(['identify', traits]);
  },

  track : function (event, properties) {
    properties || (properties = {});

    // Storyberg takes the `userId` as part of the properties object
    properties.name = event;

    window._sbq.push(['event', properties]);
  }

});
<|endoftext|>


<commit_before>var Point = require('../point/Point');
var MATH_CONST = require('../../math/const');

//  deg = degrees (0-360)

/**
 * [description]
 *
 * @function Phaser.Geom.Rectangle.PerimeterPoint
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Rectangle} rect - [description]
 * @param {integer} deg - [description]
 * @param {Phaser.Geom.Point} [out] - [description]
 *
 * @return {Phaser.Geom.Point} [description]
 */
var PerimeterPoint = function (rect, deg, out)
{
    if (out === undefined) { out = new Point(); }

    var theta = deg * MATH_CONST.DEG_TO_RAD;

    while (theta < -Math.PI)
    {
        theta += MATH_CONST.PI2;
    }

    while (theta > Math.PI)
    {
        theta -= MATH_CONST.PI2;
    }

    var rectAtan = Math.atan2(rect.height, rect.width);
    var tanTheta = Math.tan(theta);
    var thetaBounds = Math.PI - rectAtan;
    var region;
    var xFactor = 1;
    var yFactor = 1;

    if (theta > -rectAtan && theta <= rectAtan)
    {
        region = 1;
        yFactor = -1;
    }
    else if (theta > rectAtan && theta <= thetaBounds)
    {
        region = 2;
        yFactor = -1;
    }
    else if (theta > thetaBounds || theta <= -thetaBounds)
    {
        region = 3;
        xFactor = -1;
    }
    else
    {
        region = 4;
        xFactor = -1;
    }

    out.x = rect.x + (rect.width / 2);
    out.y = rect.y + (rect.height / 2);

    if (region === 1 || region === 3)
    {
        out.x += xFactor * (rect.width / 2);                                     // "Z0"
        out.y += yFactor * (rect.width / 2) * tanTheta;
    }
    else
    {
        out.x += xFactor * (rect.height / (2 * tanTheta));                        // "Z1"
        out.y += yFactor * (rect.height / 2);
    }

    return out;
};

module.exports = PerimeterPoint;
<commit_msg>Revised to use faster method of detecting the perimeter point from the angle.<commit_after>var Point = require('../point/Point');
var DegToRad = require('../../math/DegToRad');

/**
 * [description]
 *
 * @function Phaser.Geom.Rectangle.PerimeterPoint
 * @since 3.0.0
 *
 * @param {Phaser.Geom.Rectangle} rectangle - [description]
 * @param {integer} angle - [description]
 * @param {Phaser.Geom.Point} [out] - [description]
 *
 * @return {Phaser.Geom.Point} [description]
 */
var PerimeterPoint = function (rectangle, angle, out)
{
    if (out === undefined) { out = new Point(); }

    angle = DegToRad(angle);

    var s = Math.sin(angle);
    var c = Math.cos(angle);

    var dx = (c > 0) ? rectangle.width / 2 : rectangle.width / -2;
    var dy = (s > 0) ? rectangle.height / 2 : rectangle.height / -2;

    if (Math.abs(dx * s) < Math.abs(dy * c))
    {
        dy = (dx * s) / c;
    }
    else
    {
        dx = (dy * c) / s;
    }

    out.x = dx + rectangle.centerX;
    out.y = dy + rectangle.centerY;

    return out;
};

module.exports = PerimeterPoint;
<|endoftext|>


<commit_before>/**
 * Logic for the device updater module for LabJack Swichboard.
 *
 * @author A. Samuel Pottinger (LabJack Corp, 2013)
**/

var BASE_FIRMWARE_LISTING_URL = 'http://www.labjack.com/support/firmware/t7';
var FIRMWARE_LISTING_URL = BASE_FIRMWARE_LISTING_URL;
var BETA_LISTING_URL = BASE_FIRMWARE_LISTING_URL+'/beta';
var OLD_LISTING_URL = BASE_FIRMWARE_LISTING_URL+'/old';
var DEVICE_SELECTOR_SRC = 'device_updater/device_selector.html';
var FIRMWARE_LISTING_SRC = 'device_updater/firmware_listing.html';
var DEVICE_SELECTOR_PANE_SELECTOR = '#device-overview';
var FIRMWARE_LIST_SELECTOR = '#firmware-list';
var FIRMWARE_LINK_REGEX = /href\=\".*T7firmware\_([\d\-]+)\_([\d\-]+)\.bin"/g;
var NUM_UPGRADE_STEPS = 4.0;
var COULD_NOT_PARSE_MSG = 'Could not find firmwares on labjack.com';

var async = require('async');
var handlebars = require('handlebars');
var q = require('q');
var request = require('request');

var labjack_t7_upgrade = require('./labjack_t7_upgrade');

var selectedSerials = [];

var DISABLE_WIFI_POWER = true;

var ERROR_TEMPLATE = handlebars.compile(
    '
Could not read {{ . }} registers
'
);

var HUMAN_VERSION_TEMPLATE = handlebars.compile(
    '{{ version }} ({{ humanName }})'
);

/**
 * A wrapper around a device to make device update operations easier.
 *
 * @param {Objct} device The device to adapt.
**/
function UpgradeableDeviceAdapter(device)
{
    var executeErrorSafeFunction = function (target) {
        try {
            return target();
        } catch (e) {
            var errMsg;

            if (e.retError === undefined) {
                errMsg = e.toString();
            } else {
                errMsg = e.retError.toString();
            }

            showAlert('Failed to read device info: ' + errMsg);
            return '[unavailable]';
        }
    };

    /**
     * Get the serial number of the device that is this decorator encapsulates.
     *
     * @return {Number} The serial number of the inner device.
    **/
    this.getSerial = function()
    {
        return executeErrorSafeFunction(device.getSerial);
    };

    /**
     * Get the name of the device that this decorator encapsulates.
     *
     * @return {String} The name of the inner device.
    **/
    this.getName = function()
    {
        return device.getName();
    };

    /**
     * Get the type of device that this decorator encapsulates.
     *
     * @return {String} The string description of the model of the device that
     *      this decorator encapsulates.
    **/
    this.getDeviceType = function()
    {
        return executeErrorSafeFunction(device.getDeviceType);
    };

    /**
     * Get the version of the firmware currently loaded on the given device.
     *
     * @return {Number} The version of the firmware on this decorator's
     *      encapsulated device.
    **/
    this.getFirmwareVersion = function()
    {
        var formattedCall = function () {
            return device.getFirmwareVersion().toFixed(4);
        };
        return executeErrorSafeFunction(formattedCall);
    };

    /**
     * Get the version of the bootloader currently loaded on the given device.
     *
     * @return {Number} The version of the bootloader on this decorator's
     *      encapsulated device.
    **/
    this.getBootloaderVersion = function()
    {
        var formattedCall = function () {
            return device.getBootloaderVersion().toFixed(4);
        };
        return executeErrorSafeFunction(formattedCall);
    };

    this.getConnectionTypeStr = function () {
        return device.getConnectionTypeStr();
    };
}

/**
 * Download a list of available firmware versions.
 *
 * @param {function} onError The function to call if an error is encountered
 *      while downloading the firmware versions.
 * @param {function} onSuccess The function to call after the firmware version
 *      listing has been downloaded.
**/
function getAvailableFirmwareListing(onError, onSuccess)
{
    var nicerOnError = function (display) {
        $('#web-load-waiting-indicator').slideUp();
        $('#no-internet-message').show();
        $('#no-internet-message').hide();
        $('#no-internet-message').slideDown();
        $('#internet-controls').html(COULD_NOT_PARSE_MSG);
    };

    var innerRequest = function (url, humanName, hasLatest) {
        return function (overallFirmwareListing) {
            var innerDeferred = q.defer();
            request(
                url,
                function (error, response, body) {
                    if (error || response.statusCode != 200) {
                        $('#internet-error-list').append(
                            ERROR_TEMPLATE(humanName)
                        );
                        innerDeferred.resolve(overallFirmwareListing);
                        return;
                    }

                    var firmwareListing = [];
                    var match = FIRMWARE_LINK_REGEX.exec(body);
                    var targetURL = match[0].replace(/href\=\"/g, '');
                    targetURL = targetURL.replace(/\"/g, '');

                    while (match !== null) {
                        var version = (parseFloat(match[1])/10000).toFixed(4);
                        var humanVersion = HUMAN_VERSION_TEMPLATE({
                            version: version,
                            humanName: humanName
                        });

                        firmwareListing.push(
                            {
                                version: version,
                                latest: false,
                                humanVersion: humanVersion,
                                url: targetURL
                            }
                        );
                        match = FIRMWARE_LINK_REGEX.exec(body);
                    }

                    // TODO: Display betas at lowest
                    var numFirmwares = firmwareListing.length;
                    var highestFirmware = firmwareListing[0];
                    for (var i=1; i<numFirmwares; i++) {
                        if (highestFirmware.version < firmwareListing[i].version)
                            highestFirmware = firmwareListing[i];
                    }

                    if (hasLatest)
                        highestFirmware.latest = true;

                    overallFirmwareListing = overallFirmwareListing.concat(
                        firmwareListing
                    );
                    innerDeferred.resolve(overallFirmwareListing);
                }
            );

            return innerDeferred.promise;
        };
    };

    var futures = [
        innerRequest(FIRMWARE_LISTING_URL, 'current', true),
        innerRequest(BETA_LISTING_URL, 'beta', false),
        innerRequest(OLD_LISTING_URL, 'old', false)
    ];

    var finalPromise = futures.reduce(
        function (lastPromise, currentPromise) {
            if (lastPromise === null)
                return currentPromise([]);
            else
                return lastPromise.then(currentPromise);
        },
        null
    );

    finalPromise.then(function (firmwareListing) {
        if (firmwareListing.length === 0)
            nicerOnError();
        else
            $('#internet-error-list').remove();
        onSuccess(firmwareListing);
    })
}

/**
 * Handler for selecting / unselecting devices for updating.
 *
 * Handler for checkboxes that select / unselect devices for updating. If no
 * devices are selected, the configuration pane / updater pane is hidden.
**/
function onChangeSelectedDevices()
{
    var selectedCheckboxes = $('.device-selection-checkbox:checked');
    if(selectedCheckboxes.length === 0) {
        selectedSerials = [];
        $('#device-configuration-pane').fadeOut();
    }
    else {
        selectedSerials = [];
        selectedCheckboxes.each(function (index, item)  {
            selectedSerials.push($(item).attr('id'));
        });
        $('#device-configuration-pane').fadeIn();
    }
}

/**
 * Handler for when a firmware version is selected.
 *
 * Handler for when a firmware version is selected. Updates the dropdown menu
 * that allows the user to select a firmware.
 *
 * @param {Object} event The jQuery event information.
**/
function onFirmwareLinkSelect(event)
{
    var firmwareDisplayStr;

    var version = event.target.id.replace('-selector', '');

    if(event.target.getAttribute('latest') === 'true')
        firmwareDisplayStr = version + ' (latest)';
    else
        firmwareDisplayStr = version;

    $('#selected-firmware').html('version ' + firmwareDisplayStr);
    $('#selected-firmware').attr('selected-version', version);
    $('#selected-firmware').attr('remote', $(event.target).attr('remote'));
}

/**
 * Populate the firmware options dropdown menu.
 *
 * Populate the firmware options dropdown menu, making the first firmware marked
 * as "latest" as the default choice.
 *
 * @param {Array} firmwareInfo An Array of Object with firmware version
 *      information.
**/
function displayFirmwareListing(firmwareInfo)
{
    var latestFirmwares = firmwareInfo.filter(function(e){ return e.latest; });
    var latestFirmware = latestFirmwares[0];

    $('#selected-firmware').html(
        'version ' + latestFirmware.version + ' (latest)'
    );
    $('#selected-firmware').attr('selected-version', latestFirmware.version);
    $('#selected-firmware').attr('remote', latestFirmware.url);

    var location = fs_facade.getExternalURI(FIRMWARE_LISTING_SRC);
    fs_facade.renderTemplate(
        location,
        {'firmwares': firmwareInfo},
        showAlert,
        function(renderedHTML)
        {
            $(FIRMWARE_LIST_SELECTOR).html(renderedHTML);
            $('.firmware-selection-link').click(onFirmwareLinkSelect);

            $('#web-load-waiting-indicator').hide();
            $('#firmware-select').fadeIn();
        }
    );
}

/**
 * Disable old-firmware checking
**/
var disableOldFirmwareCheck = function(bundle) {
    var deferred = q.defer();
    device_controller.ljm_driver.writeLibrary(
        "LJM_OLD_FIRMWARE_CHECK",           // Parameter
        0,                                  // Value
        function() {                        // onError
            console.log('Error Disabling Firmware Check');
            deferred.resolve(bundle);
        },
        function() {                        // onSuccess
            console.log('Successfully Disabled Firmware Check');
            deferred.resolve(bundle);
        }
    );
    return deferred.promise;
}
/**
 * Enable old-firmware checking
**/
var enableOldFirmwareCheck = function(bundle) {
    var deferred = q.defer();
    device_controller.ljm_driver.writeLibrary(
        "LJM_OLD_FIRMWARE_CHECK",           // Parameter
        1,                                  // Value
        function() {                        // onError
            console.log('Error Disabling Firmware Check');
            deferred.resolve(bundle);
        },
        function() {                        // onSuccess
            console.log('Successfully Disabled Firmware Check');
            deferred.resolve(bundle);
        }
    );
    return deferred.promise;
}

/**
 * Routine to update the firmware on the selected devices.
 *
 * Routine to update the firmware on the devices selected within the device
 * keeper.
 *
 * @param {String} firmwareFileLocation The location of the firmware file to use
 *      to update this device. If this location starts with "http://", the file
 *      will be downloaded from the Internet.
**/
function updateFirmware (firmwareFileLocation) {
    $('.firmware-source-option').slideUp();
    $('#working-status-pane').slideDown();

    var keeper = device_controller.getDeviceKeeper();

    var ProgressListener = function () {

        this.update = function (value, callback) {
            $('#device-upgrade-progress-indicator-bar').css(
                {'width': value.toString() + '%'}
            );
            if (callback !== undefined)
                callback();
        };

        this.displayStatusText = function (value, callback) {
            $('#device-upgrade-progress-status').html(value);
            if (callback !== undefined)
                callback();
        };

        this.update(0);
    };

    $('#total-devices-display').html(selectedSerials.length);
    $('#complete-devices-display').html(0);

    var numUpgraded = 0;
    async.each(
        selectedSerials,
        function (serial, callback) {
            console.log('reported serial',serial);
            console.log('typeof',typeof(serial));
            serial = serial.split('-selector')[0];
            var device = keeper.getDevice(serial);
            var connectionType = device.getConnectionTypeStr();
            var progressListener = new ProgressListener();

            var runUpgrade = function () {
                labjack_t7_upgrade.updateFirmware(
                    device.device,
                    firmwareFileLocation,
                    connectionType,
                    progressListener
                ).then(
                    function (bundle) {
                        var firmwareDisplaySelector = '#';
                        firmwareDisplaySelector += serial.toString();
                        firmwareDisplaySelector += '-firmware-display';
                        device.device = bundle.getDevice();
                        console.log(device.device);
                        device.invalidateCache();
                        numUpgraded++;
                        $(firmwareDisplaySelector).html(
                            bundle.getFirmwareVersion()
                        );
                        $('#complete-devices-display').html(numUpgraded);
                        callback(null);
                    },
                    function (err) {
                        callback(err);
                    }
                );
            };

            try {
                if (DISABLE_WIFI_POWER && device.getConnectionTypeStr() !== "LJM_ctWIFI" && device.read('POWER_WIFI') != 0) {
                    try{
                        device.write('POWER_WIFI', 0);
                        device.write('POWER_WIFI_DEFAULT', 0);
                    } catch(err) {

                    }
                    setTimeout(runUpgrade, 3000);
                } else {
                    runUpgrade();
                }
            } catch (e) {
                if(e.message == 1307) {
                    callback(e.message);
                } else {
                    callback(
                        'Configuring WIFI failed. Please try upgrading again.'+e.toString()
                    );
                }
            }

        },
        function (err) {
            if (err) {
                var errMsg;
                // Check for wifi-error
                if (err == 2358) {
                    $('#flash-notice').slideDown();
                    setTimeout(
                        function () {
                            $('#flash-notice').slideUp();
                            updateFirmware(firmwareFileLocation);
                        },
                        3000
                    );
                    return;
                }
                // Check for old-firmware error
                if (err == 1307) {
                    console.log('Updating device w/ old firmware');
                    // disableOldFirmwareCheck()
                    // .then(function() {
                    //     updateFirmware(firmwareFileLocation);
                    // },
                    // function() {
                    //     console.log('Issues disabling oldFirmwareCheck')
                    // })
                    DISABLE_WIFI_POWER = false;
                    updateFirmware(firmwareFileLocation);
                    return;
                }

                if (err.retError === undefined) {
                    errMsg = err.toString();
                } else  {
                    errMsg = err.retError.toString();
                }
                console.log('Error..... bleh',err);
                showAlert(
                    'Failed to update device firmware. Please try ' +
                    'again. If the problem persists, please contact ' +
                    'support@labjack.com. Error: ' + errMsg
                );
            } else {
                DISABLE_WIFI_POWER = true;
            }
            $('.firmware-source-option').slideDown();
            $('#working-status-pane').slideUp();
        }
    );
}

/**
 * Initialization logic for the devie update module.
**/
$('#network-configuration').ready(function(){
    var keeper = device_controller.getDeviceKeeper();
    var devices = keeper.getDevices();

    var decoratedDevices = devices.map(function(device) {
        return new UpgradeableDeviceAdapter(device);
    });

    selectedSerials = decoratedDevices.map(
        function (e) { return e.getSerial(); }
    );

    var location = fs_facade.getExternalURI(DEVICE_SELECTOR_SRC);
    fs_facade.renderTemplate(
        location,
        {
            'devices': decoratedDevices,
            'hasMultipleDevices': decoratedDevices.length > 1
        },
        genericErrorHandler,
        function(renderedHTML)
        {
            $(DEVICE_SELECTOR_PANE_SELECTOR).html(renderedHTML);
            $('.device-selection-checkbox').click(onChangeSelectedDevices);
        }
    );

    $('#browse-link').click(function () {
        var chooser = $('#file-dialog-hidden');
        chooser.change(function(evt) {
            var fileLoc = $(this).val();
            $('#file-loc-input').val(fileLoc);
        });

        chooser.trigger('click');
        return false;
    });

    $('#local-update-button').click(function () {
        updateFirmware($('#file-loc-input').val());
        return false;
    });

    $('#web-update-button').click(function () {
        updateFirmware($('#selected-firmware').attr('remote'));
        return false;
    });

    getAvailableFirmwareListing(genericErrorHandler, displayFirmwareListing);
});
<commit_msg>Possible fix for cannot read firmwares from site.<commit_after>/**
 * Logic for the device updater module for LabJack Swichboard.
 *
 * @author A. Samuel Pottinger (LabJack Corp, 2013)
**/

var BASE_FIRMWARE_LISTING_URL = 'http://www.labjack.com/support/firmware/t7';
var FIRMWARE_LISTING_URL = BASE_FIRMWARE_LISTING_URL;
var BETA_LISTING_URL = BASE_FIRMWARE_LISTING_URL+'/beta';
var OLD_LISTING_URL = BASE_FIRMWARE_LISTING_URL+'/old';
var DEVICE_SELECTOR_SRC = 'device_updater/device_selector.html';
var FIRMWARE_LISTING_SRC = 'device_updater/firmware_listing.html';
var DEVICE_SELECTOR_PANE_SELECTOR = '#device-overview';
var FIRMWARE_LIST_SELECTOR = '#firmware-list';
var FIRMWARE_LINK_REGEX = /href\=\".*T7firmware\_([\d\-]+)\_([\d\-]+)\.bin"/g;
var NUM_UPGRADE_STEPS = 4.0;
var COULD_NOT_PARSE_MSG = 'Could not find firmwares on labjack.com';

var async = require('async');
var handlebars = require('handlebars');
var q = require('q');
var request = require('request');

var labjack_t7_upgrade = require('./labjack_t7_upgrade');

var selectedSerials = [];

var DISABLE_WIFI_POWER = true;

var ERROR_TEMPLATE = handlebars.compile(
    '
Could not read {{ . }} registers
'
);

var HUMAN_VERSION_TEMPLATE = handlebars.compile(
    '{{ version }} ({{ humanName }})'
);

/**
 * A wrapper around a device to make device update operations easier.
 *
 * @param {Objct} device The device to adapt.
**/
function UpgradeableDeviceAdapter(device)
{
    var executeErrorSafeFunction = function (target) {
        try {
            return target();
        } catch (e) {
            var errMsg;

            if (e.retError === undefined) {
                errMsg = e.toString();
            } else {
                errMsg = e.retError.toString();
            }

            showAlert('Failed to read device info: ' + errMsg);
            return '[unavailable]';
        }
    };

    /**
     * Get the serial number of the device that is this decorator encapsulates.
     *
     * @return {Number} The serial number of the inner device.
    **/
    this.getSerial = function()
    {
        return executeErrorSafeFunction(device.getSerial);
    };

    /**
     * Get the name of the device that this decorator encapsulates.
     *
     * @return {String} The name of the inner device.
    **/
    this.getName = function()
    {
        return device.getName();
    };

    /**
     * Get the type of device that this decorator encapsulates.
     *
     * @return {String} The string description of the model of the device that
     *      this decorator encapsulates.
    **/
    this.getDeviceType = function()
    {
        return executeErrorSafeFunction(device.getDeviceType);
    };

    /**
     * Get the version of the firmware currently loaded on the given device.
     *
     * @return {Number} The version of the firmware on this decorator's
     *      encapsulated device.
    **/
    this.getFirmwareVersion = function()
    {
        var formattedCall = function () {
            return device.getFirmwareVersion().toFixed(4);
        };
        return executeErrorSafeFunction(formattedCall);
    };

    /**
     * Get the version of the bootloader currently loaded on the given device.
     *
     * @return {Number} The version of the bootloader on this decorator's
     *      encapsulated device.
    **/
    this.getBootloaderVersion = function()
    {
        var formattedCall = function () {
            return device.getBootloaderVersion().toFixed(4);
        };
        return executeErrorSafeFunction(formattedCall);
    };

    this.getConnectionTypeStr = function () {
        return device.getConnectionTypeStr();
    };
}

/**
 * Download a list of available firmware versions.
 *
 * @param {function} onError The function to call if an error is encountered
 *      while downloading the firmware versions.
 * @param {function} onSuccess The function to call after the firmware version
 *      listing has been downloaded.
**/
function getAvailableFirmwareListing(onError, onSuccess)
{
    var nicerOnError = function (display) {
        $('#web-load-waiting-indicator').slideUp();
        $('#no-internet-message').show();
        $('#no-internet-message').hide();
        $('#no-internet-message').slideDown();
        $('#internet-controls').html(COULD_NOT_PARSE_MSG);
    };

    var innerRequest = function (url, humanName, hasLatest) {
        return function (overallFirmwareListing) {
            var innerDeferred = q.defer();
            request(
                url,
                function (error, response, body) {
                    if (error || response.statusCode != 200) {
                        $('#internet-error-list').append(
                            ERROR_TEMPLATE(humanName)
                        );
                        innerDeferred.resolve(overallFirmwareListing);
                        return;
                    }

                    var firmwareListing = [];
                    var match = FIRMWARE_LINK_REGEX.exec(body);
                    var targetURL = match[0].replace(/href\=\"/g, '');
                    targetURL = targetURL.replace(/\"/g, '');

                    while (match !== null) {
                        var version = (parseFloat(match[1])/10000).toFixed(4);
                        var humanVersion = HUMAN_VERSION_TEMPLATE({
                            version: version,
                            humanName: humanName
                        });

                        firmwareListing.push(
                            {
                                version: version,
                                latest: false,
                                humanVersion: humanVersion,
                                url: targetURL
                            }
                        );
                        match = FIRMWARE_LINK_REGEX.exec(body);
                    }

                    var numFirmwares = firmwareListing.length;
                    if (numFirmwares == 0) {
                        innerDeferred.resolve(overallFirmwareListing);
                        return;
                    }

                    var highestFirmware = firmwareListing[0];
                    for (var i=1; i<numFirmwares; i++) {
                        if (highestFirmware.version < firmwareListing[i].version)
                            highestFirmware = firmwareListing[i];
                    }

                    if (hasLatest)
                        highestFirmware.latest = true;

                    overallFirmwareListing = overallFirmwareListing.concat(
                        firmwareListing
                    );
                    innerDeferred.resolve(overallFirmwareListing);
                }
            );

            return innerDeferred.promise;
        };
    };

    var futures = [
        innerRequest(FIRMWARE_LISTING_URL, 'current', true),
        innerRequest(BETA_LISTING_URL, 'beta', false),
        innerRequest(OLD_LISTING_URL, 'old', false)
    ];

    var finalPromise = futures.reduce(
        function (lastPromise, currentPromise) {
            if (lastPromise === null)
                return currentPromise([]);
            else
                return lastPromise.then(currentPromise);
        },
        null
    );

    finalPromise.then(function (firmwareListing) {
        if (firmwareListing.length === 0)
            nicerOnError();
        else
            $('#internet-error-list').remove();
        onSuccess(firmwareListing);
    })
}

/**
 * Handler for selecting / unselecting devices for updating.
 *
 * Handler for checkboxes that select / unselect devices for updating. If no
 * devices are selected, the configuration pane / updater pane is hidden.
**/
function onChangeSelectedDevices()
{
    var selectedCheckboxes = $('.device-selection-checkbox:checked');
    if(selectedCheckboxes.length === 0) {
        selectedSerials = [];
        $('#device-configuration-pane').fadeOut();
    }
    else {
        selectedSerials = [];
        selectedCheckboxes.each(function (index, item)  {
            selectedSerials.push($(item).attr('id'));
        });
        $('#device-configuration-pane').fadeIn();
    }
}

/**
 * Handler for when a firmware version is selected.
 *
 * Handler for when a firmware version is selected. Updates the dropdown menu
 * that allows the user to select a firmware.
 *
 * @param {Object} event The jQuery event information.
**/
function onFirmwareLinkSelect(event)
{
    var firmwareDisplayStr;

    var version = event.target.id.replace('-selector', '');

    if(event.target.getAttribute('latest') === 'true')
        firmwareDisplayStr = version + ' (latest)';
    else
        firmwareDisplayStr = version;

    $('#selected-firmware').html('version ' + firmwareDisplayStr);
    $('#selected-firmware').attr('selected-version', version);
    $('#selected-firmware').attr('remote', $(event.target).attr('remote'));
}

/**
 * Populate the firmware options dropdown menu.
 *
 * Populate the firmware options dropdown menu, making the first firmware marked
 * as "latest" as the default choice.
 *
 * @param {Array} firmwareInfo An Array of Object with firmware version
 *      information.
**/
function displayFirmwareListing(firmwareInfo)
{
    var latestFirmwares = firmwareInfo.filter(function(e){ return e.latest; });
    var latestFirmware = latestFirmwares[0];

    $('#selected-firmware').html(
        'version ' + latestFirmware.version + ' (latest)'
    );
    $('#selected-firmware').attr('selected-version', latestFirmware.version);
    $('#selected-firmware').attr('remote', latestFirmware.url);

    var location = fs_facade.getExternalURI(FIRMWARE_LISTING_SRC);
    fs_facade.renderTemplate(
        location,
        {'firmwares': firmwareInfo},
        showAlert,
        function(renderedHTML)
        {
            $(FIRMWARE_LIST_SELECTOR).html(renderedHTML);
            $('.firmware-selection-link').click(onFirmwareLinkSelect);

            $('#web-load-waiting-indicator').hide();
            $('#firmware-select').fadeIn();
        }
    );
}

/**
 * Disable old-firmware checking
**/
var disableOldFirmwareCheck = function(bundle) {
    var deferred = q.defer();
    device_controller.ljm_driver.writeLibrary(
        "LJM_OLD_FIRMWARE_CHECK",           // Parameter
        0,                                  // Value
        function() {                        // onError
            console.log('Error Disabling Firmware Check');
            deferred.resolve(bundle);
        },
        function() {                        // onSuccess
            console.log('Successfully Disabled Firmware Check');
            deferred.resolve(bundle);
        }
    );
    return deferred.promise;
}
/**
 * Enable old-firmware checking
**/
var enableOldFirmwareCheck = function(bundle) {
    var deferred = q.defer();
    device_controller.ljm_driver.writeLibrary(
        "LJM_OLD_FIRMWARE_CHECK",           // Parameter
        1,                                  // Value
        function() {                        // onError
            console.log('Error Disabling Firmware Check');
            deferred.resolve(bundle);
        },
        function() {                        // onSuccess
            console.log('Successfully Disabled Firmware Check');
            deferred.resolve(bundle);
        }
    );
    return deferred.promise;
}

/**
 * Routine to update the firmware on the selected devices.
 *
 * Routine to update the firmware on the devices selected within the device
 * keeper.
 *
 * @param {String} firmwareFileLocation The location of the firmware file to use
 *      to update this device. If this location starts with "http://", the file
 *      will be downloaded from the Internet.
**/
function updateFirmware (firmwareFileLocation) {
    $('.firmware-source-option').slideUp();
    $('#working-status-pane').slideDown();

    var keeper = device_controller.getDeviceKeeper();

    var ProgressListener = function () {

        this.update = function (value, callback) {
            $('#device-upgrade-progress-indicator-bar').css(
                {'width': value.toString() + '%'}
            );
            if (callback !== undefined)
                callback();
        };

        this.displayStatusText = function (value, callback) {
            $('#device-upgrade-progress-status').html(value);
            if (callback !== undefined)
                callback();
        };

        this.update(0);
    };

    $('#total-devices-display').html(selectedSerials.length);
    $('#complete-devices-display').html(0);

    var numUpgraded = 0;
    async.each(
        selectedSerials,
        function (serial, callback) {
            console.log('reported serial',serial);
            console.log('typeof',typeof(serial));
            serial = serial.split('-selector')[0];
            var device = keeper.getDevice(serial);
            var connectionType = device.getConnectionTypeStr();
            var progressListener = new ProgressListener();

            var runUpgrade = function () {
                labjack_t7_upgrade.updateFirmware(
                    device.device,
                    firmwareFileLocation,
                    connectionType,
                    progressListener
                ).then(
                    function (bundle) {
                        var firmwareDisplaySelector = '#';
                        firmwareDisplaySelector += serial.toString();
                        firmwareDisplaySelector += '-firmware-display';
                        device.device = bundle.getDevice();
                        console.log(device.device);
                        device.invalidateCache();
                        numUpgraded++;
                        $(firmwareDisplaySelector).html(
                            bundle.getFirmwareVersion()
                        );
                        $('#complete-devices-display').html(numUpgraded);
                        callback(null);
                    },
                    function (err) {
                        callback(err);
                    }
                );
            };

            try {
                if (DISABLE_WIFI_POWER && device.getConnectionTypeStr() !== "LJM_ctWIFI" && device.read('POWER_WIFI') != 0) {
                    try{
                        device.write('POWER_WIFI', 0);
                        device.write('POWER_WIFI_DEFAULT', 0);
                    } catch(err) {

                    }
                    setTimeout(runUpgrade, 3000);
                } else {
                    runUpgrade();
                }
            } catch (e) {
                if(e.message == 1307) {
                    callback(e.message);
                } else {
                    callback(
                        'Configuring WIFI failed. Please try upgrading again.'+e.toString()
                    );
                }
            }

        },
        function (err) {
            if (err) {
                var errMsg;
                // Check for wifi-error
                if (err == 2358) {
                    $('#flash-notice').slideDown();
                    setTimeout(
                        function () {
                            $('#flash-notice').slideUp();
                            updateFirmware(firmwareFileLocation);
                        },
                        3000
                    );
                    return;
                }
                // Check for old-firmware error
                if (err == 1307) {
                    console.log('Updating device w/ old firmware');
                    // disableOldFirmwareCheck()
                    // .then(function() {
                    //     updateFirmware(firmwareFileLocation);
                    // },
                    // function() {
                    //     console.log('Issues disabling oldFirmwareCheck')
                    // })
                    DISABLE_WIFI_POWER = false;
                    updateFirmware(firmwareFileLocation);
                    return;
                }

                if (err.retError === undefined) {
                    errMsg = err.toString();
                } else  {
                    errMsg = err.retError.toString();
                }
                console.log('Error..... bleh',err);
                showAlert(
                    'Failed to update device firmware. Please try ' +
                    'again. If the problem persists, please contact ' +
                    'support@labjack.com. Error: ' + errMsg
                );
            } else {
                DISABLE_WIFI_POWER = true;
            }
            $('.firmware-source-option').slideDown();
            $('#working-status-pane').slideUp();
        }
    );
}

/**
 * Initialization logic for the devie update module.
**/
$('#network-configuration').ready(function(){
    var keeper = device_controller.getDeviceKeeper();
    var devices = keeper.getDevices();

    var decoratedDevices = devices.map(function(device) {
        return new UpgradeableDeviceAdapter(device);
    });

    selectedSerials = decoratedDevices.map(
        function (e) { return e.getSerial(); }
    );

    var location = fs_facade.getExternalURI(DEVICE_SELECTOR_SRC);
    fs_facade.renderTemplate(
        location,
        {
            'devices': decoratedDevices,
            'hasMultipleDevices': decoratedDevices.length > 1
        },
        genericErrorHandler,
        function(renderedHTML)
        {
            $(DEVICE_SELECTOR_PANE_SELECTOR).html(renderedHTML);
            $('.device-selection-checkbox').click(onChangeSelectedDevices);
        }
    );

    $('#browse-link').click(function () {
        var chooser = $('#file-dialog-hidden');
        chooser.change(function(evt) {
            var fileLoc = $(this).val();
            $('#file-loc-input').val(fileLoc);
        });

        chooser.trigger('click');
        return false;
    });

    $('#local-update-button').click(function () {
        updateFirmware($('#file-loc-input').val());
        return false;
    });

    $('#web-update-button').click(function () {
        updateFirmware($('#selected-firmware').attr('remote'));
        return false;
    });

    getAvailableFirmwareListing(genericErrorHandler, displayFirmwareListing);
});
<|endoftext|>


<commit_before>// The login view

var LoginView = Backbone.Marionette.ItemView.extend({
    template: require('../../templates/login.html'),

    events: {
        'click button': 'login'
    },

    login: function(ev) {
        var self  = this;
        var radio = Backbone.Wreqr.radio.channel('global');
        var data = {};
        $.each(self.$el.find('form.login_form').serializeArray(), function() { data[this.name] = this.value; });
        radio.vent.trigger('login', data);
    }
});

module.exports = LoginView;<commit_msg>login form now submits when enter key is pressed<commit_after>// The login view

var LoginView = Backbone.Marionette.ItemView.extend({
    template: require('../../templates/login.html'),

    events: {
        'click button': 'login',
        'keyup input': 'loginEnter'
    },

    loginEnter: function(ev) {
        var self = this;
        var keyCode = ev.keyCode || ev.which;
        if (keyCode == '13'){
            self.login(ev);
        }
    },

    login: function(ev) {
        var self  = this;
        var radio = Backbone.Wreqr.radio.channel('global');
        var data = {};
        $.each(self.$el.find('form.login_form').serializeArray(), function() { data[this.name] = this.value; });
        radio.vent.trigger('login', data);
    }
});

module.exports = LoginView;
<|endoftext|>


<commit_before>const path = require('path')
const express = require('express')
const next = require('next')
const apiHandler = require('./api')

const dev = process.env.NODE_ENV !== 'production'
const app = next({
  dev,
  dir: path.resolve(__dirname + '/client'),
})
const nextHandler = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.use('/api', apiHandler)
  server.get('*', (req, res) => {
    return nextHandler(req, res)
  })

  server.listen(3001, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})
<commit_msg>change log<commit_after>const path = require('path')
const express = require('express')
const next = require('next')
const apiHandler = require('./api')

const dev = process.env.NODE_ENV !== 'production'
const app = next({
  dev,
  dir: path.resolve(__dirname + '/client'),
})
const nextHandler = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.use('/api', apiHandler)
  server.get('*', (req, res) => {
    return nextHandler(req, res)
  })

  server.listen(3001, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:3001')
  })
})
<|endoftext|>