<commit_before>'use strict';

window.lively = this;

import * as scripts from './script-manager.js';
import * as messaging from './messaging.js';
import * as preferences from './preferences.js';
import * as persistence from './persistence.js';

import files from './files.js';
import html from './html.js';
import paths from './paths.js';

import inspector from './inspector.js';

import keys from './keys.js';
import components from './morphic/component-loader.js';

/* expose external modules */
import color from '../external/tinycolor.js';
import focalStorage from '../external/focalStorage.js';
import * as jquery from '../external/jquery.js';
import * as _ from '../external/underscore.js';

let $ = window.$,
  babel = window.babel,
  System = window.System; // known global variables.

// a) Special shorthands for interactive development
// b) this is the only reasonable way to use modules in template scripts, due to no shared lexical scope #TODO
var exportmodules = [
  "scripts",
  "messaging",
  "preferences",
  "persistence",
  "files",
  "keys",
  "paths",
  "html",
  "components",
  "inspector",
  "color",
  "focalStorage"];

// #LiveProgramming #Syntax #ES6Modules #Experiment #Jens
// By structuring our modules differently, we still can act as es6 module to the outside but develop at runtime
// #IDEA: I refactored from "static module and function style" to "dynamic object" style
export default class Lively {

  static import(moduleName, path, forceLoad) {
    if (!path) path = this.defaultPath(moduleName)
    if (!path) throw Error("Could not imoport " + moduleName + ", not path specified!")

    if (this[moduleName] && !forceLoad)
      return new Promise((resolve) => { resolve(this[moduleName])})
    if (forceLoad) {
      path += "?" + Date.now()
    }
    return System.import(path).then( (module, err) => {
      if (err) {
        lively.notify("Could not load module " + moduleName, err);
      } else {
        console.log("lively: load "+ moduleName)

        if (moduleName == "lively") {
          this.notify("migrate lively.js")
          var oldLively = window.lively;
          window.lively =module.default || module
          this["previous"] = oldLively
          this.components = oldLively.components // components have important state
        } else {
          this[moduleName] = module.default || module
        }

        if (lively.components && this[moduleName])
          lively.components.updatePrototype(this[moduleName].prototype);

        return module.default || module
      }
    })
  }

  static reloadModule(path, optSource) {
    if (!path) path = this.defaultPath(moduleName)
    if (!path) throw Error("Could not imoport " + moduleName + ", not path specified!")

    if (this[moduleName])
      return new Promise((resolve) => { resolve(this[moduleName])})
    return System.import(path).then( module => {
      console.log("lively: load "+ moduleName)
      this[moduleName] = module.default || module
    })
  }

  static defaultPath(moduleName) {
    return ({
      math: lively4url + "/src/external/math.js",
      typo: lively4url + "/src/external/typo.js",
      contextmenu: lively4url + '/src/client/contextmenu.js',
      customize: lively4url + '/src/client/customize.js'
    })[moduleName]
  }

  static handleError(error) {
    lively.LastError = error
   lively.notify("Error: ", error.message, 20, () =>
    		  lively.openWorkspace("Error:" + error.message + "\nLine:" + error.lineno + " Col: " + error.colno+"\nSource:" + error.source + "\nError:" + error.stack))
  }

  static loaded() {
    // #Refactor with #ContextJS
    // guard againsst wrapping twice and ending in endless recursion
    if (!console.log.originalFunction) {
        var nativeLog = console.log;
        console.log = function() {
            nativeLog.apply(console, arguments);
            lively.log.apply(undefined, arguments);
        };
        console.log.originalFunction = nativeLog; // #TODO use generic Wrapper mechanism here
    }
    if (!console.error.originalFunction) {
        var nativeError = console.error;
        console.error = function() {
            nativeError.apply(console, arguments);
            lively.log.apply(undefined, arguments);
        };
        console.error.originalFunction = nativeError; // #TODO use generic Wrapper mechanism here
    }

    // General Error Handling
    if (window.onerror === null) {
      window.onerror  = function(message, source, lineno, colno, error) {
    	  lively.handleError(error)
      }
    }
    // do it just once
    if (!window.unhandledRejectionEventLister) {
      window.unhandledRejectionEventLister = function(evt) {lively.handleError(evt.reason)} ;
      window.addEventListener('unhandledrejection', unhandledRejectionEventLister);
    }

    exportmodules.forEach(name => lively[name] = eval(name)); // oh... this seems uglier than expected

    this.import("authGithub", lively4url + '/src/client/auth-github.js')
    this.import("authDropbox", lively4url + '/src/client/auth-dropbox.js')
  }

  static array(anyList){
    return Array.prototype.slice.call(anyList);
  }

  static openWorkspace(string, pos) {
    var name = "juicy-ace-editor";
    var comp  = document.createElement(name);
    return lively.components.openInWindow(comp).then((container) => {
      pos = pos || lively.pt(100,100);
      comp.changeMode("javascript");
      comp.enableAutocompletion();
      comp.editor.setValue(string)
      lively.setPosition(container,pos);
    }).then( () => {
      comp.editor.focus();
      return comp
    });
  }

  static boundEval(str, ctx) {
    var interactiveEval = function(text) { return eval(text) };
    var transpiledSource = babel.transform(str).code;
    // #TODO alt: babel.run
    // #TODO context does not seem to work!
    return interactiveEval.call(ctx, transpiledSource);
  }

  static pt(x,y) {
    return {x: x, y: y};
  }

  static setPosition(obj, point) {
      obj.style.position = "absolute";

      // var bounds = that.getBoundingClientRect().top
      //var deltax = point.x - bounds.left
      // var deltay = point.y - bounds.top

      // obj.style.left = ""+  ((obj.style.left || 0) - deltax) + "px";
      // obj.style.top = "" + ((obj.style.top || 0) - deltay) + "px";
      obj.style.left = ""+  point.x + "px";
      obj.style.top = "" +  point.y + "px";
  }

  static openFile(url) {
    if (url.hostname == "lively4"){
      var container  = $('lively-container')[0];
      if (container) {
        container.followPath(url.pathname);
      } else {
        console.log("fall back on editor: "+ url);
        this.editFile(url);
      }
    } else {
      this.editFile(url);
    }
  }

  static editFile(url) {
    var editor  = document.createElement("lively-editor");
    lively.components.openInWindow(editor).then((container) => {
        lively.setPosition(container, lively.pt(100, 100));
        editor.setURL(url);
        editor.loadFile();
    });
  }

  static hideContextMenu(evt) {
    // console.log("hide: " + (evt.path[0] === document.body))
    if (evt.path[0] !== document.body) return
    console.log("hide context menu:" + evt)
    this.import("contextmenu").then(m => m.hide());
  }

  static openContextMenu(container, evt, target) {
    if (HaloService.areHalosActive() ||
      (HaloService.halosHidden && ((Date.now() - HaloService.halosHidden) < 500))) {
      target = that
    }
    console.log("open context menu: " + target);
    this.import("contextmenu").then(m => m.openIn(container, evt, target));

  }

  static log(/* varargs */) {
      var args = arguments;
      $('lively-console').each(function() {
        try{
          if (this.log) this.log.apply(this, args);
        }catch(e) {
          // ignore...
        }
      });
  }

  static notify(title, text, timeout, cb) {
    // lively.notify("hello","",3)
    // just in case...
    if (Notification.permission !== "granted") Notification.requestPermission();

    var time = Date.now()
    if (lively.lastNotificationTime && (time - lively.lastNotificationTime) < 500) {
      return console.log("SILENT NOTE: " + title  + " (" + text + ")");
    }

    lively.lastNotificationTime = time
    console.log("NOTE: " + title  + " (" + text + ")");

    var notification = new Notification(title || "", {
      icon: 'https://www.lively-kernel.org/media/livelylogo-small.png',
      body: text || "",
    });
    if (cb) notification.onclick = cb
    if (timeout === undefined) timeout = 3
    setTimeout(() => notification.close(), timeout * 1000);
    // notification.onclick = cb
  }

  static initializeDocument(doc, loadedAsExtension) {
    console.log("Lively4 initializeDocument");
      doc.addEventListener('contextmenu', function(evt) {
          if (evt.ctrlKey) {
            evt.preventDefault();
            lively.openContextMenu($('body')[0], evt);
            return false;
          }
      }, false);

    if (loadedAsExtension) {
      this.import("customize").then(customize => {
          customize.customizePage()
      })
      lively.notify("Lively4 extension loaded!",
        "  CTRL+LeftClick  ... open halo\n" +
        "  CTRL+RightClick ... open menu");
    } else {
      // doc.addEventListener('contextmenu', function(evt) {
      //   evt.preventDefault();
      //   lively.openContextMenu($('body')[0], evt);
      //   return false;
      // }, false);
    }

    doc.addEventListener('click', function(evt){lively.hideContextMenu(evt)}, false);
    doc.addEventListener('keydown', function(evt){lively.keys.handle(evt)}, false);
  }

  static initializeHalos() {
    if ($('lively-halos').size() === 0) {
        $('<lively-halos>')
            .attr('data-lively4-donotpersist', 'all')
            .appendTo($('body'));
    }
    lively.components.loadUnresolved();
  }

   static unload() {
      lively.notify("unloading Lively is not supported yet! Please reload page....");
  }

  static updateTemplate(html) {
    var tagName = components.reloadComponent(html);
    if (!tagName) return;

    _.each($(tagName), function(oldInstance) {
      if (oldInstance.__ingoreUpdates) return;

      var owner = oldInstance.parentElement;
      var newInstance = document.createElement(tagName);

      owner.replaceChild(newInstance, oldInstance);
      _.each(oldInstance.childNodes, function(ea) {
        newInstance.appendChild(ea);
        console.log("append old child: " + ea);

      });
      _.each(oldInstance.attributes, function(ea) {
        console.log("set old attribute " + ea.name + " to: " + ea.value);
        newInstance.setAttribute(ea.name, ea.value);

      });
      _.each(_.keys(oldInstance), function(ea) {
        console.log("ignore properties: " + newInstance[ea] + " <-- " + oldInstance[ea]);
      });
    });
  }

  static showPoint(point) {
    var comp = document.createElement("div")
    comp.style['pointer-events'] = "none"
    comp.style.width = "5px"
    comp.style.height = "5px"
    comp.style.padding = "1px"
    comp.style.backgroundColor = "red"
    document.body.appendChild(comp)
    lively.setPosition(comp, point)
    comp.setAttribute("data-is-meta", "true")

    setTimeout( () => $(comp).remove(), 3000)
    // ea.getBoundingClientRect

  }

  static showSource(object, evt) {
    if (object instanceof HTMLElement) {
        var comp  = document.createElement("lively-container");
        lively.components.openInWindow(comp).then((container) => {
          comp.editFile(lively4url +"/templates/" + object.localName + ".html")
        })
    } else {
      lively.notify("Could not show source for: " + object)
    }
  }

  static showElement(elem, timeout) {
    var comp = document.createElement("div")
    var bounds = elem.getBoundingClientRect()
    var pos = lively.pt(
      bounds.left +  $(document).scrollLeft(),
      bounds.top +  $(document).scrollTop())

    comp.style.width = bounds.width +"px"
    comp.style.height = bounds.height +"px"
    comp.style['pointer-events'] = "none"
    // comp.style.height = "0px"
    comp.style["z-index"] = 1000;
    comp.style.border = "1px solid red";
    document.body.appendChild(comp)
    lively.setPosition(comp, pos);
    comp.setAttribute("data-is-meta", "true")

    comp.innerHTML = "
" +
        elem.tagName +": " + elem.id + "\n" +
        elem.getAttribute("class") +"\n"

      + "
"

    setTimeout( () => $(comp).remove(), timeout || 3000)
    return comp
  }

  static allProperties(obj, result) {
    result = result || {};
    Object.getOwnPropertyNames(obj).forEach( name => {result[name] = obj.constructor.name})
    if (obj.__proto__) {
      lively.allProperties(obj.__proto__, result);
    }
    return result
  }

  static registerTemplate() {
    var template = document.currentScript.ownerDocument.querySelector('template');
    var clone = document.importNode(template.content, true);
    System.import('../src/client/morphic/component-loader.js').then(loader => { loader.register(template.id, clone); });
  }
}

window.lively = Lively
Lively.loaded();

console.log("loaded lively");
<commit_msg>SYNC  M src/client/lively.js;<commit_after>'use strict';

window.lively = this;

import * as scripts from './script-manager.js';
import * as messaging from './messaging.js';
import * as preferences from './preferences.js';
import * as persistence from './persistence.js';

import files from './files.js';
import html from './html.js';
import paths from './paths.js';

import inspector from './inspector.js';

import keys from './keys.js';
import components from './morphic/component-loader.js';

/* expose external modules */
import color from '../external/tinycolor.js';
import focalStorage from '../external/focalStorage.js';
import * as jquery from '../external/jquery.js';
import * as _ from '../external/underscore.js';

let $ = window.$,
  babel = window.babel,
  System = window.System; // known global variables.

// a) Special shorthands for interactive development
// b) this is the only reasonable way to use modules in template scripts, due to no shared lexical scope #TODO
var exportmodules = [
  "scripts",
  "messaging",
  "preferences",
  "persistence",
  "files",
  "keys",
  "paths",
  "html",
  "components",
  "inspector",
  "color",
  "focalStorage"];

// #LiveProgramming #Syntax #ES6Modules #Experiment #Jens
// By structuring our modules differently, we still can act as es6 module to the outside but develop at runtime
// #IDEA: I refactored from "static module and function style" to "dynamic object" style
export default class Lively {

  static import(moduleName, path, forceLoad) {
    if (!path) path = this.defaultPath(moduleName)
    if (!path) throw Error("Could not imoport " + moduleName + ", not path specified!")

    if (this[moduleName] && !forceLoad)
      return new Promise((resolve) => { resolve(this[moduleName])})
    if (forceLoad) {
      path += "?" + Date.now()
    }
    return System.import(path).then( (module, err) => {
      if (err) {
        lively.notify("Could not load module " + moduleName, err);
      } else {
        console.log("lively: load "+ moduleName)

        if (moduleName == "lively") {
          this.notify("migrate lively.js")
          var oldLively = window.lively;
          window.lively =module.default || module
          this["previous"] = oldLively
          this.components = oldLively.components // components have important state
        } else {
          this[moduleName] = module.default || module
        }

        if (lively.components && this[moduleName])
          lively.components.updatePrototype(this[moduleName].prototype);

        return module.default || module
      }
    })
  }

  static reloadModule(path, optSource) {
    if (!path) path = this.defaultPath(moduleName)
    if (!path) throw Error("Could not imoport " + moduleName + ", not path specified!")

    if (this[moduleName])
      return new Promise((resolve) => { resolve(this[moduleName])})
    return System.import(path).then( module => {
      console.log("lively: load "+ moduleName)
      this[moduleName] = module.default || module
    })
  }

  static defaultPath(moduleName) {
    return ({
      math: lively4url + "/src/external/math.js",
      typo: lively4url + "/src/external/typo.js",
      contextmenu: lively4url + '/src/client/contextmenu.js',
      customize: lively4url + '/src/client/customize.js'
    })[moduleName]
  }

  static handleError(error) {
    lively.LastError = error
   lively.notify("Error: ", error.message, 20, () =>
    		  lively.openWorkspace("Error:" + error.message + "\nLine:" + error.lineno + " Col: " + error.colno+"\nSource:" + error.source + "\nError:" + error.stack))
  }

  static loaded() {
    // #Refactor with #ContextJS
    // guard againsst wrapping twice and ending in endless recursion
    if (!console.log.originalFunction) {
        var nativeLog = console.log;
        console.log = function() {
            nativeLog.apply(console, arguments);
            lively.log.apply(undefined, arguments);
        };
        console.log.originalFunction = nativeLog; // #TODO use generic Wrapper mechanism here
    }
    if (!console.error.originalFunction) {
        var nativeError = console.error;
        console.error = function() {
            nativeError.apply(console, arguments);
            lively.log.apply(undefined, arguments);
        };
        console.error.originalFunction = nativeError; // #TODO use generic Wrapper mechanism here
    }

    // General Error Handling
    if (window.onerror === null) {
      window.onerror  = function(message, source, lineno, colno, error) {
    	  lively.handleError(error)
      }
    }
    // do it just once
    if (!window.unhandledRejectionEventLister) {
      window.unhandledRejectionEventLister = function(evt) {lively.handleError(evt.reason)} ;
      window.addEventListener('unhandledrejection', unhandledRejectionEventLister);
    }

    exportmodules.forEach(name => lively[name] = eval(name)); // oh... this seems uglier than expected

    this.import("authGithub", lively4url + '/src/client/auth-github.js')
    this.import("authDropbox", lively4url + '/src/client/auth-dropbox.js')
  }

  static array(anyList){
    return Array.prototype.slice.call(anyList);
  }

  static openWorkspace(string, pos) {
    var name = "juicy-ace-editor";
    var comp  = document.createElement(name);
    return lively.components.openInWindow(comp).then((container) => {
      pos = pos || lively.pt(100,100);
      comp.changeMode("javascript");
      comp.enableAutocompletion();
      comp.editor.setValue(string)
      lively.setPosition(container,pos);
    }).then( () => {
      comp.editor.focus();
      return comp
    });
  }

  static boundEval(str, ctx) {
    var interactiveEval = function(text) { return eval(text) };
    var transpiledSource = babel.transform(str).code;
    // #TODO alt: babel.run
    // #TODO context does not seem to work!
    return interactiveEval.call(ctx, transpiledSource);
  }

  static pt(x,y) {
    return {x: x, y: y};
  }

  static setPosition(obj, point) {
      obj.style.position = "absolute";

      // var bounds = that.getBoundingClientRect().top
      //var deltax = point.x - bounds.left
      // var deltay = point.y - bounds.top

      // obj.style.left = ""+  ((obj.style.left || 0) - deltax) + "px";
      // obj.style.top = "" + ((obj.style.top || 0) - deltay) + "px";
      obj.style.left = ""+  point.x + "px";
      obj.style.top = "" +  point.y + "px";
  }

  static openFile(url) {
    if (url.hostname == "lively4"){
      var container  = $('lively-container')[0];
      if (container) {
        container.followPath(url.pathname);
      } else {
        console.log("fall back on editor: "+ url);
        this.editFile(url);
      }
    } else {
      this.editFile(url);
    }
  }

  static editFile(url) {
    var editor  = document.createElement("lively-editor");
    lively.components.openInWindow(editor).then((container) => {
        lively.setPosition(container, lively.pt(100, 100));
        editor.setURL(url);
        editor.loadFile();
    });
  }

  static hideContextMenu(evt) {
    // console.log("hide: " + (evt.path[0] === document.body))
    if (evt.path[0] !== document.body) return
    console.log("hide context menu:" + evt)
    this.import("contextmenu").then(m => m.hide());
  }

  static openContextMenu(container, evt, target) {
    if (HaloService.areHalosActive() ||
      (HaloService.halosHidden && ((Date.now() - HaloService.halosHidden) < 500))) {
      target = that
    }
    console.log("open context menu: " + target);
    this.import("contextmenu").then(m => m.openIn(container, evt, target));

  }

  static log(/* varargs */) {
      var args = arguments;
      $('lively-console').each(function() {
        try{
          if (this.log) this.log.apply(this, args);
        }catch(e) {
          // ignore...
        }
      });
  }

  static notify(title, text, timeout, cb) {
    // lively.notify("hello","",3)
    // just in case...
    if (Notification.permission !== "granted") Notification.requestPermission();

    var time = Date.now()
    if (lively.lastNotificationTime && (time - lively.lastNotificationTime) < 500) {
      return console.log("SILENT NOTE: " + title  + " (" + text + ")");
    }

    lively.lastNotificationTime = time
    console.log("NOTE: " + title  + " (" + text + ")");

    var notification = new Notification(title || "", {
      icon: 'https://www.lively-kernel.org/media/livelylogo-small.png',
      body: text || "",
    });
    if (cb) notification.onclick = cb
    if (timeout === undefined) timeout = 3
    setTimeout(() => notification.close(), timeout * 1000);
    // notification.onclick = cb
  }

  static initializeDocument(doc, loadedAsExtension) {
    console.log("Lively4 initializeDocument");
      doc.addEventListener('contextmenu', function(evt) {
          if (evt.ctrlKey) {
            evt.preventDefault();
            lively.openContextMenu($('body')[0], evt);
            return false;
          }
      }, false);

    if (loadedAsExtension) {
      this.import("customize").then(customize => {
          customize.customizePage()
      })
      lively.notify("Lively4 extension loaded!",
        "  CTRL+LeftClick  ... open halo\n" +
        "  CTRL+RightClick ... open menu");
    } else {
      // doc.addEventListener('contextmenu', function(evt) {
      //   evt.preventDefault();
      //   lively.openContextMenu($('body')[0], evt);
      //   return false;
      // }, false);
    }

    doc.addEventListener('click', function(evt){lively.hideContextMenu(evt)}, false);
    doc.addEventListener('keydown', function(evt){lively.keys.handle(evt)}, false);
  }

  static initializeHalos() {
    if ($('lively-halos').size() === 0) {
        $('<lively-halos>')
            .attr('data-lively4-donotpersist', 'all')
            .appendTo($('body'));
    }
    lively.components.loadUnresolved();
  }

   static unload() {
      lively.notify("unloading Lively is not supported yet! Please reload page....");
  }

  static updateTemplate(html) {
    var tagName = components.reloadComponent(html);
    if (!tagName) return;

    _.each($(tagName), function(oldInstance) {
      if (oldInstance.__ingoreUpdates) return;

      var owner = oldInstance.parentElement;
      var newInstance = document.createElement(tagName);

      owner.replaceChild(newInstance, oldInstance);
      _.each(oldInstance.childNodes, function(ea) {
        newInstance.appendChild(ea);
        console.log("append old child: " + ea);

      });
      _.each(oldInstance.attributes, function(ea) {
        console.log("set old attribute " + ea.name + " to: " + ea.value);
        newInstance.setAttribute(ea.name, ea.value);

      });
      _.each(_.keys(oldInstance), function(ea) {
        console.log("ignore properties: " + newInstance[ea] + " <-- " + oldInstance[ea]);
      });
    });
  }

  static showPoint(point) {
    var comp = document.createElement("div")
    comp.style['pointer-events'] = "none"
    comp.style.width = "5px"
    comp.style.height = "5px"
    comp.style.padding = "1px"
    comp.style.backgroundColor = "red"
    document.body.appendChild(comp)
    lively.setPosition(comp, point)
    comp.setAttribute("data-is-meta", "true")

    setTimeout( () => $(comp).remove(), 3000)
    // ea.getBoundingClientRect

  }

  static showSource(object, evt) {
    if (object instanceof HTMLElement) {
        var comp  = document.createElement("lively-container");
        lively.components.openInWindow(comp).then((container) => {
          comp.editFile(lively4url +"/templates/" + object.localName + ".html")
        })
    } else {
      lively.notify("Could not show source for: " + object)
    }
  }

  static showElement(elem, timeout) {
    var comp = document.createElement("div")
    var bounds = elem.getBoundingClientRect()
    var pos = lively.pt(
      bounds.left +  $(document).scrollLeft(),
      bounds.top +  $(document).scrollTop())

    comp.style.width = bounds.width +"px"
    comp.style.height = bounds.height +"px"
    comp.style['pointer-events'] = "none"
    // comp.style.height = "0px"
    comp.style["z-index"] = 1000;
    comp.style.border = "1px solid red";
    document.body.appendChild(comp)
    lively.setPosition(comp, pos);
    comp.setAttribute("data-is-meta", "true")

    comp.innerHTML = "
" +
        elem.tagName +": " + elem.id + "\n" +
        elem.getAttribute("class") +"\n"

      + "
"

    setTimeout( () => $(comp).remove(), timeout || 3000)
    return comp
  }

  static allProperties(obj, result) {
    result = result || {};
    Object.getOwnPropertyNames(obj).forEach( name => {result[name] = obj.constructor.name})
    if (obj.__proto__) {
      lively.allProperties(obj.__proto__, result);
    }
    return result
  }

  static registerTemplate() {
    var template = document.currentScript.ownerDocument.querySelector('template');
    var clone = document.importNode(template.content, true);
    System.import(lively4url + '/src/client/morphic/component-loader.js').then(loader => { loader.register(template.id, clone); });
  }
}

window.lively = Lively
Lively.loaded();

console.log("loaded lively");
<|endoftext|>


<commit_before>"use strict";

var $ = require('jquery'),
    zoom = require('./lib/mapUtil').ZOOM,
    L = require('leaflet'),
    mapModule = require('./map'),
    SelectableBlockfaceLayer = require('./lib/SelectableBlockfaceLayer');

require('./lib/mapHelp');

// Extends the leaflet object
require('leaflet-utfgrid');

var progressMap = mapModule.create({
        geolocation: true,
        legend: true,
        search: true
    }),
    tileLayer = null,
    grid = null,
    selectedLayer = null,
    geojsonLayer = null,

    dom = {
        modeDropdown: '.dropdown',
        modeButton: '.btn',
        modeChoice: '.dropdown li a',
        legendEntries: '[data-mode]',
        actionBar: '#action-bar'
    },
    $actionBar = $(dom.actionBar),
    $mode = null;

$(dom.modeChoice).click(onModeChanged);

loadLayers($(dom.modeChoice).first());

function onModeChanged(e) {
    e.preventDefault();
    if ($mode !== null && $mode[0] === e.currentTarget) {
        return;
    }
    $mode = $(e.currentTarget);

    // Shown chosen mode on dropdown button
    $mode.parents(dom.modeDropdown).find(dom.modeButton).text($mode.text());

    // Show appropriate legend entries
    var mode = $mode.attr('href').slice(1);  // strip leading #
    $(dom.legendEntries).addClass('hidden');
    $('[data-mode=' + mode + ']').removeClass('hidden');

    loadLayers($mode);
}

function loadLayers($mode) {
    var tileUrl = $mode.data('tile-url'),
        gridUrl = $mode.data('grid-url'),
        geojsonUrl = $mode.data('geojson-url'),
        bounds = $mode.data('bounds');

    // Clear action bar
    $actionBar.empty();

    // Replace layers
    if (tileLayer) {
        progressMap.removeLayer(tileLayer);
    }
    if (grid) {
        progressMap.removeLayer(grid);
    }
    if (selectedLayer) {
        progressMap.removeLayer(selectedLayer);
    }
    if (geojsonLayer) {
        progressMap.removeLayer(geojsonLayer);
    }
    if (tileUrl) {
        tileLayer = mapModule.addTileLayer(progressMap, tileUrl);
        grid = mapModule.addGridLayer(progressMap, gridUrl);

        createSelectableLayer();

        if (bounds) {
            mapModule.fitBounds(progressMap, bounds);
        }
    }
    if (geojsonUrl) {
        $.getJSON(geojsonUrl, function(geojson) {
            geojsonLayer = L.geoJson(geojson, {
                style: function() {
                    return {
                        color: '#36b5db',
                        weight: 3,
                    };
                },
                onEachFeature: function(feature, layer) {
                    layer.on('click', function showGroupBlockfaces() {
                        progressMap.removeLayer(tileLayer);
                        progressMap.removeLayer(grid);

                        tileLayer = mapModule.addTileLayer(progressMap, feature.properties.tileUrl);
                        grid = mapModule.addGridLayer(progressMap, feature.properties.gridUrl);

                        createSelectableLayer();

                        mapModule.fitBounds(progressMap, feature.properties.bounds);
                        $actionBar.load(feature.properties.popupUrl);
                    });
                }
            });
            geojsonLayer.addTo(progressMap);
        });
    }
}

function createSelectableLayer() {
    selectedLayer = new SelectableBlockfaceLayer(progressMap, grid, {
        onAdd: function(gridData) {
            selectedLayer.clearLayers();

            // Note: this must be kept in sync with
            // src/nyc_trees/apps/survey/urls/blockface.py
            var url = '/blockedge/' + gridData.id + '/progress-page-blockedge-popup/';

            if (gridData.group_id) {
                url += '?group_id=' + gridData.group_id;
            }
            $actionBar.load(url);
            return true;
        }
    });
    progressMap.addLayer(selectedLayer);
}
<commit_msg>Add a class to the body when content is added to the actionbar.<commit_after>"use strict";

var $ = require('jquery'),
    zoom = require('./lib/mapUtil').ZOOM,
    L = require('leaflet'),
    mapModule = require('./map'),
    SelectableBlockfaceLayer = require('./lib/SelectableBlockfaceLayer');

require('./lib/mapHelp');

// Extends the leaflet object
require('leaflet-utfgrid');

var progressMap = mapModule.create({
        geolocation: true,
        legend: true,
        search: true
    }),
    tileLayer = null,
    grid = null,
    selectedLayer = null,
    geojsonLayer = null,

    dom = {
        modeDropdown: '.dropdown',
        modeButton: '.btn',
        modeChoice: '.dropdown li a',
        legendEntries: '[data-mode]',
        actionBar: '#action-bar'
    },
    $actionBar = $(dom.actionBar),
    $mode = null;

$(dom.modeChoice).click(onModeChanged);

loadLayers($(dom.modeChoice).first());

function onModeChanged(e) {
    e.preventDefault();
    if ($mode !== null && $mode[0] === e.currentTarget) {
        return;
    }
    $mode = $(e.currentTarget);

    // Shown chosen mode on dropdown button
    $mode.parents(dom.modeDropdown).find(dom.modeButton).text($mode.text());

    // Show appropriate legend entries
    var mode = $mode.attr('href').slice(1);  // strip leading #
    $(dom.legendEntries).addClass('hidden');
    $('[data-mode=' + mode + ']').removeClass('hidden');

    loadLayers($mode);
}

function loadLayers($mode) {
    var tileUrl = $mode.data('tile-url'),
        gridUrl = $mode.data('grid-url'),
        geojsonUrl = $mode.data('geojson-url'),
        bounds = $mode.data('bounds');

    // Clear action bar
    $actionBar.empty();
    $('body').removeClass('actionbar-triggered');

    // Replace layers
    if (tileLayer) {
        progressMap.removeLayer(tileLayer);
    }
    if (grid) {
        progressMap.removeLayer(grid);
    }
    if (selectedLayer) {
        progressMap.removeLayer(selectedLayer);
    }
    if (geojsonLayer) {
        progressMap.removeLayer(geojsonLayer);
    }
    if (tileUrl) {
        tileLayer = mapModule.addTileLayer(progressMap, tileUrl);
        grid = mapModule.addGridLayer(progressMap, gridUrl);

        createSelectableLayer();

        if (bounds) {
            mapModule.fitBounds(progressMap, bounds);
        }
    }
    if (geojsonUrl) {
        $.getJSON(geojsonUrl, function(geojson) {
            geojsonLayer = L.geoJson(geojson, {
                style: function() {
                    return {
                        color: '#36b5db',
                        weight: 3,
                    };
                },
                onEachFeature: function(feature, layer) {
                    layer.on('click', function showGroupBlockfaces() {
                        progressMap.removeLayer(tileLayer);
                        progressMap.removeLayer(grid);

                        tileLayer = mapModule.addTileLayer(progressMap, feature.properties.tileUrl);
                        grid = mapModule.addGridLayer(progressMap, feature.properties.gridUrl);

                        createSelectableLayer();

                        mapModule.fitBounds(progressMap, feature.properties.bounds);
                        $actionBar.load(feature.properties.popupUrl);
                        $('body').addClass('actionbar-triggered');
                    });
                }
            });
            geojsonLayer.addTo(progressMap);
        });
    }
}

function createSelectableLayer() {
    selectedLayer = new SelectableBlockfaceLayer(progressMap, grid, {
        onAdd: function(gridData) {
            selectedLayer.clearLayers();

            // Note: this must be kept in sync with
            // src/nyc_trees/apps/survey/urls/blockface.py
            var url = '/blockedge/' + gridData.id + '/progress-page-blockedge-popup/';

            if (gridData.group_id) {
                url += '?group_id=' + gridData.group_id;
            }
            $actionBar.load(url);
            $('body').addClass('actionbar-triggered');
            return true;
        }
    });
    progressMap.addLayer(selectedLayer);
}
<|endoftext|>


<commit_before>import configService from '../../shared/ConfigService';
import { close } from '../actions/parent';
import { toggleFavouriteInWindow } from '../../child/actions/favourites';
import { willBeInitialOpen } from '../../child/actions/initialOpen';

class ParentService {

    constructor(store) {
        this.store = store;
        this.parentClosing = false;
        this.onChildClosed = this.onChildClosed.bind(this);
        this.onCloseRequested = this.onCloseRequested.bind(this);

        fin.desktop.InterApplicationBus.subscribe(
            fin.desktop.Application.getCurrent().uuid,
            'createChildWindow',
            (config) => this.createChildWindow(config)
        );
    }

    getChildWindowCount() {
        return Object.keys(this.store.getState().childWindows).length;
    }

    getWindowDragOutCount() {
        return Object.keys(this.store.getState().dragOut).length;
    }

    onChildClosed({ name }) {
        if (this.parentClosing) {
            return;
        }

        const isFinalChildWindowClosing = this.getChildWindowCount() <= 1;

        if (isFinalChildWindowClosing && this.getWindowDragOutCount() === 0) {
            fin.desktop.Window.getCurrent().close();
        } else {
            this.store.dispatch(close(name, Date.now()));
        }
    }

    onCloseRequested() {
        this.parentClosing = true;
        fin.desktop.Window.getCurrent().close(true);
    }

    createChildWindowSuccess(childWindow, position, defaultStocks) {
        if (position) {
            childWindow.setBounds(position[0], position[1]);
        }

        if (defaultStocks) {
            const childWindowName = childWindow.name;
            this.store.dispatch(willBeInitialOpen(childWindowName));
            defaultStocks.forEach((code) => {
                this.store.dispatch(toggleFavouriteInWindow(code, childWindowName));
            });
        }

        childWindow.show();
        childWindow.addEventListener('closed', this.onChildClosed);
    }

    createChildWindow(config = {}) {
        const { windowName, position, intialState, defaultStocks } = config;
        const windowConfig = this.getChildWindowConfigOrDefault(windowName, intialState);
        const childWindow = new fin.desktop.Window(
            windowConfig,
            () => this.createChildWindowSuccess(childWindow, position, defaultStocks)
        );
    }

    getChildWindowConfigOrDefault(windowName, intialState) {
        let windowConfig;
        if (windowName && intialState) {
            if (intialState.isCompact) {
                windowConfig = configService.getCompactWindowConfig(windowName);
            } else if (intialState.isMaximized) {
                windowConfig = configService.getMaximizedWindowConfig(windowName);
            } else {
                windowConfig = configService.getWindowConfig(windowName);
            }
        } else if (windowName) {
            windowConfig = configService.getWindowConfig(windowName);
        } else {
            windowConfig = configService.getWindowConfig();
        }
        return windowConfig;
    }

    start() {
        fin.desktop.Window.getCurrent().contentWindow.store = this.store;

        fin.desktop.Window.getCurrent().addEventListener('close-requested', this.onCloseRequested);

        if (this.getChildWindowCount() === 0) {
            this.createChildWindow({ defaultStocks: configService.getDefaultStocks() });
        } else {
            const childWindows = this.store.getState().childWindows;
            Object.keys(childWindows).forEach((windowName) => {
                const newWindowName = windowName === 'undefined' ? null : windowName;
                this.createChildWindow({ windowName: newWindowName, initalState: childWindows[newWindowName] });
            });
        }
    }

}

export default ParentService;
<commit_msg>fix: fix child window config in parent service (#944)<commit_after>import configService from '../../shared/ConfigService';
import { close } from '../actions/parent';
import { toggleFavouriteInWindow } from '../../child/actions/favourites';
import { willBeInitialOpen } from '../../child/actions/initialOpen';

class ParentService {

    constructor(store) {
        this.store = store;
        this.parentClosing = false;
        this.onChildClosed = this.onChildClosed.bind(this);
        this.onCloseRequested = this.onCloseRequested.bind(this);

        fin.desktop.InterApplicationBus.subscribe(
            fin.desktop.Application.getCurrent().uuid,
            'createChildWindow',
            (config) => this.createChildWindow(config)
        );
    }

    getChildWindowCount() {
        return Object.keys(this.store.getState().childWindows).length;
    }

    getWindowDragOutCount() {
        return Object.keys(this.store.getState().dragOut).length;
    }

    onChildClosed({ name }) {
        if (this.parentClosing) {
            return;
        }

        const isFinalChildWindowClosing = this.getChildWindowCount() <= 1;

        if (isFinalChildWindowClosing && this.getWindowDragOutCount() === 0) {
            fin.desktop.Window.getCurrent().close();
        } else {
            this.store.dispatch(close(name, Date.now()));
        }
    }

    onCloseRequested() {
        this.parentClosing = true;
        fin.desktop.Window.getCurrent().close(true);
    }

    createChildWindowSuccess(childWindow, position, defaultStocks) {
        if (position) {
            childWindow.setBounds(position[0], position[1]);
        }

        if (defaultStocks) {
            const childWindowName = childWindow.name;
            this.store.dispatch(willBeInitialOpen(childWindowName));
            defaultStocks.forEach((code) => {
                this.store.dispatch(toggleFavouriteInWindow(code, childWindowName));
            });
        }

        childWindow.show();
        childWindow.addEventListener('closed', this.onChildClosed);
    }

    createChildWindow(config = {}) {
        const { windowName, position, initialState, defaultStocks } = config;
        const windowConfig = this.getChildWindowConfigOrDefault(windowName, initialState);
        const childWindow = new fin.desktop.Window(
            windowConfig,
            () => this.createChildWindowSuccess(childWindow, position, defaultStocks)
        );
    }

    getChildWindowConfigOrDefault(windowName, initialState) {
        let windowConfig;
        if (windowName && initialState) {
            if (initialState.windowState.isCompact) {
                windowConfig = configService.getCompactWindowConfig(windowName);
            } else if (initialState.windowState.isMaximized) {
                windowConfig = configService.getMaximizedWindowConfig(windowName);
            } else {
                windowConfig = configService.getWindowConfig(windowName);
            }
        } else if (windowName) {
            windowConfig = configService.getWindowConfig(windowName);
        } else {
            windowConfig = configService.getWindowConfig();
        }
        return windowConfig;
    }

    start() {
        fin.desktop.Window.getCurrent().contentWindow.store = this.store;

        fin.desktop.Window.getCurrent().addEventListener('close-requested', this.onCloseRequested);

        if (this.getChildWindowCount() === 0) {
            this.createChildWindow({ defaultStocks: configService.getDefaultStocks() });
        } else {
            const childWindows = this.store.getState().childWindows;
            Object.keys(childWindows).forEach((windowName) => {
                const newWindowName = windowName === 'undefined' ? null : windowName;
                this.createChildWindow({ windowName: newWindowName, initialState: childWindows[newWindowName] });
            });
        }
    }

}

export default ParentService;
<|endoftext|>


<commit_before>class ColorManager {
    generateGradationColorListByHex(count, base_code) {
        const list = [];
        try {
            if (count < 1) {
                throw '"gen_cnt" must be an integer greater than or equal to 1.';
            }

            if (!base_code.match(/^#[0-9a-f]{6}$/i)) {
                throw 'The format of "base_color" is invalid. Please specify it with 6 hexadecimal digits.';
            }

            const base_rgb = this.hexToRgb(base_code);
            const max_val = Math.max.apply(null, base_rgb);
            const min_val = Math.min.apply(null, base_rgb);
            let color_range = Math.floor(((max_val - min_val) * 6) / count);
            if (color_range < 1) {
                color_range = 1;
            }

            const max_val_idx = base_rgb.indexOf(max_val);
            const min_val_idx = base_rgb.indexOf(min_val);

            const snd_idx = max_val_idx;
            const trd_idx = min_val_idx;
            const fst_idx = 3 - snd_idx - trd_idx;

            const idx_list = [fst_idx, snd_idx, trd_idx];
            let tmp_rgb = base_rgb;
            let roop_cnt = 0;
            let now_idx = fst_idx, next_idx = snd_idx;
            let now_color_range = color_range, color_code_tmp = '';
            let to_up = tmp_rgb[fst_idx] - min_val > max_val - tmp_rgb[fst_idx] ? true : false;

            while (list.length < count) {
                if (tmp_rgb[fst_idx] == tmp_rgb[snd_idx] && tmp_rgb[snd_idx] == tmp_rgb[trd_idx]) {
                    list.push(this.rgbToHex(tmp_rgb));
                } else {
                    now_color_range = now_color_range < 1 ? 1 : now_color_range;

                    if (to_up) {
                        if (tmp_rgb[now_idx] + now_color_range > max_val) {
                            now_color_range = now_color_range - (max_val - tmp_rgb[now_idx]);
                            tmp_rgb[now_idx] = max_val;
                            now_idx = this.__getNextIndex(now_idx, idx_list);
                            to_up = false;
                        } else {
                            tmp_rgb[now_idx] = tmp_rgb[now_idx] + now_color_range;

                            color_code_tmp = this.rgbToHex(tmp_rgb);
                            if (list.indexOf(color_code_tmp) < 0 || roop_cnt > 2) {
                                list.push(color_code_tmp);
                                roop_cnt = 0;
                            } else {
                                roop_cnt++;
                            }

                            now_color_range = color_range;
                        }
                    } else {
                        if (tmp_rgb[now_idx] - now_color_range < min_val) {
                            now_color_range = now_color_range - (tmp_rgb[now_idx] - min_val);
                            tmp_rgb[now_idx] = min_val;
                            now_idx = this.__getNextIndex(now_idx, idx_list);
                            to_up = true;
                        } else {
                            tmp_rgb[now_idx] = tmp_rgb[now_idx] - now_color_range;

                            color_code_tmp = this.rgbToHex(tmp_rgb);
                            if (list.indexOf(color_code_tmp) < 0 || roop_cnt > 2) {
                                list.push(color_code_tmp);
                                roop_cnt = 0;
                            } else {
                                roop_cnt++;
                            }

                            now_color_range = color_range;
                        }
                    }
                }
            }

            return list;
        } catch (e) {
            console.log(e);
            return [];
        }
    }

    hexToRgb(color_code) {
        return [parseInt(color_code.substr(1,2), 16), parseInt(color_code.substr(3,2), 16), parseInt(color_code.substr(5,2), 16)];
    }

    rgbToHex(rgb) {
        let r = parseInt(rgb[0]).toString(16).length == 1 ? `0${parseInt(rgb[0]).toString(16)}` : parseInt(rgb[0]).toString(16);
        let g = parseInt(rgb[1]).toString(16).length == 1 ? `0${parseInt(rgb[1]).toString(16)}` : parseInt(rgb[1]).toString(16);
        let b = parseInt(rgb[2]).toString(16).length == 1 ? `0${parseInt(rgb[2]).toString(16)}` : parseInt(rgb[2]).toString(16);
        return `#${r}${g}${b}`;
    }

    __getNextIndex(now_idx, idx_list) {
        switch (now_idx) {
            case idx_list[0]: return idx_list[1];
            case idx_list[1]: return idx_list[2];
            case idx_list[2]: return idx_list[0];
        }
    }

}<commit_msg>added function that generate random color<commit_after>class ColorManager {
    randColorCode(is_rgb = false) {
        const rgb = [Math.floor(Math.random()*(255)), Math.floor(Math.random()*(255)), Math.floor(Math.random()*(255))];
        console.log(rgb);
        if (typeof is_rgb != 'undefined' && is_rgb == true) {
            return rgb;
        } else {
            return this.rgbToHex(rgb)
        }
    }

    generateGradationColorListByHex(count, base_code) {
        const list = [];
        try {
            if (count < 1) throw '"gen_cnt" must be an integer greater than or equal to 1.';

            if (!base_code.match(/^#[0-9a-f]{6}$/i)) throw `The format of "base_color" is invalid. Please specify it with 6 hexadecimal digits. {${base_code}}`;

            const base_rgb = this.hexToRgb(base_code);
            const max_val = Math.max.apply(null, base_rgb);
            const min_val = Math.min.apply(null, base_rgb);
            let color_range = Math.floor(((max_val - min_val) * 6) / count);
            if (color_range < 1) color_range = 1;

            const max_val_idx = base_rgb.indexOf(max_val);
            const min_val_idx = base_rgb.indexOf(min_val);

            const snd_idx = max_val_idx;
            const trd_idx = min_val_idx;
            const fst_idx = 3 - snd_idx - trd_idx;

            const idx_list = [fst_idx, snd_idx, trd_idx];
            let tmp_rgb = base_rgb;
            let roop_cnt = 0;
            let now_idx = fst_idx, next_idx = snd_idx;
            let now_color_range = color_range, color_code_tmp = '';
            let to_up = tmp_rgb[fst_idx] - min_val > max_val - tmp_rgb[fst_idx] ? true : false;

            while (list.length < count) {
                if (tmp_rgb[fst_idx] == tmp_rgb[snd_idx] && tmp_rgb[snd_idx] == tmp_rgb[trd_idx]) {
                    list.push(this.rgbToHex(tmp_rgb));
                } else {
                    now_color_range = now_color_range < 1 ? 1 : now_color_range;

                    if (to_up) {
                        if (tmp_rgb[now_idx] + now_color_range > max_val) {
                            now_color_range = now_color_range - (max_val - tmp_rgb[now_idx]);
                            tmp_rgb[now_idx] = max_val;
                            now_idx = this.__getNextIndex(now_idx, idx_list);
                            to_up = false;
                        } else {
                            tmp_rgb[now_idx] = tmp_rgb[now_idx] + now_color_range;

                            color_code_tmp = this.rgbToHex(tmp_rgb);
                            if (list.indexOf(color_code_tmp) < 0 || roop_cnt > 2) {
                                list.push(color_code_tmp);
                                roop_cnt = 0;
                            } else {
                                roop_cnt++;
                            }

                            now_color_range = color_range;
                        }
                    } else {
                        if (tmp_rgb[now_idx] - now_color_range < min_val) {
                            now_color_range = now_color_range - (tmp_rgb[now_idx] - min_val);
                            tmp_rgb[now_idx] = min_val;
                            now_idx = this.__getNextIndex(now_idx, idx_list);
                            to_up = true;
                        } else {
                            tmp_rgb[now_idx] = tmp_rgb[now_idx] - now_color_range;

                            color_code_tmp = this.rgbToHex(tmp_rgb);
                            if (list.indexOf(color_code_tmp) < 0 || roop_cnt > 2) {
                                list.push(color_code_tmp);
                                roop_cnt = 0;
                            } else {
                                roop_cnt++;
                            }

                            now_color_range = color_range;
                        }
                    }
                }
            }

            return list;
        } catch (e) {
            console.log(e);
            return [];
        }
    }

    hexToRgb(color_code) {
        return [parseInt(color_code.substr(1,2), 16), parseInt(color_code.substr(3,2), 16), parseInt(color_code.substr(5,2), 16)];
    }

    rgbToHex(rgb) {
        let r = parseInt(rgb[0]).toString(16).length == 1 ? `0${parseInt(rgb[0]).toString(16)}` : parseInt(rgb[0]).toString(16);
        let g = parseInt(rgb[1]).toString(16).length == 1 ? `0${parseInt(rgb[1]).toString(16)}` : parseInt(rgb[1]).toString(16);
        let b = parseInt(rgb[2]).toString(16).length == 1 ? `0${parseInt(rgb[2]).toString(16)}` : parseInt(rgb[2]).toString(16);
        return `#${r}${g}${b}`;
    }

    __getNextIndex(now_idx, idx_list) {
        switch (now_idx) {
            case idx_list[0]: return idx_list[1];
            case idx_list[1]: return idx_list[2];
            case idx_list[2]: return idx_list[0];
        }
    }

}<|endoftext|>


<commit_before>/*
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
                http://www.apache.org/licenses/LICENSE-2.0
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

(function() {
    var joint= null;

    var normalizeConfig = function normalizeConfig(configuration) {
        if (typeof configuration !== 'object') {
            configuration = {};
        }

        if (typeof configuration.label !== 'string') {
            configuration.label = "---";
        }

        if (typeof configuration.background !== 'string') {
            configuration.background = "#FFF";
        }

        if (typeof configuration.iconbackground !== 'string') {
            configuration.iconbackground = "#68B828";
        }

        if (typeof configuration.initfrom !== "number") {
            configuration.initfrom = 0;
        }

        if (typeof configuration.initto !== "number") {
            configuration.initto = 0;
        }

        if (typeof configuration.changetime !== "number") {
            configuration.changetime = 3;
        }

        if (typeof configuration.changeeasing !== "boolean") {
            configuration.changeeasing = true;
        }

        if (typeof configuration.label2 !== "string") {
            configuration.label2 = true;
        }

        if (typeof configuration.label2color !== "string") {
            configuration.label2color = "rgba(0, 0, 0, 0.7)";
        }

        if (typeof configuration.counter2color !== "string") {
            configuration.counter2color = "#000";
        }

        if (typeof configuration.decimal2 !== "number") {
            configuration.decimal2 = 2;
        }

        if (typeof configuration.icon !== "string") {
            configuration.icon = "octicon octicon-octoface";
        }

        if (typeof configuration.iconcolor !== "string") {
            configuration.iconcolor = "#FFF";
        }

        if (typeof configuration.labelcolor !== "string") {
            configuration.labelcolor = "rgba(0, 0, 0, 0.7)";
        }

        if (typeof configuration.countercolor !== "string") {
            configuration.countercolor = "#000";
        }

        if (typeof configuration.decimal !== "number") {
            configuration.decimal = 2;
        }
        return configuration;
    };

    /* BuildTransitions constructor
    *   element: the DOM element that will contains the BuildTransitions div
    *   data: the data id array
    *   contextId: if necesary, the contextId link this chart data data
    *           with changes in other context provider chart.
    *  configuration: you can use his optional parameter to assing a custom
    *       contextID for this context provider chart. Ej:
    *      {
    *         label: label text,
    *         labelcolor: label text color,
    *         countercolor: color of the number,
    *         label2: label2 text,
    *         label2color: label2 text color,
    *         counter2color: color of the second counter number,
    *         background: optional color in any css compatible format ej: "#0C0C0C" (default #FFF),
    *         initfrom: optional initial animation value (default 0),
    *         initto: optional final animation value (default 0),
    *         changetime: this time in seconds set the change data animation duration (default 3),
    *         changeeasing: optional animation effect data-easing fast-slow (default true),
    *         icon: optional icon css class (default "octicon octicon-octoface"),
    *         iconcolor: widget icon color,
    *         iconbackground: optional color in any css compatible format ej: "#0C0C0C" (default #68B828),
    *         decimal: number of decimals in metric value
    *      }
    */
    var BuildTransitions = function BuildTransitions(element, metrics, contextId, configuration) {
        console.log("BuildTransitions 1");
        if(!framework.isReady()) {
            console.error("BuildTransitions object could not be created because framework is not loaded.");
            return;
        }

        // CHECK Joint.js
        if(typeof joint === 'undefined') {
            console.log("BuildTransitions could not be loaded.");
            //return;
        }

        // extending widget
        this.element = $(element);
        framework.widgets.CommonWidget.call(this, false, this.element.get(0));

        // Configuration
        //this.configuration = normalizeConfig(configuration);
        this.configuration = configuration;

        this.observeCallback = this.commonObserveCallback.bind(this);

        framework.data.observe(metrics, function(e) {
                this.observeCallback(e);
            }.bind(this),
            contextId, 1
        );

    };

    BuildTransitions.prototype = new framework.widgets.CommonWidget(true);

    BuildTransitions.prototype.updateData = function(framework_data) {
        console.log("Updating BuildTransitions 1");
        var normalizedData = getNormalizedData.call(this,framework_data);

        //Update data
        if(this.chart != null) {
            updateValues.call(this, normalizedData);
        } else { // Paint it for first time
            paint.call(this, normalizedData, framework_data);
        }
    };

    BuildTransitions.prototype.delete = function() {

        //Stop observing for data changes
        framework.data.stopObserve(this.observeCallback);

        //Clear DOM
        $(this.container).empty();
        this.element.empty();

    };

    //Function that returns the value to replace with the label variables
    var replacer = function(resourceId, resource, str) {

        //Remove the initial an trailing '%' of the string
        str = str.substring(1, str.length-1);

        //Check if it is a parameter an return its value
        if(str === "resourceId") { //Special command to indicate the name of the resource
            return resourceId;

        } else { // Obtain its value through the object given the path

            var path = str.split(".");
            var subObject = resource;

            for(var p = 0; p < path.length; ++p) {
                if((subObject = subObject[path[p]]) == null)
                    return "";
            }

            return subObject.toString();
        }

    };
    var currentValues = {
            "pas_pas": 0,
            "pas_brk": 0,
            "brk_fix": 0,
            "fix_pas": 0,
            "fix_fai": 0,
            "fai_fai": 0,
            "fai_fix": 0
    };
    // TODO take this from config
    var flagMat = {
            paspasmetricid: "pas_pas",
            pasbrkmetricid: "pas_brk",
            brkfixmetricid: "brk_fix",
            fixpasmetricid: "fix_pas",
            fixfaimetricid: "fix_fai",
            faifaimetricid: "fai_fai",
            faifixmetricid: "fai_fix"
    };

    /**
     * random number from interval.
     * @param min
     * @param max
     * @returns {Number} random number
     */
    var randomIntFromInterval = function randomIntFromInterval(min,max) {
        return Math.floor(Math.random()*(max-min+1)+min);
    };

    /**
     * Update link values.
     * @param data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var updateValues = function updateValues(framework_data) {
        //TODO use real data
        /*for (var metricId in framework_data) {
            for (var m in framework_data[metricId]) {
                // only 1
                currentValues[flagMat[metricId]] = framework_data[metricId][m]['data'][0];
            }
        }*/
        currentValues = {
            "pas_pas": randomIntFromInterval(1,300),
            "pas_brk": randomIntFromInterval(1,300),
            "brk_fix": randomIntFromInterval(1,300),
            "fix_pas": randomIntFromInterval(1,300),
            "fix_fai": randomIntFromInterval(1,300),
            "fai_fai": randomIntFromInterval(1,300),
            "fai_fix": randomIntFromInterval(1,300)
        };
        for (var key in this.linksById) {
            this.linksById[key].label(0, {
                position: .5,
                attrs: {
                    text: { text: currentValues[key] }
                }
            })
        }
    };

    /**
     * Gets a normalized array of data according to the chart expected input from the data returned by the framework.
     * @param framework_data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var getNormalizedData = function getNormalizedData(framework_data) {
        return framework_data;
    };

    /**
     * Gets a normalized array of data according to the chart expected input from the data returned by the framework.
     * @param framework_data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var paint = function paint(normalizedData, framework_data) {
        //require(['joint'], function(joint) {
        var graph = new joint.dia.Graph();
        var paper = new joint.dia.Paper({
            el: this.element,
            width: 530,
            height: 318,
            gridSize: 10,
            perpendicularLinks: true,
            model: graph
        });

        var pn = joint.shapes.pn;

        // Generic box
        var genericBox = new pn.Transition({
            size: { width: 70, height: 70 },
            attrs: {
                '.label': { fill: 'black'},
                '.root' : { fill: '#9586fd', stroke: '#9586fd' }
            }
        });

        //Generic Ball
        var genericBall = new pn.Place({
            position: { x: 200, y: 50 },
            size: { width: 70, height: 70 },
            attrs: {
                '.root' : { stroke: '#9586fd', 'stroke-width': 3},
                '.tokens > circle': { fill : '#7a7e9b'}
            }
        });

        var passedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'green',
                'font-size': 12
            }
        }).position(60, 60).set('tokens', "Passed");

        var brokenBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'red',
                'font-size': 12
            }
        }).position(60, 225).set('tokens', 'Broken');

        var fixedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'green',
                'font-size': 12
            }
        }).position(220, 130).set('tokens', 'Fixed');

        var failedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'red',
                'font-size': 12
            }
        }).position(400, 60).set('tokens', 'Failed');

        this.linksById = {};

        var link = function link (a, b, type, linkShape, color, position) {
            if (typeof position !== 'number') {
                position = .2;
            } else {
                console.log(position);
            }
            var newLink = new pn.Link({
                source: { id: a.id, selector: '.root'},
                target: { id: b.id, selector: '.root' },
                attrs: {
                    '.connection': {
                        'fill': 'none',
                        'stroke-linejoin': 'round',
                        'stroke-width': '2',
                        'stroke': '#4b4a67'
                    }
                },
                labels: [
                    {
                        position: position,
                        attrs: {
                            rect: { fill: 'white' },
                            text: {
                                'fill': color,
                                'text': "--",
                                'font-family': 'Courier New',
                                'font-size': 20,
                                'font-weight': 'bold',
                                'ref-x': 0.5,
                                'ref-y': 0.5
                            }
                        }
                    }
                ]
            });
            /*newLink.label(0, {
                position: position,
                attrs: {
                    rect: { fill: 'white' },
                    text: {
                        'fill': color,
                        'text': "--",
                        'font-family': 'Courier New',
                        'font-size': 20,
                        'font-weight': 'bold',
                        'ref-x': 0.5,
                        'ref-y': 0.5
                    }
                }
            });*/
            //newLink.set('manhattan', true);
            //newLink.set('smooth', true);
            //newLink.set('orthogonal', true);
            if (typeof linkShape !== 'object' || linkShape == null) {
                newLink.set("smooth", true);
            } else {
                for (var i = linkShape.length - 1; i >= 0; i--) {
                    newLink.set(linkShape[i], true);
                };
            }
            this.linksById[type] = newLink;
            return newLink;
        }.bind(this);

        graph.addCell([ passedBall, brokenBall, fixedBall, failedBall]);

        graph.addCell([
            link(passedBall, passedBall, "pas_pas", ["manhattan", "smooth"], 'green'),
            link(passedBall, brokenBall, "pas_brk", null, 'red'),
            link(brokenBall, fixedBall, "brk_fix", null, 'green'),
            link(fixedBall, passedBall, "fix_pas", null, 'green'),
            link(fixedBall, failedBall, "fix_fai", ["manhattan", "smooth"], 'red', 0),
            link(failedBall, failedBall, "fai_fai", ["manhattan", "smooth"], 'red'),
            link(failedBall, fixedBall, "fai_fix", null, 'green', -0.1)
        ]);

        function fireTransition(t, sec) {

            var allbound = graph.getConnectedLinks(t);
            var elemcolors = [];
            var color;
            for (var i = 0; i < allbound.length; i++) {
                var source = graph.getCell(allbound[i].get('source').id);
                var target = graph.getCell(allbound[i].get('target').id);
                var sourceid = source.attributes.tokens;
                var targetid = target.attributes.tokens;
                if (targetid == "Failed" || targetid == "Broken") {
                    color = "red";
                } else {
                    color = "green";
                }
                elemcolors.push({target : target, source : source, color: color});
            }

            var isFirable = true;

            if (isFirable) {
                _.each(elemcolors,
                    function(p) {
                        var link = _.find(allbound, function(l) {
                        return (l.get('target').id === p.target.id) && (l.get('source').id === p.source.id)
                    });
                    paper.findViewByModel(link).sendToken(joint.Vectorizer('circle', { r: 7, fill: p.color }).node, sec * 1300);
                });
            }
        }

        function simulate() {
            var transitions = [passedBall, failedBall, brokenBall, fixedBall];
            _.each(transitions, function(t) { fireTransition(t, 1); });
            return setInterval(function() {
                _.each(transitions, function(t) { fireTransition(t, 1); });
            }, 2000);
        }

        function stopSimulation(simulationId) {
            clearInterval(simulationId);
        }

        var simulationId = simulate();

        updateValues.call(this, normalizedData);
        //}).bind(this);
    };

    window.framework.widgets.BuildTransitions = BuildTransitions;

    // AMD compliant
    if ( typeof define === "function" && define.amd) {
        define( ['joint'], function (_joint) {
            joint = _joint;
            return BuildTransitions;
        });
    }

})();<commit_msg>[Widget][buildTransitions] Improve style and initial node positions<commit_after>/*
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
                http://www.apache.org/licenses/LICENSE-2.0
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

(function() {
    var joint= null;

    var normalizeConfig = function normalizeConfig(configuration) {
        if (typeof configuration !== 'object') {
            configuration = {};
        }

        if (typeof configuration.label !== 'string') {
            configuration.label = "---";
        }

        if (typeof configuration.background !== 'string') {
            configuration.background = "#FFF";
        }

        if (typeof configuration.iconbackground !== 'string') {
            configuration.iconbackground = "#68B828";
        }

        if (typeof configuration.initfrom !== "number") {
            configuration.initfrom = 0;
        }

        if (typeof configuration.initto !== "number") {
            configuration.initto = 0;
        }

        if (typeof configuration.changetime !== "number") {
            configuration.changetime = 3;
        }

        if (typeof configuration.changeeasing !== "boolean") {
            configuration.changeeasing = true;
        }

        if (typeof configuration.label2 !== "string") {
            configuration.label2 = true;
        }

        if (typeof configuration.label2color !== "string") {
            configuration.label2color = "rgba(0, 0, 0, 0.7)";
        }

        if (typeof configuration.counter2color !== "string") {
            configuration.counter2color = "#000";
        }

        if (typeof configuration.decimal2 !== "number") {
            configuration.decimal2 = 2;
        }

        if (typeof configuration.icon !== "string") {
            configuration.icon = "octicon octicon-octoface";
        }

        if (typeof configuration.iconcolor !== "string") {
            configuration.iconcolor = "#FFF";
        }

        if (typeof configuration.labelcolor !== "string") {
            configuration.labelcolor = "rgba(0, 0, 0, 0.7)";
        }

        if (typeof configuration.countercolor !== "string") {
            configuration.countercolor = "#000";
        }

        if (typeof configuration.decimal !== "number") {
            configuration.decimal = 2;
        }
        return configuration;
    };

    /* BuildTransitions constructor
    *   element: the DOM element that will contains the BuildTransitions div
    *   data: the data id array
    *   contextId: if necesary, the contextId link this chart data data
    *           with changes in other context provider chart.
    *  configuration: you can use his optional parameter to assing a custom
    *       contextID for this context provider chart. Ej:
    *      {
    *         label: label text,
    *         labelcolor: label text color,
    *         countercolor: color of the number,
    *         label2: label2 text,
    *         label2color: label2 text color,
    *         counter2color: color of the second counter number,
    *         background: optional color in any css compatible format ej: "#0C0C0C" (default #FFF),
    *         initfrom: optional initial animation value (default 0),
    *         initto: optional final animation value (default 0),
    *         changetime: this time in seconds set the change data animation duration (default 3),
    *         changeeasing: optional animation effect data-easing fast-slow (default true),
    *         icon: optional icon css class (default "octicon octicon-octoface"),
    *         iconcolor: widget icon color,
    *         iconbackground: optional color in any css compatible format ej: "#0C0C0C" (default #68B828),
    *         decimal: number of decimals in metric value
    *      }
    */
    var BuildTransitions = function BuildTransitions(element, metrics, contextId, configuration) {
        console.log("BuildTransitions 1");
        if(!framework.isReady()) {
            console.error("BuildTransitions object could not be created because framework is not loaded.");
            return;
        }

        // CHECK Joint.js
        if(typeof joint === 'undefined') {
            console.log("BuildTransitions could not be loaded.");
            //return;
        }

        // extending widget
        this.element = $(element);
        framework.widgets.CommonWidget.call(this, false, this.element.get(0));

        // Configuration
        //this.configuration = normalizeConfig(configuration);
        this.configuration = configuration;

        this.observeCallback = this.commonObserveCallback.bind(this);

        framework.data.observe(metrics, function(e) {
                this.observeCallback(e);
            }.bind(this),
            contextId, 1
        );

    };

    BuildTransitions.prototype = new framework.widgets.CommonWidget(true);

    BuildTransitions.prototype.updateData = function(framework_data) {
        console.log("Updating BuildTransitions 1");
        var normalizedData = getNormalizedData.call(this,framework_data);

        //Update data
        if(this.chart != null) {
            updateValues.call(this, normalizedData);
        } else { // Paint it for first time
            paint.call(this, normalizedData, framework_data);
        }
    };

    BuildTransitions.prototype.delete = function() {

        //Stop observing for data changes
        framework.data.stopObserve(this.observeCallback);

        //Clear DOM
        $(this.container).empty();
        this.element.empty();

    };

    //Function that returns the value to replace with the label variables
    var replacer = function(resourceId, resource, str) {

        //Remove the initial an trailing '%' of the string
        str = str.substring(1, str.length-1);

        //Check if it is a parameter an return its value
        if(str === "resourceId") { //Special command to indicate the name of the resource
            return resourceId;

        } else { // Obtain its value through the object given the path

            var path = str.split(".");
            var subObject = resource;

            for(var p = 0; p < path.length; ++p) {
                if((subObject = subObject[path[p]]) == null)
                    return "";
            }

            return subObject.toString();
        }

    };
    var currentValues = {
            "pas_pas": 0,
            "pas_brk": 0,
            "brk_fix": 0,
            "fix_pas": 0,
            "fix_fai": 0,
            "fai_fai": 0,
            "fai_fix": 0
    };
    // TODO take this from config
    var flagMat = {
            paspasmetricid: "pas_pas",
            pasbrkmetricid: "pas_brk",
            brkfixmetricid: "brk_fix",
            fixpasmetricid: "fix_pas",
            fixfaimetricid: "fix_fai",
            faifaimetricid: "fai_fai",
            faifixmetricid: "fai_fix"
    };

    /**
     * random number from interval.
     * @param min
     * @param max
     * @returns {Number} random number
     */
    var randomIntFromInterval = function randomIntFromInterval(min,max) {
        return Math.floor(Math.random()*(max-min+1)+min);
    };

    /**
     * Update link values.
     * @param data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var updateValues = function updateValues(framework_data) {
        //TODO use real data
        /*for (var metricId in framework_data) {
            for (var m in framework_data[metricId]) {
                // only 1
                currentValues[flagMat[metricId]] = framework_data[metricId][m]['data'][0];
            }
        }*/
        currentValues = {
            "pas_pas": randomIntFromInterval(1,300),
            "pas_brk": randomIntFromInterval(1,300),
            "brk_fix": randomIntFromInterval(1,300),
            "brk_fai": randomIntFromInterval(1,300),
            "fix_pas": randomIntFromInterval(1,300),
            "fix_brk": randomIntFromInterval(1,300),
            "fai_fai": randomIntFromInterval(1,300),
            "fai_fix": randomIntFromInterval(1,300)
        };
        for (var key in this.linksById) {
            this.linksById[key].label(0, {
                position: .5,
                attrs: {
                    text: { text: currentValues[key] }
                }
            })
        }
    };

    /**
     * Gets a normalized array of data according to the chart expected input from the data returned by the framework.
     * @param framework_data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var getNormalizedData = function getNormalizedData(framework_data) {
        return framework_data;
    };

    /**
     * Gets a normalized array of data according to the chart expected input from the data returned by the framework.
     * @param framework_data
     * @returns {Array} Contains objects with 'label' and 'value'.
     */
    var paint = function paint(normalizedData, framework_data) {
        //require(['joint'], function(joint) {
        var graph = new joint.dia.Graph();
        var paper = new joint.dia.Paper({
            el: this.element,
            width: 630,
            height: 348,
            gridSize: 10,
            perpendicularLinks: true,
            model: graph
        });

        var pn = joint.shapes.pn;

        // Generic box
        var genericBox = new pn.Transition({
            size: { width: 70, height: 70 },
            attrs: {
                '.label': { fill: 'black'},
                '.root' : { fill: '#9586fd', stroke: '#9586fd' }
            }
        });

        //Generic Ball
        var genericBall = new pn.Place({
            position: { x: 200, y: 50 },
            size: { width: 70, height: 70 },
            attrs: {
                '.root' : { stroke: '#9586fd', 'stroke-width': 3},
                '.tokens > circle': { fill : '#7a7e9b'}
            }
        });

        var passedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'green',
                'font-size': 12
            }
        }).position(60, 60).set('tokens', "Passed");

        var brokenBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'red',
                'font-size': 12
            }
        }).position(60, 225).set('tokens', 'Broken');

        var fixedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'green',
                'font-size': 12
            }
        }).position(400, 60).set('tokens', 'Fixed');

        var failedBall = genericBall.clone().attr({
            '.alot > text': {
                'fill': 'red',
                'font-size': 12
            }
        }).position(400, 225).set('tokens', 'Failed');

        this.linksById = {};

        var link = function link (a, b, type, linkShape, color, position) {
            if (typeof position !== 'number') {
                position = .2;
            } else {
                console.log(position);
            }
            var newLink = new pn.Link({
                source: { id: a.id, selector: '.root'},
                target: { id: b.id, selector: '.root' },
                attrs: {
                    '.connection': {
                        'fill': 'none',
                        'stroke-linejoin': 'round',
                        'stroke-width': '2',
                        'stroke': '#4b4a67'
                    }
                },
                labels: [
                    {
                        position: position,
                        attrs: {
                            rect: { fill: 'white' },
                            text: {
                                'fill': color,
                                'text': "--",
                                'font-family': 'Courier New',
                                'font-size': 20,
                                'font-weight': 'bold',
                                'ref-x': 0.5,
                                'ref-y': 0.5
                            }
                        }
                    }
                ]
            });
            /*newLink.label(0, {
                position: position,
                attrs: {
                    rect: { fill: 'white' },
                    text: {
                        'fill': color,
                        'text': "--",
                        'font-family': 'Courier New',
                        'font-size': 20,
                        'font-weight': 'bold',
                        'ref-x': 0.5,
                        'ref-y': 0.5
                    }
                }
            });*/
            //newLink.set('manhattan', true);
            //newLink.set('smooth', true);
            //newLink.set('orthogonal', true);
            if (typeof linkShape !== 'object' || linkShape == null) {
                newLink.set("smooth", true);
            } else {
                for (var i = linkShape.length - 1; i >= 0; i--) {
                    newLink.set(linkShape[i], true);
                };
            }
            this.linksById[type] = newLink;

            // Ñapping edges
            if (type == "brk_fix") {
                newLink.set("vertices", [{ x: 255, y: 155 }]);
            } else if (type == "fix_brk") {
                newLink.set("vertices", [{ x: 280, y: 200 }]);
            } else if (type == "fai_fai") {
                newLink.set("vertices", [{ x: 502, y: 317 }]);
            }

            return newLink;
        }.bind(this);

        graph.addCell([ passedBall, brokenBall, fixedBall, failedBall]);

        graph.addCell([
            link(passedBall, passedBall, "pas_pas", ["manhattan", "smooth"], 'green'),
            link(passedBall, brokenBall, "pas_brk", null, 'red'),
            link(brokenBall, fixedBall, "brk_fix", null, 'green'),
            link(brokenBall, failedBall, "brk_fai", null, 'red'),
            link(fixedBall, passedBall, "fix_pas", null, 'green'),
            link(fixedBall, brokenBall, "fix_brk", ["smooth"], 'red', 0),
            link(failedBall, failedBall, "fai_fai", ["manhattan", "smooth"], 'red'),
            link(failedBall, fixedBall, "fai_fix", null, 'green', -0.1)
        ]);

        function fireTransition(t, sec) {

            var allbound = graph.getConnectedLinks(t);
            var elemcolors = [];
            var color;
            for (var i = 0; i < allbound.length; i++) {
                var source = graph.getCell(allbound[i].get('source').id);
                var target = graph.getCell(allbound[i].get('target').id);
                var sourceid = source.attributes.tokens;
                var targetid = target.attributes.tokens;
                if (targetid == "Failed" || targetid == "Broken") {
                    color = "red";
                } else {
                    color = "green";
                }
                elemcolors.push({target : target, source : source, color: color});
            }

            var isFirable = true;

            if (isFirable) {
                _.each(elemcolors,
                    function(p) {
                        var link = _.find(allbound, function(l) {
                        return (l.get('target').id === p.target.id) && (l.get('source').id === p.source.id)
                    });
                    paper.findViewByModel(link).sendToken(joint.Vectorizer('circle', { r: 7, fill: p.color }).node, sec * 1300);
                });
            }
        }

        function simulate() {
            var transitions = [passedBall, failedBall, brokenBall, fixedBall];
            _.each(transitions, function(t) { fireTransition(t, 1); });
            return setInterval(function() {
                _.each(transitions, function(t) { fireTransition(t, 1); });
            }, 2000);
        }

        function stopSimulation(simulationId) {
            clearInterval(simulationId);
        }

        var simulationId = simulate();

        updateValues.call(this, normalizedData);
        //}).bind(this);
    };

    window.framework.widgets.BuildTransitions = BuildTransitions;

    // AMD compliant
    if ( typeof define === "function" && define.amd) {
        define( ['joint'], function (_joint) {
            joint = _joint;
            return BuildTransitions;
        });
    }

})();<|endoftext|>


<commit_before>'use strict';

/*
    * Move mouse: look around
    * Mouse down: move forward
    * Mouse up: stop moving forward
*/

var THREE = require('three');
var _getFloorHeight = require('../distanceToFloor.js');

var cos = Math.cos,
    sin = Math.sin,
    pow = Math.pow;

var HEIGHT = 6;

var DISTANCE_TO_LOOK_AT = 20;
var MAX_HORI_SPEED = Math.PI/100;
var MAX_VERTI_SPEED = Math.PI/120;

module.exports = function(camera, scene, domElement){

    var getFloorHeight = _getFloorHeight(scene);

    var alpha;
    var beta;
    // var animationFrame;
    var rotation = 0;

    var lookAtPoint;

    function moveCamera(){
        var newx = camera.position.x +
            ((lookAtPoint.x - camera.position.x)*cos(alpha) - (lookAtPoint.y - camera.position.y)*sin(alpha));
        var newy = camera.position.y +
            ((lookAtPoint.x - camera.position.x)*sin(alpha) + (lookAtPoint.y - camera.position.y)*cos(alpha));
        var newz = camera.position.z + 20*DISTANCE_TO_LOOK_AT * Math.sin(beta);
        // console.log("beta", beta, "alpha", alpha, "newz", newz)

        lookAtPoint.x = newx;
        lookAtPoint.y = newy;
        lookAtPoint.z = newz;

        camera.lookAt( lookAtPoint );
        rotation += alpha;
        // animationFrame = requestAnimationFrame(moveCamera)
    }

    function mouseMoveListener(e){
        var canvasBoundingRect = domElement.getBoundingClientRect();

        var deltaX = e.clientX - canvasBoundingRect.width/2;
        var deltaZ = e.clientY - canvasBoundingRect.height/2;

        if(Math.abs(deltaX) > canvasBoundingRect.width/10 || Math.abs(deltaZ) > canvasBoundingRect.height/20){

            if (Math.abs(deltaX) > canvasBoundingRect.width/10){
                alpha = MAX_HORI_SPEED *
                    (Math.abs(deltaX) - canvasBoundingRect.width/10)/
                    (canvasBoundingRect.width/2 - canvasBoundingRect.width/10);
                if(deltaX > 0)
                    alpha = -alpha;
            } else {alpha = 0}

            if (Math.abs(deltaZ) > canvasBoundingRect.height/20){
                beta = MAX_VERTI_SPEED *
                    (Math.abs(deltaZ) - canvasBoundingRect.height/20)/
                    (canvasBoundingRect.height/2 - canvasBoundingRect.height/20);
                if(deltaZ > 0)
                    beta = -beta;
            } else { beta = 0}

            // if(!animationFrame)
            //     animationFrame = requestAnimationFrame(moveCamera)
        }
        // else{
        //     cancelAnimationFrame(animationFrame);
        //     animationFrame = undefined;
        // }
    }

    var moveAnimationFrame;
    var SPEED = 0.05;

    function mouseDownListener(){

        moveAnimationFrame = requestAnimationFrame(function moveForward(){

            var moveVector = {
                x : lookAtPoint.x - camera.position.x,
                y : lookAtPoint.y - camera.position.y,
            };
            camera.position.x += SPEED*moveVector.x;
            lookAtPoint.x     += SPEED*moveVector.x;
            camera.position.y += SPEED*moveVector.y;
            lookAtPoint.y     += SPEED*moveVector.y;

            var rayCasterPosition = camera.position;
            rayCasterPosition.z = 10000;
            var distanceToFloor = getFloorHeight(rayCasterPosition);
            if(distanceToFloor !== undefined){
                camera.position.z += HEIGHT - distanceToFloor;
            }

            moveAnimationFrame = requestAnimationFrame(moveForward);
        });

    }

    function mouseUpListener(){
        cancelAnimationFrame(moveAnimationFrame);
        moveAnimationFrame = undefined;
    }

    return function(x, y){
        camera.up = new THREE.Vector3(0, 0, 1);
        camera.near = 1;
        camera.far = 50;

        var rayCasterPosition = camera.position;
        rayCasterPosition.z = 10000;
        var distanceToFloor = getFloorHeight(rayCasterPosition);
        console.log('distance to floor', distanceToFloor, camera.position.z + HEIGHT - distanceToFloor)

        // init camera
        camera.position.x = x;
        camera.position.y = y;
        camera.position.z = distanceToFloor !== undefined ? camera.position.z + HEIGHT - distanceToFloor : HEIGHT;

        // Looking north
        lookAtPoint = new THREE.Vector3( camera.position.x, camera.position.y + DISTANCE_TO_LOOK_AT, camera.position.z )
        camera.lookAt( lookAtPoint );

        domElement.addEventListener('mousemove', mouseMoveListener);
        domElement.addEventListener('mousedown', mouseDownListener);
        domElement.addEventListener('mouseup', mouseUpListener);

        return function desactivate(){
            domElement.removeEventListener('mousemove', mouseMoveListener);
            domElement.removeEventListener('mousedown', mouseDownListener);
            domElement.removeEventListener('mouseup', mouseUpListener);
            cancelAnimationFrame(moveAnimationFrame);
            moveAnimationFrame = undefined;
        };
    }

};<commit_msg>fixed mouseMove call in FPS view<commit_after>'use strict';

/*
    * Move mouse: look around
    * Mouse down: move forward
    * Mouse up: stop moving forward
*/

var THREE = require('three');
var _getFloorHeight = require('../distanceToFloor.js');

var cos = Math.cos,
    sin = Math.sin,
    pow = Math.pow;

var HEIGHT = 6;

var DISTANCE_TO_LOOK_AT = 20;
var MAX_HORI_SPEED = Math.PI/100;
var MAX_VERTI_SPEED = Math.PI/120;

module.exports = function(camera, scene, domElement){

    var getFloorHeight = _getFloorHeight(scene);

    var alpha;
    var beta;
    var animationFrame;
    var rotation = 0;

    var lookAtPoint;

    function moveCamera(){
        var newx = camera.position.x +
            ((lookAtPoint.x - camera.position.x)*cos(alpha) - (lookAtPoint.y - camera.position.y)*sin(alpha));
        var newy = camera.position.y +
            ((lookAtPoint.x - camera.position.x)*sin(alpha) + (lookAtPoint.y - camera.position.y)*cos(alpha));
        var newz = camera.position.z + 20*DISTANCE_TO_LOOK_AT * Math.sin(beta);
        // console.log("beta", beta, "alpha", alpha, "newz", newz)

        lookAtPoint.x = newx;
        lookAtPoint.y = newy;
        lookAtPoint.z = newz;

        camera.lookAt( lookAtPoint );
        rotation += alpha;
        // animationFrame = requestAnimationFrame(moveCamera)
    }

    function mouseMoveListener(e){
        var canvasBoundingRect = domElement.getBoundingClientRect();

        var deltaX = e.clientX - canvasBoundingRect.width/2;
        var deltaZ = e.clientY - canvasBoundingRect.height/2;

        if(Math.abs(deltaX) > canvasBoundingRect.width/10 || Math.abs(deltaZ) > canvasBoundingRect.height/20){

            if (Math.abs(deltaX) > canvasBoundingRect.width/10){
                alpha = MAX_HORI_SPEED *
                    (Math.abs(deltaX) - canvasBoundingRect.width/10)/
                    (canvasBoundingRect.width/2 - canvasBoundingRect.width/10);
                if(deltaX > 0)
                    alpha = -alpha;
            } else {alpha = 0}

            if (Math.abs(deltaZ) > canvasBoundingRect.height/20){
                beta = MAX_VERTI_SPEED *
                    (Math.abs(deltaZ) - canvasBoundingRect.height/20)/
                    (canvasBoundingRect.height/2 - canvasBoundingRect.height/20);
                if(deltaZ > 0)
                    beta = -beta;
            } else { beta = 0}

            moveCamera();

            // if(!animationFrame)
            //     animationFrame = requestAnimationFrame(moveCamera)
        }
        // else{
        //     cancelAnimationFrame(animationFrame);
        //     animationFrame = undefined;
        // }
    }

    var moveAnimationFrame;
    var SPEED = 0.05;

    function mouseDownListener(){

        moveAnimationFrame = requestAnimationFrame(function moveForward(){

            var moveVector = {
                x : lookAtPoint.x - camera.position.x,
                y : lookAtPoint.y - camera.position.y,
            };
            camera.position.x += SPEED*moveVector.x;
            lookAtPoint.x     += SPEED*moveVector.x;
            camera.position.y += SPEED*moveVector.y;
            lookAtPoint.y     += SPEED*moveVector.y;

            var rayCasterPosition = camera.position;
            rayCasterPosition.z = 10000;
            var distanceToFloor = getFloorHeight(rayCasterPosition);
            if(distanceToFloor !== undefined){
                camera.position.z += HEIGHT - distanceToFloor;
            }

            moveAnimationFrame = requestAnimationFrame(moveForward);
        });

    }

    function mouseUpListener(){
        cancelAnimationFrame(moveAnimationFrame);
        moveAnimationFrame = undefined;
    }

    return function(x, y){
        camera.up = new THREE.Vector3(0, 0, 1);
        camera.near = 1;
        camera.far = 50;

        var rayCasterPosition = camera.position;
        rayCasterPosition.z = 10000;
        var distanceToFloor = getFloorHeight(rayCasterPosition);
        console.log('distance to floor', distanceToFloor, camera.position.z + HEIGHT - distanceToFloor)

        // init camera
        camera.position.x = x;
        camera.position.y = y;
        camera.position.z = distanceToFloor !== undefined ? camera.position.z + HEIGHT - distanceToFloor : HEIGHT;

        // Looking north
        lookAtPoint = new THREE.Vector3( camera.position.x, camera.position.y + DISTANCE_TO_LOOK_AT, camera.position.z )
        camera.lookAt( lookAtPoint );

        domElement.addEventListener('mousemove', mouseMoveListener);
        domElement.addEventListener('mousedown', mouseDownListener);
        domElement.addEventListener('mouseup', mouseUpListener);

        return function desactivate(){
            domElement.removeEventListener('mousemove', mouseMoveListener);
            domElement.removeEventListener('mousedown', mouseDownListener);
            domElement.removeEventListener('mouseup', mouseUpListener);
            cancelAnimationFrame(moveAnimationFrame);
            moveAnimationFrame = undefined;
        };
    }

};<|endoftext|>