<commit_before>//we are using bundlers so there is no need to create a singleton in the form of java

//File: EventsManager.js
//a super simplistic event listener implementation
class EventsManager {
  constructor() {
    this.index = 0;
    this.events = {};

    //binding
    this.on = this.on.bind(this);
    this.dispatch = this.dispatch.bind(this);
    this.remove = this.remove.bind(this);
  }

  on(event, callback) {
    if(!this.events[event]) this.events[event] = []; //initialize
    this.index++;
    this.events[event].push({index: this.index, callback: callback});
    return this.index++; //return listener id
  }

  dispatch(event, data) {
    if(!this.events[event]) return; //validation
    for(let e of this.events[event]) {
      e.callback(data); //call all listeners
    }
  }

  remove(event, index) {
    if(!this.events[event]) return; //validation
    this.events[event] = this.events[event].filter(e => e.index !== index);
  }

}

let eventManager = new EventManager();
export default eventManager; //exporting a singleton
<commit_msg>Update singleton.js<commit_after>//we are using bundlers so there is no need to create a singleton in the form of java

//File: EventsManager.js
//a super simplistic event listener implementation
class EventsManager {
  constructor() {
    this.index = 0;
    this.events = {};

    //binding
    this.on = this.on.bind(this);
    this.dispatch = this.dispatch.bind(this);
    this.remove = this.remove.bind(this);
  }

  on(event, callback) {
    if(!this.events[event]) this.events[event] = []; //initialize
    this.index++;
    this.events[event].push({index: this.index, callback: callback});
    return this.index++; //return listener id
  }

  dispatch(event, data) {
    if(!this.events[event]) return; //validation
    for(let e of this.events[event]) {
      e.callback(data); //call all listeners
    }
  }

  remove(event, index) {
    if(!this.events[event]) return; //validation
    this.events[event] = this.events[event].filter(e => e.index !== index);
  }

}

let eventManager = new EventManager(); //creating an instance
export default eventManager; //exporting a singleton
<|endoftext|>


<commit_before>/**@license
 * Copyright (c) 2013-2015, XorfacX - FairyDwarves
 * Please report to LICENSE.md file.
 */

/**
* Main file
*/
"use strict"; //enable strict mode

define([
    'dojo/_base/lang',
    'dojo/_base/declare',
    "dojo/on",
    "dojo/ready",
    "dojo/Deferred",
    "app/system",
    "app/appM",
    "app/appV",
    "app/sound",
    "app/Environment"
], function (lang, declare, on, ready, Deferred, system, model, view, appSound) {

    /** @private */
    var context, screenTO = 2000; //screenTO == sum of transition duration defined inside css for #title and #logo

    /**
     * Create the whole app view
     * This is the controller part
     */
    return declare(null, {
        /**
         * @constructor
         */
        constructor: function () {
            context = this; //need to keep track inside "on" and "require" calls if we don't want to (or can't) use lang.hitch

            var forcedNode = (location.search.match(/n=(\S+)/) ? RegExp.$1 : undefined); //"n", node parameter

            //set AppEnv
            setEnvironment();
            system.LSKey = AppEnv.LSKey;

            //create the gloabal app Deferred
            window.appDeferred = new Deferred();

            //init sound
            //appSound.init(system.LSKey);

            //create the model
            this.model = new model();

            //create the default view empty (can't be populated until appDeferred is resolved)
            var aV = this.view = new view();

            //wait for dom ready
            ready(function () {
                if (typeof forcedNode == "undefined") {
                    aV.showTitle("My App Title".replace(/_/gi, " ").replace(/ /g, "
")); //replace potential underscore with space than spaces with
 tag

                    var onSig = on.once(aV.getRawView(), "click", function (e) {
                        context._Title2Logo(aV, to);
                    });

                    var to = setTimeout(function () {
                        context._Title2Logo(aV, onSig); //TODO: fix, CANT use on.emit
                    }, screenTO);
                } else { //to display directly a specific node
                    this._launch(aV, forcedNode);
                }
            }); //ready
        }, //constructor

        model: undefined,
        view: undefined,

        /**
         * Transition from Title to Logo screen
         *
         * @private
         */
        _Title2Logo: function (aV, _signal) {
            if (_signal) {
                if (typeof _signal.remove == "function") { //remove event if called through setTimeout
                    _signal.remove();
                } else {
                    clearTimeout(_signal); //cleartimeout if called through on event
                }
            }

            aV.hideTitle().showLogo();

            var onSig = on.once(aV.getRawView(), "click", function (e) {
                context._Logo2Launch(aV, to);
            });

            var to = setTimeout(function () {
                context._Logo2Launch(aV, onSig);
            }, screenTO);
        },

        /**
         * Transition from Logo to Launch screen
         *
         * @private
         */
        _Logo2Launch: function (aV, _signal) {
            if (_signal) {
                if (typeof _signal.remove == "function") { //remove event if called through setTimeout
                    _signal.remove();
                } else {
                    clearTimeout(_signal); //cleartimeout if called through on event
                }
            }

            context._launch(aV);
        },

        /**
         * Launch the view
         * @private
         */
        _launch: function (aV, node) {
            window.appDeferred.then( //waiting for whatever we want to preload
                function (deferredRes) { //when wating is over call this function
                    console.log(deferredRes);
                    aV.hideLogo();
                    context.reset();
                });
            window.appDeferred.resolve("Loading successful"); //TOSET: proper location of this code when all you wan to preload is done
        },

        /**
         * Reset the displayed view
         *
         * @param nId {string}, node id to display
         *
         * @return {!object} this, for chaining
         */
        reset: function (nId) {
            //TOSET: APP CODE GOES HERE

            this.view.reset();
            on(document, "touched, click", lang.hitch(this, function (event) {
                var res = "App model says: " + this.model.get();
                console.log(res);
                this.view.display(res);
            }));
        }
    });  //declare
});     //define

<commit_msg>back button handling dummy code<commit_after>/**@license
 * Copyright (c) 2013-2016, XorfacX - FairyDwarves
 * Please report to LICENSE.md file.
 */

/**
* Main file
*/
"use strict"; //enable strict mode

define([
    'dojo/_base/lang',
    'dojo/_base/declare',
    "dojo/on",
    "dojo/touch",
    "dojo/ready",
    "dojo/Deferred",
    "app/system",
    "app/appM",
    "app/appV",
    "app/sound",
    "app/Environment"
], function (lang, declare, on, touch, ready, Deferred, system, model, view, appSound) {

    /** @private */
    var context, screenTO = 2000; //screenTO == sum of transition duration defined inside css for #title and #logo

    /**
     * Create the whole app view
     * This is the controller part
     */
    return declare(null, {
        /**
         * @constructor
         */
        constructor: function () {
            context = this; //need to keep track inside "on" and "require" calls if we don't want to (or can't) use lang.hitch

            var forcedNode = (location.search.match(/n=(\S+)/) ? RegExp.$1 : undefined); //"n", node parameter

            //set AppEnv
            setEnvironment();
            system.LSKey = AppEnv.LSKey;

            //create the gloabal app Deferred
            window.appDeferred = new Deferred();

            //init sound
            //appSound.init(system.LSKey);

            //create the model
            this.model = new model();

            //create the default view empty (can't be populated until appDeferred is resolved)
            var aV = this.view = new view();

            //wait for dom ready
            ready(function () {
                if (typeof forcedNode == "undefined") {
                    aV.showTitle("My App Title".replace(/_/gi, " ").replace(/ /g, "
")); //replace potential underscore with space than spaces with
 tag

                    var onSig = on.once(aV.getRawView(), "click", function (e) {
                        context._Title2Logo(aV, to);
                    });

                    var to = setTimeout(function () {
                        context._Title2Logo(aV, onSig); //CANT use on.emit ...
                    }, screenTO);
                } else { //to display directly a specific node
                    this._launch(aV, forcedNode);
                }
            }); //ready
        }, //constructor

        model: undefined,
        view: undefined,

        /**
         * Transition from Title to Logo screen
         *
         * @private
         */
        _Title2Logo: function (aV, _signal) {
            if (_signal) {
                if (typeof _signal.remove == "function") { //remove event if called through dojo.on event
                    _signal.remove();
                } else {
                    clearTimeout(_signal); //clearTimeout if called through setTimeout
                }
            }

            aV.hideTitle().showLogo();

            var onSig = on.once(aV.getRawView(), "click", function (e) {
                context._Logo2Launch(aV, to);
            });

            var to = setTimeout(function () {
                context._Logo2Launch(aV, onSig);
            }, screenTO);
        },

        /**
         * Transition from Logo to Launch screen
         *
         * @private
         */
        _Logo2Launch: function (aV, _signal) {
            if (_signal) {
                if (typeof _signal.remove == "function") { //remove event if called through setTimeout
                    _signal.remove();
                } else {
                    clearTimeout(_signal); //cleartimeout if called through on event
                }
            }

            context._launch(aV);
        },

        /**
         * Launch the view
         * @private
         */
        _launch: function (aV, node) {
            window.appDeferred.then( //waiting for whatever we want to preload
                function (deferredRes) { //when wating is over call this function
                    console.log(deferredRes);
                    aV.hideLogo();
                    context.reset();
                });
            window.appDeferred.resolve("Loading successful"); //TOSET: proper location of this code when all you wan to preload is done
        },

        /**
         * Reset the displayed view
         *
         * @param nId {string}, node id to display
         *
         * @return {!object} this, for chaining
         */
        reset: function (nId) {
            //TOSET: APP CODE GOES HERE

            this.view.reset();
            on(document, touch.release, lang.hitch(this, function (event) {
                var res = "App model says: " + this.model.get();
                console.log(res);
                this.view.display(res);
            }));
            on(document, "backbutton", lang.hitch(this, function (event) {
                var res = "back btn pressed";
                console.log(res);
                this.view.display(res);
            }));
        }
    });  //declare
});     //define

<|endoftext|>


<commit_before>/**
* Plugin Name: Public-Key-Web-Login (PKWL)
* Author: Mirko Oleszuk
* URI: http://www.codepunks.net
* License: The MIT License (MIT)
*/

var popup = {

  /**
  * enable/disable login button
  * @param msg string sets value of login button and disables it
  * if empty button gets enabled
  */
  buttonReset: function(msg){

    if(undefined === msg){
      document.getElementById('LoginButton').value = "Login";
      document.getElementById('LoginButton').disabled = false;
    } else {
      document.getElementById('LoginButton').value = msg;
      document.getElementById('LoginButton').disabled = true;
    }

  },

  /**
  * sends xml request to given hostname with the parameter username
  * and returns result from server via callback function
  */
  handleXMLRequest: function(hostname, data, callback){

    try {
      // create a new xml http request
      var xhr = new XMLHttpRequest();

      // get protocol string ("http:", "https:")
      var protocol = document.getElementById('protocol').value;

      // open request
      xhr.open("POST", protocol + "//" + hostname, true);

      // set header
      xhr.setRequestHeader("Content-type",    "application/x-www-form-urlencoded");

      // result received
      xhr.onreadystatechange = function(){

        if( xhr.readyState == 4 && xhr.status == 200 ){

          // save response
          var result = xhr.responseText;

          // return result via callback (still unescaped here, be careful!)
          callback(result);
        }
      }

      // send the request
      xhr.send(data);

    } catch(e) {

      // message the user about the error
      console.log("ERROR: XMLHttpRequest not supported! Pleas update your client!", e);
      log("ERROR: XMLHttpRequest not supported! Pleas update your client!");

      // re-enable button
      popup.buttonReset();
    }
  },

  /**
  * get data from html and form
  * query key from db
  * send auth-request, handle tlp, handle decryption, handle cookies
  */
  auth: function(){
    //console.log("OK: popup.auth() called!");

    // get vars from form
    var hostname = document.getElementById('hostname').innerHTML;
    var username = document.getElementById('username').value;

    // redirect to new host page
    if(username == ""){
      self.location = '/html/host_new.html';
    }

    // show loading infos
    popup.buttonReset("Please wait...");

    // query id of key
    pkwl.getKeyID(hostname, username, function(keyid){
      //console.log("RET: getKeyID(", hostname, username, ") = ", keyid);

      if(!keyid){
        console.log("ERROR: No key found! (getKeyID)");
        log("ERROR: No key found! Please associate a key with this hostname and username!");
        popup.buttonReset();
        return;
      }

      // get the actual key numbers
      pkwl.getKey(keyid, function(returnedkey){
        //console.log("RET: getKey(", keyid, ") = ", returnedkey);

        if(!returnedkey){
          console.log("ERROR: No key found! (getKey)");
          log("ERROR: No key found! Please associate a key with this hostname and username!");
          popup.buttonReset();
          return;
        }

        // key management
        var bits = 2048;

        // set internal precision, keysize in byte + bonus (see RSA/BigInt.js)
        setMaxDigits(bits / 8 + 32);

        // object RSAKeyPair(private exponent, public exponent, modulus)
        // e and d switch places here, because we want to encrypt with the private key
        // so that the server can decrypt with the public key
        var key = new RSAKeyPair(returnedkey.e, returnedkey.d, returnedkey.n);

        // build xml request data
        var xmldata = "pkwl_action=auth&pkwl_username=" + username;

        // request tlp from server
        popup.handleXMLRequest(hostname, xmldata, function(result){
          //console.log("OK: TLP received:", result);

          // handle result
          switch(result){

            case "ERROR-INVALID-ACTION":
                    console.log("ERROR: INVALID ACTION");
                    log("ERROR: Invalid action.");
                    popup.buttonReset();
                    return;

            case "ERROR-INVALID-USER":
                    console.log("ERROR: INVALID USER");
                    log("ERROR: The selected username does not exist on the website or hasn't uploaded a public-key!");
                    popup.buttonReset();
                    return;

            case "ERROR-NO-PUBLICKEY":
                    console.log("ERROR: SERVER HAS NO PUBLIC-KEY");
                    log("ERROR: Please add a public-key to your account.");
                    popup.buttonReset();
                    return;
          }

          // handle input
          var data      = result.split(";");
          var n         = data[0];
          var t         = data[1];

          // solve puzzle
          var solution = SolPuzzle(t, n);

          // build xml request data
          var xmldata = "";
          xmldata += "pkwl_action=" + "auth";
          xmldata += "&pkwl_username=" + username;
          xmldata += "&pkwl_solution=" + solution;

          // send data to server
          popup.handleXMLRequest(hostname, xmldata, function(result){
            //console.log("OK: Received Cookie Data", result);

            // handle the xmlrequest result
            switch(result){

              case "ERROR-INVALID-ACTION":
                log("ERROR: Action invalid.");
                popup.buttonReset();
                return;

              case "ERROR-NO-PUBLICKEY":
                log("No public-key found! Please upload a public-key to your account");
                popup.buttonReset();
                return;

              case "ERROR-TLP-INVALID":
                log("ERROR: TLP invalid. Please try again.");
                popup.buttonReset();
                return;

              case "ERROR-TLP-EXPIRED":
                log("ERROR: TLP expired. Please try again.");
                popup.buttonReset();
                return;
            }

            // handle input
            var ciphertext = result.split(";");

            // decrypt data and concat to string
            var plaintext = "";
            for(var i = 0; i < ciphertext.length; i++){
              plaintext += decryptedString(key, ciphertext[i]);
            }

            // parse cookiestring
            var cookiedata = plaintext.split(";");
            for(var i = 0; i < cookiedata.length; i++){

              try {

                // parse cookie content
                var c = cookiedata[i].split(",");
                c[0] = document.getElementById('protocol').value + "//" + c[0];
                c[4] = parseInt(c[4]);

                // set cookie via chrome api
                chrome.cookies.set({ url: c[0], name: c[1], value: c[2], path: c[3], expirationDate: c[4], httpOnly: true }, function(cookie){
                  //console.log("OK: Cookie set!");
                });

              } catch(e){

                console.log("ERROR: Could not decrypt data!");
                log("ERROR: Could not decrypt data! Did you use the correct key?");
                popup.buttonReset();
                return;

              }
            }

            // call chrome tabs api for reloading
            chrome.tabs.query({'active':true}, function(tabs){

              // reload the active tab
              chrome.tabs.reload();

              // close plugin window
              window.close();

            });
          });
        });
      });
    });
  },

  /**
  * init call
  * get hostname
  * query saved hostnames
  */
  init: function(){
    //console.log("OK: pkwl.init() called!");
    try {
      // get active tab url
      chrome.tabs.query({'active':true}, function(tabs){

        // parse hostname from url string via dom js function
        var parser = document.createElement('a');

        // set url of active tab as parser href to access the hostname, protocol, etc. via parser.*
        parser.href = tabs[0].url;

        // set hostname as headline
        document.getElementById('hostname').innerHTML = parser.hostname;

        // save protocol for later use when requesting tlp
        document.getElementById('protocol').value = parser.protocol;

        // getAllObjects(table, outputmode, preselection, searchterm, resultid){
        pkwl.getAllObjects("hosts", "username-only", "", parser.hostname, "username");

      });
    } catch(e){
      // not running chrome
      console.log("ERROR: This plugin is not running in chrome!");
    }
  }
};

/**
* Init
*/
function bodyLoad(){
  // register events
  document.getElementById("LoginButton").addEventListener("click", popup.auth, false);

  // init database
  pkwl.initDatabase();

  // init popup
  popup.init();
};

/**
* SolPuzzle() solves given puzzle
* @param t timeslotvar
* @param n = p*q
*/
function SolPuzzle(t, n){
  // bigInt  str2bigInt(s,b,n,m)    //return a bigInt for number represented in string s in base b with at least n bits and m array elements
  var n   = str2bigInt(n, 10, 0);
  var s   = int2bigInt(2, 10, 0);
  var two = int2bigInt(2, 10, 0);
  for(i = 0; i < t; i++){
    s = powMod(s, two, n);
  }
  return bigInt2str(s,10);
}

/**
* Run my function bodyLoad() after Document Object Model (DOM) has been loaded
* useCapture = false (default)
*/
document.addEventListener("DOMContentLoaded", bodyLoad, false);
<commit_msg>Update popup.js - Fixed a typo<commit_after>/**
* Plugin Name: Public-Key-Web-Login (PKWL)
* Author: Mirko Oleszuk
* URI: http://www.codepunks.net
* License: The MIT License (MIT)
*/

var popup = {

  /**
  * enable/disable login button
  * @param msg string sets value of login button and disables it
  * if empty button gets enabled
  */
  buttonReset: function(msg){

    if(undefined === msg){
      document.getElementById('LoginButton').value = "Login";
      document.getElementById('LoginButton').disabled = false;
    } else {
      document.getElementById('LoginButton').value = msg;
      document.getElementById('LoginButton').disabled = true;
    }

  },

  /**
  * sends xml request to given hostname with the parameter username
  * and returns result from server via callback function
  */
  handleXMLRequest: function(hostname, data, callback){

    try {
      // create a new xml http request
      var xhr = new XMLHttpRequest();

      // get protocol string ("http:", "https:")
      var protocol = document.getElementById('protocol').value;

      // open request
      xhr.open("POST", protocol + "//" + hostname, true);

      // set header
      xhr.setRequestHeader("Content-type",    "application/x-www-form-urlencoded");

      // result received
      xhr.onreadystatechange = function(){

        if( xhr.readyState == 4 && xhr.status == 200 ){

          // save response
          var result = xhr.responseText;

          // return result via callback (still unescaped here, be careful!)
          callback(result);
        }
      }

      // send the request
      xhr.send(data);

    } catch(e) {

      // message the user about the error
      console.log("ERROR: XMLHttpRequest not supported! Please update your client!", e);
      log("ERROR: XMLHttpRequest not supported! Please update your client!");

      // re-enable button
      popup.buttonReset();
    }
  },

  /**
  * get data from html and form
  * query key from db
  * send auth-request, handle tlp, handle decryption, handle cookies
  */
  auth: function(){
    //console.log("OK: popup.auth() called!");

    // get vars from form
    var hostname = document.getElementById('hostname').innerHTML;
    var username = document.getElementById('username').value;

    // redirect to new host page
    if(username == ""){
      self.location = '/html/host_new.html';
    }

    // show loading infos
    popup.buttonReset("Please wait...");

    // query id of key
    pkwl.getKeyID(hostname, username, function(keyid){
      //console.log("RET: getKeyID(", hostname, username, ") = ", keyid);

      if(!keyid){
        console.log("ERROR: No key found! (getKeyID)");
        log("ERROR: No key found! Please associate a key with this hostname and username!");
        popup.buttonReset();
        return;
      }

      // get the actual key numbers
      pkwl.getKey(keyid, function(returnedkey){
        //console.log("RET: getKey(", keyid, ") = ", returnedkey);

        if(!returnedkey){
          console.log("ERROR: No key found! (getKey)");
          log("ERROR: No key found! Please associate a key with this hostname and username!");
          popup.buttonReset();
          return;
        }

        // key management
        var bits = 2048;

        // set internal precision, keysize in byte + bonus (see RSA/BigInt.js)
        setMaxDigits(bits / 8 + 32);

        // object RSAKeyPair(private exponent, public exponent, modulus)
        // e and d switch places here, because we want to encrypt with the private key
        // so that the server can decrypt with the public key
        var key = new RSAKeyPair(returnedkey.e, returnedkey.d, returnedkey.n);

        // build xml request data
        var xmldata = "pkwl_action=auth&pkwl_username=" + username;

        // request tlp from server
        popup.handleXMLRequest(hostname, xmldata, function(result){
          //console.log("OK: TLP received:", result);

          // handle result
          switch(result){

            case "ERROR-INVALID-ACTION":
                    console.log("ERROR: INVALID ACTION");
                    log("ERROR: Invalid action.");
                    popup.buttonReset();
                    return;

            case "ERROR-INVALID-USER":
                    console.log("ERROR: INVALID USER");
                    log("ERROR: The selected username does not exist on the website or hasn't uploaded a public-key!");
                    popup.buttonReset();
                    return;

            case "ERROR-NO-PUBLICKEY":
                    console.log("ERROR: SERVER HAS NO PUBLIC-KEY");
                    log("ERROR: Please add a public-key to your account.");
                    popup.buttonReset();
                    return;
          }

          // handle input
          var data      = result.split(";");
          var n         = data[0];
          var t         = data[1];

          // solve puzzle
          var solution = SolPuzzle(t, n);

          // build xml request data
          var xmldata = "";
          xmldata += "pkwl_action=" + "auth";
          xmldata += "&pkwl_username=" + username;
          xmldata += "&pkwl_solution=" + solution;

          // send data to server
          popup.handleXMLRequest(hostname, xmldata, function(result){
            //console.log("OK: Received Cookie Data", result);

            // handle the xmlrequest result
            switch(result){

              case "ERROR-INVALID-ACTION":
                log("ERROR: Action invalid.");
                popup.buttonReset();
                return;

              case "ERROR-NO-PUBLICKEY":
                log("No public-key found! Please upload a public-key to your account");
                popup.buttonReset();
                return;

              case "ERROR-TLP-INVALID":
                log("ERROR: TLP invalid. Please try again.");
                popup.buttonReset();
                return;

              case "ERROR-TLP-EXPIRED":
                log("ERROR: TLP expired. Please try again.");
                popup.buttonReset();
                return;
            }

            // handle input
            var ciphertext = result.split(";");

            // decrypt data and concat to string
            var plaintext = "";
            for(var i = 0; i < ciphertext.length; i++){
              plaintext += decryptedString(key, ciphertext[i]);
            }

            // parse cookiestring
            var cookiedata = plaintext.split(";");
            for(var i = 0; i < cookiedata.length; i++){

              try {

                // parse cookie content
                var c = cookiedata[i].split(",");
                c[0] = document.getElementById('protocol').value + "//" + c[0];
                c[4] = parseInt(c[4]);

                // set cookie via chrome api
                chrome.cookies.set({ url: c[0], name: c[1], value: c[2], path: c[3], expirationDate: c[4], httpOnly: true }, function(cookie){
                  //console.log("OK: Cookie set!");
                });

              } catch(e){

                console.log("ERROR: Could not decrypt data!");
                log("ERROR: Could not decrypt data! Did you use the correct key?");
                popup.buttonReset();
                return;

              }
            }

            // call chrome tabs api for reloading
            chrome.tabs.query({'active':true}, function(tabs){

              // reload the active tab
              chrome.tabs.reload();

              // close plugin window
              window.close();

            });
          });
        });
      });
    });
  },

  /**
  * init call
  * get hostname
  * query saved hostnames
  */
  init: function(){
    //console.log("OK: pkwl.init() called!");
    try {
      // get active tab url
      chrome.tabs.query({'active':true}, function(tabs){

        // parse hostname from url string via dom js function
        var parser = document.createElement('a');

        // set url of active tab as parser href to access the hostname, protocol, etc. via parser.*
        parser.href = tabs[0].url;

        // set hostname as headline
        document.getElementById('hostname').innerHTML = parser.hostname;

        // save protocol for later use when requesting tlp
        document.getElementById('protocol').value = parser.protocol;

        // getAllObjects(table, outputmode, preselection, searchterm, resultid){
        pkwl.getAllObjects("hosts", "username-only", "", parser.hostname, "username");

      });
    } catch(e){
      // not running chrome
      console.log("ERROR: This plugin is not running in chrome!");
    }
  }
};

/**
* Init
*/
function bodyLoad(){
  // register events
  document.getElementById("LoginButton").addEventListener("click", popup.auth, false);

  // init database
  pkwl.initDatabase();

  // init popup
  popup.init();
};

/**
* SolPuzzle() solves given puzzle
* @param t timeslotvar
* @param n = p*q
*/
function SolPuzzle(t, n){
  // bigInt  str2bigInt(s,b,n,m)    //return a bigInt for number represented in string s in base b with at least n bits and m array elements
  var n   = str2bigInt(n, 10, 0);
  var s   = int2bigInt(2, 10, 0);
  var two = int2bigInt(2, 10, 0);
  for(i = 0; i < t; i++){
    s = powMod(s, two, n);
  }
  return bigInt2str(s,10);
}

/**
* Run my function bodyLoad() after Document Object Model (DOM) has been loaded
* useCapture = false (default)
*/
document.addEventListener("DOMContentLoaded", bodyLoad, false);
<|endoftext|>


<commit_before>(function (context, definition) {

  'use strict';

  if (typeof module != 'undefined' && module.exports) {
    module.exports = definition();
  } else if (typeof define == 'function' && define.amd) {
    define(definition);
  } else {
    window.SimpleSlider = definition();
  }

})(this, function () {

  'use strict';

  // requestAnimationFrame polyfill

  if (!Date.now)
    Date.now = function() { return new Date().getTime(); };

  var vendors = ['webkit', 'moz'];
  for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
    var vp = vendors[i];
    window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
    window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] || window[vp+'CancelRequestAnimationFrame']);
  }

  if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || // iOS6 is buggy
    !window.requestAnimationFrame || !window.cancelAnimationFrame) {
    var lastTime = 0;
    window.requestAnimationFrame = function(callback) {
      var now = Date.now();
      var nextTime = Math.max(lastTime + 16, now);
      return setTimeout(function() { callback(lastTime = nextTime); }, nextTime - now);
    };
    window.cancelAnimationFrame = clearTimeout;
  }

  // ------------------

  function getdef(val, def){
    return val===undefined || val===null ? def : val;
  }

  function getUnit(args) {

    var item;
    var count = args.length;
    var unit = '';

    while (--count >= 0) {
      item = args[count];
      if (typeof item === 'string') {
        unit = item
          .replace(parseInt(item, 10) + '', '');
      }
    }

    return unit;

  }

  // Test if have children and throw warning otherwise
  function testChildrenNum(value) {

    if (value <= 0) {
      try {
        console.warn(
          'A SimpleSlider main container element' +
          'should have at least one child.'
        );
      } catch(e) {}

      return true;

    } else {

      return false;
    }

  }

  function anim(target, prop, unit, transitionDuration, startTime, elapsedTime, fromValue, toValue){

    function loop() {

      window.requestAnimationFrame(function requestAnimationFunction(time){

        if (startTime === 0) {
          startTime = time;
        }

        anim(target, prop, unit, transitionDuration, startTime, time, fromValue, toValue);

      });
    }

    var percentual;

    if (startTime === 0) {

      return loop();

    } else {

      percentual = (elapsedTime - startTime) / transitionDuration;

      if (percentual < 1) {

        var diffVal = toValue - fromValue;
        target[prop] = (fromValue + (percentual * diffVal)) + unit;
        loop();

      } else {

        target[prop] = (toValue) + unit;
      }
    }

  }

  var SimpleSlider = function(containerElem, options){
    this.containerElem = containerElem;
    this.interval = 0;
    if( !options ) options = {};
    this.trProp = getdef(options.transitionProperty, 'opacity');
    this.trTime = getdef(options.transitionTime, 0.5);
    this.delay = getdef(options.transitionDelay, 2);
    this.unit = getUnit([options.startValue, options.visibleValue, options.endValue]);
    this.startVal = parseInt(getdef(options.startValue, 0), 10);
    this.visVal = parseInt(getdef(options.visibleValue, 100), 10);
    this.endVal = parseInt(getdef(options.endValue, 0), 10);
    this.autoPlay = getdef(options.autoPlay, true);
    this.init();
  };

  SimpleSlider.prototype.init = function() {
    this.reset();
    this.configSlideshow();
  };

  SimpleSlider.prototype.reset = function() {

    if (testChildrenNum(this.containerElem.children.length)) {
      return; // Do not follow reset logic if don't have children
    }

    var i = this.containerElem.children.length-1;
    this.imgs = [];
    while (i>=0) {
      this.imgs[i] = this.containerElem.children[i];
      this.imgs[i].style[this.trProp] = this.endVal + this.unit;
      i--;
    }

    this.imgs[0].style[this.trProp] = this.startVal + this.unit;
    this.actualIndex = 0;
  };

  SimpleSlider.prototype.configSlideshow = function() {

    if (!this.imgs) {
      return;
    }

    if (this.autoPlay) {
      var scope = this;
      if (this.interval) {
        window.clearInterval(this.interval);
      } else {
        this.interval = window.setInterval(function(){
          scope.change(scope.nextIndex());
        }, this.delay*1000);
      }
    }

  };

  SimpleSlider.prototype.startAnim = function(target, fromValue, toValue){

    anim(target.style, this.trProp, this.unit, this.trTime * 1000, 0, 0, fromValue, toValue);

  };

  SimpleSlider.prototype.remove = function(index){
    this.startAnim(this.imgs[index], this.visVal, this.endVal);
  };

  SimpleSlider.prototype.insert = function(index){
    this.startAnim(this.imgs[index], this.startVal, this.visVal);
  };

  SimpleSlider.prototype.change = function(newIndex){
    this.remove(this.actualIndex);
    this.insert(newIndex);
    this.actualIndex = newIndex;
  };

  SimpleSlider.prototype.nextIndex = function(){
    var newIndex = this.actualIndex+1;
    if( newIndex >= this.imgs.length ){
      newIndex = 0;
    }
    return newIndex;
  };

  SimpleSlider.prototype.dispose = function(){

    window.clearInterval(this.actualIndex);

    var i = this.imgs.length;
    while (--i) {
      this.imgs.pop();
    }
    this.imgs = null;

    this.containerElem = null;
    this.interval = null;
    this.trProp = null;
    this.trTime = null;
    this.delay = null;
    this.startVal = null;
    this.endVal = null;
    this.autoPlay = null;
    this.actualIndex = null;
  };

  return SimpleSlider;

});
<commit_msg>Adding z-index support, relates to #4 Fix initial values<commit_after>(function (context, definition) {

  'use strict';

  if (typeof module != 'undefined' && module.exports) {
    module.exports = definition();
  } else if (typeof define == 'function' && define.amd) {
    define(definition);
  } else {
    window.SimpleSlider = definition();
  }

})(this, function () {

  'use strict';

  // requestAnimationFrame polyfill

  if (!Date.now)
    Date.now = function() { return new Date().getTime(); };

  var vendors = ['webkit', 'moz'];
  for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
    var vp = vendors[i];
    window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
    window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] || window[vp+'CancelRequestAnimationFrame']);
  }

  if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || // iOS6 is buggy
    !window.requestAnimationFrame || !window.cancelAnimationFrame) {
    var lastTime = 0;
    window.requestAnimationFrame = function(callback) {
      var now = Date.now();
      var nextTime = Math.max(lastTime + 16, now);
      return setTimeout(function() { callback(lastTime = nextTime); }, nextTime - now);
    };
    window.cancelAnimationFrame = clearTimeout;
  }

  // ------------------

  function getdef(val, def){
    return val===undefined || val===null ? def : val;
  }

  function getUnit(args) {

    var item;
    var count = args.length;
    var unit = '';

    while (--count >= 0) {
      item = args[count];
      if (typeof item === 'string') {
        unit = item
          .replace(parseInt(item, 10) + '', '');
      }
    }

    return unit;

  }

  // Test if have children and throw warning otherwise
  function testChildrenNum(value) {

    if (value <= 0) {
      try {
        console.warn(
          'A SimpleSlider main container element' +
          'should have at least one child.'
        );
      } catch(e) {}

      return true;

    } else {

      return false;
    }

  }

  function anim(target, prop, unit, transitionDuration, startTime, elapsedTime, fromValue, toValue){

    function loop() {

      window.requestAnimationFrame(function requestAnimationFunction(time){

        if (startTime === 0) {
          startTime = time;
        }

        anim(target, prop, unit, transitionDuration, startTime, time, fromValue, toValue);

      });
    }

    var percentual;

    if (startTime === 0) {

      return loop();

    } else {

      percentual = (elapsedTime - startTime) / transitionDuration;

      if (percentual < 1) {

        var diffVal = toValue - fromValue;
        target[prop] = (fromValue + (percentual * diffVal)) + unit;
        loop();

      } else {

        target[prop] = (toValue) + unit;
        //target.zIndex = 0;
      }
    }

  }

  var SimpleSlider = function(containerElem, options){
    this.containerElem = containerElem;
    this.interval = 0;
    if( !options ) options = {};
    this.trProp = getdef(options.transitionProperty, 'opacity');
    this.trTime = getdef(options.transitionTime, 0.5);
    this.delay = getdef(options.transitionDelay, 2);
    this.unit = getUnit([options.startValue, options.visibleValue, options.endValue]);
    this.startVal = parseInt(getdef(options.startValue, 0), 10);
    this.visVal = parseInt(getdef(options.visibleValue, 100), 10);
    this.endVal = parseInt(getdef(options.endValue, 0), 10);
    this.autoPlay = getdef(options.autoPlay, true);
    this.init();
  };

  SimpleSlider.prototype.init = function() {
    this.reset();
    this.configSlideshow();
  };

  SimpleSlider.prototype.reset = function() {

    if (testChildrenNum(this.containerElem.children.length)) {
      return; // Do not follow reset logic if don't have children
    }

    var i = this.containerElem.children.length-1;
    this.imgs = [];
    while (i>=0) {
      this.imgs[i] = this.containerElem.children[i];
      this.imgs[i].style[this.trProp] = this.startVal + this.unit;
      this.imgs[i].style.zIndex = 0;
      i--;
    }

    this.imgs[0].style[this.trProp] = this.visVal + this.unit;
    this.imgs[0].style.zIndex = 1;
    this.actualIndex = 0;
  };

  SimpleSlider.prototype.configSlideshow = function() {

    if (!this.imgs) {
      return;
    }

    if (this.autoPlay) {
      var scope = this;
      if (this.interval) {
        window.clearInterval(this.interval);
      } else {
        this.interval = window.setInterval(function(){
          scope.change(scope.nextIndex());
        }, this.delay*1000);
      }
    }

  };

  SimpleSlider.prototype.startAnim = function(target, fromValue, toValue){

    anim(target.style, this.trProp, this.unit, this.trTime * 1000, 0, 0, fromValue, toValue);

  };

  SimpleSlider.prototype.remove = function(index){
    this.imgs[index].style.zIndex = 1;
    this.startAnim(this.imgs[index], this.visVal, this.endVal);
  };

  SimpleSlider.prototype.insert = function(index){
    this.imgs[index].style.zIndex = 2;
    this.startAnim(this.imgs[index], this.startVal, this.visVal);
  };

  SimpleSlider.prototype.change = function(newIndex){
    this.remove(this.actualIndex);
    this.insert(newIndex);
    this.actualIndex = newIndex;
  };

  SimpleSlider.prototype.nextIndex = function(){
    var newIndex = this.actualIndex+1;
    if( newIndex >= this.imgs.length ){
      newIndex = 0;
    }
    return newIndex;
  };

  SimpleSlider.prototype.dispose = function(){

    window.clearInterval(this.actualIndex);

    var i = this.imgs.length;
    while (--i) {
      this.imgs.pop();
    }
    this.imgs = null;

    this.containerElem = null;
    this.interval = null;
    this.trProp = null;
    this.trTime = null;
    this.delay = null;
    this.startVal = null;
    this.endVal = null;
    this.autoPlay = null;
    this.actualIndex = null;
  };

  return SimpleSlider;

});
<|endoftext|>


<commit_before>'use strict';
angular.module('arethusa.core').controller('NotifierCtrl', [
  '$scope',
  'notifier',
  function ($scope, notifier) {
    $scope.messages = notifier.messages;
    $scope.$watchCollection('messages', function (newVal, oldVal) {
      $scope.lastMessage = notifier.lastMessage();
      $scope.oldMessages = notifier.oldMessages();
    });
  }
]);
<commit_msg>Remove NotifierCtrl - using directives instead<commit_after><|endoftext|>


<commit_before>/*
 * Description : A Gloc Demo module.
 *      Author : Ian McEwan, Ashima Arts.
 *     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
 *               Distributed under the MIT License. See LICENSE file.
 */

function ashimaGlocDemo() {
  var D = this;
  var awe = ashimaWebGLEngine0;

  //var gl, prog, verts, tris;
  var pi = 3.1415926535897932384626433832795029 ;
  var elemDemo, elemRoot, elemCanvas;
  var curW , curH ;
  //var mvMatrix, pMatrix;
  theta = 0.;
  phi = 0.;
  function makePerspective(fovy, aspect, near, far)
    { // swipped from somewhere!
    var tp = near * Math.tan(fovy * Math.PI / 360.0);
    var bt = -tp;
    var lt = bt * aspect;
    var rt = tp * aspect;

    var X =    2*near/(rt-lt);
    var Y =    2*near/(tp-bt);
    var A =  (rt+lt)/(rt-lt);
    var B =  (tp+bt)/(tp-bt);
    var C = -(far+near)/(far-near);
    var D = -2*far*near/(far-near);

    return [X, 0, 0, 0,
            0, Y, 0, 0,
            A, B, C, -1,
            0, 0, D, 0 ] ;
    }

  function glinit() {
    gl = awe.getGlContext(elemCanvas,{});

    if (!gl)
      throw "No webgl here";

    var vs = "\
  const float pi = 3.1415926535897932384626433832795029 ; \
\
  attribute vec2 position2D;                       \
  vec4 P,N; \
  void map2Rto3P() { /* plain */ \
    P = vec4(position2D.x,position2D.y,0.,1.);        \
    N = vec4(0.,0.,1.,1.); \
    }                                  \
\
  void map2Rto3Ps() { /* sphere */ \
    vec2 v = position2D * pi; \
    P = vec4(cos(v.x)*sin(v.y), sin(v.x)*sin(v.y), cos(v.y), 1.0);\
    N = P;\
    }                                  \
\
  uniform mat4 pMatrix; \
  uniform mat4 mvMatrix;\
\
  varying vec4 normal; \
  varying vec2 texCoord;                    \
\
  void main(void) {                       \
    map2Rto3Ps(); \
    texCoord = position2D; \
    normal = N;\
   \
    gl_Position = pMatrix *  (P*mvMatrix  - vec4(0.,0.,4,0.));  \
    /*gl_Position = vec4(Rxy, 1.0,1.0);*/\
    }";

    var fs = "#ifdef GL_ES\nprecision highp float;\n#endif\n\
  const float ipi = 1.0 / 3.1415926535897932384626433832795029 ; \
  uniform sampler2D tex0; \
  varying vec2 texCoord; \
  varying vec4 normal; \
void textureMain() {\
    gl_FragColor = texture2D(tex0, texCoord ); \
    /*gl_FragColor.w = 1.0;*/\
} \
void gradedMain() { \
    gl_FragColor = vec4(abs(texCoord), 1.0,1.0 ); \
} \
  void main(void) { \
    textureMain(); \
    /*gradedMain();*/\
    }";

    prog = awe.compileAndLink(vs, fs);
    var num = 40;
    var step = 2 / (num-1);
     jverts = new Array;
    for (var j = 0; j < num; j++ )
    for (var i = 0; i < num; i++ )
      {
      jverts[(j*num+i)*2+0] = i * step - 1.0;
      jverts[(j*num+i)*2+1] = j * step - 1.0;
      }
     jtris = new Array;
    for (var j = 0; j < num-1 ; j++ )
    for (var i = 0; i < num-1 ; i++ )
      {
      jtris[ (j*(num-1)+i)*6 +0] = (j+0)*num+(i+0) ;
      jtris[ (j*(num-1)+i)*6 +1] = (j+0)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +2] = (j+1)*num+(i+0) ;

      jtris[ (j*(num-1)+i)*6 +3] = (j+0)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +4] = (j+1)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +5] = (j+1)*num+(i+0) ;
      }
    verts = awe.makeBuffer(gl.ARRAY_BUFFER,gl.FLOAT,2,gl.STATIC_DRAW,jverts );
    tris = awe.makeBuffer(gl.ELEMENT_ARRAY_BUFFER,gl.UNSIGNED_SHORT,3,gl.STATIC_DRAW,jtris );

    }

var demoTex, demoImg;
  function renderinit()
    {
    demoTex = awe.textureCreate();
    demoImg = new Image ;
    demoImg.onload = function() {
      demoTex.aweFromElem(demoImg);
      demoTex.aweParams( gl.LINEAR, gl.LINEAR, gl.REPEAT, gl.REPEAT, false);
      }
    demoImg.src = "Stone1.jpg";

    prog.aweUse();
    demoTex.aweSet(0, prog.aweSym['tex0'] );
    verts.aweSetVertexAttPtr(prog.aweSym["position2D"]);
    }

  function updateCanvasSize() {
    curW = elemRoot.clientWidth;
    curH = elemRoot.clientHeight;
    pMatrix = new Float32Array(makePerspective( 45, curW/curH, 2, 10. ));
    gl.viewport(0, 0,
      gl.viewportWidth  = elemCanvas.width  = curW,
      gl.viewportHeight = elemCanvas.height = curH  );
    }

  function resizeNow()
    {
    updateCanvasSize();
    D.animator.play();
    }

  function clearFrame()
    {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clearDepth(100.0);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
    gl.enable(gl.CULL_FACE);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    }

  function render() {
    var w = elemRoot.clientWidth;
    var h = elemRoot.clientHeight;
    phi += pi / 240;

    if (w != curW || h != curH) {
      D.animator.pause();
      setTimeout(resizeNow,200);
      }
    else
      {
      clearFrame();
      ct = Math.cos(theta); st = Math.sin(theta);
      cp = Math.cos(phi);   sp = Math.sin(phi);

      /*mvMatrix = new Float32Array( [
      ct*cp, -sp, st*cp, 0,
      ct*sp,  cp, st*sp, 0,
      -st,    0,  ct,    0,
      0,      0,  0,     1.0 ] );*/
      mvMatrix = new Float32Array( [
      cp, -sp, 0, 0,
      ct*sp, ct*cp ,-st , 0,
      st*sp, st*cp, ct, 0,
      0,      0,  0,     1.0 ] );

      gl.uniformMatrix4fv(prog.aweSym["pMatrix"], false, pMatrix);
      gl.uniformMatrix4fv(prog.aweSym["mvMatrix"], false, mvMatrix);
      tris.drawElements(gl.TRIANGLES);
      }
    }

  D.updateCanvasSize = updateCanvasSize;
  //D.updateElems = updateElems;

  D.init = function(p) {
    elemRoot   = p;

    elemCanvas = document.createElement("canvas");
    elemCanvas.style.zIndex = -1;
    elemCanvas.style.position = "absolute";
    elemDemo = document.createElement("div");
    elemDemo.style.zIndex = 1;
    elemDemo.appendChild(elemCanvas);
    elemRoot.appendChild(elemDemo);

    glinit();
    renderinit();
    updateCanvasSize();
    D.animator = awe.animationStart(render,gl.canvas,1000/30,true);

    theta = -1.0;
    phi = 0;
    }

  var rendering = false;

};

<commit_msg>added simple lighting.<commit_after>/*
 * Description : A Gloc Demo module.
 *      Author : Ian McEwan, Ashima Arts.
 *     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
 *               Distributed under the MIT License. See LICENSE file.
 */

function ashimaGlocDemo() {
  var D = this;
  var awe = ashimaWebGLEngine0;

  //var gl, prog, verts, tris;
  var pi = 3.1415926535897932384626433832795029 ;
  var elemDemo, elemRoot, elemCanvas;
  var curW , curH ;
  //var mvMatrix, pMatrix;
  theta = 0.;
  phi = 0.;
  function makePerspective(fovy, aspect, near, far)
    { // swipped from somewhere!
    var tp = near * Math.tan(fovy * Math.PI / 360.0);
    var bt = -tp;
    var lt = bt * aspect;
    var rt = tp * aspect;

    var X =    2*near/(rt-lt);
    var Y =    2*near/(tp-bt);
    var A =  (rt+lt)/(rt-lt);
    var B =  (tp+bt)/(tp-bt);
    var C = -(far+near)/(far-near);
    var D = -2*far*near/(far-near);

    return [X, 0, 0, 0,
            0, Y, 0, 0,
            A, B, C, -1,
            0, 0, D, 0 ] ;
    }

  function glinit() {
    gl = awe.getGlContext(elemCanvas,{});

    if (!gl)
      throw "No webgl here";

    var vs = "\
  const float pi = 3.1415926535897932384626433832795029 ; \
\
  attribute vec2 position2D;                       \
  vec4 P,N; \
  void map2Rto3P() { /* plain */ \
    P = vec4(position2D.x,position2D.y,0.,1.);        \
    N = vec4(0.,0.,1.,1.); \
    }                                  \
\
  void map2Rto3Ps() { /* sphere */ \
    vec2 v = position2D * pi; \
    P = vec4(cos(v.x)*sin(v.y), sin(v.x)*sin(v.y), cos(v.y), 1.0);\
    N = P;\
    }                                  \
\
  uniform mat4 pMatrix; \
  uniform mat4 mvMatrix;\
\
  varying vec4 normal; \
  varying vec2 texCoord;                    \
  varying vec4 position4; \
\
  void main(void) {                       \
    map2Rto3Ps(); \
    texCoord = position2D; \
    normal = N*mvMatrix;\
   \
    position4 = P*mvMatrix  - vec4(0.,0.,4,0.); \
    gl_Position = pMatrix * position4;\
    }";

    var fs = "#ifdef GL_ES\nprecision highp float;\n#endif\n\
  const float ipi = 1.0 / 3.1415926535897932384626433832795029 ; \
  uniform sampler2D tex0; \
  varying vec2 texCoord; \
  varying vec4 position4; \
\
  void lightingNull() {\
  }\
\
  varying vec4 normal; \
  uniform vec4 ambientColor ;\
  uniform vec4 directionalColor ;\
  uniform vec4 lightingDirection ;\
  void lightingSimple() {\
    gl_FragColor *= \
      ambientColor + directionalColor * max(dot(normal, lightingDirection),0.);\
  }\
  void textureMain() {\
    gl_FragColor = texture2D(tex0, texCoord ); \
    /*gl_FragColor.w = 1.0;*/\
  } \
  void gradedMain() { \
    gl_FragColor = vec4(abs(texCoord), 1.0,1.0 ); \
  } \
  void main(void) { \
    textureMain(); \
    /*gradedMain();*/\
    lightingSimple();\
    }";

    prog = awe.compileAndLink(vs, fs);
    var num = 40;
    var step = 2 / (num-1);
     jverts = new Array;
    for (var j = 0; j < num; j++ )
    for (var i = 0; i < num; i++ )
      {
      jverts[(j*num+i)*2+0] = i * step - 1.0;
      jverts[(j*num+i)*2+1] = j * step - 1.0;
      }
     jtris = new Array;
    for (var j = 0; j < num-1 ; j++ )
    for (var i = 0; i < num-1 ; i++ )
      {
      jtris[ (j*(num-1)+i)*6 +0] = (j+0)*num+(i+0) ;
      jtris[ (j*(num-1)+i)*6 +1] = (j+0)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +2] = (j+1)*num+(i+0) ;

      jtris[ (j*(num-1)+i)*6 +3] = (j+0)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +4] = (j+1)*num+(i+1) ;
      jtris[ (j*(num-1)+i)*6 +5] = (j+1)*num+(i+0) ;
      }
    verts = awe.makeBuffer(gl.ARRAY_BUFFER,gl.FLOAT,2,gl.STATIC_DRAW,jverts );
    tris = awe.makeBuffer(gl.ELEMENT_ARRAY_BUFFER,gl.UNSIGNED_SHORT,3,gl.STATIC_DRAW,jtris );

    }

var demoTex, demoImg;
  function renderinit()
    {
    demoTex = awe.textureCreate();
    demoImg = new Image ;
    demoImg.onload = function() {
      demoTex.aweFromElem(demoImg);
      demoTex.aweParams( gl.LINEAR, gl.LINEAR, gl.REPEAT, gl.REPEAT, false);
      }
    demoImg.src = "Stone1.jpg";

    prog.aweUse();
    demoTex.aweSet(0, prog.aweSym['tex0'] );
    verts.aweSetVertexAttPtr(prog.aweSym["position2D"]);
    }

  function updateCanvasSize() {
    curW = elemRoot.clientWidth;
    curH = elemRoot.clientHeight;
    pMatrix = new Float32Array(makePerspective( 45, curW/curH, 2, 10. ));
    gl.viewport(0, 0,
      gl.viewportWidth  = elemCanvas.width  = curW,
      gl.viewportHeight = elemCanvas.height = curH  );
    }

  function resizeNow()
    {
    updateCanvasSize();
    D.animator.play();
    }

  function clearFrame()
    {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clearDepth(100.0);
    gl.enable(gl.DEPTH_TEST);
    gl.disable(gl.BLEND);
    gl.enable(gl.CULL_FACE);
    gl.depthFunc(gl.LEQUAL);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    }

  function render() {
    var w = elemRoot.clientWidth;
    var h = elemRoot.clientHeight;
    phi += pi / 240;

    if (w != curW || h != curH) {
      D.animator.pause();
      setTimeout(resizeNow,200);
      }
    else
      {
      clearFrame();
      ct = Math.cos(theta); st = Math.sin(theta);
      cp = Math.cos(phi);   sp = Math.sin(phi);

      mvMatrix = new Float32Array( [
      cp, -sp, 0, 0,
      ct*sp, ct*cp ,-st , 0,
      st*sp, st*cp, ct, 0,
      0,      0,  0,     1.0 ] );

      gl.uniformMatrix4fv(prog.aweSym["pMatrix"], false, pMatrix);
      gl.uniformMatrix4fv(prog.aweSym["mvMatrix"], false, mvMatrix);
      gl.uniform4fv(prog.aweSym["ambientColor"], [0.1,0.1,0.1,1.0] );
      gl.uniform4fv(prog.aweSym["directionalColor"], [0.9,0.9,0.9,1.0] );
      gl.uniform4fv(prog.aweSym["lightingDirection"], [1.0,1.0,1.0,1.0] );

      tris.drawElements(gl.TRIANGLES);
      }
    }

  D.updateCanvasSize = updateCanvasSize;
  //D.updateElems = updateElems;

  D.init = function(p) {
    elemRoot   = p;

    elemCanvas = document.createElement("canvas");
    elemCanvas.style.zIndex = -1;
    elemCanvas.style.position = "absolute";
    elemDemo = document.createElement("div");
    elemDemo.style.zIndex = 1;
    elemDemo.appendChild(elemCanvas);
    elemRoot.appendChild(elemDemo);

    glinit();
    renderinit();
    updateCanvasSize();
    D.animator = awe.animationStart(render,gl.canvas,1000/30,true);

    theta = -1.0;
    phi = 0;
    }

  var rendering = false;

};

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOController',
    'foam.comics.DAOUpdateControllerView',
    'foam.u2.view.ScrollTableView'
  ],

  imports: [
    'stack',
    'summaryView? as importedSummaryView',
    'data? as importedData',
    'window'
  ],

  exports: [
    'data.selection as selection',
    'data.data as dao',
    'dblclick'
  ],

  // TODO: wrong class name, fix when ActionView fixed.
  css: `
    .middle-row {
      display: flex;
    }

    .middle-row > *:not(:empty) {
      margin-left: 10px;
    }

    .middle-row > *:last-child {
      margin-right: 10px;
    }

    .middle-row .actions {
      display: inline-block;
      margin-bottom: 10px;
    }

    .middle-row .net-nanopay-ui-ActionView {
      background: #59aadd;
      color: white;
      margin-right: 10px;
    }
  `,

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOController',
      name: 'data',
      expression: function(importedData) { return importedData; }
    },
    {
      name: 'cls',
      expression: function(data) { return data.cls_; }
    },
    {
      name: 'summaryView',
      factory: function() {
        return this.importedSummaryView$ ?
            this.importedSummaryView :
            { class: 'foam.u2.view.ScrollTableView' };
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$data$of) {
        return 'Browse ' + data$data$of.name;
      }
    }
  ],

  reactions: [
    [ 'data', 'action.create', 'onCreate' ],
    [ 'data', 'edit', 'onEdit' ],
    [ 'data', 'action.findRelatedObject', 'onFindRelated' ],
    [ 'data', 'finished', 'onFinished' ]
  ],

  methods: [
    function initE() {
      var self = this;

      this.
        addClass(this.myClass()).
        tag(this.data.topBorder$).
        start().
          addClass('middle-row').
          tag(this.data.leftBorder).
          start().add(this.cls.PREDICATE).end().
          start().
            style({ 'overflow-x': 'auto' }).
            start().
              addClass('actions').
              show(self.mode$.map((m) => m === foam.u2.DisplayMode.RW)).
                start().add(self.cls.getAxiomsByClass(foam.core.Action)).end().
            end().
            start().
              style({ 'overflow-x': 'auto' }).
              tag(this.summaryView, { data$: this.data.filteredDAO$ }).
            end().
          end().
          tag(this.data.rightBorder$).
        end().
        tag(this.data.bottomBorder$);
    },

    function dblclick(obj) {
      this.onEdit(null, null, obj.id);
    }
  ],

  listeners: [
    function onCreate() {
      this.stack.push({
        class: 'foam.comics.DAOCreateControllerView'
      }, this);
    },

    function onEdit(s, edit, id) {
      this.stack.push({
        class: 'foam.comics.DAOUpdateControllerView',
        key: id
      }, this);
    },

    function onFindRelated() {
      var data = this.DAOController.create({
        data: this.data.relationship.targetDAO,
        addEnabled: true,
        relationship: this.data.relationship
      });

      this.stack.push({
        class: 'foam.comics.DAOControllerView',
        data: data
      }, this);
    },

    function onFinished() {
      this.stack.back();
    }
  ]
});
<commit_msg>DAO Controller View implements export modal<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.comics',
  name: 'DAOControllerView',
  extends: 'foam.u2.View',

  requires: [
    'foam.comics.DAOController',
    'foam.u2.view.ScrollTableView',
    'foam.u2.dialog.Popup',
    'foam.u2.dialog.ExportModal'
  ],

  imports: [
    'stack',
    'summaryView? as importedSummaryView',
    'data? as importedData',
    'window'
  ],

  exports: [
    'data.selection as selection',
    'data.data as dao',
    'dblclick'
  ],

  // TODO: wrong class name, fix when ActionView fixed.
  css: `
    ^ {
      display: flex;
    }

    ^ > * {
      margin-left: 10px;
    }

    ^ > *:last-child {
      margin-right: 10px;
    }

    ^ .actions {
      display: inline-block;
      margin-bottom: 10px;
    }

    ^ .net-nanopay-ui-ActionView {
      background: #59aadd;
      color: white;
      margin-right: 10px;
    }
  `,

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.comics.DAOController',
      name: 'data',
      expression: function(importedData) { return importedData; }
    },
    {
      name: 'cls',
      expression: function(data) { return data.cls_; }
    },
    {
      name: 'summaryView',
      factory: function() {
        return this.importedSummaryView$ ?
            this.importedSummaryView :
            { class: 'foam.u2.view.ScrollTableView' };
      }
    },
    {
      class: 'String',
      name: 'title',
      expression: function(data$data$of) {
        return 'Browse ' + data$data$of.name;
      }
    }
  ],

  reactions: [
    [ 'data', 'action.create', 'onCreate' ],
    [ 'data', 'edit', 'onEdit' ],
    [ 'data', 'action.findRelatedObject', 'onFindRelated' ],
    [ 'data', 'finished', 'onFinished' ]
  ],

  methods: [
    function initE() {
      var self = this;

      this.
        addClass(this.myClass()).
        start().add(this.cls.PREDICATE).end().
        start().
          style({ 'overflow-x': 'auto' }).
          start().
            addClass('actions').
            show(self.mode$.map((m) => m === foam.u2.DisplayMode.RW)).
              start().add(self.cls.getAxiomsByClass(foam.core.Action)).end().
          end().
          startContext({ data: this }).
            start(this.EXPORT_DATA).
            end().
          endContext().
          start().
            style({ 'overflow-x': 'auto' }).
            tag(this.summaryView, { data$: this.data.filteredDAO$ }).
          end().
        end();
    },

    function dblclick(obj) {
      this.onEdit(null, null, obj.id);
    }
  ],

  listeners: [
    function onCreate() {
      this.stack.push({
        class: 'foam.comics.DAOCreateControllerView'
      }, this);
    },

    function onEdit(s, edit, id) {
      this.stack.push({
        class: 'foam.comics.DAOUpdateControllerView',
        key: id
      }, this);
    },

    function onFindRelated() {
      var data = this.DAOController.create({
        data: this.data.relationship.targetDAO,
        addEnabled: true,
        relationship: this.data.relationship
      });

      this.stack.push({
        class: 'foam.comics.DAOControllerView',
        data: data
      }, this);
    },

    function onFinished() {
      this.stack.back();
    }
  ],

  actions: [
    {
      name: 'exportData',
      label: 'Export',
      code: function(X) {
        this.add(this.Popup.create().tag({
          class: 'foam.u2.ExportModal',
          exportData: this.data.data
        }));
      }
    }
  ]
});
<|endoftext|>


<commit_before>define([
   "underscore", "jquery", "backbone", "logger", "extract-youtube-id",
   "underscore-template-config"
], function(_, $, Backbone, logger, extractYoutubeId) {

var DATA_API_URL = "https://gdata.youtube.com/feeds/api/videos/{id}?v=2&alt=json-in-script&callback=?",
    IFRAME_API_URL = "https://www.youtube.com/iframe_api",
    video = {};

if (!window.YouTubeLoadQueue) {
    window.YouTubeLoadQueue = [];
}
if (!window.onYouTubeIframeAPIReady) {
    window.onYouTubeIframeAPIReady = function() {
        _.each(window.YouTubeLoadQueue, function(params) {
            new YT.Player(params.id, params.attrs);
        });
        window.YouTubeLoadQueue = [];
    };
}

var VIDEO_DETAILS_CACHE = {};
video.getVideoDetails = function(id, callback) {
    if (id in VIDEO_DETAILS_CACHE) {
        return callback(VIDEO_DETAILS_CACHE[id]);
    }
    $.getJSON(
        DATA_API_URL.replace("{id}", id)
    ).done(function(data) {
        VIDEO_DETAILS_CACHE[id] = {
            id: id,
            title: data.entry.title.$t,
            duration: parseInt(data.entry.media$group.yt$duration.seconds),
            thumbnail: data.entry.media$group.media$thumbnail[0]
        };
    }).fail(function() {
        VIDEO_DETAILS_CACHE[id] = null;
    }).always(function() {
        callback(VIDEO_DETAILS_CACHE[id]);
    });

};

video.extractYoutubeId = extractYoutubeId.extractYoutubeId;

video.YoutubeVideo = Backbone.View.extend({
    tagName: "table",
    template: _.template($("#youtube-video").html()),
    controlsTemplate: _.template($("#youtube-video-controls").html()),
    events: {
        'click .play-for-everyone': 'playForEveryone',
        'click .sync-lock': 'toggleSync',
        'click .video-settings': 'triggerVideoSettings',
    },
    initialize: function(options) {
        this.ytID = options.ytID;
        this.showGroupControls = options.showGroupControls;
        this.permitGroupControl = options.permitGroupControl;
        this.intendToSync = true;
        _.bindAll(this, "playForEveryone", "toggleSync",
                        "onPlayerReady", "onPlayerStateChange",
                        "triggerVideoSettings");
        this.logger = new logger.Logger("VIDEO", "debug");
    },
    render: function() {
        this.$el.html(this.template({cid: this.cid}));
        window.YouTubeLoadQueue.push({
            id: 'player-' + this.cid,
            attrs: {
                width: '320',
                height: '240',
                videoId: this.ytID,
                events: {
                    onReady: this.onPlayerReady,
                    onStateChange: this.onPlayerStateChange
                },
                playerVars: { wmode: "transparent" }
            }
        });
        // Check if the YouTube API has loaded yet.  Load it if not.
        if (!window.YT) {
            var tag = document.createElement('script');
            tag.src = IFRAME_API_URL;
            document.body.appendChild(tag);
        } else {
            // API is loaded already -- tell it to run the load queue.
            window.onYouTubeIframeAPIReady();
        }
        this.renderControls();
        if (this.permitGroupControl) {
            setInterval(_.bind(this.renderTime, this), 500);
        }
    },
    renderControls: function() {
        this.$(".video-controls").html(this.controlsTemplate({
            playing: this.isPlayingForEveryone(),
            awaitingStart: this.isAwaitingStart(),
            synced: this.isSynced(),
            showGroupControls: this.showGroupControls,
            intendToSync: this.intendToSync,
            syncAvailable: this.isSyncAvailable()
        }));
        this.trigger("renderControls");
    },
    renderTime: function() {
        var time;
        var formatTime = function(seconds) {
            var hours = parseInt(seconds / (60 * 60));
            var minutes = parseInt((seconds % 3600) / 60);
            var seconds = parseInt(seconds % 60);
            hours = (hours > 0 ? hours + ":" : "");
            minutes = ((hours && (minutes < 10)) ? "0" : "") + minutes + ":";
            seconds = (seconds < 10 ? "0" : "") + seconds;
            return hours + minutes + seconds;
        };
        if (this.ctrl) {
            if (this.ctrl.state === "playing") {
                time = formatTime(this.ctrl.time +
                                  (Date.now() - this.ctrl.localBegin) / 1000);
            } else if (this.ctrl.state === "paused") {
                if (!this.player) {
                    time = "";
                } else {
                    time = formatTime(this.player.getCurrentTime());
                }
            }
        } else {
            time = "";
        }
        this.$(".time-indicator").html(time);
        this.trigger("render-time", time);
    },
    setVideoId: function(id) {
        if (id != this.ytID) {
            this.ytID = id;
            this.render();
        }
    },
    isSyncAvailable: function() {
        return !!this.ctrl && this.ctrl.state === "playing";
    },
    isSynced: function() {
        return this.isSyncAvailable() && this.isPlayStatusSynced() && this.isTimeSynced();
    },
    isTimeSynced: function() {
        if (!this.player) {
            return false;
        }
        if (this.ctrl.state === "playing") {
            // How long since the control signal told us to begin, in seconds?
            var diff = (Date.now() - this.ctrl.localBegin) / 1000;
            // Use that diff to figure out where we ought to be in the video.
            var expected = this.ctrl.time + diff;
            // Consider us synced if we're within 10 seconds of that.
            return Math.abs(expected - this.player.getCurrentTime()) < 10
        } else {
            return true;
        }
    },
    isPlayStatusSynced: function() {
        return this.player && (
            (this.ctrl.state == "playing") == (this.player.getPlayerState() == YT.PlayerState.PLAYING)
        );
    },
    receiveControl: function(args) {
        this.logger.debug("Receive control", args.state, args);
        //
        // Mute control: out-of-band from regular video sync. Currently only
        // triggered by joining a hangout-on-air for which this is the embed.
        //
        if (args.mute === true || args.mute === false) {
            return this.handleMute(args.mute);
        }
        //
        // Regular video sync.
        //
        this.ctrl = args;
        if (args.localBegin === undefined) {
            this.ctrl.localBegin = Date.now();
        }
        if (!this.player) {
            // If we don't have a player yet, delay until it's ready.
            setTimeout(_.bind(function() {
                this.logger.debug("player not ready yet, delaying.");
                this.receiveControl(args);
            }, this), 1000);
            return;
        }
        // Do we have no intention of syncing?  Return.
        if (!this.intendToSync) {
            this.renderControls();
            return;
        }
        if (args.state === "paused" || args.state === "playing") {
            // Cancel polling for the video to start if someone else has
            // triggered play.
            this.cancelPollForStart();
        }
        // Has the video finished? Tell the server to pause.
        var dur = this.player.getDuration();
        if (args.state === "playing" && dur > 0 && args.time > dur) {
            this.logger.info("Pausing, video is over");
            if (this.permitGroupControl) {
                this.logger.info("Telling server to pause.");
                this.trigger("control-video", {action: "pause"});
            } else {
                this.logger.debug("Not telling server to pause - not permitted.");
            }
            this.player.pauseVideo();
            return;
        }
        if (!this.isPlayStatusSynced()) {
            if (args.state === "playing") {
                this.logger.debug("Playing");
                this.player.playVideo();
                this.once("player-state-playing", _.bind(this.syncTime, this));
            } else {
                this.logger.debug("Pausing");
                this.player.pauseVideo();
            }
        } else if (args.state === "playing") {
            this.syncTime();
        }

        this.renderControls();
    },
    syncTime: function() {
        if (!this.isTimeSynced()) {
            var curTime = this.ctrl.time + (Date.now() - this.ctrl.localBegin) / 1000;
            this.logger.debug("Seeking to", curTime);
            this.player.seekTo(curTime, true);
        }
    },
    handleMute: function(mute) {
        if (!this.player) {
            // This is a slightly ugly, slightly dangerous hack -- if we get a
            // mute request, but the player isn't ready yet, delay 100ms and
            // try again.
            return setTimeout(_.bind(function() {
                this.handleMute(mute);
            }, this), 100);
        }
        if (mute) {
            this.player.mute();
        } else {
            this.player.unMute();
        }
    },
    onPlayerReady: function(event) {
        this.player = event.target;
        // Fix for z-index issues -- see http://stackoverflow.com/a/9074366
        this.$("iframe").attr("wmode", "Opaque");
    },
    onPlayerStateChange: function(event) {
        this.renderControls();
        this.logger.debug("onPlayerStateChange", event.data);
        // Google gives us no "onSeekTo" or seek-related player state change,
        // so we have to be a little tricky about figuring out if someone has
        // tried to seek to elsewhere in the video.
        //
        // If we get a pause signal ...
        if (event.data == YT.PlayerState.PAUSED &&
                // ... when 'sync' enabled ...
                this.intendToSync &&
                // ... and the video is playing ...
                this.isSyncAvailable()) {
            // ... interpret it as an intention to seek or pause.
            this.logger.debug("times", this.ctrl.time, this.player.getCurrentTime());
            if (this.ctrl.state === "playing" && Math.abs(
                    this.player.getDuration() - this.ctrl.time) > 10) {
                this.toggleSync();
            }
        }
        // Trigger report of human-readable state.
        var state;
        switch (event.data) {
            case YT.PlayerState.PAUSED:
                state = "paused";
                break;
            case YT.PlayerState.PLAYING:
                state = "playing";
                break;
            case YT.PlayerState.BUFFERING:
                state = "buffering";
                break;
            case YT.PlayerState.CUED:
                state = "cued";
                break;
            case YT.PlayerState.ENDED:
                state = "ended";
                break;
        }
        this.trigger("player-state-change", state);
        this.trigger("player-state-" + state);
    },
    playForEveryone: function(event) {
        if (event) { event.preventDefault(); }
        var playing = this.isPlayingForEveryone();
        var awaitingStart = this.isAwaitingStart();
        var args;
        if (playing || awaitingStart) {
            args = {action: "pause"};
            this.cancelPollForStart();
        } else {
            var dur = this.player.getDuration();
            if (dur === 0) {
                this.pollForStart();
                // Don't trigger any server-side control yet; but *do* start
                // the player, so we get notified when its state changes.  If
                // we pause, it'll get paused by the "control-video" broadcast.
                this.player.playVideo();
                this.renderControls();
                return;
            } else {
                if (this.player.getCurrentTime() >= dur) {
                    time = 0;
                } else {
                    time = this.player.getCurrentTime();
                }
                args = {action: "play", time: time};
            }
        }
        this.trigger("control-video", args);
    },
    pollForStart: function() {
        this._awaitingStart = setInterval(_.bind(function() {
            var dur = this.player.getDuration();
            if (dur > 0) {
                this.cancelPollForStart();
                this.playForEveryone();
            }
        }, this), 100);
    },
    cancelPollForStart: function() {
        if (this._awaitingStart) {
            clearInterval(this._awaitingStart);
        }
        this._awaitingStart = null;
    },
    isAwaitingStart: function() {
        return !!this._awaitingStart;
    },
    toggleSync: function(event) {
        if (event) { event.preventDefault(); }
        if (this.intendToSync) {
            this.intendToSync = false;
            this.renderControls();
        } else {
            this.intendToSync = true;
            if (this.ctrl) {
                this.receiveControl(this.ctrl);
            }
        }
    },
    triggerVideoSettings: function(event) {
        this.trigger("video-settings", this);
    },
    isPlayingForEveryone: function() {
        return this.ctrl && this.ctrl.state === "playing";
    }
});

return video;

});
<commit_msg>Restore auto-pausing on video end.<commit_after>define([
   "underscore", "jquery", "backbone", "logger", "extract-youtube-id",
   "underscore-template-config"
], function(_, $, Backbone, logger, extractYoutubeId) {

var DATA_API_URL = "https://gdata.youtube.com/feeds/api/videos/{id}?v=2&alt=json-in-script&callback=?",
    IFRAME_API_URL = "https://www.youtube.com/iframe_api",
    video = {};

if (!window.YouTubeLoadQueue) {
    window.YouTubeLoadQueue = [];
}
if (!window.onYouTubeIframeAPIReady) {
    window.onYouTubeIframeAPIReady = function() {
        _.each(window.YouTubeLoadQueue, function(params) {
            new YT.Player(params.id, params.attrs);
        });
        window.YouTubeLoadQueue = [];
    };
}

var VIDEO_DETAILS_CACHE = {};
video.getVideoDetails = function(id, callback) {
    if (id in VIDEO_DETAILS_CACHE) {
        return callback(VIDEO_DETAILS_CACHE[id]);
    }
    $.getJSON(
        DATA_API_URL.replace("{id}", id)
    ).done(function(data) {
        VIDEO_DETAILS_CACHE[id] = {
            id: id,
            title: data.entry.title.$t,
            duration: parseInt(data.entry.media$group.yt$duration.seconds),
            thumbnail: data.entry.media$group.media$thumbnail[0]
        };
    }).fail(function() {
        VIDEO_DETAILS_CACHE[id] = null;
    }).always(function() {
        callback(VIDEO_DETAILS_CACHE[id]);
    });

};

video.extractYoutubeId = extractYoutubeId.extractYoutubeId;

video.YoutubeVideo = Backbone.View.extend({
    tagName: "table",
    template: _.template($("#youtube-video").html()),
    controlsTemplate: _.template($("#youtube-video-controls").html()),
    events: {
        'click .play-for-everyone': 'playForEveryone',
        'click .sync-lock': 'toggleSync',
        'click .video-settings': 'triggerVideoSettings',
    },
    initialize: function(options) {
        this.ytID = options.ytID;
        this.showGroupControls = options.showGroupControls;
        this.permitGroupControl = options.permitGroupControl;
        this.intendToSync = true;
        _.bindAll(this, "playForEveryone", "toggleSync",
                        "onPlayerReady", "onPlayerStateChange",
                        "triggerVideoSettings");
        this.logger = new logger.Logger("VIDEO", "debug");
    },
    render: function() {
        this.$el.html(this.template({cid: this.cid}));
        window.YouTubeLoadQueue.push({
            id: 'player-' + this.cid,
            attrs: {
                width: '320',
                height: '240',
                videoId: this.ytID,
                events: {
                    onReady: this.onPlayerReady,
                    onStateChange: this.onPlayerStateChange
                },
                playerVars: { wmode: "transparent" }
            }
        });
        // Check if the YouTube API has loaded yet.  Load it if not.
        if (!window.YT) {
            var tag = document.createElement('script');
            tag.src = IFRAME_API_URL;
            document.body.appendChild(tag);
        } else {
            // API is loaded already -- tell it to run the load queue.
            window.onYouTubeIframeAPIReady();
        }
        this.renderControls();
        setInterval(_.bind(this.renderTime, this), 500);
    },
    renderControls: function() {
        this.$(".video-controls").html(this.controlsTemplate({
            playing: this.isPlayingForEveryone(),
            awaitingStart: this.isAwaitingStart(),
            synced: this.isSynced(),
            showGroupControls: this.showGroupControls,
            intendToSync: this.intendToSync,
            syncAvailable: this.isSyncAvailable()
        }));
        this.trigger("renderControls");
    },
    renderTime: function() {
        var time;
        var formatTime = function(seconds) {
            var hours = parseInt(seconds / (60 * 60));
            var minutes = parseInt((seconds % 3600) / 60);
            var seconds = parseInt(seconds % 60);
            hours = (hours > 0 ? hours + ":" : "");
            minutes = ((hours && (minutes < 10)) ? "0" : "") + minutes + ":";
            seconds = (seconds < 10 ? "0" : "") + seconds;
            return hours + minutes + seconds;
        };
        if (this.ctrl) {
            if (this.ctrl.state === "playing") {
                time = formatTime(this.getCurSyncSeconds());
            } else if (this.ctrl.state === "paused") {
                if (!this.player) {
                    time = "";
                } else {
                    time = formatTime(this.player.getCurrentTime());
                }
            }
        } else {
            time = "";
        }
        this.$(".time-indicator").html(time);
        this.trigger("render-time", time);
    },
    setVideoId: function(id) {
        if (id != this.ytID) {
            this.ytID = id;
            this.render();
        }
    },
    isSyncAvailable: function() {
        return !!this.ctrl && this.ctrl.state === "playing";
    },
    isSynced: function() {
        return this.isSyncAvailable() && this.isPlayStatusSynced() && this.isTimeSynced();
    },
    isTimeSynced: function() {
        if (!this.player) {
            return false;
        }
        var curSyncTime = this.getCurSyncSeconds();
        if (curSyncTime !== null) {
            return Math.abs(curSyncTime - this.player.getCurrentTime()) < 10
        } else {
            return true;
        }
    },
    isPlayStatusSynced: function() {
        return this.player && (
            (this.ctrl.state == "playing") == (this.player.getPlayerState() == YT.PlayerState.PLAYING)
        );
    },
    getCurSyncSeconds: function() {
        // Return the current sync time of the playing video, or null if none.
        if (this.isSyncAvailable()) {
            return this.ctrl.time + (Date.now() - this.ctrl.localBegin) / 1000;
        }
        return null;
    },
    receiveControl: function(args) {
        this.logger.debug("Receive control", args.state, args);
        //
        // Mute control: out-of-band from regular video sync. Currently only
        // triggered by joining a hangout-on-air for which this is the embed.
        //
        if (args.mute === true || args.mute === false) {
            return this.handleMute(args.mute);
        }
        //
        // Regular video sync.
        //
        this.ctrl = args;
        if (args.localBegin === undefined) {
            this.ctrl.localBegin = Date.now();
        }
        if (!this.player) {
            // If we don't have a player yet, delay until it's ready.
            setTimeout(_.bind(function() {
                this.logger.debug("player not ready yet, delaying.");
                this.receiveControl(args);
            }, this), 1000);
            return;
        }
        // Do we have no intention of syncing?  Return.
        if (!this.intendToSync) {
            this.renderControls();
            return;
        }
        if (args.state === "paused" || args.state === "playing") {
            // Cancel polling for the video to start if someone else has
            // triggered play.
            this.cancelPollForStart();
        }
        if (!this.isPlayStatusSynced()) {
            if (args.state === "playing") {
                this.logger.debug("Playing");
                this.player.playVideo();
                this.once("player-state-playing", _.bind(this.syncTime, this));
            } else {
                this.logger.debug("Pausing");
                this.player.pauseVideo();
            }
        } else if (args.state === "playing") {
            this.syncTime();
        }

        this.renderControls();
    },
    syncTime: function() {
        if (!this.isTimeSynced()) {
            var curSyncTime = this.getCurSyncSeconds();
            if (curSyncTime !== null) {
                this.logger.debug("Seeking to", curSyncTime);
                this.player.seekTo(curSyncTime, true);
            }
        }
    },
    handleMute: function(mute) {
        if (!this.player) {
            // This is a slightly ugly, slightly dangerous hack -- if we get a
            // mute request, but the player isn't ready yet, delay 100ms and
            // try again.
            return setTimeout(_.bind(function() {
                this.handleMute(mute);
            }, this), 100);
        }
        if (mute) {
            this.player.mute();
        } else {
            this.player.unMute();
        }
    },
    onPlayerReady: function(event) {
        this.player = event.target;
        // Fix for z-index issues -- see http://stackoverflow.com/a/9074366
        this.$("iframe").attr("wmode", "Opaque");
    },
    onPlayerStateChange: function(event) {
        this.renderControls();
        this.logger.debug("onPlayerStateChange", event.data);
        // Google gives us no "onSeekTo" or seek-related player state change,
        // so we have to be a little tricky about figuring out if someone has
        // tried to seek to elsewhere in the video.
        //
        // If we get a pause signal and the video is playing ...
        if (event.data == YT.PlayerState.PAUSED && this.isSyncAvailable()) {
            // Has the video finished? Tell the server to pause.
            var curSyncTime = this.getCurSyncSeconds();
            var dur = this.player.getDuration();
            var closeEnoughToEnd = dur > 0 && Math.abs(curSyncTime - dur) < 10;
            if (this.isTimeSynced() && closeEnoughToEnd) {
                this.logger.info("Pausing, video is over");
                if (this.permitGroupControl) {
                    this.logger.info("Telling server to pause.");
                    this.trigger("control-video", {action: "pause"});
                } else {
                    this.logger.debug("Not telling server to pause - not permitted.");
                }
                this.player.pauseVideo();
            } else if (this.intendToSync) {
                // ... interpret it as an intention to seek or pause.
                this.logger.debug("times", this.ctrl.time, this.player.getCurrentTime());
                if (this.ctrl.state === "playing" && Math.abs(
                        this.player.getDuration() - curSyncTime) > 10) {
                    this.toggleSync();
                }
            }
        }
        // Trigger report of human-readable state.
        var state;
        switch (event.data) {
            case YT.PlayerState.PAUSED:
                state = "paused";
                break;
            case YT.PlayerState.PLAYING:
                state = "playing";
                break;
            case YT.PlayerState.BUFFERING:
                state = "buffering";
                break;
            case YT.PlayerState.CUED:
                state = "cued";
                break;
            case YT.PlayerState.ENDED:
                state = "ended";
                break;
        }
        this.trigger("player-state-change", state);
        this.trigger("player-state-" + state);
    },
    playForEveryone: function(event) {
        if (event) { event.preventDefault(); }
        var playing = this.isPlayingForEveryone();
        var awaitingStart = this.isAwaitingStart();
        var args;
        if (playing || awaitingStart) {
            args = {action: "pause"};
            this.cancelPollForStart();
        } else {
            var dur = this.player.getDuration();
            if (dur === 0) {
                this.pollForStart();
                // Don't trigger any server-side control yet; but *do* start
                // the player, so we get notified when its state changes.  If
                // we pause, it'll get paused by the "control-video" broadcast.
                this.player.playVideo();
                this.renderControls();
                return;
            } else {
                if (this.player.getCurrentTime() >= dur) {
                    time = 0;
                } else {
                    time = this.player.getCurrentTime();
                }
                args = {action: "play", time: time};
            }
        }
        this.trigger("control-video", args);
    },
    pollForStart: function() {
        this._awaitingStart = setInterval(_.bind(function() {
            var dur = this.player.getDuration();
            if (dur > 0) {
                this.cancelPollForStart();
                this.playForEveryone();
            }
        }, this), 100);
    },
    cancelPollForStart: function() {
        if (this._awaitingStart) {
            clearInterval(this._awaitingStart);
        }
        this._awaitingStart = null;
    },
    isAwaitingStart: function() {
        return !!this._awaitingStart;
    },
    toggleSync: function(event) {
        if (event) { event.preventDefault(); }
        if (this.intendToSync) {
            this.intendToSync = false;
            this.renderControls();
        } else {
            this.intendToSync = true;
            if (this.ctrl) {
                this.receiveControl(this.ctrl);
            }
        }
    },
    triggerVideoSettings: function(event) {
        this.trigger("video-settings", this);
    },
    isPlayingForEveryone: function() {
        return this.ctrl && this.ctrl.state === "playing";
    }
});

return video;

});
<|endoftext|>


<commit_before>/**
 * Created with JetBrains WebStorm.
 * User: yujilong
 * Date: 14-2-14
 * Time: 下午4:10
 * To change this template use File | Settings | File Templates.
 */
var util = require('./../../common/util').util;
var logger = require('./../../common/log').getLogger();
var Constant = require('./../../common/Constant');
module.exports = function (app) {

    var postSdkService = app.get(Constant.SERVICE_FACTORY)[Constant.SERVICE_SDK_POST];

    app.get('/burning/sdk/getPostListDetail', function (req, res) {
        var categoryId = req.param('categoryId');
        var boardId = req.param('boardId');
        if (!boardId) {
            postSdkService.getCurrentBoardPosts(categoryId, function (err, list) {
                if (err) {
                    logger.error(err);
                    res.json(200, {
                        status: '500'
                    });
                } else {
                    res.json(200, {
                        status: '200',
                        data: list
                    });
                }
            });
        } else {
            postSdkService.getPostListByBoardId(categoryId, boardId, function (err, list) {
                if (err) {
                    logger.error(err);
                    res.json(200, {
                        status: '500'
                    });
                } else {
                    res.json(200, {
                        status: '200',
                        data: list
                    });
                }
            });
        }
    });
    //获取当前菜单下的所有 期刊封面
    app.get('/burning/sdk/getPostListFontImgByCategoryId', function (req, res) {
        var categoryId = req.param('categoryId');
        //当前的 pageNum代表一个期刊
        var index = req.param('index') - 1;
        postSdkService.getPostListFontImgByCategoryId(categoryId, index, function (err, list, board) {
            var hasNext = false;
            if (err) {
                logger.error(err);
                res.json(200, {
                    status: '500'
                });
            } else {
                if (list && list.length > 0) {
                    hasNext = true;
                }
                res.json(200, {
                    status: '200',
                    data: {
                        postList:list,
                        boardName:board.name
                    },
                    hasNext: hasNext
                })
            }
        });
    });

};<commit_msg>fixed problem of categoryId<commit_after>/**
 * Created with JetBrains WebStorm.
 * User: yujilong
 * Date: 14-2-14
 * Time: 下午4:10
 * To change this template use File | Settings | File Templates.
 */
var util = require('./../../common/util').util;
var logger = require('./../../common/log').getLogger();
var Constant = require('./../../common/Constant');
module.exports = function (app) {

    var postSdkService = app.get(Constant.SERVICE_FACTORY)[Constant.SERVICE_SDK_POST];

    app.get('/burning/sdk/getPostListDetail', function (req, res) {
        var categoryId = req.param('categoryId');
        var boardId = req.param('boardId');
        if (!boardId) {
            postSdkService.getCurrentBoardPosts(categoryId, function (err, list) {
                if (err) {
                    logger.error(err);
                    res.json(200, {
                        status: '500'
                    });
                } else {
                    res.json(200, {
                        status: '200',
                        data: list
                    });
                }
            });
        } else {
            postSdkService.getPostListByBoardId(categoryId, boardId, function (err, list) {
                if (err) {
                    logger.error(err);
                    res.json(200, {
                        status: '500'
                    });
                } else {
                    res.json(200, {
                        status: '200',
                        data: list
                    });
                }
            });
        }
    });
    //获取当前菜单下的所有 期刊封面
    app.get('/burning/sdk/getPostListFontImgByCategoryId', function (req, res) {
        var categoryId = req.param('categoryId');
        //当前的 pageNum代表一个期刊
        var index = req.param('index') - 1;
        postSdkService.getPostListFontImgByCategoryId(categoryId, index, function (err, list, board) {
            var hasNext = false;
            if (err) {
                logger.error(err);
                res.json(200, {
                    status: '500'
                });
            } else {
                if (list && list.length > 0) {
                    hasNext = true;
                }
                res.json(200, {
                    status: '200',
                    data: {
                        postList:list,
                        boardName:board?board.name : ''
                    },
                    hasNext: hasNext
                })
            }
        });
    });

};<|endoftext|>


<commit_before>var PI = Math.PI,
  abs = Math.abs,
  random = Math.random,
  mmax = Math.max,
  mmin = Math.min,
  defaultCfg = {
    fillStyle: '#ccc',
    strokeStyle: '#000',
    lineWidth: 1,
    shadowColor: '#fff',
    shadowBlur: 0,
    shadowOffsetX: 0,
    shadowOffsetY: 0,
    lineCap: 'butt',
    lineJoin: 'miter',
    miterLimit: 0,
    font: '12px',
    textBaseline: 'middle',
    textAlign: 'center'
  };

function deg2rad(d){
  return d * PI / 180;
}

function rad2deg(r){
  return r * 180 / PI;
}

<commit_msg>新增三个math方法的缓存<commit_after>var PI = Math.PI,
  abs = Math.abs,
  random = Math.random,
  mmax = Math.max,
  mmin = Math.min,
  defaultCfg = {
    fillStyle: '#ccc',
    strokeStyle: '#000',
    lineWidth: 1,
    shadowColor: '#fff',
    shadowBlur: 0,
    shadowOffsetX: 0,
    shadowOffsetY: 0,
    lineCap: 'butt',
    lineJoin: 'miter',
    miterLimit: 0,
    font: '12px',
    textBaseline: 'middle',
    textAlign: 'center'
  },
  sin = Math.sin,
  cos = Math.cos,
  tan = Math.tan;

function deg2rad(d){
  return d * PI / 180;
}

function rad2deg(r){
  return r * 180 / PI;
}

<|endoftext|>