<commit_before>"use strict";
/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2013, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

(function() {

  window.OSjs   = window.OSjs   || {};
  OSjs.Handlers = OSjs.Handlers || {};

  /////////////////////////////////////////////////////////////////////////////
  // DEFAULT HANDLING CODE
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Storage
   */
  var DefaultStorage = function() {
    if ( !OSjs.Compability.localStorage ) {
      throw "Your browser does not support localStorage :(";
    }
    this.prefix = 'andersevenrud.github.io/OS.js-v2/';
  };

  DefaultStorage.prototype.set = function(k, v) {
    localStorage.setItem(this.prefix + k, JSON.stringify(v));
  };

  DefaultStorage.prototype.get = function(k) {
    var val = localStorage.getItem(this.prefix + k);
    return val ? JSON.parse(val) : null;
  };

  /**
   * Handler
   */
  var DefaultHandler = function() {
    this.storage  = new DefaultStorage();
    this.packages = {};
    this.config   = OSjs.Settings.DefaultConfig();
    this.userData = {};
    this.offline  = false;

    var self = this;
    if ( typeof navigator.onLine !== 'undefined' ) {
      window.addEventListener("offline", function(ev) {
        self.onOffline();
      });
      window.addEventListener("online", function(ev) {
        self.onOnline();
      });
    }
  };

  DefaultHandler.prototype.call = function(opts, cok, cerror) {
    if ( this.offline ) {
      cerror("You are currently off-line and cannot perform this operation!");
      return false;
    }

    return OSjs.Utils.Ajax(this.config.Core.APIURI, function(response, httpRequest, url) {
      cok.apply(this, arguments);
    }, function(error, response, httpRequest, url) {
      cerror.apply(this, arguments);
    }, opts);
  };

  //
  // Events
  //

  DefaultHandler.prototype.onOnline = function() {
    console.warn("DefaultHandler::onOnline()", "Going online...");
    this.offline = false;

    var wm = OSjs.API.getWMInstance();
    if ( wm ) {
      wm.notification({title: "Warning!", message: "You are Offline!"});
    }
  };

  DefaultHandler.prototype.onOffline = function() {
    console.warn("DefaultHandler::onOffline()", "Going offline...");
    this.offline = true;

    var wm = OSjs.API.getWMInstance();
    if ( wm ) {
      wm.notification({title: "Warning!", message: "You are On-line!"});
    }
  };

  DefaultHandler.prototype.onInitialized = function() {
  };

  //
  // Main
  //
  DefaultHandler.prototype.init = function(callback) {
    var self      = this;
    var container = document.getElementById('Login');
    var login     = document.getElementById('LoginForm');
    var u         = document.getElementById('LoginUsername');
    var p         = document.getElementById('LoginPassword');
    var s         = document.getElementById('LoginSubmit');

    var _restore = function() {
      s.removeAttribute("disabled");
      u.removeAttribute("disabled");
      p.removeAttribute("disabled");
    };

    var _lock = function() {
      s.setAttribute("disabled", "disabled");
      u.setAttribute("disabled", "disabled");
      p.setAttribute("disabled", "disabled");
    };

    var _login = function(username, password) {
      self.login(username, password, function(result, error) {
        if ( error ) {
          alert(error);
          _restore();
          return;
        }
        self.userData = result;

        container.parentNode.removeChild(container);
        callback();
      });
    };

    /*
    login.onsubmit = function(ev) {
      _lock();
      if ( ev ) ev.preventDefault();
      _login(u.value, p.value);
    };
    */

    OSjs.Locale.setLocale(this.config.Core.Locale);
    _login("demo", "demo");
  };

  DefaultHandler.prototype.boot = function(callback) {
    callback = callback || {};
    var self = this;

    this.pollPackages(function(result, error) {
      if ( error ) {
        callback(false, error);
        return;
      }

      if ( result ) {
        self.packages = result;
        callback(true);
        return;
      }

      callback(false);
    });
  };

  DefaultHandler.prototype.login = function(username, password, callback) {
    if ( username === 'demo' && password === 'demo' ) {
      var userData = {
        id:         1,
        username:   'demo',
        name:       'Demo User',
        groups:     ['demo']
      };

      callback(userData);
      return;
    }
    callback(false, "Invalid login");
  };

  DefaultHandler.prototype.logout = function(session, callback) {
    if ( session !== null ) {
      this.setUserSession(session, function() {
        callback(true);
      });
      return;
    }
    callback(true);
  };

  DefaultHandler.prototype.loadSession = function() {
    var _list = [];

    var onSuccess = function(data, a) {
      var w, r;
      for ( var i = 0, l = data.length; i < l; i++ ) {
        r = data[i];
        w = a._getWindow(r.name);
        if ( w ) {
          w._move(r.position.x, r.position.y);
          w._resize(r.dimension.w, r.dimension.h);

          console.info('DefaultHandler::loadSession()->onSuccess()', 'Restored window "' + r.name + '" from session');
        }
      }

      onNext();
    };

    var onNext = function() {
      if ( _list.length ) {
        var s = _list.pop();
        var sargs = s.args || {};
        if ( typeof sargs.length !== 'undefined' ) { sargs = {}; }

        OSjs.API.launch(s.name, sargs, (function(data) {
          return function(a) {
            onSuccess(data, a);
          };
        })(s.windows), function(err) {
          console.warn("_loadSession() error", err);
          onNext();
        });
      }
    };

    this.getUserSession(function(res) {
      if ( res ) {
        _list = res;
        onNext();
      }
    });
  };

  DefaultHandler.prototype.pollPackages = function(callback) {
    callback = callback || function() {};

    var uri = this.getConfig('Core').PACKAGEURI;
    return OSjs.Utils.Ajax(uri, function(response, httpRequest, url) {
      if ( response ) {
        callback(response);
      } else {
        callback(false, "No packages found!");
      }
    }, function(error, response, httpRequest) {
      if ( httpRequest && httpRequest.status != 200 ) {
        error = 'Failed to load package manifest from ' + uri + ' - HTTP Error: ' + httpRequest.status;
      }
      callback(false, error);
    }, {method: 'GET', parse: true});
  };

  //
  // Settings / Sessions
  //

  DefaultHandler.prototype.getApplicationsMetadata = function() {
    return this.packages;
  };

  DefaultHandler.prototype.getApplicationNameByMime = function(mime, fname, forceList, callback) {
    var self = this;
    var packages = this.packages;

    var _createList = function() {
      var j, i, a;
      var list = [];
      for ( i in packages ) {
        if ( packages.hasOwnProperty(i) ) {
          a = packages[i];
          if ( a && a.mime ) {
            for ( j = 0; j < a.mime.length; j++ ) {
              if ( (new RegExp(a.mime[j])).test(mime) === true ) {
                list.push(i);
              }
            }
          }
        }
      }

      return list;
    };

    this._getSettings('defaultApplication', mime, function(val) {
      console.debug("OSjs::DefaultHandler::getApplicationNameByMime()", "default application", val);
      if ( !forceList && val ) {
        if ( packages[val] ) {
          callback([val]);
          return;
        }
      }
      callback(_createList());
    });
  };

  DefaultHandler.prototype.setDefaultApplication = function(mime, app, callback) {
    callback = callback || function() {};
    console.debug("OSjs::DefaultHandler::setDefaultApplication()", mime, app);
    this._setSettings('defaultApplication', mime, app, callback);
  };

  DefaultHandler.prototype.getApplicationMetadata = function(name) {
    if ( typeof this.packages[name] !== 'undefined' ) {
      return this.packages[name];
    }
    return false;
  };

  DefaultHandler.prototype._setSetting = function(cat, values, callback) {
    this.storage.set(cat, values);
    callback(true);
  };

  DefaultHandler.prototype._setSettings = function(cat, key, opts, callback) {
    var settings = this.storage.get(cat);
    if ( typeof settings !== 'object' || !settings ) {
      settings = {};
    }
    if ( typeof settings[key] !== 'object' || !settings[key] ) {
      settings[key] = {};
    }
    settings[key] = opts;

    this.storage.set(cat, settings);
    callback(true);
  };

  DefaultHandler.prototype._getSettings = function(cat, key, callback) {
    var s = this.storage.get(cat) || {};
    if ( key === null ) {
      callback(s);
      return;
    } else if ( s[key] ) {
      callback(s[key]);
      return;
    }
    callback(false);
  };

  DefaultHandler.prototype.setUserSettings = function(key, opts, callback) {
    callback = callback || function() {};
    this._setSettings('userSettings', key, opts, callback);
  };

  DefaultHandler.prototype.getUserSettings = function(key, callback) {
    callback = callback || function() {};
    this._getSettings('userSettings', key, callback);
  };

  DefaultHandler.prototype.setApplicationSettings = function(app, settings, callback) {
    callback = callback || function() {};
    this._setSetting(app, settings, callback);
  };

  DefaultHandler.prototype.getApplicationSettings = function(app, callback) {
    callback = callback || function() {};
    this._getSettings(app, null, callback);
  };

  DefaultHandler.prototype.setUserSession = function(session, callback) {
    callback = callback || function() {};
    this.storage.set("userSession", session);
    callback(true);
  };

  DefaultHandler.prototype.getUserSession = function(callback) {
    callback = callback || function() {};
    var s = this.storage.get("userSession");
    callback(s);
  };

  DefaultHandler.prototype.getConfig = function(key) {
    return key ? this.config[key] : this.config;
  };

  DefaultHandler.prototype.getUserConfig = function(key) {
    var cfg = this.config.User || {};
    return key ? cfg[key] : cfg;
  };

  DefaultHandler.prototype.getUserData = function() {
    return this.userData;
  };

  //
  // Resources
  //

  DefaultHandler.prototype.getApplicationResource = function(app, name) {
    var aname = ((app instanceof OSjs.Core.Process)) ? (app.__path || '') : app;
    return '/' + aname + '/' + name;
  };

  DefaultHandler.prototype.getThemeResource = function(name, type, args) {
    name = name || null;
    type = type || null;
    args = args || null;

    if ( name ) {
      var wm = OSjs.API.getWMInstance();
      var theme = (wm ? wm.getSetting('theme') : 'default') || 'default';
      if ( !name.match(/^\//) ) {
        if ( type == 'icon' ) {
          var size = args || '16x16';
          name = '/themes/' + theme + '/icons/' + size + '/' + name;
        } else if ( type == 'sound' ) {
          var ext = 'oga';
          if ( !OSjs.Compability.audioTypes.ogg ) {
            ext = 'mp3';
          }
          name = '/themes/' + theme + '/sounds/' + name + '.' + ext;
        } else if ( type == 'wm' ) {
          name = '/themes/' + theme + '/wm/' + name;
        } else if ( type == 'base' ) {
          name = '/themes/' + theme + '/' + name;
        }
      }
    }

    return name;
  };

  DefaultHandler.prototype.getIcon = function(name, app, args) {
    if ( name.match(/\.\//) ) {
      if ( (app instanceof OSjs.Core.Application) || (typeof app === 'string') ) {
          return OSjs.API.getApplicationResource(app, name);
      } else {
        if ( typeof app === 'object' ) {
          return OSjs.API.getApplicationResource(app.path, name);
        }
      }
    }
    return OSjs.API.getThemeResource(name, 'icon', args);
  };

  DefaultHandler.prototype.getThemeCSS = function(name) {
    if ( name === null ) {
      return '/frontend/blank.css';
    }
    return '/themes/' + name + '.css';
  };

  DefaultHandler.prototype.getResourceURL = function(path) {
    if ( path && path.match(/^\/(themes|frontend|apps)/) ) {
      return path;
    }
    var fsuri = this.getConfig('Core').FSURI;
    return path ? (fsuri + path) : fsuri;
  };

  OSjs.Handlers.Default = DefaultHandler;

})();

<commit_msg>Added some code doc<commit_after>"use strict";
/*!
 * OS.js - JavaScript Operating System
 *
 * Copyright (c) 2011-2013, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

(function() {

  window.OSjs   = window.OSjs   || {};
  OSjs.Handlers = OSjs.Handlers || {};

  /////////////////////////////////////////////////////////////////////////////
  // DEFAULT HANDLING CODE
  /////////////////////////////////////////////////////////////////////////////

  /**
   * Storage
   */
  var DefaultStorage = function() {
    if ( !OSjs.Compability.localStorage ) {
      throw "Your browser does not support localStorage :(";
    }
    this.prefix = 'andersevenrud.github.io/OS.js-v2/';
  };

  DefaultStorage.prototype.set = function(k, v) {
    localStorage.setItem(this.prefix + k, JSON.stringify(v));
  };

  DefaultStorage.prototype.get = function(k) {
    var val = localStorage.getItem(this.prefix + k);
    return val ? JSON.parse(val) : null;
  };

  /**
   * Default Handler Implementation
   *
   * Used for communication, resources, settings and session handling
   *
   * You can implement your own, see documentation on Wiki.
   */
  var DefaultHandler = function() {
    this.storage  = new DefaultStorage();
    this.packages = {};
    this.config   = OSjs.Settings.DefaultConfig();
    this.userData = {};
    this.offline  = false;

    var self = this;
    if ( typeof navigator.onLine !== 'undefined' ) {
      window.addEventListener("offline", function(ev) {
        self.onOffline();
      });
      window.addEventListener("online", function(ev) {
        self.onOnline();
      });
    }
  };

  /**
   * Default method to perform a call to the backend
   */
  DefaultHandler.prototype.call = function(opts, cok, cerror) {
    if ( this.offline ) {
      cerror("You are currently off-line and cannot perform this operation!");
      return false;
    }

    return OSjs.Utils.Ajax(this.config.Core.APIURI, function(response, httpRequest, url) {
      cok.apply(this, arguments);
    }, function(error, response, httpRequest, url) {
      cerror.apply(this, arguments);
    }, opts);
  };

  //
  // Events
  //

  /**
   * Event when browser goes on-line (again)
   */
  DefaultHandler.prototype.onOnline = function() {
    console.warn("DefaultHandler::onOnline()", "Going online...");
    this.offline = false;

    var wm = OSjs.API.getWMInstance();
    if ( wm ) {
      wm.notification({title: "Warning!", message: "You are Offline!"});
    }
  };

  /**
   * Event when browser gies off-line
   */
  DefaultHandler.prototype.onOffline = function() {
    console.warn("DefaultHandler::onOffline()", "Going offline...");
    this.offline = true;

    var wm = OSjs.API.getWMInstance();
    if ( wm ) {
      wm.notification({title: "Warning!", message: "You are On-line!"});
    }
  };

  /**
   * Event when OS.js has successfully initialized
   */
  DefaultHandler.prototype.onInitialized = function() {
  };

  //
  // Main
  //

  /**
   * Called upon window loaded
   */
  DefaultHandler.prototype.init = function(callback) {
    var self      = this;
    var container = document.getElementById('Login');
    var login     = document.getElementById('LoginForm');
    var u         = document.getElementById('LoginUsername');
    var p         = document.getElementById('LoginPassword');
    var s         = document.getElementById('LoginSubmit');

    var _restore = function() {
      s.removeAttribute("disabled");
      u.removeAttribute("disabled");
      p.removeAttribute("disabled");
    };

    var _lock = function() {
      s.setAttribute("disabled", "disabled");
      u.setAttribute("disabled", "disabled");
      p.setAttribute("disabled", "disabled");
    };

    var _login = function(username, password) {
      self.login(username, password, function(result, error) {
        if ( error ) {
          alert(error);
          _restore();
          return;
        }
        self.userData = result;

        container.parentNode.removeChild(container);
        callback();
      });
    };

    /*
    login.onsubmit = function(ev) {
      _lock();
      if ( ev ) ev.preventDefault();
      _login(u.value, p.value);
    };
    */

    OSjs.Locale.setLocale(this.config.Core.Locale);
    _login("demo", "demo");
  };

  /**
   * Called after successfull login
   */
  DefaultHandler.prototype.boot = function(callback) {
    callback = callback || {};
    var self = this;

    this.pollPackages(function(result, error) {
      if ( error ) {
        callback(false, error);
        return;
      }

      if ( result ) {
        self.packages = result;
        callback(true);
        return;
      }

      callback(false);
    });
  };

  /**
   * Default login method
   */
  DefaultHandler.prototype.login = function(username, password, callback) {
    if ( username === 'demo' && password === 'demo' ) {
      var userData = {
        id:         1,
        username:   'demo',
        name:       'Demo User',
        groups:     ['demo']
      };

      callback(userData);
      return;
    }
    callback(false, "Invalid login");
  };

  /**
   * Default logout method
   */
  DefaultHandler.prototype.logout = function(session, callback) {
    if ( session !== null ) {
      this.setUserSession(session, function() {
        callback(true);
      });
      return;
    }
    callback(true);
  };

  /**
   * Default method to restore last running session
   */
  DefaultHandler.prototype.loadSession = function() {
    var _list = [];

    var onSuccess = function(data, a) {
      var w, r;
      for ( var i = 0, l = data.length; i < l; i++ ) {
        r = data[i];
        w = a._getWindow(r.name);
        if ( w ) {
          w._move(r.position.x, r.position.y);
          w._resize(r.dimension.w, r.dimension.h);

          console.info('DefaultHandler::loadSession()->onSuccess()', 'Restored window "' + r.name + '" from session');
        }
      }

      onNext();
    };

    var onNext = function() {
      if ( _list.length ) {
        var s = _list.pop();
        var sargs = s.args || {};
        if ( typeof sargs.length !== 'undefined' ) { sargs = {}; }

        OSjs.API.launch(s.name, sargs, (function(data) {
          return function(a) {
            onSuccess(data, a);
          };
        })(s.windows), function(err) {
          console.warn("_loadSession() error", err);
          onNext();
        });
      }
    };

    this.getUserSession(function(res) {
      if ( res ) {
        _list = res;
        onNext();
      }
    });
  };

  /**
   * Default method to pull package manifest
   */
  DefaultHandler.prototype.pollPackages = function(callback) {
    callback = callback || function() {};

    var uri = this.getConfig('Core').PACKAGEURI;
    return OSjs.Utils.Ajax(uri, function(response, httpRequest, url) {
      if ( response ) {
        callback(response);
      } else {
        callback(false, "No packages found!");
      }
    }, function(error, response, httpRequest) {
      if ( httpRequest && httpRequest.status != 200 ) {
        error = 'Failed to load package manifest from ' + uri + ' - HTTP Error: ' + httpRequest.status;
      }
      callback(false, error);
    }, {method: 'GET', parse: true});
  };

  //
  // Settings / Sessions
  //

  /**
   * Get all package metadata
   */
  DefaultHandler.prototype.getApplicationsMetadata = function() {
    return this.packages;
  };

  /**
   * Get a list of application supporting mime type
   */
  DefaultHandler.prototype.getApplicationNameByMime = function(mime, fname, forceList, callback) {
    var self = this;
    var packages = this.packages;

    var _createList = function() {
      var j, i, a;
      var list = [];
      for ( i in packages ) {
        if ( packages.hasOwnProperty(i) ) {
          a = packages[i];
          if ( a && a.mime ) {
            for ( j = 0; j < a.mime.length; j++ ) {
              if ( (new RegExp(a.mime[j])).test(mime) === true ) {
                list.push(i);
              }
            }
          }
        }
      }

      return list;
    };

    this._getSettings('defaultApplication', mime, function(val) {
      console.debug("OSjs::DefaultHandler::getApplicationNameByMime()", "default application", val);
      if ( !forceList && val ) {
        if ( packages[val] ) {
          callback([val]);
          return;
        }
      }
      callback(_createList());
    });
  };

  /**
   * Set the default application for given mime type
   */
  DefaultHandler.prototype.setDefaultApplication = function(mime, app, callback) {
    callback = callback || function() {};
    console.debug("OSjs::DefaultHandler::setDefaultApplication()", mime, app);
    this._setSettings('defaultApplication', mime, app, callback);
  };

  /**
   * Get metadata for application by class-name
   */
  DefaultHandler.prototype.getApplicationMetadata = function(name) {
    if ( typeof this.packages[name] !== 'undefined' ) {
      return this.packages[name];
    }
    return false;
  };

  /**
   * Internal method for setting a value in category (wrapper)
   */
  DefaultHandler.prototype._setSetting = function(cat, values, callback) {
    this.storage.set(cat, values);
    callback(true);
  };

  /**
   * Internal method for setting settings (wrapper)
   */
  DefaultHandler.prototype._setSettings = function(cat, key, opts, callback) {
    var settings = this.storage.get(cat);
    if ( typeof settings !== 'object' || !settings ) {
      settings = {};
    }
    if ( typeof settings[key] !== 'object' || !settings[key] ) {
      settings[key] = {};
    }
    settings[key] = opts;

    this.storage.set(cat, settings);
    callback(true);
  };

  /**
   * Internal method for getting settings (wrapper)
   */
  DefaultHandler.prototype._getSettings = function(cat, key, callback) {
    var s = this.storage.get(cat) || {};
    if ( key === null ) {
      callback(s);
      return;
    } else if ( s[key] ) {
      callback(s[key]);
      return;
    }
    callback(false);
  };

  /**
   * Set the users settings
   */
  DefaultHandler.prototype.setUserSettings = function(key, opts, callback) {
    callback = callback || function() {};
    this._setSettings('userSettings', key, opts, callback);
  };

  /**
   * Get the users settings
   */
  DefaultHandler.prototype.getUserSettings = function(key, callback) {
    callback = callback || function() {};
    this._getSettings('userSettings', key, callback);
  };

  /**
   * Set settings for an application
   */
  DefaultHandler.prototype.setApplicationSettings = function(app, settings, callback) {
    callback = callback || function() {};
    this._setSetting(app, settings, callback);
  };

  /**
   * Get settings for an application
   */
  DefaultHandler.prototype.getApplicationSettings = function(app, callback) {
    callback = callback || function() {};
    this._getSettings(app, null, callback);
  };

  /**
   * Set user session
   */
  DefaultHandler.prototype.setUserSession = function(session, callback) {
    callback = callback || function() {};
    this.storage.set("userSession", session);
    callback(true);
  };

  /**
   * Get user session
   */
  DefaultHandler.prototype.getUserSession = function(callback) {
    callback = callback || function() {};
    var s = this.storage.get("userSession");
    callback(s);
  };

  /**
   * Get entire configuration
   */
  DefaultHandler.prototype.getConfig = function(key) {
    return key ? this.config[key] : this.config;
  };

  /**
   * Get configuration from logged in user
   */
  DefaultHandler.prototype.getUserConfig = function(key) {
    var cfg = this.config.User || {};
    return key ? cfg[key] : cfg;
  };

  /**
   * Get data for logged in user
   */
  DefaultHandler.prototype.getUserData = function() {
    return this.userData;
  };

  //
  // Resources
  //

  /**
   * Default method for getting a resource from application
   */
  DefaultHandler.prototype.getApplicationResource = function(app, name) {
    var aname = ((app instanceof OSjs.Core.Process)) ? (app.__path || '') : app;
    return '/' + aname + '/' + name;
  };

  /**
   * Default method for getting a resource from theme
   */
  DefaultHandler.prototype.getThemeResource = function(name, type, args) {
    name = name || null;
    type = type || null;
    args = args || null;

    if ( name ) {
      var wm = OSjs.API.getWMInstance();
      var theme = (wm ? wm.getSetting('theme') : 'default') || 'default';
      if ( !name.match(/^\//) ) {
        if ( type == 'icon' ) {
          var size = args || '16x16';
          name = '/themes/' + theme + '/icons/' + size + '/' + name;
        } else if ( type == 'sound' ) {
          var ext = 'oga';
          if ( !OSjs.Compability.audioTypes.ogg ) {
            ext = 'mp3';
          }
          name = '/themes/' + theme + '/sounds/' + name + '.' + ext;
        } else if ( type == 'wm' ) {
          name = '/themes/' + theme + '/wm/' + name;
        } else if ( type == 'base' ) {
          name = '/themes/' + theme + '/' + name;
        }
      }
    }

    return name;
  };

  /**
   * Default method for getting a icon (wrapper for above methods)
   */
  DefaultHandler.prototype.getIcon = function(name, app, args) {
    if ( name.match(/\.\//) ) {
      if ( (app instanceof OSjs.Core.Application) || (typeof app === 'string') ) {
          return OSjs.API.getApplicationResource(app, name);
      } else {
        if ( typeof app === 'object' ) {
          return OSjs.API.getApplicationResource(app.path, name);
        }
      }
    }
    return OSjs.API.getThemeResource(name, 'icon', args);
  };

  /**
   * Default method for getting path to css theme
   */
  DefaultHandler.prototype.getThemeCSS = function(name) {
    if ( name === null ) {
      return '/frontend/blank.css';
    }
    return '/themes/' + name + '.css';
  };

  /**
   * Default method for getting path to a resource
   */
  DefaultHandler.prototype.getResourceURL = function(path) {
    if ( path && path.match(/^\/(themes|frontend|apps)/) ) {
      return path;
    }
    var fsuri = this.getConfig('Core').FSURI;
    return path ? (fsuri + path) : fsuri;
  };

  OSjs.Handlers.Default = DefaultHandler;

})();

<|endoftext|>


<commit_before>$(document).ready(function () {
  $('.button-collapse').sideNav();
  $('.dropdown-button').dropdown();
  $('ul.tabs').tabs();
  $('.collapsible').collapsible();

  $('.slider-carousel').owlCarousel({
    loop: true,
    margin: 10,
    autoplay: true,
    autoplayTimeout: 1000,
    autoplayHoverPause: false,
    dots: false,
    items: 1
  });

  $('.awards-carousel').owlCarousel({
    loop: true,
    margin: 10,
    autoplay: true,
    autoplayTimeout: 1000,
    autoplayHoverPause: false,
    dots: false,
    items: 4
  });

  $('.how-carousel').owlCarousel({
    loop: true,
    margin: 10,
    nav: true,
    navText: ['', ''],
    items: 1
  });

  function showPage(pageName) {
    $('.page-wrapper').hide();
    $('#' + pageName).show();
    $('.nav-link').removeClass('active-link');
    $('.home-main-menu a[href="#!' + pageName + '"]').addClass('active-link');
  }

  var pageLinks = ['explorer', 'certification', 'homepage', 'tools', 'partners', 'feedback', 'faqs', 'events'];

  pageLinks.forEach(function (name) {
    $('a[href="#!' + name + '"]').on('click', function () {
      showPage(name);
    });

    if (window.location.href.substr(-name.length) === name) {
      showPage(name);
    }
  });

  $('select').material_select();

  $('.faq-switch').on('click', function (e) {
    $('#mainContent').fadeOut(300, function () {
      $('#' + $(e.target).data('switch')).fadeIn();
    });
  });

  $('.faq-collapsible-back').on('click', function (e) {
    $(e.target).closest('.faq-collapsible').fadeOut(300, function () {
      $('#mainContent').fadeIn();
    });
  });

  var sidebarToggle = false;
  $('body').on('click', '#hideCourseSidenav', function () {
    sidebarToggle = !sidebarToggle;
    var sidebarWidth = sidebarToggle ? $('.course-accordion').width() : 0;

    $('.course-accordion').toggleClass('hide-sidenav');
    $('.course-card').animate({ 'margin-left': sidebarWidth / 2 + 'px' }, 300);
    $('.course-accordion').animate({ 'margin-left': '-' + sidebarWidth + 'px' }, 300);
  });
});<commit_msg>fix(home page): Update link to images<commit_after>$(document).ready(function () {
  $('.button-collapse').sideNav();
  $('.dropdown-button').dropdown();
  $('ul.tabs').tabs();
  $('.collapsible').collapsible();

  $('.slider-carousel').owlCarousel({
    loop: true,
    margin: 10,
    autoplay: true,
    autoplayTimeout: 5000,
    autoplayHoverPause: false,
    dots: false,
    items: 1
  });

  $('.awards-carousel').owlCarousel({
    loop: true,
    margin: 10,
    autoplay: true,
    autoplayTimeout: 1000,
    autoplayHoverPause: false,
    dots: false,
    items: 4
  });

  $('.how-carousel').owlCarousel({
    loop: true,
    margin: 10,
    nav: true,
    navText: ['', ''],
    items: 1
  });

  function showPage(pageName) {
    $('.page-wrapper').hide();
    $('#' + pageName).show();
    $('.nav-link').removeClass('active-link');
    $('.home-main-menu a[href="#!' + pageName + '"]').addClass('active-link');
  }

  var pageLinks = ['explorer', 'certification', 'homepage', 'tools', 'partners', 'feedback', 'faqs', 'events'];

  pageLinks.forEach(function (name) {
    $('a[href="#!' + name + '"]').on('click', function () {
      showPage(name);
    });

    if (window.location.href.substr(-name.length) === name) {
      showPage(name);
    }
  });

  $('select').material_select();

  $('.faq-switch').on('click', function (e) {
    $('#mainContent').fadeOut(300, function () {
      $('#' + $(e.target).data('switch')).fadeIn();
    });
  });

  $('.faq-collapsible-back').on('click', function (e) {
    $(e.target).closest('.faq-collapsible').fadeOut(300, function () {
      $('#mainContent').fadeIn();
    });
  });

  var sidebarToggle = false;
  $('body').on('click', '#hideCourseSidenav', function () {
    sidebarToggle = !sidebarToggle;
    var sidebarWidth = sidebarToggle ? $('.course-accordion').width() : 0;

    $('.course-accordion').toggleClass('hide-sidenav');
    $('.course-card').animate({ 'margin-left': sidebarWidth / 2 + 'px' }, 300);
    $('.course-accordion').animate({ 'margin-left': '-' + sidebarWidth + 'px' }, 300);
  });
});<|endoftext|>


<commit_before>var socket = io();

if ( ! Detector.webgl ) {

  Detector.addGetWebGLMessage();
  document.getElementById( 'container' ).innerHTML = "";

}

socket.on("msg", function(msg) {
  pointLightL.position.x = msg.x;
  pointLightL.position.y = msg.y;
  pointLightL.position.z = msg.z;

  pointLightR.position.x = msg.x;
  pointLightR.position.y = msg.y;
  pointLightR.position.z = msg.z-1500;

  options.position.x = msg.x;
  options.position.y = msg.y;
  options.position.z = msg.z;
  console.log(msg);
});

var container, stats;
var camera, scene, renderer;
var sphere;
var light;
var pointLightR;
var pointLightL;
var particleSystem;
var tick = 0;
var clock = new THREE.Clock(true);

// options passed during each spawned
var options = {
  position: new THREE.Vector3(),
  positionRandomness: .3,
  velocity: new THREE.Vector3(),
  velocityRandomness: .5,
  color: 0xff99ff,
  colorRandomness: .2,
  turbulence: .05,
  lifetime: 0.9,
  size: 5,
  sizeRandomness: 1
};

var spawnerOptions = {
  spawnRate: 150,
  horizontalSpeed: 1.5,
  verticalSpeed: 1.33,
  timeScale: 1
}

var parameters = {
  width: 2000,
  height: 2000,
  widthSegments: 250,
  heightSegments: 250,
  depth: 1500,
  param: 4,
  filterparam: 1
};

var waterNormals;

init();
animate();

function init() {
  initScene();
  initWater();
  initSkyBox();
  initBoat();
  initFireflies();
  initParticles();
}

function initScene () {
  container = document.createElement( 'div' );
  document.body.appendChild( container );

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
  camera.position.set( 2000, 750, 2000 );

  controls = new THREE.OrbitControls( camera, renderer.domElement );
  controls.enablePan = false;
  controls.minDistance = 1000.0;
  controls.maxDistance = 5000.0;
  controls.maxPolarAngle = Math.PI * 0.495;
  controls.center.set( 0, 500, 0 );

  scene.add( new THREE.AmbientLight( 0x444444 ) );

  light = new THREE.DirectionalLight( 0xffffbb, 1 );
  light.position.set( - 1, 1, - 1 );
  scene.add( light );
}

function initWater () {
  waterNormals = new THREE.ImageUtils.loadTexture( 'img/waternormals.jpg' );
  waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;

  water = new THREE.Water( renderer, camera, scene, {
    textureWidth: 512,
    textureHeight: 512,
    waterNormals: waterNormals,
    alpha: 	1.0,
    sunDirection: light.position.clone().normalize(),
    sunColor: 0xffffff,
    waterColor: 0x001e0f,
    distortionScale: 50.0,
  } );

  mirrorMesh = new THREE.Mesh(
    new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
    water.material
  );

  mirrorMesh.add( water );
  mirrorMesh.rotation.x = - Math.PI * 0.5;
  scene.add( mirrorMesh );
}

function initSkyBox () {
  // load skybox

  var cubeMap = new THREE.CubeTexture( [] );
  cubeMap.format = THREE.RGBFormat;

  var loader = new THREE.ImageLoader();
  loader.load( 'img/skyboxsun25degtest.png', function ( image ) {

    var getSide = function ( x, y ) {

      var size = 1024;

      var canvas = document.createElement( 'canvas' );
      canvas.width = size;
      canvas.height = size;

      var context = canvas.getContext( '2d' );
      context.drawImage( image, - x * size, - y * size );

      return canvas;

    };

    cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
    cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
    cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
    cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
    cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
    cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
    cubeMap.needsUpdate = true;

  } );

  var cubeShader = THREE.ShaderLib[ 'cube' ];
  cubeShader.uniforms[ 'tCube' ].value = cubeMap;

  var skyBoxMaterial = new THREE.ShaderMaterial( {
    fragmentShader: cubeShader.fragmentShader,
    vertexShader: cubeShader.vertexShader,
    uniforms: cubeShader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
  } );

  var skyBox = new THREE.Mesh(
    new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
    skyBoxMaterial
  );

  scene.add( skyBox );
}

function initBoat () {
  var loader = new THREE.STLLoader();
    loader.load( './models/rowing_boat.stl', function ( geometry ) {

      var material = new THREE.MeshPhongMaterial( { color: 0xA52A2A, specular: 0x111111, shininess: 200 } );
      var mesh = new THREE.Mesh( geometry, material );

      mesh.position.set( 0, -120, 0 );
      mesh.rotation.set( - Math.PI / 2, 0, 0 );
      mesh.scale.set( 20.1, 20.1, 20.1 );

      mesh.castShadow = true;
      mesh.receiveShadow = true;

      scene.add( mesh );

    } );
}

function initFireflies () {
  function createLight( color ) {
    var newLight = new THREE.PointLight( color, 1, 30 );
    newLight.castShadow = false;
    newLight.shadowCameraNear = 1;
    newLight.shadowCameraFar = 300000000;
    newLight.shadowCameraVisible = true;
    newLight.shadowMapWidth = 2048;
    newLight.shadowMapHeight = 1024;
    newLight.shadowBias = 0.01;
    newLight.shadowDarkness = 0.5;

    var geometry = new THREE.SphereGeometry( 20, 16, 16 );
    var material = new THREE.MeshBasicMaterial( { color: color } );
    var sphere = new THREE.Mesh( geometry, material );
    newLight.add( sphere );

    return newLight
  }
  pointLightL = createLight( 0xaa0000 );
  scene.add( pointLightL );

  pointLightR = createLight( 0x0000aa );
  scene.add( pointLightR );
}

function animate() {

  requestAnimationFrame( animate );
  render();

}

function initParticles () {
  particleSystem = new THREE.GPUParticleSystem({
    maxParticles: 2500
  });
  scene.add( particleSystem);

}

function render() {

  var time = performance.now() * 0.001;

  var delta = clock.getDelta() * spawnerOptions.timeScale;
  tick += delta;

  if (tick < 0) tick = 0;

  if (delta > 0) {
    particleSystem.spawnParticle(options);
  }

  particleSystem.update(tick);

  water.material.uniforms.time.value += 1.0 / 60.0;
  controls.update();
  water.render();
  renderer.render( scene, camera );

}
<commit_msg>Nice particles<commit_after>var socket = io();

if ( ! Detector.webgl ) {

  Detector.addGetWebGLMessage();
  document.getElementById( 'container' ).innerHTML = "";

}

socket.on("msg", function(msg) {
  pointLightL.position.x = msg.x;
  pointLightL.position.y = msg.y;
  pointLightL.position.z = msg.z;

  pointLightR.position.x = msg.x;
  pointLightR.position.y = msg.y;
  pointLightR.position.z = msg.z-1500;

  particlesL.position.x = msg.x;
  particlesL.position.y = msg.y;
  particlesL.position.z = msg.z;

  particlesR.position.x = msg.x;
  particlesR.position.y = msg.y;
  particlesR.position.z = msg.z-1500;
});

var container, stats;
var camera, scene, renderer;
var sphere;
var light;
var pointLightR;
var pointLightL;
var particleSystem;
var tick = 0;
var clock = new THREE.Clock(true);

// particlesL passed during each spawned
var particlesL = {
  position: new THREE.Vector3(),
  positionRandomness: .3,
  velocity: new THREE.Vector3(),
  velocityRandomness: .5,
  color: 0xff99ff,
  colorRandomness: .5,
  turbulence: .5,
  lifetime: 2,
  size: 2,
  sizeRandomness: 2
};
var particlesR = {
  position: new THREE.Vector3(),
  positionRandomness: .3,
  velocity: new THREE.Vector3(),
  velocityRandomness: .5,
  color: 0xff99ff,
  colorRandomness: .5,
  turbulence: .5,
  lifetime: 2,
  size: 2,
  sizeRandomness: 2
};

var spawnerparticlesL = {
  spawnRate: 1,
  horizontalSpeed: 1.5,
  verticalSpeed: 1.33,
  timeScale: 1
}

var parameters = {
  width: 2000,
  height: 2000,
  widthSegments: 250,
  heightSegments: 250,
  depth: 1500,
  param: 4,
  filterparam: 1
};

var waterNormals;

init();
animate();

function init() {
  initScene();
  initWater();
  initSkyBox();
  initBoat();
  initFireflies();
  initParticles();
}

function initScene () {
  container = document.createElement( 'div' );
  document.body.appendChild( container );

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderer.shadowMap.enabled = true;
	renderer.shadowMap.type = THREE.BasicShadowMap;
  container.appendChild( renderer.domElement );

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.5, 3000000 );
  camera.position.set( 1000, 750, 1000 );

  controls = new THREE.OrbitControls( camera, renderer.domElement );
  controls.enablePan = false;
  controls.minDistance = 1000.0;
  controls.maxDistance = 5000.0;
  controls.maxPolarAngle = Math.PI * 0.495;
  controls.center.set( 0, 500, 0 );

  scene.add( new THREE.AmbientLight( 0x444444 ) );

  light = new THREE.DirectionalLight( 0xffffbb, 1 );
  light.position.set( - 1, 1, - 1 );
  scene.add( light );
}

function initWater () {
  waterNormals = new THREE.ImageUtils.loadTexture( 'img/waternormals.jpg' );
  waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;

  water = new THREE.Water( renderer, camera, scene, {
    textureWidth: 512,
    textureHeight: 512,
    waterNormals: waterNormals,
    alpha: 	1.0,
    sunDirection: light.position.clone().normalize(),
    sunColor: 0xffffff,
    waterColor: 0x001e0f,
    distortionScale: 50.0,
  } );

  mirrorMesh = new THREE.Mesh(
    new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
    water.material
  );

  mirrorMesh.add( water );
  mirrorMesh.rotation.x = - Math.PI * 0.5;
  scene.add( mirrorMesh );
}

function initSkyBox () {
  // load skybox

  var cubeMap = new THREE.CubeTexture( [] );
  cubeMap.format = THREE.RGBFormat;

  var loader = new THREE.ImageLoader();
  loader.load( 'img/skyboxsun25degtest.png', function ( image ) {

    var getSide = function ( x, y ) {

      var size = 1024;

      var canvas = document.createElement( 'canvas' );
      canvas.width = size;
      canvas.height = size;

      var context = canvas.getContext( '2d' );
      context.drawImage( image, - x * size, - y * size );

      return canvas;

    };

    cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
    cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
    cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
    cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
    cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
    cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
    cubeMap.needsUpdate = true;

  } );

  var cubeShader = THREE.ShaderLib[ 'cube' ];
  cubeShader.uniforms[ 'tCube' ].value = cubeMap;

  var skyBoxMaterial = new THREE.ShaderMaterial( {
    fragmentShader: cubeShader.fragmentShader,
    vertexShader: cubeShader.vertexShader,
    uniforms: cubeShader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
  } );

  var skyBox = new THREE.Mesh(
    new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
    skyBoxMaterial
  );

  scene.add( skyBox );
}

function initBoat () {
  var loader = new THREE.STLLoader();
    loader.load( './models/rowing_boat.stl', function ( geometry ) {

      var material = new THREE.MeshPhongMaterial( {
					color: 0x966F33,
					shininess: 10,
					specular: 0x111111,
					shading: THREE.SmoothShading
				} );
      var mesh = new THREE.Mesh( geometry, material );

      mesh.position.set( 0, -120, 0 );
      mesh.rotation.set( - Math.PI / 2, 0, 0 );
      mesh.scale.set( 20.1, 20.1, 20.1 );

      mesh.castShadow = true;
      mesh.receiveShadow = true;

      scene.add( mesh );

    } );
}

function initFireflies () {
  function createLight( color ) {
    var newLight = new THREE.PointLight( color, 1, 30 );
    newLight.castShadow = true;
    newLight.shadowCameraNear = 1;
    newLight.shadowCameraFar = 300000;
    // newLight.shadowCameraVisible = true;
    newLight.shadowMapWidth = 204;
    newLight.shadowMapHeight = 102;
    newLight.shadowBias = 0.1;
    newLight.shadowDarkness = 0.2;

    var geometry = new THREE.SphereGeometry( 20, 16, 16 );
    var material = new THREE.MeshBasicMaterial( { color: color } );
    var sphere = new THREE.Mesh( geometry, material );
    newLight.add( sphere );

    return newLight
  }
  pointLightL = createLight( 0xaa0000 );
  scene.add( pointLightL );

  pointLightR = createLight( 0x0000aa );
  scene.add( pointLightR );
}

function animate() {

  requestAnimationFrame( animate );
  render();

}

function initParticles () {
  particleSystem = new THREE.GPUParticleSystem({
    maxParticles: 2500
  });
  scene.add( particleSystem);

}

function render() {

  var time = performance.now() * 0.001;

  var delta = clock.getDelta() * spawnerparticlesL.timeScale;
  tick += delta;

  if (tick < 0) tick = 0;

  if (delta > 0) {
    particleSystem.spawnParticle(particlesL);
    particleSystem.spawnParticle(particlesR);
  }

  particleSystem.update(tick);

  water.material.uniforms.time.value += 1.0 / 60.0;
  controls.update();
  water.render();
  renderer.render( scene, camera );

}
<|endoftext|>


<commit_before>import pointInEllipse from './pointInEllipse.js';

/**
 * Calculates the statistics of an elliptical region of interest.
 * @export @public @method
 * @name calculateEllipseStatistics
 *
 * @param  {number[]} sp    Array of the image data's pixel values.
 * @param  {Object} ellipse An object describing the ellipse.
 * @returns {Object}         The statistics of the ellipse.
 */
export default function(sp, ellipse) {
  // TODO: Get a real statistics library here that supports large counts

  let sum = 0;
  let sumSquared = 0;
  let count = 0;
  let index = 0;

  for (let y = ellipse.top; y < ellipse.top + ellipse.height; y++) {
    for (let x = ellipse.left; x < ellipse.left + ellipse.width; x++) {
      const point = {
        x,
        y,
      };

      if (pointInEllipse(ellipse, point)) {
        sum += sp[index];
        sumSquared += sp[index] * sp[index];
        count++;
      }

      index++;
    }
  }

  if (count === 0) {
    return {
      count,
      mean: 0.0,
      variance: 0.0,
      stdDev: 0.0,
    };
  }

  const mean = sum / count;
  const variance = sumSquared / count - mean * mean;

  return {
    count,
    mean,
    variance,
    stdDev: Math.sqrt(variance),
  };
}
<commit_msg>Add min/max to ellipse statistics<commit_after>import pointInEllipse from './pointInEllipse.js';

/**
 * Calculates the statistics of an elliptical region of interest.
 *
 * @private
 * @function calculateEllipseStatistics
 *
 * @param {number[]} sp - Array of the image data's pixel values.
 * @param {Object} ellipse - An object describing the ellipse.
 * @returns {Object} { count, mean, variance, stdDev, min, max }
 */
export default function(sp, ellipse) {
  let sum = 0;
  let sumSquared = 0;
  let count = 0;
  let index = 0;
  let min = sp.length ? sp[0] : 0;
  let max = sp.length ? sp[0] : 0;

  for (let y = ellipse.top; y < ellipse.top + ellipse.height; y++) {
    for (let x = ellipse.left; x < ellipse.left + ellipse.width; x++) {
      const point = {
        x,
        y,
      };

      if (pointInEllipse(ellipse, point)) {
        sum += sp[index];
        sumSquared += sp[index] * sp[index];
        min = Math.min(min, sp[index]);
        max = Math.max(max, sp[index]);
        count++;
      }

      index++;
    }
  }

  if (count === 0) {
    return {
      count,
      mean: 0.0,
      variance: 0.0,
      stdDev: 0.0,
      min,
      max,
    };
  }

  const mean = sum / count;
  const variance = sumSquared / count - mean * mean;

  return {
    count,
    mean,
    variance,
    stdDev: Math.sqrt(variance),
    min,
    max,
  };
}
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */
var _ = require('lodash');
var crypto = require('crypto');
var Waterline = require('waterline');
var util = require('util');
var log = require('debug-logger')('connect-waterline');

/**
 * Default options
 */
var defaultOptions = {
  // Global options
  collection: 'sessions',
  stringify: true,
  hash: false,
  ttl: 60 * 60 * 24 * 14, // 14 days
  autoRemove: 'interval',
  autoRemoveInterval: 10
};

var defaultHashOptions = {
  salt: 'connect-waterline',
  algorithm: 'sha1'
};

var defaultSerializationOptions = {
  serialize: function (session) {
    // Copy each property of the session to a new object
    var obj = {};
    for (var prop in session) {
      if (prop === 'cookie') {

        // Convert the cookie instance to an object, if possible
        // This gets rid of the duplicate object under session.cookie.data property
        obj.cookie = session.cookie.toJSON ? session.cookie.toJSON() : session.cookie;
      } else {
        obj[prop] = session[prop];
      }
    }
    return obj;
  },
  unserialize: _.identity
};

var stringifySerializationOptions = {
  serialize: JSON.stringify,
  unserialize: JSON.parse
};

module.exports = function(connect) {
  var Store = connect.Store || connect.session.Store;
  var MemoryStore = connect.MemoryStore || connect.session.MemoryStore;

  /**
   * Initialize WaterlineStore with the given `options`.
   *
   * @param {Object} options
   * @api public
   */

  function WaterlineStore(options) {
    options = _.clone(options);

    /* Fallback */

    if (options.fallbackMemory && MemoryStore) {
      return new MemoryStore();
    }

    /* Options */

    options = _.defaults(options || {}, defaultOptions);

    if (options.hash) {
      options.hash = _.defaults(options.hash, defaultHashOptions);
    }

    if (!options.stringify || options.serialize || options.unserialize) {
      options = _.defaults(options, defaultSerializationOptions);
      options.sessionType = options.sessionType || 'json';
    } else {
      options = _.assign(options, stringifySerializationOptions);
      options.sessionType = options.sessionType || 'string';
    }

    this.options =  options;

    Store.call(this, options);

    var self = this;

    function changeState(newState) {
      log.info('switched to state: %s', newState);
      self.state = newState;
      self.emit(newState);
    }

    function connectionReady(err, collection) {
      if (err) {
        log.error('not able to connect to the database');
        changeState('disconnected');
        throw err;
      }

      self.collection = collection;

      switch (options.autoRemove) {

        case 'native':
          throw new Error('"native" is not supported (yet), please use another option.');
//          self.collection.ensureIndex({ expires: 1 }, { expireAfterSeconds: 0 }, function (err) {
//            if (err) throw err;
//            changeState('connected');
//          });
//          break;

        case 'interval':
          setInterval(function () {
            self.collection.destroy({ expires: { '>': new Date() } }, function(err){
              if(err) { log.warn('Failed to delete expired sesssions:', err); }
            });
          }, options.autoRemoveInterval * 1000 * 60);
          changeState('connected');
          break;

        default:
          changeState('connected');
          break;

      }
    }

    function initWithWaterlineModel(){
      process.nextTick(function(){
        self.waterline = options.model.waterline;  // TODO: double check this
        connectionReady(null, options.model);
      });
    }

    function initWithNewConnection() {
      var adapters = options.adapters || {};
      var connections = options.connections || {};

      self.waterline = new Waterline();

      // Apply options to collection definition
      var modelDefinition = _.cloneDeep(module.exports.defaultModelDefinition);
      modelDefinition.tableName = options.collection || 'sessions';
      modelDefinition.attributes.session = options.sessionType;

      self.waterline.loadCollection(Waterline.Collection.extend(modelDefinition));

      self.waterline.initialize({
        adapters: adapters,
        connections: connections
      }, function(err, ontology){
        log.info('Waterline initialized');
        connectionReady(err, ontology && ontology.collections.sessions);
      });
    }

    this.getCollection = function (done) {
      switch (self.state) {
        case 'connected':
          done(null, self.collection);
          break;
        case 'connecting':
          self.once('connected', function () {
            done(null, self.collection);
          });
          break;
        case 'disconnected':
          done(new Error('Not connected'));
          break;
      }
    };

    this.getSessionId = function (sid) {
      if (options.hash) {
        return crypto.createHash(options.hash.algorithm).update(options.hash.salt + sid).digest('hex');
      } else {
        return sid;
      }
    };

    changeState('init');

    if (options.model) {
      log.debug('use strategy: `waterline_model`');
      initWithWaterlineModel();
    } else {
      log.debug('use strategy: `new_connection`');
      initWithNewConnection();
    }

    changeState('connecting');
  }

  /**
   * Inherit from `Store`.
   */
   util.inherits(WaterlineStore, Store);

  /**
   * Attempt to fetch session by the given `sid`.
   *
   * @param {String} sid
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.get = function(sid, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    var self = this;

    var query = {
      sid: sid,
      or: [
        { has_expires: false },
        { expires: { '>': new Date() } }
      ]
    };

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.findOne(query, function(err, session) {
        if (err) {
          log.error('not able to execute `find` query for session: ' + sid);
          return callback(err);
        }

        if (session) {
          var s;
          try {
            s = self.options.unserialize(session.session);
            if(self.options.touchAfter > 0 && session.lastModified){
              s.lastModified = session.lastModified;
            }
          } catch (err) {
            log.error('unable to deserialize session');
            callback(err);
          }
          callback(null, s);
        } else {
          callback();
        }
      });
    });
  };

  /**
   * Commit the given `sess` object associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Session} sess
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.set = function(sid, session, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    // removing the lastModified prop from the session object before update
    if(this.options.touchAfter > 0 && session && session.lastModified){
      delete session.lastModified;
    }

    var s;

    try {
      s = {sid: sid, session: this.options.serialize(session)};
    } catch (err) {
      log.error('unable to serialize session');
      callback(err);
    }

    if (session && session.cookie && session.cookie.expires) {
      s.expires = new Date(session.cookie.expires);
    } else {
      // If there's no expiration date specified, it is
      // browser-session cookie or there is no cookie at all,
      // as per the connect docs.
      //
      // So we set the expiration to two-weeks from now
      // - as is common practice in the industry (e.g Django) -
      // or the default specified in the options.
      s.expires = new Date(Date.now() + this.options.ttl * 1000);
    }

    if(this.options.touchAfter > 0){
      s.lastModified = new Date();
    }

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.update({sid: sid}, s, function(err, res) {
        if (err) {
          log.error('not able to set/update session: ' + sid, err);
          return callback(err);
        }
        if (res.length === 0){
          // doesn't exist yet, let's create it
          collection.create(s, function(err, res) {
            if (err) log.error('not able to create session: ' + sid);
            callback(err);
          });
        } else {
          callback();
        }
      });
    });
  };

  /**
   * Touch the given `sess` object associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Session} session
   * @param {Function} callback
   * @api public
   */
  WaterlineStore.prototype.touch = function (sid, session, callback) {

    var updateFields = {},
      touchAfter = this.options.touchAfter * 1000,
      lastModified = session.lastModified ? session.lastModified.getTime() : 0,
      currentDate = new Date();

    sid = this.getSessionId(sid);

    callback = callback ? callback : _.noop;

    // if the given options has a touchAfter property, check if the
    // current timestamp - lastModified timestamp is bigger than
    // the specified, if it's not, don't touch the session
    if(touchAfter > 0 && lastModified > 0){

      var timeElapsed = currentDate.getTime() - session.lastModified;

      if(timeElapsed < touchAfter){
        return callback();
      } else {
        updateFields.lastModified = currentDate;
      }

    }

    if (session && session.cookie && session.cookie.expires) {
      updateFields.expires = new Date(session.cookie.expires);
    } else {
      updateFields.expires = new Date(Date.now() + this.options.ttl * 1000);
    }

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.update({ sid: sid }, updateFields, function (err, result) {
        if (err) {
          log.error('not able to touch session: %s (error)', sid);
          callback(err);
        } else if (result.length === 0) {
          log.error('not able to touch session: %s (not found)', sid);
          callback(new Error('Unable to find the session to touch'));
        }
        callback();
      });
    });
  };

  /**
   * Destroy the session associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.destroy = function(sid, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.destroy({sid: sid}, function(err) {
        if (err) log.error('not able to destroy session: ' + sid);
        callback(err);
      });
    });
  };

  /**
   * Fetch number of sessions.
   *
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.length = function(callback) {
    if (!callback) callback = _.noop;
    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.count({}, function(err, count) {
        if (err) log.error('not able to count sessions');
        callback(err, count);
      });
    });
  };

  /**
   * Clear all sessions.
   *
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.clear = function(callback) {
    if (!callback) callback = _.noop;
    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.destroy({}, function(err) {
        if (err) log.error('not able to clear sessions: ' + sid);
        callback(err);
      });
    });
  };

  return WaterlineStore;
};

module.exports.defaultModelDefinition = {
  identity: 'sessions',

  connection: 'connect-waterline',

  autoPK: false,
  autoCreatedAt: false,
  associationFinders: false,

  attributes: {
    sid: {
      type: 'string',
      primaryKey: true,
      unique: true,
      required: true,
    },
    session: 'string',
    expires: 'datetime',
    has_expires: 'boolean',
    lastModified: 'datetime'
  },

  // Ugly workaround for detecting empty expires:
  // https://github.com/balderdashy/waterline/issues/189
  beforeValidate: function(values, next) {
    if (values.expires) {
      values.has_expires = true;
    } else {
      values.has_expires = false;
    }
    next();
  }
};
<commit_msg>Avoid customPK for now due to appscot/sails-orientdb#105<commit_after>/**
 * Module dependencies
 */
var _ = require('lodash');
var crypto = require('crypto');
var Waterline = require('waterline');
var util = require('util');
var log = require('debug-logger')('connect-waterline');

/**
 * Default options
 */
var defaultOptions = {
  // Global options
  collection: 'sessions',
  stringify: true,
  hash: false,
  ttl: 60 * 60 * 24 * 14, // 14 days
  autoRemove: 'interval',
  autoRemoveInterval: 10
};

var defaultHashOptions = {
  salt: 'connect-waterline',
  algorithm: 'sha1'
};

var defaultSerializationOptions = {
  serialize: function (session) {
    // Copy each property of the session to a new object
    var obj = {};
    for (var prop in session) {
      if (prop === 'cookie') {

        // Convert the cookie instance to an object, if possible
        // This gets rid of the duplicate object under session.cookie.data property
        obj.cookie = session.cookie.toJSON ? session.cookie.toJSON() : session.cookie;
      } else {
        obj[prop] = session[prop];
      }
    }
    return obj;
  },
  unserialize: _.identity
};

var stringifySerializationOptions = {
  serialize: JSON.stringify,
  unserialize: JSON.parse
};

module.exports = function(connect) {
  var Store = connect.Store || connect.session.Store;
  var MemoryStore = connect.MemoryStore || connect.session.MemoryStore;

  /**
   * Initialize WaterlineStore with the given `options`.
   *
   * @param {Object} options
   * @api public
   */

  function WaterlineStore(options) {
    options = _.clone(options);

    /* Fallback */

    if (options.fallbackMemory && MemoryStore) {
      return new MemoryStore();
    }

    /* Options */

    options = _.defaults(options || {}, defaultOptions);

    if (options.hash) {
      options.hash = _.defaults(options.hash, defaultHashOptions);
    }

    if (!options.stringify || options.serialize || options.unserialize) {
      options = _.defaults(options, defaultSerializationOptions);
      options.sessionType = options.sessionType || 'json';
    } else {
      options = _.assign(options, stringifySerializationOptions);
      options.sessionType = options.sessionType || 'string';
    }

    this.options =  options;

    Store.call(this, options);

    var self = this;

    function changeState(newState) {
      log.info('switched to state: %s', newState);
      self.state = newState;
      self.emit(newState);
    }

    function connectionReady(err, collection) {
      if (err) {
        log.error('not able to connect to the database');
        changeState('disconnected');
        throw err;
      }

      self.collection = collection;

      switch (options.autoRemove) {

        case 'native':
          throw new Error('"native" is not supported (yet), please use another option.');
//          self.collection.ensureIndex({ expires: 1 }, { expireAfterSeconds: 0 }, function (err) {
//            if (err) throw err;
//            changeState('connected');
//          });
//          break;

        case 'interval':
          setInterval(function () {
            self.collection.destroy({ expires: { '>': new Date() } }, function(err){
              if(err) { log.warn('Failed to delete expired sesssions:', err); }
            });
          }, options.autoRemoveInterval * 1000 * 60);
          changeState('connected');
          break;

        default:
          changeState('connected');
          break;

      }
    }

    function initWithWaterlineModel(){
      process.nextTick(function(){
        self.waterline = options.model.waterline;  // TODO: double check this
        connectionReady(null, options.model);
      });
    }

    function initWithNewConnection() {
      var adapters = options.adapters || {};
      var connections = options.connections || {};

      self.waterline = new Waterline();

      // Apply options to collection definition
      var modelDefinition = _.cloneDeep(module.exports.defaultModelDefinition);
      modelDefinition.tableName = options.collection || 'sessions';
      modelDefinition.attributes.session = options.sessionType;

      self.waterline.loadCollection(Waterline.Collection.extend(modelDefinition));

      self.waterline.initialize({
        adapters: adapters,
        connections: connections
      }, function(err, ontology){
        log.info('Waterline initialized');
        connectionReady(err, ontology && ontology.collections.sessions);
      });
    }

    this.getCollection = function (done) {
      switch (self.state) {
        case 'connected':
          done(null, self.collection);
          break;
        case 'connecting':
          self.once('connected', function () {
            done(null, self.collection);
          });
          break;
        case 'disconnected':
          done(new Error('Not connected'));
          break;
      }
    };

    this.getSessionId = function (sid) {
      if (options.hash) {
        return crypto.createHash(options.hash.algorithm).update(options.hash.salt + sid).digest('hex');
      } else {
        return sid;
      }
    };

    changeState('init');

    if (options.model) {
      log.debug('use strategy: `waterline_model`');
      initWithWaterlineModel();
    } else {
      log.debug('use strategy: `new_connection`');
      initWithNewConnection();
    }

    changeState('connecting');
  }

  /**
   * Inherit from `Store`.
   */
   util.inherits(WaterlineStore, Store);

  /**
   * Attempt to fetch session by the given `sid`.
   *
   * @param {String} sid
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.get = function(sid, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    var self = this;

    var query = {
      sid: sid,
      or: [
        { has_expires: false },
        { expires: { '>': new Date() } }
      ]
    };

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.findOne(query, function(err, session) {
        if (err) {
          log.error('not able to execute `find` query for session: ' + sid);
          return callback(err);
        }

        if (session) {
          var s;
          try {
            s = self.options.unserialize(session.session);
            if(self.options.touchAfter > 0 && session.lastModified){
              s.lastModified = session.lastModified;
            }
          } catch (err) {
            log.error('unable to deserialize session');
            callback(err);
          }
          callback(null, s);
        } else {
          callback();
        }
      });
    });
  };

  /**
   * Commit the given `sess` object associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Session} sess
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.set = function(sid, session, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    // removing the lastModified prop from the session object before update
    if(this.options.touchAfter > 0 && session && session.lastModified){
      delete session.lastModified;
    }

    var s;

    try {
      s = {sid: sid, session: this.options.serialize(session)};
    } catch (err) {
      log.error('unable to serialize session');
      callback(err);
    }

    if (session && session.cookie && session.cookie.expires) {
      s.expires = new Date(session.cookie.expires);
    } else {
      // If there's no expiration date specified, it is
      // browser-session cookie or there is no cookie at all,
      // as per the connect docs.
      //
      // So we set the expiration to two-weeks from now
      // - as is common practice in the industry (e.g Django) -
      // or the default specified in the options.
      s.expires = new Date(Date.now() + this.options.ttl * 1000);
    }

    if(this.options.touchAfter > 0){
      s.lastModified = new Date();
    }

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.update({sid: sid}, s, function(err, res) {
        if (err) {
          log.error('not able to set/update session: ' + sid, err);
          return callback(err);
        }
        if (res.length === 0){
          // doesn't exist yet, let's create it
          collection.create(s, function(err, res) {
            if (err) log.error('not able to create session: ' + sid);
            callback(err);
          });
        } else {
          callback();
        }
      });
    });
  };

  /**
   * Touch the given `sess` object associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Session} session
   * @param {Function} callback
   * @api public
   */
  WaterlineStore.prototype.touch = function (sid, session, callback) {

    var updateFields = {},
      touchAfter = this.options.touchAfter * 1000,
      lastModified = session.lastModified ? session.lastModified.getTime() : 0,
      currentDate = new Date();

    sid = this.getSessionId(sid);

    callback = callback ? callback : _.noop;

    // if the given options has a touchAfter property, check if the
    // current timestamp - lastModified timestamp is bigger than
    // the specified, if it's not, don't touch the session
    if(touchAfter > 0 && lastModified > 0){

      var timeElapsed = currentDate.getTime() - session.lastModified;

      if(timeElapsed < touchAfter){
        return callback();
      } else {
        updateFields.lastModified = currentDate;
      }

    }

    if (session && session.cookie && session.cookie.expires) {
      updateFields.expires = new Date(session.cookie.expires);
    } else {
      updateFields.expires = new Date(Date.now() + this.options.ttl * 1000);
    }

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.update({ sid: sid }, updateFields, function (err, result) {
        if (err) {
          log.error('not able to touch session: %s (error)', sid);
          callback(err);
        } else if (result.length === 0) {
          log.error('not able to touch session: %s (not found)', sid);
          callback(new Error('Unable to find the session to touch'));
        }
        callback();
      });
    });
  };

  /**
   * Destroy the session associated with the given `sid`.
   *
   * @param {String} sid
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.destroy = function(sid, callback) {
    if (!callback) callback = _.noop;
    sid = this.getSessionId(sid);

    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.destroy({sid: sid}, function(err) {
        if (err) log.error('not able to destroy session: ' + sid);
        callback(err);
      });
    });
  };

  /**
   * Fetch number of sessions.
   *
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.length = function(callback) {
    if (!callback) callback = _.noop;
    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.count({}, function(err, count) {
        if (err) log.error('not able to count sessions');
        callback(err, count);
      });
    });
  };

  /**
   * Clear all sessions.
   *
   * @param {Function} callback
   * @api public
   */

  WaterlineStore.prototype.clear = function(callback) {
    if (!callback) callback = _.noop;
    this.getCollection(function(err, collection) {
      if (err) return callback(err);
      collection.destroy({}, function(err) {
        if (err) log.error('not able to clear sessions: ' + sid);
        callback(err);
      });
    });
  };

  return WaterlineStore;
};

module.exports.defaultModelDefinition = {
  identity: 'sessions',

  connection: 'connect-waterline',

  //autoPK: false,
  autoCreatedAt: false,
  associationFinders: false,

  attributes: {
    sid: {
      type: 'string',
      //primaryKey: true,
      unique: true,
      required: true,
    },
    session: 'string',
    expires: 'datetime',
    has_expires: 'boolean',
    lastModified: 'datetime'
  },

  // Ugly workaround for detecting empty expires:
  // https://github.com/balderdashy/waterline/issues/189
  beforeValidate: function(values, next) {
    if (values.expires) {
      values.has_expires = true;
    } else {
      values.has_expires = false;
    }
    next();
  }
};
<|endoftext|>


<commit_before>// General setup and functions

var fayeClient = new Faye.Client('FAYEHOST');
var services = [ 'Classify', 'AnnotationSet', 'WikiMeta', 'Spotlight', 'Sentiment'];
var currentAnnoName = 'currentAnno';

var outputDocument = parent.document;
var $enclosure = $('#pxContent', outputDocument);
var startingHTML = $enclosure.html().toString();

if (!$enclosure.length) { // We are not running as iframe
  console.log('enclosure is pxContent');
  $enclosure = $('#pxContent', outputDocument);
  outputDocument = preview;
} else {
  console.log('enclosure is parent');
  parent.window.annotateCurrentURI = annotateCurrentURI;
}

var pxMember = parent.window.pxMember;
var isScraper = pxMember == 'scraper' || parent.window.pxScraper;
$('#pxMember').html(pxMember);

// tree setup

// shared across multiple subscribes
var treeData;
// retreive data from selected tree nodes
var idMap = {};
// incrementor
var ids = 0;

if (window.parent.location) {
  annotateCurrentURI(window.parent.location.toString());
}

function resetTreeData() {
  ids = 0;
  idMap = {};
  treeData = {
    json_data : {
      data : [
      ]
    },
    "types" : {
      "types" : {
        "default" : {
           "select_node" : function(e) {
             this.toggle_node(e);
           }
        }
      }
    },
    plugins : [ 'json_data', 'ui', 'themes', 'crrm', 'types' ]
  };
}

// annotation

var annos = fayeClient.subscribe('/annotations', function(message) {
  console.log('annotations', message.annotations);
  addChat('is visiting ' + '' + message.uri + '');
  if (message.uri === currentURI) { // FIXME add to subscription
    var terms = [];
    for (var k in message.annotations) {
      var ann = message.annotations[k];
      var instances = [];
      ann.instances.forEach(function(c) {
        instances.push({ data: (c.value || ann.quote), attr: { id: ++ids} });
        idMap[ids] = c;
      });
      terms.push({ data: ann.value || ann.quote, attr: { id: ++ids }, children : instances});
      idMap[ids] = ann;
    }
    treeData.json_data.data.push({ data: message.service, metadata : { id : ids++}, children: terms});
    updateTree();
  }
});

function updateTree() {
  $("#annoTree").jstree(treeData).bind("select_node.jstree", function (e, data) {
    var id = data.rslt.obj.attr('id');
    var selected= idMap[id];
    if (selected.value) {
      setAnnotation(selected);
    }
    if (selected && selected.tagset) {
      var hier = {};
      // split tags, FIXME data structure on annotators
      selected.tagset.forEach(function(t) {
        var s = t.split(':');
        if (s.length === 2) {
          hier[s[0]] = s[1];
        } else {
          hier[s] = t;
        }
      });
    }
  });
  $('#annoTree').bind('hover_node.jstree', function (e, data) {
    var id = data.rslt.obj.attr('id');
    var hovered = idMap[id];
    if (hovered && hovered.ranges) {
      console.log('hovered range', hovered);
      markAnno(hovered.ranges[0].startOffset + annoOffset, hovered.quote, true);
    } else {
      console.log('upper', hovered);
    }
  });
}

// offset for agent automation
var annoOffset = -816;

function markAnno(start, text, jump) {
console.log('markAnno', startingHTML.substr(start, 90));
  var found = -1;
  while (start > 0 && found < 0) {
    found = startingHTML.indexOf(text, start);
    start--;
  }
  window.parent.location.hash = '';
  if (found < 1) {
    return;
  }
  console.log(found, text);
  $enclosure.html(startingHTML.substring(0, found) + '' + text + '' + startingHTML.substring(found + text.length));
  if (jump) {
    window.parent.location.hash = currentAnnoName;
  }
}

function annotateCurrentURI(u) {
    currentURI = u.replace('#'+currentAnnoName, '').replace(/#$/, '');
    resetTreeData();
    console.log('resetting to', currentURI);
    if (currentURI) {
      $('#annoTree').html('');
      fayeClient.publish('/annotate', { services : services, uri: currentURI});
    }
}

function addChat(msg) {
  var n = new Date();
  $('#collabStream').append('' + n.getHours() + ":"  + n.getMinutes() + ":" + n.getSeconds() + ' ' + pxMember  + ' ' + msg + '
');
  $('.visiting').click(function(t) {
    annotateCurrentURI($(this).text());
  });
}

$('.morenext').click(function() {
  $(this).next().toggle();
});

// search

$('#searchForm').submit(function(event) {
  event.preventDefault();
  var search = { terms : $('#termSearch').val(), annotations : $('#annoSearch').val(),
    from: $('#fromDate').val(), to: $('#toDate').val(),
    member: $('#searchMember').val() };
  fayeClient.publish('/search', search);
});

var searchRes = fayeClient.subscribe('/searchResults', function(searchResults) {
  console.table('searchResults', searchResults);
});

// collab
var collab = fayeClient.subscribe('/collab', function(message) {
  addChat(message.text);
});
$('#collabInput').keypress(function(e) {
  if(e.which == 13) {
    fayeClient.publish('/collab', { text : $('#collabInput').val()});
    $('#collabInput').val('');
    return false;
  }
});

// scrape
if (isScraper) {
  console.log('I am a scraper');

  fayeClient.subscribe('/scrape', function(link) {
    console.log('/scrape', link);
    outputDocument.location = link;
  });
  var links = [];
  var myDomain = currentURI.split('/')[2];
  for (var i = 0; i < outputDocument.links.length; i++) {
    var href = outputDocument.links[i].href;
    var link = href.split('/')[2];
    console.log(href, link, myDomain);
    var inDomain = (link.indexOf(myDomain) > -1);
    if (link && (href.toLowerCase().indexOf('pdf') < 0) ) {
      links.push(href);
    }
    setTimeout(function() {
//      console.log('sending', links); fayeClient.publish('/links', { site: currentURI, links: links};)
      setInterval(function() { console.log('sending', links); fayeClient.publish('/links', { site: currentURI, links: []})}, 5000);
    }, 1000);
  }
}

$('#updateAnnotations').click(function() {
    annotateCurrentURI(outputDocument.location.toString());
});

$('#annoNew').click(function() {
  selectingAnno = true;
  clearAnno();
});

$('#annoCancel').click(function() {
  selectingAnno = false;
  clearAnno();
  $('#annotateEditor').hide();
  return false;
});

$('#annoSave').click(function() {
  var annos = [ { quote: $('#annoQuote').val(), value : $('#annoValue').val(), types: $('#types').val(), description: $('#annoDesc').val(), validated: true, creator: pxMember } ];
  fayeClient.publish('/saveAnnotations', { uri: currentURI, annotations: annos });
  return false;
});

$('#annoUnsave').click(function() {
  return false;
});

$('#annoErase').click(function() {
  return false;
});

var teams = [ {people : [
    { name : 'Andy', icon: 'demo.png', activities : [{annotate : 'default'}, { search : true}]}
    , { name : 'Betty', icon: 'manager.png', activities : [{annotate : 'default'}, { search : true}]}
  ]},
  { services : [
    { name:'Spotlight', icon:'dbpedia.jpg', active:true, activities : [{annotate : 'default'}]}
    , { name : 'Sentiment', icon : 'sentiment.jpg', activities : [{annotate:'default'}]}
    , { name : 'WikiMeta', icon : 'wikimeta.png', activities : [{annotate:'true'}]}
    , { name : 'Carrot2', icon : 'carrot2.png', activities : [{annotate:'true'}]}
    , { name : 'Board members', icon : 'board.jpg', activities : [{annotate : true}]}
    , { name : 'MicroRDF', icon: 'rdf.png', activities : [{annotate: true}]}
    , { name : 'MycoMine', icon : 'mycomine_logo.png', activities : [{annotate:true}]}
    , { name : 'GATE', icon : 'gate.jpg', activities : [{annotate:true}]}
    , { name : 'DC', icon: 'dublin_core.png', activities : [{annotate:'true'}, { search : 'default'}]}
    , { name : 'ElasticSearch', icon : 'esearch.png', activities : [{search : 'default'}, {storage: 'default'}]}
  ]}
]

// display selected and available team members
$('.teamToggle').each(function() {
  var $p = $(this);
  $p.append('
Team -

Available +

');
  var $c = $p.find('.available');
  var $s = $p.find('.selected');
  var f = $p.attr('for');
  teams.forEach(function(team) {
    $.each(team, function(i, indi) {
      $.each(indi, function(m, member) {
        member.activities.forEach(function(activity) {
          for (var a in activity) {
            if (a == f) {
              $el = activity[a] == 'default' ? $s : $c;
              $el.append('' + (member.icon ? '' : '' + member.name+'') + '');
            }
          }
        });
      });
    });
  });
  $s.sortable();
  $c.find('a').draggable({
      cancel: "a.ui-icon",
      revert: "invalid",
      containment: "document",
      helper: "clone",
      cursor: "move"
    });

  $s.droppable({
    activeClass: "ui-state-highlight",
    drop: function( event, ui ) {
      $(this).append(ui.draggable);
    }
  });
  $s.find('a').draggable({
      cancel: "a.ui-icon",
      revert: "invalid",
      containment: "document",
      helper: "clone",
      cursor: "move"
    });

  $c.droppable({
    activeClass: "ui-state-highlight",
    drop: function( event, ui ) {
      $(this).append(ui.draggable);
    }
  });
});

$('.toggle').click ( function () {
  var $next = $(this).next();
  $next.toggle ();

  if ($next.is (':visible' ) === true ) {
    $(this).find('.ind').html('-');
  } else {
    $(this).find('.ind').html('+');
  }
});

$(document).tooltip();
var resizeIframe = function(event, ui) {
  var w = Math.round(ui.size.width);
  window.parent.pxContent.style.left = (w + 5) + 'px';
  window.parent.pxContent.style.width = window.parent.innerWidth - (ui.size.width + 5);
  try {
  console.log('SZ', window.parent.innerWidth, ui.size.width);
  $('#pxContent').next().style.width = w - 5 + 'px';
  } catch (e) {
    console.log('failed resize', e);
  }
};

if (window.parent.pxContent) {
  resizeIframe(null, { size: { width: 300}});
  $("#pxControls" ).on("resize", resizeIframe );
}

// annotation functions
var selectingAnno = false;

$enclosure.mouseup(function() {
  if (!selectingAnno) {
    return;
  }
   var selection = outputDocument.getSelection();
  var startOffset = (selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange()).startOffset;
  var text = selection.toString();
  markAnno(startOffset, text);
  var selected = { quote: text, value : text, created: new Date(), types: '', annoDesc: ''};
  setAnnotation(selected);
  return false;
});

function setAnnotation(selected) {
  $('#annoQuote').val(selected.quote);
  $('#annoValue').val(selected.value || '');
  $('#created').val(selected.created || '');
  $('#types').val(selected.types || '');
  $('#annoDesc').val(selected.text || '');
  $('#annotateEditor').show();
  return false;
}

function clearAnno() {
  setAnnotation({});
  $enclosure.html(startingHTML);
}

<commit_msg>preparing for lib modularization<commit_after>// General setup and functions

var fayeClient = new Faye.Client('FAYEHOST');
var services = [ 'Classify', 'AnnotationSet', 'WikiMeta', 'Spotlight', 'Sentiment'];
var currentAnnoName = 'currentAnno';

var outputDocument = parent.document;
var $enclosure = $('#pxContent', outputDocument);
var startingHTML = $enclosure.html().toString();

if (!$enclosure.length) { // We are not running as iframe
  console.log('enclosure is pxContent');
  $enclosure = $('#pxContent', outputDocument);
  outputDocument = preview;
} else {
  console.log('enclosure is parent');
  parent.window.annotateCurrentURI = annotateCurrentURI;
}

var pxMember = parent.window.pxMember;
var isScraper = pxMember == 'scraper' || parent.window.pxScraper;
$('#pxMember').html(pxMember);

// tree setup

// shared across multiple subscribes
var treeData;
// retreive data from selected tree nodes
var idMap = {};
// incrementor
var ids = 0;

if (window.parent.location) {
  annotateCurrentURI(window.parent.location.toString());
}

function resetTreeData() {
  ids = 0;
  idMap = {};
  treeData = {
    json_data : {
      data : [
      ]
    },
    "types" : {
      "types" : {
        "default" : {
           "select_node" : function(e) {
             this.toggle_node(e);
           }
        }
      }
    },
    plugins : [ 'json_data', 'ui', 'themes', 'crrm', 'types' ]
  };
}

// annotation

var annos = fayeClient.subscribe('/annotations', function(message) {
  console.log('annotations', message.annotations);
  addChat('is visiting ' + '' + message.uri + '');
  if (message.uri === currentURI) { // FIXME add to subscription
    var terms = [];
    for (var k in message.annotations) {
      var ann = message.annotations[k];
      var instances = [];
      ann.instances.forEach(function(c) {
        instances.push({ data: (c.value || ann.quote), attr: { id: ++ids} });
        idMap[ids] = c;
      });
      terms.push({ data: ann.value || ann.quote, attr: { id: ++ids }, children : instances});
      idMap[ids] = ann;
    }
    treeData.json_data.data.push({ data: message.service, metadata : { id : ids++}, children: terms});
    updateTree();
  }
});

function updateTree() {
  $("#annoTree").jstree(treeData).bind("select_node.jstree", function (e, data) {
    var id = data.rslt.obj.attr('id');
    var selected= idMap[id];
    if (selected.value) {
      setAnnotation(selected);
    }
    if (selected && selected.tagset) {
      var hier = {};
      // split tags, FIXME data structure on annotators
      selected.tagset.forEach(function(t) {
        var s = t.split(':');
        if (s.length === 2) {
          hier[s[0]] = s[1];
        } else {
          hier[s] = t;
        }
      });
    }
  });
  $('#annoTree').bind('hover_node.jstree', function (e, data) {
    var id = data.rslt.obj.attr('id');
    var hovered = idMap[id];
    if (hovered && hovered.ranges) {
      console.log('hovered range', hovered);
      markAnno(hovered.ranges[0].startOffset + annoOffset, hovered.quote, true);
    } else {
      console.log('upper', hovered);
    }
  });
}

// offset for agent automation
var annoOffset = -816;

function markAnno(start, text, jump) {
console.log('markAnno', startingHTML.substr(start, 90));
  var found = -1;
  while (start > 0 && found < 0) {
    found = startingHTML.indexOf(text, start);
    start--;
  }
  window.parent.location.hash = '';
  if (found < 1) {
    return;
  }
  console.log(found, text);
  $enclosure.html(startingHTML.substring(0, found) + '' + text + '' + startingHTML.substring(found + text.length));
  if (jump) {
    window.parent.location.hash = currentAnnoName;
  }
}

function annotateCurrentURI(u) {
  currentURI = u.replace('#'+currentAnnoName, '').replace(/#$/, '');
  resetTreeData();
  console.log('resetting to', currentURI);
  if (currentURI) {
    $('#annoTree').html('');
    fayeClient.publish('/annotate', { services : services, uri: currentURI});
  }
}

function addChat(msg) {
  var n = new Date();
  $('#collabStream').append('' + n.getHours() + ":"  + n.getMinutes() + ":" + n.getSeconds() + ' ' + pxMember  + ' ' + msg + '
');
  $('.visiting').click(function(t) {
    annotateCurrentURI($(this).text());
  });
}

$('.morenext').click(function() {
  $(this).next().toggle();
});

// search

$('#searchForm').submit(function(event) {
  event.preventDefault();
  var search = { terms : $('#termSearch').val(), annotations : $('#annoSearch').val(),
    from: $('#fromDate').val(), to: $('#toDate').val(),
    member: $('#searchMember').val() };
  fayeClient.publish('/search', search);
});

var searchRes = fayeClient.subscribe('/searchResults', function(searchResults) {
  console.table('searchResults', searchResults);
});

// collab
var collab = fayeClient.subscribe('/collab', function(message) {
  addChat(message.text);
});
$('#collabInput').keypress(function(e) {
  if(e.which == 13) {
    fayeClient.publish('/collab', { text : $('#collabInput').val()});
    $('#collabInput').val('');
    return false;
  }
});

// scrape
if (isScraper) {
  console.log('I am a scraper');

  fayeClient.subscribe('/scrape', function(link) {
    console.log('/scrape', link);
    outputDocument.location = link;
  });
  var links = [];
  var myDomain = currentURI.split('/')[2];
  for (var i = 0; i < outputDocument.links.length; i++) {
    var href = outputDocument.links[i].href;
    var link = href.split('/')[2];
    console.log(href, link, myDomain);
    var inDomain = (link.indexOf(myDomain) > -1);
    if (link && (href.toLowerCase().indexOf('pdf') < 0) ) {
      links.push(href);
    }
    setTimeout(function() {
//      console.log('sending', links); fayeClient.publish('/links', { site: currentURI, links: links};)
      setInterval(function() { console.log('sending', links); fayeClient.publish('/links', { site: currentURI, links: []})}, 5000);
    }, 1000);
  }
}

$('#updateAnnotations').click(function() {
    annotateCurrentURI(outputDocument.location.toString());
});

$('#annoNew').click(function() {
  selectingAnno = true;
  clearAnno();
});

$('#annoCancel').click(function() {
  selectingAnno = false;
  clearAnno();
  $('#annotateEditor').hide();
  return false;
});

$('#annoSave').click(function() {
  var annos = [ { quote: $('#annoQuote').val(), value : $('#annoValue').val(), types: $('#types').val(), description: $('#annoDesc').val(), validated: true, creator: pxMember } ];
  fayeClient.publish('/saveAnnotations', { uri: currentURI, annotations: annos });
  return false;
});

$('#annoUnsave').click(function() {
  return false;
});

$('#annoErase').click(function() {
  return false;
});

var teams = [ {people : [
    { name : 'Andy', icon: 'demo.png', activities : [{annotate : 'default'}, { search : true}]}
    , { name : 'Betty', icon: 'manager.png', activities : [{annotate : 'default'}, { search : true}]}
  ]},
  { services : [
    { name:'Spotlight', icon:'dbpedia.jpg', active:true, activities : [{annotate : 'default'}]}
    , { name : 'Sentiment', icon : 'sentiment.jpg', activities : [{annotate:'default'}]}
    , { name : 'WikiMeta', icon : 'wikimeta.png', activities : [{annotate:'true'}]}
    , { name : 'Carrot2', icon : 'carrot2.png', activities : [{annotate:'true'}]}
    , { name : 'Board members', icon : 'board.jpg', activities : [{annotate : true}]}
    , { name : 'MicroRDF', icon: 'rdf.png', activities : [{annotate: true}]}
    , { name : 'MycoMine', icon : 'mycomine_logo.png', activities : [{annotate:true}]}
    , { name : 'GATE', icon : 'gate.jpg', activities : [{annotate:true}]}
    , { name : 'DC', icon: 'dublin_core.png', activities : [{annotate:'true'}, { search : 'default'}]}
    , { name : 'ElasticSearch', icon : 'esearch.png', activities : [{search : 'default'}, {storage: 'default'}]}
  ]}
]

// display selected and available team members
$('.teamToggle').each(function() {
  var $p = $(this);
  $p.append('
Team -

Available +

');
  var $c = $p.find('.available');
  var $s = $p.find('.selected');
  var f = $p.attr('for');
  teams.forEach(function(team) {
    $.each(team, function(i, indi) {
      $.each(indi, function(m, member) {
        member.activities.forEach(function(activity) {
          for (var a in activity) {
            if (a == f) {
              $el = activity[a] == 'default' ? $s : $c;
              $el.append('' + (member.icon ? '' : '' + member.name+'') + '');
            }
          }
        });
      });
    });
  });
  $s.sortable();
  $c.find('a').draggable({
      cancel: "a.ui-icon",
      revert: "invalid",
      containment: "document",
      helper: "clone",
      cursor: "move"
    });

  $s.droppable({
    activeClass: "ui-state-highlight",
    drop: function( event, ui ) {
      $(this).append(ui.draggable);
    }
  });
  $s.find('a').draggable({
      cancel: "a.ui-icon",
      revert: "invalid",
      containment: "document",
      helper: "clone",
      cursor: "move"
    });

  $c.droppable({
    activeClass: "ui-state-highlight",
    drop: function( event, ui ) {
      $(this).append(ui.draggable);
    }
  });
});

$('.toggle').click ( function () {
  var $next = $(this).next();
  $next.toggle ();

  if ($next.is (':visible' ) === true ) {
    $(this).find('.ind').html('-');
  } else {
    $(this).find('.ind').html('+');
  }
});

$(document).tooltip();
var resizeIframe = function(event, ui) {
  var w = Math.round(ui.size.width);
  window.parent.pxContent.style.left = (w + 5) + 'px';
  window.parent.pxContent.style.width = window.parent.innerWidth - (ui.size.width + 5);
  try {
  console.log('SZ', window.parent.innerWidth, ui.size.width);
  $('#pxContent').next().style.width = w - 5 + 'px';
  } catch (e) {
    console.log('failed resize', e);
  }
};

if (window.parent.pxContent) {
  resizeIframe(null, { size: { width: 300}});
  $("#pxControls" ).on("resize", resizeIframe );
}

// annotation functions
var selectingAnno = false;

$enclosure.mouseup(function() {
  if (!selectingAnno) {
    return;
  }
   var selection = outputDocument.getSelection();
  var startOffset = (selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange()).startOffset;
  var text = selection.toString();
  markAnno(startOffset, text);
  var selected = { quote: text, value : text, created: new Date(), types: '', annoDesc: ''};
  setAnnotation(selected);
  return false;
});

function setAnnotation(selected) {
  $('#annoQuote').val(selected.quote);
  $('#annoValue').val(selected.value || '');
  $('#created').val(selected.created || '');
  $('#types').val(selected.types || '');
  $('#annoDesc').val(selected.text || '');
  $('#annotateEditor').show();
  return false;
}

function clearAnno() {
  setAnnotation({});
  $enclosure.html(startingHTML);
}

<|endoftext|>