<commit_before>(function()
{
  /**
   * Shortcuts
   */
  var Dom = YAHOO.util.Dom,
      Selector = YAHOO.util.Selector,
      Event = YAHOO.util.Event,
      Pagination = Activiti.util.Pagination,
      $html = Activiti.util.decodeHTML;

  /**
   * Artifact constructor.
   *
   * @param {String} htmlId The HTML id of the parent element
   * @return {Activiti.component.Artifact} The new component.Artifact instance
   * @constructor
   */
  Activiti.component.Artifact = function Artifact_constructor(htmlId)
  {
    Activiti.component.Artifact.superclass.constructor.call(this, "Activiti.component.Artifact", htmlId);
    // Create new service instances and set this component to receive the callbacks
    this.services.repositoryService = new Activiti.service.RepositoryService(this);
    // Listen for events that interest this component
    this.onEvent(Activiti.event.updateArtifactView, this.onUpdateArtifactView);
    this.onEvent(Activiti.event.clickFormEventButton, this.onClickFormEventButton);

    this._tabView = {};
    this._repositoryNodeId = "";
    this._isRepositoryArtifact = false;
    this._name = "";
    this._activeTabIndex = 0;

    this._fileChooserDialog = {};

    return this;
  };

  YAHOO.extend(Activiti.component.Artifact, Activiti.component.Base,
  {
    /**
    * Fired by YUI when parent element is available for scripting.
    * Template initialisation, including instantiation of YUI widgets and event listener binding.
    *
    * @method onReady
    */
    onReady: function Artifact_onReady()
    {

    },

    /**
     * This method is invoked when a node in the tree is selected or the active tab chages.
     * It first checks whether the node is still the same and updates the active tab if
     * needed. If a new node was selected in the tree, the current artifact view is removed
     * and the loadArtifact method is invoked with the new artifacts id.
     *
     * @method onUpdateArtifactView
     * @param event {String} the name of the event that triggered this method invokation
     * @param args {array} an array of object literals
     */
    onUpdateArtifactView: function Artifact_onUpdateArtifactView(event, args) {

      var eventValue = args[1].value;

      this._connectorId = eventValue.connectorId;
      this._repositoryNodeId = eventValue.repositoryNodeId;
      this._isRepositoryArtifact = eventValue.isRepositoryArtifact;
      this._name = eventValue.name;
      this._activeTabIndex = eventValue.activeTabIndex;

      // get the header el of the content area
      var headerEl = Selector.query("h1", this.id, true);
      // determine whether the node is still the same
      if("header-" + eventValue.repositoryNodeId === headerEl.id) {
        // still the same node, if the tab view is instanciated, the tab selection should be updated
        if(this._tabView.set) {
          // Update active tab selection silently, without firing an event (last parameter 'true')
          this._tabView.set("activeTab", this._tabView.getTab(this._activeTabIndex), true);
        }
      } else {
        // a new node has been selected in the tree
        var tabViewHtml = YAHOO.util.Selector.query('div', 'artifact-div', true);
        // check whether an artifact was selected before. If yes, remove tabViewHtml and actions
        if(tabViewHtml) {
          var artifactDiv = document.getElementById('artifact-div');
          artifactDiv.removeChild(tabViewHtml);
          var optionsDiv = document.getElementById('options-div');
          optionsDiv.innerHTML = "";
          optionsDiv.removeAttribute("class");
        }
        // Check whether the selected node is a file node. If so, load its data
        if(eventValue.isRepositoryArtifact ) {
          this.services.repositoryService.loadArtifact(eventValue.connectorId, eventValue.repositoryNodeId);
        }
        // Update the heading that displays the name of the selected node
        headerEl.id = "header-" + eventValue.repositoryNodeId;
        headerEl.innerHTML = eventValue.name;
      }
    },

    /**
     * This method is invoked when an artifact is loaded successfully. It will draw a
     * yui tab view component to display the different content representations of the
     * artifact and create an options panel for links, downloads and actions.
     *
     * @method onLoadArtifactSuccess
     * @param response {object} The callback response
     * @param obj {object} Helper object
     */
    onLoadArtifactSuccess: function RepoTree_RepositoryService_onLoadArtifactSuccess(response, obj)
    {
      var me = this;
      this._tabView = new YAHOO.widget.TabView();

      // Retrieve rest api response
      var artifactJson = response.json;

      for(var i = 0; i<artifactJson.contentRepresentations.length; i++) {
        var tab = new YAHOO.widget.Tab({
          label: artifactJson.contentRepresentations[i],
          dataSrc: this.loadTabDataURL(artifactJson.connectorId, artifactJson.artifactId, artifactJson.contentRepresentations[i]),
          cacheData: true
        });
        tab.addListener("contentChange", this.onTabDataLoaded);

        tab.loadHandler.success = function(response) {
          me.onLoadTabSuccess(this /* the tab */, response);
        };
        this._tabView.addTab(tab);
      }

      this._tabView.appendTo('artifact-div');

      // replace the tabViews onActiveTabCHange evnet handler with our own one
      this._tabView.unsubscribe("activeTabChange", this._tabView._onActiveTabChange);
      this._tabView.subscribe("activeTabChange", this.onActiveTabChange, null, this);

      // Select the active tab without firing an event (last parameter is 'silent=true')
      this._tabView.set("activeTab", this._tabView.getTab(this._activeTabIndex), true);

      // Create the options panel
      var optionsDiv = document.getElementById("options-div");//YAHOO.util.Selector.query('div', 'artifact-div', true);

      // Add a dropdown for the actions
      if(artifactJson.actions.length > 0) {
        var actionsDiv = document.createElement("div");
        actionsDiv.setAttribute('id', "artifact-actions");
        actionsDiv.appendChild(document.createTextNode("Actions: "));
        var actionsDropdown = document.createElement("select");
        actionsDropdown.setAttribute('name', "Actions");

        var option = document.createElement("option");
        option.appendChild(document.createTextNode("choose an action..."));
        actionsDropdown.appendChild(option);

        for(i = 0; i<artifactJson.actions.length; i++) {
          option = document.createElement("option");
          option.setAttribute('value', artifactJson.connectorId + "#TOKEN#" + artifactJson.artifactId + "#TOKEN#" + artifactJson.actions[i].name);
          option.appendChild(document.createTextNode(artifactJson.actions[i].label));
          actionsDropdown.appendChild(option);
          YAHOO.util.Event.addListener(option, "click", this.onExecuteActionClick);
        }
        actionsDiv.appendChild(actionsDropdown);
        optionsDiv.appendChild(actionsDiv);
      }
      if(artifactJson.links.length > 0) {
        var linksDiv = document.createElement("div");
        linksDiv.setAttribute('id', "artifact-links");
        linksDiv.appendChild(document.createTextNode("Links: "));
        for(i=0; i<artifactJson.links.length; i++) {
          var link = document.createElement("a");
          link.setAttribute('href', artifactJson.links[i].url);
          link.setAttribute('title', artifactJson.links[i].label);
          link.setAttribute('target', "blank");
          link.appendChild(document.createTextNode(artifactJson.links[i].label));
          linksDiv.appendChild(link);
          if(i < (artifactJson.links.length - 1)) {
            linksDiv.appendChild(document.createTextNode(" | "));
          }
        }
        optionsDiv.appendChild(linksDiv);
      }
      // Add download links if available
      if(artifactJson.downloads.length > 0) {
        var downloadsDiv = document.createElement("div");
        downloadsDiv.setAttribute('id', "artifact-downloads");
        downloadsDiv.appendChild(document.createTextNode("Downloads: "));
        for(i=0; i<artifactJson.downloads.length; i++) {
          var link1 = document.createElement("a");
          link1.setAttribute('href', artifactJson.downloads[i].url);
          link1.setAttribute('title', artifactJson.downloads[i].name + " (" + artifactJson.downloads[i].type + ")");
          link1.setAttribute('target', "blank");
          link1.appendChild(document.createTextNode(artifactJson.downloads[i].name));
          downloadsDiv.appendChild(link1);
          if(i < (artifactJson.downloads.length -1)) {
            downloadsDiv.appendChild(document.createTextNode(" | "));
          }
        }
        optionsDiv.appendChild(downloadsDiv);
      }
      var clearDiv = document.createElement('div');
      clearDiv.setAttribute('style', 'clear: both');
      optionsDiv.appendChild(clearDiv);
      optionsDiv.setAttribute('class', 'active');
    },

    onLoadTabSuccess: function Artifact_onLoadTabSuccess(tab, response) {

      try {
        var responseJson = YAHOO.lang.JSON.parse(response.responseText);
        // parse response, create tab content and set it to the tab

        var tabContent;
        if(responseJson.renderInfo == "IMAGE") {
          tabContent = '

';
        } else if (responseJson.renderInfo == "HTML") {
          tabContent = '

Your browser does not support iframes.

';
        } else if (responseJson.renderInfo == "HTML_REFERENCE") {
          tabContent = '

Your browser does not support iframes.

';
        } else if (responseJson.renderInfo == "BINARY") {
          // TODO: show some information but no content for binary
          tabContent = '

No preview available...

';
        } else if (responseJson.renderInfo == "CODE") {
          tabContent = '

' + responseJson.content + '

';
        } else if (responseJson.renderInfo == "TEXT_PLAIN") {
          tabContent = '

' + responseJson.content + '

';
        }
        tab.set('content', tabContent);
        //{ "renderInfo": "IMAGE", "contentRepresentationId": "PNG", "contentType": "image\/png", "imageUrl": "\/activiti-cycle\/proxy\/activiti-rest-endpoint\/content?artifactId=%2FDemo%2Fminutes%2FInitialMindmap.mm&contentRepresentationId=PNG" }
      }
      catch (e) {
          alert("Invalid response for tab data");
      }
    },

    onExecuteActionClick: function Artifact_onExecuteActionClick(e)
    {
      var connectorId = this.value.split("#TOKEN#")[0];
      var artifactId = this.value.split("#TOKEN#")[1];
      var actionName = this.value.split("#TOKEN#")[2];

      return new Activiti.widget.ExecuteArtifactActionForm(this.id + "-executeArtifactActionForm", connectorId, artifactId, actionName);
    },

    onTabDataLoaded: function Artifact_onTabDataLoaded()
    {
      prettyPrint();
    },

    loadTabDataURL: function Artifact_loadTabDataURL(connectorId, artifactId, representationId)
    {
      return Activiti.service.REST_PROXY_URI_RELATIVE + "content-representation?connectorId=" + encodeURIComponent(connectorId) + "&artifactId=" + encodeURIComponent(artifactId) + "&representationId=" + encodeURIComponent(representationId);
    },

    onActiveTabChange: function Artifact_onActiveTabChange(event)
    {
      var newActiveTabIndex = this._tabView.getTabIndex(event.newValue);
      this.fireEvent(Activiti.event.updateArtifactView, {"connectorId": this._connectorId, "repositoryNodeId": this._repositoryNodeId, "isRepositoryArtifact": this._isRepositoryArtifact, "name": this._name, "activeTabIndex": newActiveTabIndex}, null, true);
      YAHOO.util.Event.preventDefault(event);
    },

    onClickFormEventButton: function Artifact_onClickFormEventButton(event, args)
    {
      return new Activiti.component.FileChooserDialog(this.id, args[1].value.callback);
    }

  });

})();
<commit_msg>added view of artifact links and first shot at event handling for artifact links<commit_after>(function()
{
  /**
   * Shortcuts
   */
  var Dom = YAHOO.util.Dom,
      Selector = YAHOO.util.Selector,
      Event = YAHOO.util.Event,
      Pagination = Activiti.util.Pagination,
      $html = Activiti.util.decodeHTML;

  /**
   * Artifact constructor.
   *
   * @param {String} htmlId The HTML id of the parent element
   * @return {Activiti.component.Artifact} The new component.Artifact instance
   * @constructor
   */
  Activiti.component.Artifact = function Artifact_constructor(htmlId)
  {
    Activiti.component.Artifact.superclass.constructor.call(this, "Activiti.component.Artifact", htmlId);
    // Create new service instances and set this component to receive the callbacks
    this.services.repositoryService = new Activiti.service.RepositoryService(this);
    // Listen for events that interest this component
    this.onEvent(Activiti.event.updateArtifactView, this.onUpdateArtifactView);
    this.onEvent(Activiti.event.clickFormEventButton, this.onClickFormEventButton);

    this._tabView = {};
    this._repositoryNodeId = "";
    this._isRepositoryArtifact = false;
    this._name = "";
    this._activeTabIndex = 0;

    this._fileChooserDialog = {};

    return this;
  };

  YAHOO.extend(Activiti.component.Artifact, Activiti.component.Base,
  {
    /**
    * Fired by YUI when parent element is available for scripting.
    * Template initialisation, including instantiation of YUI widgets and event listener binding.
    *
    * @method onReady
    */
    onReady: function Artifact_onReady()
    {

    },

    /**
     * This method is invoked when a node in the tree is selected or the active tab chages.
     * It first checks whether the node is still the same and updates the active tab if
     * needed. If a new node was selected in the tree, the current artifact view is removed
     * and the loadArtifact method is invoked with the new artifacts id.
     *
     * @method onUpdateArtifactView
     * @param event {String} the name of the event that triggered this method invokation
     * @param args {array} an array of object literals
     */
    onUpdateArtifactView: function Artifact_onUpdateArtifactView(event, args) {

      var eventValue = args[1].value;

      this._connectorId = eventValue.connectorId;
      this._repositoryNodeId = eventValue.repositoryNodeId;
      this._isRepositoryArtifact = eventValue.isRepositoryArtifact;
      this._name = eventValue.name;
      this._activeTabIndex = eventValue.activeTabIndex;

      // get the header el of the content area
      var headerEl = Selector.query("h1", this.id, true);
      // determine whether the node is still the same
      if("header-" + eventValue.repositoryNodeId === headerEl.id) {
        // still the same node, if the tab view is instanciated, the tab selection should be updated
        if(this._tabView.set) {
          // Update active tab selection silently, without firing an event (last parameter 'true')
          this._tabView.set("activeTab", this._tabView.getTab(this._activeTabIndex), true);
        }
      } else {
        // a new node has been selected in the tree
        var tabViewHtml = YAHOO.util.Selector.query('div', 'artifact-div', true);
        // check whether an artifact was selected before. If yes, remove tabViewHtml and actions
        if(tabViewHtml) {
          var artifactDiv = document.getElementById('artifact-div');
          artifactDiv.removeChild(tabViewHtml);
          var optionsDiv = document.getElementById('options-div');
          optionsDiv.innerHTML = "";
          optionsDiv.removeAttribute("class");
        }
        // Check whether the selected node is a file node. If so, load its data
        if(eventValue.isRepositoryArtifact ) {
          this.services.repositoryService.loadArtifact(eventValue.connectorId, eventValue.repositoryNodeId);
        }
        // Update the heading that displays the name of the selected node
        headerEl.id = "header-" + eventValue.repositoryNodeId;
        headerEl.innerHTML = eventValue.name;
      }
    },

    /**
     * This method is invoked when an artifact is loaded successfully. It will draw a
     * yui tab view component to display the different content representations of the
     * artifact and create an options panel for links, downloads and actions.
     *
     * @method onLoadArtifactSuccess
     * @param response {object} The callback response
     * @param obj {object} Helper object
     */
    onLoadArtifactSuccess: function RepoTree_RepositoryService_onLoadArtifactSuccess(response, obj)
    {
      var me = this;
      this._tabView = new YAHOO.widget.TabView();

      // Retrieve rest api response
      var artifactJson = response.json;

      for(var i = 0; i<artifactJson.contentRepresentations.length; i++) {
        var tab = new YAHOO.widget.Tab({
          label: artifactJson.contentRepresentations[i],
          dataSrc: this.loadTabDataURL(artifactJson.connectorId, artifactJson.artifactId, artifactJson.contentRepresentations[i]),
          cacheData: true
        });
        tab.addListener("contentChange", this.onTabDataLoaded);

        tab.loadHandler.success = function(response) {
          me.onLoadTabSuccess(this /* the tab */, response);
        };
        this._tabView.addTab(tab);
      }

      // ------------------------------ Links Tab --

      // Add artifact links tab
			var linksTab = new YAHOO.widget.Tab({
				label: "Links",
				dataSrc: Activiti.service.REST_PROXY_URI_RELATIVE + "artifact-links?connectorId=" + encodeURIComponent(artifactJson.connectorId) + "&artifactId=" + encodeURIComponent(artifactJson.artifactId),
				cacheData: true
			});

			linksTab.loadHandler.success = function(response) {
				me.onLodLinksSuccess(this /* the tab */, response);
			};

			this._tabView.addTab(linksTab);

      // -------------------------- End Links Tab --

      this._tabView.appendTo('artifact-div');

      // replace the tabViews onActiveTabCHange evnet handler with our own one
      this._tabView.unsubscribe("activeTabChange", this._tabView._onActiveTabChange);
      this._tabView.subscribe("activeTabChange", this.onActiveTabChange, null, this);

      // Select the active tab without firing an event (last parameter is 'silent=true')
      this._tabView.set("activeTab", this._tabView.getTab(this._activeTabIndex), true);

      // Create the options panel
      var optionsDiv = document.getElementById("options-div");//YAHOO.util.Selector.query('div', 'artifact-div', true);

      // Add a dropdown for the actions
      if(artifactJson.actions.length > 0) {
        var actionsDiv = document.createElement("div");
        actionsDiv.setAttribute('id', "artifact-actions");
        actionsDiv.appendChild(document.createTextNode("Actions: "));
        var actionsDropdown = document.createElement("select");
        actionsDropdown.setAttribute('name', "Actions");

        var option = document.createElement("option");
        option.appendChild(document.createTextNode("choose an action..."));
        actionsDropdown.appendChild(option);

        for(i = 0; i<artifactJson.actions.length; i++) {
          option = document.createElement("option");
          option.setAttribute('value', artifactJson.connectorId + "#TOKEN#" + artifactJson.artifactId + "#TOKEN#" + artifactJson.actions[i].name);
          option.appendChild(document.createTextNode(artifactJson.actions[i].label));
          actionsDropdown.appendChild(option);
          YAHOO.util.Event.addListener(option, "click", this.onExecuteActionClick);
        }
        actionsDiv.appendChild(actionsDropdown);
        optionsDiv.appendChild(actionsDiv);
      }
      if(artifactJson.links.length > 0) {
        var linksDiv = document.createElement("div");
        linksDiv.setAttribute('id', "artifact-links");
        linksDiv.appendChild(document.createTextNode("Links: "));
        for(i=0; i<artifactJson.links.length; i++) {
          var link = document.createElement("a");
          link.setAttribute('href', artifactJson.links[i].url);
          link.setAttribute('title', artifactJson.links[i].label);
          link.setAttribute('target', "blank");
          link.appendChild(document.createTextNode(artifactJson.links[i].label));
          linksDiv.appendChild(link);
          if(i < (artifactJson.links.length - 1)) {
            linksDiv.appendChild(document.createTextNode(" | "));
          }
        }
        optionsDiv.appendChild(linksDiv);
      }
      // Add download links if available
      if(artifactJson.downloads.length > 0) {
        var downloadsDiv = document.createElement("div");
        downloadsDiv.setAttribute('id', "artifact-downloads");
        downloadsDiv.appendChild(document.createTextNode("Downloads: "));
        for(i=0; i<artifactJson.downloads.length; i++) {
          var link1 = document.createElement("a");
          link1.setAttribute('href', artifactJson.downloads[i].url);
          link1.setAttribute('title', artifactJson.downloads[i].name + " (" + artifactJson.downloads[i].type + ")");
          link1.setAttribute('target', "blank");
          link1.appendChild(document.createTextNode(artifactJson.downloads[i].name));
          downloadsDiv.appendChild(link1);
          if(i < (artifactJson.downloads.length -1)) {
            downloadsDiv.appendChild(document.createTextNode(" | "));
          }
        }
        optionsDiv.appendChild(downloadsDiv);
      }
      var clearDiv = document.createElement('div');
      clearDiv.setAttribute('style', 'clear: both');
      optionsDiv.appendChild(clearDiv);
      optionsDiv.setAttribute('class', 'active');
    },

    onLoadTabSuccess: function Artifact_onLoadTabSuccess(tab, response) {

      try {
        var responseJson = YAHOO.lang.JSON.parse(response.responseText);
        // parse response, create tab content and set it to the tab

        var tabContent;
        if(responseJson.renderInfo == "IMAGE") {
          tabContent = '

';
        } else if (responseJson.renderInfo == "HTML") {
          tabContent = '

Your browser does not support iframes.

';
        } else if (responseJson.renderInfo == "HTML_REFERENCE") {
          tabContent = '

Your browser does not support iframes.

';
        } else if (responseJson.renderInfo == "BINARY") {
          // TODO: show some information but no content for binary
          tabContent = '

No preview available...

';
        } else if (responseJson.renderInfo == "CODE") {
          tabContent = '

' + responseJson.content + '

';
        } else if (responseJson.renderInfo == "TEXT_PLAIN") {
          tabContent = '

' + responseJson.content + '

';
        }
        tab.set('content', tabContent);
        //{ "renderInfo": "IMAGE", "contentRepresentationId": "PNG", "contentType": "image\/png", "imageUrl": "\/activiti-cycle\/proxy\/activiti-rest-endpoint\/content?artifactId=%2FDemo%2Fminutes%2FInitialMindmap.mm&contentRepresentationId=PNG" }
      }
      catch (e) {
          alert("Invalid response for tab data");
      }
    },

    onLodLinksSuccess: function Artifact_onLodLinksSuccess(tab, response) {
      try{
        var responseJson = YAHOO.lang.JSON.parse(response.responseText);

        tab.set('content', '
');

        var linksColumnDefs = [
            {key:"Name", sortable:true},
            {key:"Revision", sortable:true},
            {key:"Type"}
          ];

        var rows = [];
        for(var i=0; i<responseJson.length; i++) {
          var row = {Name: '' + responseJson[i].label + '', Revision: responseJson[i].targetArtifactRevision, Type: responseJson[i].targetContentType };
          rows.push(row);
        }
        var linksDataSource = new YAHOO.util.LocalDataSource(rows);

        linksDataSource.responseSchema = {
            fields: ["Name","Revision","Type"]
          };

        var linksDataTable = new YAHOO.widget.DataTable("linksTab", linksColumnDefs, linksDataSource, {scrollable:true});

        var linkElements = Dom.getElementsByClassName("openArtifactLink", "a");
        for (var i = 0; i < linkElements.length; i++) {
				  YAHOO.util.Event.addListener(linkElements[i], "click", this.onArtifactLinkClick, this, true);
        }
      }
      catch (e) {
          alert("Invalid response for tab data");
      }
    },

    onExecuteActionClick: function Artifact_onExecuteActionClick(e)
    {
      var connectorId = this.value.split("#TOKEN#")[0];
      var artifactId = this.value.split("#TOKEN#")[1];
      var actionName = this.value.split("#TOKEN#")[2];

      return new Activiti.widget.ExecuteArtifactActionForm(this.id + "-executeArtifactActionForm", connectorId, artifactId, actionName);
    },

    onTabDataLoaded: function Artifact_onTabDataLoaded()
    {
      prettyPrint();
    },

    loadTabDataURL: function Artifact_loadTabDataURL(connectorId, artifactId, representationId)
    {
      return Activiti.service.REST_PROXY_URI_RELATIVE + "content-representation?connectorId=" + encodeURIComponent(connectorId) + "&artifactId=" + encodeURIComponent(artifactId) + "&representationId=" + encodeURIComponent(representationId);
    },

    onActiveTabChange: function Artifact_onActiveTabChange(event)
    {
      var newActiveTabIndex = this._tabView.getTabIndex(event.newValue);
      this.fireEvent(Activiti.event.updateArtifactView, {"connectorId": this._connectorId, "repositoryNodeId": this._repositoryNodeId, "isRepositoryArtifact": this._isRepositoryArtifact, "name": this._name, "activeTabIndex": newActiveTabIndex}, null, true);
      YAHOO.util.Event.preventDefault(event);
    },

    onArtifactLinkClick: function Artifact_onArtifactLinkClick(event)
    {

      var params = event.target.href.split("?")[1].split("&");

      var connectorId = params[0].split("=")[1];
      var artifactId = params[1].split("=")[1];
      var artifactName = params[2].split("=")[1];

      this.fireEvent(Activiti.event.updateArtifactView, {"connectorId": connectorId, "repositoryNodeId": artifactId, "isRepositoryArtifact": true, "name": artifactName, "activeTabIndex": 0}, null, true);
    },

    onClickFormEventButton: function Artifact_onClickFormEventButton(event, args)
    {
      return new Activiti.component.FileChooserDialog(this.id, args[1].value.callback);
    }

  });

})();
<|endoftext|>


<commit_before>var mychart = new plotdb.view.chart(chart, { data: chart.data });
mychart.attach(document.getElementById("wrapper"));

console.log(chart.data);

for (var key in chart.data) {
    console.log(chart.data[key].order);
}

var getScore = function(callback) {
    var options = {
        api: 'https://script.google.com/macros/s/AKfycbzTfdt_q9aNqvWp7LW9JKy6sZeL9fK-KjDcsuaFdmoLlzYsu0-R/exec',
        sheet: 'team_score'
    };
    queryData(options, function(response) {

        if (response.result) {
            chart.data[0].radius = [1, 1, 1, 1, 1, 1];
            console.log(response.data);
        } else {
            console.log(response);
        }
    });
};

// 取得分數名稱的資料
var getScoreName = function(callback) {
    var options = {
        api: 'https://script.google.com/macros/s/AKfycbzTfdt_q9aNqvWp7LW9JKy6sZeL9fK-KjDcsuaFdmoLlzYsu0-R/exec',
        sheet: 'score_table'
    };

    queryData(options, function(response) {

        if (response.result) {

            console.log(response.data);
        } else {
            console.log(response);
        }
    });
};

getScoreName();
getScore();
// $(window).load(function() {
//     getScoreName();
// });<commit_msg>add updateScore function<commit_after>var mychart = new plotdb.view.chart(chart, { data: chart.data });
mychart.attach(document.getElementById("wrapper"));

console.log(chart.data);

for (var key in chart.data) {
    console.log(chart.data[key].order);
}

var getScore = function(callback) {
    var options = {
        api: 'https://script.google.com/macros/s/AKfycbzTfdt_q9aNqvWp7LW9JKy6sZeL9fK-KjDcsuaFdmoLlzYsu0-R/exec',
        sheet: 'team_score'
    };
    queryData(options, function(response) {

        if (response.result) {

            console.log(response.data);
        } else {
            console.log(response);
        }
    });
};

// 取得分數名稱的資料
var getScoreName = function(callback) {
    var options = {
        api: 'https://script.google.com/macros/s/AKfycbzTfdt_q9aNqvWp7LW9JKy6sZeL9fK-KjDcsuaFdmoLlzYsu0-R/exec',
        sheet: 'score_table'
    };

    queryData(options, function(response) {

        if (response.result) {

            console.log(response.data);
        } else {
            console.log(response);
        }
    });
};

var updateScore = function() {
    mychart._.chart.data[0].radius = [1, 1, 1, 1, 1, 1];
    mychart.parse();
    mychart.update();
};

getScoreName();
getScore();
updateScore();
// $(window).load(function() {
//     getScoreName();
// });<|endoftext|>


<commit_before>define(["dojo/_base/kernel", "dojo/_base/html", "dojo/_base/Color"], function(dojo){
	dojo.getObject("gfx._base", true, dojox);

	var g = dojox.gfx, b = g._base;

	// candidates for dojox.style (work on VML and SVG nodes)
	g._hasClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary:
		//		Returns whether or not the specified classes are a portion of the
		//		class list currently applied to the node.
		// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className)	// Boolean
		var cls = node.getAttribute("className");
		return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0;  // Boolean
	};
	g._addClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary:
		//		Adds the specified classes to the end of the class list on the
		//		passed node.
		var cls = node.getAttribute("className") || "";
		if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
			node.setAttribute("className", cls + (cls ? " " : "") + classStr);
		}
	};
	g._removeClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary: Removes classes from node.
		var cls = node.getAttribute("className");
		if(cls){
			node.setAttribute(
				"className",
				cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
			);
		}
	};

	// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)

	//	derived from Morris John's emResized measurer
	b._getFontMeasurements = function(){
		//	summary:
		//		Returns an object that has pixel equivilents of standard font
		//		size values.
		var heights = {
			'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
			'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
			'xx-large': 0
		};
		var p;

		if(dojo.isIE){
			//	we do a font-size fix if and only if one isn't applied already.
			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
			dojo.doc.documentElement.style.fontSize="100%";
		}

		//	set up the measuring node.
		var div = dojo.create("div", {style: {
				position: "absolute",
				left: "0",
				top: "-100px",
				width: "30px",
				height: "1000em",
				borderWidth: "0",
				margin: "0",
				padding: "0",
				outline: "none",
				lineHeight: "1",
				overflow: "hidden"
			}}, dojo.body());

		//	do the measurements.
		for(p in heights){
			div.style.fontSize = p;
			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
		}

		dojo.body().removeChild(div);
		return heights; //object
	};

	var fontMeasurements = null;

	b._getCachedFontMeasurements = function(recalculate){
		if(recalculate || !fontMeasurements){
			fontMeasurements = b._getFontMeasurements();
		}
		return fontMeasurements;
	};

	// candidate for dojox.html.metrics

	var measuringNode = null, empty = {};
	b._getTextBox = function(	/*String*/ text,
								/*Object*/ style,
								/*String?*/ className){
		var m, s, al = arguments.length;
		var i;
		if(!measuringNode){
			measuringNode = dojo.create("div", {style: {
				position: "absolute",
				top: "-10000px",
				left: "0"
			}}, dojo.body());
		}
		m = measuringNode;
		// reset styles
		m.className = "";
		s = m.style;
		s.borderWidth = "0";
		s.margin = "0";
		s.padding = "0";
		s.outline = "0";
		// set new style
		if(al > 1 && style){
			for(i in style){
				if(i in empty){ continue; }
				s[i] = style[i];
			}
		}
		// set classes
		if(al > 2 && className){
			m.className = className;
		}
		// take a measure
		m.innerHTML = text;

		if(m["getBoundingClientRect"]){
			var bcr = m.getBoundingClientRect();
			return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
		}else{
			return dojo.marginBox(m);
		}
	};

	// candidate for dojo.dom

	var uniqueId = 0;
	b._getUniqueId = function(){
		// summary: returns a unique string for use with any DOM element
		var id;
		do{
			id = dojo._scopeName + "Unique" + (++uniqueId);
		}while(dojo.byId(id));
		return id;
	};

	dojo.mixin(dojox.gfx, {
		//	summary:
		//		defines constants, prototypes, and utility functions

		// default shapes, which are used to fill in missing parameters
		defaultPath: {
			type: "path", path: ""
		},
		defaultPolyline: {
			type: "polyline", points: []
		},
		defaultRect: {
			type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
		},
		defaultEllipse: {
			type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
		},
		defaultCircle: {
			type: "circle", cx: 0, cy: 0, r: 100
		},
		defaultLine: {
			type: "line", x1: 0, y1: 0, x2: 100, y2: 100
		},
		defaultImage: {
			type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
		},
		defaultText: {
			type: "text", x: 0, y: 0, text: "", align: "start",
			decoration: "none", rotated: false, kerning: true
		},
		defaultTextPath: {
			type: "textpath", text: "", align: "start",
			decoration: "none", rotated: false, kerning: true
		},

		// default geometric attributes
		defaultStroke: {
			type: "stroke", color: "black", style: "solid", width: 1,
			cap: "butt", join: 4
		},
		defaultLinearGradient: {
			type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
			colors: [
				{ offset: 0, color: "black" }, { offset: 1, color: "white" }
			]
		},
		defaultRadialGradient: {
			type: "radial", cx: 0, cy: 0, r: 100,
			colors: [
				{ offset: 0, color: "black" }, { offset: 1, color: "white" }
			]
		},
		defaultPattern: {
			type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
		},
		defaultFont: {
			type: "font", style: "normal", variant: "normal",
			weight: "normal", size: "10pt", family: "serif"
		},

		getDefault: (function(){
			var typeCtorCache = {};
			// a memoized delegate()
			return function(/*String*/ type){
				var t = typeCtorCache[type];
				if(t){
					return new t();
				}
				t = typeCtorCache[type] = new Function();
				t.prototype = dojox.gfx[ "default" + type ];
				return new t();
			}
		})(),

		normalizeColor: function(/*dojo.Color|Array|string|Object*/ color){
			//	summary:
			//		converts any legal color representation to normalized
			//		dojo.Color object
			return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
		},
		normalizeParameters: function(existed, update){
			//	summary:
			//		updates an existing object with properties from an "update"
			//		object
			//	existed: Object
			//		the "target" object to be updated
			//	update:  Object
			//		the "update" object, whose properties will be used to update
			//		the existed object
			var x;
			if(update){
				var empty = {};
				for(x in existed){
					if(x in update && !(x in empty)){
						existed[x] = update[x];
					}
				}
			}
			return existed;	// Object
		},
		makeParameters: function(defaults, update){
			//	summary:
			//		copies the original object, and all copied properties from the
			//		"update" object
			//	defaults: Object
			//		the object to be cloned before updating
			//	update:   Object
			//		the object, which properties are to be cloned during updating
			var i = null;
			if(!update){
				// return dojo.clone(defaults);
				return dojo.delegate(defaults);
			}
			var result = {};
			for(i in defaults){
				if(!(i in result)){
					result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
				}
			}
			return result; // Object
		},
		formatNumber: function(x, addSpace){
			// summary: converts a number to a string using a fixed notation
			// x:			Number:		number to be converted
			// addSpace:	Boolean?:	if it is true, add a space before a positive number
			var val = x.toString();
			if(val.indexOf("e") >= 0){
				val = x.toFixed(4);
			}else{
				var point = val.indexOf(".");
				if(point >= 0 && val.length - point > 5){
					val = x.toFixed(4);
				}
			}
			if(x < 0){
				return val; // String
			}
			return addSpace ? " " + val : val; // String
		},
		// font operations
		makeFontString: function(font){
			// summary: converts a font object to a CSS font string
			// font:	Object:	font object (see dojox.gfx.defaultFont)
			return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
		},
		splitFontString: function(str){
			// summary:
			//		converts a CSS font string to a font object
			// description:
			//		Converts a CSS font string to a gfx font object. The CSS font
			//		string components should follow the W3C specified order
			//		(see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
			//		style, variant, weight, size, optional line height (will be
			//		ignored), and family.
			// str: String
			//		a CSS font string
			var font = dojox.gfx.getDefault("Font");
			var t = str.split(/\s+/);
			do{
				if(t.length < 5){ break; }
				font.style   = t[0];
				font.variant = t[1];
				font.weight  = t[2];
				var i = t[3].indexOf("/");
				font.size = i < 0 ? t[3] : t[3].substring(0, i);
				var j = 4;
				if(i < 0){
					if(t[4] == "/"){
						j = 6;
					}else if(t[4].charAt(0) == "/"){
						j = 5;
					}
				}
				if(j < t.length){
					font.family = t.slice(j).join(" ");
				}
			}while(false);
			return font;	// Object
		},
		// length operations
		cm_in_pt: 72 / 2.54,	// Number: points per centimeter
		mm_in_pt: 7.2 / 2.54,	// Number: points per millimeter
		px_in_pt: function(){
			// summary: returns a number of pixels per point
			return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12;	// Number
		},
		pt2px: function(len){
			// summary: converts points to pixels
			// len: Number: a value in points
			return len * dojox.gfx.px_in_pt();	// Number
		},
		px2pt: function(len){
			// summary: converts pixels to points
			// len: Number: a value in pixels
			return len / dojox.gfx.px_in_pt();	// Number
		},
		normalizedLength: function(len) {
			// summary: converts any length value to pixels
			// len: String: a length, e.g., "12pc"
			if(len.length === 0){ return 0; }
			if(len.length > 2){
				var px_in_pt = dojox.gfx.px_in_pt();
				var val = parseFloat(len);
				switch(len.slice(-2)){
					case "px": return val;
					case "pt": return val * px_in_pt;
					case "in": return val * 72 * px_in_pt;
					case "pc": return val * 12 * px_in_pt;
					case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
					case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
				}
			}
			return parseFloat(len);	// Number
		},

		// a constant used to split a SVG/VML path into primitive components
		pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
		pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,

		equalSources: function(a, b){
			// summary: compares event sources, returns true if they are equal
			return a && b && a === b;
		},

		switchTo: function(renderer){
			var ns = typeof renderer == "string" ? dojox.gfx[renderer] : renderer;
			if(ns){
				dojo.forEach(["Group", "Rect", "Ellipse", "Circle", "Line",
						"Polyline", "Image", "Text", "Path", "TextPath",
						"Surface", "createSurface", "fixTarget"], function(name){
					dojox.gfx[name] = ns[name];
				});
			}
		}
	});
});
<commit_msg>refs #12863 dojox.gfx._base using dojox without getting a reference on it \!strict<commit_after>define(["dojo/_base/kernel", "dojox/main", "dojo/_base/html", "dojo/_base/Color"], function(dojo, dojox){
	dojo.getObject("gfx._base", true, dojox);

	var g = dojox.gfx, b = g._base;

	// candidates for dojox.style (work on VML and SVG nodes)
	g._hasClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary:
		//		Returns whether or not the specified classes are a portion of the
		//		class list currently applied to the node.
		// return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className)	// Boolean
		var cls = node.getAttribute("className");
		return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0;  // Boolean
	};
	g._addClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary:
		//		Adds the specified classes to the end of the class list on the
		//		passed node.
		var cls = node.getAttribute("className") || "";
		if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
			node.setAttribute("className", cls + (cls ? " " : "") + classStr);
		}
	};
	g._removeClass = function(/*DomNode*/node, /*String*/classStr){
		//	summary: Removes classes from node.
		var cls = node.getAttribute("className");
		if(cls){
			node.setAttribute(
				"className",
				cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
			);
		}
	};

	// candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)

	//	derived from Morris John's emResized measurer
	b._getFontMeasurements = function(){
		//	summary:
		//		Returns an object that has pixel equivilents of standard font
		//		size values.
		var heights = {
			'1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
			'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
			'xx-large': 0
		};
		var p;

		if(dojo.isIE){
			//	we do a font-size fix if and only if one isn't applied already.
			//	NOTE: If someone set the fontSize on the HTML Element, this will kill it.
			dojo.doc.documentElement.style.fontSize="100%";
		}

		//	set up the measuring node.
		var div = dojo.create("div", {style: {
				position: "absolute",
				left: "0",
				top: "-100px",
				width: "30px",
				height: "1000em",
				borderWidth: "0",
				margin: "0",
				padding: "0",
				outline: "none",
				lineHeight: "1",
				overflow: "hidden"
			}}, dojo.body());

		//	do the measurements.
		for(p in heights){
			div.style.fontSize = p;
			heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
		}

		dojo.body().removeChild(div);
		return heights; //object
	};

	var fontMeasurements = null;

	b._getCachedFontMeasurements = function(recalculate){
		if(recalculate || !fontMeasurements){
			fontMeasurements = b._getFontMeasurements();
		}
		return fontMeasurements;
	};

	// candidate for dojox.html.metrics

	var measuringNode = null, empty = {};
	b._getTextBox = function(	/*String*/ text,
								/*Object*/ style,
								/*String?*/ className){
		var m, s, al = arguments.length;
		var i;
		if(!measuringNode){
			measuringNode = dojo.create("div", {style: {
				position: "absolute",
				top: "-10000px",
				left: "0"
			}}, dojo.body());
		}
		m = measuringNode;
		// reset styles
		m.className = "";
		s = m.style;
		s.borderWidth = "0";
		s.margin = "0";
		s.padding = "0";
		s.outline = "0";
		// set new style
		if(al > 1 && style){
			for(i in style){
				if(i in empty){ continue; }
				s[i] = style[i];
			}
		}
		// set classes
		if(al > 2 && className){
			m.className = className;
		}
		// take a measure
		m.innerHTML = text;

		if(m["getBoundingClientRect"]){
			var bcr = m.getBoundingClientRect();
			return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
		}else{
			return dojo.marginBox(m);
		}
	};

	// candidate for dojo.dom

	var uniqueId = 0;
	b._getUniqueId = function(){
		// summary: returns a unique string for use with any DOM element
		var id;
		do{
			id = dojo._scopeName + "Unique" + (++uniqueId);
		}while(dojo.byId(id));
		return id;
	};

	dojo.mixin(dojox.gfx, {
		//	summary:
		//		defines constants, prototypes, and utility functions

		// default shapes, which are used to fill in missing parameters
		defaultPath: {
			type: "path", path: ""
		},
		defaultPolyline: {
			type: "polyline", points: []
		},
		defaultRect: {
			type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
		},
		defaultEllipse: {
			type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
		},
		defaultCircle: {
			type: "circle", cx: 0, cy: 0, r: 100
		},
		defaultLine: {
			type: "line", x1: 0, y1: 0, x2: 100, y2: 100
		},
		defaultImage: {
			type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
		},
		defaultText: {
			type: "text", x: 0, y: 0, text: "", align: "start",
			decoration: "none", rotated: false, kerning: true
		},
		defaultTextPath: {
			type: "textpath", text: "", align: "start",
			decoration: "none", rotated: false, kerning: true
		},

		// default geometric attributes
		defaultStroke: {
			type: "stroke", color: "black", style: "solid", width: 1,
			cap: "butt", join: 4
		},
		defaultLinearGradient: {
			type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
			colors: [
				{ offset: 0, color: "black" }, { offset: 1, color: "white" }
			]
		},
		defaultRadialGradient: {
			type: "radial", cx: 0, cy: 0, r: 100,
			colors: [
				{ offset: 0, color: "black" }, { offset: 1, color: "white" }
			]
		},
		defaultPattern: {
			type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
		},
		defaultFont: {
			type: "font", style: "normal", variant: "normal",
			weight: "normal", size: "10pt", family: "serif"
		},

		getDefault: (function(){
			var typeCtorCache = {};
			// a memoized delegate()
			return function(/*String*/ type){
				var t = typeCtorCache[type];
				if(t){
					return new t();
				}
				t = typeCtorCache[type] = new Function();
				t.prototype = dojox.gfx[ "default" + type ];
				return new t();
			}
		})(),

		normalizeColor: function(/*dojo.Color|Array|string|Object*/ color){
			//	summary:
			//		converts any legal color representation to normalized
			//		dojo.Color object
			return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
		},
		normalizeParameters: function(existed, update){
			//	summary:
			//		updates an existing object with properties from an "update"
			//		object
			//	existed: Object
			//		the "target" object to be updated
			//	update:  Object
			//		the "update" object, whose properties will be used to update
			//		the existed object
			var x;
			if(update){
				var empty = {};
				for(x in existed){
					if(x in update && !(x in empty)){
						existed[x] = update[x];
					}
				}
			}
			return existed;	// Object
		},
		makeParameters: function(defaults, update){
			//	summary:
			//		copies the original object, and all copied properties from the
			//		"update" object
			//	defaults: Object
			//		the object to be cloned before updating
			//	update:   Object
			//		the object, which properties are to be cloned during updating
			var i = null;
			if(!update){
				// return dojo.clone(defaults);
				return dojo.delegate(defaults);
			}
			var result = {};
			for(i in defaults){
				if(!(i in result)){
					result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
				}
			}
			return result; // Object
		},
		formatNumber: function(x, addSpace){
			// summary: converts a number to a string using a fixed notation
			// x:			Number:		number to be converted
			// addSpace:	Boolean?:	if it is true, add a space before a positive number
			var val = x.toString();
			if(val.indexOf("e") >= 0){
				val = x.toFixed(4);
			}else{
				var point = val.indexOf(".");
				if(point >= 0 && val.length - point > 5){
					val = x.toFixed(4);
				}
			}
			if(x < 0){
				return val; // String
			}
			return addSpace ? " " + val : val; // String
		},
		// font operations
		makeFontString: function(font){
			// summary: converts a font object to a CSS font string
			// font:	Object:	font object (see dojox.gfx.defaultFont)
			return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
		},
		splitFontString: function(str){
			// summary:
			//		converts a CSS font string to a font object
			// description:
			//		Converts a CSS font string to a gfx font object. The CSS font
			//		string components should follow the W3C specified order
			//		(see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
			//		style, variant, weight, size, optional line height (will be
			//		ignored), and family.
			// str: String
			//		a CSS font string
			var font = dojox.gfx.getDefault("Font");
			var t = str.split(/\s+/);
			do{
				if(t.length < 5){ break; }
				font.style   = t[0];
				font.variant = t[1];
				font.weight  = t[2];
				var i = t[3].indexOf("/");
				font.size = i < 0 ? t[3] : t[3].substring(0, i);
				var j = 4;
				if(i < 0){
					if(t[4] == "/"){
						j = 6;
					}else if(t[4].charAt(0) == "/"){
						j = 5;
					}
				}
				if(j < t.length){
					font.family = t.slice(j).join(" ");
				}
			}while(false);
			return font;	// Object
		},
		// length operations
		cm_in_pt: 72 / 2.54,	// Number: points per centimeter
		mm_in_pt: 7.2 / 2.54,	// Number: points per millimeter
		px_in_pt: function(){
			// summary: returns a number of pixels per point
			return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12;	// Number
		},
		pt2px: function(len){
			// summary: converts points to pixels
			// len: Number: a value in points
			return len * dojox.gfx.px_in_pt();	// Number
		},
		px2pt: function(len){
			// summary: converts pixels to points
			// len: Number: a value in pixels
			return len / dojox.gfx.px_in_pt();	// Number
		},
		normalizedLength: function(len) {
			// summary: converts any length value to pixels
			// len: String: a length, e.g., "12pc"
			if(len.length === 0){ return 0; }
			if(len.length > 2){
				var px_in_pt = dojox.gfx.px_in_pt();
				var val = parseFloat(len);
				switch(len.slice(-2)){
					case "px": return val;
					case "pt": return val * px_in_pt;
					case "in": return val * 72 * px_in_pt;
					case "pc": return val * 12 * px_in_pt;
					case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
					case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
				}
			}
			return parseFloat(len);	// Number
		},

		// a constant used to split a SVG/VML path into primitive components
		pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
		pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,

		equalSources: function(a, b){
			// summary: compares event sources, returns true if they are equal
			return a && b && a === b;
		},

		switchTo: function(renderer){
			var ns = typeof renderer == "string" ? dojox.gfx[renderer] : renderer;
			if(ns){
				dojo.forEach(["Group", "Rect", "Ellipse", "Circle", "Line",
						"Polyline", "Image", "Text", "Path", "TextPath",
						"Surface", "createSurface", "fixTarget"], function(name){
					dojox.gfx[name] = ns[name];
				});
			}
		}
	});
});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    var MenuItem = Backbone.Model.extend({
        defaults: {
	    id: '',
	    name: '',
	    img: '',
	    calories: 0,
	    rating: 0,
	    description: '',
	    selected: false,
        }
    });

    var MenuItemsCollection = Backbone.Collection.extend({
        model: MenuItem
    });

    var MenuItemView = Backbone.View.extend({

        tagName: 'tr',      // Will create a new tag on render

        events: {
	    'click .select-item': 'selectItem'
        },

        initialize: function( item ) {
            this.model = item;
            this.render();
        },

        selectItem: function(e) {
	        e.preventDefault();
	        Backbone.trigger('app:select', this.model.id); // post a message using Backbone as a global bus
        },

        template: _.template($('#menuItem-template').html(), {variable: 'menuItem'}),

        render: function() {
	        this.$el.html(this.template(this.model.attributes));
	        return this;
        }

    });

    var SelectedItemView = Backbone.View.extend({
        el: '#selected-item',

        initialize: function( item ) {
            this.select( item );
        },

        select: function ( item ) {
	        this.model = item;
	        this.render();
        },

        template: _.template($('#selectedItem-template').html(), {variable: 'menuItem'}),

        render: function() {
            this.$el.html(this.template(this.model));
            return this;
        }
    });

    var ItemDetailView = Backbone.View.extend({
        el: '#details',

        events: {
	    'click .close': 'hide'
        },

        template: _.template($('#itemDetails-template').html(), {variable: 'menuItem'}),

        initialize: function( item ) {
            this.select( item );
        },

        select: function ( item ) {
	        this.model = item;
	        this.render();
        },

        hide: function() {
	        Backbone.trigger('app:clearSelection'); // put a message on the global event bus
        },

        render: function(id) {
            var content = this.model ? this.template(this.model.attributes) : '';
	        this.$el.html(content);
	        return this;
        },

    });

    var FoodRouter = Backbone.Router.extend({
        routes: {
	    '': 'home',
	    'item/:id': 'item'
        },

        home: function(){
	        Backbone.trigger('app:clearSelection');
        },

        item: function(id) {
	        Backbone.trigger('app:select', id);
        }
    });

    var AppView = Backbone.View.extend({

        el: '#app',

        initialize: function( initialMenu ) {
            this.collection = new MenuItemsCollection( initialMenu );
            this.selectedItem = null;

            var menu = $('#table-body');
            this.collection.each(function( item ) {
                this.addMenuItem( menu, item );
            }, this );

            this.selectedItemView = new SelectedItemView( );
	         $('#selected-item').append(this.selectedItemView.render().el);

            this.itemDetailView = new ItemDetailView ( );
            $('#details').append(this.itemDetailView.render().el);

            this.listenTo(Backbone, 'app:clearSelection', this.clearSelection);
            this.listenTo(Backbone, 'app:select', this.select);

            this.router = new FoodRouter( this );
            Backbone.history.start();
        },

        clearSelection: function() {
            this.select(null);
            Backbone.history.navigate('');
        },

        select: function( id ) {
            // Note: Only one item will ever be selected
            var oldSelection = this.collection.findWhere({ selected: true });
            if (oldSelection) {
                if (oldSelection.get('id') == id) return; // no change
                oldSelection.set('selected', false);
            }

            var newSelection = this.collection.findWhere({ id: (id) });
            if (newSelection) {
                newSelection.set('selected', true);
            }
            this.selectedItemView.select(newSelection);
            this.itemDetailView.select(newSelection);
        },

        render: function() {
            return this; // all views will re-render on update
        },

        addMenuItem: function( menu, item ) {
	        var menuItem = new MenuItemView( item );
	        menu.append(menuItem.render().el);
        }

    });

    // Start the app
    var initialMenuItems = [{
        id: 'chicken-pomegranate-salad',
        name: 'Chicken Pomegranate Salad',
        image: 'chicken-pomegranate-salad.jpg',
        calories: 430,
        rating: 4.1,
        description: 'A simple, sweet and delicious salad of chicken, pomegranates, spinach, and spiced candied walnuts. Served with a side of citrus vinaigrette.',
        source: 'https://www.pexels.com/photo/salad-pomegranate-chicken-spinach-5916/',
        photographer: 'Karolina Grabowska.STAFFAGE'
    },
    {
        id: 'strawberry-pudding',
        name: 'Strawberry Pudding',
        image: 'strawberry-pudding.jpg',
        calories: 280,
        rating: 5,
        description: 'A sweet and tasty pudding filled with strawberries, blueberries, and raspberries.',
        source: 'https://www.pexels.com/photo/restaurant-dessert-pudding-strawberries-3674/',
        photographer: ''
    },
    {
        id: 'ham-goat-cheese-croissant',
        name: 'Ham and Goat Cheese Croissant',
        image: 'ham-goat-cheese-croissant.jpg',
        calories: 670,
        rating: 3.9,
        description: 'A savory slice of ham topped with a wedge of goat cheese, all on a buttery, flaky croissant.',
        source: 'https://www.pexels.com/photo/croissant-bakery-plate-food-7390/',
        photographer: ''
    }];

    var app = new AppView( initialMenuItems );

})();
<commit_msg>Properly linted code<commit_after>(function () {
    'use strict';

    var MenuItem = Backbone.Model.extend({
        defaults: {
	    id: '',
	    name: '',
	    img: '',
	    calories: 0,
	    rating: 0,
	    description: '',
	    selected: false,
        }
    });

    var MenuItemsCollection = Backbone.Collection.extend({
        model: MenuItem
    });

    var MenuItemView = Backbone.View.extend({

        tagName: 'tr',      // Will create a new tag on render

        events: {
	    'click .select-item': 'selectItem'
        },

        initialize: function( item ) {
            this.model = item;
            this.render();
        },

        selectItem: function(e) {
	        e.preventDefault();
	        Backbone.trigger('app:select', this.model.id); // post a message using Backbone as a global bus
        },

        template: _.template($('#menuItem-template').html(), {variable: 'menuItem'}),

        render: function() {
	        this.$el.html(this.template(this.model.attributes));
	        return this;
        }

    });

    var SelectedItemView = Backbone.View.extend({
        el: '#selected-item',

        initialize: function( item ) {
            this.select( item );
        },

        select: function ( item ) {
	        this.model = item;
	        this.render();
        },

        template: _.template($('#selectedItem-template').html(), {variable: 'menuItem'}),

        render: function() {
            this.$el.html(this.template(this.model));
            return this;
        }
    });

    var ItemDetailView = Backbone.View.extend({
        el: '#details',

        events: {
	    'click .close': 'hide'
        },

        template: _.template($('#itemDetails-template').html(), {variable: 'menuItem'}),

        initialize: function( item ) {
            this.select( item );
        },

        select: function ( item ) {
	        this.model = item;
	        this.render();
        },

        hide: function() {
	        Backbone.trigger('app:clearSelection'); // put a message on the global event bus
        },

        render: function() {
            var content = this.model ? this.template(this.model.attributes) : '';
	        this.$el.html(content);
	        return this;
        },

    });

    var FoodRouter = Backbone.Router.extend({
        routes: {
	    '': 'home',
	    'item/:id': 'item'
        },

        home: function(){
	        Backbone.trigger('app:clearSelection');
        },

        item: function(id) {
	        Backbone.trigger('app:select', id);
        }
    });

    var AppView = Backbone.View.extend({

        el: '#app',

        initialize: function( initialMenu ) {
            this.collection = new MenuItemsCollection( initialMenu );
            this.selectedItem = null;

            var menu = $('#table-body');
            this.collection.each(function( item ) {
                this.addMenuItem( menu, item );
            }, this );

            this.selectedItemView = new SelectedItemView( );
	         $('#selected-item').append(this.selectedItemView.render().el);

            this.itemDetailView = new ItemDetailView ( );
            $('#details').append(this.itemDetailView.render().el);

            this.listenTo(Backbone, 'app:clearSelection', this.clearSelection);
            this.listenTo(Backbone, 'app:select', this.select);

            this.router = new FoodRouter( this );
            Backbone.history.start();
        },

        clearSelection: function() {
            this.select(null);
            Backbone.history.navigate('');
        },

        select: function( id ) {
            // Note: Only one item will ever be selected
            var oldSelection = this.collection.findWhere({ selected: true });
            if (oldSelection) {
                if (oldSelection.get('id') === id) { return; }// no change
                oldSelection.set('selected', false);
            }

            var newSelection = this.collection.findWhere({ id: (id) });
            if (newSelection) {
                newSelection.set('selected', true);
            }
            this.selectedItemView.select(newSelection);
            this.itemDetailView.select(newSelection);
        },

        render: function() {
            return this; // all views will re-render on update
        },

        addMenuItem: function( menu, item ) {
	        var menuItem = new MenuItemView( item );
	        menu.append(menuItem.render().el);
        }

    });

    // Start the app
    var initialMenuItems = [{
        id: 'chicken-pomegranate-salad',
        name: 'Chicken Pomegranate Salad',
        image: 'chicken-pomegranate-salad.jpg',
        calories: 430,
        rating: 4.1,
        description: 'A simple, sweet and delicious salad of chicken, pomegranates, spinach, and spiced candied walnuts. Served with a side of citrus vinaigrette.',
        source: 'https://www.pexels.com/photo/salad-pomegranate-chicken-spinach-5916/',
        photographer: 'Karolina Grabowska.STAFFAGE'
    },
    {
        id: 'strawberry-pudding',
        name: 'Strawberry Pudding',
        image: 'strawberry-pudding.jpg',
        calories: 280,
        rating: 5,
        description: 'A sweet and tasty pudding filled with strawberries, blueberries, and raspberries.',
        source: 'https://www.pexels.com/photo/restaurant-dessert-pudding-strawberries-3674/',
        photographer: ''
    },
    {
        id: 'ham-goat-cheese-croissant',
        name: 'Ham and Goat Cheese Croissant',
        image: 'ham-goat-cheese-croissant.jpg',
        calories: 670,
        rating: 3.9,
        description: 'A savory slice of ham topped with a wedge of goat cheese, all on a buttery, flaky croissant.',
        source: 'https://www.pexels.com/photo/croissant-bakery-plate-food-7390/',
        photographer: ''
    }];

    new AppView( initialMenuItems );

})();
<|endoftext|>


<commit_before>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-07-16');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<commit_msg>New clientlib ver<commit_after>// ===================================================================================================
//                           _  __     _ _
//                          | |/ /__ _| | |_ _  _ _ _ __ _
//                          | ' </ _` | |  _| || | '_/ _` |
//                          |_|\_\__,_|_|\__|\_,_|_| \__,_|
//
// This file is part of the Kaltura Collaborative Media Suite which allows users
// to do with audio, video, and animation what Wiki platfroms allow them to do with
// text.
//
// Copyright (C) 2006-2017  Kaltura Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// @ignore
// ===================================================================================================
/**
 * The Kaltura Client - this is the facade through which all service actions should be called.
 * @param config the Kaltura configuration object holding partner credentials (type: KalturaConfiguration).
 */
var util = require('util');
var kaltura = require('./KalturaClientBase');
kaltura.services = require('./KalturaServices');
kaltura.objects = require('./KalturaModel');
kaltura.enums = require('./KalturaTypes');

class Client extends kaltura.ClientBase {

	/**
	 * @param Configuration config
	 */
	constructor(config) {
		super(config);
		this.setApiVersion('3.3.0');
		this.setClientTag('node:17-07-17');
	}
}

module.exports = kaltura;
module.exports.Client = Client;

<|endoftext|>


<commit_before>const path = require('path');
const _ = require('lodash');
const EmailTemplate = require('email-templates').EmailTemplate;
const nodemailer = require('nodemailer');
const ses = require('nodemailer-ses-transport');
const logger = require('../utilities/logger');

const getTransporter = () => {
  if (process.env.ACCESSKEYID == null || process.env.ACCESSKEYID === '') {
    throw new Error('Missing ACCESSKEYID config value');
  }
  if (process.env.SECRETACCESSKEY == null || process.env.SECRETACCESSKEY === '') {
    throw new Error('Missing SECRETACCESSKEY config value');
  }
  return nodemailer.createTransport(ses({
    accessKeyId: process.env.ACCESSKEYID,
    secretAccessKey: process.env.SECRETACCESSKEY,
    region: 'eu-west-1'
  }));
};

module.exports.signup = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'signup');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Welcome'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/'
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.confirmEmail = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'confirm-email');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Confirm Email'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/email/',
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.resetPassword = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'reset-password');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Reset your password'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'password/verify/'+data.email+'/'+data.token,
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.confirmNewEmail = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'confirm-new-email');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Confirm New Email'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/email/',
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};
<commit_msg>EmailTemplate is not a constructor...<commit_after>const path = require('path');
const _ = require('lodash');
const EmailTemplate = require('email-templates').EmailTemplate;
const nodemailer = require('nodemailer');
const ses = require('nodemailer-ses-transport');
const logger = require('../utilities/logger');

const getTransporter = () => {
  if (process.env.ACCESSKEYID == null || process.env.ACCESSKEYID === '') {
    throw new Error('Missing ACCESSKEYID config value');
  }
  if (process.env.SECRETACCESSKEY == null || process.env.SECRETACCESSKEY === '') {
    throw new Error('Missing SECRETACCESSKEY config value');
  }
  return nodemailer.createTransport(ses({
    accessKeyId: process.env.ACCESSKEYID,
    secretAccessKey: process.env.SECRETACCESSKEY,
    region: 'eu-west-1'
  }));
};

module.exports.signup = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'signup');
  const mail = getTransporter();//.templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Welcome'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/'
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.confirmEmail = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'confirm-email');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Confirm Email'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/email/',
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.resetPassword = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'reset-password');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Reset your password'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'password/verify/'+data.email+'/'+data.token,
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};

module.exports.confirmNewEmail = (options, data, cb) => {
  const template = path.join(__dirname, 'mailer/templates', 'confirm-new-email');
  const mail = getTransporter().templateSender(new EmailTemplate(template));

  const defaults = {
    from: process.env.MAILFROM,
    subject: 'AVnode.net – Confirm New Email'
  };
  const mailOptions = _.merge(options, defaults);

  const context = _.merge({
    link: process.env.BASE + 'user/confirm/email/',
  }, data);

  mail(mailOptions, context, (err, info) => {
    if (err) {
      return cb(err);
    }
    logger.info('email sent', info);
    return cb(null, info);
  });
};
<|endoftext|>


<commit_before>var chai = require('chai');
var sinon = require('sinon');
var expect = chai.expect;
var Mugshot = require('../lib/mugshot.js');
var path = require('path');

chai.use(require('sinon-chai'));

describe('Mugshot', function() {
  var dummySelector = {
        name: 'path'
      },
      captureItem = {
        name: dummySelector.name,
        selector: 'a dom selector'
      },
      rect = {
        width: 100,
        height: 100,
        top: 50,
        left: 50
      },
      error = new Error('Fatal Error'),
      baseline = new Buffer('bXVnc2hvdA=='),
      screenshot = new Buffer('ZmxvcmVudGlu'),
      diff = new Buffer('anything'),
      rootDirectory = 'visual-tests',
      extension = '.png',
      baselinePath = path.join(rootDirectory, dummySelector.name + extension),
      screenshotPath = path.join(rootDirectory, dummySelector.name + '.new' +
        extension),
      diffPath = path.join(rootDirectory, dummySelector.name + '.diff' +
        extension),
      mugshot, browser,
      FS, differ,
      PNGProcessor;

  beforeEach(function() {
    browser = {
      takeScreenshot: sinon.stub().yields(null, screenshot),
      getBoundingClientRect: sinon.stub()
    };

    FS = {
      exists: sinon.stub(),
      readFile: sinon.stub(),
      writeFile: sinon.stub(),
      mkdir: sinon.stub().yields(null),
      unlink: sinon.stub()
    };

    PNGProcessor = {
      crop: sinon.stub()
    };

    differ = {
      isEqual: sinon.stub(),
      createDiff: sinon.stub()
    };

    var options = {
      differ: differ,
      fs: FS,
      PNGProcessor: PNGProcessor
    };

    mugshot = new Mugshot(browser, options);
  });

  it('should throw an error if no selector is provided', function() {
    expect(mugshot.test.bind(mugshot)).to.throw(Error);
  });

  it('should throw an error if the parameter is not an object', function() {
    expect(mugshot.test.bind(mugshot, function() {})).to.throw(Error);
  });

  it('should throw an error if the parameter is an array', function() {
    expect(mugshot.test.bind(mugshot, [])).to.throw(Error);
  });

  it('should throw an error if the object has no name property', function() {
    expect(mugshot.test.bind(mugshot, {})).to.throw(Error);
  });

  it('should create the rootDirectory', function() {
    mugshot.test(dummySelector);

    expect(FS.mkdir).to.have.been.calledWith(rootDirectory);
  });

  it('should not throw error if the rootDirectory already exists', function() {
    var error = {code: 'EEXIST'};
    FS.mkdir.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.not.throw(error);
  });

  it('should throw error if mkdir callback receives another error', function() {
    FS.mkdir.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should call the browser to take a screenshot', function() {
    mugshot.test(dummySelector);

    expect(browser.takeScreenshot).to.have.been.calledOnce;
  });

  it('should throw an error if the screenshot fails', function() {
    browser.takeScreenshot.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should verify if a baseline already exists', function() {
    mugshot.test(dummySelector);

    expect(FS.exists).to.have.been.calledWith(baselinePath, sinon.match.func);
  });

  it('should write the screenshot on disk if no baseline exists', function() {
    FS.exists.yields(false);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(baselinePath, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the screenshot cannot be written', function() {
    FS.exists.yields(false);
    FS.writeFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not write the screenshot on disk if there is already a baseline',
     function() {
    FS.exists.yields(true);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.not.have.been.called;
  });

  it('should read the baseline from disk if it exists', function() {
    FS.exists.yields(true);

    mugshot.test(dummySelector);

    expect(FS.readFile).to.have.been.calledWith(baselinePath, sinon.match.func);
  });

  it('should throw an error if the baseline cannot be read', function() {
    FS.exists.yields(true);
    FS.readFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not read a baseline from disk if there is none', function() {
    FS.exists.yields(false);

    mugshot.test(dummySelector);

    expect(FS.readFile).to.not.have.been.called;
  });

  it('should call the differ to compare the baseline from the fs with the ' +
     'screenshot from the browser', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);

    mugshot.test(dummySelector);

    expect(differ.isEqual).to.have.been.calledWith(baseline, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the comparison fails', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not compare if there is no baseline', function() {
    FS.exists.yields(false);
    FS.readFile.yields(null, baseline);

    mugshot.test(dummySelector);

    expect(differ.isEqual).to.not.have.been.called;
  });

  it('should create a diff only if there are differences', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);

    mugshot.test(dummySelector);

    expect(differ.createDiff).to.have.been.calledWith(baseline, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the diff building fails', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not create a diff if there are no differences', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(differ.createDiff).to.not.have.been.called;
  });

  it('should call the fs to write the diff on disk', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(diffPath, diff,
      sinon.match.func);
  });

  it('should throw an error if the diff cannot be written', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);
    FS.writeFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not call the fs to write the diff on disk if there is none',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.not.have.been.called;
  });

  it('should call the fs to write the screenshot on disk', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(screenshotPath, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the screenshot cannot be written', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);
    FS.writeFile.onSecondCall().yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should try to unlink old diff if the comparison returns true',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.have.been.calledWith(diffPath);
  });

  it('should try to unlink old screenshot if the comparison returns true',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.have.been.calledWith(screenshotPath);
  });

  it('should not try to unlink old diff and screenshot if the comparison ' +
     'returns false', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.not.have.been.called;
  });

  it('should not throw an error if the file is not there', function() {
    var error = {code: 'ENOENT'};
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.not.throw(error);
  });

  it('should throw an error if the file couldn\'t be unlinked', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);
    FS.unlink.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should get the bounding rect if a selector is provided', function() {
    mugshot.test(captureItem);

    expect(browser.getBoundingClientRect).to.have.been.calledWith(
      captureItem.selector, sinon.match.func);
  });

  it('should throw an error if the bounding rect couldn\'t be calculated',
     function() {
      browser.getBoundingClientRect.yields(error);

      expect(mugshot.test.bind(mugshot, captureItem)).to.throw(Error);
    });

  it('should not get the bounding rect if no selector is provided', function() {
    mugshot.test(dummySelector);

    expect(browser.getBoundingClientRect).to.have.been.not.called;
  });

  it('should crop the image if a selector is provided', function() {
    browser.getBoundingClientRect.yields(null, rect);

    mugshot.test(captureItem);

    expect(PNGProcessor.crop).to.have.been.calledWith(screenshot, rect,
      sinon.match.func);
  });

  it('should throw an error if the screenshot couldn\'t be cropped',
     function() {
      browser.getBoundingClientRect.yields(error);
      PNGProcessor.crop.yields(error);

      expect(mugshot.test.bind(mugshot, captureItem)).to.throw(Error);
    });

  it('should not crop the image if there is no selector', function() {
    mugshot.test(dummySelector);

    expect(PNGProcessor.crop).to.have.been.not.called;
  });
});
<commit_msg>update expect chainable language<commit_after>var chai = require('chai');
var sinon = require('sinon');
var expect = chai.expect;
var Mugshot = require('../lib/mugshot.js');
var path = require('path');

chai.use(require('sinon-chai'));

describe('Mugshot', function() {
  var dummySelector = {
        name: 'path'
      },
      captureItem = {
        name: dummySelector.name,
        selector: 'a dom selector'
      },
      rect = {
        width: 100,
        height: 100,
        top: 50,
        left: 50
      },
      error = new Error('Fatal Error'),
      baseline = new Buffer('bXVnc2hvdA=='),
      screenshot = new Buffer('ZmxvcmVudGlu'),
      diff = new Buffer('anything'),
      rootDirectory = 'visual-tests',
      extension = '.png',
      baselinePath = path.join(rootDirectory, dummySelector.name + extension),
      screenshotPath = path.join(rootDirectory, dummySelector.name + '.new' +
        extension),
      diffPath = path.join(rootDirectory, dummySelector.name + '.diff' +
        extension),
      mugshot, browser,
      FS, differ,
      PNGProcessor;

  beforeEach(function() {
    browser = {
      takeScreenshot: sinon.stub().yields(null, screenshot),
      getBoundingClientRect: sinon.stub()
    };

    FS = {
      exists: sinon.stub(),
      readFile: sinon.stub(),
      writeFile: sinon.stub(),
      mkdir: sinon.stub().yields(null),
      unlink: sinon.stub()
    };

    PNGProcessor = {
      crop: sinon.stub()
    };

    differ = {
      isEqual: sinon.stub(),
      createDiff: sinon.stub()
    };

    var options = {
      differ: differ,
      fs: FS,
      PNGProcessor: PNGProcessor
    };

    mugshot = new Mugshot(browser, options);
  });

  it('should throw an error if no selector is provided', function() {
    expect(mugshot.test.bind(mugshot)).to.throw(Error);
  });

  it('should throw an error if the parameter is not an object', function() {
    expect(mugshot.test.bind(mugshot, function() {})).to.throw(Error);
  });

  it('should throw an error if the parameter is an array', function() {
    expect(mugshot.test.bind(mugshot, [])).to.throw(Error);
  });

  it('should throw an error if the object has no name property', function() {
    expect(mugshot.test.bind(mugshot, {})).to.throw(Error);
  });

  it('should create the rootDirectory', function() {
    mugshot.test(dummySelector);

    expect(FS.mkdir).to.have.been.calledWith(rootDirectory);
  });

  it('should not throw error if the rootDirectory already exists', function() {
    var error = {code: 'EEXIST'};
    FS.mkdir.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.not.throw(error);
  });

  it('should throw error if mkdir callback receives another error', function() {
    FS.mkdir.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should call the browser to take a screenshot', function() {
    mugshot.test(dummySelector);

    expect(browser.takeScreenshot).to.have.been.calledOnce;
  });

  it('should throw an error if the screenshot fails', function() {
    browser.takeScreenshot.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should verify if a baseline already exists', function() {
    mugshot.test(dummySelector);

    expect(FS.exists).to.have.been.calledWith(baselinePath, sinon.match.func);
  });

  it('should write the screenshot on disk if no baseline exists', function() {
    FS.exists.yields(false);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(baselinePath, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the screenshot cannot be written', function() {
    FS.exists.yields(false);
    FS.writeFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not write the screenshot on disk if there is already a baseline',
     function() {
    FS.exists.yields(true);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.not.have.been.called;
  });

  it('should read the baseline from disk if it exists', function() {
    FS.exists.yields(true);

    mugshot.test(dummySelector);

    expect(FS.readFile).to.have.been.calledWith(baselinePath, sinon.match.func);
  });

  it('should throw an error if the baseline cannot be read', function() {
    FS.exists.yields(true);
    FS.readFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not read a baseline from disk if there is none', function() {
    FS.exists.yields(false);

    mugshot.test(dummySelector);

    expect(FS.readFile).to.not.have.been.called;
  });

  it('should call the differ to compare the baseline from the fs with the ' +
     'screenshot from the browser', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);

    mugshot.test(dummySelector);

    expect(differ.isEqual).to.have.been.calledWith(baseline, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the comparison fails', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not compare if there is no baseline', function() {
    FS.exists.yields(false);
    FS.readFile.yields(null, baseline);

    mugshot.test(dummySelector);

    expect(differ.isEqual).to.not.have.been.called;
  });

  it('should create a diff only if there are differences', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);

    mugshot.test(dummySelector);

    expect(differ.createDiff).to.have.been.calledWith(baseline, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the diff building fails', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not create a diff if there are no differences', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(differ.createDiff).to.not.have.been.called;
  });

  it('should call the fs to write the diff on disk', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(diffPath, diff,
      sinon.match.func);
  });

  it('should throw an error if the diff cannot be written', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);
    FS.writeFile.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should not call the fs to write the diff on disk if there is none',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.not.have.been.called;
  });

  it('should call the fs to write the screenshot on disk', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);

    mugshot.test(dummySelector);

    expect(FS.writeFile).to.have.been.calledWith(screenshotPath, screenshot,
      sinon.match.func);
  });

  it('should throw an error if the screenshot cannot be written', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);
    differ.createDiff.yields(null, diff);
    FS.writeFile.onSecondCall().yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should try to unlink old diff if the comparison returns true',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.have.been.calledWith(diffPath);
  });

  it('should try to unlink old screenshot if the comparison returns true',
     function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.have.been.calledWith(screenshotPath);
  });

  it('should not try to unlink old diff and screenshot if the comparison ' +
     'returns false', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, false);

    mugshot.test(dummySelector);

    expect(FS.unlink).to.not.have.been.called;
  });

  it('should not throw an error if the file is not there', function() {
    var error = {code: 'ENOENT'};
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.not.throw(error);
  });

  it('should throw an error if the file couldn\'t be unlinked', function() {
    FS.exists.yields(true);
    FS.readFile.yields(null, baseline);
    differ.isEqual.yields(null, true);
    FS.unlink.yields(error);

    expect(mugshot.test.bind(mugshot, dummySelector)).to.throw(Error);
  });

  it('should get the bounding rect if a selector is provided', function() {
    mugshot.test(captureItem);

    expect(browser.getBoundingClientRect).to.have.been.calledWith(
      captureItem.selector, sinon.match.func);
  });

  it('should throw an error if the bounding rect couldn\'t be calculated',
     function() {
      browser.getBoundingClientRect.yields(error);

      expect(mugshot.test.bind(mugshot, captureItem)).to.throw(Error);
    });

  it('should not get the bounding rect if no selector is provided', function() {
    mugshot.test(dummySelector);

    expect(browser.getBoundingClientRect).to.not.have.been.called;
  });

  it('should crop the image if a selector is provided', function() {
    browser.getBoundingClientRect.yields(null, rect);

    mugshot.test(captureItem);

    expect(PNGProcessor.crop).to.have.been.calledWith(screenshot, rect,
      sinon.match.func);
  });

  it('should throw an error if the screenshot couldn\'t be cropped',
     function() {
      browser.getBoundingClientRect.yields(error);
      PNGProcessor.crop.yields(error);

      expect(mugshot.test.bind(mugshot, captureItem)).to.throw(Error);
    });

  it('should not crop the image if there is no selector', function() {
    mugshot.test(dummySelector);

    expect(PNGProcessor.crop).to.not.have.been.called;
  });
});
<|endoftext|>


<commit_before>function Shell( pos, dir, image )
{
	Prop.call(this, pos, image);

	this.direction = dir.Clone();
}

Shell.prototype = new Prop(new Vec2(0, 0), null);
Shell.constuctor = Shell;
Shell.prototype.size = new Vec2(16, 16);

Shell.prototype.update =
	function( game )
	{
		this.position.addv(this.direction);
		this.updateBounds();

		for(var entityId in game.entities)
		{
			var entity = game.entities[entityId];
			if(entity.bounds && entity != this)
			{
				var horzOverlap = Math.calculateRangeOverlap(this.bounds.left, this.bounds.right, entity.bounds.left, entity.bounds.right);
				var vertOverlap = Math.calculateRangeOverlap(this.bounds.top, this.bounds.bottom, entity.bounds.top, entity.bounds.bottom);
				if(horzOverlap != 0 && vertOverlap != 0)
				{
					if(entity instanceof Tank)
					{
						game.removeEntity(this.id);
						return;
					}
					else
					{
						var horzMagnitude = Math.abs(horzOverlap);
						var vertMagnitude = Math.abs(vertOverlap);
						if(horzMagnitude!=0 && horzMagnitude < vertMagnitude && Math.sign(-horzOverlap)==Math.sign(this.direction.x))
						{
							this.direction.x *= -1;
						}

						if(vertMagnitude!=0 && vertMagnitude < horzMagnitude && Math.sign(-vertOverlap)==Math.sign(this.direction.y))
						{
							this.direction.y *= -1;
						}
					}
				}
			}
		}
	};

<commit_msg>Shells to destroy after a number of bounces.<commit_after>function Shell( pos, dir, image )
{
	Prop.call(this, pos, image);

	this.numBouncesRemaining = 3;
	this.direction = dir.Clone();
}

Shell.prototype = new Prop(new Vec2(0, 0), null);
Shell.constuctor = Shell;
Shell.prototype.size = new Vec2(16, 16);

Shell.prototype.update =
	function( game )
	{
		this.position.addv(this.direction);
		this.updateBounds();

		for(var entityId in game.entities)
		{
			var entity = game.entities[entityId];
			if(entity.bounds && entity != this)
			{
				var horzOverlap = Math.calculateRangeOverlap(this.bounds.left, this.bounds.right, entity.bounds.left, entity.bounds.right);
				var vertOverlap = Math.calculateRangeOverlap(this.bounds.top, this.bounds.bottom, entity.bounds.top, entity.bounds.bottom);
				if(horzOverlap != 0 && vertOverlap != 0)
				{
					if(entity instanceof Tank)
					{
						game.removeEntity(this.id);
						return;
					}
					else
					{
						var horzMagnitude = Math.abs(horzOverlap);
						var vertMagnitude = Math.abs(vertOverlap);
						if(horzMagnitude!=0 && horzMagnitude < vertMagnitude && Math.sign(-horzOverlap)==Math.sign(this.direction.x))
						{
							this.direction.x *= -1;
							--this.numBouncesRemaining;
						}

						if(vertMagnitude!=0 && vertMagnitude < horzMagnitude && Math.sign(-vertOverlap)==Math.sign(this.direction.y))
						{
							this.direction.y *= -1;
							--this.numBouncesRemaining;
						}

						if(this.numBouncesRemaining<=0)
						{
							game.removeEntity(this.id);
							return;
						}
					}
				}
			}
		}
	};

<|endoftext|>