<commit_before>var GUI = (function(){
  var controller;
  var settings;

  var stateChangedEvent = (type, detail) => {
    if (controller){
      var force = type === "gui" && detail === "controller";

      if (type === "data" || force){
        controller.ui.btnDownload.disabled = controller.ui.btnReset.disabled = !STATE.hasSavedData();
      }

      if (type === "tracking" || force){
        controller.ui.btnToggleTracking.innerHTML = STATE.isTracking() ? "Pause Tracking" : "Start Tracking";
      }
    }

    if (settings && type === "gui" && detail === "settings"){
      settings.ui.cbAutoscroll.checked = STATE.settings.autoscroll;
    }
  };

  var registeredEvent = false;

  var setupStateChanged = function(detail){
    if (!registeredEvent){
      STATE.onStateChanged(stateChangedEvent);
      registeredEvent = true;
    }

    stateChangedEvent("gui", detail);
  };

  var root = {
    showController: function(){
      controller = {};

      // styles

      controller.styles = DOM.createStyle([
        ".app, .connecting { bottom: 48px !important; }",
        "#dht-ctrl { position: absolute; bottom: 0; width: 100%; height: 48px; background-color: #fff; }",
        "#dht-ctrl button { height: 32px; margin: 8px 0 8px 8px; font-size: 18px; padding: 0 12px; background-color: #adf; }",
        "#dht-ctrl button:disabled { background-color: #d0d0d0; cursor: default; }",
        "#dht-ctrl p { display: inline-block; margin: 14px 12px; }",
        "#dht-ctrl input { display: none; }"
      ]);

      // main

      controller.ele = DOM.createElement("div", document.body);
      controller.ele.id = "dht-ctrl";

      controller.ele.innerHTML = [
        "<button id='dht-ctrl-upload'>Upload Previous File</button>",
        "<button id='dht-ctrl-settings'>Settings</button>",
        "<button id='dht-ctrl-track'></button>",
        "<button id='dht-ctrl-download'>Download</button>",
        "<button id='dht-ctrl-reset'>Reset</button>",
        "

",
        "<input id='dht-ctrl-upload-input' type='file' multiple>"
      ].join("");

      // elements

      controller.ui = {
        btnUpload: DOM.id("dht-ctrl-upload"),
        btnSettings: DOM.id("dht-ctrl-settings"),
        btnToggleTracking: DOM.id("dht-ctrl-track"),
        btnDownload: DOM.id("dht-ctrl-download"),
        btnReset: DOM.id("dht-ctrl-reset"),
        textStatus: DOM.id("dht-ctrl-status"),
        inputUpload: DOM.id("dht-ctrl-upload-input")
      };

      // events

      controller.ui.btnUpload.addEventListener("click", () => {
        controller.ui.inputUpload.click();
      });

      controller.ui.btnSettings.addEventListener("click", () => {
        root.showSettings();
      });

      controller.ui.btnToggleTracking.addEventListener("click", () => {
        STATE.toggleTracking();
      });

      controller.ui.btnDownload.addEventListener("click", () => {
        STATE.downloadSavefile();
      });

      controller.ui.btnReset.addEventListener("click", () => {
        STATE.resetState();
      });

      controller.ui.inputUpload.addEventListener("change", () => {
        for(var file of controller.ui.inputUpload.files){
          var reader = new FileReader();

          reader.onload = function(){
            var obj = {};

            try{
              obj = JSON.parse(reader.result); // TODO check content validity
            }catch(e){
              alert("Could not parse '"+file.name+"', see console for details.");
              console.error(e);
              return;
            }

            if (SAVEFILE.isValid(obj)){
              STATE.uploadSavefile(new SAVEFILE(obj));
            }
            else{
              alert("File '"+file.name+"' has an invalid format.");
            }
          };

          reader.readAsText(file, "UTF-8");
        }

        controller.ui.inputUpload.value = null;
      });

      setupStateChanged("controller");
    },

    hideController: function(){
      if (controller){
        DOM.removeElement(controller.ele);
        DOM.removeElement(controller.styles);
        controller = null;
      }
    },

    showSettings: function(){
      settings = {};

      // styles

      settings.styles = DOM.createStyle([
        "#dht-cfg-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #000; opacity: 0.5; display: block; z-index: 1000; }",
        "#dht-cfg { position: absolute; left: 50%; top: 50%; width: 500px; height: 300px; margin-left: -250px; margin-top: -174px; padding: 8px; background-color: #fff; z-index: 1001; }"
      ]);

      // overlay

      settings.overlay = DOM.createElement("div", document.body);
      settings.overlay.id = "dht-cfg-overlay";

      settings.overlay.addEventListener("click", () => {
        root.hideSettings();
      });

      // main

      settings.ele = DOM.createElement("div", document.body);
      settings.ele.id = "dht-cfg";

      settings.ele.innerHTML = [
        "<input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll"
      ].join("");

      // elements

      settings.ui = {
        cbAutoscroll: DOM.id("dht-cfg-autoscroll")
      };

      // events

      settings.ui.cbAutoscroll.addEventListener("change", () => {
        STATE.settings.autoscroll = settings.ui.cbAutoscroll.checked;
      });

      setupStateChanged("settings");
    },

    hideSettings: function(){
      if (settings){
        DOM.removeElement(settings.overlay);
        DOM.removeElement(settings.ele);
        DOM.removeElement(settings.styles);
        settings = null;
      }
    }
  };

  return root;
})();
<commit_msg>Disable upload and settings buttons while tracking<commit_after>var GUI = (function(){
  var controller;
  var settings;

  var stateChangedEvent = (type, detail) => {
    if (controller){
      var force = type === "gui" && detail === "controller";

      if (type === "data" || force){
        controller.ui.btnDownload.disabled = controller.ui.btnReset.disabled = !STATE.hasSavedData();
      }

      if (type === "tracking" || force){
        controller.ui.btnUpload.disabled = controller.ui.btnSettings.disabled = STATE.isTracking();
        controller.ui.btnToggleTracking.innerHTML = STATE.isTracking() ? "Pause Tracking" : "Start Tracking";
      }
    }

    if (settings && type === "gui" && detail === "settings"){
      settings.ui.cbAutoscroll.checked = STATE.settings.autoscroll;
    }
  };

  var registeredEvent = false;

  var setupStateChanged = function(detail){
    if (!registeredEvent){
      STATE.onStateChanged(stateChangedEvent);
      registeredEvent = true;
    }

    stateChangedEvent("gui", detail);
  };

  var root = {
    showController: function(){
      controller = {};

      // styles

      controller.styles = DOM.createStyle([
        ".app, .connecting { bottom: 48px !important; }",
        "#dht-ctrl { position: absolute; bottom: 0; width: 100%; height: 48px; background-color: #fff; }",
        "#dht-ctrl button { height: 32px; margin: 8px 0 8px 8px; font-size: 18px; padding: 0 12px; background-color: #adf; }",
        "#dht-ctrl button:disabled { background-color: #d0d0d0; cursor: default; }",
        "#dht-ctrl p { display: inline-block; margin: 14px 12px; }",
        "#dht-ctrl input { display: none; }"
      ]);

      // main

      controller.ele = DOM.createElement("div", document.body);
      controller.ele.id = "dht-ctrl";

      controller.ele.innerHTML = [
        "<button id='dht-ctrl-upload'>Upload Previous File</button>",
        "<button id='dht-ctrl-settings'>Settings</button>",
        "<button id='dht-ctrl-track'></button>",
        "<button id='dht-ctrl-download'>Download</button>",
        "<button id='dht-ctrl-reset'>Reset</button>",
        "

",
        "<input id='dht-ctrl-upload-input' type='file' multiple>"
      ].join("");

      // elements

      controller.ui = {
        btnUpload: DOM.id("dht-ctrl-upload"),
        btnSettings: DOM.id("dht-ctrl-settings"),
        btnToggleTracking: DOM.id("dht-ctrl-track"),
        btnDownload: DOM.id("dht-ctrl-download"),
        btnReset: DOM.id("dht-ctrl-reset"),
        textStatus: DOM.id("dht-ctrl-status"),
        inputUpload: DOM.id("dht-ctrl-upload-input")
      };

      // events

      controller.ui.btnUpload.addEventListener("click", () => {
        controller.ui.inputUpload.click();
      });

      controller.ui.btnSettings.addEventListener("click", () => {
        root.showSettings();
      });

      controller.ui.btnToggleTracking.addEventListener("click", () => {
        STATE.toggleTracking();
      });

      controller.ui.btnDownload.addEventListener("click", () => {
        STATE.downloadSavefile();
      });

      controller.ui.btnReset.addEventListener("click", () => {
        STATE.resetState();
      });

      controller.ui.inputUpload.addEventListener("change", () => {
        for(var file of controller.ui.inputUpload.files){
          var reader = new FileReader();

          reader.onload = function(){
            var obj = {};

            try{
              obj = JSON.parse(reader.result); // TODO check content validity
            }catch(e){
              alert("Could not parse '"+file.name+"', see console for details.");
              console.error(e);
              return;
            }

            if (SAVEFILE.isValid(obj)){
              STATE.uploadSavefile(new SAVEFILE(obj));
            }
            else{
              alert("File '"+file.name+"' has an invalid format.");
            }
          };

          reader.readAsText(file, "UTF-8");
        }

        controller.ui.inputUpload.value = null;
      });

      setupStateChanged("controller");
    },

    hideController: function(){
      if (controller){
        DOM.removeElement(controller.ele);
        DOM.removeElement(controller.styles);
        controller = null;
      }
    },

    showSettings: function(){
      settings = {};

      // styles

      settings.styles = DOM.createStyle([
        "#dht-cfg-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background-color: #000; opacity: 0.5; display: block; z-index: 1000; }",
        "#dht-cfg { position: absolute; left: 50%; top: 50%; width: 500px; height: 300px; margin-left: -250px; margin-top: -174px; padding: 8px; background-color: #fff; z-index: 1001; }"
      ]);

      // overlay

      settings.overlay = DOM.createElement("div", document.body);
      settings.overlay.id = "dht-cfg-overlay";

      settings.overlay.addEventListener("click", () => {
        root.hideSettings();
      });

      // main

      settings.ele = DOM.createElement("div", document.body);
      settings.ele.id = "dht-cfg";

      settings.ele.innerHTML = [
        "<input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll"
      ].join("");

      // elements

      settings.ui = {
        cbAutoscroll: DOM.id("dht-cfg-autoscroll")
      };

      // events

      settings.ui.cbAutoscroll.addEventListener("change", () => {
        STATE.settings.autoscroll = settings.ui.cbAutoscroll.checked;
      });

      setupStateChanged("settings");
    },

    hideSettings: function(){
      if (settings){
        DOM.removeElement(settings.overlay);
        DOM.removeElement(settings.ele);
        DOM.removeElement(settings.styles);
        settings = null;
      }
    }
  };

  return root;
})();
<|endoftext|>


<commit_before>import express from "express";
import {CourtCase, CourtCaseEvent} from "./db/models";

const router = express.Router();

const handleError = (res, message) => (err) => {
    console.error(message, err);
    res.status(500).send(message);
};

const casesBaseUrl = `/v1/cases`;

router.route(casesBaseUrl)
    .get((req, res) =>
        // Courtbot uses this endpoint
        CourtCase.query(qb => qb.whereRaw(`LOWER("caseNumber") LIKE LOWER(?)`, [`%${req.query.caseNumber}%`]))
            .fetchAll()
            .then(courtCases => res.send(courtCases)))
    .post((req, res) =>
        CourtCase.forge(req.body)
            .save(null)
            .then((createdCourtCase) => res.send(createdCourtCase))
            .catch(handleError(res, "Failed to create court case.")));

router.route(`${casesBaseUrl}/:courtCaseId`)
    .get((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .then(courtCase => res.send(courtCase))
            .catch(handleError(res, "Failed to fetch court case.")));

const getEventsByCaseId = (courtCaseId) => CourtCaseEvent.where({courtCaseId}).fetchAll();

router.route(`${casesBaseUrl}/:courtCaseId/events`)
    .post((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .courtCaseEvents().attach(req.body)
            .then((courtCase) => res.send(courtCase))
            .catch(handleError(res, "Failed to create court case events.")))
    .get((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .then(courtCase => getEventsByCaseId(courtCase.id))
            .then(courtCaseEvents => res.send(courtCaseEvents))
            .catch(handleError(res, "Failed to fetch events.")));

const getCaseByNumberAndDefendant = (caseNumber, defendant) =>
    CourtCase.query(qb => qb
        .whereRaw(`LOWER("caseNumber") LIKE LOWER(?)`, [`%${caseNumber}%`])
        .whereRaw(`LOWER("defendant") LIKE LOWER(?)`, [`%${defendant}%`])
    ).fetch();

router.route(`${casesBaseUrl}/:caseNumber/defendant/:defendant`)
    .get((req, res) =>
        // Courtbot uses this endpoint
        getCaseByNumberAndDefendant(req.params.caseNumber, req.params.defendant)
            .then(courtCase => console.info("courtCase=") || courtCase ? getEventsByCaseId(courtCase.id) : [])
            .then(courtCaseEvents => res.send(courtCaseEvents))
            .catch(handleError(res, "Failed to get events for case number and defendant.")));

export default router;
<commit_msg>Endpoint should be /events instead.<commit_after>import express from "express";
import {CourtCase, CourtCaseEvent} from "./db/models";

const router = express.Router();

const handleError = (res, message) => (err) => {
    console.error(message, err);
    res.status(500).send(message);
};

const casesBaseUrl = `/v1/cases`;

router.route(casesBaseUrl)
    .get((req, res) =>
        // Courtbot uses this endpoint
        CourtCase.query(qb => qb.whereRaw(`LOWER("caseNumber") LIKE LOWER(?)`, [`%${req.query.caseNumber}%`]))
            .fetchAll()
            .then(courtCases => res.send(courtCases)))
    .post((req, res) =>
        CourtCase.forge(req.body)
            .save(null)
            .then((createdCourtCase) => res.send(createdCourtCase))
            .catch(handleError(res, "Failed to create court case.")));

router.route(`${casesBaseUrl}/:courtCaseId`)
    .get((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .then(courtCase => res.send(courtCase))
            .catch(handleError(res, "Failed to fetch court case.")));

const getEventsByCaseId = (courtCaseId) => CourtCaseEvent.where({courtCaseId}).fetchAll();

router.route(`${casesBaseUrl}/:courtCaseId/events`)
    .post((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .courtCaseEvents().attach(req.body)
            .then((courtCase) => res.send(courtCase))
            .catch(handleError(res, "Failed to create court case events.")))
    .get((req, res) =>
        CourtCase.where({id: req.params.courtCaseId})
            .fetch()
            .then(courtCase => getEventsByCaseId(courtCase.id))
            .then(courtCaseEvents => res.send(courtCaseEvents))
            .catch(handleError(res, "Failed to fetch events.")));

const getCaseByNumberAndDefendant = (caseNumber, defendant) =>
    CourtCase.query(qb => qb
        .whereRaw(`LOWER("caseNumber") LIKE LOWER(?)`, [`%${caseNumber}%`])
        .whereRaw(`LOWER("defendant") LIKE LOWER(?)`, [`%${defendant}%`])
    ).fetch();

router.route(`${casesBaseUrl}/:caseNumber/defendant/:defendant/events`)
    .get((req, res) =>
        // Courtbot uses this endpoint
        getCaseByNumberAndDefendant(req.params.caseNumber, req.params.defendant)
            .then(courtCase => console.info("courtCase=") || courtCase ? getEventsByCaseId(courtCase.id) : [])
            .then(courtCaseEvents => res.send(courtCaseEvents))
            .catch(handleError(res, "Failed to get events for case number and defendant.")));

export default router;
<|endoftext|>


<commit_before>var json_driver  = require("./json-driver"),
    mongo_driver = require("./mongo-driver"),
    mbc          = require("mbc-common"),
    logger       = mbc.logger().addLogger('PLAYLISTS-DRIVER'),
    test_driver  = require("./test-driver");

exports = module.exports = function(type, config) {
    logger.info("Creating playlists driver for type [" + type + "]");

    if (type === 'json') {
        return new json_driver(config);
    } else if (type === 'mongo') {
        return new mongo_driver(config);
    } else if (type === 'test') {
        return new test_driver(config);
    }

    /******************************************************************
     * playlists_driver.prototype.setWindow(from, to)
     * this receives either a from=date, to=date or an object that is
     * interpreted as follows:
     * {
     *   from: date,
     *   to: date,
     *   span: int,
     * }
     * span should be in milliseconds
     * if from is absent, it is assumed to be `now`.
     * if either one of `to` or `span` is be present, the missing one is calculated
     * using `from` and the other one thus:
     * span = (to - from) // this is in miliseconds
     * to = from + span
     * if both are absent, the config file is used to get the span value
     * it returns the window object with the structure above (always complete)
     *******************************************************************/
    /******************************************************************
     * playlists_driver.prototype.getPlaylists(ops, callback)
     * ops is
     * {
     *    from: date
     *    to: date
     *    setWindow: boolean
     * }
     * with the same description as in setWindow
     ******************************************************************/

    var err = new Error("Unknown type of driver [" + type + "]");
    logger.error(err);
    throw err;
    return null;
};
<commit_msg>Removed reference to test_driver<commit_after>var json_driver  = require("./json-driver"),
    mongo_driver = require("./mongo-driver"),
    mbc          = require("mbc-common"),
    logger       = mbc.logger().addLogger('PLAYLISTS-DRIVER');

exports = module.exports = function(type, config) {
    logger.info("Creating playlists driver for type [" + type + "]");

    if (type === 'json') {
        return new json_driver(config);
    } else if (type === 'mongo') {
        return new mongo_driver(config);
    }

    /******************************************************************
     * playlists_driver.prototype.setWindow(from, to)
     * this receives either a from=date, to=date or an object that is
     * interpreted as follows:
     * {
     *   from: date,
     *   to: date,
     *   span: int,
     * }
     * span should be in milliseconds
     * if from is absent, it is assumed to be `now`.
     * if either one of `to` or `span` is be present, the missing one is calculated
     * using `from` and the other one thus:
     * span = (to - from) // this is in miliseconds
     * to = from + span
     * if both are absent, the config file is used to get the span value
     * it returns the window object with the structure above (always complete)
     *******************************************************************/
    /******************************************************************
     * playlists_driver.prototype.getPlaylists(ops, callback)
     * ops is
     * {
     *    from: date
     *    to: date
     *    setWindow: boolean
     * }
     * with the same description as in setWindow
     ******************************************************************/

    var err = new Error("Unknown type of driver [" + type + "]");
    logger.error(err);
    throw err;
    return null;
};
<|endoftext|>


<commit_before>var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://walkingdeadcomics.org/the-walking-dead-next-issue/', true);

xhr.onload = function () {
  var parser = new DOMParser();
  var doc = parser.parseFromString(this.responseText, 'text/html');

  var titleNode = doc.getElementById('p-title');
  var issueNumber = titleNode.innerText.substr(titleNode.innerText.indexOf('#')+1);
  var availabilityText = doc.querySelector('div.vision-contentbox-content.tt-content-style-black > span').innerText;
  var dateStart = availabilityText.substr(availabilityText.indexOf(':') + 1).trim();
  var array = dateStart.split(' ');
  var releaseDateString = array[0] + ' ' + array[1] + ' ' + array[2] + ' 09:00 GMT-0500';

  var releaseDate = new Date(releaseDateString);
  var wholeDaysUntilNextIssue = getDaysUntilDate(releaseDate);
  var issueCoverImageURL = generateIssueCoverURL(issueNumber);

  setComicVariablesInTasker(issueCoverImageURL, issueNumber, wholeDaysUntilNextIssue, releaseDateString);

  //signal to Tasker that the code is completed
  exit();
};

xhr.send();

function getDaysUntilDate(date) {
  var millisecondsUntilNextIssue = date - new Date();
  var days = millisecondsUntilNextIssue/1000/60/60/24;
  var wholeDaysUntilNextIssue = Math.floor(days);

  return wholeDaysUntilNextIssue;
}

function generateIssueCoverURL(issueNo) {
    if (issueNo.length === 1) {
	    issueNo = '0' + issueNo;
	}
	return ['http://i1.wp.com/walkingdeadcomics.org/wp-images/gallery/standard/', issueNo, '.jpg'].join('')
}

function setComicVariablesInTasker(issueCoverImageURL, issueNumber, wholeDaysUntilNextIssue, releaseDateString) {
  setLocalVariable('img',issueCoverImageURL);
  setLocalVariable('issueno',issueNumber);
  setLocalVariable('days',wholeDaysUntilNextIssue);
  setLocalVariable('date',releaseDateString);
}

function setLocalVariable(name, value, debug) {
    if (debug) {
        flash('setting ' + name + ' to ' + value);
	}
	setLocal(name, value);
};<commit_msg>Refactor date retrieval logic<commit_after>var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://walkingdeadcomics.org/the-walking-dead-next-issue/', true);

xhr.onload = function () {
  var parser = new DOMParser();
  var doc = parser.parseFromString(this.responseText, 'text/html');

  var titleNode = doc.getElementById('p-title');
  var issueNumber = titleNode.innerText.substr(titleNode.innerText.indexOf('#')+1);
  var availabilityText = doc.querySelector('div.vision-contentbox-content.tt-content-style-black > span').innerText;
  var dateStart = availabilityText.substr(availabilityText.indexOf(':') + 1).trim();
  var array = dateStart.split(' ');
  var releaseDateString = getIssueDateString(array[0], array[1], array[2]);

  var releaseDate = new Date(releaseDateString);
  var wholeDaysUntilNextIssue = getDaysUntilDate(releaseDate);
  var issueCoverImageURL = generateIssueCoverURL(issueNumber);

  setComicVariablesInTasker(issueCoverImageURL, issueNumber, wholeDaysUntilNextIssue, releaseDateString);

  //signal to Tasker that the code is completed
  exit();
};

xhr.send();

function getIssueDateString(month, day, year) {
    return [month, day, year, '09:00 GMT-0500'].join(' ');
}

function getDaysUntilDate(date) {
  var millisecondsUntilNextIssue = date - new Date();
  var days = millisecondsUntilNextIssue/1000/60/60/24;
  var wholeDaysUntilNextIssue = Math.floor(days);

  return wholeDaysUntilNextIssue;
}

function generateIssueCoverURL(issueNo) {
    if (issueNo.length === 1) {
	    issueNo = '0' + issueNo;
	}
	return ['http://i1.wp.com/walkingdeadcomics.org/wp-images/gallery/standard/', issueNo, '.jpg'].join('')
}

function setComicVariablesInTasker(issueCoverImageURL, issueNumber, wholeDaysUntilNextIssue, releaseDateString) {
  setLocalVariable('img',issueCoverImageURL);
  setLocalVariable('issueno',issueNumber);
  setLocalVariable('days',wholeDaysUntilNextIssue);
  setLocalVariable('date',releaseDateString);
}

function setLocalVariable(name, value, debug) {
    if (debug) {
        flash('setting ' + name + ' to ' + value);
	}
	setLocal(name, value);
};<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { Router, Route, Link } from 'react-router'

class Header extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    //this.loadCarbonAds();
    //this.renderConnectedDots();
  }

  loadCarbonAds() {
    let carbonAdsContainer = this.refs.carbonAds;
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=sahatyalkabovcom';
    script.id = '_carbonads_js';
    carbonAdsContainer.appendChild(script);
  }

  renderConnectedDots() {
    let canvas = this.refs.connectedDots;
    let ctx = canvas.getContext('2d');
    let colorDot = '#fff';
    let color = '#fff';

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.display = 'block';
    ctx.fillStyle = colorDot;
    ctx.lineWidth = .1;
    ctx.strokeStyle = color;

    var mousePosition = {
      x: 30 * canvas.width / 100,
      y: 30 * canvas.height / 100
    };

    var dots = {
      nb: 350,
      distance: 60,
      d_radius: 100,
      array: []
    };

    function Dot() {
      this.x = Math.random() * canvas.width;
      this.y = Math.random() * canvas.height;

      this.vx = -.5 + Math.random();
      this.vy = -.5 + Math.random();

      this.radius = Math.random();
    }

    Dot.prototype = {
      create: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        ctx.fill();
      },

      animate: function() {

        for (let i = 0; i < dots.nb; i++) {

          var dot = dots.array[i];

          if (dot.y < 0 || dot.y > canvas.height) {
            dot.vx = dot.vx;
            dot.vy = -dot.vy;
          }
          else if (dot.x < 0 || dot.x > canvas.width) {
            dot.vx = -dot.vx;
            dot.vy = dot.vy;
          }
          dot.x += dot.vx;
          dot.y += dot.vy;
        }
      },

      line: function() {
        for (let i = 0; i < dots.nb; i++) {
          for (let j = 0; j < dots.nb; j++) {
            var i_dot = dots.array[i];
            var j_dot = dots.array[j];

            if ((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > -dots.distance && (i_dot.y - j_dot.y) > -dots.distance) {
              if ((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > -dots.d_radius && (i_dot.y - mousePosition.y) > -dots.d_radius) {
                ctx.beginPath();
                ctx.moveTo(i_dot.x, i_dot.y);
                ctx.lineTo(j_dot.x, j_dot.y);
                ctx.stroke();
                ctx.closePath();
              }
            }
          }
        }
      }
    };

    function createDots() {
      let dot;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let i = 0; i < dots.nb; i++) {
        dots.array.push(new Dot());
        dot = dots.array[i];

        dot.create();
      }

      dot.line();
      dot.animate();
    }

    window.onmousemove = function(parameter) {
      mousePosition.x = parameter.pageX;
      mousePosition.y = parameter.pageY;
    };

    mousePosition.x = window.innerWidth / 2;
    mousePosition.y = window.innerHeight / 2;

    setInterval(createDots, 1000 / 30);
  }

  render() {
    return (

        <canvas ref="connectedDots"/>

Bug Reports

Contributing

Mega Boilerplate

            Simple and easy to use hand-crafted starter kits.

Demo 1

Demo 2

Demo 3

Demo 4

            Don't forget to  on GitHub if you liked this project!

    );
  }
}

export default Header;
<commit_msg>Updated header<commit_after>import React from 'react';
import cx from 'classnames';
import { Router, Route, Link } from 'react-router'

class Header extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    //this.loadCarbonAds();
    //this.renderConnectedDots();
  }

  loadCarbonAds() {
    let carbonAdsContainer = this.refs.carbonAds;
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = '//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=sahatyalkabovcom';
    script.id = '_carbonads_js';
    carbonAdsContainer.appendChild(script);
  }

  renderConnectedDots() {
    let canvas = this.refs.connectedDots;
    let ctx = canvas.getContext('2d');
    let colorDot = '#fff';
    let color = '#fff';

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.display = 'block';
    ctx.fillStyle = colorDot;
    ctx.lineWidth = .1;
    ctx.strokeStyle = color;

    var mousePosition = {
      x: 30 * canvas.width / 100,
      y: 30 * canvas.height / 100
    };

    var dots = {
      nb: 350,
      distance: 60,
      d_radius: 100,
      array: []
    };

    function Dot() {
      this.x = Math.random() * canvas.width;
      this.y = Math.random() * canvas.height;

      this.vx = -.5 + Math.random();
      this.vy = -.5 + Math.random();

      this.radius = Math.random();
    }

    Dot.prototype = {
      create: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        ctx.fill();
      },

      animate: function() {

        for (let i = 0; i < dots.nb; i++) {

          var dot = dots.array[i];

          if (dot.y < 0 || dot.y > canvas.height) {
            dot.vx = dot.vx;
            dot.vy = -dot.vy;
          }
          else if (dot.x < 0 || dot.x > canvas.width) {
            dot.vx = -dot.vx;
            dot.vy = dot.vy;
          }
          dot.x += dot.vx;
          dot.y += dot.vy;
        }
      },

      line: function() {
        for (let i = 0; i < dots.nb; i++) {
          for (let j = 0; j < dots.nb; j++) {
            var i_dot = dots.array[i];
            var j_dot = dots.array[j];

            if ((i_dot.x - j_dot.x) < dots.distance && (i_dot.y - j_dot.y) < dots.distance && (i_dot.x - j_dot.x) > -dots.distance && (i_dot.y - j_dot.y) > -dots.distance) {
              if ((i_dot.x - mousePosition.x) < dots.d_radius && (i_dot.y - mousePosition.y) < dots.d_radius && (i_dot.x - mousePosition.x) > -dots.d_radius && (i_dot.y - mousePosition.y) > -dots.d_radius) {
                ctx.beginPath();
                ctx.moveTo(i_dot.x, i_dot.y);
                ctx.lineTo(j_dot.x, j_dot.y);
                ctx.stroke();
                ctx.closePath();
              }
            }
          }
        }
      }
    };

    function createDots() {
      let dot;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let i = 0; i < dots.nb; i++) {
        dots.array.push(new Dot());
        dot = dots.array[i];

        dot.create();
      }

      dot.line();
      dot.animate();
    }

    window.onmousemove = function(parameter) {
      mousePosition.x = parameter.pageX;
      mousePosition.y = parameter.pageY;
    };

    mousePosition.x = window.innerWidth / 2;
    mousePosition.y = window.innerHeight / 2;

    setInterval(createDots, 1000 / 30);
  }

  render() {
    return (

        <canvas ref="connectedDots"/>

Report a bug

Contributing

Mega Boilerplate

            Simple and easy to use hand-crafted starter kits.

Demo 1

Demo 2

Demo 3

            Don't forget to  on GitHub if you liked this project!

    );
  }
}

export default Header;
<|endoftext|>


<commit_before>mini.Module(
	"engine/game"
)
.requires(
	"engine/loop"
)
.defines(function(Loop) {
	var Game = mini.Class.subclass({
		initialize: function() {
			console.log("NEW GAME");
			env.game = this;

			// prepare datGui
			this.datGui = new dat.GUI();

			// prepare stats
			this.stats = new Stats();
			$("body").prepend(this.stats.domElement);
			env.loop.add(this.stats, this.stats.update);
		}
	});

	return Game;
});
<commit_msg>attached stats.js as sticky bar<commit_after>mini.Module(
	"engine/game"
)
.requires(
	"engine/loop"
)
.defines(function(Loop) {
	var Game = mini.Class.subclass({
		initialize: function() {
			console.log("NEW GAME");
			env.game = this;

			// prepare datGui
			this.datGui = new dat.GUI();

			// prepare stats
			this.stats = new Stats();
			var stats = this.stats;
			$(this.stats.domElement)
				.css("position", "absolute")
				.css("top", $(window).scrollTop() + "px")
				.prependTo($("body"));
			$(window).scroll(function() {
			    $(stats.domElement).css('top', $(this).scrollTop() + "px");
			});
			env.loop.add(this.stats, this.stats.update);
		}
	});

	return Game;
});
<|endoftext|>


<commit_before>import React from 'react';

import FeaturesSet from '../sidebar/FeaturesSet';

class Sidebar extends React.Component {
  constructor(props) {
    super(props);
  }

  applyFilters(e){
    e.preventDefault();
    this.props.applyFilters();
  }

  render() {
    const featuresSets = this.props.features.map(item => {
      const isActive = (item.ref === this.props.activeFiltersSet) ? true : false;

      return <FeaturesSet
              key={item.title}
              title={item.title}
              colour={item.colour}
              filters={item.filters}
              isActive={isActive}
              onReset={this.props.onReset} />;
    });

    return (

FILTERS

          <button type="button" class="btn btn-success btn-block" onClick={this.applyFilters.bind(this)}>Apply</button>

        {featuresSets}

    );
  }

}

export default Sidebar;
<commit_msg>Improved Sidebar render time<commit_after>import React from 'react';

import FeaturesSet from '../sidebar/FeaturesSet';

class Sidebar extends React.Component {
  constructor(props) {
    super(props);
  }

  applyFilters(e){
    e.preventDefault();
    this.props.applyFilters();
  }

  shouldComponentUpdate(nextProps, nextState) {
    return nextProps.activeFiltersSet != this.props.activeFiltersSet;
  }

  render() {
    const featuresSets = this.props.features.map(item => {
      const isActive = (item.ref === this.props.activeFiltersSet) ? true : false;

      return <FeaturesSet
              key={item.ref}
              title={item.title}
              colour={item.colour}
              filters={item.filters}
              isActive={isActive}
              onReset={this.props.onReset}
              onChange={this.props.onChange}
               />;
    });

    return (

FILTERS

          <button type="button" class="btn btn-success btn-block" onClick={this.applyFilters.bind(this)}>Apply</button>

        {featuresSets}

    );
  }

}

export default Sidebar;
<|endoftext|>


<commit_before>var assert = require('assert')
var bufferutils = require('./bufferutils')
var crypto = require('./crypto')
var opcodes = require('./opcodes')
var scripts = require('./scripts')

var Address = require('./address')
var ECKey = require('./eckey')
var ECSignature = require('./ecsignature')
var Script = require('./script')

Transaction.DEFAULT_SEQUENCE = 0xffffffff
Transaction.SIGHASH_ALL = 0x01
Transaction.SIGHASH_NONE = 0x02
Transaction.SIGHASH_SINGLE = 0x03
Transaction.SIGHASH_ANYONECANPAY = 0x80

function Transaction() {
  this.version = 1
  this.locktime = 0
  this.ins = []
  this.outs = []
}

/**
 * Create a new txin.
 *
 * Can be called with any of:
 *
 * - A transaction and an index
 * - A transaction hash and an index
 *
 * Note that this method does not sign the created input.
 */
Transaction.prototype.addInput = function(tx, index, sequence) {
  if (sequence == undefined) sequence = Transaction.DEFAULT_SEQUENCE

  var hash

  if (typeof tx === 'string') {
    hash = new Buffer(tx, 'hex')

    // TxId hex is big-endian, we need little-endian
    Array.prototype.reverse.call(hash)

  } else if (tx instanceof Transaction) {
    hash = tx.getHash()

  } else {
    hash = tx
  }

  assert(Buffer.isBuffer(hash), 'Expected Transaction, txId or txHash, got ' + tx)
  assert.equal(hash.length, 32, 'Expected hash length of 32, got ' + hash.length)
  assert.equal(typeof index, 'number', 'Expected number index, got ' + index)

  return (this.ins.push({
    hash: hash,
    index: index,
    script: Script.EMPTY,
    sequence: sequence
  }) - 1)
}

/**
 * Create a new txout.
 *
 * Can be called with:
 *
 * - A base58 address string and a value
 * - An Address object and a value
 * - A scriptPubKey Script and a value
 */
Transaction.prototype.addOutput = function(scriptPubKey, value) {
  // Attempt to get a valid address if it's a base58 address string
  if (typeof scriptPubKey === 'string') {
    scriptPubKey = Address.fromBase58Check(scriptPubKey)
  }

  // Attempt to get a valid script if it's an Address object
  if (scriptPubKey instanceof Address) {
    var address = scriptPubKey

    scriptPubKey = address.toOutputScript()
  }

  return (this.outs.push({
    script: scriptPubKey,
    value: value,
  }) - 1)
}

Transaction.prototype.toBuffer = function () {
  var txInSize = this.ins.reduce(function(a, x) {
    return a + (40 + bufferutils.varIntSize(x.script.buffer.length) + x.script.buffer.length)
  }, 0)

  var txOutSize = this.outs.reduce(function(a, x) {
    return a + (8 + bufferutils.varIntSize(x.script.buffer.length) + x.script.buffer.length)
  }, 0)

  var buffer = new Buffer(
    8 +
    bufferutils.varIntSize(this.ins.length) +
    bufferutils.varIntSize(this.outs.length) +
    txInSize +
    txOutSize
  )

  var offset = 0
  function writeSlice(slice) {
    slice.copy(buffer, offset)
    offset += slice.length
  }
  function writeUInt32(i) {
    buffer.writeUInt32LE(i, offset)
    offset += 4
  }
  function writeUInt64(i) {
    bufferutils.writeUInt64LE(buffer, i, offset)
    offset += 8
  }
  function writeVarInt(i) {
    var n = bufferutils.writeVarInt(buffer, i, offset)
    offset += n
  }

  writeUInt32(this.version)
  writeVarInt(this.ins.length)

  this.ins.forEach(function(txin) {
    writeSlice(txin.hash)
    writeUInt32(txin.index)
    writeVarInt(txin.script.buffer.length)
    writeSlice(txin.script.buffer)
    writeUInt32(txin.sequence)
  })

  writeVarInt(this.outs.length)
  this.outs.forEach(function(txout) {
    writeUInt64(txout.value)
    writeVarInt(txout.script.buffer.length)
    writeSlice(txout.script.buffer)
  })

  writeUInt32(this.locktime)

  return buffer
}

Transaction.prototype.toHex = function() {
  return this.toBuffer().toString('hex')
}

/**
 * Hash transaction for signing a specific input.
 *
 * Bitcoin uses a different hash for each signed transaction input. This
 * method copies the transaction, makes the necessary changes based on the
 * hashType, serializes and finally hashes the result. This hash can then be
 * used to sign the transaction input in question.
 */
Transaction.prototype.hashForSignature = function(prevOutScript, inIndex, hashType) {
  assert(inIndex >= 0, 'Invalid vin index')
  assert(inIndex < this.ins.length, 'Invalid vin index')
  assert(prevOutScript instanceof Script, 'Invalid Script object')

  var txTmp = this.clone()
  var hashScript = prevOutScript.without(opcodes.OP_CODESEPARATOR)

  // Blank out other inputs' signatures
  txTmp.ins.forEach(function(txin) {
    txin.script = Script.EMPTY
  })
  txTmp.ins[inIndex].script = hashScript

  var hashTypeModifier = hashType & 0x1f
  if (hashTypeModifier === Transaction.SIGHASH_NONE) {
    assert(false, 'SIGHASH_NONE not yet supported')

  } else if (hashTypeModifier === Transaction.SIGHASH_SINGLE) {
    assert(false, 'SIGHASH_SINGLE not yet supported')

  }

  if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
    assert(false, 'SIGHASH_ANYONECANPAY not yet supported')
  }

  var hashTypeBuffer = new Buffer(4)
  hashTypeBuffer.writeInt32LE(hashType, 0)

  var buffer = Buffer.concat([txTmp.toBuffer(), hashTypeBuffer])
  return crypto.hash256(buffer)
}

Transaction.prototype.getHash = function () {
  return crypto.hash256(this.toBuffer())
}

Transaction.prototype.getId = function () {
  var buffer = this.getHash()

  // Big-endian is used for TxHash
  Array.prototype.reverse.call(buffer)

  return buffer.toString('hex')
}

Transaction.prototype.clone = function () {
  var newTx = new Transaction()
  newTx.version = this.version
  newTx.locktime = this.locktime

  newTx.ins = this.ins.map(function(txin) {
    return {
      hash: txin.hash,
      index: txin.index,
      script: txin.script,
      sequence: txin.sequence
    }
  })

  newTx.outs = this.outs.map(function(txout) {
    return {
      script: txout.script,
      value: txout.value
    }
  })

  return newTx
}

Transaction.fromBuffer = function(buffer) {
  var offset = 0
  function readSlice(n) {
    offset += n
    return buffer.slice(offset - n, offset)
  }
  function readUInt32() {
    var i = buffer.readUInt32LE(offset)
    offset += 4
    return i
  }
  function readUInt64() {
    var i = bufferutils.readUInt64LE(buffer, offset)
    offset += 8
    return i
  }
  function readVarInt() {
    var vi = bufferutils.readVarInt(buffer, offset)
    offset += vi.size
    return vi.number
  }

  var tx = new Transaction()
  tx.version = readUInt32()

  var vinLen = readVarInt()
  for (var i = 0; i < vinLen; ++i) {
    var hash = readSlice(32)
    var vout = readUInt32()
    var scriptLen = readVarInt()
    var script = readSlice(scriptLen)
    var sequence = readUInt32()

    tx.ins.push({
      hash: hash,
      index: vout,
      script: Script.fromBuffer(script),
      sequence: sequence
    })
  }

  var voutLen = readVarInt()
  for (i = 0; i < voutLen; ++i) {
    var value = readUInt64()
    var scriptLen = readVarInt()
    var script = readSlice(scriptLen)

    tx.outs.push({
      value: value,
      script: Script.fromBuffer(script)
    })
  }

  tx.locktime = readUInt32()
  assert.equal(offset, buffer.length, 'Transaction has unexpected data')

  return tx
}

Transaction.fromHex = function(hex) {
  return Transaction.fromBuffer(new Buffer(hex, 'hex'))
}

/**
 * Signs a pubKeyHash output at some index with the given key
 */
Transaction.prototype.sign = function(index, privKey, hashType) {
  var prevOutScript = privKey.pub.getAddress().toOutputScript()
  var signature = this.signInput(index, prevOutScript, privKey, hashType)

  // FIXME: Assumed prior TX was pay-to-pubkey-hash
  var scriptSig = scripts.pubKeyHashInput(signature, privKey.pub)
  this.setInputScript(index, scriptSig)
}

Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) {
  hashType = hashType || Transaction.SIGHASH_ALL

  var hash = this.hashForSignature(prevOutScript, index, hashType)
  var signature = privKey.sign(hash)

  return signature.toScriptSignature(hashType)
}

Transaction.prototype.setInputScript = function(index, script) {
  this.ins[index].script = script
}

// FIXME: could be validateInput(index, prevTxOut, pub)
Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, buffer) {
  var parsed = ECSignature.parseScriptSignature(buffer)
  var hash = this.hashForSignature(prevOutScript, index, parsed.hashType)

  return pubKey.verify(hash, parsed.signature)
}

module.exports = Transaction
<commit_msg>Transaction: add assertion that scriptPubKey exists<commit_after>var assert = require('assert')
var bufferutils = require('./bufferutils')
var crypto = require('./crypto')
var opcodes = require('./opcodes')
var scripts = require('./scripts')

var Address = require('./address')
var ECKey = require('./eckey')
var ECSignature = require('./ecsignature')
var Script = require('./script')

Transaction.DEFAULT_SEQUENCE = 0xffffffff
Transaction.SIGHASH_ALL = 0x01
Transaction.SIGHASH_NONE = 0x02
Transaction.SIGHASH_SINGLE = 0x03
Transaction.SIGHASH_ANYONECANPAY = 0x80

function Transaction() {
  this.version = 1
  this.locktime = 0
  this.ins = []
  this.outs = []
}

/**
 * Create a new txin.
 *
 * Can be called with any of:
 *
 * - A transaction and an index
 * - A transaction hash and an index
 *
 * Note that this method does not sign the created input.
 */
Transaction.prototype.addInput = function(tx, index, sequence) {
  if (sequence == undefined) sequence = Transaction.DEFAULT_SEQUENCE

  var hash

  if (typeof tx === 'string') {
    hash = new Buffer(tx, 'hex')

    // TxId hex is big-endian, we need little-endian
    Array.prototype.reverse.call(hash)

  } else if (tx instanceof Transaction) {
    hash = tx.getHash()

  } else {
    hash = tx
  }

  assert(Buffer.isBuffer(hash), 'Expected Transaction, txId or txHash, got ' + tx)
  assert.equal(hash.length, 32, 'Expected hash length of 32, got ' + hash.length)
  assert.equal(typeof index, 'number', 'Expected number index, got ' + index)

  return (this.ins.push({
    hash: hash,
    index: index,
    script: Script.EMPTY,
    sequence: sequence
  }) - 1)
}

/**
 * Create a new txout.
 *
 * Can be called with:
 *
 * - A base58 address string and a value
 * - An Address object and a value
 * - A scriptPubKey Script and a value
 */
Transaction.prototype.addOutput = function(scriptPubKey, value) {
  // Attempt to get a valid address if it's a base58 address string
  if (typeof scriptPubKey === 'string') {
    scriptPubKey = Address.fromBase58Check(scriptPubKey)
  }

  // Attempt to get a valid script if it's an Address object
  if (scriptPubKey instanceof Address) {
    var address = scriptPubKey

    scriptPubKey = address.toOutputScript()
  }

  assert(scriptPubKey instanceof Script, 'Expected Address or Script, got ' + scriptPubKey)

  return (this.outs.push({
    script: scriptPubKey,
    value: value
  }) - 1)
}

Transaction.prototype.toBuffer = function () {
  var txInSize = this.ins.reduce(function(a, x) {
    return a + (40 + bufferutils.varIntSize(x.script.buffer.length) + x.script.buffer.length)
  }, 0)

  var txOutSize = this.outs.reduce(function(a, x) {
    return a + (8 + bufferutils.varIntSize(x.script.buffer.length) + x.script.buffer.length)
  }, 0)

  var buffer = new Buffer(
    8 +
    bufferutils.varIntSize(this.ins.length) +
    bufferutils.varIntSize(this.outs.length) +
    txInSize +
    txOutSize
  )

  var offset = 0
  function writeSlice(slice) {
    slice.copy(buffer, offset)
    offset += slice.length
  }
  function writeUInt32(i) {
    buffer.writeUInt32LE(i, offset)
    offset += 4
  }
  function writeUInt64(i) {
    bufferutils.writeUInt64LE(buffer, i, offset)
    offset += 8
  }
  function writeVarInt(i) {
    var n = bufferutils.writeVarInt(buffer, i, offset)
    offset += n
  }

  writeUInt32(this.version)
  writeVarInt(this.ins.length)

  this.ins.forEach(function(txin) {
    writeSlice(txin.hash)
    writeUInt32(txin.index)
    writeVarInt(txin.script.buffer.length)
    writeSlice(txin.script.buffer)
    writeUInt32(txin.sequence)
  })

  writeVarInt(this.outs.length)
  this.outs.forEach(function(txout) {
    writeUInt64(txout.value)
    writeVarInt(txout.script.buffer.length)
    writeSlice(txout.script.buffer)
  })

  writeUInt32(this.locktime)

  return buffer
}

Transaction.prototype.toHex = function() {
  return this.toBuffer().toString('hex')
}

/**
 * Hash transaction for signing a specific input.
 *
 * Bitcoin uses a different hash for each signed transaction input. This
 * method copies the transaction, makes the necessary changes based on the
 * hashType, serializes and finally hashes the result. This hash can then be
 * used to sign the transaction input in question.
 */
Transaction.prototype.hashForSignature = function(prevOutScript, inIndex, hashType) {
  assert(inIndex >= 0, 'Invalid vin index')
  assert(inIndex < this.ins.length, 'Invalid vin index')
  assert(prevOutScript instanceof Script, 'Invalid Script object')

  var txTmp = this.clone()
  var hashScript = prevOutScript.without(opcodes.OP_CODESEPARATOR)

  // Blank out other inputs' signatures
  txTmp.ins.forEach(function(txin) {
    txin.script = Script.EMPTY
  })
  txTmp.ins[inIndex].script = hashScript

  var hashTypeModifier = hashType & 0x1f
  if (hashTypeModifier === Transaction.SIGHASH_NONE) {
    assert(false, 'SIGHASH_NONE not yet supported')

  } else if (hashTypeModifier === Transaction.SIGHASH_SINGLE) {
    assert(false, 'SIGHASH_SINGLE not yet supported')

  }

  if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
    assert(false, 'SIGHASH_ANYONECANPAY not yet supported')
  }

  var hashTypeBuffer = new Buffer(4)
  hashTypeBuffer.writeInt32LE(hashType, 0)

  var buffer = Buffer.concat([txTmp.toBuffer(), hashTypeBuffer])
  return crypto.hash256(buffer)
}

Transaction.prototype.getHash = function () {
  return crypto.hash256(this.toBuffer())
}

Transaction.prototype.getId = function () {
  var buffer = this.getHash()

  // Big-endian is used for TxHash
  Array.prototype.reverse.call(buffer)

  return buffer.toString('hex')
}

Transaction.prototype.clone = function () {
  var newTx = new Transaction()
  newTx.version = this.version
  newTx.locktime = this.locktime

  newTx.ins = this.ins.map(function(txin) {
    return {
      hash: txin.hash,
      index: txin.index,
      script: txin.script,
      sequence: txin.sequence
    }
  })

  newTx.outs = this.outs.map(function(txout) {
    return {
      script: txout.script,
      value: txout.value
    }
  })

  return newTx
}

Transaction.fromBuffer = function(buffer) {
  var offset = 0
  function readSlice(n) {
    offset += n
    return buffer.slice(offset - n, offset)
  }
  function readUInt32() {
    var i = buffer.readUInt32LE(offset)
    offset += 4
    return i
  }
  function readUInt64() {
    var i = bufferutils.readUInt64LE(buffer, offset)
    offset += 8
    return i
  }
  function readVarInt() {
    var vi = bufferutils.readVarInt(buffer, offset)
    offset += vi.size
    return vi.number
  }

  var tx = new Transaction()
  tx.version = readUInt32()

  var vinLen = readVarInt()
  for (var i = 0; i < vinLen; ++i) {
    var hash = readSlice(32)
    var vout = readUInt32()
    var scriptLen = readVarInt()
    var script = readSlice(scriptLen)
    var sequence = readUInt32()

    tx.ins.push({
      hash: hash,
      index: vout,
      script: Script.fromBuffer(script),
      sequence: sequence
    })
  }

  var voutLen = readVarInt()
  for (i = 0; i < voutLen; ++i) {
    var value = readUInt64()
    var scriptLen = readVarInt()
    var script = readSlice(scriptLen)

    tx.outs.push({
      value: value,
      script: Script.fromBuffer(script)
    })
  }

  tx.locktime = readUInt32()
  assert.equal(offset, buffer.length, 'Transaction has unexpected data')

  return tx
}

Transaction.fromHex = function(hex) {
  return Transaction.fromBuffer(new Buffer(hex, 'hex'))
}

/**
 * Signs a pubKeyHash output at some index with the given key
 */
Transaction.prototype.sign = function(index, privKey, hashType) {
  var prevOutScript = privKey.pub.getAddress().toOutputScript()
  var signature = this.signInput(index, prevOutScript, privKey, hashType)

  // FIXME: Assumed prior TX was pay-to-pubkey-hash
  var scriptSig = scripts.pubKeyHashInput(signature, privKey.pub)
  this.setInputScript(index, scriptSig)
}

Transaction.prototype.signInput = function(index, prevOutScript, privKey, hashType) {
  hashType = hashType || Transaction.SIGHASH_ALL

  var hash = this.hashForSignature(prevOutScript, index, hashType)
  var signature = privKey.sign(hash)

  return signature.toScriptSignature(hashType)
}

Transaction.prototype.setInputScript = function(index, script) {
  this.ins[index].script = script
}

// FIXME: could be validateInput(index, prevTxOut, pub)
Transaction.prototype.validateInput = function(index, prevOutScript, pubKey, buffer) {
  var parsed = ECSignature.parseScriptSignature(buffer)
  var hash = this.hashForSignature(prevOutScript, index, parsed.hashType)

  return pubKey.verify(hash, parsed.signature)
}

module.exports = Transaction
<|endoftext|>


<commit_before>define (["./_default-component-plugin"], function (DefaultPlugin) {
	var IgniteUIGridPlugin = IgniteUIGridPlugin || DefaultPlugin.extend({
		init: function (options) {
			this._super(options);
		},
		getName: function () {
			return "igGrid";
		},
		_getWidgetName: function () {
			return "igGrid";
		},
		getMarkup: function (descriptor) {
			return "

";
		},
		getCodeEditorScriptSnippet: function (descriptor) {
			var code = "";
			var opts = descriptor.options;
			var lineCount = 4;
			var orderedReturnProps = [];
			var xtraMarkup = "\t\t\t\t\tfeatures: []";
			//A.T. - we can either drop with no features in the code editor
			// or an empty array - empty arr makes it easier to manage with markers
			code = "\t\t\t\t$(\"#" + descriptor.id + "\").igGrid({\n" + xtraMarkup;
			//	"\t\t\t\t\theight: " + opts.height + ",\n" +
			//	"\t\t\t\t\twidth: " + opts.width + xtraMarkup;
			/*
			orderedReturnProps.push({
				name: "height",
				value: opts.height,
				type: "number"
			});
			orderedReturnProps.push({
				name: "width",
				value: opts.width,
				type: "number"
			});
			*/
			if (descriptor.data && window[descriptor.data]) {
				code += ",\n\t\t\t\t\tdataSource: " + descriptor.data;
				orderedReturnProps.push({
					name: "dataSource",
					value: descriptor.data,
					type: "literal"
				});
			}
			var props = this.settings.packageInfo.components[descriptor.type].properties;
			for (var key in opts) {
			//	if (opts.hasOwnProperty(key) && key !== "dataSource" && key !== "height" && key !== "width") {
				if (opts.hasOwnProperty(key) && key !== "dataSource" && key !== "features") {
					orderedReturnProps.push({
						name: key,
						value: opts[key],
						type: props[key].type
					});
					if (props[key].type === "string") {
						code += ",\n\t\t\t\t\t" + key + ": \"" + opts[key] + "\"";
						orderedReturnProps[orderedReturnProps.length - 1].type = "string";
					} else {
						code += ",\n\t\t\t\t\t" + key + ": " + opts[key];
						orderedReturnProps[orderedReturnProps.length - 1].type = "literal";
					}
					lineCount++;
				}
			}
			code += "\n\t\t\t\t});\n";
			return {
				codeString: code,
				lineCount: lineCount,
				orderedProps: orderedReturnProps
			};
			//return this.evalTemplate("grid.code.js", descriptor);
		},
		addExtraMarkers: function (descriptor) {
			this._super(descriptor);
			// we don't want to hardcode this value but find it in the current range
			// it may well happen that someone adds lots of options and extra code *above* the features or any other object
			var featuresRange = this.settings.editor.find("features", {start: descriptor.marker.range.start});
			featuresRange = new descriptor.rclass(featuresRange.start.row, 0, featuresRange.start.row + 1, 0);
			featuresRange.start = this.settings.editor.getSession().doc.createAnchor(featuresRange.start);
			featuresRange.end = this.settings.editor.getSession().doc.createAnchor(featuresRange.end);
			if (!descriptor.marker.extraMarkers.options) {
				descriptor.marker.extraMarkers.options = {};
			}
			descriptor.marker.extraMarkers.options.features = {marker: featuresRange};
		},
		customPropertyEditor: function (descriptor) {
			if (this._super && this._super(descriptor)) {
				return;
			}
			// columns, features, dataSource, etc. - also reuse those UIs
			// when something gets changed in this editor, we want to also update the code editor as well as the component itself
			var p = descriptor.propName, rec = descriptor, packageInfo = this.settings.packageInfo, session = descriptor.editorSession, $this = this;
			if (p === "features") {
				// open features editor
				var container = this.openCollectionEditor(descriptor);
				var ddtmpl = $("#dropdownTemplate").html();
				var texts = [];
				// TODO: Refactor drop down logic into ide-ui
				var Mustache = require("mustache");
				for (var i in rec.schema) {
					if (rec.schema.hasOwnProperty(i)) {
						texts.push({
							key: i,
							text: i,
							title: rec.schema[i].description // tooltip
						});
					}
				}
				var dd_id = "features_dropDown";
				var propData = {
					dropdownId: dd_id,
					titleText: "Change property value",
					closeOnClick: true,
					defaultVal: rec.propValue,
					defaultKey: rec.propValue,
					itemTexts: texts
				};
				var enumHtml = Mustache.to_html(ddtmpl, propData);
				var td = $("
").insertBefore(container.find("a.add-item"));
				container.find("a.add-item").addClass("add-feature").text("Add");
				td.html(enumHtml).addClass("enum-prop-edit");
				var label = td.find(".ig-dropdown-label");
				label.css({
					display: "inline-block",
					width: td.innerWidth() - td.find(".input-group-btn > button").outerWidth()
				});
				label.toggleClass("non-default-val", rec.propValue !== rec.defaultValue);
				td.find(".layout-menu").css({
					"min-height": 0
				});
				td.find(".dropdown-container").css({
					position: "absolute",
					display: "none",
					"z-index": 20000
				}).addClass("adorner-prop-menu").appendTo("body");
				td.find(".ig-dropdown-label,.ig-dropdown-button").on("click", function (event) {
					var target = $(event.target), dd = target.closest(".ig-dropdown");
					var ddlist = dd.find(".dropdown-container");
					if (ddlist.length === 0) {
						ddlist = $("body").find(".dropdown-container[data-id=" + dd.attr("data-id") + "]");
					}
					$this.settings.ide._toggleDropDown(dd, ddlist);
					if (ddlist.is(":visible")) {
						$("input.ig-hidden").attr("data-id", dd.attr("data-id")).focus();
					}
					event.stopPropagation();
					event.preventDefault();
				})
				$(".dropdown-container[data-id=" + dd_id + "]").on("mouseup", "ul > li", function (event) {
					var $this = $(this), ddlist = $(event.target).closest(".dropdown-container");
					var dd = $("body").find(".ig-dropdown[data-id=" + ddlist.attr("data-id") + "]");
					var oldVal = label.attr("data-key");
					label.text($this.attr("data-text")).attr("data-key", $this.attr("data-key"));
					descriptor.ide._toggleDropDown(dd, ddlist);
				}).on("mousedown click", "ul > li", function (event) {
					event.preventDefault();
					event.stopPropagation();
				});

				container.off();
				container.on("click", ".add-item", function () {
					var label = td.find(".ig-dropdown-label"),
						labelText = label.text();
					if (!labelText) {
						return;
					}
					var value = $this.getPropValue(descriptor),
						schema;
					try {
						schema = $this.loadFeatureInfo(descriptor, labelText);
					} catch (e) {
						console.error("Could not load feature info for '" + labelText + "'. Error: " + e);
					}
					var descr = {
						oldPropValue: value,
						schema: schema
					};
					if (!value) {
						value = [];
					}
					value.push({
						name: labelText
					});
					label.text("");
					$(".dropdown-container[data-id=" + dd_id + "] li[data-text=" + labelText + "]").remove();
					$("
" + labelText + "
").insertBefore($(this).closest("li"));
					descr.propValue = value;
					descriptor.updateFunction(descr);
					event.stopPropagation();
					return false;
				});
				container.on('click', '.adorner-collection-edit', function (event) {
					var labelText = $(this).text(),
						propertyExplorer = require("ide-propertyexplorer"),
						container = $("

").insertAfter(descriptor.ide.currentAdorner()),
						editor = $('

').appendTo(container),
						options = $.extend({}, descriptor),
						property,
						count = 0,
						schema,
						updateComp = function (descr) {
							var features = $this.getPropValue(descriptor),
								i,
								feature,
								schema;
							for (i = 0; i < features.length; i++ ) {
								if (features[i].name === labelText) {
									feature = features[i];
									break;
								}
							}
							if (!feature) {
								return;
							}
							feature[descr.propName] = descr.propValue;
							var opt = descriptor;
							if (descr.handlerFlag) {
								opt.args = descr.args;
								opt.handlerFlag = true;
								opt.funcName = descr.funcName;
							}
							opt.propValue = features;
							schema = $this.settings.packageInfo.components[descriptor.type].properties.features.components;
							schema.heterogeneous = true;
							opt.schema = schema;
							// updateComponent also updates the code editor
							if (descriptor.updateFunction) {
								descriptor.updateFunction(opt);
							} else {
								descriptor.provider.updateComponent(opt);
							}
						};
					options.id = "featureEditor";
					options.containerId = "feature";
					options.parent = editor;
					options.data = [];
					options.updateFunction = updateComp;
					try {
						schema = $this.loadFeatureInfo(descriptor, labelText);
					} catch (e) {
						console.error("Could not load feature info for '" + labelText + "'. Error: " + e);
					}
					for (property in schema) {
						if (schema.hasOwnProperty(property) && property !== "name") {
							options.data.push({
								id: count++,
								propName: property,
								defaultValue: schema[property].defaultValue,
								propValue: schema[property].defaultValue,
								propType: schema[property].type,
								description: schema[property].description,
								valueOptions: schema[property].valueOptions,
								displayProp: schema[property].designerDisplayProperty,
								args: schema[property].args,
								schema: schema[property].schema
							});
						}
					}
					// render and open a property explorer
					propertyExplorer(options);
					descriptor.ide.adornerMoveLeft();
					event.stopPropagation();
					return false;
				});
				container.on('click', '.delete-item', function (event, ui) {
					var labelText = $(this).closest("li").text(), value = $this.getPropValue(descriptor), schema, i, opt = $.extend({}, descriptor);
					$(this).closest('li').remove();
					for (i = 0; i < value.length; i++) {
						if (value[i].name === labelText) {
							value.splice(i, 1);
							break;
						}
					}
					schema = $this.settings.packageInfo.components[opt.type].properties.features.components;
					opt.propValue = value;
					opt.propType = "array";
					schema.heterogeneous = true;
					opt.schema = schema;
					$("
" + labelText + "
").attr({
							"data-text": labelText,
							"data-key": labelText,
							"title": labelText
						}).appendTo(".dropdown-container[data-id=" + dd_id + "] ul");
					descriptor.provider.updateComponent(opt);
				});
			}
		},
		loadFeatureInfo: function (descriptor, name) {
			var features = this.settings.packageInfo.components[descriptor.type].properties.features,
				feature = features.components[name],
				schema;
			if (feature && feature.properties) {
				schema = feature.properties;
			} else {
				var url = this.settings.packageInfo.configPath + "/" + descriptor.schema[name].schemaRef + ".json";
				// load metadata for every feature
				var json = $.ajax({ // TODO: we could refactor this usage into a shared func on package info perhaps
					type: "GET",
					url: url,
					cache: true,
					dataType: "json",
					async: false
				});
				features.components[name] = $.parseJSON(json.responseText);
				schema = features.components[name].properties;
			}
			return schema;
		},
		setPropertyExplorerValueContents: function (descriptor) {
			if (descriptor.propName === "features") {
				descriptor.td.html("Configure...");
			} else if (this._super) {
				this._super(descriptor);
			}
		}
		/*
		render: function(descriptor) {
			// THIS IS WHERE WE PUT FULLY CUSTOM EDITORS FOR COMPONENTS
		},
		*/
	});
	return IgniteUIGridPlugin;
});
<commit_msg>Refactoring the features editor into three separate functions.<commit_after>define (["./_default-component-plugin"], function (DefaultPlugin) {
	var IgniteUIGridPlugin = IgniteUIGridPlugin || DefaultPlugin.extend({
		init: function (options) {
			this._super(options);
		},
		getName: function () {
			return "igGrid";
		},
		_getWidgetName: function () {
			return "igGrid";
		},
		getMarkup: function (descriptor) {
			return "

";
		},
		getCodeEditorScriptSnippet: function (descriptor) {
			var code = "";
			var opts = descriptor.options;
			var lineCount = 4;
			var orderedReturnProps = [];
			var xtraMarkup = "\t\t\t\t\tfeatures: []";
			//A.T. - we can either drop with no features in the code editor
			// or an empty array - empty arr makes it easier to manage with markers
			code = "\t\t\t\t$(\"#" + descriptor.id + "\").igGrid({\n" + xtraMarkup;
			//	"\t\t\t\t\theight: " + opts.height + ",\n" +
			//	"\t\t\t\t\twidth: " + opts.width + xtraMarkup;
			/*
			orderedReturnProps.push({
				name: "height",
				value: opts.height,
				type: "number"
			});
			orderedReturnProps.push({
				name: "width",
				value: opts.width,
				type: "number"
			});
			*/
			if (descriptor.data && window[descriptor.data]) {
				code += ",\n\t\t\t\t\tdataSource: " + descriptor.data;
				orderedReturnProps.push({
					name: "dataSource",
					value: descriptor.data,
					type: "literal"
				});
			}
			var props = this.settings.packageInfo.components[descriptor.type].properties;
			for (var key in opts) {
			//	if (opts.hasOwnProperty(key) && key !== "dataSource" && key !== "height" && key !== "width") {
				if (opts.hasOwnProperty(key) && key !== "dataSource" && key !== "features") {
					orderedReturnProps.push({
						name: key,
						value: opts[key],
						type: props[key].type
					});
					if (props[key].type === "string") {
						code += ",\n\t\t\t\t\t" + key + ": \"" + opts[key] + "\"";
						orderedReturnProps[orderedReturnProps.length - 1].type = "string";
					} else {
						code += ",\n\t\t\t\t\t" + key + ": " + opts[key];
						orderedReturnProps[orderedReturnProps.length - 1].type = "literal";
					}
					lineCount++;
				}
			}
			code += "\n\t\t\t\t});\n";
			return {
				codeString: code,
				lineCount: lineCount,
				orderedProps: orderedReturnProps
			};
			//return this.evalTemplate("grid.code.js", descriptor);
		},
		addExtraMarkers: function (descriptor) {
			this._super(descriptor);
			// we don't want to hardcode this value but find it in the current range
			// it may well happen that someone adds lots of options and extra code *above* the features or any other object
			var featuresRange = this.settings.editor.find("features", {start: descriptor.marker.range.start});
			featuresRange = new descriptor.rclass(featuresRange.start.row, 0, featuresRange.start.row + 1, 0);
			featuresRange.start = this.settings.editor.getSession().doc.createAnchor(featuresRange.start);
			featuresRange.end = this.settings.editor.getSession().doc.createAnchor(featuresRange.end);
			if (!descriptor.marker.extraMarkers.options) {
				descriptor.marker.extraMarkers.options = {};
			}
			descriptor.marker.extraMarkers.options.features = {marker: featuresRange};
		},
		customPropertyEditor: function (descriptor) {
			if (this._super && this._super(descriptor)) {
				return;
			}
			// columns, features, dataSource, etc. - also reuse those UIs
			// when something gets changed in this editor, we want to also update the code editor as well as the component itself
			var p = descriptor.propName, rec = descriptor, packageInfo = this.settings.packageInfo, session = descriptor.editorSession, $this = this;
			if (p === "features") {
				// open features editor
				var container = this.openCollectionEditor(descriptor);
				var ddtmpl = $("#dropdownTemplate").html();
				var texts = [];
				// TODO: Refactor drop down logic into ide-ui
				var Mustache = require("mustache");
				for (var i in rec.schema) {
					if (rec.schema.hasOwnProperty(i)) {
						texts.push({
							key: i,
							text: i,
							title: rec.schema[i].description // tooltip
						});
					}
				}
				var dd_id = "features_dropDown";
				var propData = {
					dropdownId: dd_id,
					titleText: "Change property value",
					closeOnClick: true,
					defaultVal: rec.propValue,
					defaultKey: rec.propValue,
					itemTexts: texts
				};
				var enumHtml = Mustache.to_html(ddtmpl, propData);
				var td = $("
").insertBefore(container.find("a.add-item"));
				container.find("a.add-item").addClass("add-feature").text("Add");
				td.html(enumHtml).addClass("enum-prop-edit");
				var label = td.find(".ig-dropdown-label");
				label.css({
					display: "inline-block",
					width: td.innerWidth() - td.find(".input-group-btn > button").outerWidth()
				});
				label.toggleClass("non-default-val", rec.propValue !== rec.defaultValue);
				td.find(".layout-menu").css({
					"min-height": 0
				});
				td.find(".dropdown-container").css({
					position: "absolute",
					display: "none",
					"z-index": 20000
				}).addClass("adorner-prop-menu").appendTo("body");
				td.find(".ig-dropdown-label,.ig-dropdown-button").on("click", function (event) {
					var target = $(event.target), dd = target.closest(".ig-dropdown");
					var ddlist = dd.find(".dropdown-container");
					if (ddlist.length === 0) {
						ddlist = $("body").find(".dropdown-container[data-id=" + dd.attr("data-id") + "]");
					}
					$this.settings.ide._toggleDropDown(dd, ddlist);
					if (ddlist.is(":visible")) {
						$("input.ig-hidden").attr("data-id", dd.attr("data-id")).focus();
					}
					event.stopPropagation();
					event.preventDefault();
				})
				$(".dropdown-container[data-id=" + dd_id + "]").on("mouseup", "ul > li", function (event) {
					var $this = $(this), ddlist = $(event.target).closest(".dropdown-container");
					var dd = $("body").find(".ig-dropdown[data-id=" + ddlist.attr("data-id") + "]");
					var oldVal = label.attr("data-key");
					label.text($this.attr("data-text")).attr("data-key", $this.attr("data-key"));
					descriptor.ide._toggleDropDown(dd, ddlist);
				}).on("mousedown click", "ul > li", function (event) {
					event.preventDefault();
					event.stopPropagation();
				});

				container.off();
				container.on("click", ".add-item", function (event) {
					$this.addFeatureHandler(descriptor, td, $(this).closest("li"), dd_id);
					event.stopPropagation();
					return false;
				});
				container.on('click', '.adorner-collection-edit', function (event) {
					$this.editFeatureHandler(descriptor, $(this));
					event.stopPropagation();
					return false;
				});
				container.on('click', '.delete-item', function (event) {
					$this.deleteFeatureHandler(descriptor, $(this).closest("li"), dd_id);
				});
			}
		},
		loadFeatureInfo: function (descriptor, name) {
			var features = this.settings.packageInfo.components[descriptor.type].properties.features,
				feature = features.components[name],
				schema;
			if (feature && feature.properties) {
				schema = feature.properties;
			} else {
				var url = this.settings.packageInfo.configPath + "/" + descriptor.schema[name].schemaRef + ".json";
				// load metadata for every feature
				var json = $.ajax({ // TODO: we could refactor this usage into a shared func on package info perhaps
					type: "GET",
					url: url,
					cache: true,
					dataType: "json",
					async: false
				});
				features.components[name] = $.parseJSON(json.responseText);
				schema = features.components[name].properties;
			}
			return schema;
		},
		addFeatureHandler: function (descriptor, td, target, id) {
			var label = td.find(".ig-dropdown-label"),
				labelText = label.text();
			if (!labelText) {
				return;
			}
			var value = this.getPropValue(descriptor),
				schema;
			try {
				schema = this.loadFeatureInfo(descriptor, labelText);
			} catch (e) {
				console.error("Could not load feature info for '" + labelText + "'. Error: " + e);
			}
			var descr = {
				oldPropValue: value,
				schema: schema
			};
			if (!value) {
				value = [];
			}
			value.push({
				name: labelText
			});
			label.text("");
			$(".dropdown-container[data-id=" + id + "] li[data-text=" + labelText + "]").remove();
			$("
" + labelText + "
").insertBefore(target);
			descr.propValue = value;
			descriptor.updateFunction(descr);
		},
		editFeatureHandler: function (descriptor, target) {
			var labelText = target.text(),
				$this = this,
				propertyExplorer = require("ide-propertyexplorer"),
				container = $("

").insertAfter(descriptor.ide.currentAdorner()),
				editor = $('

').appendTo(container),
				options = $.extend({}, descriptor),
				property,
				count = 0,
				schema,
				updateComp = function (descr) {
					var features = $this.getPropValue(descriptor),
						i,
						feature,
						schema;
					for (i = 0; i < features.length; i++ ) {
						if (features[i].name === labelText) {
							feature = features[i];
							break;
						}
					}
					if (!feature) {
						return;
					}
					feature[descr.propName] = descr.propValue;
					var opt = descriptor;
					if (descr.handlerFlag) {
						opt.args = descr.args;
						opt.handlerFlag = true;
						opt.funcName = descr.funcName;
					}
					opt.propValue = features;
					schema = $this.settings.packageInfo.components[descriptor.type].properties.features.components;
					schema.heterogeneous = true;
					opt.schema = schema;
					// updateComponent also updates the code editor
					if (descriptor.updateFunction) {
						descriptor.updateFunction(opt);
					} else {
						descriptor.provider.updateComponent(opt);
					}
				};
			options.id = "featureEditor";
			options.containerId = "feature";
			options.parent = editor;
			options.data = [];
			options.updateFunction = updateComp;
			try {
				schema = this.loadFeatureInfo(descriptor, labelText);
			} catch (e) {
				console.error("Could not load feature info for '" + labelText + "'. Error: " + e);
			}
			for (property in schema) {
				if (schema.hasOwnProperty(property) && property !== "name") {
					options.data.push({
						id: count++,
						propName: property,
						defaultValue: schema[property].defaultValue,
						propValue: schema[property].defaultValue,
						propType: schema[property].type,
						description: schema[property].description,
						valueOptions: schema[property].valueOptions,
						displayProp: schema[property].designerDisplayProperty,
						args: schema[property].args,
						schema: schema[property].schema
					});
				}
			}
			// render and open a property explorer
			propertyExplorer(options);
			descriptor.ide.adornerMoveLeft();
		},
		deleteFeatureHandler: function (descriptor, target, id) {
			var labelText = target.text(), value = this.getPropValue(descriptor), schema, i, opt = $.extend({}, descriptor);
			target.remove();
			for (i = 0; i < value.length; i++) {
				if (value[i].name === labelText) {
					value.splice(i, 1);
					break;
				}
			}
			schema = this.settings.packageInfo.components[opt.type].properties.features.components;
			opt.propValue = value;
			opt.propType = "array";
			schema.heterogeneous = true;
			opt.schema = schema;
			$("
" + labelText + "
").attr({
					"data-text": labelText,
					"data-key": labelText,
					"title": labelText
				}).appendTo(".dropdown-container[data-id=" + id + "] ul");
			descriptor.provider.updateComponent(opt);
		},
		setPropertyExplorerValueContents: function (descriptor) {
			if (descriptor.propName === "features") {
				descriptor.td.html("Configure...");
			} else if (this._super) {
				this._super(descriptor);
			}
		}
		/*
		render: function(descriptor) {
			// THIS IS WHERE WE PUT FULLY CUSTOM EDITORS FOR COMPONENTS
		},
		*/
	});
	return IgniteUIGridPlugin;
});
<|endoftext|>


<commit_before>
import "babel-polyfill";

/**
 * Read and Write Chrome storage
 *
 * @class
 */

const name = "simpread",
    remote = "http://ojec5ddd5.bkt.clouddn.com/website_list.json",
    local  = chrome.extension.getURL( "website_list.json" ),
    mode   = {
        focus     : "focus",
        read      : "read",
        option    : "option",
    },
    site   = {
        name      : "",   // only read mode
        title     : "",   // only read mode
        desc      : "",   // only read mode
        exclude   : [],
        include   : "",
    },
    focus  = {
        version   : "2016-12-29",
        bgcolor   : "rgba( 235, 235, 235, 0.9 )",
        opacity   : 90,
        shortcuts : "A S",
        sites     : [],    // e.g. [ "<url>", site ]
    },
    read   = {
        version   : "2017-01-07",
        shortcuts : "A A",
        theme     : "theme1",
        fontfamily: "",
        fontsize  : 14,
        sites     : []    // e.g. [ "<url>", site ]
    };

let current  = {},
    origin   = {},
    simpread = {
        focus,
        read,
        sites  : [],
        option : {},
    };

class Storage {

    /**
     * Get simpread.focus data structure
     *
     * @return {object} simpread["focus"]
     */
    get focus() {
        return simpread[ mode.focus ];
    }

    /**
     * Get simpread.read data structure
     *
     * @return {object} simpread["read"]
     */
    get read() {
        return simpread[ mode.read ];
    }

    /**
     * Get current data structure
     *
     * @return {object} current
     */
    get current() {
        return current;
    }

    /**
     * Restore simpread[key]
     *
     * @param {string} @see mode
     */
    Restore( key ) {
        simpread[key] = clone( origin[key] );
        this.Setcur( key );
    }

    /**
     * Set current object, current object structure include:
     *
     * focus mode: { url, mode, site, shortcuts, bgcolor, opacity }
     * read  mode: { url, mode, site, shortcuts, theme, fontsize, fontfamily }
     *
     * @param {string} @see mode
     */
    Setcur( key ) {
        const [ url, sites ] = [getURI(), new Map( simpread[key].sites )];
        current      = swap( simpread[key], {} );
        current.url  = url;
        current.mode = key;
        current.site = sites.get( url );
        while( !current.site ) {
            current.site = findSitebyURL( url );
            if ( !current.site ) {
                sites.set( url, clone( site ));
                current.site = sites.get( url );
            }
            simpread[key].sites.push([ url, current.site ]);
        }
        console.log( "current site object is ", current )
    }

    /**
     * Save simpread to chrome storage
     *
     * @param {string} @see mode
     */
    Set( key ) {
        swap( current, simpread[key] );
        save();
    }

    /**
     * Get simpread object from chrome storage
     *
     * @param {function} callback
     */
    Get ( callback ) {
        chrome.storage.local.get( [name], function( result ) {
            if ( result && !$.isEmptyObject( result )) {
                simpread = result[name];
            }
            origin   = clone( simpread );
            callback();
            console.log( "chrome storage read success!", simpread, origin, result );
        });
    }

    /**
     * Get local/remote JSON usage async
     *
     * @param  {string} url, e.g. chrome-extension://xxxx/website_list.json or http://xxxx.xx/website_list.json
     */
    async GetNewsites( type ) {
        try {
            const url    = type === "remote" ? remote : local,
                response = await fetch( url + "?_=" + Math.round(+new Date()) ),
                sites    = await response.json(),
                len      = simpread.sites.length;
            if ( len == 0 ) {
                simpread.sites = formatSites( sites );
            } else {
                addsites( formatSites( sites ));
            }
            if ( len == 0 || len != simpread.sites.length ) {
                save();
            }
        } catch ( error ) {
            console.error( error );
        }
    }

    /**
     * Verity current changed
     *
     * @param {string} @see mode
     */
    VerifyCur( type ) {
        return ( current.mode && current.mode != type ) || $.isEmptyObject( current );
    }

    /**
     * Adapter site
     *
     * @return {number} 0: success; -1: not exsit; -2:tieba.com; -3:chiphell.com
     */
    Adapter() {
        const [ hostname, pathname, href ] = [ window.location.hostname, window.location.pathname, window.location.href ];
        if ( hostname == "tieba.baidu.com" && !href.includes( "see_lz=1" ) ) {
            return -2;
        } else if ( hostname == "www.chiphell.com" ) {
            if ( pathname == "/forum.php" && window.location.search.includes( "mod=viewthread" ) ) {
                return 0;
            } else if ( pathname.includes( "thread" ) && window.location.search == "" ) {
                return -3;
            } else {
                return -1;
            }
        } else if ( current.site.name === "" ) {
            return -1;
        } else {
            const sites = new Map( simpread.sites ),
                  url   = href.endsWith("/") ? href : href + "/",
                  urls  = [ ...sites.keys() ].filter( item => {
                      if ( item.includes( url )) {
                          const suffix = item.replace( url, "" );
                          if ( suffix != "" ) return url;
                      }
                  });
            if ( urls.length > 0 ) {
                return -1;
            } else {
                return 0;
            }
        }
    }

}

/**
 * Swap source and target property
 *
 * @param {object} source origin
 * @param {object} target origin
 */
function swap( source, target ) {
    for ( const key of Object.keys( source ) ) {
        if ( ![ "site", "sites", "version", "url", "mode" ].includes( key ) ) {
            target[key] = source[key];
        }
    }
    return target;
}

/**
 * Get URI
 *
 * @return {string} e.g. current site url is http://www.cnbeta.com/articles/1234.html return http://www.cnbeta.com/articles/
 */
function getURI() {
    const arr = window.location.pathname.match( /(\S+\/\b|^\/)/g );
    return `${ window.location.protocol }//${ window.location.hostname }${ arr[0] }`;
}

/**
 * Deep clone object
 *
 * @param  {object} target object
 * @return {object} new target object
 */
function clone( target ) {
    return $.extend( true, {}, target );
}

/**
 * Format sites object from loacal or remote json file
 *
 * @param  {object} sites.[array]
 * @return {array} foramat e.g. [[ <url>, object ],[ <url>, object ]]
 */
function formatSites( result ) {
    const format = new Map();
    for ( let site of result.sites ) {
        const url = site.url;
        delete site.url;
        format.set( url, site );
    }
    return [ ...format ];
}

/**
 * Add new sites to old sites
 *
 * @param {array} new sites from local or remote
 */
function addsites( sites ) {
    const old  = new Map( simpread.sites );
    const urls = [ ...old.keys() ];
    for ( const site of sites ) {
        if ( !urls.includes( site[0] ) ) {
            simpread.sites.push([ site[0], site[1] ]);
        }
    }
}

/**
 * Find site by url from simpread.sites, include wildcard, support: *
 *
 * @param  {string} url
 * @return {object} site object or not found return undefined
 */
function findSitebyURL( url ) {
    const sites     = new Map( simpread.sites ),
          urls     = [ ...sites.keys() ],
          arr      = url.match( /[.a-zA-z0-9-_]+/g ),
          wildcard = arr[1];
    for ( const cur of urls ) {
        const name = sites.get(cur).name;
        if ( cur.includes( "*" ) && wildcard.includes( name ) ) {
            return clone( sites.get( cur ));
        } else if ( cur == url ) {
            return clone( sites.get( url ));
        }
    }
    return undefined;
}

/**
 * Call chrome storage set
 */
function save() {
    chrome.storage.local.set( { [name] : simpread }, function() {
        console.log( "chrome storage save success!", simpread );
        origin   = clone( simpread );
    });
}

const storage = new Storage();

export {
    storage,
    mode  as STORAGE_MODE,
    clone as Clone
};<commit_msg>Fix findSitebyURL() return bug.<commit_after>
import "babel-polyfill";

/**
 * Read and Write Chrome storage
 *
 * @class
 */

const name = "simpread",
    remote = "http://ojec5ddd5.bkt.clouddn.com/website_list.json",
    local  = chrome.extension.getURL( "website_list.json" ),
    mode   = {
        focus     : "focus",
        read      : "read",
        option    : "option",
    },
    site   = {
        name      : "",   // only read mode
        title     : "",   // only read mode
        desc      : "",   // only read mode
        exclude   : [],
        include   : "",
    },
    focus  = {
        version   : "2016-12-29",
        bgcolor   : "rgba( 235, 235, 235, 0.9 )",
        opacity   : 90,
        shortcuts : "A S",
        sites     : [],    // e.g. [ "<url>", site ]
    },
    read   = {
        version   : "2017-01-07",
        shortcuts : "A A",
        theme     : "theme1",
        fontfamily: "",
        fontsize  : 14,
        sites     : []    // e.g. [ "<url>", site ]
    };

let current  = {},
    origin   = {},
    simpread = {
        focus,
        read,
        sites  : [],
        option : {},
    };

class Storage {

    /**
     * Get simpread.focus data structure
     *
     * @return {object} simpread["focus"]
     */
    get focus() {
        return simpread[ mode.focus ];
    }

    /**
     * Get simpread.read data structure
     *
     * @return {object} simpread["read"]
     */
    get read() {
        return simpread[ mode.read ];
    }

    /**
     * Get current data structure
     *
     * @return {object} current
     */
    get current() {
        return current;
    }

    /**
     * Restore simpread[key]
     *
     * @param {string} @see mode
     */
    Restore( key ) {
        simpread[key] = clone( origin[key] );
        this.Setcur( key );
    }

    /**
     * Set current object, current object structure include:
     *
     * focus mode: { url, mode, site, shortcuts, bgcolor, opacity }
     * read  mode: { url, mode, site, shortcuts, theme, fontsize, fontfamily }
     *
     * @param {string} @see mode
     */
    Setcur( key ) {
        const [ url, sites ] = [getURI(), new Map( simpread[key].sites )];
        current      = swap( simpread[key], {} );
        current.url  = url;
        current.mode = key;
        current.site = sites.get( url );
        while( !current.site ) {
            const arr = findSitebyURL( url );
            if ( arr ) {
                current.site = arr[0];
                current.url  = arr[1];
            } else {
                sites.set( url, clone( site ));
                current.site = sites.get( url );
            }
            simpread[key].sites.push([ current.url, current.site ]);
        }
        console.log( "current site object is ", current )
    }

    /**
     * Save simpread to chrome storage
     *
     * @param {string} @see mode
     */
    Set( key ) {
        swap( current, simpread[key] );
        save();
    }

    /**
     * Get simpread object from chrome storage
     *
     * @param {function} callback
     */
    Get ( callback ) {
        chrome.storage.local.get( [name], function( result ) {
            if ( result && !$.isEmptyObject( result )) {
                simpread = result[name];
            }
            origin   = clone( simpread );
            callback();
            console.log( "chrome storage read success!", simpread, origin, result );
        });
    }

    /**
     * Get local/remote JSON usage async
     *
     * @param  {string} url, e.g. chrome-extension://xxxx/website_list.json or http://xxxx.xx/website_list.json
     */
    async GetNewsites( type ) {
        try {
            const url    = type === "remote" ? remote : local,
                response = await fetch( url + "?_=" + Math.round(+new Date()) ),
                sites    = await response.json(),
                len      = simpread.sites.length;
            if ( len == 0 ) {
                simpread.sites = formatSites( sites );
            } else {
                addsites( formatSites( sites ));
            }
            if ( len == 0 || len != simpread.sites.length ) {
                save();
            }
        } catch ( error ) {
            console.error( error );
        }
    }

    /**
     * Verity current changed
     *
     * @param {string} @see mode
     */
    VerifyCur( type ) {
        return ( current.mode && current.mode != type ) || $.isEmptyObject( current );
    }

    /**
     * Adapter site
     *
     * @return {number} 0: success; -1: not exsit; -2:tieba.com; -3:chiphell.com
     */
    Adapter() {
        const [ hostname, pathname, href ] = [ window.location.hostname, window.location.pathname, window.location.href ];
        if ( hostname == "tieba.baidu.com" && !href.includes( "see_lz=1" ) ) {
            return -2;
        } else if ( hostname == "www.chiphell.com" ) {
            if ( pathname == "/forum.php" && window.location.search.includes( "mod=viewthread" ) ) {
                return 0;
            } else if ( pathname.includes( "thread" ) && window.location.search == "" ) {
                return -3;
            } else {
                return -1;
            }
        } else if ( current.site.name === "" ) {
            return -1;
        } else {
            const sites = new Map( simpread.sites ),
                  url   = href.endsWith("/") ? href : href + "/",
                  urls  = [ ...sites.keys() ].filter( item => {
                      if ( item.includes( url )) {
                          const suffix = item.replace( url, "" );
                          if ( suffix != "" ) return url;
                      }
                  });
            if ( urls.length > 0 ) {
                return -1;
            } else {
                return 0;
            }
        }
    }

}

/**
 * Swap source and target property
 *
 * @param {object} source origin
 * @param {object} target origin
 */
function swap( source, target ) {
    for ( const key of Object.keys( source ) ) {
        if ( ![ "site", "sites", "version", "url", "mode" ].includes( key ) ) {
            target[key] = source[key];
        }
    }
    return target;
}

/**
 * Get URI
 *
 * @return {string} e.g. current site url is http://www.cnbeta.com/articles/1234.html return http://www.cnbeta.com/articles/
 */
function getURI() {
    const arr = window.location.pathname.match( /(\S+\/\b|^\/)/g );
    return `${ window.location.protocol }//${ window.location.hostname }${ arr[0] }`;
}

/**
 * Deep clone object
 *
 * @param  {object} target object
 * @return {object} new target object
 */
function clone( target ) {
    return $.extend( true, {}, target );
}

/**
 * Format sites object from loacal or remote json file
 *
 * @param  {object} sites.[array]
 * @return {array} foramat e.g. [[ <url>, object ],[ <url>, object ]]
 */
function formatSites( result ) {
    const format = new Map();
    for ( let site of result.sites ) {
        const url = site.url;
        delete site.url;
        format.set( url, site );
    }
    return [ ...format ];
}

/**
 * Add new sites to old sites
 *
 * @param {array} new sites from local or remote
 */
function addsites( sites ) {
    const old  = new Map( simpread.sites );
    const urls = [ ...old.keys() ];
    for ( const site of sites ) {
        if ( !urls.includes( site[0] ) ) {
            simpread.sites.push([ site[0], site[1] ]);
        }
    }
}

/**
 * Find site by url from simpread.sites, include wildcard, support: *
 *
 * @param  {string} url
 * @return {array} arr[0]: current site; arr[1]: current url
 */
function findSitebyURL( url ) {
    const sites     = new Map( simpread.sites ),
          urls     = [ ...sites.keys() ],
          arr      = url.match( /[.a-zA-z0-9-_]+/g ),
          wildcard = arr[1];
    for ( const cur of urls ) {
        const name = sites.get(cur).name;
        if ( cur.includes( "*" ) && wildcard.includes( name ) ) {
            return [ clone( sites.get( cur )), cur ];
        } else if ( cur == url ) {
            return [ clone( sites.get( url )), url ];
        }
    }
    return undefined;
}

/**
 * Call chrome storage set
 */
function save() {
    chrome.storage.local.set( { [name] : simpread }, function() {
        console.log( "chrome storage save success!", simpread );
        origin   = clone( simpread );
    });
}

const storage = new Storage();

export {
    storage,
    mode  as STORAGE_MODE,
    clone as Clone
};<|endoftext|>