<commit_before>window.onload = function animateJSON() {

    var animator = JSON.parse(localStorage.getItem('stringJSON'));
    var mainDiv = document.getElementById("outputJSON");

    const processDivClassName = "processes";
    const frameDivClassName = "frame";
    const frameTitleClassName = "frameTitle";
    const lifelines = "lifeLine";
    const activatorClassName = "activator";
    const arrowDivClassName = "arrowLtoR";
    const arrowDivClassName2 = "arrowRtoL";
    const messageDivClassName = "messages";

    for(var i = 0; i < animator.processes.length; i++) {

        var div = document.createElement("div");
        div.className = processDivClassName;
        div.innerHTML =
            animator.processes[i].name.toString() + ": " +
            animator.processes[i].class.toString();
        mainDiv.appendChild(div);

        var lifeLineDiv = document.createElement("div");
        lifeLineDiv.className = lifelines;
        lifeLineDiv.id = animator.processes[i].name.toString();
        var activatorDiv = document.createElement("div");
        activatorDiv.className = activatorClassName;
        div.appendChild(lifeLineDiv);
        lifeLineDiv.appendChild(activatorDiv);
    }

    var animatorDiagramArray = Object.keys(animator.diagram);
     //if (animatorDiagramArray.hasOwnProperty('node'))
    for (var i = 0; i < animatorDiagramArray.length; i++) {
        if (animatorDiagramArray[i] === 'node') {
            var frameDiv = document.createElement("div");
            frameDiv.className = frameDivClassName;
            frameDiv.id = animator.diagram.node.toString();
            var frameTitle = document.createElement("div");
            frameTitle.className = frameTitleClassName;
            frameTitle.id = animator.diagram.node.toString() + "Title";
            frameTitle.innerHTML = animator.diagram.node.toString();
            mainDiv.appendChild(frameDiv);
            frameDiv.appendChild(frameTitle);
        }
    }

    var a = 50;
    var counter = 0;

    for(var j = 0; j < animator.diagram.content.length; j++) {

        if(j !== 0) {
            var lineBreak = document.createElement('hr');
          if (frameDiv !== undefined) {
            //frameDiv.appendChild(lineBreak);
            }
        }

        for (var i = 0; i < animator.diagram.content[j].content.length; i++) {

        }
    }

createArrow(animator, 0, 0, 0, frameDiv, mainDiv);
createLog(animator, 0, 0, 0);

};

function createArrow(animator, j, i, counter, frameDiv,mainDiv){

     if(animator.diagram.content[j].content.length === i){
                i = 0;
                j++;

                var lineBreak = document.createElement('hr');
                if (frameDiv != undefined) {
                 frameDiv.appendChild(lineBreak);
                }
             }

const processDivClassName = "processes";
    const frameDivClassName = "frame";
    const frameTitleClassName = "frameTitle";
    const lifelines = "lifeLine";
    const activatorClassName = "activator";
    const arrowDivClassName = "arrowLtoR";
    const arrowDivClassName2 = "arrowRtoL";
    const messageDivClassName = "messages";

            var startPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].from.toString()));
            var endPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].to.toString()));

            var arrow = document.createElement("div");
            var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
            var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
            var message = document.createElement("div");
            message.className = messageDivClassName;
            svg.setAttribute("preserveAspectRatio", "xMaxYMid slice");

            svg.setAttribute("viewBox", "0 0 1400 14");
            // decides what direction the arrow will go, and makes the length of the arrows

            if (startPosition.x > endPosition.x) {
                arrow.className = arrowDivClassName2;
                var arrowLengthLeft = startPosition.x - endPosition.x;
                svg.setAttribute("width", arrowLengthLeft + "px");
                arrow.style.transform = "rotate(180deg)";
                arrow.style.left = startPosition.x - 30 + 'px';
                message.style.left = arrowLengthLeft / 2 + 'px';
                message.style.top = 40 + 'px';
                message.style.transform = "rotate(180deg)";
            }
            else {
                arrow.className = arrowDivClassName;
                var arrowLengthRight = endPosition.x - startPosition.x;
                svg.setAttribute("width", arrowLengthRight + "px");
                arrow.style.left = startPosition.x - 30 + 'px';
                message.style.left = arrowLengthRight / 2 + 'px';
            }

            svg.setAttribute("height", "14");
            polygon.setAttribute("points", "1400,7 1385,1 1390,6 0,6 0,8 1390,8 1385,13 1400,7");

            message.innerHTML =
                animator.diagram.content[j].content[i].message.toString();

            // making so every arrow is on their own line with 50px heigth difference
           // arrow.style.top = startPosition.y + counter * a - 20 + 'px';
            counter++;
            arrow.style.right = ((startPosition.x) - (startPosition.x - endPosition.x)) + 'px';

            // arrow.innerHTML =
            //     animator.diagram.content[0].content[i].message.toString();

            // arrow.style.position = "absolute";
            // arrow.style.left = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().left.toString() + 'px';
            // arrow.style.right = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().right.toString() + 'px';
            // arrow.style.top = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().top.toString() + 'px';
            // console.log(document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().left.toString());

            arrow.appendChild(message);
            svg.appendChild(polygon);
            arrow.appendChild(svg);
            if (frameDiv === undefined) {
                mainDiv.appendChild(arrow);
            }
            else {
                frameDiv.appendChild(arrow);
             }

            if(animator.diagram.content[j].content[i+1] === undefined && j+1 === animator.diagram.content.length){}

                else{

             setTimeout(function () {
            // Do Something Here
            // Then recall the parent function to
            // create a recursive loop.
            i++;

            createArrow(animator, j, i, counter, frameDiv, mainDiv);
            }, 1000);
         }
}

function createLog(animator, i, e, total){
var ul = document.getElementById("logList");
    if(animator.diagram.content[e].content.length === i){
    i = 0;
    e++;
}

            var li = document.createElement("li");
            li.setAttribute('id',((total+1)+": Sending message From: " +
            animator.diagram.content[e].content[i].from.toString() +" To: "+
            animator.diagram.content[e].content[i].to.toString() +" || Message: "+
            animator.diagram.content[e].content[i].message.toString()));
            li.appendChild(document.createTextNode((total+1)+": Sending message From: " +
            animator.diagram.content[e].content[i].from.toString() +" To: "+
            animator.diagram.content[e].content[i].to.toString() +" || Message: "+
            animator.diagram.content[e].content[i].message.toString()));
            ul.appendChild(li);

    if(animator.diagram.content.length > e){

    if(animator.diagram.content[e].content[i+1] === undefined && e+1 === animator.diagram.content.length){}

    else{

    setTimeout(function () {
        // Do Something Here
        // Then recall the parent function to
        // create a recursive loop.
        i++;
        total++;
        createLog(animator, i, e, total);
        }, 1000);
    }
     //setTimeout(createLog(animator), 1000);
   }

}

// var arrows = [];
//
// function Arrow(from, to, message) {
//     this.from = from;
//     this.to = to;
//     this.message = message;
// }
//
// function addArrow(from, to, message) {
//     var msg = new Arrow(from, to, message);
//     arrows.push(msg);
// }

// Helper function to get an element's exact position

function getPosition(el) {
    var xPos = 0;
    var yPos = 0;
    while (el) {
        if (el.tagName == "BODY") {
            // deal with browser quirks with body/window/document and page scroll
            var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
            var yScroll = el.scrollTop || document.documentElement.scrollTop;

            xPos += (el.offsetLeft - xScroll + el.clientLeft);
            yPos += (el.offsetTop - yScroll + el.clientTop);
        } else {
            // for all other non-BODY elements
            xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
            yPos += (el.offsetTop - el.scrollTop + el.clientTop);
        }

        el = el.offsetParent;
    }
    return {
        x: xPos,
        y: yPos
    };
}<commit_msg>Added some comments in animator.js<commit_after>window.onload = function animateJSON() {

    var animator = JSON.parse(localStorage.getItem('stringJSON'));
    var mainDiv = document.getElementById("outputJSON");

//Block of constants used to name classes of HTML elements created, if change needed change the constant's value
    const processDivClassName = "processes";
    const frameDivClassName = "frame";
    const frameTitleClassName = "frameTitle";
    const lifelines = "lifeLine";
    const activatorClassName = "activator";
    const arrowDivClassName = "arrowLtoR";
    const arrowDivClassName2 = "arrowRtoL";
    const messageDivClassName = "messages";

//Selects the processes array in JSON File and iterates for every element
    for(var i = 0; i < animator.processes.length; i++) {

        var div = document.createElement("div");            //Creates an HTML <div> element
        div.className = processDivClassName;                //assigns it a class
        div.innerHTML =
            animator.processes[i].name.toString() + ": " +  //Gives it a text output as specified in the JSON file, here the class and name of the object
            animator.processes[i].class.toString();         //here it is the class and name of the SSD object
        mainDiv.appendChild(div);                           //Places the new <div> element under the mainDiv, as specified in the variable declaration in l.4

    //Similar behavior as in the previous block, but this time the lifeliens are given a unique ID, are appended to the <div> created in the previous block
    //and the activators are appended to the lifeline divs.
        var lifeLineDiv = document.createElement("div");
        lifeLineDiv.className = lifelines;
        lifeLineDiv.id = animator.processes[i].name.toString();
        var activatorDiv = document.createElement("div");
        activatorDiv.className = activatorClassName;
        div.appendChild(lifeLineDiv);
        lifeLineDiv.appendChild(activatorDiv);
    }

    var animatorDiagramArray = Object.keys(animator.diagram); //In order to check whether or not the JSON element is a node, we must select the diagram object's keys.
     //if (animatorDiagramArray.hasOwnProperty('node'))
    for (var i = 0; i < animatorDiagramArray.length; i++) {   //loop through the array of Keys created above
        if (animatorDiagramArray[i] === 'node') {             //we check wether the JSON element is a node here
            var frameDiv = document.createElement("div");
            frameDiv.className = frameDivClassName;
            frameDiv.id = animator.diagram.node.toString();
            var frameTitle = document.createElement("div");
            frameTitle.className = frameTitleClassName;
            frameTitle.id = animator.diagram.node.toString() + "Title";
            frameTitle.innerHTML = animator.diagram.node.toString();
            mainDiv.appendChild(frameDiv);
            frameDiv.appendChild(frameTitle);
        }
    }

    var a = 50;
    var counter = 0;

    for(var j = 0; j < animator.diagram.content.length; j++) {

        if(j !== 0) {
            var lineBreak = document.createElement('hr');
          if (frameDiv !== undefined) {
            //frameDiv.appendChild(lineBreak);
            }
        }

        for (var i = 0; i < animator.diagram.content[j].content.length; i++) {

        }
    }

createArrow(animator, 0, 0, 0, frameDiv, mainDiv);
createLog(animator, 0, 0, 0);

};

function createArrow(animator, j, i, counter, frameDiv,mainDiv){

     if(animator.diagram.content[j].content.length === i){
                i = 0;
                j++;

                var lineBreak = document.createElement('hr');
                if (frameDiv != undefined) {
                 frameDiv.appendChild(lineBreak);
                }
             }

const processDivClassName = "processes";
    const frameDivClassName = "frame";
    const frameTitleClassName = "frameTitle";
    const lifelines = "lifeLine";
    const activatorClassName = "activator";
    const arrowDivClassName = "arrowLtoR";
    const arrowDivClassName2 = "arrowRtoL";
    const messageDivClassName = "messages";

            var startPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].from.toString()));
            var endPosition = getPosition(document.querySelector("#" + animator.diagram.content[j].content[i].to.toString()));

            var arrow = document.createElement("div");
            var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
            var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
            var message = document.createElement("div");
            message.className = messageDivClassName;
            svg.setAttribute("preserveAspectRatio", "xMaxYMid slice");

            svg.setAttribute("viewBox", "0 0 1400 14");
            // decides what direction the arrow will go, and makes the length of the arrows

            if (startPosition.x > endPosition.x) {
                arrow.className = arrowDivClassName2;
                var arrowLengthLeft = startPosition.x - endPosition.x;
                svg.setAttribute("width", arrowLengthLeft + "px");
                arrow.style.transform = "rotate(180deg)";
                arrow.style.left = startPosition.x - 30 + 'px';
                message.style.left = arrowLengthLeft / 2 + 'px';
                message.style.top = 40 + 'px';
                message.style.transform = "rotate(180deg)";
            }
            else {
                arrow.className = arrowDivClassName;
                var arrowLengthRight = endPosition.x - startPosition.x;
                svg.setAttribute("width", arrowLengthRight + "px");
                arrow.style.left = startPosition.x - 30 + 'px';
                message.style.left = arrowLengthRight / 2 + 'px';
            }

            svg.setAttribute("height", "14");
            polygon.setAttribute("points", "1400,7 1385,1 1390,6 0,6 0,8 1390,8 1385,13 1400,7");

            message.innerHTML =
                animator.diagram.content[j].content[i].message.toString();

            // making so every arrow is on their own line with 50px heigth difference
           // arrow.style.top = startPosition.y + counter * a - 20 + 'px';
            counter++;
            arrow.style.right = ((startPosition.x) - (startPosition.x - endPosition.x)) + 'px';

            // arrow.innerHTML =
            //     animator.diagram.content[0].content[i].message.toString();

            // arrow.style.position = "absolute";
            // arrow.style.left = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().left.toString() + 'px';
            // arrow.style.right = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().right.toString() + 'px';
            // arrow.style.top = document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().top.toString() + 'px';
            // console.log(document.getElementById(animator.diagram.content[0].content[i].from.toString()).getBoundingClientRect().left.toString());

            arrow.appendChild(message);
            svg.appendChild(polygon);
            arrow.appendChild(svg);
            if (frameDiv === undefined) {
                mainDiv.appendChild(arrow);
            }
            else {
                frameDiv.appendChild(arrow);
             }

            if(animator.diagram.content[j].content[i+1] === undefined && j+1 === animator.diagram.content.length){}

                else{

             setTimeout(function () {
            // Do Something Here
            // Then recall the parent function to
            // create a recursive loop.
            i++;

            createArrow(animator, j, i, counter, frameDiv, mainDiv);
            }, 1000);
         }
}

function createLog(animator, i, e, total){
var ul = document.getElementById("logList");
    if(animator.diagram.content[e].content.length === i){
    i = 0;
    e++;
}

            var li = document.createElement("li");
            li.setAttribute('id',((total+1)+": Sending message From: " +
            animator.diagram.content[e].content[i].from.toString() +" To: "+
            animator.diagram.content[e].content[i].to.toString() +" || Message: "+
            animator.diagram.content[e].content[i].message.toString()));
            li.appendChild(document.createTextNode((total+1)+": Sending message From: " +
            animator.diagram.content[e].content[i].from.toString() +" To: "+
            animator.diagram.content[e].content[i].to.toString() +" || Message: "+
            animator.diagram.content[e].content[i].message.toString()));
            ul.appendChild(li);

    if(animator.diagram.content.length > e){

    if(animator.diagram.content[e].content[i+1] === undefined && e+1 === animator.diagram.content.length){}

    else{

    setTimeout(function () {
        // Do Something Here
        // Then recall the parent function to
        // create a recursive loop.
        i++;
        total++;
        createLog(animator, i, e, total);
        }, 1000);
    }
     //setTimeout(createLog(animator), 1000);
   }

}

// var arrows = [];
//
// function Arrow(from, to, message) {
//     this.from = from;
//     this.to = to;
//     this.message = message;
// }
//
// function addArrow(from, to, message) {
//     var msg = new Arrow(from, to, message);
//     arrows.push(msg);
// }

// Helper function to get an element's exact position

function getPosition(el) {
    var xPos = 0;
    var yPos = 0;
    while (el) {
        if (el.tagName == "BODY") {
            // deal with browser quirks with body/window/document and page scroll
            var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
            var yScroll = el.scrollTop || document.documentElement.scrollTop;

            xPos += (el.offsetLeft - xScroll + el.clientLeft);
            yPos += (el.offsetTop - yScroll + el.clientTop);
        } else {
            // for all other non-BODY elements
            xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
            yPos += (el.offsetTop - el.scrollTop + el.clientTop);
        }

        el = el.offsetParent;
    }
    return {
        x: xPos,
        y: yPos
    };
}<|endoftext|>


<commit_before>
// Copyright 2009 Google Inc.
//
// 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 bookmarklet = {};
bookmarklet.loadScript = function(id, src, opt_scriptLoadedCheck, opt_onScriptLoad) {
  if(!document.getElementById(id)) {
    var s = document.createElement("script");
    s.id = id;
    s.type = "text/javascript";
    s.src = src;
    bookmarklet.getHead(document).appendChild(s);
    if(opt_scriptLoadedCheck)bookmarklet.waitForScriptLoad(opt_scriptLoadedCheck, opt_onScriptLoad || bookmarklet.nullFunction);
    return true
  }return false
};
bookmarklet.nullFunction = function() {
};
bookmarklet.getHead = function(ownerDocument) {
  var head = ownerDocument.getElementsByTagName("head")[0];
  if(!head)head = ownerDocument.appendChild(ownerDocument.createElement("head"));
  return head
};
bookmarklet.waitForScriptLoad = function(scriptLoadedCheck, onScriptLoad) {
  var setIntervalId = window.setInterval(function() {
    var r = eval(scriptLoadedCheck);
    if(r) {
      window.clearInterval(setIntervalId);
      onScriptLoad()
    }
  }, 50)
};
bookmarklet.loadCSS = function(id, src, ownerDocument) {
  if(!ownerDocument.getElementById(id)) {
    var s = ownerDocument.createElement("link");
    s.id = id;
    s.type = "text/css";
    s.rel = "stylesheet";
    s.href = src;
    bookmarklet.getHead(ownerDocument).appendChild(s)
  }
};
bookmarklet.showStatus = function(statusId, message, opt_timeToShow) {
  if(!document.body)return false;
  var statusLabel = document.getElementById(statusId);
  if(!statusLabel) {
    statusLabel = document.createElement("span");
    statusLabel.id = statusId;
    var isIE = navigator.userAgent.indexOf("MSIE") != -1;
    var position = isIE ? "absolute" : "fixed";
    statusLabel.style.cssText = "z-index:99; font-size: 18px; " + "background: #FFF1A8; position: " + position + "; top: 0";
    document.body.appendChild(statusLabel)
  }statusLabel.innerHTML = message;
  var docClientWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth;
  statusLabel.style.left = (docClientWidth - statusLabel.clientWidth) / 2 + "px";
  if(opt_timeToShow)window.setTimeout(function() {
    bookmarklet.clearStatus(statusId)
  }, opt_timeToShow);
  return true
};
bookmarklet.clearStatus = function(statusId) {
  var statusElement = document.getElementById(statusId);
  if(statusElement) {
    statusElement.parentNode.removeChild(statusElement);
    return true
  }else return false
};
bookmarklet.getProtocol = function() {
  var protocol = window.location.protocol;
  return protocol == "https:" ? "https:" : "http:"
};
bookmarklet.getParameter = function(url, name) {
  if(url) {
    var regex = new RegExp("[?&]" + name + "=([^&#]*)");
    var result = regex.exec(url);
    if(result)return result[1]
  }return null
};
bookmarklet.hasActiveElementSupport = function() {
  return typeof document.activeElement != "undefined"
};
bookmarklet.getActiveTextField = function(opt_doc) {
  var doc = opt_doc || window.document;
  var activeElement = doc.activeElement;
  if(!activeElement)return null;
  var elementName = activeElement.tagName.toUpperCase();
  if(elementName == "TEXTAREA" || elementName == "INPUT" && activeElement.type.toUpperCase() == "TEXT")return activeElement;
  var iframes = doc.getElementsByTagName("iframe");
  for(var i = 0;i < iframes.length;i++)try {
    var iframe = iframes[i];
    var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    if(!iframeDocument)continue;
    var iframeActiveTextField = bookmarklet.getActiveTextField(iframeDocument);
    if(iframeActiveTextField)return iframeActiveTextField
  }catch(e) {
  }return null
};
bookmarklet.contains = function(arr, element) {
  for(var i = 0;i < arr.length;i++)if(arr[i] === element)return true;
  return false
};var t13nBookmarklet = {};
t13nBookmarklet.NAME = "t13nb";
t13nBookmarklet.BASE_URL = "http://t13n.googlecode.com/svn/trunk/blet/";
t13nBookmarklet.SCRIPT_URL = t13nBookmarklet.BASE_URL + "rt13n.js";
t13nBookmarklet.SCRIPT_ID = "t13ns";
t13nBookmarklet.STATUS_ID = "t13n";
t13nBookmarklet.MESSAGE_LOADING = "Loading transliteration";
t13nBookmarklet.MESSAGE_STILL_LOADING = "Still loading transliteration";
t13nBookmarklet.MESSAGE_LOADED = "Transliteration loaded";
t13nBookmarklet.MESSAGE_ENABLED = "Transliteration enabled";
t13nBookmarklet.MESSAGE_DISABLED = "Transliteration disabled";t13nBookmarklet.initialized = false;
t13nBookmarklet.loadURL = null;
t13nBookmarklet.lang = null;
t13nBookmarklet.control = null;
t13nBookmarklet.registeredElements = [];
t13nBookmarklet.CSS_ID = "t13nCSS";
t13nBookmarklet.CSS_URL = "http://www.google.com/uds/modules/elements/transliteration/api.css";
t13nBookmarklet.MESSAGE_NOT_SUPPORTED = "Your browser is not supported. Supported on Chrome/Safari/IE7/FF3";
t13nBookmarklet.MESSAGE_USAGE = "To enable transliteration, press OK and click on a textbox.\r\n" + "Or press Cancel to stop this operation.";
t13nBookmarklet.KEYBOARD_SHORTCUT = "Ctrl+G";
t13nBookmarklet.MESSAGE_TOOLTIP = "(Ctrl+G to toggle transliteration)";
t13nBookmarklet.initBookmarklet = function() {
  bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_LOADING);
  var t13nScript = document.getElementById(t13nBookmarklet.SCRIPT_ID);
  if(t13nScript) {
    t13nBookmarklet.loadURL = t13nScript.src;
    t13nBookmarklet.lang = bookmarklet.getParameter(t13nBookmarklet.loadURL, "l")
  }window[t13nBookmarklet.NAME] = t13nBookmarklet.toggle;
  if(!bookmarklet.hasActiveElementSupport()) {
    bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }bookmarklet.loadScript("t13nJSAPIScript", bookmarklet.getProtocol() + "//www.google.com/jsapi", "window.google && google.load", function() {
    google.load("elements", "1", {packages:"transliteration", callback:function() {
      t13nBookmarklet.initialized = true;
      bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_LOADED, 5000);
      if(t13nBookmarklet.lang)t13nBookmarklet.toggle()
    }})
  })
};
t13nBookmarklet.toggle = function(opt_lang) {
  var tbns = t13nBookmarklet;
  tbns.lang = opt_lang || tbns.lang || "hi";
  if(!bookmarklet.hasActiveElementSupport()) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }if(!tbns.initialized) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_STILL_LOADING);
    return
  }if(!google.elements.transliteration.isBrowserCompatible()) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }var tns = google.elements.transliteration;
  var translitControlClass = tns.TransliterationControl;
  if(!tbns.control) {
    var options = {sourceLanguage:tns.LanguageCode.ENGLISH, destinationLanguage:tbns.lang, shortcutKey:tbns.KEYBOARD_SHORTCUT, transliterationEnabled:false};
    tbns.control = new translitControlClass(options);
    tbns.control.addEventListener(translitControlClass.EventType.STATE_CHANGED, tbns.setElementStyle, tbns.control)
  }tbns.control.setLanguagePair(tns.LanguageCode.ENGLISH, tbns.lang);
  var activeTextField = bookmarklet.getActiveTextField();
  if(!activeTextField) {
    if(tbns.control.isTransliterationEnabled()) {
      tbns.control.toggleTransliteration();
      return
    }if(confirm(tbns.MESSAGE_USAGE))window.setTimeout(function() {
      tbns.toggle()
    }, 3000);
    return
  }if(activeTextField.ownerDocument != document)bookmarklet.loadCSS(t13nBookmarklet.CSS_ID, t13nBookmarklet.CSS_URL, activeTextField.ownerDocument);
  if(!bookmarklet.contains(tbns.registeredElements, activeTextField))try {
    tbns.control.makeTransliteratable([activeTextField]);
    activeTextField.title = (activeTextField.title || "") + " " + tbns.MESSAGE_TOOLTIP;
    tbns.registeredElements.push(activeTextField);
    tbns.control.enableTransliteration();
    t13nBookmarklet.setElementStyle()
  }catch(e) {
  }else tbns.control.toggleTransliteration()
};
t13nBookmarklet.setElementStyle = function() {
  var tbns = t13nBookmarklet;
  for(var i = 0;i < tbns.registeredElements.length;i++) {
    var element = tbns.registeredElements[i];
    if(!element.parentNode)continue;
    element.style.backgroundImage = 'url("' + tbns.BASE_URL + tbns.lang + "_" + (tbns.control.isTransliterationEnabled() ? "e" : "d") + '.gif")';
    element.style.backgroundRepeat = "no-repeat";
    if(tbns.lang == "ar") {
      element.style.backgroundPosition = "100% 0%";
      element.style.paddingRight = "20px"
    }else {
      element.style.backgroundPosition = "0% 0%";
      element.style.paddingLeft = "20px"
    }
  }bookmarklet.showStatus(tbns.STATUS_ID, tbns.control.isTransliterationEnabled() ? tbns.MESSAGE_ENABLED : tbns.MESSAGE_DISABLED, 3000)
};
t13nBookmarklet.initBookmarklet();
})();
<commit_msg>Change image URL.<commit_after>
// Copyright 2009 Google Inc.
//
// 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 bookmarklet = {};
bookmarklet.loadScript = function(id, src, opt_scriptLoadedCheck, opt_onScriptLoad) {
  if(!document.getElementById(id)) {
    var s = document.createElement("script");
    s.id = id;
    s.type = "text/javascript";
    s.src = src;
    bookmarklet.getHead(document).appendChild(s);
    if(opt_scriptLoadedCheck)bookmarklet.waitForScriptLoad(opt_scriptLoadedCheck, opt_onScriptLoad || bookmarklet.nullFunction);
    return true
  }return false
};
bookmarklet.nullFunction = function() {
};
bookmarklet.getHead = function(ownerDocument) {
  var head = ownerDocument.getElementsByTagName("head")[0];
  if(!head)head = ownerDocument.appendChild(ownerDocument.createElement("head"));
  return head
};
bookmarklet.waitForScriptLoad = function(scriptLoadedCheck, onScriptLoad) {
  var setIntervalId = window.setInterval(function() {
    var r = eval(scriptLoadedCheck);
    if(r) {
      window.clearInterval(setIntervalId);
      onScriptLoad()
    }
  }, 50)
};
bookmarklet.loadCSS = function(id, src, ownerDocument) {
  if(!ownerDocument.getElementById(id)) {
    var s = ownerDocument.createElement("link");
    s.id = id;
    s.type = "text/css";
    s.rel = "stylesheet";
    s.href = src;
    bookmarklet.getHead(ownerDocument).appendChild(s)
  }
};
bookmarklet.showStatus = function(statusId, message, opt_timeToShow) {
  if(!document.body)return false;
  var statusLabel = document.getElementById(statusId);
  if(!statusLabel) {
    statusLabel = document.createElement("span");
    statusLabel.id = statusId;
    var isIE = navigator.userAgent.indexOf("MSIE") != -1;
    var position = isIE ? "absolute" : "fixed";
    statusLabel.style.cssText = "z-index:99; font-size: 18px; " + "background: #FFF1A8; position: " + position + "; top: 0";
    document.body.appendChild(statusLabel)
  }statusLabel.innerHTML = message;
  var docClientWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth;
  statusLabel.style.left = (docClientWidth - statusLabel.clientWidth) / 2 + "px";
  if(opt_timeToShow)window.setTimeout(function() {
    bookmarklet.clearStatus(statusId)
  }, opt_timeToShow);
  return true
};
bookmarklet.clearStatus = function(statusId) {
  var statusElement = document.getElementById(statusId);
  if(statusElement) {
    statusElement.parentNode.removeChild(statusElement);
    return true
  }else return false
};
bookmarklet.getProtocol = function() {
  var protocol = window.location.protocol;
  return protocol == "https:" ? "https:" : "http:"
};
bookmarklet.getParameter = function(url, name) {
  if(url) {
    var regex = new RegExp("[?&]" + name + "=([^&#]*)");
    var result = regex.exec(url);
    if(result)return result[1]
  }return null
};
bookmarklet.hasActiveElementSupport = function() {
  return typeof document.activeElement != "undefined"
};
bookmarklet.getActiveTextField = function(opt_doc) {
  var doc = opt_doc || window.document;
  var activeElement = doc.activeElement;
  if(!activeElement)return null;
  var elementName = activeElement.tagName.toUpperCase();
  if(elementName == "TEXTAREA" || elementName == "INPUT" && activeElement.type.toUpperCase() == "TEXT")return activeElement;
  var iframes = doc.getElementsByTagName("iframe");
  for(var i = 0;i < iframes.length;i++)try {
    var iframe = iframes[i];
    var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
    if(!iframeDocument)continue;
    var iframeActiveTextField = bookmarklet.getActiveTextField(iframeDocument);
    if(iframeActiveTextField)return iframeActiveTextField
  }catch(e) {
  }return null
};
bookmarklet.contains = function(arr, element) {
  for(var i = 0;i < arr.length;i++)if(arr[i] === element)return true;
  return false
};var t13nBookmarklet = {};
t13nBookmarklet.NAME = "t13nb";
t13nBookmarklet.SCRIPT_BASE_URL = "http://t13n.googlecode.com/svn/trunk/blet/";
t13nBookmarklet.IMAGE_BASE_URL = "http://t13n.googlecode.com/files/";
t13nBookmarklet.SCRIPT_URL = t13nBookmarklet.SCRIPT_BASE_URL + "rt13n.js";
t13nBookmarklet.SCRIPT_ID = "t13ns";
t13nBookmarklet.STATUS_ID = "t13n";
t13nBookmarklet.MESSAGE_LOADING = "Loading transliteration";
t13nBookmarklet.MESSAGE_STILL_LOADING = "Still loading transliteration";
t13nBookmarklet.MESSAGE_LOADED = "Transliteration loaded";
t13nBookmarklet.MESSAGE_ENABLED = "Transliteration enabled";
t13nBookmarklet.MESSAGE_DISABLED = "Transliteration disabled";t13nBookmarklet.initialized = false;
t13nBookmarklet.loadURL = null;
t13nBookmarklet.lang = null;
t13nBookmarklet.control = null;
t13nBookmarklet.registeredElements = [];
t13nBookmarklet.CSS_ID = "t13nCSS";
t13nBookmarklet.CSS_URL = "http://www.google.com/uds/modules/elements/transliteration/api.css";
t13nBookmarklet.MESSAGE_NOT_SUPPORTED = "Your browser is not supported. Supported on Chrome/Safari/IE7/FF3";
t13nBookmarklet.MESSAGE_USAGE = "To enable transliteration, press OK and click on a textbox.\r\n" + "Or press Cancel to stop this operation.";
t13nBookmarklet.KEYBOARD_SHORTCUT = "Ctrl+G";
t13nBookmarklet.MESSAGE_TOOLTIP = "(Ctrl+G to toggle transliteration)";
t13nBookmarklet.initBookmarklet = function() {
  bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_LOADING);
  var t13nScript = document.getElementById(t13nBookmarklet.SCRIPT_ID);
  if(t13nScript) {
    t13nBookmarklet.loadURL = t13nScript.src;
    t13nBookmarklet.lang = bookmarklet.getParameter(t13nBookmarklet.loadURL, "l")
  }window[t13nBookmarklet.NAME] = t13nBookmarklet.toggle;
  if(!bookmarklet.hasActiveElementSupport()) {
    bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }bookmarklet.loadScript("t13nJSAPIScript", bookmarklet.getProtocol() + "//www.google.com/jsapi", "window.google && google.load", function() {
    google.load("elements", "1", {packages:"transliteration", callback:function() {
      t13nBookmarklet.initialized = true;
      bookmarklet.showStatus(t13nBookmarklet.STATUS_ID, t13nBookmarklet.MESSAGE_LOADED, 5000);
      if(t13nBookmarklet.lang)t13nBookmarklet.toggle()
    }})
  })
};
t13nBookmarklet.toggle = function(opt_lang) {
  var tbns = t13nBookmarklet;
  tbns.lang = opt_lang || tbns.lang || "hi";
  if(!bookmarklet.hasActiveElementSupport()) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }if(!tbns.initialized) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_STILL_LOADING);
    return
  }if(!google.elements.transliteration.isBrowserCompatible()) {
    bookmarklet.showStatus(tbns.STATUS_ID, tbns.MESSAGE_NOT_SUPPORTED, 5000);
    return
  }var tns = google.elements.transliteration;
  var translitControlClass = tns.TransliterationControl;
  if(!tbns.control) {
    var options = {sourceLanguage:tns.LanguageCode.ENGLISH, destinationLanguage:tbns.lang, shortcutKey:tbns.KEYBOARD_SHORTCUT, transliterationEnabled:false};
    tbns.control = new translitControlClass(options);
    tbns.control.addEventListener(translitControlClass.EventType.STATE_CHANGED, tbns.setElementStyle, tbns.control)
  }tbns.control.setLanguagePair(tns.LanguageCode.ENGLISH, tbns.lang);
  var activeTextField = bookmarklet.getActiveTextField();
  if(!activeTextField) {
    if(tbns.control.isTransliterationEnabled()) {
      tbns.control.toggleTransliteration();
      return
    }if(confirm(tbns.MESSAGE_USAGE))window.setTimeout(function() {
      tbns.toggle()
    }, 3000);
    return
  }if(activeTextField.ownerDocument != document)bookmarklet.loadCSS(t13nBookmarklet.CSS_ID, t13nBookmarklet.CSS_URL, activeTextField.ownerDocument);
  if(!bookmarklet.contains(tbns.registeredElements, activeTextField))try {
    tbns.control.makeTransliteratable([activeTextField]);
    activeTextField.title = (activeTextField.title || "") + " " + tbns.MESSAGE_TOOLTIP;
    tbns.registeredElements.push(activeTextField);
    tbns.control.enableTransliteration();
    t13nBookmarklet.setElementStyle()
  }catch(e) {
  }else tbns.control.toggleTransliteration()
};
t13nBookmarklet.setElementStyle = function() {
  var tbns = t13nBookmarklet;
  for(var i = 0;i < tbns.registeredElements.length;i++) {
    var element = tbns.registeredElements[i];
    if(!element.parentNode)continue;
    element.style.backgroundImage = 'url("' + tbns.IMAGE_BASE_URL + tbns.lang + "_" + (tbns.control.isTransliterationEnabled() ? "e" : "d") + '.gif")';
    element.style.backgroundRepeat = "no-repeat";
    if(tbns.lang == "ar") {
      element.style.backgroundPosition = "100% 0%";
      element.style.paddingRight = "20px"
    }else {
      element.style.backgroundPosition = "0% 0%";
      element.style.paddingLeft = "20px"
    }
  }bookmarklet.showStatus(tbns.STATUS_ID, tbns.control.isTransliterationEnabled() ? tbns.MESSAGE_ENABLED : tbns.MESSAGE_DISABLED, 3000)
};
t13nBookmarklet.initBookmarklet();
})();
<|endoftext|>


<commit_before>// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
// IT'S ALL JUST JUNK FOR OUR DOCS!
// ++++++++++++++++++++++++++++++++++++++++++

!function ($) {

  $(function(){

    var $window = $(window)

    // Disable certain links in docs
    $('section [href^=#]').click(function (e) {
      e.preventDefault()
    })

    // side bar
    $('.bs-docs-sidenav').affix({
      offset: {
        top: function () { return $window.width() <= 980 ? 290 : 210 }
      , bottom: 270
      }
    })

    // make code pretty
    window.prettyPrint && prettyPrint()

    // add-ons
    $('.add-on :checkbox').on('click', function () {
      var $this = $(this)
        , method = $this.attr('checked') ? 'addClass' : 'removeClass'
      $(this).parents('.add-on')[method]('active')
    })

    // add tipsies to grid for scaffolding
    if ($('#gridSystem').length) {
      $('#gridSystem').tooltip({
          selector: '.show-grid > div'
        , title: function () { return $(this).width() + 'px' }
      })
    }

    // tooltip demo
    $('.tooltip-demo').tooltip({
      selector: "a[rel=tooltip]"
    })

    $('.tooltip-test').tooltip()
    $('.popover-test').popover()

    // popover demo
    $("a[rel=popover]")
      .popover()
      .click(function(e) {
        e.preventDefault()
      })

    // button state demo
    $('#fat-btn')
      .click(function () {
        var btn = $(this)
        btn.button('loading')
        setTimeout(function () {
          btn.button('reset')
        }, 3000)
      })

    // carousel demo
    $('#myCarousel').carousel()

    // javascript build logic
    var inputsComponent = $("#components.download input")
      , inputsPlugin = $("#plugins.download input")
      , inputsVariables = $("#variables.download input")

    // toggle all plugin checkboxes
    $('#components.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsComponent.attr('checked', !inputsComponent.is(':checked'))
    })

    $('#plugins.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsPlugin.attr('checked', !inputsPlugin.is(':checked'))
    })

    $('#variables.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsVariables.val('')
    })

    // request built javascript
    $('.download-btn').on('click', function () {

      var css = $("#components.download input:checked")
            .map(function () { return this.value })
            .toArray()
        , js = $("#plugins.download input:checked")
            .map(function () { return this.value })
            .toArray()
        , vars = {}
        , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png']

    $("#variables.download input")
      .each(function () {
        $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())
      })

      $.ajax({
        type: 'POST'
      , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com'
      , dataType: 'jsonpi'
      , params: {
          js: js
        , css: css
        , vars: vars
        , img: img
      }
      })
    })
  })

// Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi
$.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) {
  var url = opts.url;

  return {
    send: function(_, completeCallback) {
      var name = 'jQuery_iframe_' + jQuery.now()
        , iframe, form

      iframe = $('<iframe>')
        .attr('name', name)
        .appendTo('head')

      form = $('<form>')
        .attr('method', opts.type) // GET or POST
        .attr('action', url)
        .attr('target', name)

      $.each(opts.params, function(k, v) {

        $('<input>')
          .attr('type', 'hidden')
          .attr('name', k)
          .attr('value', typeof v == 'string' ? v : JSON.stringify(v))
          .appendTo(form)
      })

      form.appendTo('body').submit()
    }
  }
})

}(window.jQuery)<commit_msg>fixes #5922: clicking only button should download custom build<commit_after>// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
// IT'S ALL JUST JUNK FOR OUR DOCS!
// ++++++++++++++++++++++++++++++++++++++++++

!function ($) {

  $(function(){

    var $window = $(window)

    // Disable certain links in docs
    $('section [href^=#]').click(function (e) {
      e.preventDefault()
    })

    // side bar
    $('.bs-docs-sidenav').affix({
      offset: {
        top: function () { return $window.width() <= 980 ? 290 : 210 }
      , bottom: 270
      }
    })

    // make code pretty
    window.prettyPrint && prettyPrint()

    // add-ons
    $('.add-on :checkbox').on('click', function () {
      var $this = $(this)
        , method = $this.attr('checked') ? 'addClass' : 'removeClass'
      $(this).parents('.add-on')[method]('active')
    })

    // add tipsies to grid for scaffolding
    if ($('#gridSystem').length) {
      $('#gridSystem').tooltip({
          selector: '.show-grid > div'
        , title: function () { return $(this).width() + 'px' }
      })
    }

    // tooltip demo
    $('.tooltip-demo').tooltip({
      selector: "a[rel=tooltip]"
    })

    $('.tooltip-test').tooltip()
    $('.popover-test').popover()

    // popover demo
    $("a[rel=popover]")
      .popover()
      .click(function(e) {
        e.preventDefault()
      })

    // button state demo
    $('#fat-btn')
      .click(function () {
        var btn = $(this)
        btn.button('loading')
        setTimeout(function () {
          btn.button('reset')
        }, 3000)
      })

    // carousel demo
    $('#myCarousel').carousel()

    // javascript build logic
    var inputsComponent = $("#components.download input")
      , inputsPlugin = $("#plugins.download input")
      , inputsVariables = $("#variables.download input")

    // toggle all plugin checkboxes
    $('#components.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsComponent.attr('checked', !inputsComponent.is(':checked'))
    })

    $('#plugins.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsPlugin.attr('checked', !inputsPlugin.is(':checked'))
    })

    $('#variables.download .toggle-all').on('click', function (e) {
      e.preventDefault()
      inputsVariables.val('')
    })

    // request built javascript
    $('.download-btn .btn').on('click', function () {

      var css = $("#components.download input:checked")
            .map(function () { return this.value })
            .toArray()
        , js = $("#plugins.download input:checked")
            .map(function () { return this.value })
            .toArray()
        , vars = {}
        , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png']

    $("#variables.download input")
      .each(function () {
        $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())
      })

      $.ajax({
        type: 'POST'
      , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com'
      , dataType: 'jsonpi'
      , params: {
          js: js
        , css: css
        , vars: vars
        , img: img
      }
      })
    })
  })

// Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi
$.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) {
  var url = opts.url;

  return {
    send: function(_, completeCallback) {
      var name = 'jQuery_iframe_' + jQuery.now()
        , iframe, form

      iframe = $('<iframe>')
        .attr('name', name)
        .appendTo('head')

      form = $('<form>')
        .attr('method', opts.type) // GET or POST
        .attr('action', url)
        .attr('target', name)

      $.each(opts.params, function(k, v) {

        $('<input>')
          .attr('type', 'hidden')
          .attr('name', k)
          .attr('value', typeof v == 'string' ? v : JSON.stringify(v))
          .appendTo(form)
      })

      form.appendTo('body').submit()
    }
  }
})

}(window.jQuery)<|endoftext|>


<commit_before>(function($){
  $(function(){

  	// metrics
  	var users = 0,
  			locations = 0,
  			reports = 0;

		// materialize components
  	$('.parallax').parallax();

  	// logo
		$('.logo').click(function() {
			$('html, body').animate({
				scrollTop: $('.navbar-fixed').offset().top
			}, 1000);
		});

		// if screen size is >= 600px, animate immediately
		if ( $( window ).height() >= 600 ) {
			setTimeout( function(){
				$( '.dashboard' ).css( 'display', 'block' );
			}, 400 );
		}

  	// animate dashboard image on scroll
		var dashboard = new Waypoint({
		  element: document.getElementById( 'promo-title' ),
		  handler: function() {
		    $( '.dashboard' ).css( 'display', 'block' );
		  }
		});

  	// jQuery requests for metric data
		$.get( 'http://192.168.33.16/api/metrics/getUsers', function( data ) {
		  users = data.value;
		  $( '.users' ).html( users );
		});
  	// jQuery requests for metric data
		$.get( 'http://192.168.33.16/api/metrics/getLocations', function( data ) {
		  locations = data.value;
		  $( '.locations' ).html( locations );
		});
  	// jQuery requests for metric data
		$.get( 'http://192.168.33.16/api/metrics/getReports', function( data ) {
		  reports = data.value;
		  $( '.reports' ).html( reports );
		});

  	// animate metrics on scroll
  	var animate = true;
		var dashboard = new Waypoint({
		  element: document.getElementById('feature-row-1'),
		  handler: function() {
		  	if ( animate ) {
			    $('#users').animateNumber({
			    	number: users,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    $('#locations').animateNumber({
			    	number: locations,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    $('#reports').animateNumber({
			    	number: reports,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    animate = false;
			  }
		  }
		});

  }); // end of document ready
})( jQuery ); // end of jQuery name space<commit_msg>Promo - updated init.js to point to correct api href<commit_after>(function($){
  $(function(){

  	// metrics
  	var users = 0,
  			locations = 0,
  			reports = 0,
  			href = window.location.href;

		// materialize components
  	$('.parallax').parallax();

  	// logo
		$('.logo').click(function() {
			$('html, body').animate({
				scrollTop: $('.navbar-fixed').offset().top
			}, 1000);
		});

		// if screen size is >= 600px, animate immediately
		if ( $( window ).height() >= 600 ) {
			setTimeout( function(){
				$( '.dashboard' ).css( 'display', 'block' );
			}, 400 );
		}

  	// animate dashboard image on scroll
		var dashboard = new Waypoint({
		  element: document.getElementById( 'promo-title' ),
		  handler: function() {
		    $( '.dashboard' ).css( 'display', 'block' );
		  }
		});

  	// jQuery requests for metric data
		$.get( href + '/api/metrics/getUsers', function( data ) {
		  users = data.value;
		  $( '.users' ).html( users );
		});
  	// jQuery requests for metric data
		$.get( href + '/api/metrics/getLocations', function( data ) {
		  locations = data.value;
		  $( '.locations' ).html( locations );
		});
  	// jQuery requests for metric data
		$.get( href + '/api/metrics/getReports', function( data ) {
		  reports = data.value;
		  $( '.reports' ).html( reports );
		});

  	// animate metrics on scroll
  	var animate = true;
		var dashboard = new Waypoint({
		  element: document.getElementById('feature-row-1'),
		  handler: function() {
		  	if ( animate ) {
			    $('#users').animateNumber({
			    	number: users,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    $('#locations').animateNumber({
			    	number: locations,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    $('#reports').animateNumber({
			    	number: reports,
			    	numberStep: $.animateNumber.numberStepFactories.separator(',')
			    }, 4000 );
			    animate = false;
			  }
		  }
		});

  }); // end of document ready
})( jQuery ); // end of jQuery name space<|endoftext|>


<commit_before>function get_attribute_value(obj, attrib, def) {
    if (obj[attrib]) {
        return obj[attrib];
    }
    return def;
}

var mapContex = {
    get_line_strokeColor: function (feature) { return get_attribute_value(feature.attributes, "color", "#888"); }
            	, get_fontSize: function (feature) { return 8 + road_size * (2940 / map.getScale()); }
            	, get_display: function (feature) { return get_attribute_value(feature.attributes, "mapLevel", 0) == 1 ? "display" : "none"; }
};
function getPolygonShadingStyle(key, dataTable, indicator, colorOptions) {
    colorOptions = extendColorOption(colorOptions);

    return {
        "default":
        {
            "Polygon":
            {
                fillOpacity: 1
                , strokeOpacity: 1
               // , label: function (feature) { return get_attribute_value(feature.attributes, "name", ""); }
                , label: function (feature) {
                    var keyVal = get_attribute_value(feature.attributes, key, "");
                    var row = dataTable["row" + keyVal];
                    if (row) {
                        var att = dataTable["row" + keyVal][indicator + "normalized"];
                        att = Math.round(att * (colorOptions.sample-1));
                        return get_attribute_value(feature.attributes, "name", "") + " " + att;
                    }
                    return get_attribute_value(feature.attributes, "name", "") + " - ";
                }
                , fillColor: function (feature) {
                    var keyVal = get_attribute_value(feature.attributes, key, "");
                    var name=get_attribute_value(feature.attributes, "name", "");
                    var row = dataTable["row" + keyVal];
                    if (row) {
                        var att = dataTable["row" + keyVal][indicator + "normalized"];
                       // att = Math.round(att * 5) + "";
                       // att = att / 5;
                        return getRGBValue(colorOptions.h, colorOptions.s, colorOptions.b1, colorOptions.b2, colorOptions.sample-1, att, name);
                        return getRGBShade(colorOptions.minColor, colorOptions.maxColor, att);
                    }
                    return colorOptions.noValColor;
                }
               , strokeColor: "${get_defaultPolygonfillColor}"

            }
        }
    }
}
function extendColorOption(colorOptions) {
    var _colorOptions = { h: 70, s: 38, b1: 230, b2: 100, sample: 5, noValColor: "rgb(240,240,240)" };
    if (!colorOptions) {
        colorOptions = {};
    }
    for (var i in _colorOptions) {
        if (typeof (colorOptions[i]) == "undefined") {
            colorOptions[i] = _colorOptions[i];
        }
    }
    return colorOptions;
}
function getRGBValue(h, s, b1, b2, segments, v, name) {

    v = Math.round(v * (segments)) + "";
    v = v / segments;
    var bDiff = (b2 - b1);
    var b = b1 + bDiff * v;
    var color = hslToRgb(h / 240, s / 240, b / 240);
    console.log("getRGBValue",name,v,b);
    return "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
}
function hslToRgb(h, s, l) {
    var r, g, b;

    if (s == 0) {
        r = g = b = l; // achromatic
    } else {
        function hue2rgb(p, q, t) {
            if (t < 0) t += 1;
            if (t > 1) t -= 1;
            if (t < 1 / 6) return p + (q - p) * 6 * t;
            if (t < 1 / 2) return q;
            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
            return p;
        }

        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        var p = 2 * l - q;
        r = hue2rgb(p, q, h + 1 / 3);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1 / 3);
    }

    return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
}
function HSVtoRGB(h, s, v) {
    var r, g, b, i, f, p, q, t;
    if (h && s === undefined && v === undefined) {
        s = h.s, v = h.v, h = h.h;
    }
    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }
    return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
    };
}
function createStyle(rules) {
    var context = {};
    for (var r in rules) {
        var symbolizer = rules[r];
        for (var g in symbolizer) {
            var geometry = symbolizer[g];
            for (var s in geometry) {
                var styleAtt = geometry[s];
                if (typeof (styleAtt) == "function") {

                    //console.log("createStyle", { rule: r, geometry: g, style: s, val: styleAtt });
                    var functionName = "get_" + r + g + s;
                    context[functionName] = styleAtt;
                    geometry[s] = "${" + functionName + "}";
                }
            }
        }
    }
    //console.log("createStyle-context", { context: context, rule: rules });

    var StyleMaps = {};
    for (var m in rules) {
        var symbolizer = rules[m];
        var style = new OpenLayers.Style(null, {
            context: context,
            rules: [new OpenLayers.Rule({ symbolizer: symbolizer })]
        });
        StyleMaps[m] = style;
    }
    var styles = new OpenLayers.StyleMap(StyleMaps);
    return styles;
}
function rgb(r, g, b) {
    return { r: r, g: g, b: b };
}
function middleValue(s, e, r) {
    var diff = e - s;
    return Math.round(s + diff * r);
}
function getRGBShade(colorFrom, colorTo, nv) {
    var cFrom = {};
    var cTo = {};
    eval("cFrom=" + colorFrom);
    eval("cTo=" + colorTo);
    var r = middleValue(cFrom.r, cTo.r, nv);
    var g = middleValue(cFrom.g, cTo.g, nv);
    var b = middleValue(cFrom.b, cTo.b, nv);
    var rgbstr = "rgb(" + r + "," + g + "," + b + ")";
    return rgbstr;
}
function colorValue(base, factor) {
    return Math.min(Math.round(base * factor), 255);
}
function rgbColor(base, factor) {
    var r = colorValue(base[0], factor);
    var g = colorValue(base[1], factor);
    var b = colorValue(base[2], factor);
    return "rgb(" + r + "," + g + "," + b + ")";
}

var stylePresets = {
    outline: createStyle({ "default": { "Polygon": { fill: 0, strokeWidth: 0, strokeColor: "#999" } } })
    ,solid: createStyle({ "default": { "Polygon": { fill: 0, strokeWidth: 0, strokeColor: "#999" } } })
}
function colorChanged(nam, val) {
    colorRange[nam] = val;
    drawShades();
}
function rgb(r, g, b) {
    return { r: r, g: g, b: b };
}
function middleValue(s, e, r) {
    var diff = e - s;
    return Math.round(s + diff * r);
}
function getRGBShade(colorFrom, colorTo, nv) {
    var cFrom = {};
    var cTo = {};
    eval("cFrom=" + colorFrom);
    eval("cTo=" + colorTo);
    var r = middleValue(cFrom.r, cTo.r, nv);
    var g = middleValue(cFrom.g, cTo.g, nv);
    var b = middleValue(cFrom.b, cTo.b, nv);
    var rgbstr = "rgb(" + r + "," + g + "," + b + ")";
    return rgbstr;
}
function drawShades() {
    for (var i in colorRange) {
        document.getElementById(i).style.backgroundColor = colorRange[i];
    }

    var htm = "";
    for (var i = 0; i < 10; i++) {
        var rgbstr = getRGBShade(colorRange.colorFrom, colorRange.colorTo, i / 10)
        htm += "
 " + rgbstr + "
";

    }
    document.getElementById("shadeDisp").innerHTML = htm;
}<commit_msg>Sample size changed.<commit_after>function get_attribute_value(obj, attrib, def) {
    if (obj[attrib]) {
        return obj[attrib];
    }
    return def;
}

var mapContex = {
    get_line_strokeColor: function (feature) { return get_attribute_value(feature.attributes, "color", "#888"); }
            	, get_fontSize: function (feature) { return 8 + road_size * (2940 / map.getScale()); }
            	, get_display: function (feature) { return get_attribute_value(feature.attributes, "mapLevel", 0) == 1 ? "display" : "none"; }
};
function getPolygonShadingStyle(key, dataTable, indicator, colorOptions) {
    colorOptions = extendColorOption(colorOptions);

    return {
        "default":
        {
            "Polygon":
            {
                fillOpacity: 0.8
                , strokeOpacity: 1
               // , label: function (feature) { return get_attribute_value(feature.attributes, "name", ""); }
                , label: function (feature) {
                    return "";
                    var keyVal = get_attribute_value(feature.attributes, key, "");
                    var row = dataTable["row" + keyVal];
                    if (row) {
                        var att = dataTable["row" + keyVal][indicator];
                      //  att = Math.round(att * (colorOptions.sample-1));
                        return get_attribute_value(feature.attributes, "name", "") + " " + att;
                    }
                    return get_attribute_value(feature.attributes, "name", "") + " - ";
                }
                , fillColor: function (feature) {
                    var keyVal = get_attribute_value(feature.attributes, key, "");
                    var name=get_attribute_value(feature.attributes, "name", "");
                    var row = dataTable["row" + keyVal];
                    if (row) {
                        var att = dataTable["row" + keyVal][indicator + "normalized"];
                       // att = Math.round(att * 5) + "";
                       // att = att / 5;
                        return getRGBValue(colorOptions.h, colorOptions.s, colorOptions.b1, colorOptions.b2, colorOptions.sample-1, att, name);
                        return getRGBShade(colorOptions.minColor, colorOptions.maxColor, att);
                    }
                    return colorOptions.noValColor;
                }
               , strokeColor: "${get_defaultPolygonfillColor}"

            }
        }
    }
}
function extendColorOption(colorOptions) {
    var _colorOptions = { h: 220, s: 200, b1: 200, b2: 100, sample: 5, noValColor: "rgb(64,64,64)" };
    if (!colorOptions) {
        colorOptions = {};
    }
    for (var i in _colorOptions) {
        if (typeof (colorOptions[i]) == "undefined") {
            colorOptions[i] = _colorOptions[i];
        }
    }
    return colorOptions;
}
function getRGBValue(h, s, b1, b2, segments, v, name) {

    v = Math.round(v * (segments)) + "";
    v = v / segments;
    var bDiff = (b2 - b1);
    var b = b1 + bDiff * v;
    var color = hslToRgb(h / 240, s / 240, b / 240);
    console.log("getRGBValue",name,v,b);
    return "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
}
function hslToRgb(h, s, l) {
    var r, g, b;

    if (s == 0) {
        r = g = b = l; // achromatic
    } else {
        function hue2rgb(p, q, t) {
            if (t < 0) t += 1;
            if (t > 1) t -= 1;
            if (t < 1 / 6) return p + (q - p) * 6 * t;
            if (t < 1 / 2) return q;
            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
            return p;
        }

        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        var p = 2 * l - q;
        r = hue2rgb(p, q, h + 1 / 3);
        g = hue2rgb(p, q, h);
        b = hue2rgb(p, q, h - 1 / 3);
    }

    return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
}
function HSVtoRGB(h, s, v) {
    var r, g, b, i, f, p, q, t;
    if (h && s === undefined && v === undefined) {
        s = h.s, v = h.v, h = h.h;
    }
    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }
    return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
    };
}
function createStyle(rules) {
    var context = {};
    for (var r in rules) {
        var symbolizer = rules[r];
        for (var g in symbolizer) {
            var geometry = symbolizer[g];
            for (var s in geometry) {
                var styleAtt = geometry[s];
                if (typeof (styleAtt) == "function") {

                    //console.log("createStyle", { rule: r, geometry: g, style: s, val: styleAtt });
                    var functionName = "get_" + r + g + s;
                    context[functionName] = styleAtt;
                    geometry[s] = "${" + functionName + "}";
                }
            }
        }
    }
    //console.log("createStyle-context", { context: context, rule: rules });

    var StyleMaps = {};
    for (var m in rules) {
        var symbolizer = rules[m];
        var style = new OpenLayers.Style(null, {
            context: context,
            rules: [new OpenLayers.Rule({ symbolizer: symbolizer })]
        });
        StyleMaps[m] = style;
    }
    var styles = new OpenLayers.StyleMap(StyleMaps);
    return styles;
}
function rgb(r, g, b) {
    return { r: r, g: g, b: b };
}
function middleValue(s, e, r) {
    var diff = e - s;
    return Math.round(s + diff * r);
}
function getRGBShade(colorFrom, colorTo, nv) {
    var cFrom = {};
    var cTo = {};
    eval("cFrom=" + colorFrom);
    eval("cTo=" + colorTo);
    var r = middleValue(cFrom.r, cTo.r, nv);
    var g = middleValue(cFrom.g, cTo.g, nv);
    var b = middleValue(cFrom.b, cTo.b, nv);
    var rgbstr = "rgb(" + r + "," + g + "," + b + ")";
    return rgbstr;
}
function colorValue(base, factor) {
    return Math.min(Math.round(base * factor), 255);
}
function rgbColor(base, factor) {
    var r = colorValue(base[0], factor);
    var g = colorValue(base[1], factor);
    var b = colorValue(base[2], factor);
    return "rgb(" + r + "," + g + "," + b + ")";
}

var stylePresets = {
    outline: createStyle({ "default": { "Polygon": { fill: 0, strokeWidth: 0, strokeColor: "#999" } } })
    ,solid: createStyle({ "default": { "Polygon": { fill: 0, strokeWidth: 0, strokeColor: "#999" } } })
}
function colorChanged(nam, val) {
    colorRange[nam] = val;
    drawShades();
}
function rgb(r, g, b) {
    return { r: r, g: g, b: b };
}
function middleValue(s, e, r) {
    var diff = e - s;
    return Math.round(s + diff * r);
}
function getRGBShade(colorFrom, colorTo, nv) {
    var cFrom = {};
    var cTo = {};
    eval("cFrom=" + colorFrom);
    eval("cTo=" + colorTo);
    var r = middleValue(cFrom.r, cTo.r, nv);
    var g = middleValue(cFrom.g, cTo.g, nv);
    var b = middleValue(cFrom.b, cTo.b, nv);
    var rgbstr = "rgb(" + r + "," + g + "," + b + ")";
    return rgbstr;
}
function drawShades() {
    for (var i in colorRange) {
        document.getElementById(i).style.backgroundColor = colorRange[i];
    }

    var htm = "";
    for (var i = 0; i < 10; i++) {
        var rgbstr = getRGBShade(colorRange.colorFrom, colorRange.colorTo, i / 10)
        htm += "
 " + rgbstr + "
";

    }
    document.getElementById("shadeDisp").innerHTML = htm;
}<|endoftext|>


<commit_before>
/*
 Copyright 2013 Simon Paulger <spaulger@codezen.co.uk>

 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() {
    'use strict';

    /**
     * jQuery inArray alternative
     *
     * @param key Array key to be found
     * @param list Array to search
     * @returns {number} Position within array or -1 if not found
     */
    function inArray(key, list) {
        for (var i = 0; i < list.length; i++) {
            if (i in list && list[i] === key) {
                return i;
            }
        }

        return -1;
    }

    /**
     * chrome.storage Backbone storage adapter
     *
     * @param keyNamespace storage namespace prefix
     * @param storageArea Storage area to use
     * @constructor
     */
    Backbone.ChromeStorageAdapter = function(keyNamespace, storageArea)
    {
        if (typeof keyNamespace == 'string' && keyNamespace != '') {
            this._keyNamespace = keyNamespace;
        } else {
            throw new TypeError('Invalid key namespace.');
        }

        // Apply storage area
        if (storageArea == 'local' || storageArea == null) {
            this._chromeStorage = chrome.storage.local;
        } else if (storageArea == 'sync') {
            this._chromeStorage = chrome.storage.sync;
        } else {
            throw new TypeError('Invalid storage area declaration.');
        }
    };

    /**
     * Enum for StorageArea type. Should be when declaring
     * the storage area when constructing the storage adapter
     */
    Backbone.ChromeStorageAdapter.StorageArea =
    {
        SYNC: 'sync',
        LOCAL: 'local'
    };

    Backbone.ChromeStorageAdapter.prototype =
    {
        _keyNamespace: null,
        _chromeStorage: null,
        _recordIndex: [],

        /**
         * Get the chrome.storage.* namespace pointer
         *
         * @returns {Object} chrome.storage.* namespace object
         * @private
         */
        _getChromeStorage: function()
        {
            return this._chromeStorage;
        },

        /**
         * Generate a unique UUID for use as a key
         *
         * @returns {string} Unique UUID
         * @private
         */
        _generateUuid: function()
        {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        },

        /**
         * Add or update an existing model in storage
         *
         * @param model Model of data to update
         * @param options Storage options
         * @private
         */
        _updateRecord: function(model, options)
        {
            function apiCallback() {
                // Notify callbacks if defined
                if (chrome.runtime.lastError == null) {
                    var attributes = model.attributes;
                    options.success(attributes);
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            // Get or generate an Id
            var id = model.id || this._generateUuid();
            model.id = id;

            // Update record index with new id if not found
            if (inArray(id, this._recordIndex) == -1) {
                this._recordIndex.push(id);
            }

            // Update index if adding, and add/update record
            var data = {};
            data[this._keyNamespace] = this._recordIndex;
            data[id] = model.attributes;

            // Trigger request event
            model.trigger('request', model, data, options);

            // Set data
            this._getChromeStorage().set(data, apiCallback);
        },

        /**
         * Remove a model from storage
         *
         * @param model Model of data to remove
         * @param options Storage options
         * @private
         */
        _deleteRecord: function(model, options)
        {
            var callbackCount = 0;
            var success = true;
            var errors = [];

            function apiCallback() {
                callbackCount++;

                // Check if an error occurred
                if (chrome.runtime.lastError != null) {
                    success = false;
                    errors.push(chrome.runtime.lastError);
                }

                // Notify callbacks if defined
                if (callbackCount == 2 && success) {
                    // Success
                    options.success({});
                } else if (callbackCount == 2 && !success) {
                    // Error
                    options.error(errors);
                }
            }

            // If the model has an id, attempt to remove it from storage
            if (!model.isNew()) {
                // Find record index position and remove
                var recordPosition = inArray(model.id, this._recordIndex);
                if (recordPosition >= 0) {
                    this._recordIndex.splice(recordPosition, 1);
                }

                // Trigger request event
                model.trigger('request', model, model.id, options);

                // Update record index with item removed in storage
                var data = {};
                data[this._keyNamespace] = this._recordIndex;
                this._getChromeStorage().set(data, apiCallback);

                // Remove item from storage
                this._getChromeStorage().remove([model.id], apiCallback);
            } else {
                // Nothing to remove, notify error callback if defined
                options.error('Model id is not defined');
            }
        },

        /**
         * Read a model or collection from storage
         *
         * @param modelOrCollection Model with id to read
         * @param options Storage options
         * @private
         */
        _readRecord: function(modelOrCollection, options)
        {
            var that = this;

            function recordReadCallback(items) {
                if (chrome.runtime.lastError == null) {
                    // Format items into object to pass to success
                    // and reply to success callback with resp
                    var resp = [];

                    for (var key in items) {
                        resp.push(items[key]);
                    }

                    options.success(resp);
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            function recordIndexReadCallback(items) {
                if (chrome.runtime.lastError == null) {
                    // Attempt to read all records for all id's in the record index
                    var recordIndex = items[that._keyNamespace] || null;

                    // Trigger request event
                    modelOrCollection.trigger('request', modelOrCollection, [recordIndex], options);

                    // Get data
                    if (recordIndex == null) {
                        // No records to retrieve, fire read callback with zero results
                        recordReadCallback({});
                    } else {
                        that._getChromeStorage().get(recordIndex, recordReadCallback);
                    }
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            if (modelOrCollection instanceof Backbone.Collection) {
                // Update record index with item removed in storage
                this._getChromeStorage().get([this._keyNamespace], recordIndexReadCallback);
            } else {
                // Trigger request event
                modelOrCollection.trigger('request', modelOrCollection, [this._keyNamespace], options);

                // Get data
                this._getChromeStorage().get([modelOrCollection.id], recordReadCallback);
            }
        },

        /**
         * Implement Backbone.sync function signature.
         *
         * @param method Sync method
         * @param modelOrCollection Backbone model or collection
         * @param options Options
         */
        sync: function(method, modelOrCollection, options)
        {
            switch (method) {
                case 'update':  return this._updateRecord(modelOrCollection, options);
                case 'create':  return this._updateRecord(modelOrCollection, options);
                case 'read':    return this._readRecord(modelOrCollection, options);
                case 'delete':  return this._deleteRecord(modelOrCollection, options);
            }

            throw new TypeError('Unknown method ' + method + ' in sync');
        }
    };
})();
<commit_msg>jsdoc optional parameter<commit_after>
/*
 Copyright 2013 Simon Paulger <spaulger@codezen.co.uk>

 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() {
    'use strict';

    /**
     * jQuery inArray alternative
     *
     * @param key Array key to be found
     * @param list Array to search
     * @returns {number} Position within array or -1 if not found
     */
    function inArray(key, list) {
        for (var i = 0; i < list.length; i++) {
            if (i in list && list[i] === key) {
                return i;
            }
        }

        return -1;
    }

    /**
     * chrome.storage Backbone storage adapter
     *
     * @param keyNamespace storage namespace prefix
     * @param {string=} storageArea Storage area to use
     * @constructor
     */
    Backbone.ChromeStorageAdapter = function(keyNamespace, storageArea)
    {
        if (typeof keyNamespace == 'string' && keyNamespace != '') {
            this._keyNamespace = keyNamespace;
        } else {
            throw new TypeError('Invalid key namespace.');
        }

        // Apply storage area
        if (storageArea == 'local' || storageArea == null) {
            this._chromeStorage = chrome.storage.local;
        } else if (storageArea == 'sync') {
            this._chromeStorage = chrome.storage.sync;
        } else {
            throw new TypeError('Invalid storage area declaration.');
        }
    };

    /**
     * Enum for StorageArea type. Should be when declaring
     * the storage area when constructing the storage adapter
     */
    Backbone.ChromeStorageAdapter.StorageArea =
    {
        SYNC: 'sync',
        LOCAL: 'local'
    };

    Backbone.ChromeStorageAdapter.prototype =
    {
        _keyNamespace: null,
        _chromeStorage: null,
        _recordIndex: [],

        /**
         * Get the chrome.storage.* namespace pointer
         *
         * @returns {Object} chrome.storage.* namespace object
         * @private
         */
        _getChromeStorage: function()
        {
            return this._chromeStorage;
        },

        /**
         * Generate a unique UUID for use as a key
         *
         * @returns {string} Unique UUID
         * @private
         */
        _generateUuid: function()
        {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        },

        /**
         * Add or update an existing model in storage
         *
         * @param model Model of data to update
         * @param options Storage options
         * @private
         */
        _updateRecord: function(model, options)
        {
            function apiCallback() {
                // Notify callbacks if defined
                if (chrome.runtime.lastError == null) {
                    var attributes = model.attributes;
                    options.success(attributes);
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            // Get or generate an Id
            var id = model.id || this._generateUuid();
            model.id = id;

            // Update record index with new id if not found
            if (inArray(id, this._recordIndex) == -1) {
                this._recordIndex.push(id);
            }

            // Update index if adding, and add/update record
            var data = {};
            data[this._keyNamespace] = this._recordIndex;
            data[id] = model.attributes;

            // Trigger request event
            model.trigger('request', model, data, options);

            // Set data
            this._getChromeStorage().set(data, apiCallback);
        },

        /**
         * Remove a model from storage
         *
         * @param model Model of data to remove
         * @param options Storage options
         * @private
         */
        _deleteRecord: function(model, options)
        {
            var callbackCount = 0;
            var success = true;
            var errors = [];

            function apiCallback() {
                callbackCount++;

                // Check if an error occurred
                if (chrome.runtime.lastError != null) {
                    success = false;
                    errors.push(chrome.runtime.lastError);
                }

                // Notify callbacks if defined
                if (callbackCount == 2 && success) {
                    // Success
                    options.success({});
                } else if (callbackCount == 2 && !success) {
                    // Error
                    options.error(errors);
                }
            }

            // If the model has an id, attempt to remove it from storage
            if (!model.isNew()) {
                // Find record index position and remove
                var recordPosition = inArray(model.id, this._recordIndex);
                if (recordPosition >= 0) {
                    this._recordIndex.splice(recordPosition, 1);
                }

                // Trigger request event
                model.trigger('request', model, model.id, options);

                // Update record index with item removed in storage
                var data = {};
                data[this._keyNamespace] = this._recordIndex;
                this._getChromeStorage().set(data, apiCallback);

                // Remove item from storage
                this._getChromeStorage().remove([model.id], apiCallback);
            } else {
                // Nothing to remove, notify error callback if defined
                options.error('Model id is not defined');
            }
        },

        /**
         * Read a model or collection from storage
         *
         * @param modelOrCollection Model with id to read
         * @param options Storage options
         * @private
         */
        _readRecord: function(modelOrCollection, options)
        {
            var that = this;

            function recordReadCallback(items) {
                if (chrome.runtime.lastError == null) {
                    // Format items into object to pass to success
                    // and reply to success callback with resp
                    var resp = [];

                    for (var key in items) {
                        resp.push(items[key]);
                    }

                    options.success(resp);
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            function recordIndexReadCallback(items) {
                if (chrome.runtime.lastError == null) {
                    // Attempt to read all records for all id's in the record index
                    var recordIndex = items[that._keyNamespace] || null;

                    // Trigger request event
                    modelOrCollection.trigger('request', modelOrCollection, [recordIndex], options);

                    // Get data
                    if (recordIndex == null) {
                        // No records to retrieve, fire read callback with zero results
                        recordReadCallback({});
                    } else {
                        that._getChromeStorage().get(recordIndex, recordReadCallback);
                    }
                } else {
                    options.error(chrome.runtime.lastError);
                }
            }

            if (modelOrCollection instanceof Backbone.Collection) {
                // Update record index with item removed in storage
                this._getChromeStorage().get([this._keyNamespace], recordIndexReadCallback);
            } else {
                // Trigger request event
                modelOrCollection.trigger('request', modelOrCollection, [this._keyNamespace], options);

                // Get data
                this._getChromeStorage().get([modelOrCollection.id], recordReadCallback);
            }
        },

        /**
         * Implement Backbone.sync function signature.
         *
         * @param method Sync method
         * @param modelOrCollection Backbone model or collection
         * @param options Options
         */
        sync: function(method, modelOrCollection, options)
        {
            switch (method) {
                case 'update':  return this._updateRecord(modelOrCollection, options);
                case 'create':  return this._updateRecord(modelOrCollection, options);
                case 'read':    return this._readRecord(modelOrCollection, options);
                case 'delete':  return this._deleteRecord(modelOrCollection, options);
            }

            throw new TypeError('Unknown method ' + method + ' in sync');
        }
    };
})();
<|endoftext|>


<commit_before>Crypto.Rabbit = function () {

	// Shortcut
	var util = Crypto.util;

	// Inner state
	var X = [],
	    C = [],
	    b;

	return {

		// Key setup scheme
		_KeySetup: function (K) {

			// Generate initial state values
			X[0] = K[0];
			X[2] = K[1];
			X[4] = K[2];
			X[6] = K[3];
			X[1] = (K[3] << 16) | (K[2] >>> 16);
			X[3] = (K[0] << 16) | (K[3] >>> 16);
			X[5] = (K[1] << 16) | (K[0] >>> 16);
			X[7] = (K[2] << 16) | (K[1] >>> 16);

			// Generate initial counter values
			C[0] = util.rotl(K[2], 16);
			C[2] = util.rotl(K[3], 16);
			C[4] = util.rotl(K[0], 16);
			C[6] = util.rotl(K[1], 16);
			C[1] = (K[0] & 0xFFFF0000) | (K[1] & 0xFFFF);
			C[3] = (K[1] & 0xFFFF0000) | (K[2] & 0xFFFF);
			C[5] = (K[2] & 0xFFFF0000) | (K[3] & 0xFFFF);
			C[7] = (K[3] & 0xFFFF0000) | (K[0] & 0xFFFF);

			// Clear carry bit
			b = 0;

			// Iterate the system four times
			for (var i = 0; i < 4; i++) this._NextState();

			// Modify the counters
			for (var i = 0; i < 8; i++) C[i] ^= X[(i + 4) & 7];

		},

		// IV setup scheme
		_IVSetup: function (IV) {

			// Generate four subvectors
			var i0 = util.endian(IV[0]),
			    i2 = util.endian(IV[1]),
			    i1 = (i0 >>> 16) | (i2 & 0xFFFF0000),
			    i3 = (i2 <<  16) | (i0 & 0x0000FFFF);

			// Modify counter values
			C[0] ^= i0;
			C[1] ^= i1;
			C[2] ^= i2;
			C[3] ^= i3;
			C[4] ^= i0;
			C[5] ^= i1;
			C[6] ^= i2;
			C[7] ^= i3;

			// Iterate the system four times
			for (var i = 0; i < 4; i++) this._NextState();

		},

		// Next-state function
		_NextState: function () {

			// Save old counter values
			var C_old = [];
			for (var i = 0; i < 8; i++) C_old[i] = C[i];

			// Calculate new counter values
			C[0] = (C[0] + 0x4D34D34D + b) >>> 0;
			C[1] = (C[1] + 0xD34D34D3 + ((C[0] >>> 0) < (C_old[0] >>> 0) ? 1 : 0)) >>> 0;
			C[2] = (C[2] + 0x34D34D34 + ((C[1] >>> 0) < (C_old[1] >>> 0) ? 1 : 0)) >>> 0;
			C[3] = (C[3] + 0x4D34D34D + ((C[2] >>> 0) < (C_old[2] >>> 0) ? 1 : 0)) >>> 0;
			C[4] = (C[4] + 0xD34D34D3 + ((C[3] >>> 0) < (C_old[3] >>> 0) ? 1 : 0)) >>> 0;
			C[5] = (C[5] + 0x34D34D34 + ((C[4] >>> 0) < (C_old[4] >>> 0) ? 1 : 0)) >>> 0;
			C[6] = (C[6] + 0x4D34D34D + ((C[5] >>> 0) < (C_old[5] >>> 0) ? 1 : 0)) >>> 0;
			C[7] = (C[7] + 0xD34D34D3 + ((C[6] >>> 0) < (C_old[6] >>> 0) ? 1 : 0)) >>> 0;
			b = (C[7] >>> 0) < (C_old[7] >>> 0) ? 1 : 0;

			// Calculate the g-values
			for (var i = 0, g = []; i < 8; i++) {

				var gx = (X[i] + C[i]) >>> 0;

				// Construct high and low argument for squaring
				var ga = gx & 0xFFFF,
				    gb = gx >>> 16;

				// Calculate high and low result of squaring
				var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb,
				    gl = (((gx & 0xFFFF0000) * gx) >>> 0) + (((gx & 0x0000FFFF) * gx) >>> 0) >>> 0;

				// High XOR low
				g[i] = gh ^ gl;

			}

			// Calculate new state values
			X[0] = g[0] + ((g[7] << 16) | (g[7] >>> 16)) + ((g[6] << 16) | (g[6] >>> 16));
			X[1] = g[1] + ((g[0] <<  8) | (g[0] >>> 24)) + g[7];
			X[2] = g[2] + ((g[1] << 16) | (g[1] >>> 16)) + ((g[0] << 16) | (g[0] >>> 16));
			X[3] = g[3] + ((g[2] <<  8) | (g[2] >>> 24)) + g[1];
			X[4] = g[4] + ((g[3] << 16) | (g[3] >>> 16)) + ((g[2] << 16) | (g[2] >>> 16));
			X[5] = g[5] + ((g[4] <<  8) | (g[4] >>> 24)) + g[3];
			X[6] = g[6] + ((g[5] << 16) | (g[5] >>> 16)) + ((g[4] << 16) | (g[4] >>> 16));
			X[7] = g[7] + ((g[6] <<  8) | (g[6] >>> 24)) + g[5];

		},

		// Encryption/decryption scheme
		_Rabbit: function (M, K, IV) {

			this._KeySetup(K);
			if (IV) this._IVSetup(IV);

			for (var i = 0, S = []; i < M.length; i++) {

				if (S.length == 0) {

					// Iterate the system
					this._NextState();

					// Generate 16 bytes of pseudo-random data
					S = [
						X[0] ^ (X[5] >>> 16) ^ (X[3] << 16),
						X[2] ^ (X[7] >>> 16) ^ (X[5] << 16),
						X[4] ^ (X[1] >>> 16) ^ (X[7] << 16),
						X[6] ^ (X[3] >>> 16) ^ (X[1] << 16)
					];

					// Swap endian
					for (var j = 0; j < 4; j++) {
						S[j] = ((S[j] <<  8) | (S[j] >>> 24)) & 0x00FF00FF |
						       ((S[j] << 24) | (S[j] >>>  8)) & 0xFF00FF00;
					}

					// Convert words to bytes
					var bytes = [];
					for (var b = 0; b < 128; b += 8)
						bytes.push((S[b >>> 5] >>> (24 - b % 32)) & 0xFF);
					S = bytes;

				}

				M[i] ^= S.shift();
			}

		},

		/**
		 * Public API
		 */

		encrypt: function (message, key, IV) {

			// Convert to bytes and words
			var M = util.string_bytes(message),
			    K = util.endian(util.string_words(key));

			// Generate random IV, or use given IV if testing
			if (!this.testMode) {
				IV = [
					Math.floor(Math.random() * 0x100000000),
					Math.floor(Math.random() * 0x100000000)
				];
			}

			// Encrypt
			this._Rabbit(M, K, IV);

			// Return ciphertext
			return !this.testMode ? util.words_bytes(IV).concat(M) : M;

		},

		decrypt: function (M, key, IV) {

			// Convert to words
			var K = util.endian(util.string_words(key));

			// Separate IV and message, or use given IV if testing
			if (!this.testMode) {
				IV = util.bytes_words(M.slice(0,8));
				M = M.slice(8);
			}

			// Decrypt
			this._Rabbit(M, K, IV);

			// Return plaintext
			return util.bytes_string(M);

		},

		testMode: false

	};

}();
<commit_msg>Cosmetic.<commit_after>Crypto.Rabbit = function () {

	// Shortcut
	var util = Crypto.util;

	// Inner state
	var X = [],
	    C = [],
	    b;

	return {

		// Key setup scheme
		_KeySetup: function (K) {

			// Generate initial state values
			X[0] = K[0];
			X[2] = K[1];
			X[4] = K[2];
			X[6] = K[3];
			X[1] = (K[3] << 16) | (K[2] >>> 16);
			X[3] = (K[0] << 16) | (K[3] >>> 16);
			X[5] = (K[1] << 16) | (K[0] >>> 16);
			X[7] = (K[2] << 16) | (K[1] >>> 16);

			// Generate initial counter values
			C[0] = util.rotl(K[2], 16);
			C[2] = util.rotl(K[3], 16);
			C[4] = util.rotl(K[0], 16);
			C[6] = util.rotl(K[1], 16);
			C[1] = (K[0] & 0xFFFF0000) | (K[1] & 0xFFFF);
			C[3] = (K[1] & 0xFFFF0000) | (K[2] & 0xFFFF);
			C[5] = (K[2] & 0xFFFF0000) | (K[3] & 0xFFFF);
			C[7] = (K[3] & 0xFFFF0000) | (K[0] & 0xFFFF);

			// Clear carry bit
			b = 0;

			// Iterate the system four times
			for (var i = 0; i < 4; i++) this._NextState();

			// Modify the counters
			for (var i = 0; i < 8; i++) C[i] ^= X[(i + 4) & 7];

		},

		// IV setup scheme
		_IVSetup: function (IV) {

			// Generate four subvectors
			var i0 = util.endian(IV[0]),
			    i2 = util.endian(IV[1]),
			    i1 = (i0 >>> 16) | (i2 & 0xFFFF0000),
			    i3 = (i2 <<  16) | (i0 & 0x0000FFFF);

			// Modify counter values
			C[0] ^= i0;
			C[1] ^= i1;
			C[2] ^= i2;
			C[3] ^= i3;
			C[4] ^= i0;
			C[5] ^= i1;
			C[6] ^= i2;
			C[7] ^= i3;

			// Iterate the system four times
			for (var i = 0; i < 4; i++) this._NextState();

		},

		// Next-state function
		_NextState: function () {

			// Save old counter values
			var C_old = [];
			for (var i = 0; i < 8; i++) C_old[i] = C[i];

			// Calculate new counter values
			C[0] = (C[0] + 0x4D34D34D + b) >>> 0;
			C[1] = (C[1] + 0xD34D34D3 + ((C[0] >>> 0) < (C_old[0] >>> 0) ? 1 : 0)) >>> 0;
			C[2] = (C[2] + 0x34D34D34 + ((C[1] >>> 0) < (C_old[1] >>> 0) ? 1 : 0)) >>> 0;
			C[3] = (C[3] + 0x4D34D34D + ((C[2] >>> 0) < (C_old[2] >>> 0) ? 1 : 0)) >>> 0;
			C[4] = (C[4] + 0xD34D34D3 + ((C[3] >>> 0) < (C_old[3] >>> 0) ? 1 : 0)) >>> 0;
			C[5] = (C[5] + 0x34D34D34 + ((C[4] >>> 0) < (C_old[4] >>> 0) ? 1 : 0)) >>> 0;
			C[6] = (C[6] + 0x4D34D34D + ((C[5] >>> 0) < (C_old[5] >>> 0) ? 1 : 0)) >>> 0;
			C[7] = (C[7] + 0xD34D34D3 + ((C[6] >>> 0) < (C_old[6] >>> 0) ? 1 : 0)) >>> 0;
			b = (C[7] >>> 0) < (C_old[7] >>> 0) ? 1 : 0;

			// Calculate the g-values
			for (var i = 0, g = []; i < 8; i++) {

				var gx = (X[i] + C[i]) >>> 0;

				// Construct high and low argument for squaring
				var ga = gx & 0xFFFF,
				    gb = gx >>> 16;

				// Calculate high and low result of squaring
				var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb,
				    gl = (((gx & 0xFFFF0000) * gx) >>> 0) + (((gx & 0x0000FFFF) * gx) >>> 0) >>> 0;

				// High XOR low
				g[i] = gh ^ gl;

			}

			// Calculate new state values
			X[0] = g[0] + ((g[7] << 16) | (g[7] >>> 16)) + ((g[6] << 16) | (g[6] >>> 16));
			X[1] = g[1] + ((g[0] <<  8) | (g[0] >>> 24)) + g[7];
			X[2] = g[2] + ((g[1] << 16) | (g[1] >>> 16)) + ((g[0] << 16) | (g[0] >>> 16));
			X[3] = g[3] + ((g[2] <<  8) | (g[2] >>> 24)) + g[1];
			X[4] = g[4] + ((g[3] << 16) | (g[3] >>> 16)) + ((g[2] << 16) | (g[2] >>> 16));
			X[5] = g[5] + ((g[4] <<  8) | (g[4] >>> 24)) + g[3];
			X[6] = g[6] + ((g[5] << 16) | (g[5] >>> 16)) + ((g[4] << 16) | (g[4] >>> 16));
			X[7] = g[7] + ((g[6] <<  8) | (g[6] >>> 24)) + g[5];

		},

		// Encryption/decryption scheme
		_Rabbit: function (M, K, IV) {

			this._KeySetup(K);
			if (IV) this._IVSetup(IV);

			for (var i = 0, S = []; i < M.length; i++) {

				if (S.length == 0) {

					// Iterate the system
					this._NextState();

					// Generate 16 bytes of pseudo-random data
					S = [
						X[0] ^ (X[5] >>> 16) ^ (X[3] << 16),
						X[2] ^ (X[7] >>> 16) ^ (X[5] << 16),
						X[4] ^ (X[1] >>> 16) ^ (X[7] << 16),
						X[6] ^ (X[3] >>> 16) ^ (X[1] << 16)
					];

					// Swap endian
					for (var j = 0; j < 4; j++) {
						S[j] = ((S[j] <<  8) | (S[j] >>> 24)) & 0x00FF00FF |
						       ((S[j] << 24) | (S[j] >>>  8)) & 0xFF00FF00;
					}

					// Convert words to bytes
					var bytes = [];
					for (var b = 0; b < 128; b += 8)
						bytes.push((S[b >>> 5] >>> (24 - b % 32)) & 0xFF);
					S = bytes;

				}

				M[i] ^= S.shift();
			}

		},

		/**
		 * Public API
		 */

		encrypt: function (message, key, IV) {

			// Convert to bytes and words
			var M = util.string_bytes(message),
			    K = util.endian(util.string_words(key));

			// Generate random IV, or use given IV if testing
			if (!this.testMode) {
				IV = [ Math.floor(Math.random() * 0x100000000),
				       Math.floor(Math.random() * 0x100000000) ];
			}

			// Encrypt
			this._Rabbit(M, K, IV);

			// Return ciphertext
			return !this.testMode ? util.words_bytes(IV).concat(M) : M;

		},

		decrypt: function (M, key, IV) {

			// Convert to words
			var K = util.endian(util.string_words(key));

			// Separate IV and message, or use given IV if testing
			if (!this.testMode) {
				IV = util.bytes_words(M.slice(0,8));
				M = M.slice(8);
			}

			// Decrypt
			this._Rabbit(M, K, IV);

			// Return plaintext
			return util.bytes_string(M);

		},

		testMode: false

	};

}();
<|endoftext|>