<commit_before>function PillarBuilder()
{
	"use strict";
	var pb = this,
		myth = require('myth'),
		minify = require('cssmin'),
		config = require('./package.json'),
		settings = {
			prefix: 'pllr',
			separator: '-',

			myth: true,
			minify: true
		},
		output = process.stdout;

	function init()
	{
		Object.keys(settings).forEach(function(key){
			Object.defineProperty(pb, key, getSetter(key));
		});
	}

	function getSetter(key)
	{
		return {
			get: function(){
				return settings[key];
			},
			set: function(value){
				settings[key] = value;

				if (!(/^[a-z][a-z0-9-]*$/i).test(settings.prefix + settings.separator))
					throw new Error('Invalid value "' + value + '" for ' + key);
			}
		};
	}

	function generate(n)
	{
		var result = [],
			i, j;

		for (i = 1; i < n; ++i)
		{
			result.push([n - i, i]);
			generate(i).forEach(function(combine){
				result.push([n - i].concat(combine));
			});
		}

		return result;
	}

	function pattern(skip, seek)
	{
		return new RegExp([
			'^',
			(Array.apply(null, new Array(skip)).map(String.prototype.valueOf, '[0-9]+')).join(settings.separator),
			skip > 0 ? settings.separator : '',
			seek,
			'\\b'
		].join(''));
	}

	function mythRule(span)
	{
		return '{\n\twidth: calc(var(--column-width) * ' + span + ');\n}';
	}

	function rules(tokens, columns)
	{
		var result = {},
			divider = '-' + settings.separator,
			rx, i, j;

		for (i = 0; i < columns; ++i)
			for (j = 2; j <= columns; ++j)
			{
				rx = pattern(i, j);
				tokens.forEach(function(selector){
					var rule;

					if (rx.test(selector))
					{
						rule = mythRule(j);

						if (!(rule in result))
							result[rule] = {};

						if (!(i + 1 in result[rule]))
							result[rule][i + 1] = {};

						result[rule][i + 1]['.' + settings.prefix + divider + selector + ' > :nth-child(' + selector.split(settings.separator).length + 'n+' + (i + 1) + ')'] = !0;
					}
				});
			}

		return result;
	}

	function compose(rules, columns)
	{
		var year = new Date().getFullYear(),
			buffer = [];

		if (year !== 2015)
			year = '2015-' + year;

		buffer.push(
			'/*!  ' + config.name + ' v' + config.version + '  -  ' + config.description + ' (' + columns + ' pillars/columns)',
			'Copyright ⓒ ' + year + ' ' + config.author + ' (Konfirm). All rights reserved.',
			'Licensed under the MIT License.',
			'*//*',
			'\tInspired by the awesome Pure CSS framework (http://purecss.io)',
			'*/',
			'',
			':root {',
			'	--column-count: ' + columns + ';',
			'	--column-width: calc(100% / var(--column-count));',
			'}',
			'',
			'/*  The default \'column\' width and display mode  */',
			'[class *= "' + settings.prefix + columns + '"] > *,',
			'[class *= "' + settings.prefix + '"] > * {',
			'	display: inline-block;',
			'	*display: inline; /*  IE < 8: fake inline-block  */',
			'	zoom: 1;',
			'	width: calc(var(--column-width) * 1);',
			'}',
			'',
			'/*  The \'row\' will be using the flex display mode  */',
			'[class *= "' + settings.prefix + '"] {',
			'	display: flex;',
			'	flex-flow: row wrap;',
			'	text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */',
			'}',
			'',
			'/*  The generated pillars/columns/grid  */',
			''
		);

		Object.keys(rules).forEach(function(rule){
			var merge = [],
				max = 0;

			Object.keys(rules[rule]).forEach(function(key){
				Object.keys(rules[rule][key]).forEach(function(key){
					max = Math.max(max, key.length);
					merge.push(key);
				});
			});

			merge = merge
				.map(function(key){
					return key.replace('>', new Array(max).join(' ').substr(0, max - key.length) + '>');
				});

			buffer.push(merge.join(',\n') + ' ' + rule, '', '');
		});

		buffer = buffer.join('\n');

		if (settings.myth)
			buffer = myth(buffer);

		if (settings.minify)
			buffer = minify(buffer);

		output.write(buffer);
	}

	pb.grid = function(columns){
		var selectors = generate(columns).map(function(selector){
				return selector.join(settings.separator);
			});

		compose(rules(selectors, columns), columns);
	};

	init();
}

var builder = new PillarBuilder();

if (process.argv.length > 3)
	builder.prefix = process.argv[3];

if (process.argv.length > 4)
	builder.separator = process.argv[4];

if (process.env.MYTH === 'off')
{
	builder.myth   = false;
	builder.minify = false;
}
else if (process.env.MIN === 'off')
{
	builder.minify = false;
}

builder.grid(+(process.argv[2] || 6));
<commit_msg>ensure at least one separator character between the prefix and the columns<commit_after>function PillarBuilder()
{
	"use strict";
	var pb = this,
		myth = require('myth'),
		minify = require('cssmin'),
		config = require('./package.json'),
		settings = {
			prefix: 'pllr',
			separator: '-',

			myth: true,
			minify: true
		},
		output = process.stdout;

	function init()
	{
		Object.keys(settings).forEach(function(key){
			Object.defineProperty(pb, key, getSetter(key));
		});
	}

	function getSetter(key)
	{
		return {
			get: function(){
				return settings[key];
			},
			set: function(value){
				settings[key] = value;

				if (!(/^[a-z][a-z0-9-]*$/i).test(settings.prefix + settings.separator))
					throw new Error('Invalid value "' + value + '" for ' + key);
			}
		};
	}

	function generate(n)
	{
		var result = [],
			i, j;

		for (i = 1; i < n; ++i)
		{
			result.push([n - i, i]);
			generate(i).forEach(function(combine){
				result.push([n - i].concat(combine));
			});
		}

		return result;
	}

	function pattern(skip, seek)
	{
		return new RegExp([
			'^',
			(Array.apply(null, new Array(skip)).map(String.prototype.valueOf, '[0-9]+')).join(settings.separator),
			skip > 0 ? settings.separator : '',
			seek,
			'\\b'
		].join(''));
	}

	function mythRule(span)
	{
		return '{\n\twidth: calc(var(--column-width) * ' + span + ');\n}';
	}

	function rules(tokens, columns)
	{
		var result = {},
			divider = (settings.separator || '-') + settings.separator,
			rx, i, j;

		for (i = 0; i < columns; ++i)
			for (j = 2; j <= columns; ++j)
			{
				rx = pattern(i, j);
				tokens.forEach(function(selector){
					var rule;

					if (rx.test(selector))
					{
						rule = mythRule(j);

						if (!(rule in result))
							result[rule] = {};

						if (!(i + 1 in result[rule]))
							result[rule][i + 1] = {};

						result[rule][i + 1]['.' + settings.prefix + divider + selector + ' > :nth-child(' + selector.split(settings.separator).length + 'n+' + (i + 1) + ')'] = !0;
					}
				});
			}

		return result;
	}

	function compose(rules, columns)
	{
		var year = new Date().getFullYear(),
			buffer = [];

		if (year !== 2015)
			year = '2015-' + year;

		buffer.push(
			'/*!  ' + config.name + ' v' + config.version + '  -  ' + config.description + ' (' + columns + ' pillars/columns)',
			'Copyright ⓒ ' + year + ' ' + config.author + ' (Konfirm). All rights reserved.',
			'Licensed under the MIT License.',
			'*//*',
			'\tInspired by the awesome Pure CSS framework (http://purecss.io)',
			'*/',
			'',
			':root {',
			'	--column-count: ' + columns + ';',
			'	--column-width: calc(100% / var(--column-count));',
			'}',
			'',
			'/*  The default \'column\' width and display mode  */',
			'[class *= "' + settings.prefix + columns + '"] > *,',
			'[class *= "' + settings.prefix + '"] > * {',
			'	display: inline-block;',
			'	*display: inline; /*  IE < 8: fake inline-block  */',
			'	zoom: 1;',
			'	width: calc(var(--column-width) * 1);',
			'}',
			'',
			'/*  The \'row\' will be using the flex display mode  */',
			'[class *= "' + settings.prefix + '"] {',
			'	display: flex;',
			'	flex-flow: row wrap;',
			'	text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */',
			'}',
			'',
			'/*  The generated pillars/columns/grid  */',
			''
		);

		Object.keys(rules).forEach(function(rule){
			var merge = [],
				max = 0;

			Object.keys(rules[rule]).forEach(function(key){
				Object.keys(rules[rule][key]).forEach(function(key){
					max = Math.max(max, key.length);
					merge.push(key);
				});
			});

			merge = merge
				.map(function(key){
					return key.replace('>', new Array(max).join(' ').substr(0, max - key.length) + '>');
				});

			buffer.push(merge.join(',\n') + ' ' + rule, '', '');
		});

		buffer = buffer.join('\n');

		if (settings.myth)
			buffer = myth(buffer);

		if (settings.minify)
			buffer = minify(buffer);

		output.write(buffer);
	}

	pb.grid = function(columns){
		var selectors = generate(columns).map(function(selector){
				return selector.join(settings.separator);
			});

		compose(rules(selectors, columns), columns);
	};

	init();
}

var builder = new PillarBuilder();

if (process.argv.length > 3)
	builder.prefix = process.argv[3];

if (process.argv.length > 4)
	builder.separator = process.argv[4];

if (process.env.MYTH === 'off')
{
	builder.myth   = false;
	builder.minify = false;
}
else if (process.env.MIN === 'off')
{
	builder.minify = false;
}

builder.grid(+(process.argv[2] || 6));
<|endoftext|>


<commit_before>  /**
 * The Imazon layer module.
 *
 * @return ImazonLayer class (extends CartoDBLayerClass)
 */
define([
  'moment',
  'uri',
  'abstract/layer/CartoDBLayerClass',
  'text!map/cartocss/forma.cartocss',
  'map/presenters/layers/ImazonLayerPresenter'
], function(moment, UriTemplate, CartoDBLayerClass, FormaCartoCSS, Presenter) {

  'use strict';

  var ImazonLayer = CartoDBLayerClass.extend({
    options: {
      sql: 'SELECT cartodb_id, the_geom_webmercator, to_char(date,\'YYYYMMDD\')::int as date, data_type AS layer, data_type AS name FROM {tableName} ' +
        'WHERE date BETWEEN to_date(\'{startYear}-{startMonth}\',\'YYYY-MM\') AND to_date(\'{endYear}-{endMonth}\',\'YYYY-MM\')',
      cartocss: FormaCartoCSS
    },

    init: function(layer, options, map) {
      this.options.cartocss = FormaCartoCSS.replace(/#date_to_change/g,layer.maxdate.subtract(1, 'months').format('YYYYMMDD'));
      this.presenter = new Presenter(this);
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this._super(layer, options, map);
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    /**
     * Get the CartoDB query.
     *
     * @return {string} CartoDB query
     * @override
     */
    getQuery: function() {
      var query = new UriTemplate(this.options.sql).fillFromObject({
        tableName: this.layer.table_name,
        startMonth: this.currentDate[0].format('MM'),
        startYear: this.currentDate[0].format('YYYY'),
        endMonth: this.currentDate[1].format('MM'),
        endYear: this.currentDate[1].format('YYYY')
      });
      return query;
    }
  });

  return ImazonLayer;

});
<commit_msg>Fix IMAZON SAD date correlation<commit_after>  /**
 * The Imazon layer module.
 *
 * @return ImazonLayer class (extends CartoDBLayerClass)
 */
define([
  'moment',
  'uri',
  'abstract/layer/CartoDBLayerClass',
  'text!map/cartocss/forma.cartocss',
  'map/presenters/layers/ImazonLayerPresenter'
], function(moment, UriTemplate, CartoDBLayerClass, FormaCartoCSS, Presenter) {

  'use strict';

  var ImazonLayer = CartoDBLayerClass.extend({
    options: {
      sql: 'SELECT cartodb_id, the_geom_webmercator, to_char(date,\'YYYYMMDD\')::int as date, data_type AS layer, data_type AS name FROM {tableName} ' +
        'WHERE date BETWEEN to_date(\'{startYear}-{startMonth}\',\'YYYY-MM\') AND to_date(\'{endYear}-{endMonth}\',\'YYYY-MM\')',
      cartocss: FormaCartoCSS
    },

    init: function(layer, options, map) {
      this.options.cartocss = FormaCartoCSS.replace(/#date_to_change/g,layer.maxdate.subtract(1, 'months').utc().format('YYYYMMDD'));
      this.presenter = new Presenter(this);
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this._super(layer, options, map);
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    /**
     * Get the CartoDB query.
     *
     * @return {string} CartoDB query
     * @override
     */
    getQuery: function() {
      var query = new UriTemplate(this.options.sql).fillFromObject({
        tableName: this.layer.table_name,
        startMonth: this.currentDate[0].format('MM'),
        startYear: this.currentDate[0].format('YYYY'),
        endMonth: this.currentDate[1].format('MM'),
        endYear: this.currentDate[1].format('YYYY')
      });
      return query;
    }
  });

  return ImazonLayer;

});
<|endoftext|>


<commit_before>import { EventSource } from '../io/ModernEventSource.js';

/*global Response, ReadableStream, TextEncoder */

class EventSourceProxy {
    constructor(url) {
        this.eventSource = new EventSource(url, {
            fireEvent: (event) => {
                this.dispatch(event);
            },
        });
        this.streams = new Map();
        this._lastEventId = '';
        this._lastChunk = null;
    }

    connect() {
        this.eventSource.open();
    }

    disconnect() {
        this.eventSource.close();
    }

    dispatch({ type, data, lastEventId }) {
        const lines = [];
        if (type !== 'message') {
            lines.push(`event:${type}`);
        }
        if (lastEventId) {
            lines.push(`id:${lastEventId}`);
        }
        if (data) {
            data.split('\n').forEach((datum) => {
                lines.push(`data:${datum}`);
            });
        }
        const chunk = new TextEncoder().encode(lines.join('\n') + '\n\n');
        if (lastEventId && lastEventId !== this._lastEventId) {
            this._lastEventId = lastEventId;
            this._lastChunk = chunk;
        }
        this.streams.forEach((streamController) =>
            streamController.enqueue(chunk),
        );
    }

    register(stream, streamController, lastEventId) {
        if (!this.streams.size) {
            this.connect();
        }
        this.streams.set(stream, streamController);
        // Firefox doesn't resolve fetch promise until first chunk, so make
        // sure we always send something immediately.
        const chunk =
            (lastEventId !== this._lastEventId && this._lastChunk) ||
            new TextEncoder().encode(':\n');
        streamController.enqueue(chunk);
    }

    deregister(stream) {
        this.streams.delete(stream);
        if (!this.streams.size) {
            this.disconnect();
        }
    }

    getResponseStream(request) {
        const proxy = this;
        const controller = {
            start(streamController) {
                proxy.register(
                    this,
                    streamController,
                    request.headers.get('Last-Event-ID'),
                );
            },
            cancel() {
                proxy.deregister(this);
            },
        };
        const stream = new ReadableStream(controller);
        // Not supported in any browser yet, but will be I hope!
        request.signal.addEventListener('abort', () => stream.cancel(), false);
        return new Response(stream, {
            status: 200,
            headers: {
                'Cache-Control': 'max-age=0, no-store',
                'Connection': 'keep-alive',
                'Content-Type': 'text/event-stream',
                'Transfer-Encoding': 'chunked',
            },
        });
    }
}

// ---

export { EventSourceProxy };
<commit_msg>Fix event source proxy<commit_after>import { EventSource } from '../io/ModernEventSource.js';

/*global Response, ReadableStream, TextEncoder */

class EventSourceProxy {
    constructor(url) {
        this.eventSource = new EventSource({
            url,
            onevent: (event) => {
                this.dispatch(event);
            },
        });
        this.streams = new Map();
        this._lastEventId = '';
        this._lastChunk = null;
    }

    connect() {
        this.eventSource.open();
    }

    disconnect() {
        this.eventSource.close();
    }

    dispatch({ type, data, lastEventId }) {
        const lines = [];
        if (type !== 'message') {
            lines.push(`event:${type}`);
        }
        if (lastEventId) {
            lines.push(`id:${lastEventId}`);
        }
        if (data) {
            data.split('\n').forEach((datum) => {
                lines.push(`data:${datum}`);
            });
        }
        const chunk = new TextEncoder().encode(lines.join('\n') + '\n\n');
        if (lastEventId && lastEventId !== this._lastEventId) {
            this._lastEventId = lastEventId;
            this._lastChunk = chunk;
        }
        this.streams.forEach((streamController) =>
            streamController.enqueue(chunk),
        );
    }

    register(stream, streamController, lastEventId) {
        if (!this.streams.size) {
            this.connect();
        }
        this.streams.set(stream, streamController);
        // Firefox doesn't resolve fetch promise until first chunk, so make
        // sure we always send something immediately.
        const chunk =
            (lastEventId !== this._lastEventId && this._lastChunk) ||
            new TextEncoder().encode(':\n');
        streamController.enqueue(chunk);
    }

    deregister(stream) {
        this.streams.delete(stream);
        if (!this.streams.size) {
            this.disconnect();
        }
    }

    getResponseStream(request) {
        const proxy = this;
        const controller = {
            start(streamController) {
                proxy.register(
                    this,
                    streamController,
                    request.headers.get('Last-Event-ID'),
                );
            },
            cancel() {
                proxy.deregister(this);
            },
        };
        const stream = new ReadableStream(controller);
        // Not supported in any browser yet, but will be I hope!
        request.signal.addEventListener('abort', () => stream.cancel(), false);
        return new Response(stream, {
            status: 200,
            headers: {
                'Cache-Control': 'max-age=0, no-store',
                'Connection': 'keep-alive',
                'Content-Type': 'text/event-stream',
                'Transfer-Encoding': 'chunked',
            },
        });
    }
}

// ---

export { EventSourceProxy };
<|endoftext|>


<commit_before>console.log("restarting the keep alive counter")
chrome.runtime.sendMessage({activity: true}, function(response) {console.log(response)});

var elts = document.getElementsByTagName('a');
var show = function() { chrome.runtime.sendMessage({activity: true}, function(response) {console.log(response)}); }
for (var i = elts.length - 1; i >= 0; --i) {
    elts[i].onclick = show;
}

//inject our JS resource
var s = document.createElement('script');
s.src = chrome.extension.getURL('/all/content/all.js');
(document.head || document.documentElement).appendChild(s)

var logo = document.getElementsByClassName("navbar-brand");
logo[0].style.background="transparent url('"+chrome.extension.getURL("lighthouse.png")+"') 0% 50% no-repeat";
logo[0].style.backgroundSize="105px 35px";
logo[0].style.width="120px";
logo[0].style.height="50px";
logo[0].style.margin="0 0 0 10px";
logo[0].style.padding="0";

<commit_msg>idle timeout protection<commit_after>console.log("telling the keep alive system we are still active")
chrome.runtime.sendMessage({activity: true}, function(response) {console.log(response)});

var elts = document.getElementsByTagName('a');
var show = function() { chrome.runtime.sendMessage({activity: true}, function(response) {console.log(response)}); }
for (var i = elts.length - 1; i >= 0; --i) {
    elts[i].onclick = show;
}

//inject our JS resource
var s = document.createElement('script');
s.src = chrome.extension.getURL('/all/content/all.js');
(document.head || document.documentElement).appendChild(s)

var logo = document.getElementsByClassName("navbar-brand");
logo[0].style.background="transparent url('"+chrome.extension.getURL("lighthouse.png")+"') 0% 50% no-repeat";
logo[0].style.backgroundSize="105px 35px";
logo[0].style.width="120px";
logo[0].style.height="50px";
logo[0].style.margin="0 0 0 10px";
logo[0].style.padding="0";

<|endoftext|>


<commit_before>/*
 * Copyright 2010, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
 * OWNER 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.
 */

/**
 * @fileoverview This file contains functions every webgl program will need
 * a version of one way or another.
 *
 * Instead of setting up a context manually it is recommended to
 * use. This will check for success or failure. On failure it
 * will attempt to present an approriate message to the user.
 *
 *       gl = WebGLUtils.setupWebGL(canvas);
 *
 * For animated WebGL apps use of setTimeout or setInterval are
 * discouraged. It is recommended you structure your rendering
 * loop like this.
 *
 *       function render() {
 *         window.requestAnimFrame(render, canvas);
 *
 *         // do rendering
 *         ...
 *       }
 *       render();
 *
 * This will call your rendering function up to the refresh rate
 * of your display but will stop rendering if your app is not
 * visible.
 */

WebGLUtils = function() {

/**
 * Creates the HTLM for a failure message
 * @param {string} canvasContainerId id of container of th
 *        canvas.
 * @return {string} The html.
 */
var makeFailHTML = function(msg) {
  return '' +
    '

' +
    '' +
    '
' +
    '
' + msg + '
' +
    '
' +
    '

';
};

/**
 * Mesasge for getting a webgl browser
 * @type {string}
 */
var GET_A_WEBGL_BROWSER = '' +
  'Marine Compass requires a browser that supports WebGL.
' +
  'Click here to check support by browser.';

var GET_DEVICE_ORIENTATION_BROWSER = '' +
  'Marine Compass requires a browser that supports Device Orientation Events.
' +
  'Click here to check support by browser.';

/**
 * Mesasge for need better hardware
 * @type {string}
 */
var OTHER_PROBLEM = '' +
  "It doesn't appear your computer can support WebGL.
" +
  'Click here for more information.';

/**
 * Creates a webgl context. If creation fails it will
 * change the contents of the container of the <canvas>
 * tag to an error message with the correct links for WebGL.
 * @param {Element} canvas. The canvas element to create a
 *     context from.
 * @param {WebGLContextCreationAttirbutes} opt_attribs Any
 *     creation attributes you want to pass in.
 * @return {WebGLRenderingContext} The created context.
 */
var setupWebGL = function(canvas, opt_attribs) {
  function showLink(str) {
    var container = canvas.parentNode;
    if (container) {
      container.innerHTML = makeFailHTML(str);
    }
  };

  if (!window.WebGLRenderingContext) {
      console.log()
    showLink(GET_A_WEBGL_BROWSER);
    return null;
  }

  var context = create3DContext(canvas, opt_attribs);
  if (!context) {
    showLink(OTHER_PROBLEM);
  }
  return context;
};

/**
 * Creates a webgl context.
 * @param {!Canvas} canvas The canvas tag to get context
 *     from. If one is not passed in one will be created.
 * @return {!WebGLContext} The created context.
 */
var create3DContext = function(canvas, opt_attribs) {
  var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
  var context = null;
  for (var ii = 0; ii < names.length; ++ii) {
    try {
      context = canvas.getContext(names[ii], opt_attribs);
    } catch(e) {}
    if (context) {
      break;
    }
  }
  return context;
}

return {
  create3DContext: create3DContext,
  setupWebGL: setupWebGL
};
}();<commit_msg>Remove webgl-utils.js<commit_after><|endoftext|>


<commit_before>const fs = require('fs');
const svgstore = require('svgstore');
const svgDir = './src/svg';

function getFileList(dir) {
    const targetDir = svgDir + '/' + dir;
    const sprites = svgstore();
    fs.readdir(targetDir, (err, files) => {
        if (!files) return;
        files.forEach(file => {
            const id = `${dir}-${file.replace(/\.svg$/, '')}`;
            const svg = fs.readFileSync(targetDir + '/' + file);
            sprites.add(id, svg);
        });
        fs.writeFileSync(`./dist/${dir}.svg`, sprites);
    });
}

fs.readdir('./src/svg', (err, dirs) => {
    dirs.forEach(dir => {
        getFileList(dir);
    });
})

<commit_msg>fixed makesvg<commit_after>const fs = require('fs');
const svgstore = require('svgstore');
const svgDir = './src/svg';

function getFileList(dir) {
    const targetDir = svgDir + '/' + dir;
    const sprites = svgstore();
    fs.readdir(targetDir, (err, files) => {
        if (!files) return;
        files.forEach(file => {
            if (file.match(/^\./)) return;
            const id = `${dir}-${file.replace(/\.svg$/, '')}`;
            const svg = fs.readFileSync(targetDir + '/' + file);
            sprites.add(id, svg);
        });
        fs.writeFileSync(`./dist/${dir}.svg`, sprites);
    });
}

fs.readdir('./src/svg', (err, dirs) => {
    dirs.forEach(dir => {
        getFileList(dir);
    });
})

<|endoftext|>


<commit_before>var buster = require("buster-core");
var bResources = require("buster-resources");
var bCapServBayeuxServer = require("./buster-capture-server-bayeux-server");
var httpServerRequestListenerProxy = require("./http-server-request-listener-proxy");
var bCapServSession = require("./session");
var bCapServSlave = require("./slave");
var URL = require("url");

var NOOP = function(){};

exports.create = function () {
    var busterResources = Object.create(bResources);
    var httpServer;
    var headerHeight;
    var headerResourceSet;
    var bayeuxServer;
    var sessions = [];
    var slaves = [];
    var logger = {"error":NOOP,"warn":NOOP,"log":NOOP,"info":NOOP,"debug":NOOP};

    var captureServer = {
        messagingContextPath: "/sessions/messaging",
        capturePath: "/capture",

        get sessions() {
            return sessions;
        },

        get slaves() {
            return slaves;
        },

        get logger() {
            return logger;
        },

        set logger(newLogger) {
            logger = newLogger;
            bayeuxServer.setLogger(newLogger);
        },

        header: function (height, resourceSetOpts) {
            if (headerResourceSet !== undefined) busterResources.removeResourceSet(headerResourceSet);

            headerHeight = height;
            resourceSetOpts.contextPath = "/slaveHeader";
            headerResourceSet = busterResources.createResourceSet(resourceSetOpts);
            return headerResourceSet;
        },

        createSession: function (data) {
            var error = bCapServSession.validate(data);
            if (error) throw new Error(error);
            logger.info("Creating session");
            return createSessionWithData(data);
        },

        destroySession: function (id) {
            var i = getSessionIndexById(id);
            if (i >= -1) {
                logger.info("Destroying session");
                logger.debug("Session ID", id)
                sessions[i].end();
            }
        },

        destroyCurrentSession: function () {
            if (sessions.length > 0) {
                this.destroySession(sessions[0].id);
            }
        },

        get bayeux() {
            return bayeuxServer.getClient();
        },

        attach: function (_httpServer) {
            httpServer = _httpServer;
            bayeuxServer.attach(httpServer);
            httpServerRequestListenerProxy.attach(httpServer, respond);
        }
    }

    function respond(req, res) {
        var url = URL.parse(req.url);

        if (req.method == "GET" && url.pathname == captureServer.capturePath) {
            logger.info("Capturing new slave");
            captureSlave(req, res);
            return true;
        }

        if (req.method == "POST" && url.pathname == "/sessions") {
            logger.debug("Creating session via HTTP");
            createSessionFromRequest(req, res);
            return true;
        }

        if (req.method == "GET" && url.pathname == "/resources") {
            listKnownResources(res);
            return true;
        }

        if (req.method == "DELETE" && url.pathname == "/resources") {
            resourceGc(res);
            return true;
        }

        if (slaves.some(function (slave) {
            return slave.respond(req, res, url.pathname);
        })) return true;

        if (sessions.some(function(session) {
            return session.respond(req, res, url.pathname)
        })) return true;

        if (busterResources.getResourceViaHttp(req, res)) return true;
    }

    function resourceGc(res) {
        logger.debug("Performing resource garbage collection");
        busterResources.gc();
        res.writeHead(200);
        res.end();
    }

    function listKnownResources(res) {
        logger.debug("Listing known resources");
        res.writeHead(200);
        res.write(JSON.stringify(busterResources.getCachedResources()));
        res.end();
    }

    function getSessionIndexById(id) {
        var matches = sessions.filter(function (sess) { return sess.id == id; });
        return sessions.indexOf(matches[0]);
    }

    function unloadSession(id) {
        var i = getSessionIndexById(id);

        var session = sessions[i];
        // TODO: Session should remove its own resource set
        busterResources.removeResourceSet(session.resourceSet);
        sessions.splice(i, 1);

        // Did we unload the current session?
        if (i == 0) {
            logger.debug("Current session did end.");
            if (sessions.length > 0) {
                logger.debug("Starting queued session.");
                loadCurrentSession();
            }
        }
    }

    function createSessionFromRequest(req, res) {
        var requestBody = "";
        req.setEncoding("utf8");
        req.on("data", function (chunk) { requestBody += chunk; });
        req.on("end", function () {
            createSessionWithRequestBody(requestBody, req, res);
        });
    }

    function createSessionWithRequestBody(requestBody, req, res) {
        try {
            var data = JSON.parse(requestBody);
        } catch(e) {
            logger.error("Invalid JSON", requestBody);
            return failWithMessage(res, "Invalid JSON");
        }

        var error = bCapServSession.validate(data);
        if (error) {
            logger.error("Invalid session", error);
            return failWithMessage(res, error);
        }

        try {
            var session = createSessionWithData(data);
        } catch (e) {
            logger.error("Failed to create session", e);
            res.writeHead(403);
            res.write(e.message);
            res.end();
            return;
        }

        var statusCode = sessions.length > 1 ? 202 : 201;

        res.writeHead(statusCode, {"Location": session.rootPath});
        res.write(JSON.stringify(buster.extend(session.toJSON(), {
            slaves: slaves.map(function (slave) {
                return {id: slave.id}
            })
        })));
        res.end();
    }

    function createSessionWithData(data) {
        var resourceSet = busterResources.createResourceSet();
        var session = bCapServSession.create(data, resourceSet, httpServer);
        session.logger = logger;
        session.on("end", function () {
            unloadSession(session.id);
        });

        sessions.push(session);
        if (sessions.length == 1) {
            logger.debug("Starting newly created session immediately");
            loadCurrentSession();
        } else {
            logger.debug("Queuing newly created session");
        }

        return session;
    }

    function loadCurrentSession() {
        logger.debug("Broadcasting session start to slaves");
        slaves.forEach(function (slave) {
            slave.startSession(sessions[0]);
        });
    }

    function failWithMessage(res, message) {
        res.writeHead(400);
        res.write(message + "\n");
        res.end();
    }

    function captureSlave(req, res) {
        if (typeof(captureServer.oncapture) != "function") {
            failWithMessage(res, "Slave was created with no 'oncapture' handler.");
            return;
        }

        var slave = bCapServSlave.create(captureServer, bayeuxServer, busterResources,
                                         headerResourceSet, headerHeight,
                                         sessions[0]);
        slave.on("end", function () {
            unloadSlave(slave);
        });
        slaves.push(slave);
        captureServer.oncapture(req, res, slave);
    }

    function unloadSlave(slave) {
        slaves.splice(slaves.indexOf(slave), 1);
    }

    bayeuxServer = bCapServBayeuxServer.create(logger, captureServer.messagingContextPath);

    return captureServer;
};<commit_msg>Making slave instance creation a separate private function, for clarity.<commit_after>var buster = require("buster-core");
var bResources = require("buster-resources");
var bCapServBayeuxServer = require("./buster-capture-server-bayeux-server");
var httpServerRequestListenerProxy = require("./http-server-request-listener-proxy");
var bCapServSession = require("./session");
var bCapServSlave = require("./slave");
var URL = require("url");

var NOOP = function(){};

exports.create = function () {
    var busterResources = Object.create(bResources);
    var httpServer;
    var headerHeight;
    var headerResourceSet;
    var bayeuxServer;
    var sessions = [];
    var slaves = [];
    var logger = {"error":NOOP,"warn":NOOP,"log":NOOP,"info":NOOP,"debug":NOOP};

    var captureServer = {
        messagingContextPath: "/sessions/messaging",
        capturePath: "/capture",

        get sessions() {
            return sessions;
        },

        get slaves() {
            return slaves;
        },

        get logger() {
            return logger;
        },

        set logger(newLogger) {
            logger = newLogger;
            bayeuxServer.setLogger(newLogger);
        },

        header: function (height, resourceSetOpts) {
            if (headerResourceSet !== undefined) busterResources.removeResourceSet(headerResourceSet);

            headerHeight = height;
            resourceSetOpts.contextPath = "/slaveHeader";
            headerResourceSet = busterResources.createResourceSet(resourceSetOpts);
            return headerResourceSet;
        },

        createSession: function (data) {
            var error = bCapServSession.validate(data);
            if (error) throw new Error(error);
            logger.info("Creating session");
            return createSessionWithData(data);
        },

        destroySession: function (id) {
            var i = getSessionIndexById(id);
            if (i >= -1) {
                logger.info("Destroying session");
                logger.debug("Session ID", id)
                sessions[i].end();
            }
        },

        destroyCurrentSession: function () {
            if (sessions.length > 0) {
                this.destroySession(sessions[0].id);
            }
        },

        get bayeux() {
            return bayeuxServer.getClient();
        },

        attach: function (_httpServer) {
            httpServer = _httpServer;
            bayeuxServer.attach(httpServer);
            httpServerRequestListenerProxy.attach(httpServer, respond);
        }
    }

    function respond(req, res) {
        var url = URL.parse(req.url);

        if (req.method == "GET" && url.pathname == captureServer.capturePath) {
            logger.info("Capturing new slave");
            captureSlave(req, res);
            return true;
        }

        if (req.method == "POST" && url.pathname == "/sessions") {
            logger.debug("Creating session via HTTP");
            createSessionFromRequest(req, res);
            return true;
        }

        if (req.method == "GET" && url.pathname == "/resources") {
            listKnownResources(res);
            return true;
        }

        if (req.method == "DELETE" && url.pathname == "/resources") {
            resourceGc(res);
            return true;
        }

        if (slaves.some(function (slave) {
            return slave.respond(req, res, url.pathname);
        })) return true;

        if (sessions.some(function(session) {
            return session.respond(req, res, url.pathname)
        })) return true;

        if (busterResources.getResourceViaHttp(req, res)) return true;
    }

    function resourceGc(res) {
        logger.debug("Performing resource garbage collection");
        busterResources.gc();
        res.writeHead(200);
        res.end();
    }

    function listKnownResources(res) {
        logger.debug("Listing known resources");
        res.writeHead(200);
        res.write(JSON.stringify(busterResources.getCachedResources()));
        res.end();
    }

    function getSessionIndexById(id) {
        var matches = sessions.filter(function (sess) { return sess.id == id; });
        return sessions.indexOf(matches[0]);
    }

    function unloadSession(id) {
        var i = getSessionIndexById(id);

        var session = sessions[i];
        // TODO: Session should remove its own resource set
        busterResources.removeResourceSet(session.resourceSet);
        sessions.splice(i, 1);

        // Did we unload the current session?
        if (i == 0) {
            logger.debug("Current session did end.");
            if (sessions.length > 0) {
                logger.debug("Starting queued session.");
                loadCurrentSession();
            }
        }
    }

    function createSessionFromRequest(req, res) {
        var requestBody = "";
        req.setEncoding("utf8");
        req.on("data", function (chunk) { requestBody += chunk; });
        req.on("end", function () {
            createSessionWithRequestBody(requestBody, req, res);
        });
    }

    function createSessionWithRequestBody(requestBody, req, res) {
        try {
            var data = JSON.parse(requestBody);
        } catch(e) {
            logger.error("Invalid JSON", requestBody);
            return failWithMessage(res, "Invalid JSON");
        }

        var error = bCapServSession.validate(data);
        if (error) {
            logger.error("Invalid session", error);
            return failWithMessage(res, error);
        }

        try {
            var session = createSessionWithData(data);
        } catch (e) {
            logger.error("Failed to create session", e);
            res.writeHead(403);
            res.write(e.message);
            res.end();
            return;
        }

        var statusCode = sessions.length > 1 ? 202 : 201;

        res.writeHead(statusCode, {"Location": session.rootPath});
        res.write(JSON.stringify(buster.extend(session.toJSON(), {
            slaves: slaves.map(function (slave) {
                return {id: slave.id}
            })
        })));
        res.end();
    }

    function createSessionWithData(data) {
        var resourceSet = busterResources.createResourceSet();
        var session = bCapServSession.create(data, resourceSet, httpServer);
        session.logger = logger;
        session.on("end", function () {
            unloadSession(session.id);
        });

        sessions.push(session);
        if (sessions.length == 1) {
            logger.debug("Starting newly created session immediately");
            loadCurrentSession();
        } else {
            logger.debug("Queuing newly created session");
        }

        return session;
    }

    function loadCurrentSession() {
        logger.debug("Broadcasting session start to slaves");
        slaves.forEach(function (slave) {
            slave.startSession(sessions[0]);
        });
    }

    function failWithMessage(res, message) {
        res.writeHead(400);
        res.write(message + "\n");
        res.end();
    }

    function captureSlave(req, res) {
        if (typeof(captureServer.oncapture) != "function") {
            failWithMessage(res, "Slave was created with no 'oncapture' handler.");
            return;
        }

        captureServer.oncapture(req, res, createSlave());
    }

    function createSlave() {
        var slave = bCapServSlave.create(captureServer, bayeuxServer, busterResources,
                                         headerResourceSet, headerHeight,
                                         sessions[0]);
        slave.on("end", function () { unloadSlave(slave); });
        slaves.push(slave);

        return slave;
    }

    function unloadSlave(slave) {
        slaves.splice(slaves.indexOf(slave), 1);
    }

    bayeuxServer = bCapServBayeuxServer.create(logger, captureServer.messagingContextPath);

    return captureServer;
};<|endoftext|>


<commit_before>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('core') ;

/** @namespace SC.RestServer

  Implements a REST client communicating in a RESTful manner with a backend server.

*/
SC.RestServer = SC.Server.extend({

  urlFor: function(resource, action, ids, params, method) {
    url = resource;
    if (ids && ids.length == 1) url = url + '/' + ids[0];
    if (action && action != '') url = url + '/' + action;
    return url;
  },

  _listForAction: '',
  _listForMethod: 'get',

  _createAction: '',
  _createMethod: 'post',

  _refreshAction: '',
  _refreshMethod: 'get',

  _commitAction: '',
  _commitMethod: 'put',

  _destroyAction: '',
  _destroyMethod: 'delete'

}) ;
<commit_msg>Comments for rest_server<commit_after>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('core') ;

/** @namespace SC.RestServer

  Implements a REST client communicating in a RESTful manner with a backend server.

  Usually you wouldn't need to call any of the methods on this class or it's superclass,
  except for calling the +listFor+ method. The other methods are called for you when you
  work with your model objects. For example, calling myObject.commit(); will call the
  commitRecords method on this server if you had defined this server to be to the
  +dataSource+ of myObject.

  To have an SC model reflect data on a backend server attach an instance of this class
  to your application. For example:

      Contacts = SC.Object.create({
        server: SC.RESTServer.create({ prefix: ['Contacts'] })
      }) ;

  Then attach that server as the +dataSource+ to each model class that you want to have
  reflected. Also define a +resourceURL+ which defines the URL where the collection of
  your model can be queried. For example:

      Contacts.Contact = SC.Record.extend(
        dataSource: Contacts.server,
        resourceURL: 'sc/contacts',
        properties: ['guid','firstName','lastName'],
        primaryKey: 'guid'
      }) ;

  When you work with your models, behind the scenes SC will use 5 main methods on this
  server. Each is listed below, together with the HTTP method used in the call to the
  backend server and the URL that is being called. The URL is based on the example
  given above.

      listFor             GET    /sc/contacts

      createRecords       POST   /sc/contacts

      refreshRecords
      for one record      GET    /sc/contacts/12345

      refreshRecords
      for many records    GET    /sc/contacts?ids=1,2,3,4,5,6

      commitRecords
      for one record      PUT    /sc/contacts/12345

      commitRecords
      for many records    PUT    /sc/contacts?ids=1,2,3,4,5

      destroyRecords
      for one record      DELETE /sc/contacts/12345

      destroyRecords
      for many records    DELETE /sc/contacts?ids=1,2,3,4,5

  The above is the default behaviour of this server. If you want different URLs
  to be generated then extend this class and override the +urlFor+ method.

  Another way to override the above is to tell SC where member resources can
  be refreshed, committed and destroyed. For example, when SC calls
      GET /sc/contacts
  you could reply as follows:

      records: [
        {  guid: '123',
          type: "Contact",
          refreshURL: "/contacts?refresh=123",
          updateURL: "/contacts/123?update=Y",
          destroyURL: "/contacts/123",
          firstName: "Charles",
          ...
        }],
        ...
      }

  Then when contact 123 needs to be refreshed later on by SC, it will call:

      GET /contacts?refresh=123

  instead of GET /contacts/123. Note that this only works for members on your
  resource. If a collection of contacts needed to be refreshed it would still
  call for example GET /contacts?id=123,456,789 instead of making 3 separate
  calls.

  Because some browsers cannot actually perform an HTTP PUT or HTTP DELETE it
  will actually perform an HTTP POST but will put an additional key,value pair
  in the post data packet. For HTTP PUT it will add _method='put' and for
  HTTP DELETE it will add _method='delete' in the post data.

  Via the SC.Server#request method you can also call collection and member
  functions on your resource. Use the +action+ parameter for this. For
  example, server.request('contacts', 'archive', null, params, 'delete')
  would call:

      DELETE /contacts/archive

  And server.request('contacts', 'give', [12345], {'amount': 1000}, 'put')
  would call:

      PUT /contacts/12345/give

  with post data amount=1000.

  Alternatively explicitely define the URL to use by setting the +url+
  property in the +params+ argument that is passed to the server.request method.
  For example:

      Contacts.server.request(null,null,null, {url: '/sc/archive'}, 'delete')

  would call:

      DELETE /sc/archive

  @extends SC.Server
  @author Lawrence Pit
  @copyright 2006-2008, Sprout Systems, Inc. and contributors.
  @since SproutCore 1.0
*/
SC.RestServer = SC.Server.extend({

  /**
    Generates the URL that is going to be called by this server. Note that you
    should only return relative URLs. You can only call resources that are on
    the same domain as where this script was downloaded from.

    @param {String} resource  the URL where the collection of the resource can be queried
    @param {String} action    the action that should be performed on the resource
    @param {Array} ids        array of identifiers of your model instances
    @param {Array} params     parameters that were passed to the SC.Server#request method
    @param {String} method    the HTTP method that will be used
    @returns {String} the URL to use in the request to the backend server
  **/
  urlFor: function(resource, action, ids, params, method) {
    url = resource;
    if (ids && ids.length == 1) url = url + '/' + ids[0];
    if (action && action != '') url = url + '/' + action;
    return url;
  },

  /* privates, overrides the values in SC.Server */

  _listForAction: '',
  _listForMethod: 'get',

  _createAction: '',
  _createMethod: 'post',

  _refreshAction: '',
  _refreshMethod: 'get',

  _commitAction: '',
  _commitMethod: 'put',

  _destroyAction: '',
  _destroyMethod: 'delete'

}) ;
<|endoftext|>


<commit_before>define([
    'underscore',
    'backbone',
    'text!templates/TrackPicker.html',
    'Audiee/Models.Track'
], function(_, Backbone, TrackPickerV, TrackM) {

    return Backbone.View.extend({
        // parent DOM element
        el: $('#app-tracks-listing'),

        // cached template function
        template: _.template(TrackPickerV),

        // DOM events listeners
        events: {
            'click #pickerHeader'   : 'togglePicker',
            'click li.category'     : 'showCategory',
            'click .choice'         : 'addTrack'
        },

        initialize: function() {
            _.bindAll(this, 'render', 'uploadFile', 'addTrack', 'createFileBlob'); //, '_fileSelected', '_fileLoaded', 'handleKey'
            this.el.bind('Audiee:fileLoaded', this._fileLoaded);
            this.render();
        },

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

        togglePicker: function(el) {
            if (!this.el.hasClass('active')) {
                var height = $('#editor-view').outerHeight();
                var drawerHeight = $('#app-tracks-listing').outerHeight() - $('#pickerHeader').outerHeight();
                $('#app-tracks-listing').animate({
                    'bottom': '0px'
                }, 200);
                $('#editor-view').animate({
                    'height': height - drawerHeight
                }, 200);

                // Add active class
                this.el.addClass('active');
            } else {
                $('#app-tracks-listing').animate({
                    'bottom': '-200px'
                }, 200, function() {
                    Audiee.Views.Editor.resizeView();
                });

                // Remove active class
                this.el.removeClass('active');
            }
            $('#app-tracks-listing .category-listing').toggleClass('show');
        },

        showCategory: function(e) {
            var $target = $(e.target);
            $target.siblings().removeClass('active');
            $target.addClass('active');
        },

        createFileBlob: function(directory, blob, fileName, opt_callback) {
            var onError = function(e) {
                console.log('There was an error', e);
            };

            directory.getFile(fileName, {create: true, exclusive: true}, function(fileEntry) {
                fileEntry.createWriter(function(writer) {
                    if (opt_callback) {
                        writer.onwrite = opt_callback;
                    }
                    writer.write(blob);
                }, onError);
            }, onError);
        },

        uploadFile: function(url, name) {
            var onError = function(e) {
                console.log('There was an error', e);
            };

            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.responseType = 'blob';

            xhr.onload = function(e) {
                if (this.status == 200) {

                    window.requestFileSystem(TEMPORARY, 1024*1024*5 , function(fs) {
                        var onWrite = function(evt) {
                            console.log('Write completed.');
                            // name is the track file name
                            $('li.choice').removeClass('active');
                            filer.open(name, function(file) {
                                Audiee.Player.loadFile(file, $('#menu-view'));
                            });
                        };

                        // Write file to the root directory.
                        Audiee.Views.TrackPicker.createFileBlob(fs.root, xhr.response, name, onWrite);
                    }, onError);
                }
            };

            xhr.send(null);
        },

        addTrack: function(e) {
            var $target = $(e.target),
                directory = '/track-library/' + $target.data('directory') + '/',
                track = $target.data('track');
            var exists = false;

            filer.ls('/', function(entries) {
                $.each(entries, function(index, value) {
                    if (value.name === track) {
                        exists = true;
                    }
                });
                if (exists) {
                    filer.open(track, function(file) {
                        Audiee.Player.loadFile(file, $('#menu-view'));
                    });
                } else {
                    Audiee.Views.TrackPicker.uploadFile(directory + track, track);
                }
            });

        }
    });
});<commit_msg>Added licensing information at the top of the Picker View scripts page<commit_after>/**
 * View for the Track Selection drawer
 *
 * @file        Views.TrackPicker.js
 * @author      Doug Niccum <dniccumdesign[at]gmail.com>
 * @copyright   Copyright 2015, Doug Niccum (http://dniccumdesign.com)
 * @license     MIT License (http://www.opensource.org/licenses/mit-license.php)
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 */

define([
    'underscore',
    'backbone',
    'text!templates/TrackPicker.html',
    'Audiee/Models.Track'
], function(_, Backbone, TrackPickerV, TrackM) {

    return Backbone.View.extend({
        // parent DOM element
        el: $('#app-tracks-listing'),

        // cached template function
        template: _.template(TrackPickerV),

        // DOM events listeners
        events: {
            'click #pickerHeader'   : 'togglePicker',
            'click li.category'     : 'showCategory',
            'click .choice'         : 'addTrack'
        },

        initialize: function() {
            _.bindAll(this, 'render', 'uploadFile', 'addTrack', 'createFileBlob'); //, '_fileSelected', '_fileLoaded', 'handleKey'
            this.el.bind('Audiee:fileLoaded', this._fileLoaded);
            this.render();
        },

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

        togglePicker: function(el) {
            if (!this.el.hasClass('active')) {
                var height = $('#editor-view').outerHeight();
                var drawerHeight = $('#app-tracks-listing').outerHeight() - $('#pickerHeader').outerHeight();
                $('#app-tracks-listing').animate({
                    'bottom': '0px'
                }, 200);
                $('#editor-view').animate({
                    'height': height - drawerHeight
                }, 200);

                // Add active class
                this.el.addClass('active');
            } else {
                $('#app-tracks-listing').animate({
                    'bottom': '-200px'
                }, 200, function() {
                    Audiee.Views.Editor.resizeView();
                });

                // Remove active class
                this.el.removeClass('active');
            }
            $('#app-tracks-listing .category-listing').toggleClass('show');
        },

        showCategory: function(e) {
            var $target = $(e.target);
            $target.siblings().removeClass('active');
            $target.addClass('active');
        },

        createFileBlob: function(directory, blob, fileName, opt_callback) {
            var onError = function(e) {
                console.log('There was an error', e);
            };

            directory.getFile(fileName, {create: true, exclusive: true}, function(fileEntry) {
                fileEntry.createWriter(function(writer) {
                    if (opt_callback) {
                        writer.onwrite = opt_callback;
                    }
                    writer.write(blob);
                }, onError);
            }, onError);
        },

        uploadFile: function(url, name) {
            var onError = function(e) {
                console.log('There was an error', e);
            };

            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.responseType = 'blob';

            xhr.onload = function(e) {
                if (this.status == 200) {

                    window.requestFileSystem(TEMPORARY, 1024*1024*5 , function(fs) {
                        var onWrite = function(evt) {
                            console.log('Write completed.');
                            // name is the track file name
                            $('li.choice').removeClass('active');
                            filer.open(name, function(file) {
                                Audiee.Player.loadFile(file, $('#menu-view'));
                            });
                        };

                        // Write file to the root directory.
                        Audiee.Views.TrackPicker.createFileBlob(fs.root, xhr.response, name, onWrite);
                    }, onError);
                }
            };

            xhr.send(null);
        },

        addTrack: function(e) {
            var $target = $(e.target),
                directory = '/track-library/' + $target.data('directory') + '/',
                track = $target.data('track');
            var exists = false;

            filer.ls('/', function(entries) {
                $.each(entries, function(index, value) {
                    if (value.name === track) {
                        exists = true;
                    }
                });
                if (exists) {
                    filer.open(track, function(file) {
                        Audiee.Player.loadFile(file, $('#menu-view'));
                    });
                } else {
                    Audiee.Views.TrackPicker.uploadFile(directory + track, track);
                }
            });

        }
    });
});<|endoftext|>


<commit_before>import Vue from "vue";
import Vuex from "vuex";
import App from "./app.view";
import { createRouter } from "./router";

import EffectLoader from "./effect-loader.js";

import Packages from "./all.websom-packages";
import State from "./all.websom-state";
import Scripts from "./all.websom-scripts";
import Effects from "./all.websom-effects";
import "./all.websom-styles";

import WebsomVue from "./vue.plugin";

import PortalVue from "portal-vue";

import WebsomUtils from "./websom-client";

import "normalize.css";

import WebsomLogo from "../base-theme/assets/logo.svg";
import WebsomLogoRaster from "../base-theme/assets/logo.png";

export async function createApp (api, websomServer) {
	const router = createRouter(Packages);

	Vue.use(WebsomVue);

	Vue.use(PortalVue);

	Vue.use(Vuex);

	let ssr = true;

	if (typeof window !== "undefined") {
		ssr = false;
		api = window.websom_api || api;
	}

	const store = new Vuex.Store({
		state: () => ({
			websom: {
				colorScheme: "light",
				api,
				ssr,
				data: {
					config: {},
					routes: {},
					endpoints: {},
					navigation: {

					},
					loaded: false
				},
				validators: {}
			},
			userSystem: {
				user: null
			},
			entities: {},
			assets: {
				logo: WebsomLogo,
				logoRaster: WebsomLogoRaster
			},
			title: "Websom Page",
			metaDescription: "This is a websom page."
		}),
		actions: {
			async fetchWebsomData({ commit }) {
				if (ssr) {
					commit("setWebsomData", await websomServer.configService.computeClientData());
				}else{
					commit("setWebsomData", await websomUtils.fetch("/data", {}));
				}
			},
			registerValidator({ commit }, d) {
				commit("setValidator", d);
			}
		},
		mutations: {
			setWebsomData(state, data) {
				state.websom.data = data;
				state.websom.data.loaded = true;
			},
			setValidator(state, d) {
				Vue.set(state.websom.validators, d.type, d.handler);
			},
			setColorScheme(state, d) {
				state.websom.colorScheme = d;
			},
			setUser(state, user) {
				state.userSystem.user = user;
			},
			setEntity(state, entity) {
				let collection = entity.$collection;

				if (!state.entities[collection])
					state.entities[collection] = {};

				if (state.entities[collection][entity.id]) {
					let oldEntity = state.entities[collection][entity.id];

					for (let f of entity.$fields) {
						Vue.set(oldEntity, f, entity[f]);
					}
				}else{
					state.entities[collection][entity.id] = entity;
				}

				return state.entities[collection][entity.id];
			}
		}
	});

	var websomUtils = WebsomUtils(store, Packages);

	State.forEach(s =>
		store.registerModule(s.info.name, s.script(websomUtils))
	);

	if (!ssr && window.__INITIAL_STATE__) {
		console.log("Loaded with initial state");

		store.replaceState(window.__INITIAL_STATE__);

		console.log(store.state);
	}

	if (!ssr) {
		let darkModeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");

		store.commit("setColorScheme", darkModeMediaQuery.matches ? "dark" : "light");
		console.log(`Color scheme ${store.state.websom.colorScheme == "dark" ? "🌒 dark" : "☀ light"}.`);

		darkModeMediaQuery.addListener((e) => {
			store.commit("setColorScheme", e.matches ? "dark" : "light")
		});
	}

	if (!store.state.websom.data.loaded)
		await store.dispatch("fetchWebsomData");
	else
		console.log("Websom data is already loaded");

	store.state.websom.data.navigation.navbar = [
		{
			type: "component",
			component: "user-nav",
			align: "right",
			props: {
				name: "Test"
			}
		}
	];

	let formats = {
		"single-line": new RegExp("^([^\\n]*)$"),
		"email": new RegExp("^(([^<>()\\[\\]\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\"]+)*)|(\".+\"))@(([^<>()[\\]\\.,;:\\s@\"]+\\.)+[^<>()[\\]\\.,;:\\s@\"]{2,})"),
		"number": new RegExp("^(-)?([\d.,]*)$")
	};

	store.dispatch("registerValidator", {type: "format", handler: (config, value) => {
		return formats[config.format].test(value);
	}});

	store.dispatch("registerValidator", {type: "regex", handler: (config, value) => {
		return new RegExp(config.regex).test(value);
	}});

	store.dispatch("registerValidator", {type: "limit", handler: (config, value) => {
		return value.length >= config.min && value.length <= config.max;
	}});

	store.dispatch("registerValidator", {type: "unique", handler: async (config, value) => {
		if (config.route) {

		}

		return true;
	}});

	for (let v of Packages) {
		Vue.component(v.info.name, v.vue);
	}

	const app = new Vue({
		router,
		render: h => h(App.vue),
		store,
		websomUtils
	});

	if (!ssr) {
		let effectLoader = new EffectLoader(Effects);
		effectLoader.initialize();
	}

	for (let s of Scripts)
		s.script({
			app,
			websom: websomUtils,
			store,
			packages: Packages,
			ssr
		});

	return { app, router, store };
}<commit_msg>Added new state actions.<commit_after>import Vue from "vue";
import Vuex from "vuex";
import App from "./app.view";
import { createRouter } from "./router";

import EffectLoader from "./effect-loader.js";

import Packages from "./all.websom-packages";
import State from "./all.websom-state";
import Scripts from "./all.websom-scripts";
import Effects from "./all.websom-effects";
import "./all.websom-styles";

import WebsomVue from "./vue.plugin";

import PortalVue from "portal-vue";

import WebsomUtils from "./websom-client";

import "normalize.css";

import WebsomLogo from "../base-theme/assets/logo.svg";
import WebsomLogoRaster from "../base-theme/assets/logo.png";

export async function createApp (api, websomServer) {
	const router = createRouter(Packages);

	Vue.use(WebsomVue);

	Vue.use(PortalVue);

	Vue.use(Vuex);

	let ssr = true;

	if (typeof window !== "undefined") {
		ssr = false;
		api = window.websom_api || api || (typeof __websom_api !== "undefined" ? __websom_api : null);
	}

	const store = new Vuex.Store({
		state: () => ({
			websom: {
				colorScheme: "light",
				api,
				ssr,
				data: {
					config: {},
					routes: {},
					endpoints: {},
					navigation: {
						navbar: []
					},
					loaded: false
				},
				validators: {}
			},
			userSystem: {
				user: null
			},
			entities: {},
			assets: {
				logo: WebsomLogo,
				logoRaster: WebsomLogoRaster
			},
			title: "Websom Page",
			metaDescription: "This is a websom page."
		}),
		actions: {
			async fetchWebsomData({ commit }) {
				if (ssr) {
					commit("setWebsomData", await websomServer.configService.computeClientData());
				}else{
					if (typeof __websom_data !== "undefined") {
						commit("setWebsomData", __websom_data);
						return;
					}

					try {
						commit("setWebsomData", await websomUtils.fetch("/data", {}));
					} catch (e) {
						console.error(e);
					}
				}
			},
			registerValidator({ commit }, d) {
				commit("setValidator", d);
			}
		},
		mutations: {
			setWebsomData(state, data) {
				state.websom.data = data;
				state.websom.data.loaded = true;
			},
			setValidator(state, d) {
				Vue.set(state.websom.validators, d.type, d.handler);
			},
			setColorScheme(state, d) {
				state.websom.colorScheme = d;
			},
			setUser(state, user) {
				state.userSystem.user = user;
			},
			setEntity(state, entity) {
				let collection = entity.$collection;

				if (!state.entities[collection])
					state.entities[collection] = {};

				if (state.entities[collection][entity.id]) {
					let oldEntity = state.entities[collection][entity.id];

					for (let f of entity.$fields) {
						Vue.set(oldEntity, f, entity[f]);
					}
				}else{
					state.entities[collection][entity.id] = entity;
				}

				return state.entities[collection][entity.id];
			},
			addNavItem(state, data) {
				state.websom.data.navigation.navbar.push(data);
			}
		}
	});

	var websomUtils = WebsomUtils(store, Packages);

	State.forEach(s =>
		store.registerModule(s.info.name, s.script(websomUtils))
	);

	if (!ssr && window.__INITIAL_STATE__) {
		console.log("Loaded with initial state");

		store.replaceState(window.__INITIAL_STATE__);

		console.log(store.state);
	}

	if (!ssr) {
		let darkModeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");

		store.commit("setColorScheme", darkModeMediaQuery.matches ? "dark" : "light");
		console.log(`Color scheme ${store.state.websom.colorScheme == "dark" ? "🌒 dark" : "☀ light"}.`);

		darkModeMediaQuery.addListener((e) => {
			store.commit("setColorScheme", e.matches ? "dark" : "light")
		});
	}

	if (!store.state.websom.data.loaded)
		store.dispatch("fetchWebsomData").then(() => {}).catch((e) => {});
	else
		console.log("Websom data is already loaded");

	store.commit("addNavItem",
		{
			type: "component",
			component: "user-nav",
			align: "right",
			props: {
				name: "Test"
			}
		}
	);

	let formats = {
		"single-line": new RegExp("^([^\\n]*)$"),
		"email": new RegExp("^(([^<>()\\[\\]\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\"]+)*)|(\".+\"))@(([^<>()[\\]\\.,;:\\s@\"]+\\.)+[^<>()[\\]\\.,;:\\s@\"]{2,})"),
		"number": new RegExp("^(-)?([\d.,]*)$")
	};

	store.dispatch("registerValidator", {type: "format", handler: (config, value) => {
		return formats[config.format].test(value);
	}});

	store.dispatch("registerValidator", {type: "regex", handler: (config, value) => {
		return new RegExp(config.regex).test(value);
	}});

	store.dispatch("registerValidator", {type: "limit", handler: (config, value) => {
		return value.length >= config.min && value.length <= config.max;
	}});

	store.dispatch("registerValidator", {type: "unique", handler: async (config, value) => {
		if (config.route) {

		}

		return true;
	}});

	for (let v of Packages) {
		Vue.component(v.info.name, v.vue);
	}

	const app = new Vue({
		router,
		render: h => h(App.vue),
		store,
		websomUtils
	});

	if (!ssr) {
		let effectLoader = new EffectLoader(Effects);
		effectLoader.initialize();
	}

	for (let s of Scripts)
		s.script({
			app,
			websom: websomUtils,
			store,
			packages: Packages,
			ssr
		});

	if (typeof __websom_route === "string")
		router.push(__websom_route);

	return { app, router, store };
}<|endoftext|>


<commit_before>'use strict'

function _getSubscriptionContainer() {
  return document.getElementById('subscription-manager-container')
}

Promise.all([
  __collections,
  __subscriptions
]).then(valueArr => {
  var collections = valueArr[0]
  var subscriptions = valueArr[1]

  template.render('manager-section',{ quantity: Object.keys(collections).length }).then(html => {
    var elem = document.createElement('div')
    _getSubscriptionContainer().parentNode.insertBefore(elem,_getSubscriptionContainer())
    elem.outerHTML = html

    return document.getElementById('collections-manager-container')
  }).then(node => {
    var form = document.getElementById('add-collection-form')

    node.addEventListener('click',e => {
      if(e.target.hasAttribute('data-collection-id')) {
        var removedId = e.target.dataset.collectionId
        if(window.confirm('Remove collection '+ collections[removedId].name+'?')) {
          _removeCollection(e.target.dataset.collectionId)
        }
      }
    })

    form.querySelector('input[name="add-collection"]').addEventListener('input',e => {
      e.target.classList.toggle('invalid',!e.target.checkValidity() && e.target.value !== '')
    })

    form.querySelector('input[name="add-collection"]').addEventListener('invalid',e => {
      e.target.classList.add('invalid')
    })

    form.addEventListener('submit',e => {
      _addCollection(form.querySelector('input[name="add-collection"]').value)

      e.preventDefault()
      e.stopPropagation()
      return false
    })

    return document.querySelector('#collection-manager-list tbody')
  }).then(node => {
    return Object.keys(collections).map(id => {
      return template.render('manager-section-item',{
        id: id,
        name: collections[id].name
      }).then(html => {
        var elem = document.createElement('tr')
        node.appendChild(elem)
        elem.outerHTML = html
        return document.getElementById(id+'-manager-collection')
      })
    })
  })

  var buttons

  Promise.all(
    [template.render('manager-subscription-popup-item', { id: '', label: '' })].concat(
    Object.keys(collections).map(k => {
      return template.render('manager-subscription-popup-item', { id: collections[k].id, label: collections[k].name })
    }))
  ).then(valueArr => {
    buttons = valueArr.join('')
    return Promise.all(Object.keys(collections).map(k => {
      return template.render('manager-subscription-button', { id: collections[k].id, label: collections[k].name, buttons: buttons }).then(html => {
        return { [collections[k].name]: html }
      })
    }))
  })
  .then(valueArr => {
    return template.render('manager-subscription-button', { id: '', label: '', buttons: buttons }).then(html => {
      valueArr.push({'(none)':html})
      return valueArr.reduce((all,curr) => Object.assign(all,curr),{})
    })
  })
  .then(htmls => {
    let query = '#subscription-manager-list tr.subscription-item td:first-of-type .subscription-title-wrap'
    Array.prototype.slice.call(document.querySelectorAll(query))
    .map(node => {
      var collection = subscriptions[node.closest('tr').dataset.channelExternalId].collection
      var elem = document.createElement('div')
      node.appendChild(elem)

      if(collection === null) {
        elem.outerHTML = htmls['(none)']
      } else {
        elem.outerHTML = htmls[collection.name]
      }
    })
  })
})
<commit_msg>Getting the id properly.<commit_after>'use strict'

function _getSubscriptionContainer() {
  return document.getElementById('subscription-manager-container')
}

Promise.all([
  __collections,
  __subscriptions
]).then(valueArr => {
  var collections = valueArr[0]
  var subscriptions = valueArr[1]

  template.render('manager-section',{ quantity: Object.keys(collections).length }).then(html => {
    var elem = document.createElement('div')
    _getSubscriptionContainer().parentNode.insertBefore(elem,_getSubscriptionContainer())
    elem.outerHTML = html

    return document.getElementById('collections-manager-container')
  }).then(node => {
    var form = document.getElementById('add-collection-form')

    node.addEventListener('click',e => {
      if(e.target.hasAttribute('data-collection-id')) {
        var removedId = e.target.dataset.collectionId
        if(window.confirm('Remove collection '+ collections[removedId].name+'?')) {
          _removeCollection(e.target.dataset.collectionId)
        }
      }
    })

    form.querySelector('input[name="add-collection"]').addEventListener('input',e => {
      e.target.classList.toggle('invalid',!e.target.checkValidity() && e.target.value !== '')
    })

    form.querySelector('input[name="add-collection"]').addEventListener('invalid',e => {
      e.target.classList.add('invalid')
    })

    form.addEventListener('submit',e => {
      _addCollection(form.querySelector('input[name="add-collection"]').value)

      e.preventDefault()
      e.stopPropagation()
      return false
    })

    return document.querySelector('#collection-manager-list tbody')
  }).then(node => {
    return Object.keys(collections).map(id => {
      return template.render('manager-section-item',{
        id: id,
        name: collections[id].name
      }).then(html => {
        var elem = document.createElement('tr')
        node.appendChild(elem)
        elem.outerHTML = html
        return document.getElementById(id+'-manager-collection')
      })
    })
  })

  var buttons

  Promise.all(
    [template.render('manager-subscription-popup-item', { id: '', label: '' })].concat(
    Object.keys(collections).map(k => {
      return template.render('manager-subscription-popup-item', { id: k, label: collections[k].name })
    }))
  ).then(valueArr => {
    buttons = valueArr.join('')
    return Promise.all(Object.keys(collections).map(k => {
      return template.render('manager-subscription-button', { id: k, label: collections[k].name, buttons: buttons }).then(html => {
        return { [collections[k].name]: html }
      })
    }))
  })
  .then(valueArr => {
    return template.render('manager-subscription-button', { id: '', label: '', buttons: buttons }).then(html => {
      valueArr.push({'(none)':html})
      return valueArr.reduce((all,curr) => Object.assign(all,curr),{})
    })
  })
  .then(htmls => {
    let query = '#subscription-manager-list tr.subscription-item td:first-of-type .subscription-title-wrap'
    Array.prototype.slice.call(document.querySelectorAll(query))
    .map(node => {
      var collection = subscriptions[node.closest('tr').dataset.channelExternalId].collection
      var elem = document.createElement('div')
      node.appendChild(elem)

      if(collection === null) {
        elem.outerHTML = htmls['(none)']
      } else {
        elem.outerHTML = htmls[collection.name]
      }
    })
  })
})
<|endoftext|>