<commit_before>const { BadgeFactory } = require('gh-badges');
const path = require('path');
const fs = require('fs');
const ReportGenerator = require('lighthouse/lighthouse-core/report/report-generator');
const { promisify } = require('util');
const { exec } = require('child_process');
const R = require('ramda');
const { statusMessage } = require('./util');
const { getAverageScore, getSquashedScore } = require('./calculations');
const { urlEscaper } = require('./util');
const { percentageToColor } = require('./calculations');

// Buffer size for stdout, must be big enough to handle lighthouse CLI output
const maxBuffer = 1024 * 50000;

const metricsToSvg = async (lighthouseMetrics, badgeStyle, outputPath) => {
  R.keys(lighthouseMetrics).map((lighthouseMetricKey) => {
    const filepath = path.join(outputPath, `${lighthouseMetricKey.replace(/ /g, '_')}.svg`);
    const text = [lighthouseMetricKey, `${lighthouseMetrics[lighthouseMetricKey]}%`];
    const badgeColor = percentageToColor(lighthouseMetrics[lighthouseMetricKey]);
    const svg = new BadgeFactory().create({
      text,
      format: 'svg',
      colorscheme: badgeColor,
      template: badgeStyle,
    });
    fs.writeFile(filepath, svg, error => statusMessage(
      `Saved svg to ${filepath}\n`,
      `Failed to save svg to ${outputPath}`,
      error,
    ));
    return true;
  });
};

const htmlReportsToFile = async (htmlReports, outputPath) => htmlReports.map((htmlReport) => {
  const url = R.head(R.keys(htmlReport));
  if (htmlReport[url]) {
    const filepath = path.join(outputPath, `${urlEscaper(url)}.html`);
    fs.writeFile(filepath, htmlReport[url], error => statusMessage(
      `Saved report to ${filepath}\n`,
      `Failed to save report to ${outputPath}`,
      error,
    ));
  }
  return false;
});

const generateArtifacts = async ({ reports, svg, savePath }) => {
  const outputPath = savePath || process.cwd();
  await Promise.all([
    htmlReportsToFile(reports, outputPath),
    metricsToSvg(svg.results, svg.style, outputPath),
  ]);
};

const processRawLighthouseResult = async (data, url, shouldSaveReport) => {
  const htmlReport = shouldSaveReport ? ReportGenerator.generateReportHtml(data) : false;
  const { categories } = data;
  const scores = R.keys(categories).map(category => (
    { [`lighthouse ${category.toLowerCase()}`]: categories[category].score * 100 }
  ));
  const lighthouseMetrics = Object.assign({}, ...scores);
  return { metrics: lighthouseMetrics, report: { [url]: htmlReport } };
};

const calculateLighthouseMetrics = async (url, shouldSaveReport) => {
  const lighthouseBinary = path.join(__dirname, '..', 'node_modules', '.bin', 'lighthouse');
  const params = '--chrome-flags=\'--headless --no-sandbox --no-default-browser-check --no-first-run --disable-default-apps\' --output=json --output-path=stdout';
  const lighthouseCommand = `${lighthouseBinary} ${params} ${url}`;
  const execPromise = promisify(exec);
  const { stdout } = await execPromise(`${lighthouseCommand}`, { maxBuffer });
  return processRawLighthouseResult(JSON.parse(stdout), url, shouldSaveReport);
};

const processParameters = async (args, lighthouseMetricFunction) => {
  const results = await Promise.all(args.urls.map(
    url => lighthouseMetricFunction(url, args.save_report),
  ));

  const metrics = R.pluck('metrics', results);
  const reports = R.pluck('report', results);

  const metricsResults = args.single_badge
    ? await getSquashedScore(metrics)
    : await getAverageScore(metrics);

  await generateArtifacts({
    reports,
    svg: { results: metricsResults, style: args.badge_style },
    savePath: args.output_path,
  });
};

module.exports = {
  metricsToSvg,
  htmlReportsToFile,
  processRawLighthouseResult,
  calculateLighthouseMetrics,
  processParameters,
};
<commit_msg>Revert "Run without quiet"<commit_after>const { BadgeFactory } = require('gh-badges');
const path = require('path');
const fs = require('fs');
const ReportGenerator = require('lighthouse/lighthouse-core/report/report-generator');
const { promisify } = require('util');
const { exec } = require('child_process');
const R = require('ramda');
const { statusMessage } = require('./util');
const { getAverageScore, getSquashedScore } = require('./calculations');
const { urlEscaper } = require('./util');
const { percentageToColor } = require('./calculations');

// Buffer size for stdout, must be big enough to handle lighthouse CLI output
const maxBuffer = 1024 * 50000;

const metricsToSvg = async (lighthouseMetrics, badgeStyle, outputPath) => {
  R.keys(lighthouseMetrics).map((lighthouseMetricKey) => {
    const filepath = path.join(outputPath, `${lighthouseMetricKey.replace(/ /g, '_')}.svg`);
    const text = [lighthouseMetricKey, `${lighthouseMetrics[lighthouseMetricKey]}%`];
    const badgeColor = percentageToColor(lighthouseMetrics[lighthouseMetricKey]);
    const svg = new BadgeFactory().create({
      text,
      format: 'svg',
      colorscheme: badgeColor,
      template: badgeStyle,
    });
    fs.writeFile(filepath, svg, error => statusMessage(
      `Saved svg to ${filepath}\n`,
      `Failed to save svg to ${outputPath}`,
      error,
    ));
    return true;
  });
};

const htmlReportsToFile = async (htmlReports, outputPath) => htmlReports.map((htmlReport) => {
  const url = R.head(R.keys(htmlReport));
  if (htmlReport[url]) {
    const filepath = path.join(outputPath, `${urlEscaper(url)}.html`);
    fs.writeFile(filepath, htmlReport[url], error => statusMessage(
      `Saved report to ${filepath}\n`,
      `Failed to save report to ${outputPath}`,
      error,
    ));
  }
  return false;
});

const generateArtifacts = async ({ reports, svg, savePath }) => {
  const outputPath = savePath || process.cwd();
  await Promise.all([
    htmlReportsToFile(reports, outputPath),
    metricsToSvg(svg.results, svg.style, outputPath),
  ]);
};

const processRawLighthouseResult = async (data, url, shouldSaveReport) => {
  const htmlReport = shouldSaveReport ? ReportGenerator.generateReportHtml(data) : false;
  const { categories } = data;
  const scores = R.keys(categories).map(category => (
    { [`lighthouse ${category.toLowerCase()}`]: categories[category].score * 100 }
  ));
  const lighthouseMetrics = Object.assign({}, ...scores);
  return { metrics: lighthouseMetrics, report: { [url]: htmlReport } };
};

const calculateLighthouseMetrics = async (url, shouldSaveReport) => {
  const lighthouseBinary = path.join(__dirname, '..', 'node_modules', '.bin', 'lighthouse');
  const params = '--chrome-flags=\'--headless --no-sandbox --no-default-browser-check --no-first-run --disable-default-apps\' --output=json --output-path=stdout --quiet';
  const lighthouseCommand = `${lighthouseBinary} ${params} ${url}`;
  const execPromise = promisify(exec);
  const { stdout } = await execPromise(`${lighthouseCommand}`, { maxBuffer });
  return processRawLighthouseResult(JSON.parse(stdout), url, shouldSaveReport);
};

const processParameters = async (args, lighthouseMetricFunction) => {
  const results = await Promise.all(args.urls.map(
    url => lighthouseMetricFunction(url, args.save_report),
  ));

  const metrics = R.pluck('metrics', results);
  const reports = R.pluck('report', results);

  const metricsResults = args.single_badge
    ? await getSquashedScore(metrics)
    : await getAverageScore(metrics);

  await generateArtifacts({
    reports,
    svg: { results: metricsResults, style: args.badge_style },
    savePath: args.output_path,
  });
};

module.exports = {
  metricsToSvg,
  htmlReportsToFile,
  processRawLighthouseResult,
  calculateLighthouseMetrics,
  processParameters,
};
<|endoftext|>


<commit_before>var width = 960,
    height = 600;

var tooltip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

var rangesColors = [
    ["#ffffff","#ffe4b2", "#ffc04c", "#ffa500","#ff2500","#ff0000"],
    ["#ffffff", "#ffc04c","#ffa500", "#ff0000"],
    ["#ffffff","#ff0000"]
];

function getDomain() {
    var min, max;
    var len = inmigration_data.length;
    var percent = 0;
    for (var i = 0; i < len; i++) {
        percent = ((inmigration_data[i].pobindi1990* 1.0) / inmigration_data[i].tpobtot1990) * 100;
        if (typeof max === 'undefined'){
            max = percent;
            continue;
        }
        if (typeof min === 'undefined'){
            min = percent;
            continue;
        }

        if (percent > max) {
            max = percent;
        }else{
            if(percent < min){
                min = percent;
            }
        }
    }
    return [min,max];
}

function createBucketDomain(domain,numberBuckets ) {
    var min, max, bucket = [];
    min = domain[0];
    max = domain[1];
    if (numberBuckets === 2) {
        return domain;
    }
    bucket.push(min);
    var difference = ((max-min)*1.0)/(numberBuckets);
    var bucketSum = min;
    for (var i = 1; i < numberBuckets; i++) {
        bucketSum+= difference;
        bucket.push(bucketSum);
    }
    bucket.push(max);
    return bucket;
}

function createBucketColors(numberBuckets){
    switch (numberBuckets){
        case 3:{
            return rangesColors[1];
        }
        case 5: {
            return rangesColors[0]
        }
        default: return rangesColors[2];
    }
}

var nBuckets = 5;

var color = d3.scale.linear().range(createBucketColors(nBuckets)).domain(createBucketDomain(getDomain(),nBuckets));

var projection = d3.geo.mercator()
    .scale(1280)
    .center([ -100.366806, 25.657792]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

queue()
    .defer(d3.json, "estados.json")
    .await(ready);

function getMigrationPercent1990 (state_code) {
    var inmigration = inmigration_data[state_code-1];
    var percent = ((inmigration.pobindi1990* 1.0) / inmigration.tpobtot1990) * 100;
    return percent;
}

function ready(error, estados) {
  if (error) throw error;

var g = svg.append("g");

var path = g.selectAll("path")
    .data(topojson.feature(estados, estados.objects.states).features)
    .enter().append("path")
    .attr("d", d3.geo.path().projection(projection))
    .attr("fill", function (d) {
        return color( getMigrationPercent1990(d.properties.state_code));
    })
    .style("stroke", "#333")
    .attr('opacity', 0)
    .on("mouseover", function(d) {
      tooltip.transition()
        .duration(200)
        .style("opacity", .9);
      tooltip.html("" + d.properties.state_name +"
 Porcentaje de inmigrantes: "+ getMigrationPercent1990(d.properties.state_code).toFixed(2)+ "%")
        .style("left", (d3.event.pageX + 5) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      tooltip.transition()
        .duration(500)
        .style("opacity", 0);
    });

    path.transition()
    .delay(10)
    .duration(1250)
    .attr('opacity', 1);

}

<commit_msg>Added legend to choropleth<commit_after>var width = 960,
    height = 600;

var tooltip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

var rangesColors = [
    ["#ffffff","#ffe4b2", "#ffc04c", "#ffa500","#ff2500","#ff0000"],
    ["#ffffff", "#ffc04c","#ffa500", "#ff0000"],
    ["#ffffff","#ff0000"]
];

function getDomain() {
    var min, max;
    var len = inmigration_data.length;
    var percent = 0;
    for (var i = 0; i < len; i++) {
        percent = ((inmigration_data[i].pobindi1990* 1.0) / inmigration_data[i].tpobtot1990) * 100;
        if (typeof max === 'undefined'){
            max = percent;
            continue;
        }
        if (typeof min === 'undefined'){
            min = percent;
            continue;
        }

        if (percent > max) {
            max = percent;
        }else{
            if(percent < min){
                min = percent;
            }
        }
    }
    return [min,max];
}

function createBucketDomain(domain,numberBuckets ) {
    var min, max, bucket = [];
    min = domain[0];
    max = domain[1];
    if (numberBuckets === 2) {
        return domain;
    }
    bucket.push(min);
    var difference = ((max-min)*1.0)/(numberBuckets);
    var bucketSum = min;
    for (var i = 1; i < numberBuckets; i++) {
        bucketSum+= difference;
        bucket.push(bucketSum);
    }
    bucket.push(max);
    return bucket;
}

function createBucketColors(numberBuckets){
    switch (numberBuckets){
        case 3:{
            return rangesColors[1];
        }
        case 5: {
            return rangesColors[0]
        }
        default: return rangesColors[2];
    }
}

var nBuckets = 5;

var color = d3.scale.linear().range(createBucketColors(nBuckets)).domain(createBucketDomain(getDomain(),nBuckets));

var projection = d3.geo.mercator()
    .scale(1280)
    .center([ -100.366806, 25.657792]);

var path = d3.geo.path()
    .projection(projection);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

queue()
    .defer(d3.json, "estados.json")
    .await(ready);

function getMigrationPercent1990 (state_code) {
    var inmigration = inmigration_data[state_code-1];
    var percent = ((inmigration.pobindi1990* 1.0) / inmigration.tpobtot1990) * 100;
    return percent;
}

function ready(error, estados) {
  if (error) throw error;

var g = svg.append("g");

var path = g.selectAll("path")
    .data(topojson.feature(estados, estados.objects.states).features)
    .enter().append("path")
    .attr("d", d3.geo.path().projection(projection))
    .attr("fill", function (d) {
        return color( getMigrationPercent1990(d.properties.state_code));
    })
    .style("stroke", "#333")
    .attr('opacity', 0)
    .on("mouseover", function(d) {
      tooltip.transition()
        .duration(200)
        .style("opacity", .9);
      tooltip.html("" + d.properties.state_name +"
 Porcentaje de inmigrantes: "+ getMigrationPercent1990(d.properties.state_code).toFixed(2)+ "%")
        .style("left", (d3.event.pageX + 5) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      tooltip.transition()
        .duration(500)
        .style("opacity", 0);
    });

    path.transition()
    .delay(10)
    .duration(1250)
    .attr('opacity', 1);

// draw legend
  var legend = svg.selectAll(".legend")
    .data(color.domain())
    .enter().append("g")
    .attr("class", "legend")
    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  // draw legend colored rectangles
  legend.append("rect")
    .attr("x", width - 18)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", color)
    .style("border-style","solid")
    .style("border-color", "#000000");

  // draw legend text
  legend.append("text")
    .attr("x", width - 24)
    .attr("y", 9)
    .attr("dy", ".35em")
    .style("text-anchor", "end")
    .text(function(d) { return d.toFixed(2);});
}

<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.XHRLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

Object.assign( THREE.XHRLoader.prototype, {

	load: function ( url, onLoad, onProgress, onError ) {

		if ( this.path !== undefined ) url = this.path + url;

		var scope = this;

		var cached = THREE.Cache.get( url );

		if ( cached !== undefined ) {

			scope.manager.itemStart( url );

			setTimeout( function () {

				if ( onLoad ) {

					onLoad( cached );
				}

				scope.manager.itemEnd( url );

			}, 0 );

			return cached;

		}

		var request = new XMLHttpRequest();
		request.overrideMimeType( 'text/plain' );
		request.open( 'GET', url, true );

		request.addEventListener( 'load', function ( event ) {

			var response = event.target.response;

			THREE.Cache.add( url, response );

			if ( this.status === 200 ) {

				if ( onLoad ) onLoad( response );

				scope.manager.itemEnd( url );

			} else if ( this.status === 0 ) {

				// Some browsers return HTTP Status 0 when using non-http protocol
				// e.g. 'file://' or 'data://'. Handle as success.

				console.warn( 'THREE.XHRLoader: HTTP Status 0 received.' );

				if ( onLoad ) onLoad( response );

				scope.manager.itemEnd( url );

			} else {

				if ( onError ) onError( event );

				scope.manager.itemError( url );

			}

		}, false );

		if ( onProgress !== undefined ) {

			request.addEventListener( 'progress', function ( event ) {

				onProgress( event );

			}, false );

		}

		request.addEventListener( 'error', function ( event ) {

			if ( onError ) onError( event );

			scope.manager.itemError( url );

		}, false );

		if ( this.responseType !== undefined ) request.responseType = this.responseType;
		if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;

		request.send( null );

		scope.manager.itemStart( url );

		return request;

	},

	setPath: function ( value ) {

		this.path = value;
		return this;

	},

	setResponseType: function ( value ) {

		this.responseType = value;
		return this;

	},

	setWithCredentials: function ( value ) {

		this.withCredentials = value;
		return this;

	}

} );
<commit_msg>XHRLoader: Clean up.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.XHRLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

Object.assign( THREE.XHRLoader.prototype, {

	load: function ( url, onLoad, onProgress, onError ) {

		if ( this.path !== undefined ) url = this.path + url;

		var scope = this;

		var cached = THREE.Cache.get( url );

		if ( cached !== undefined ) {

			scope.manager.itemStart( url );

			setTimeout( function () {

				if ( onLoad ) onLoad( cached );

				scope.manager.itemEnd( url );

			}, 0 );

			return cached;

		}

		var request = new XMLHttpRequest();
		request.overrideMimeType( 'text/plain' );
		request.open( 'GET', url, true );

		request.addEventListener( 'load', function ( event ) {

			var response = event.target.response;

			THREE.Cache.add( url, response );

			if ( this.status === 200 ) {

				if ( onLoad ) onLoad( response );

				scope.manager.itemEnd( url );

			} else if ( this.status === 0 ) {

				// Some browsers return HTTP Status 0 when using non-http protocol
				// e.g. 'file://' or 'data://'. Handle as success.

				console.warn( 'THREE.XHRLoader: HTTP Status 0 received.' );

				if ( onLoad ) onLoad( response );

				scope.manager.itemEnd( url );

			} else {

				if ( onError ) onError( event );

				scope.manager.itemError( url );

			}

		}, false );

		if ( onProgress !== undefined ) {

			request.addEventListener( 'progress', function ( event ) {

				onProgress( event );

			}, false );

		}

		request.addEventListener( 'error', function ( event ) {

			if ( onError ) onError( event );

			scope.manager.itemError( url );

		}, false );

		if ( this.responseType !== undefined ) request.responseType = this.responseType;
		if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;

		request.send( null );

		scope.manager.itemStart( url );

		return request;

	},

	setPath: function ( value ) {

		this.path = value;
		return this;

	},

	setResponseType: function ( value ) {

		this.responseType = value;
		return this;

	},

	setWithCredentials: function ( value ) {

		this.withCredentials = value;
		return this;

	}

} );
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2012, Institute for Pervasive Computing, ETH Zurich.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Copper CoAP browser.
 ******************************************************************************/
/**
 * \file
 *         Code handling Observing Resources
 *
 * \author  Matthias Kovatsch <kovatsch@inf.ethz.ch>\author
 */

CopperChrome.ObserveEntry = function(uri, cb, token) {
	this.uri = uri;
	this.callback = cb;
	if (token!=null) {
		this.token = token;
	}
};
CopperChrome.ObserveEntry.prototype = {
	uri : null,
	callback: null,
	token : null
};

CopperChrome.Observing = function() {
	// maybe support multiple subscriptions via sidebar in the future
	//this.subscriptions = new Object();
};

CopperChrome.Observing.prototype = {

	pending : null,
	subscription : null,

	subscribe : function(uri, cb) {
		// check for existing subscriptions
		if (this.subscription) {
			this.unsubscribe();
			return;
		}

		dump('INFO: Subscribing to ' + uri + '\n');

		var token = CopperChrome.behavior.observeToken ? new Array(parseInt(Math.random()*0x100), parseInt(Math.random()*0x100)) : null;
		this.pending = new CopperChrome.ObserveEntry(uri, cb, token);

		var that = this;
		CopperChrome.client.registerToken(token, CopperChrome.myBind(that, that.handle));

		try {
			var subscribe = new CopperChrome.CoapMessage(Copper.MSG_TYPE_CON, Copper.GET, uri); // always use CON

			if (CopperChrome.coapVersion < 4) {
				subscribe.setObserve(60);
			} else {
				subscribe.setObserve(0);
			}

			subscribe.setToken(token);

			var that = this;
			CopperChrome.client.send(subscribe, CopperChrome.myBind(that, that.handle));
		} catch (ex) {
			alert('ERROR: Observing.subscribe ['+ex+']');
		}
	},

	unsubscribe : function(token) {
		if (this.subscription) {
			dump('INFO: Unsibscribing ' + this.subscription.uri + '\n');
			CopperChrome.client.deRegisterToken(this.subscription.token);

			if (CopperChrome.behavior.observeCancellation=='rst') {
				// Send a RST (with new message ID)
				try {
					var rst = new CopperChrome.CoapMessage(Copper.MSG_TYPE_RST);
					CopperChrome.client.send( rst );
				} catch (ex) {
					alert('ERROR: Observing.unsubscribe ['+ex+']');
				}
			} else if (CopperChrome.behavior.observeCancellation=='get') {
				try {
					let uri = CopperChrome.checkUri(); // get current URI
					var get = new CopperChrome.CoapMessage(Copper.MSG_TYPE_CON, Copper.GET, uri); // always use CON
					get.setToken(this.subscription.token);
					CopperChrome.client.send( get );
				} catch (ex) {
					alert('ERROR: Observing.unsubscribe ['+ex+']');
				}
			}

			this.subscription = null;
		}

		document.getElementById('toolbar_observe').image = 'chrome://copper/skin/tool_observe.png';
		document.getElementById('toolbar_observe').label = 'Observe';
	},

	handle : function(message) {

		if (this.pending) {

			// check if server supports observing this resource
			if (message.isOption(Copper.OPTION_OBSERVE)) {

				this.subscription = new CopperChrome.ObserveEntry(this.pending.uri, this.pending.callback, message.getToken());
				this.pending = null;

				document.getElementById('toolbar_observe').image = 'chrome://copper/skin/tool_unobserve.png';
				document.getElementById('toolbar_observe').label = 'Cancel ';

				this.subscription.callback(message);

			} else {

				CopperChrome.client.deRegisterToken(this.pending.token);
				this.pending = null;

				message.getCopperCode = function() { return 'Resource not observable'; };

				CopperChrome.defaultHandler(message);
			}
		} else if (this.subscription!=null) {
			this.subscription.callback(message);
		} else {
			// somehow it must have gotten here
			CopperChrome.client.deRegisterToken(message.getToken());

			throw 'Missing context for Observing.handle()';
		}
	}
};<commit_msg>Now storing last notification MID for observing cancellation by immediate RST.<commit_after>/*******************************************************************************
 * Copyright (c) 2012, Institute for Pervasive Computing, ETH Zurich.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Copper CoAP browser.
 ******************************************************************************/
/**
 * \file
 *         Code handling Observing Resources
 *
 * \author  Matthias Kovatsch <kovatsch@inf.ethz.ch>\author
 */

CopperChrome.ObserveEntry = function(uri, cb, token) {
	this.uri = uri;
	this.callback = cb;
	if (token!=null) {
		this.token = token;
	}
};
CopperChrome.ObserveEntry.prototype = {
	uri : null,
	callback: null,
	token : null,
	lastTID: -1
};

CopperChrome.Observing = function() {
	// maybe support multiple subscriptions via sidebar in the future
	//this.subscriptions = new Object();
};

CopperChrome.Observing.prototype = {

	pending : null,
	subscription : null,

	subscribe : function(uri, cb) {
		// check for existing subscriptions
		if (this.subscription) {
			this.unsubscribe();
			return;
		}

		dump('INFO: Subscribing to ' + uri + '\n');

		var token = CopperChrome.behavior.observeToken ? new Array(parseInt(Math.random()*0x100), parseInt(Math.random()*0x100)) : null;
		this.pending = new CopperChrome.ObserveEntry(uri, cb, token);

		var that = this;
		CopperChrome.client.registerToken(token, CopperChrome.myBind(that, that.handle));

		try {
			var subscribe = new CopperChrome.CoapMessage(Copper.MSG_TYPE_CON, Copper.GET, uri); // always use CON

			if (CopperChrome.coapVersion < 4) {
				subscribe.setObserve(60);
			} else {
				subscribe.setObserve(0);
			}

			subscribe.setToken(token);

			var that = this;
			CopperChrome.client.send(subscribe, CopperChrome.myBind(that, that.handle));
		} catch (ex) {
			alert('ERROR: Observing.subscribe ['+ex+']');
		}
	},

	unsubscribe : function(token) {
		if (this.subscription) {
			dump('INFO: Unsibscribing ' + this.subscription.uri + '\n');
			CopperChrome.client.deRegisterToken(this.subscription.token);

			if (CopperChrome.behavior.observeCancellation=='rst' && this.subscription.lastTID!=-1) {
				// Send a RST (with new message ID)
				try {
					var rst = new CopperChrome.CoapMessage(Copper.MSG_TYPE_RST);
					rst.setTID(this.subscription.lastTID);
					CopperChrome.client.send( rst );
				} catch (ex) {
					alert('ERROR: Observing.unsubscribe ['+ex+']');
				}
			} else if (CopperChrome.behavior.observeCancellation=='get') {
				try {
					let uri = CopperChrome.checkUri(); // get current URI
					var get = new CopperChrome.CoapMessage(Copper.MSG_TYPE_CON, Copper.GET, uri); // always use CON
					get.setToken(this.subscription.token);
					CopperChrome.client.send( get );
				} catch (ex) {
					alert('ERROR: Observing.unsubscribe ['+ex+']');
				}
			}

			this.subscription = null;
		}

		document.getElementById('toolbar_observe').image = 'chrome://copper/skin/tool_observe.png';
		document.getElementById('toolbar_observe').label = 'Observe';
	},

	handle : function(message) {

		if (this.pending) {

			// check if server supports observing this resource
			if (message.isOption(Copper.OPTION_OBSERVE)) {

				this.subscription = new CopperChrome.ObserveEntry(this.pending.uri, this.pending.callback, message.getToken());
				this.pending = null;

				document.getElementById('toolbar_observe').image = 'chrome://copper/skin/tool_unobserve.png';
				document.getElementById('toolbar_observe').label = 'Cancel ';

				this.subscription.lastTID = message.getTID();
				this.subscription.callback(message);

			} else {

				CopperChrome.client.deRegisterToken(this.pending.token);
				this.pending = null;

				message.getCopperCode = function() { return 'Resource not observable'; };

				CopperChrome.defaultHandler(message);
			}
		} else if (this.subscription!=null) {
			this.subscription.lastTID = message.getTID();
			this.subscription.callback(message);
		} else {
			// somehow it must have gotten here
			CopperChrome.client.deRegisterToken(message.getToken());

			throw 'Missing context for Observing.handle()';
		}
	}
};<|endoftext|>


<commit_before>var async = require('async'),
	StaticScraper = require('./StaticScraper'),
	DynamicScraper = require('./DynamicScraper'),
	ScraperError = require('./ScraperError');

/**
 * Transforms a string into a regular expression.
 * This function is from the project Routes.js, under the MIT licence,
 *   {@link https://github.com/aaronblohowiak/routes.js} it's present
 *   in the file {@link https://github.com/aaronblohowiak/routes.js/blob/bdad0a1ae10d11981bb286550bb3b8a1a71909bd/dist/routes.js#L49}.
 *
 * @param  {!string} path String path.
 * @param  {!Array.<string>} keys Empty array to be filled with the
 *   keys ids.
 * @return {!RegExp} Regular expression.
 */
function pathToRegExp(path, keys) {
	path = path
		.concat('/?')
		.replace(/\/\(/g, '(?:/')
		.replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?|\*/g, function(_, slash, format, key, capture, optional) {
			if (_ === '*') {
				keys.push(undefined);
				return _;
			}

			keys.push(key);
			slash = slash || '';
			return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || '([^/]+?)') + ')' + (optional || '');
		})
		.replace(/([\/.])/g, '\\$1')
		.replace(/\*/g, '(.*)');
	return new RegExp('^' + path + '$', 'i');
}

/**
 * Routes an url thought a valid, predefined, path.
 *
 * @param {!Object=} options Setup options.
 * @param {!boolean=} options.firstMatch If true the router will stop
 *   at the first path matched. The default is false, and tries to
 *   match every path.
 * @constructor
 */
var Router = function(options) {
	options = options || {};
	/**
	 * Stops routing at first successful match.
	 *
	 * @type {!boolean}
	 * @private
	 */
	this.firstMatchStop = options.firstMatch || false;
	/**
	 * Chain of promises.
	 *
	 * @type {!Array.<!Object>}
	 * @private
	 */
	this.promises = [];
	/**
	 * Otherwise promise.
	 *
	 * @type {!function(!string=)}
	 * @private
	 */
	this.otherwiseFn = function() {};
	/**
	 * Error promise.
	 *
	 * @type {!function(!string=)}
	 * @private
	 */
	this.errorFn = function() {};
};
Router.prototype = {
	constructor: Router,
	/**
	 * Promise to url match. It's promise will fire only if the path
	 *   matches with and url being routed.
	 *
	 * @param  {!(string|RegExp|function(string):?)} path The
	 *   path or regular expression to match an url.
	 *   Alternatively a function that receives the url to be matched
	 *   can be passed. If the result is false, or any
	 *   !!result===false), the path is considered valid and the
	 *   scraping should be done. If ,in case of a valid path, an Object is returned, it will be associated with the params of this
	 *   route/path.
	 *   For more information on the path matching refer to {@link https://github.com/aaronblohowiak/routes.js/blob/76bc517037a0321507c4d84a0cdaca6db31ebaa4/README.md#path-formats}
	 * @return {!Router} This router.
	 * @public
	 */
	on: function(path) {
		var callback;
		if (typeof path === 'function') {
			callback = path;
		}

		this.promises.push({
			callback: callback ? function(url) {
				return callback(url);
			} : Router.pathMatcher(path),
			scraper: null,
			rqMethod: null
		});
		return this.get();
	},
	/**
	 * Sets the request method to be a simple HTTP GET.
	 * {@see AbstractScraper.get}
	 *
	 * @return {!Router} This router.
	 * @public
	 */
	get: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last) {
			last.rqMethod = function(url) {
				last.scraper.get(url);
			};
			return this;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Sets the request method to be according to the options.
	 * {@see AbstractScraper.request}
	 *
	 * @param  {!Object} options Request options.
	 * @return {!Router} This router.
	 * @public
	 */
	request: function(options) {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last) {
			last.rqMethod = function(url) {
				options.uri = url;
				last.scraper.request(options);
			};
			return this;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * On error promise. This promise fires when an error is thrown,
	 *   at this level there shouldn't be any error.
	 * This is a one time promise, which means that the last promise
	 *   is gonna be the one to be executed, if needed be.
	 *
	 * @param  {!function(!string, ?)} callback Function with the url
	 *   and the error as the parameters.
	 * @return {!Router} This router.
	 * @public
	 */
	onError: function(callback) {
		this.errorFn = callback;
		return this;
	},
	/**
	 * A promise to be triggered when none of the paths where matched.
	 * This is a one time promise, which means that the last promise
	 *   is gonna be the one to be executed.
	 *
	 * @param  {!function(!string=)} callback Function with the url as
	 *   a parameter.
	 * @return {!Router} This router.
	 * @public
	 */
	otherwise: function(callback) {
		this.otherwiseFn = callback;
		return this;
	},
	/**
	 * Creates a static scraper, and associates it with the current
	 *   router promise chain. Note that this method returns a
	 *   {@see ScraperPromise} of a {@see StaticScraper}.
	 *
	 * @return {!ScraperPromise} A promise for the scraper.
	 * @public
	 */
	createStatic: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last && !last.scraper) {
			var ss = StaticScraper.create();
			last.scraper = ss;
			return ss;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Creates a dynamic scraper, and associates it with the current
	 *   router promise chain. Note that this method returns a
	 *   {@see ScraperPromise} of a {@see DynamicScraper}.
	 *
	 * @return {!ScraperPromise} A promise for the scraper.
	 * @public
	 */
	createDynamic: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last && !last.scraper) {
			var ss = DynamicScraper.create();
			last.scraper = ss;
			return ss;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Routes a url through every path that matches it.
	 *
	 * @param  {!string} url The url to route.
	 * @param  {!function(boolean)} callback Function to call when the
	 *   routing is complete. If any of the paths was found the
	 *   parameter is true, false otherwise.
	 * @return {!Router} This router.
	 * @public
	 */
	route: function(url, callback) {
		var that = this,
			atLeastOne = false,
			stopFlag = {};
		callback = callback || function() {};
		async.eachSeries(this.promises, function(promiseObj, done) {

			var matcher = promiseObj.callback,
				scraper = promiseObj.scraper,
				reqMethod = promiseObj.rqMethod;
			var result = matcher(url);
			if (!!result) {
				atLeastOne = true;
				scraper._setChainParameter(result);
				scraper.done(function() {
					done(that.firstMatchStop?stopFlag:undefined);
				});
				reqMethod(url);
			} else {
				done();
			}

		}, function(err) {
			if (err === stopFlag) {
				callback(atLeastOne);
			} else if (err) {
				that.errorFn(err);
			} else if (!atLeastOne) {
				that.otherwiseFn(url);
				callback(atLeastOne);
			} else {
				callback(atLeastOne);
			}
		});
		return this;
	}
};
/**
 * Creates a function to match a path against a string.
 *
 * @param  {!(string|RegExp)} pathOrRE Pattern to match, if it's a
 *   string it will be transformed into a regular expression.
 * @return {!function(string):(Object|booelan)} A matching function,
 *   that given a string will check if it matches the path. If the
 *   path has parameters it will return an object with the parameters
 *   as keys and the values as the values of the parameters. An empty
 *   object if there were no valid parameters or false if the path
 *   doesn't match with the string.
 * @public
 * @static
 */
Router.pathMatcher = function(pathOrRE) {
	var pattern,
		keys = ['url'];
	if (pathOrRE instanceof RegExp) {
		pattern = pathOrRE;
	} else if (typeof pathOrRE === 'string') {
		pattern = pathToRegExp(pathOrRE, keys);
	} else {
		throw new Error('A path must be a string or a regular expression.');
	}

	return function patternMatchingFunction(url) {
		var match = pattern.exec(url);
		if (!match) {
			return false;
		} else if (match instanceof Object) {
			return keys.reduce(function(obj, value, index) {
				obj[value] = match[index];
				return obj;
			}, {});
		} else {
			return {};
		}
	};
};

module.exports = Router;<commit_msg>Added use promise to the router. It allows to use a previously instantiated scraper.<commit_after>var async = require('async'),
	StaticScraper = require('./StaticScraper'),
	DynamicScraper = require('./DynamicScraper'),
	ScraperError = require('./ScraperError');

/**
 * Transforms a string into a regular expression.
 * This function is from the project Routes.js, under the MIT licence,
 *   {@link https://github.com/aaronblohowiak/routes.js} it's present
 *   in the file {@link https://github.com/aaronblohowiak/routes.js/blob/bdad0a1ae10d11981bb286550bb3b8a1a71909bd/dist/routes.js#L49}.
 *
 * @param  {!string} path String path.
 * @param  {!Array.<string>} keys Empty array to be filled with the
 *   keys ids.
 * @return {!RegExp} Regular expression.
 */
function pathToRegExp(path, keys) {
	path = path
		.concat('/?')
		.replace(/\/\(/g, '(?:/')
		.replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?|\*/g, function(_, slash, format, key, capture, optional) {
			if (_ === '*') {
				keys.push(undefined);
				return _;
			}

			keys.push(key);
			slash = slash || '';
			return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || '([^/]+?)') + ')' + (optional || '');
		})
		.replace(/([\/.])/g, '\\$1')
		.replace(/\*/g, '(.*)');
	return new RegExp('^' + path + '$', 'i');
}

/**
 * Routes an url thought a valid, predefined, path.
 *
 * @param {!Object=} options Setup options.
 * @param {!boolean=} options.firstMatch If true the router will stop
 *   at the first path matched. The default is false, and tries to
 *   match every path.
 * @constructor
 */
var Router = function(options) {
	options = options || {};
	/**
	 * Stops routing at first successful match.
	 *
	 * @type {!boolean}
	 * @private
	 */
	this.firstMatchStop = options.firstMatch || false;
	/**
	 * Chain of promises.
	 *
	 * @type {!Array.<!Object>}
	 * @private
	 */
	this.promises = [];
	/**
	 * Otherwise promise.
	 *
	 * @type {!function(!string=)}
	 * @private
	 */
	this.otherwiseFn = function() {};
	/**
	 * Error promise.
	 *
	 * @type {!function(!string=)}
	 * @private
	 */
	this.errorFn = function() {};
};
Router.prototype = {
	constructor: Router,
	/**
	 * Promise to url match. It's promise will fire only if the path
	 *   matches with and url being routed.
	 *
	 * @param  {!(string|RegExp|function(string):?)} path The
	 *   path or regular expression to match an url.
	 *   Alternatively a function that receives the url to be matched
	 *   can be passed. If the result is false, or any
	 *   !!result===false), the path is considered valid and the
	 *   scraping should be done. If ,in case of a valid path, an Object is returned, it will be associated with the params of this
	 *   route/path.
	 *   For more information on the path matching refer to {@link https://github.com/aaronblohowiak/routes.js/blob/76bc517037a0321507c4d84a0cdaca6db31ebaa4/README.md#path-formats}
	 * @return {!Router} This router.
	 * @public
	 */
	on: function(path) {
		var callback;
		if (typeof path === 'function') {
			callback = path;
		}

		this.promises.push({
			callback: callback ? function(url) {
				return callback(url);
			} : Router.pathMatcher(path),
			scraper: null,
			rqMethod: null
		});
		return this.get();
	},
	/**
	 * Sets the request method to be a simple HTTP GET.
	 * {@see AbstractScraper.get}
	 *
	 * @return {!Router} This router.
	 * @public
	 */
	get: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last) {
			last.rqMethod = function(url) {
				last.scraper.get(url);
			};
			return this;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Sets the request method to be according to the options.
	 * {@see AbstractScraper.request}
	 *
	 * @param  {!Object} options Request options.
	 * @return {!Router} This router.
	 * @public
	 */
	request: function(options) {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last) {
			last.rqMethod = function(url) {
				options.uri = url;
				last.scraper.request(options);
			};
			return this;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * On error promise. This promise fires when an error is thrown,
	 *   at this level there shouldn't be any error.
	 * This is a one time promise, which means that the last promise
	 *   is gonna be the one to be executed, if needed be.
	 *
	 * @param  {!function(!string, ?)} callback Function with the url
	 *   and the error as the parameters.
	 * @return {!Router} This router.
	 * @public
	 */
	onError: function(callback) {
		this.errorFn = callback;
		return this;
	},
	/**
	 * A promise to be triggered when none of the paths where matched.
	 * This is a one time promise, which means that the last promise
	 *   is gonna be the one to be executed.
	 *
	 * @param  {!function(!string=)} callback Function with the url as
	 *   a parameter.
	 * @return {!Router} This router.
	 * @public
	 */
	otherwise: function(callback) {
		this.otherwiseFn = callback;
		return this;
	},
	/**
	 * Creates a static scraper, and associates it with the current
	 *   router promise chain. Note that this method returns a
	 *   {@see ScraperPromise} of a {@see StaticScraper}.
	 *
	 * @return {!ScraperPromise} A promise for the scraper.
	 * @public
	 */
	createStatic: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last && !last.scraper) {
			var ss = StaticScraper.create();
			last.scraper = ss;
			return ss;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Associates the current route with the a scraper instance. Keep
	 *   in mind that the done promise will not be available.
	 *
	 * @param  {!AbstractScraper} scraper A scraper instance to use.
	 * @return {!Router} This router.
	 * @public
	 */
	use: function(scraper) {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last && !last.scraper) {
			last.scraper = scraper;
			return this;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Creates a dynamic scraper, and associates it with the current
	 *   router promise chain. Note that this method returns a
	 *   {@see ScraperPromise} of a {@see DynamicScraper}.
	 *
	 * @return {!ScraperPromise} A promise for the scraper.
	 * @public
	 */
	createDynamic: function() {
		var length = this.promises.length,
			last = this.promises[length - 1];
		if (length && last && !last.scraper) {
			var ss = DynamicScraper.create();
			last.scraper = ss;
			return ss;
		} else {
			throw new ScraperError('');
		}
	},
	/**
	 * Routes a url through every path that matches it.
	 *
	 * @param  {!string} url The url to route.
	 * @param  {!function(boolean)} callback Function to call when the
	 *   routing is complete. If any of the paths was found the
	 *   parameter is true, false otherwise.
	 * @return {!Router} This router.
	 * @public
	 */
	route: function(url, callback) {
		var that = this,
			atLeastOne = false,
			stopFlag = {};
		callback = callback || function() {};
		async.eachSeries(this.promises, function(promiseObj, done) {

			var matcher = promiseObj.callback,
				scraper = promiseObj.scraper,
				reqMethod = promiseObj.rqMethod;
			var result = matcher(url);
			if (!!result) {
				atLeastOne = true;
				scraper._setChainParameter(result);
				scraper.done(function() {
					done(that.firstMatchStop ? stopFlag : undefined);
				});
				reqMethod(url);
			} else {
				done();
			}

		}, function(err) {
			if (err === stopFlag) {
				callback(atLeastOne);
			} else if (err) {
				that.errorFn(err);
			} else if (!atLeastOne) {
				that.otherwiseFn(url);
				callback(atLeastOne);
			} else {
				callback(atLeastOne);
			}
		});
		return this;
	}
};
/**
 * Creates a function to match a path against a string.
 *
 * @param  {!(string|RegExp)} pathOrRE Pattern to match, if it's a
 *   string it will be transformed into a regular expression.
 * @return {!function(string):(Object|booelan)} A matching function,
 *   that given a string will check if it matches the path. If the
 *   path has parameters it will return an object with the parameters
 *   as keys and the values as the values of the parameters. An empty
 *   object if there were no valid parameters or false if the path
 *   doesn't match with the string.
 * @public
 * @static
 */
Router.pathMatcher = function(pathOrRE) {
	var pattern,
		keys = ['url'];
	if (pathOrRE instanceof RegExp) {
		pattern = pathOrRE;
	} else if (typeof pathOrRE === 'string') {
		pattern = pathToRegExp(pathOrRE, keys);
	} else {
		throw new Error('A path must be a string or a regular expression.');
	}

	return function patternMatchingFunction(url) {
		var match = pattern.exec(url);
		if (!match) {
			return false;
		} else if (match instanceof Object) {
			return keys.reduce(function(obj, value, index) {
				obj[value] = match[index];
				return obj;
			}, {});
		} else {
			return {};
		}
	};
};

module.exports = Router;<|endoftext|>


<commit_before>'use strict';

var Promise = require('es6-promise').Promise;

var cValue = require('./value');
var credentials = require('./credentials');
var harvest = require('./harvest');

var view = exports;
view.output = {};

view.execute = function (ctx) {
  return new Promise(function (resolve, reject) {
    var params = harvest.get(ctx);

    return credentials.get(ctx.api, params)
    .then(resolve)
    .catch(reject);
  });
};

view.output.success = function (ctx, results) {
  var creds = results.credentials;
  var isVerbose = ctx.option('verbose').value === true;

  if (isVerbose) {
    console.log('Execution Context: ' + results.path);
  }

  creds.forEach(function (cred) {
    var value = cValue.parse(cred.body.value);

    if (value.body.type === 'undefined') {
      return;
    }

    var line = cred.body.name.toUpperCase() + '=' + value.body.value;

    if (isVerbose) {
      line += ' (sourced from: ' + cred.body.pathexp + '/' +
        cred.body.name + ')';
    }

    console.log(line);
  });
};

view.output.failure = function () {
  console.log('It didnt work :(');
};
<commit_msg>Fix spacing of 'ag view -v'<commit_after>'use strict';

var Promise = require('es6-promise').Promise;

var cValue = require('./value');
var credentials = require('./credentials');
var harvest = require('./harvest');

var view = exports;
view.output = {};

view.execute = function (ctx) {
  return new Promise(function (resolve, reject) {
    var params = harvest.get(ctx);

    return credentials.get(ctx.api, params)
    .then(resolve)
    .catch(reject);
  });
};

view.output.success = function (ctx, results) {
  var creds = results.credentials;
  var isVerbose = ctx.option('verbose').value === true;

  if (isVerbose) {
    console.log('Execution Context: ' + results.path + '\n');
  }

  creds.forEach(function (cred) {
    var value = cValue.parse(cred.body.value);

    if (value.body.type === 'undefined') {
      return;
    }

    var line = cred.body.name.toUpperCase() + '=' + value.body.value;

    if (isVerbose) {
      line += ' (sourced from: ' + cred.body.pathexp + '/' +
        cred.body.name + ')';
    }

    console.log(line);
  });
};

view.output.failure = function () {
  console.log('It didnt work :(');
};
<|endoftext|>


<commit_before>/**
 * @fileoverview Soundworks client side seat map module
 * @author Sebastien.Robaszkiewicz@ircam.fr, Norbert.Schnell@ircam.fr
 */
'use strict';

var ClientModule = require('./ClientModule');
var client = require("./client");

class ClientSeatmap extends ClientModule {
  constructor(options = {}) {
    super('seatmap', false);

    this.map = null;
  }

  start() {
    super.start();

    var socket = client.socket;

    socket.emit('seatmap_request');

    socket.on('seatmap_init', (map) => {
      this.map = map;
      this.done();
    });
  }

  display(div) {
    if (this.seatmap) {
      var mapRatio = this.map.height / this.map.width;
      var screenHeight = window.innerHeight;
      var screenWidth = window.innerWidth;
      var screenRatio = screenHeight / screenWidth;
      var mapHeightPx;
      var mapWidthPx;

      if (screenRatio > mapRatio) { // TODO: refine sizes, with container, etc.
        mapHeightPx = screenWidth * mapRatio;
        mapWidthPx = screenWidth;
      } else {
        mapHeightPx = screenHeight;
        mapWidthPx = screenHeight / mapRatio;
      }

      var xTileSize = mapWidthPx / this.map.maxWidthDivision;
      var yTileSize = mapHeightPx / this.map.maxHeightDivision;
      var tileSize = Math.min(xTileSize, yTileSize);

      var tileMargin = tileSize / 10;

      div.style.height = mapHeightPx + "px";
      div.style.width = mapWidthPx + "px";

      var positions = this.map.positions;

      for (let i = 0; i < positions.length; i++) {
        let tile = document.createElement('div');
        tile.classList.add('tile');
        tile.setAttribute('data-index', i);
        tile.setAttribute('data-x', positions[i][0]);
        tile.setAttribute('data-y', positions[i][1]);
        tile.style.height = tileSize - 2 * tileMargin + "px";
        tile.style.width = tileSize - 2 * tileMargin + "px";
        tile.style.left = positions[i][0] * mapWidthPx - (tileSize - 2 * tileMargin) / 2 + "px";
        tile.style.top = positions[i][1] * mapHeightPx - (tileSize - 2 * tileMargin) / 2 + "px";
        div.appendChild(tile);
      }
    }
  }

  addClassToTile(div, index, className = 'player') {
    var tiles = Array.prototype.slice.call(div.childNodes); // .childNode returns a NodeList
    var tileIndex = tiles.map((t) => parseInt(t.dataset.index)).indexOf(index);
    var tile = tiles[tileIndex];

    if (tile)
      tile.classList.add(className);
  }

  removeClassFromTile(div, index, className = 'player') {
    var tiles = Array.prototype.slice.call(div.childNodes); // .childNode returns a NodeList
    var tileIndex = tiles.map((t) => parseInt(t.dataset.index)).indexOf(index);
    var tile = tiles[tileIndex];

    if (tile)
      tile.classList.remove(className);
  }
}

module.exports = ClientSeatmap;<commit_msg>Bug corrected<commit_after>/**
 * @fileoverview Soundworks client side seat map module
 * @author Sebastien.Robaszkiewicz@ircam.fr, Norbert.Schnell@ircam.fr
 */
'use strict';

var ClientModule = require('./ClientModule');
var client = require("./client");

class ClientSeatmap extends ClientModule {
  constructor(options = {}) {
    super('seatmap', false);

    this.map = null;
  }

  start() {
    super.start();

    var socket = client.socket;

    socket.emit('seatmap_request');

    socket.on('seatmap_init', (map) => {
      this.map = map;
      this.done();
    });
  }

  display(div) {
    if (this.map) {
      var mapRatio = this.map.height / this.map.width;
      var screenHeight = window.innerHeight;
      var screenWidth = window.innerWidth;
      var screenRatio = screenHeight / screenWidth;
      var mapHeightPx;
      var mapWidthPx;

      if (screenRatio > mapRatio) { // TODO: refine sizes, with container, etc.
        mapHeightPx = screenWidth * mapRatio;
        mapWidthPx = screenWidth;
      } else {
        mapHeightPx = screenHeight;
        mapWidthPx = screenHeight / mapRatio;
      }

      var xTileSize = mapWidthPx / this.map.maxWidthDivision;
      var yTileSize = mapHeightPx / this.map.maxHeightDivision;
      var tileSize = Math.min(xTileSize, yTileSize);

      var tileMargin = tileSize / 10;

      div.style.height = mapHeightPx + "px";
      div.style.width = mapWidthPx + "px";

      var positions = this.map.positions;

      for (let i = 0; i < positions.length; i++) {
        let tile = document.createElement('div');
        tile.classList.add('tile');
        tile.setAttribute('data-index', i);
        tile.setAttribute('data-x', positions[i][0]);
        tile.setAttribute('data-y', positions[i][1]);
        tile.style.height = tileSize - 2 * tileMargin + "px";
        tile.style.width = tileSize - 2 * tileMargin + "px";
        tile.style.left = positions[i][0] * mapWidthPx - (tileSize - 2 * tileMargin) / 2 + "px";
        tile.style.top = positions[i][1] * mapHeightPx - (tileSize - 2 * tileMargin) / 2 + "px";
        div.appendChild(tile);
      }
    }
  }

  addClassToTile(div, index, className = 'player') {
    var tiles = Array.prototype.slice.call(div.childNodes); // .childNode returns a NodeList
    var tileIndex = tiles.map((t) => parseInt(t.dataset.index)).indexOf(index);
    var tile = tiles[tileIndex];

    if (tile)
      tile.classList.add(className);
  }

  removeClassFromTile(div, index, className = 'player') {
    var tiles = Array.prototype.slice.call(div.childNodes); // .childNode returns a NodeList
    var tileIndex = tiles.map((t) => parseInt(t.dataset.index)).indexOf(index);
    var tile = tiles[tileIndex];

    if (tile)
      tile.classList.remove(className);
  }
}

module.exports = ClientSeatmap;<|endoftext|>


<commit_before>import moment from 'moment';
import { capitalize as _capitalize, isEmpty } from 'lodash';

export function durationHumanize(duration) {
  let humanized = '';

  if (duration === undefined) {
    humanized = '-';
  } else if (duration < 60) {
    const seconds = Math.round(duration);
    humanized = `${seconds} seconds`;
  } else if (duration > 3600 * 24) {
    const days = Math.round(parseFloat(duration) / 60.0 / 60.0 / 24.0);
    humanized = `${days} days`;
  } else if (duration === 3600) {
    humanized = '1 hour';
  } else if (duration >= 3600) {
    const hours = Math.round(parseFloat(duration) / 60.0 / 60.0);
    humanized = `${hours} hours`;
  } else if (duration === 60) {
    humanized = '1 minute';
  } else {
    const minutes = Math.round(parseFloat(duration) / 60.0);
    humanized = `${minutes} minutes`;
  }
  return humanized;
}

export function scheduleHumanize(schedule) {
  if (schedule === null) {
    return 'Never';
  } else if (schedule.match(/\d\d:\d\d/) !== null) {
    const parts = schedule.split(':');
    const localTime = moment.utc()
      .hour(parts[0])
      .minute(parts[1])
      .local()
      .format('HH:mm');

    return `Every day at ${localTime}`;
  }

  return `Every ${durationHumanize(parseInt(schedule, 10))}`;
}

export function toHuman(text) {
  return text.replace(/_/g, ' ').replace(/(?:^|\s)\S/g, a =>
    a.toUpperCase());
}

export function colWidth(widgetWidth) {
  if (widgetWidth === 0) {
    return 0;
  } else if (widgetWidth === 1) {
    return 6;
  } else if (widgetWidth === 2) {
    return 12;
  }
  return widgetWidth;
}

export function capitalize(text) {
  if (text) {
    return _capitalize(text);
  }

  return null;
}

export function remove(items, item) {
  if (items === undefined) {
    return items;
  }

  let notEquals;

  if (item instanceof Array) {
    notEquals = other => item.indexOf(other) === -1;
  } else {
    notEquals = other => item !== other;
  }

  const filtered = [];

  for (let i = 0; i < items.length; i += 1) {
    if (notEquals(items[i])) {
      filtered.push(items[i]);
    }
  }

  return filtered;
}

export function notEmpty(collection) {
  return !isEmpty(collection);
}

export function showError(field) {
  // In case of booleans, we get an undefined here.
  if (field === undefined) {
    return false;
  }
  return field.$touched && field.$invalid;
}

const units = [
  'bytes',
  'KB',
  'MB',
  'GB',
  'TB',
  'PB',
];

export function prettySize(bytes) {
  if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) {
    return '?';
  }

  let unit = 0;

  while (bytes >= 1024) {
    bytes /= 1024;
    unit += 1;
  }

  return bytes.toFixed(3) + ' ' + units[unit];
}

export function join(arr) {
  if (arr === undefined || arr === null) {
    return '';
  }

  return arr.join(' / ');
}
<commit_msg>Show null duration as '-'.<commit_after>import moment from 'moment';
import { capitalize as _capitalize, isEmpty } from 'lodash';

export function durationHumanize(duration) {
  let humanized = '';

  if (duration === undefined || duration === null) {
    humanized = '-';
  } else if (duration < 60) {
    const seconds = Math.round(duration);
    humanized = `${seconds} seconds`;
  } else if (duration > 3600 * 24) {
    const days = Math.round(parseFloat(duration) / 60.0 / 60.0 / 24.0);
    humanized = `${days} days`;
  } else if (duration === 3600) {
    humanized = '1 hour';
  } else if (duration >= 3600) {
    const hours = Math.round(parseFloat(duration) / 60.0 / 60.0);
    humanized = `${hours} hours`;
  } else if (duration === 60) {
    humanized = '1 minute';
  } else {
    const minutes = Math.round(parseFloat(duration) / 60.0);
    humanized = `${minutes} minutes`;
  }
  return humanized;
}

export function scheduleHumanize(schedule) {
  if (schedule === null) {
    return 'Never';
  } else if (schedule.match(/\d\d:\d\d/) !== null) {
    const parts = schedule.split(':');
    const localTime = moment
      .utc()
      .hour(parts[0])
      .minute(parts[1])
      .local()
      .format('HH:mm');

    return `Every day at ${localTime}`;
  }

  return `Every ${durationHumanize(parseInt(schedule, 10))}`;
}

export function toHuman(text) {
  return text.replace(/_/g, ' ').replace(/(?:^|\s)\S/g, a => a.toUpperCase());
}

export function colWidth(widgetWidth) {
  if (widgetWidth === 0) {
    return 0;
  } else if (widgetWidth === 1) {
    return 6;
  } else if (widgetWidth === 2) {
    return 12;
  }
  return widgetWidth;
}

export function capitalize(text) {
  if (text) {
    return _capitalize(text);
  }

  return null;
}

export function remove(items, item) {
  if (items === undefined) {
    return items;
  }

  let notEquals;

  if (item instanceof Array) {
    notEquals = other => item.indexOf(other) === -1;
  } else {
    notEquals = other => item !== other;
  }

  const filtered = [];

  for (let i = 0; i < items.length; i += 1) {
    if (notEquals(items[i])) {
      filtered.push(items[i]);
    }
  }

  return filtered;
}

export function notEmpty(collection) {
  return !isEmpty(collection);
}

export function showError(field) {
  // In case of booleans, we get an undefined here.
  if (field === undefined) {
    return false;
  }
  return field.$touched && field.$invalid;
}

const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];

export function prettySize(bytes) {
  if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) {
    return '?';
  }

  let unit = 0;

  while (bytes >= 1024) {
    bytes /= 1024;
    unit += 1;
  }

  return bytes.toFixed(3) + ' ' + units[unit];
}

export function join(arr) {
  if (arr === undefined || arr === null) {
    return '';
  }

  return arr.join(' / ');
}
<|endoftext|>


<commit_before>jQuery(document).ready(function ($) {

  /* Use this js doc for all application specific JS */

  /* TABS --------------------------------- */
  /* Remove if you don't need :) */

  function activateTab($tab) {
    var $activeTab = $tab.closest('dl').find('dd.active'),
        contentLocation = $tab.children('a').attr("href") + 'Tab';

    // Strip off the current url that IE adds
    contentLocation = contentLocation.replace(/^.+#/, '#');

    //Make Tab Active
    $activeTab.removeClass('active');
    $tab.addClass('active');

    //Show Tab Content
    $(contentLocation).closest('.tabs-content').children('li').removeClass('active').hide();
    $(contentLocation).css('display', 'block').addClass('active');
  }

  $('dl.tabs dd a').on('click.fndtn', function (event) {
    activateTab($(this).parent('dd'));
  });

  if (window.location.hash) {
    activateTab($('a[href="' + window.location.hash + '"]').parent('dd'));
    $.foundation.customForms.appendCustomMarkup();
  }

  /* ALERT BOXES ------------ */
  $(".alert-box").delegate("a.close", "click", function(event) {
    event.preventDefault();
    $(this).closest(".alert-box").fadeOut(function(event){
      $(this).remove();
    });
  });

  /* PLACEHOLDER FOR FORMS ------------- */
  /* Remove this and jquery.placeholder.min.js if you don't need :) */
  $('input, textarea').placeholder();

  /* TOOLTIPS ------------ */
  $(this).tooltips();

  /* UNCOMMENT THE LINE YOU WANT BELOW IF YOU WANT IE6/7/8 SUPPORT AND ARE USING .block-grids */
  //  $('.block-grid.two-up>li:nth-child(2n+1)').css({clear: 'left'});
  //  $('.block-grid.three-up>li:nth-child(3n+1)').css({clear: 'left'});
  //  $('.block-grid.four-up>li:nth-child(4n+1)').css({clear: 'left'});
  //  $('.block-grid.five-up>li:nth-child(5n+1)').css({clear: 'left'});

  /* DROPDOWN NAV ------------- */

  var lockNavBar = false;
  /* Windows Phone, sadly, does not register touch events :( */
  if (Modernizr.touch || navigator.userAgent.match(/Windows Phone/i)) {
    $('.nav-bar a.flyout-toggle').on('click.fndtn touchstart.fndtn', function(e) {
      e.preventDefault();
      var flyout = $(this).siblings('.flyout').first();
      if (lockNavBar === false) {
        $('.nav-bar .flyout').not(flyout).slideUp(500);
        flyout.slideToggle(500, function(){
          lockNavBar = false;
        });
      }
      lockNavBar = true;
    });
    $('.nav-bar>li.has-flyout').addClass('is-touch');
  } else {
    $('.nav-bar>li.has-flyout').hover(function() {
      $(this).children('.flyout').show();
    }, function() {
      $(this).children('.flyout').hide();
    });
  }

  /* DISABLED BUTTONS ------------- */
  /* Gives elements with a class of 'disabled' a return: false; */
  $('.button.disabled').on('click.fndtn', function (event) {
    event.preventDefault();
  });

  /* SPLIT BUTTONS/DROPDOWNS */
  $('.button.dropdown > ul').addClass('no-hover');

  $('.button.dropdown').on('click.fndtn', function (e) {
    e.stopPropagation();
  });
  $('.button.dropdown.split span').on('click.fndtn', function (e) {
    e.preventDefault();
    $('.button.dropdown').not($(this).parent()).children('ul').removeClass('show-dropdown');
    $(this).siblings('ul').toggleClass('show-dropdown');
  });
  $('.button.dropdown').not('.split').on('click.fndtn', function (e) {
    $('.button.dropdown').not(this).children('ul').removeClass('show-dropdown');
    $(this).children('ul').toggleClass('show-dropdown');
  });
  $('body, html').on('click.fndtn', function () {
    $('.button.dropdown ul').removeClass('show-dropdown');
  });

  // Positioning the Flyout List
  var normalButtonHeight  = $('.button.dropdown:not(.large):not(.small):not(.tiny)').outerHeight() - 1,
      largeButtonHeight   = $('.button.large.dropdown').outerHeight() - 1,
      smallButtonHeight   = $('.button.small.dropdown').outerHeight() - 1,
      tinyButtonHeight    = $('.button.tiny.dropdown').outerHeight() - 1;

  $('.button.dropdown:not(.large):not(.small):not(.tiny) > ul').css('top', normalButtonHeight);
  $('.button.dropdown.large > ul').css('top', largeButtonHeight);
  $('.button.dropdown.small > ul').css('top', smallButtonHeight);
  $('.button.dropdown.tiny > ul').css('top', tinyButtonHeight);

  $('.button.dropdown.up:not(.large):not(.small):not(.tiny) > ul').css('top', 'auto').css('bottom', normalButtonHeight - 2);
  $('.button.dropdown.up.large > ul').css('top', 'auto').css('bottom', largeButtonHeight - 2);
  $('.button.dropdown.up.small > ul').css('top', 'auto').css('bottom', smallButtonHeight - 2);
  $('.button.dropdown.up.tiny > ul').css('top', 'auto').css('bottom', tinyButtonHeight - 2);

  /* CUSTOM FORMS */
  $.foundation.customForms.appendCustomMarkup();

});<commit_msg>Added in accordion functionality.<commit_after>jQuery(document).ready(function ($) {

  /* Use this js doc for all application specific JS */

  /* TABS --------------------------------- */
  /* Remove if you don't need :) */

  function activateTab($tab) {
    var $activeTab = $tab.closest('dl').find('dd.active'),
        contentLocation = $tab.children('a').attr("href") + 'Tab';

    // Strip off the current url that IE adds
    contentLocation = contentLocation.replace(/^.+#/, '#');

    //Make Tab Active
    $activeTab.removeClass('active');
    $tab.addClass('active');

    //Show Tab Content
    $(contentLocation).closest('.tabs-content').children('li').removeClass('active').hide();
    $(contentLocation).css('display', 'block').addClass('active');
  }

  $('dl.tabs dd a').on('click.fndtn', function (event) {
    activateTab($(this).parent('dd'));
  });

  if (window.location.hash) {
    activateTab($('a[href="' + window.location.hash + '"]').parent('dd'));
    $.foundation.customForms.appendCustomMarkup();
  }

  /* ALERT BOXES ------------ */
  $(".alert-box").delegate("a.close", "click", function(event) {
    event.preventDefault();
    $(this).closest(".alert-box").fadeOut(function(event){
      $(this).remove();
    });
  });

  /* PLACEHOLDER FOR FORMS ------------- */
  /* Remove this and jquery.placeholder.min.js if you don't need :) */
  $('input, textarea').placeholder();

  /* TOOLTIPS ------------ */
  $(this).tooltips();

  /* UNCOMMENT THE LINE YOU WANT BELOW IF YOU WANT IE6/7/8 SUPPORT AND ARE USING .block-grids */
  //  $('.block-grid.two-up>li:nth-child(2n+1)').css({clear: 'left'});
  //  $('.block-grid.three-up>li:nth-child(3n+1)').css({clear: 'left'});
  //  $('.block-grid.four-up>li:nth-child(4n+1)').css({clear: 'left'});
  //  $('.block-grid.five-up>li:nth-child(5n+1)').css({clear: 'left'});

  /* DROPDOWN NAV ------------- */

  var lockNavBar = false;
  /* Windows Phone, sadly, does not register touch events :( */
  if (Modernizr.touch || navigator.userAgent.match(/Windows Phone/i)) {
    $('.nav-bar a.flyout-toggle').on('click.fndtn touchstart.fndtn', function(e) {
      e.preventDefault();
      var flyout = $(this).siblings('.flyout').first();
      if (lockNavBar === false) {
        $('.nav-bar .flyout').not(flyout).slideUp(500);
        flyout.slideToggle(500, function(){
          lockNavBar = false;
        });
      }
      lockNavBar = true;
    });
    $('.nav-bar>li.has-flyout').addClass('is-touch');
  } else {
    $('.nav-bar>li.has-flyout').hover(function() {
      $(this).children('.flyout').show();
    }, function() {
      $(this).children('.flyout').hide();
    });
  }

  // Accordion
  $('.accordion li').on('click.fndtn', function() {
    var flyout = $(this).children('.content').first();
    if (lockNavBar === false) {
      $('.accordion .content').not(flyout).slideUp(500).parent('li').removeClass('active');
      flyout.slideToggle(500, function() {
        flyout.parent('li').addClass('active');
        lockNavBar = false;
      });
    }
    lockNavBar = true;
  });

  /* DISABLED BUTTONS ------------- */
  /* Gives elements with a class of 'disabled' a return: false; */
  $('.button.disabled').on('click.fndtn', function (event) {
    event.preventDefault();
  });

  /* SPLIT BUTTONS/DROPDOWNS */
  $('.button.dropdown > ul').addClass('no-hover');

  $('.button.dropdown').on('click.fndtn', function (e) {
    e.stopPropagation();
  });
  $('.button.dropdown.split span').on('click.fndtn', function (e) {
    e.preventDefault();
    $('.button.dropdown').not($(this).parent()).children('ul').removeClass('show-dropdown');
    $(this).siblings('ul').toggleClass('show-dropdown');
  });
  $('.button.dropdown').not('.split').on('click.fndtn', function (e) {
    $('.button.dropdown').not(this).children('ul').removeClass('show-dropdown');
    $(this).children('ul').toggleClass('show-dropdown');
  });
  $('body, html').on('click.fndtn', function () {
    $('.button.dropdown ul').removeClass('show-dropdown');
  });

  // Positioning the Flyout List
  var normalButtonHeight  = $('.button.dropdown:not(.large):not(.small):not(.tiny)').outerHeight() - 1,
      largeButtonHeight   = $('.button.large.dropdown').outerHeight() - 1,
      smallButtonHeight   = $('.button.small.dropdown').outerHeight() - 1,
      tinyButtonHeight    = $('.button.tiny.dropdown').outerHeight() - 1;

  $('.button.dropdown:not(.large):not(.small):not(.tiny) > ul').css('top', normalButtonHeight);
  $('.button.dropdown.large > ul').css('top', largeButtonHeight);
  $('.button.dropdown.small > ul').css('top', smallButtonHeight);
  $('.button.dropdown.tiny > ul').css('top', tinyButtonHeight);

  $('.button.dropdown.up:not(.large):not(.small):not(.tiny) > ul').css('top', 'auto').css('bottom', normalButtonHeight - 2);
  $('.button.dropdown.up.large > ul').css('top', 'auto').css('bottom', largeButtonHeight - 2);
  $('.button.dropdown.up.small > ul').css('top', 'auto').css('bottom', smallButtonHeight - 2);
  $('.button.dropdown.up.tiny > ul').css('top', 'auto').css('bottom', tinyButtonHeight - 2);

  /* CUSTOM FORMS */
  $.foundation.customForms.appendCustomMarkup();

});<|endoftext|>


<commit_before>// Some general UI pack related JS

$(function () {
    // Custom selects
    $("select").dropkick();
});

$(document).ready(function() {
    // Todo list
    $(".todo li").click(function() {
        $(this).toggleClass("todo-done");
    });

    // Init tooltips
    $("[data-toggle=tooltip]").tooltip("show");

    // Init tags input
    $("#tagsinput").tagsInput();

    // Init jQuery UI slider
    $("#slider").slider({
        min: 1,
        max: 5,
        value: 2,
        orientation: "horizontal",
        range: "min",
    });

    // JS input/textarea placeholder
    $("input, textarea").placeholder();

    // Make pagination demo work
    $(".pagination a").click(function() {
        if (!$(this).parent().hasClass("previous") && !$(this).parent().hasClass("next")) {
            $(this).parent().siblings("li").removeClass("active");
            $(this).parent().addClass("active");
        }
    });

    $(".btn-group a").click(function() {
        $(this).siblings().removeClass("active");
        $(this).addClass("active");
    });

    // Disable link click not scroll top
    $("a[href='#']").click(function() {
        return false
    });

});

<commit_msg>quick fix in javascripts<commit_after>// Some general UI pack related JS

$(function () {
    // Custom selects
    if($("select").length > 0) {
        $("select").dropkick();
    }
});

$(document).ready(function() {
    // Todo list
    $(".todo li").click(function() {
        $(this).toggleClass("todo-done");
    });

    // Init tooltips
    $("[data-toggle=tooltip]").tooltip("show");

    // Init tags input
    $("#tagsinput").tagsInput();

    // Init jQuery UI slider
    $("#slider").slider({
        min: 1,
        max: 5,
        value: 2,
        orientation: "horizontal",
        range: "min",
    });

    // JS input/textarea placeholder
    $("input, textarea").placeholder();

    // Make pagination demo work
    $(".pagination a").click(function() {
        if (!$(this).parent().hasClass("previous") && !$(this).parent().hasClass("next")) {
            $(this).parent().siblings("li").removeClass("active");
            $(this).parent().addClass("active");
        }
    });

    $(".btn-group a").click(function() {
        $(this).siblings().removeClass("active");
        $(this).addClass("active");
    });

    // Disable link click not scroll top
    $("a[href='#']").click(function() {
        return false
    });

});

<|endoftext|>


<commit_before>import React from 'react';
import _  from 'underscore';

export class SVGComponent extends React.Component {
    render() {
        return <svg {...this.props}>{this.props.children}</svg>
    }
}
export class Rectangle extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;

        var height = (this.props.height || 0) + 2 * strokeWidth;
        var width = (this.props.width || 0) + 2 * strokeWidth;
        var props = _.omit(this.props, 'style');

        return (
            <SVGComponent height={height} width={width}>
                <rect {...props} x={strokeWidth / 2} y={strokeWidth / 2}>{this.props.children}</rect>
            </SVGComponent>)
    }
}
export class Circle extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;
        var r = this.props.r || 0;

        var height = (r * 2) + 2 * strokeWidth;
        var width = (r * 2) + 2 * strokeWidth;

        var cx = r + strokeWidth;
        var cy = r + strokeWidth;
        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <circle {...props} cx={cx} cy={cy}>{this.props.children}</circle>
            </SVGComponent>)

    }
}
export class Ellipse extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;
        var rx = this.props.rx || 0;
        var ry = this.props.ry || 0;

        var height = (ry * 2) + 2 * strokeWidth;
        var width = (rx * 2) + 2 * strokeWidth;

        var cx = rx + strokeWidth;
        var cy = ry + strokeWidth;
        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <ellipse {...props} cx={cx} cy={cy}>{this.props.children}</ellipse>
            </SVGComponent>)

    }
}
export class Line extends React.Component {
    render() {

        var strokeWidth = this.props.strokeWidth || 0;
        var x = _.max([this.props.x1, this.props.x2]);
        var y = _.max([this.props.y1, this.props.y2]);

        var height = y + (2 * strokeWidth);
        var width = x + (2 * strokeWidth);

        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <line {...props}>{this.props.children}</line>
            </SVGComponent>)
    }
}
export class Polyline extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;

        var points = _.map(this.props.points.split(' '),function(point){
            var xy = point.split(',');
            return {x:parseInt(xy[0],10),y:parseInt(xy[1],10)};
        });
        var x = _.max(_.map(points,function(point){return point.x}));
        var y = _.max(_.map(points,function(point){return point.y}));

        console.log(points);

        var height = y + (2 * strokeWidth);
        var width = x + (2 * strokeWidth);
        console.log(height + ", " + width);
        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <polyline {...props}>{this.props.children}</polyline>
            </SVGComponent>)
    }
}

export class CornerLine extends React.Component {
    render() {

        var size = this.props.size || 150;
        var cornerWidth = this.props.width || 50;
        var strokeWidth = this.props.strokeWidth || 0;

        //var height = _.max([this.props.style.height, size]);
        //var width = _.max([this.props.style.width, size]);

        var max = size;
        var min = 0;
        var diff = max - cornerWidth;

        var up = this.props.up ? true : false;

        var point = up ? [[max, min], [min, max], [min, diff], [diff, min], [max, min]] : [[max, max], [min, min], [cornerWidth, min], [max, diff], [max, max]];
        var points = _.reduce(point, function (memo, num) {
            return memo + " " + num[0] + "," + num[1];
        }, "");

        var text = this.props.text;

        var x = this.props.x || max;
        var y = this.props.y || max;

        var rotate = up ? 315 : 45;
        var transform = "rotate(" + rotate.toString() + ")";

        return (
            <SVGComponent height={size} width={size}>
                <polyline points={points} {...this.props}></polyline>
                <text x={x} y={y} transform={transform}>{this.props.text}</text>
            </SVGComponent>)
    }
}

export class CornerBox extends React.Component {
    render() {

        var type = this.props.orientation;
        var up = (type === 'topLeft' || type === 'bottomRight') ? true : false;
//        var right = (type === 'topRight' || type == 'bottomRight')?true:false;

        var size = this.props.size;
        var cornerWidth = this.props.width;
        if (type === 'bottomLeft' || type === 'bottomRight') cornerWidth = -1 * cornerWidth;

        var offset = 20;
        var x = offset;
        var y = -1 * (cornerWidth / 2)

        if (up) {
            x = -1 * (cornerWidth / 2);
            y = size - offset;
        }
        var text = this.props.text;

        return (
            <CornerLine {...this.props} size={this.props.size} width={cornerWidth} text={this.props.text} x={x} y={y}
                                        up={up}/>)
    }
}
var sharedShapeMetaData = {
    defaultColors: {
        fill: '#2409ba',
        stroke: '#E65243',
        strokeWidth: 20
    }
}
export default {
    SVGComponent: SVGComponent,
    Rectangle: _.extend(Rectangle, {
        metaData: {
            props: _.extend({
                width: 500,
                height: 300
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Circle: _.extend(Circle, {
        metaData: {
            props: _.extend({
                r: 200
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Ellipse: _.extend(Ellipse, {
        metaData: {
            props: _.extend({
                rx: 300,
                ry: 100
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Line: _.extend(Line, {
        metaData: {
            props: _.extend({
                x1: 25,
                y1: 25,
                x2: 350,
                y2: 350
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Polyline: _.extend(Polyline, {
        metaData: {
            props: _.extend({
                points: '25,25 25,350 500,350 500,500 305,250 20,15'
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    CornerBox: _.extend(CornerBox, {
        metaData: {
            props: _.extend({
                size: 400,
                width: 150,
                text: 'type your text',
                orientation: 'topLeft'
            }, sharedShapeMetaData.defaultColors),
            settings: {
                fields: {
                    orientation: {
                        type: 'select',
                        settings: {options: ['topRight', 'topLeft', 'bottomRight', 'bottomLeft']}
                    }
                }
            }
        }
    }),
    CornerLine: _.extend(CornerLine, {
        metaData: {
            props: _.extend({
                size: 150,
                width: 50,
                text: 'type your text',
                x: 25,
                y: 25,
                up: false,
            }, sharedShapeMetaData.defaultColors)
        }
    })
};
<commit_msg>Use only half of the stroke's width as offset<commit_after>import React from 'react';
import _  from 'underscore';

export class SVGComponent extends React.Component {
    render() {
        return <svg {...this.props}>{this.props.children}</svg>
    }
}
export class Rectangle extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;

        var height = (this.props.height || 0) + 2 * strokeWidth;
        var width = (this.props.width || 0) + 2 * strokeWidth;
        var props = _.omit(this.props, 'style');

        return (
            <SVGComponent height={height} width={width}>
                <rect {...props} x={strokeWidth / 2} y={strokeWidth / 2}>{this.props.children}</rect>
            </SVGComponent>)
    }
}
export class Circle extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;
        var r = this.props.r || 0;

        var height = (r * 2) + 2 * strokeWidth;
        var width = (r * 2) + 2 * strokeWidth;

        var cx = r + (strokeWidth / 2);
        var cy = r + (strokeWidth / 2);
        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <circle {...props} cx={cx} cy={cy}>{this.props.children}</circle>
            </SVGComponent>)

    }
}
export class Ellipse extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;
        var rx = this.props.rx || 0;
        var ry = this.props.ry || 0;

        var height = (ry * 2) + 2 * strokeWidth;
        var width = (rx * 2) + 2 * strokeWidth;

        var cx = rx + (strokeWidth / 2);
        var cy = ry + (strokeWidth / 2);

        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <ellipse {...props} cx={cx} cy={cy}>{this.props.children}</ellipse>
            </SVGComponent>)

    }
}
export class Line extends React.Component {
    render() {

        var strokeWidth = this.props.strokeWidth || 0;
        var x = _.max([this.props.x1, this.props.x2]);
        var y = _.max([this.props.y1, this.props.y2]);

        var height = y + (2 * strokeWidth);
        var width = x + (2 * strokeWidth);

        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <line {...props}>{this.props.children}</line>
            </SVGComponent>)
    }
}
export class Polyline extends React.Component {
    render() {
        var strokeWidth = this.props.strokeWidth || 0;

        var points = _.map(this.props.points.split(' '),function(point){
            var xy = point.split(',');
            return {x:parseInt(xy[0],10),y:parseInt(xy[1],10)};
        });
        var x = _.max(_.map(points,function(point){return point.x}));
        var y = _.max(_.map(points,function(point){return point.y}));

        console.log(points);

        var height = y + (2 * strokeWidth);
        var width = x + (2 * strokeWidth);
        console.log(height + ", " + width);
        var props = _.omit(this.props, 'style');
        return (
            <SVGComponent height={height} width={width}>
                <polyline {...props}>{this.props.children}</polyline>
            </SVGComponent>)
    }
}

export class CornerLine extends React.Component {
    render() {

        var size = this.props.size || 150;
        var cornerWidth = this.props.width || 50;
        var strokeWidth = this.props.strokeWidth || 0;

        //var height = _.max([this.props.style.height, size]);
        //var width = _.max([this.props.style.width, size]);

        var max = size;
        var min = 0;
        var diff = max - cornerWidth;

        var up = this.props.up ? true : false;

        var point = up ? [[max, min], [min, max], [min, diff], [diff, min], [max, min]] : [[max, max], [min, min], [cornerWidth, min], [max, diff], [max, max]];
        var points = _.reduce(point, function (memo, num) {
            return memo + " " + num[0] + "," + num[1];
        }, "");

        var text = this.props.text;

        var x = this.props.x || max;
        var y = this.props.y || max;

        var rotate = up ? 315 : 45;
        var transform = "rotate(" + rotate.toString() + ")";

        return (
            <SVGComponent height={size} width={size}>
                <polyline points={points} {...this.props}></polyline>
                <text x={x} y={y} transform={transform}>{this.props.text}</text>
            </SVGComponent>)
    }
}

export class CornerBox extends React.Component {
    render() {

        var type = this.props.orientation;
        var up = (type === 'topLeft' || type === 'bottomRight') ? true : false;
//        var right = (type === 'topRight' || type == 'bottomRight')?true:false;

        var size = this.props.size;
        var cornerWidth = this.props.width;
        if (type === 'bottomLeft' || type === 'bottomRight') cornerWidth = -1 * cornerWidth;

        var offset = 20;
        var x = offset;
        var y = -1 * (cornerWidth / 2)

        if (up) {
            x = -1 * (cornerWidth / 2);
            y = size - offset;
        }
        var text = this.props.text;

        return (
            <CornerLine {...this.props} size={this.props.size} width={cornerWidth} text={this.props.text} x={x} y={y}
                                        up={up}/>)
    }
}
var sharedShapeMetaData = {
    defaultColors: {
        fill: '#2409ba',
        stroke: '#E65243',
        strokeWidth: 20
    }
}
export default {
    SVGComponent: SVGComponent,
    Rectangle: _.extend(Rectangle, {
        metaData: {
            props: _.extend({
                width: 500,
                height: 300
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Circle: _.extend(Circle, {
        metaData: {
            props: _.extend({
                r: 200
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Ellipse: _.extend(Ellipse, {
        metaData: {
            props: _.extend({
                rx: 300,
                ry: 100
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Line: _.extend(Line, {
        metaData: {
            props: _.extend({
                x1: 25,
                y1: 25,
                x2: 350,
                y2: 350
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    Polyline: _.extend(Polyline, {
        metaData: {
            props: _.extend({
                points: '25,25 25,350 500,350 500,500 305,250 20,15'
            }, sharedShapeMetaData.defaultColors)
        }
    }),
    CornerBox: _.extend(CornerBox, {
        metaData: {
            props: _.extend({
                size: 400,
                width: 150,
                text: 'type your text',
                orientation: 'topLeft'
            }, sharedShapeMetaData.defaultColors),
            settings: {
                fields: {
                    orientation: {
                        type: 'select',
                        settings: {options: ['topRight', 'topLeft', 'bottomRight', 'bottomLeft']}
                    }
                }
            }
        }
    }),
    CornerLine: _.extend(CornerLine, {
        metaData: {
            props: _.extend({
                size: 150,
                width: 50,
                text: 'type your text',
                x: 25,
                y: 25,
                up: false,
            }, sharedShapeMetaData.defaultColors)
        }
    })
};
<|endoftext|>


<commit_before>importScripts('workbox-sw.dev.v2.1.0.js');

const workboxSW = new WorkboxSW();
workboxSW.precache([]);

workboxSW.router.registerRoute('https://fonts.googleapis.com/(.*)',
  workboxSW.strategies.cacheFirst({
    cacheName: 'googleapis',
    cacheExpiration: {
      maxEntries: 20
    },
    cacheableResponse: {statuses: [0, 200]}
  })
);

workboxSW.router.registerRoute(/\.(?:png|gif|jpg)$/,
  workboxSW.strategies.cacheFirst({
    cacheName: 'images',
    cacheExpiration: {
      maxEntries: 50
    }
  })
);
<commit_msg>add a license header<commit_after>/*jshint esversion:6*/
/**
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
importScripts('workbox-sw.dev.v2.1.0.js');

const workboxSW = new WorkboxSW();
workboxSW.precache([]);

workboxSW.router.registerRoute('https://fonts.googleapis.com/(.*)',
  workboxSW.strategies.cacheFirst({
    cacheName: 'googleapis',
    cacheExpiration: {
      maxEntries: 20
    },
    cacheableResponse: {statuses: [0, 200]}
  })
);

workboxSW.router.registerRoute(/\.(?:png|gif|jpg)$/,
  workboxSW.strategies.cacheFirst({
    cacheName: 'images',
    cacheExpiration: {
      maxEntries: 50
    }
  })
);
<|endoftext|>