<commit_before>requirejs.config({
    waitSeconds: 60
});

require([
  "libs/text", // part of require js
  "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js",
  "libs/ejs_production"
  ],
    function(until)
    {
      require([
      "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js",
      "libs/jquery.form"]);

      $.getJSON("api/phoxy", function(data)
      {
        phoxy.config = data;
        requirejs.config({baseUrl: phoxy.Config()['js_dir']});

        $('script[phoxy]').each(function()
        {
          phoxy.ApiRequest($(this).attr("phoxy"));
        });
      });
    }
  );

function PhoxyHashChangeCallback()
{
  if (phoxy.ChangeHash(location.hash))
    phoxy.ApiRequest(phoxy.hash);
}

var phoxy =
{
  loaded : false,
  hash : false,
  Load : function( )
    {
      this.loaded = true;
      var hash = location.hash.substring(1);
      phoxy.ApiRequest(hash);
      this.hash = hash;
      $(window).bind('hashchange', PhoxyHashChangeCallback);
    }
  ,
  Defer : function(callback, time)
  {
    if (time == undefined)
      time = 0;
    var func = $.proxy(
      function()
      {
        callback.call(this);
      },
      this);
    setTimeout(func, time);
  }
  ,
  WaitFor : function(callback_condition, callback, timeout, check_every)
    {
      var
        check_timeout = 60, // 1 minute for render to complete
        check_delay = 500; // check every 500ms

      if (timeout != undefined)
        check_timeout = timeout;
      if (check_every != undefined)
        check_delay = check_every;

      var func = function()
      {
        if (!callback_condition())
          return;
        callback();
      }
      if (callback_condition())
        return func();

      function WaitAndCallCountDown( i )
      {
        if (i <= 0)
          return func();

        phoxy.Defer(function()
        {
          if (callback_condition())
            i = 0;
          WaitAndCallCountDown(i - 1);
        }, check_delay);
      }

      WaitAndCallCountDown(check_timeout * 1000 / check_delay);
    }
  ,
  Appeared : function(jquery_selector, callback, timeout, call_delay)
    {
      function Div()
      {
        return $(phoxy.OptimiseSelector(jquery_selector));
      }
      function IsDivAppeared()
      {
        return Div()[0] != undefined;
      }

      phoxy.Defer(function()
      {
        phoxy.WaitFor(IsDivAppeared, function()
        {
          phoxy.Defer.call(Div(), callback, call_delay);
        }, timeout)
      });
    }
  ,
  Disappeared : function(jquery_selector, callback, timeout, call_delay)
    {
      function IsDivDisappeared()
      {
        return $(phoxy.OptimiseSelector(jquery_selector))[0] == undefined;
      }

      phoxy.Defer(function()
      {
        phoxy.WaitFor(IsDivDisappeared, function()
        {
          phoxy.Defer(callback, call_delay);
        }, timeout);
      });
    }
  ,
  GenerateUniqueID : function()
    {
      var ret = "";
      var dictonary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

      for (var i = 0; i < 10; i++)
        ret += dictonary.charAt(Math.floor(Math.random() * dictonary.length));

      return ret;
    }
  ,
  PrepareCanvas : function(tag)
    {
      if (tag == undefined)
        tag = '
';
      function GetElementCode( el )
      {
        return $(el).wrapAll('

').parent().html();
      }

      var id =  phoxy.GenerateUniqueID();
      var obj = $(tag).attr('id', id);
      var div = GetElementCode(obj);

      return { id: id, obj: obj, html: div };
    }
  ,
  DeferRender : function (ejs, data, rendered_callback, tag)
    {
      console.log("phoxy.DeferRender", arguments);
      if (tag == undefined)
        tag = '<defer_render>';
      var canvas = phoxy.PrepareCanvas(tag);
      var id = canvas.id;

      phoxy.Appeared('#' + id, function()
      {
        phoxy.Fancy(ejs, data, function(html)
        {
          $('#' + id).replaceWith(html);
          if (typeof(rendered_callback) != 'undefined')
            rendered_callback(ejs, data);
        });
      });

      return canvas.html;
    }
  ,
  Fancy : function(design, data, callback)
    {
      console.log("phoxy.Fancy", arguments);

      var func;
      var callback = arguments[2];
      if (typeof(callback) == 'undefined')
        callback = function (){};
      var design = arguments[0];

      if (typeof(data) == 'undefined')
      { // single param call
        if (typeof(design) == 'undefined')
          return callback(undefined, undefined, undefined);
        if (typeof(design) == 'object')
        {
          var obj = arguments[0];
          // Maybe its wrong. Maybe i should ignore other params
          var design = obj.design;
          var data = obj.data;
          if (typeof(data) == 'undefined')
            data = {};
          delete obj.design;
          delete obj.data;
          delete obj.result;
          delete obj.replace;

          phoxy.ApiAnswer(obj, function()
          {
            phoxy.Fancy(design, data, callback);
          });
        }
        else
        { /* Called as RPC
            PARAMS:
              [0] - string with RPC command
            NOTE:
              target commands ignored.
              result will be rendered in this div.
           */
          var rpc = arguments[0];
          phoxy.AJAX(rpc, function(data, callback)
          {
            phoxy.Fancy(data, undefined, callback);
          }, [callback]);
        }
        return;
      }

      var data = arguments[1];
      function DataLoadedCallback(data)
      {
        if (typeof(data) == 'undefined')
          data = {};
        phoxy.Fancy(design, data, callback);
      }

      if (typeof(data) == 'function')
      { /* Get data as function callback */
        data(DataLoadedCallback);
      }
      else if (typeof(data) == 'string')
      { /* Download data with RPC */
        phoxy.AJAX(data, function(json)
        {
          DataLoadedCallback(json.data);
        });
      }
      else
      { /* Data loaded */
        var html;
        if (design != undefined)
          html = phoxy.Render(phoxy.Config()['ejs_dir'] + "/" + design, undefined, data);
        callback(html, design, data);
      }
    }
  ,
  ChangeHash : function (hash)
    {
      var t;
      t = hash.split(location.origin)[1];
      if (t !== undefined)
        hash = t;
      var t = hash.split('#')[1];
      if (t !== undefined)
        hash = t;
      var ret = phoxy.hash != hash;
      phoxy.hash = hash;
      location.hash = hash;
      return ret;
    }
  ,
  Reset : function (url)
    {
      if (url == true)
        location.reload();
      var parts = url.split('#');
      if (parts[1] == undefined)
        phoxy.ChangeHash('');
      else
        phoxy.ChangeHash("#" + parts[1]);
      var host = parts[0];
      if (host.length)
        location = host;
      else
        location.reload(parts[0]);
    }
  ,
  Render : function (design, result, data)
    {
      if (data === undefined)
        data = {};

      console.log("phoxy.Render", arguments);
      var html;
      if (design.search(".ejs") == -1)
        design += ".ejs";
      if (!phoxy.ForwardDownload(design))
        html = new EJS({'url' : design}).render(data);
      else
        html = new EJS({'text' : phoxy.ForwardDownload(design, true)}).render(data);
      if (result != undefined && result != '')
        $("#" + result).replaceWith(html);
      return html;
    }
  ,
  ApiAnswer : function( answer, callback )
    {
      if (answer.hash !== undefined)
      {
        if (answer.hash === null)
          answer.hash = "";
        this.ChangeHash(answer.hash);
      }
      if (answer.error)
      {
        alert(answer.error);
        if (answer.reset !== undefined)
          phoxy.Reset(answer.reset);
        return;
      }
      if (answer.reset !== undefined)
        phoxy.Reset(answer.reset);

      function Before()
      {
        function AfterBefore(_answer)
        {
          if (_answer !== undefined)
            answer = _answer;
          phoxy.ScriptsLoaded(answer, callback);
        }
        if (answer.before !== undefined)
          window[answer.before](answer, AfterBefore);
        else
          AfterBefore();
      }

      if (answer.script)
        require(answer.script, Before);
      else
        Before();
    }
  ,
  ScriptsLoaded : function( answer, callback )
    {
      function ScriptsFiresUp()
      {
        if (answer.routeline !== undefined)
          window[answer.routeline](answer);
        if (callback)
          callback(answer.data);
        if (!phoxy.loaded)
          phoxy.Load();
      }
      if (answer.design === undefined)
        return ScriptsFiresUp();

      var canvas = phoxy.PrepareCanvas('<render>');
      var id = canvas.id;
      var render_id = id;

      var element = canvas.obj;

      var url = phoxy.Config()['ejs_dir'] + "/" + answer.design;
      phoxy.ForwardDownload(url + ".ejs", function()
      {
        if (answer.replace === undefined)
          if (answer.result === undefined)
            $('body').append(element);
          else
            $('#' + answer.result).html(element);
        else
          render_id = answer.replace;

        phoxy.Render(
          url,
          render_id,
          answer.data);

        phoxy.Disappeared('#' + id, ScriptsFiresUp);
      });
    }
  ,
  ForwardDownload : function( url, callback_or_true_for_return )
  {
    if (typeof(storage) === "undefined")
      storage = {};

    if (callback_or_true_for_return === true)
      return storage[url];

    function AddToLocalStorage(data)
    {
      storage[url] = data;
      if (typeof(callback_or_true_for_return) == 'function')
        callback_or_true_for_return(data);
    }

    if (storage[url] != undefined)
    {
      if (typeof(callback_or_true_for_return) == 'function')
        callback_or_true_for_return(storage[url]);
      return true;
    }

    $.get(url, AddToLocalStorage);
    return false;
  }
  ,
  AJAX : function( url, callback, params )
    {
      console.log("phoxy.AJAX", arguments);
      $(function()
      {
        $.getJSON(phoxy.Config()['api_dir'] + "/" + url, function(data)
          {
            if (params == undefined)
              params = [];
            params.unshift(data);
            callback.apply(this, params);
          });
      });
    }
  ,
  ApiRequest : function( url, callback )
    {
      if (callback == undefined)
        phoxy.AJAX(url, phoxy.ApiAnswer);
      else
        phoxy.AJAX(url, phoxy.ApiAnswer, [callback]);
    }
  ,
  MenuCall : function( url, callback )
    {
        $(function()
        {
          $.getJSON(phoxy.Config()['api_dir'] + "/" + url, function(data)
          {
            phoxy.ChangeHash(url);
            phoxy.ApiAnswer(data, callback);
          });
        });
    }
  ,
  Config : function()
    {
      return this.config;
    }
  ,
  OptimiseSelector : function( str )
    { // http://learn.jquery.com/performance/optimize-selectors/
      if (typeof(str) != 'string')
        return str;

      var last_id_tag = str.lastIndexOf('#');
      if (last_id_tag > 0)
        str = str.substr(last_id_tag);
      var elements = str.split(" ");
      var ret = $(elements[0]);
      var i = 0;
      while (++i < elements.length)
        if (elements[i].length != 0)
          ret = ret.find(elements[i]);
      return ret;
    }
}
<commit_msg>Testing window.Defer<commit_after>requirejs.config({
    waitSeconds: 60
});

require([
  "libs/text", // part of require js
  "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js",
  "libs/ejs_production"
  ],
    function(until)
    {
      require([
      "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js",
      "libs/jquery.form"]);

      $.getJSON("api/phoxy", function(data)
      {
        phoxy.config = data;
        requirejs.config({baseUrl: phoxy.Config()['js_dir']});

        $('script[phoxy]').each(function()
        {
          phoxy.ApiRequest($(this).attr("phoxy"));
        });
      });
    }
  );

function PhoxyHashChangeCallback()
{
  if (phoxy.ChangeHash(location.hash))
    phoxy.ApiRequest(phoxy.hash);
}

var phoxy =
{
  loaded : false,
  hash : false,
  Load : function( )
    {
      this.loaded = true;
      var hash = location.hash.substring(1);
      phoxy.ApiRequest(hash);
      this.hash = hash;
      $(window).bind('hashchange', PhoxyHashChangeCallback);
    }
  ,
  Defer : function(callback, time)
  {
    if (time == undefined)
      time = 0;
    var func = $.proxy(
      function()
      {
        callback.call(this);
      },
      this);
    setTimeout(func, time);
  }
  ,
  WaitFor : function(callback_condition, callback, timeout, check_every)
    {
      var
        check_timeout = 60, // 1 minute for render to complete
        check_delay = 500; // check every 500ms

      if (timeout != undefined)
        check_timeout = timeout;
      if (check_every != undefined)
        check_delay = check_every;

      var func = function()
      {
        if (!callback_condition())
          return;
        callback();
      }
      if (callback_condition())
        return func();

      function WaitAndCallCountDown( i )
      {
        if (i <= 0)
          return func();

        phoxy.Defer(function()
        {
          if (callback_condition())
            i = 0;
          WaitAndCallCountDown(i - 1);
        }, check_delay);
      }

      WaitAndCallCountDown(check_timeout * 1000 / check_delay);
    }
  ,
  Appeared : function(jquery_selector, callback, timeout, call_delay)
    {
      function Div()
      {
        return $(phoxy.OptimiseSelector(jquery_selector));
      }
      function IsDivAppeared()
      {
        return Div()[0] != undefined;
      }

      phoxy.Defer(function()
      {
        phoxy.WaitFor(IsDivAppeared, function()
        {
          phoxy.Defer.call(Div(), callback, call_delay);
        }, timeout)
      });
    }
  ,
  Disappeared : function(jquery_selector, callback, timeout, call_delay)
    {
      function IsDivDisappeared()
      {
        return $(phoxy.OptimiseSelector(jquery_selector))[0] == undefined;
      }

      phoxy.Defer(function()
      {
        phoxy.WaitFor(IsDivDisappeared, function()
        {
          phoxy.Defer(callback, call_delay);
        }, timeout);
      });
    }
  ,
  GenerateUniqueID : function()
    {
      var ret = "";
      var dictonary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

      for (var i = 0; i < 10; i++)
        ret += dictonary.charAt(Math.floor(Math.random() * dictonary.length));

      return ret;
    }
  ,
  PrepareCanvas : function(tag)
    {
      if (tag == undefined)
        tag = '
';
      function GetElementCode( el )
      {
        return $(el).wrapAll('

').parent().html();
      }

      var id =  phoxy.GenerateUniqueID();
      var obj = $(tag).attr('id', id);
      var div = GetElementCode(obj);

      return { id: id, obj: obj, html: div };
    }
  ,
  DeferRender : function (ejs, data, rendered_callback, tag)
    {
      console.log("phoxy.DeferRender", arguments);
      if (tag == undefined)
        tag = '<defer_render>';
      var canvas = phoxy.PrepareCanvas(tag);
      var id = canvas.id;

      phoxy.Appeared('#' + id, function()
      {
        phoxy.Fancy(ejs, data, function(html)
        {
          $('#' + id).replaceWith(html);
          if (typeof(rendered_callback) != 'undefined')
            rendered_callback(ejs, data);
        });
      });

      return canvas.html;
    }
  ,
  Fancy : function(design, data, callback)
    {
      console.log("phoxy.Fancy", arguments);

      var func;
      var callback = arguments[2];
      if (typeof(callback) == 'undefined')
        callback = function (){};
      var design = arguments[0];

      if (typeof(data) == 'undefined')
      { // single param call
        if (typeof(design) == 'undefined')
          return callback(undefined, undefined, undefined);
        if (typeof(design) == 'object')
        {
          var obj = arguments[0];
          // Maybe its wrong. Maybe i should ignore other params
          var design = obj.design;
          var data = obj.data;
          if (typeof(data) == 'undefined')
            data = {};
          delete obj.design;
          delete obj.data;
          delete obj.result;
          delete obj.replace;

          phoxy.ApiAnswer(obj, function()
          {
            phoxy.Fancy(design, data, callback);
          });
        }
        else
        { /* Called as RPC
            PARAMS:
              [0] - string with RPC command
            NOTE:
              target commands ignored.
              result will be rendered in this div.
           */
          var rpc = arguments[0];
          phoxy.AJAX(rpc, function(data, callback)
          {
            phoxy.Fancy(data, undefined, callback);
          }, [callback]);
        }
        return;
      }

      var data = arguments[1];
      function DataLoadedCallback(data)
      {
        if (typeof(data) == 'undefined')
          data = {};
        phoxy.Fancy(design, data, callback);
      }

      if (typeof(data) == 'function')
      { /* Get data as function callback */
        data(DataLoadedCallback);
      }
      else if (typeof(data) == 'string')
      { /* Download data with RPC */
        phoxy.AJAX(data, function(json)
        {
          DataLoadedCallback(json.data);
        });
      }
      else
      { /* Data loaded */
        var html;
        if (design != undefined)
          html = phoxy.Render(phoxy.Config()['ejs_dir'] + "/" + design, undefined, data);
        callback(html, design, data);
      }
    }
  ,
  ChangeHash : function (hash)
    {
      var t;
      t = hash.split(location.origin)[1];
      if (t !== undefined)
        hash = t;
      var t = hash.split('#')[1];
      if (t !== undefined)
        hash = t;
      var ret = phoxy.hash != hash;
      phoxy.hash = hash;
      location.hash = hash;
      return ret;
    }
  ,
  Reset : function (url)
    {
      if (url == true)
        location.reload();
      var parts = url.split('#');
      if (parts[1] == undefined)
        phoxy.ChangeHash('');
      else
        phoxy.ChangeHash("#" + parts[1]);
      var host = parts[0];
      if (host.length)
        location = host;
      else
        location.reload(parts[0]);
    }
  ,
  Render : function (design, result, data)
    {
      if (data === undefined)
        data = {};

      console.log("phoxy.Render", arguments);
      var html;
      if (design.search(".ejs") == -1)
        design += ".ejs";
      if (!phoxy.ForwardDownload(design))
        html = new EJS({'url' : design}).render(data);
      else
        html = new EJS({'text' : phoxy.ForwardDownload(design, true)}).render(data);
      if (result != undefined && result != '')
        $("#" + result).replaceWith(html);
      return html;
    }
  ,
  ApiAnswer : function( answer, callback )
    {
      if (answer.hash !== undefined)
      {
        if (answer.hash === null)
          answer.hash = "";
        this.ChangeHash(answer.hash);
      }
      if (answer.error)
      {
        alert(answer.error);
        if (answer.reset !== undefined)
          phoxy.Reset(answer.reset);
        return;
      }
      if (answer.reset !== undefined)
        phoxy.Reset(answer.reset);

      function Before()
      {
        function AfterBefore(_answer)
        {
          if (_answer !== undefined)
            answer = _answer;
          phoxy.ScriptsLoaded(answer, callback);
        }
        if (answer.before !== undefined)
          window[answer.before](answer, AfterBefore);
        else
          AfterBefore();
      }

      if (answer.script)
        require(answer.script, Before);
      else
        Before();
    }
  ,
  ScriptsLoaded : function( answer, callback )
    {
      function ScriptsFiresUp()
      {
        if (answer.routeline !== undefined)
          window[answer.routeline](answer);
        if (callback)
          callback(answer.data);
        if (!phoxy.loaded)
          phoxy.Load();
      }
      if (answer.design === undefined)
        return ScriptsFiresUp();

      var canvas = phoxy.PrepareCanvas('<render>');
      var id = canvas.id;
      var render_id = id;

      var element = canvas.obj;

      var url = phoxy.Config()['ejs_dir'] + "/" + answer.design;
      phoxy.ForwardDownload(url + ".ejs", function()
      {
        if (answer.replace === undefined)
          if (answer.result === undefined)
            $('body').append(element);
          else
            $('#' + answer.result).html(element);
        else
          render_id = answer.replace;

        phoxy.Render(
          url,
          render_id,
          answer.data);

        phoxy.Disappeared('#' + id, ScriptsFiresUp);
      });
    }
  ,
  ForwardDownload : function( url, callback_or_true_for_return )
  {
    if (typeof(storage) === "undefined")
      storage = {};

    if (callback_or_true_for_return === true)
      return storage[url];

    function AddToLocalStorage(data)
    {
      storage[url] = data;
      if (typeof(callback_or_true_for_return) == 'function')
        callback_or_true_for_return(data);
    }

    if (storage[url] != undefined)
    {
      if (typeof(callback_or_true_for_return) == 'function')
        callback_or_true_for_return(storage[url]);
      return true;
    }

    $.get(url, AddToLocalStorage);
    return false;
  }
  ,
  AJAX : function( url, callback, params )
    {
      console.log("phoxy.AJAX", arguments);
      $(function()
      {
        $.getJSON(phoxy.Config()['api_dir'] + "/" + url, function(data)
          {
            if (params == undefined)
              params = [];
            params.unshift(data);
            callback.apply(this, params);
          });
      });
    }
  ,
  ApiRequest : function( url, callback )
    {
      if (callback == undefined)
        phoxy.AJAX(url, phoxy.ApiAnswer);
      else
        phoxy.AJAX(url, phoxy.ApiAnswer, [callback]);
    }
  ,
  MenuCall : function( url, callback )
    {
        $(function()
        {
          $.getJSON(phoxy.Config()['api_dir'] + "/" + url, function(data)
          {
            phoxy.ChangeHash(url);
            phoxy.ApiAnswer(data, callback);
          });
        });
    }
  ,
  Config : function()
    {
      return this.config;
    }
  ,
  OptimiseSelector : function( str )
    { // http://learn.jquery.com/performance/optimize-selectors/
      if (typeof(str) != 'string')
        return str;

      var last_id_tag = str.lastIndexOf('#');
      if (last_id_tag > 0)
        str = str.substr(last_id_tag);
      var elements = str.split(" ");
      var ret = $(elements[0]);
      var i = 0;
      while (++i < elements.length)
        if (elements[i].length != 0)
          ret = ret.find(elements[i]);
      return ret;
    }
}

function Defer()
{
  phoxy.Defer.Apply(this, arguments);
}
<|endoftext|>


<commit_before>
/**
 * Run a script.
 * A script is a list of shell commands.
 *
 * (c) 2015 Matthias Hannig
 */

// == Libraries
var Promise = require('promise');
var cp      = require('child_process');
var sym     = require('log-symbols');

// == Modules
var Config  = require('../config/yaml');

// == Helper
var execCommandList = function(list, cb) {

  if(list.length === 0) {
    // Run callback when we are done.
    if(typeof(cb) !== 'undefined'){ cb(); }
    return;
  }

  var ts  = new Date();
  var pre = sym.info + ' ' + ts + ': ';

  var cmd = list.shift();

  cp.exec(cmd, {
    env: process.env,
    cwd: process.cwd()
  },
  function(error, stdout, stderr) {
    if(error) {
      console.error("error while running script");
      return;
    }

    if(stdout) {
      console.log(pre + stdout.slice(0,-1));
    }
    if(stderr){
      console.log(pre + stderr.slice(0,-1));
    }

    execCommandList(list, cb);
  });

};

// == Exec script
var scriptExec = function(scriptName) {
  var configFile = process.cwd() + '/launchify.yml';
  var config     = new Config(configFile);

  var promise = new Promise(function(resolve, reject){
    // Check if script exists
    if( !config.scripts || !config.scripts[scriptName] ) {
      reject('script_not_found');
      return;
    }

    var script = config.scripts[scriptName];
    execCommandList(script, function() {
      resolve('success');
    });
  });

  return promise;
};

// == Export
module.exports = scriptExec;

<commit_msg>added variable replacements.<commit_after>
/**
 * Run a script.
 * A script is a list of shell commands.
 *
 * (c) 2015 Matthias Hannig
 */

// == Libraries
var Promise = require('promise');
var cp      = require('child_process');
var sym     = require('log-symbols');

// == Modules
var Config   = require('../config/yaml');
var Omniconf = require('../config/omniconf');

// == Helper
var execCommandList = function(list, cb) {
  var conf = new Omniconf(process.cwd());

  if(list.length === 0) {
    // Run callback when we are done.
    if(typeof(cb) !== 'undefined'){ cb(); }
    return;
  }

  var ts  = new Date();
  var pre = sym.info + ' ' + ts + ': ';

  var cmd = list.shift();

  // Replace config variables
  cmd = cmd.replace(/{{.*?}}/g, function(match) {
    console.log(match);
    var attr  = match.substr(2, match.length - 4);
    var value = conf.get(attr);
    return value;
  });

  cp.exec(cmd, {
    env: process.env,
    cwd: process.cwd()
  },
  function(error, stdout, stderr) {
    if(error) {
      console.error("error while running script");
      return;
    }

    if(stdout) {
      console.log(pre + stdout.slice(0,-1));
    }
    if(stderr){
      console.log(pre + stderr.slice(0,-1));
    }

    execCommandList(list, cb);
  });

};

// == Exec script
var scriptExec = function(scriptName) {
  var configFile = process.cwd() + '/launchify.yml';
  var config     = new Config(configFile);

  var promise = new Promise(function(resolve, reject){
    // Check if script exists
    if( !config.scripts || !config.scripts[scriptName] ) {
      reject('script_not_found');
      return;
    }

    var script = config.scripts[scriptName];
    execCommandList(script, function() {
      resolve('success');
    });
  });

  return promise;
};

// == Export
module.exports = scriptExec;

<|endoftext|>


<commit_before>/**
 * Piano
 * Desktop browser keyboard for touch screens
 *
 * @author hugohil <hugo@soixantecircuits.fr>
 * @license MIT
 * @version 1.0b
 */

var piano = (function (k) {
  'use strict'

  k = {}

  k.init = function (options) {
    if (document.querySelectorAll('#piano').length) {
      return false
    }

    options = options || {}

    k.container = document.createElement('div')
    k.container.id = 'piano'
    k.container.className = 'piano-container animated'

    k.triggerName = options.triggers || 'click'
    k.slideContent = options.slideContent || false
    k.slideContainer = options.slideContainer || 'body'
    k.detectInputs()
    document.body.appendChild(k.container)

    // Make sure to hide keyboard when clicking outside
    addMultipleListeners(['click', 'touchdown'], document, function (event) {
      if (event.target.dataset.piano !== '' && !k.container.contains(event.target)) {
        k.hideKeyboard()
      }
    })

    return k
  }

  k.detectInputs = function () {
    k.triggers = document.querySelectorAll('[data-piano]')
    for (var i = 0; i < k.triggers.length; i++) {
      createKeyboard(k, k.triggers[i])
    }
    return k
  }

  function createKeyboard (parent, target) {
    var _k = clone(parent)
    delete _k.triggers
    delete _k.layouts
    var datas = target.dataset
    var options = {}

    _k.shift = false

    if (datas.pianoPosition) {
      if (datas.pianoPosition.indexOf('absolute') > -1) {
        options.position = datas.pianoPosition.replace(/absolute,\s/gi, '').split(',')
      } else {
        options.position = (datas.pianoPosition) ? datas.pianoPosition.split(',') : []
      }
    } else {
      console.warn('It seems you have incorrect values in your data-piano-position attribute on element: ', target)
      options.position = []
    }
    options.layout = datas.pianoLayout
    options.limit = datas.pianoLimit
    options.animationIn = datas.pianoAnimationIn
    options.animationOut = datas.pianoAnimationOut
    options.scale = datas.pianoScale

    var eventID = datas.pianoEventId
    var elementEvent = null
    if (eventID) {
      elementEvent = document.createEvent('Event')
      elementEvent.initEvent(eventID, true, true)
    }

    _k.settings = {
      position: {
        x: options.position[0] || 'center',
        y: options.position[1] || 'bottom'
      },
      layout: options.layout || 'default',
      limit: options.limit || -1,
      submitEvent: elementEvent,
      animationIn: options.animationIn || 'fadeInUp',
      animationOut: options.animationOut || 'fadeOutDown',
      scale: options.scale || 1
    }

    addMultipleListeners(['click', 'touchdown'], target, function (event) {
      k.clearKeyboards()
      k.currentTarget = event.target
      displayKeyboard(_k)
    })
  }

  function displayKeyboard (instance) {
    var _k = k
    _k.currentKeyboard = instance

    var rowsContainer = document.createElement('div')
    rowsContainer.className = 'piano-rows'

    var layout = k.layouts[instance.settings.layout]

    var rows = []
    rows.push(document.createElement('ul'))

    for (var i in layout) {
      var li = document.createElement('li')
      if (layout[i] == 'break') {
        rowsContainer.appendChild(rows[rows.length - 1])
        rows.push(document.createElement('ul'))
      } else {
        var key = document.createElement('button')
        if (typeof (layout[i][0]) === 'object') {
          li.className = layout[i][0].name
          key.className = 'key ' + layout[i][0].name
          key.innerHTML = layout[i][0].value
          key.dataset.pianoKey = layout[i][0].name
        } else {
          key.className = 'key ' + layout[i]
          key.textContent = layout[i][0]
          key.dataset.pianoKey = layout[i][0]
        }
        addMultipleListeners(_k.triggerName, key, function (event) {
          debounce(keyPressed(event), 300, false)
        })
        li.appendChild(key)
      }
      rowsContainer.appendChild(rows[rows.length - 1])

      rows[rows.length - 1].appendChild(li)
    }

    if (isNaN(instance.settings.position.x) || isNaN(instance.settings.position.y)) {
      k.container.className += ' ' + instance.settings.position.x
      k.container.className += ' ' + instance.settings.position.y
    } else {
      k.container.style.left = instance.settings.position.x + 'px'
      k.container.style.top = instance.settings.position.y + 'px'
    }

    k.container.classList.remove(k.currentKeyboard.settings.animationOut)
    k.container.appendChild(rowsContainer)
    k.container.classList.add(k.currentKeyboard.settings.animationIn)

    var scale = _k.currentKeyboard.settings.scale
    if (scale > 1) {
      var x = _k.currentKeyboard.settings.position.x
      var y = _k.currentKeyboard.settings.position.y
      scaleKeyboard(rowsContainer, scale, x, y)
    }

    document.body.classList.add('piano-open')
    if (k.slideContent) {
      document.querySelector(k.slideContainer).style.top = '-' + (rowsContainer.getBoundingClientRect().height / 2) + 'px'
    }
  }

  function scaleKeyboard (container, scale, x, y) {
    container.style['-webkit-transform'] = 'scale(' + scale + ')'
    container.style['-moz-transform'] = 'scale(' + scale + ')'
    container.style['-ms-transform'] = 'scale(' + scale + ')'
    container.style['-o-transform'] = 'scale(' + scale + ')'
    container.style['transform'] = 'scale(' + scale + ')'

    container.style['-webkit-transform-origin'] = x + ' ' + y
    container.style['-moz-transform-origin'] = x + ' ' + y
    container.style['-ms-transform-origin'] = x + ' ' + y
    container.style['-o-transform-origin'] = x + ' ' + y
    container.style['transform-origin'] = x + ' ' + y
  }

  function keyPressed (event) {
    var target = event.target
    var value = target.textContent
    var input = k.currentTarget
    var cursor = null
    var end = null
    if (input.type !== 'email') {
      cursor = input.selectionStart
      end = input.selectionEnd
    }
    var diff = (end - cursor) || 1
    var offset = 1
    var limit = k.currentKeyboard.settings.limit
    var submitEvent = k.currentKeyboard.settings.submitEvent

    // There are still small bugs with selections.
    if (/del/i.test(target.className)) {
      var deleteOffset = (cursor) ? -1 : 0
      input.value = insertToString(input.value, (cursor + deleteOffset), diff, '')
      offset = -1
    } else if (/space/i.test(target.className)) {
      if (input.value.length <= limit || limit === -1) {
        input.value = insertToString(input.value, cursor, (diff - 1), ' ')
      }
    } else if (/shift/i.test(target.className)) {
      k.switchCase()
    } else if (/larr/i.test(target.className)) {
      offset = -1
    } else if (/rarr/i.test(target.className)) {
      offset = 1
    } else if (/hide/i.test(target.className)) {
      k.hideKeyboard()
    } else if (/submit/i.test(target.className)) {
      if (submitEvent) {
        input.dispatchEvent(submitEvent)
      } else {
        console.warn('You did not provide a data-piano-event-id attribute.')
      }
    } else {
      if (input.value.length <= limit || limit === -1) {
        input.value = insertToString(input.value, cursor, (diff - 1), value)
      }
    }

    if (input.type !== 'email') {
      input.selectionStart = cursor + offset
      input.selectionEnd = cursor + offset
    }

    if (document.createEvent) {
      var evt = document.createEvent('HTMLEvents')
      evt.initEvent('input', false, true)
      input.dispatchEvent(evt)
    } else {
      input.fireEvent('input')
    }

    input.focus()
  }

  k.switchCase = function () {
    var shift = k.currentKeyboard.shift = !k.currentKeyboard.shift
    var keys = document.querySelectorAll('.piano-rows > ul > li')
    var layout = k.layouts[k.currentKeyboard.settings.layout]

    for (var i = 0; i < keys.length; i++) {
      var target = keys[i].children[0]
      if (target) {
        var value = target.textContent
        if (layout[i].length > 1 && layout[i][0].length > 0) {
          target.textContent = (shift) ? layout[i][1] : layout[i][0]
        } else {
          target.textContent = (shift) ? value.toUpperCase() : value.toLowerCase()
        }
      }
    }
  }

  k.hideKeyboard = function () {
    if (k.container.firstChild) {
      k.container.classList.remove(k.currentKeyboard.settings.animationIn)
      k.container.classList.add(k.currentKeyboard.settings.animationOut)
      document.body.classList.remove('piano-open')
      document.querySelector(k.slideContainer).style.top = 0
    }
  }

  k.clearKeyboards = function () {
    if (k.container.firstChild) {
      k.container.firstChild.remove()
      k.container.style.top = k.container.style.left = ''
      k.container.className = 'piano-container animated'
      k.currentKeyboard = null
      document.querySelector(k.slideContainer).style.top = 0
    }
  }

  // Found on http://stackoverflow.com/a/21350614/2033455
  function insertToString (str, index, count, add) {
    return str.slice(0, index) + (add || '') + str.slice(index + count)
  }

  function addMultipleListeners (events, target, handler) {
    events = (events instanceof Array) ? events : [events]
    for (var i = 0; i < events.length; i++) {
      target.addEventListener(events[i], function (event) {
        handler(event)
      })
    }
  }

  function clone (src) {
    var dest = {}
    for (var key in src) {
      dest[key] = src[key]
    }
    return dest
  }

  // Helpers function for piano object
  function debounce (func, wait, immediate) {
    var timeout
    return function () {
      var context = this
      var args = arguments
      var later = function () {
        timeout = null
        if (!immediate) {
          func.apply(context, args)
        }
      }
      var callNow = immediate && !timeout
      clearTimeout(timeout)
      timeout = setTimeout(later, wait || 200)
      if (callNow) {
        func.apply(context, args)
      }
    }
  }

  return k
})(piano || {})
<commit_msg>delete useless file<commit_after><|endoftext|>


<commit_before>var sidebarShown = false;

var touchDown = false;
var touchDownX = 0;
var touchDownY = 0;

//Scrollhax only works well on Chrome Android
var scrollhax = false;

if(navigator.userAgent.indexOf("Chrome") !== -1)
	scrollhax = true;

function alwaysSidebar() {
	return window.innerWidth >= 650;
}

function showSidebar() {
	if(alwaysSidebar())
		return;

	if(sidebarShown)
		return;
	sidebarShown = true;

	if (scrollhax && $(document).height() > $(window).height()) {
		var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
		$('html').addClass('noscroll').css('top',-scrollTop);
	}
	$("#mobile_sidebar").scrollTop(0);
	$("#mobile_sidebar").addClass("shown");
	$("#mobile_overlay").addClass("shown");

	return false;
}

function hideSidebar() {
	if(!sidebarShown)
		return;

	sidebarShown = false;

	if(scrollhax)
	{
		var scrollTop = parseInt($('html').css('top'));
		$('html').removeClass('noscroll');
		$('html,body').scrollTop(-scrollTop);
	}

	$("#mobile_sidebar").removeClass("shown");
	$("#mobile_overlay").removeClass("shown");

	return false;
}

$(function() {

	$('#mobile_openHeader').bind('click', function() {
		if (sidebarShown === true) {
			hideSidebar();
		} else {
			showSidebar();
		}
	});
	$('#mobile_overlay').bind('click', hideSidebar);

	document.addEventListener('touchstart', function(event) {
		touchDown = true;
		touchDownX = event.touches[0].pageX;
		touchDownY = event.touches[0].pageY;
	}, false);
	document.addEventListener('touchmove', function(event) {
		if(alwaysSidebar()) return;
		var dx = event.changedTouches[0].pageX-touchDownX;
		var dy = event.changedTouches[0].pageY-touchDownY;
		if(touchDown && $(window).scrollLeft() == 0 && !sidebarShown && dx > 0 && Math.abs(dx) > Math.abs(dy))
			event.preventDefault();
		else
			touchDown = false;

		$("#lol").text(dx+" "+dy);
		if(dx > 60)
			showSidebar();
	}, false);

	document.addEventListener('scroll', function(event) {
		touchDown = false;
	}, false);

	$(window).on("resize", function() {
		if(alwaysSidebar())
			hideSidebar();
	});
	$("body").removeClass("preload");
});
<commit_msg>Fix mobile sidebar opening when scrolling on some browsers.<commit_after>var sidebarShown = false;

var touchDown = false;
var touchDownX = 0;
var touchDownY = 0;

//Scrollhax only works well on Chrome Android
var scrollhax = false;

if(navigator.userAgent.indexOf("Chrome") !== -1)
	scrollhax = true;

function alwaysSidebar() {
	return window.innerWidth >= 650;
}

function showSidebar() {
	if(alwaysSidebar())
		return;

	if(sidebarShown)
		return;
	sidebarShown = true;

	if (scrollhax && $(document).height() > $(window).height()) {
		var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
		$('html').addClass('noscroll').css('top',-scrollTop);
	}
	$("#mobile_sidebar").scrollTop(0);
	$("#mobile_sidebar").addClass("shown");
	$("#mobile_overlay").addClass("shown");

	return false;
}

function hideSidebar() {
	if(!sidebarShown)
		return;

	sidebarShown = false;

	if(scrollhax)
	{
		var scrollTop = parseInt($('html').css('top'));
		$('html').removeClass('noscroll');
		$('html,body').scrollTop(-scrollTop);
	}

	$("#mobile_sidebar").removeClass("shown");
	$("#mobile_overlay").removeClass("shown");

	return false;
}

$(function() {

	$('#mobile_openHeader').bind('click', function() {
		if (sidebarShown === true) {
			hideSidebar();
		} else {
			showSidebar();
		}
	});
	$('#mobile_overlay').bind('click', hideSidebar);

	document.addEventListener('touchstart', function(event) {
		touchDown = true;
		touchDownX = event.touches[0].pageX;
		touchDownY = event.touches[0].pageY;
	}, false);
	document.addEventListener('touchmove', function(event) {
		if(alwaysSidebar()) return;
		var dx = event.changedTouches[0].pageX-touchDownX;
		var dy = event.changedTouches[0].pageY-touchDownY;
		if(touchDown && $(window).scrollLeft() == 0 && !sidebarShown && dx > 0 && Math.abs(dx) > Math.abs(dy))
			event.preventDefault();
		else
			touchDown = false;

		if(touchDown && dx > 60)
			showSidebar();
	}, false);

	document.addEventListener('scroll', function(event) {
		touchDown = false;
	}, false);

	$(window).on("resize", function() {
		if(alwaysSidebar())
			hideSidebar();
	});
	$("body").removeClass("preload");
});
<|endoftext|>


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

  // ----------- MAPS LAYERS -----------
  // var mappos = L.Permalink.getMapLocation();
  // var map = L.map('map', {
  //   center: mappos.center,
  //   zoom: mappos.zoom
  // });

  var map = L.map('map', {
    center: [42.3469,13.39817],
    zoom: 14
  });

  var mapy_winter = L.tileLayer('https://mapserver.mapy.cz/winter-m/{z}-{x}-{y}', {
    maxZoom: 16,
    maxNativeZoom: 18,
    minNativeZoom: 3,
    minZoom: 10,
    attribution: '© Mapy'
  }).addTo(map);

  var baselayer = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 17,
    minNativeZoom: 5,
    minZoom: 10,
    attribution: '© OpenTopoMap'
  });

  var baselayer2 = L.tileLayer('https://4umaps.com/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 15,
    minNativeZoom: 2,
    minZoom: 10,
    attribution: '© 4UMaps'
  });

  var googleHybrid = L.tileLayer('https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',{
    maxZoom: 16,
    maxNativeZoom: 20,
    minNativeZoom: 3,
    minZoom: 10,
    subdomains:['mt0','mt1','mt2','mt3'],
    attribution: '© Google'
  });

  // var igm25k_min = L.tileLayer('https://www.meteoaquilano.it/abruzzo/igm25k_min_abr/{z}/{x}/{y}.png', {
  //   //transparent: true,
  //   maxZoom: 16,
  //   maxNativeZoom: 16,
  //   minNativeZoom: 12,
  //   minZoom: 10,
  //   tms: true,
  //   attribution: '© Geoportale Nazionale'
  // });
  //
  // var igm25k_reg = L.tileLayer('https://www.meteoaquilano.it/abruzzo/igm25k_reg_abr/{z}/{x}/{y}.png', {
  //   //transparent: true,
  //   maxZoom: 16,
  //   maxNativeZoom: 16,
  //   minNativeZoom: 10,
  //   minZoom: 10,
  //   tms: true,
  //   attribution: '© Geoportale Regione Abruzzo'
  // });

  // var igm25k_reg = L.tileLayer.wms('http://geocatalogo.regione.abruzzo.it/erdas-iws/ogc/wms/?', {
  //   layers: 'Mosaici_UTM-WGS84_IGM25k_WGS84.ecw',
  //   maxZoom: 16,
  //   minZoom: 10,
  //   attribution: '© Geoportale Regione Abruzzo'
  // }).addTo(map);

  var tcdlayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/tcd_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.3,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Copernicus'
  }).addTo(map);

  var hillshlayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/ingv_dem10m_hillshade_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.2,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Tinitaly'
  }).addTo(map);

  var slopelayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/ingv_dem10m_slope_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.4,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Tinitaly'
  }).addTo(map);

  var avalanches = L.featureGroup();
  // Load kml file
  fetch('https://edrap.github.io/leaflet/shapefiles/Mappa storica delle valanghe dal 1957 al 2013 offline.kml')
      .then(res => res.text())
      .then(kmltext => {
          // Create new kml overlay
          const parser = new DOMParser();
          const kml = parser.parseFromString(kmltext, 'text/xml');
          const track = new L.KML(kml);
          avalanches.addLayer(track);

          // Adjust map to show the kml
          //const bounds = track.getBounds();
          //map.fitBounds(bounds);
      });
  avalanches.getAttribution = function() { return '© Opendata Regione Abruzzo'; };
  avalanches.addTo(map);

  var pistelayer = L.tileLayer('https://www.opensnowmap.org/tiles-pistes/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 18,
    minNativeZoom: 3,
    minZoom: 10,
    attribution: '© OpenSnowMap'
  }).addTo(map);

  var userFeatures = L.featureGroup().addTo(map);
  var gpsFeatures = L.featureGroup().addTo(map);

  // --------- HASHTAG ---------
  //var allMapLayers = {'mpw':mapy_winter, '4um':baselayer2, 'otm':baselayer, 'igm1':igm25k_min, 'igm2':igm25k_reg, 'gh':googleHybrid, 'tc':tcdlayer, 'hs':hillshlayer, 'sc':slopelayer, 'sp':pistelayer, 'uf':userFeatures};
  var allMapLayers = {'lf':gpsFeatures, 'mpw':mapy_winter, '4um':baselayer2, 'otm':baselayer, 'gh':googleHybrid, 'tc':tcdlayer, 'hs':hillshlayer, 'sc':slopelayer, 'av':avalanches, 'sp':pistelayer, 'uf':userFeatures};
  L.hash(map, allMapLayers);
  // L.Permalink.setup(map);

  //----------- INFO -----------
  L.easyButton({
    states: [{
      icon: '',
      title: 'Go to description page',
      onClick: function(){
        //var export = document.createElement('export');
        // Extract GeoJson from featureGroup
        window.open('https://edrap.github.io/abruzzomap', '_blank');
      }
    }]
  }).addTo(map);

  //// ----------- PRINT MAP -----------
  //L.control.browserPrint().addTo(map);

  // ----------- LOAD FEATURES -----------
  var load = L.Control.fileLayerLoad({
    // Allows you to use a customized version of L.geoJson.
    // For example if you are using the Proj4Leaflet leaflet plugin,
    // you can pass L.Proj.geoJson and load the files into the
    // L.Proj.GeoJson instead of the L.geoJson.
    layer: L.geoJson,
    // See http://leafletjs.com/reference.html#geojson-options
    //layerOptions: {style: {color:'red'}},
    layerOptions: {style: {color:"red",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2}},
    // Add to map after loading (default: true) ?
    addToMap: true,
    // File size limit in kb (default: 1024) ?
    fileSizeLimit: 1024,
    // Restrict accepted file formats (default: .geojson, .kml, and .gpx) ?
    formats: [
      '.geojson',
      '.gpx',
      '.kml'
    ]
  }).addTo(map);
  load.loader.on('data:loaded', function (e) {
    // Add to map layer switcher
    userFeatures.addLayer(e.layer);
  });

  // ----------- DRAW FEATURES -----------
  var drawControl = new L.Control.Draw({
    edit: {
      featureGroup: userFeatures
    }
  }).addTo(map);
  map.on('draw:created', function(e) {
    // Each time a feaute is created, it's added to the over arching feature group
    userFeatures.addLayer(e.layer);
  });

  // ----------- DOWNLOAD FEATURES -----------
  L.easyButton({
    states: [{
      icon: '',
      title: 'Export features to GPX',
      onClick: function(e) {
        // Extract GeoJson from featureGroup
        var data = userFeatures.toGeoJSON();
        // var kml = tokml(data);
        var gpx = togpx(data);
        // Stringify GPX, KML, GeoJson
        var convertedData = 'application/gpx+xml;charset=utf-8,' + encodeURIComponent(gpx);
        // var convertedData = 'application/xml;charset=utf-8,' + encodeURIComponent(kml);
        // var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
        // Create export
        var exp_feat = document.createElement('a');
        exp_feat.setAttribute('href', 'data:' + convertedData);
        // exp_feat.setAttribute('download', 'data.geojson');
        exp_feat.setAttribute('download', 'data.gpx');
        exp_feat.style.display = 'none';
        document.body.appendChild(exp_feat);
        exp_feat.click();
        document.body.removeChild(exp_feat);
      }
    }]
  }).addTo(map);

  // ----------- FULLSCREEN -----------
  L.control.fullscreen({position: 'topright'}).addTo(map);

  //----------- GET GPS LOCATION -----------
  L.control.locate({
    keepCurrentZoomLevel: 'false',
    position: 'topright',
    layer: gpsFeatures,
    setView: 'always'
  }).addTo(map);

  // ----------- SEARCH BOX -----------
  var geocoder = new L.Control.geocoder({position: "topright", collapsed: true, showResultIcons: false});
  map.addControl(geocoder);
  geocoder.markGeocode = function(result) {
    map.fitBounds(result.bbox);
  };

  // ----------- LAYERS ----------
  // var baseMaps = {'Mapy Winter':mapy_winter, '4UMaps':baselayer2, 'OpenTopoMap':baselayer, 'Igm25k Min':igm25k_min, 'Igm25k Reg':igm25k_reg, 'Google Hybrid':googleHybrid};
  var baseMaps = {'Mapy Winter':mapy_winter, '4UMaps':baselayer2, 'OpenTopoMap':baselayer, 'Google Hybrid':googleHybrid};
  var overlayMaps = {'Tree cover':tcdlayer, 'Hillshade':hillshlayer, 'Slope class':slopelayer, 'Avalanches':avalanches, 'Ski Piste':pistelayer, 'User features':userFeatures};
  L.control.layers(baseMaps, overlayMaps, {position: 'topright'}).addTo(map);

  // ----------- SCALE BAR -----------
  L.control.scale({imperial: false, position: 'bottomright'}).addTo(map);

  // ----------- LEGEND -----------
  function getColor(d) {
    return d > 45   ? '#b546fc' :
    d > 40   ? '#fb322f' :
    d > 35   ? '#fdac2b' :
    d > 30   ? '#efe72e' :
    '#FFEDA0';
  }
  function getPercent(d) {
    return d > 80   ? '#246627' :
    d > 60   ? '#3a8240' :
    d > 40   ? '#55a05a' :
    d > 20   ? '#78c376' :
    d > 1    ? '#a3ec9a' :
    '#FFEDA0';
  }
  var legend = L.control({position: 'bottomright'});
  legend.onAdd = function (map) {
    var div = L.DomUtil.create('div', 'info legend'),
    grades = [30, 35, 40, 45];
    labels = [' Slope class '];
    // loop through our density intervals and generate a label with a colored square for each interval
    div.innerHTML = labels + '
';
    for (var i = 0; i < grades.length; i++) {
      div.innerHTML +=
      ' ' +
      grades[i] + '°' + (grades[i + 1] ? '–' + grades[i + 1] + '°' + '
' : '+');
    }
    // percent = [1, 20, 40, 60, 80];
    // labels = [' Tree density '];
    //   // loop through our density intervals and generate a label with a colored square for each interval
    //   div.innerHTML += '
' + '
' + labels + '
';
    //   for (var i = 0; i < percent.length; i++) {
    //     div.innerHTML +=
    //     ' ' +
    //     percent[i] + '%' + (percent[i + 1] ? '–' + percent[i + 1] + '%' + '
' : '+');
    //   }
    return div;
  };
  legend.addTo(map);

})
<commit_msg>Update abruzzomap.js<commit_after>$(document).ready(function () {

  // ----------- MAPS LAYERS -----------
  // var mappos = L.Permalink.getMapLocation();
  // var map = L.map('map', {
  //   center: mappos.center,
  //   zoom: mappos.zoom
  // });

  var map = L.map('map', {
    center: [42.3469,13.39817],
    zoom: 14
  });

  var mapy_winter = L.tileLayer('https://mapserver.mapy.cz/winter-m/{z}-{x}-{y}', {
    maxZoom: 16,
    maxNativeZoom: 18,
    minNativeZoom: 3,
    minZoom: 10,
    attribution: '© Mapy'
  }).addTo(map);

  var baselayer = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 17,
    minNativeZoom: 5,
    minZoom: 10,
    attribution: '© OpenTopoMap'
  });

  var baselayer2 = L.tileLayer('https://4umaps.com/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 15,
    minNativeZoom: 2,
    minZoom: 10,
    attribution: '© 4UMaps'
  });

  var googleHybrid = L.tileLayer('https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',{
    maxZoom: 16,
    maxNativeZoom: 20,
    minNativeZoom: 3,
    minZoom: 10,
    subdomains:['mt0','mt1','mt2','mt3'],
    attribution: '© Google'
  });

  // var igm25k_min = L.tileLayer('https://www.meteoaquilano.it/abruzzo/igm25k_min_abr/{z}/{x}/{y}.png', {
  //   //transparent: true,
  //   maxZoom: 16,
  //   maxNativeZoom: 16,
  //   minNativeZoom: 12,
  //   minZoom: 10,
  //   tms: true,
  //   attribution: '© Geoportale Nazionale'
  // });
  //
  // var igm25k_reg = L.tileLayer('https://www.meteoaquilano.it/abruzzo/igm25k_reg_abr/{z}/{x}/{y}.png', {
  //   //transparent: true,
  //   maxZoom: 16,
  //   maxNativeZoom: 16,
  //   minNativeZoom: 10,
  //   minZoom: 10,
  //   tms: true,
  //   attribution: '© Geoportale Regione Abruzzo'
  // });

  // var igm25k_reg = L.tileLayer.wms('http://geocatalogo.regione.abruzzo.it/erdas-iws/ogc/wms/?', {
  //   layers: 'Mosaici_UTM-WGS84_IGM25k_WGS84.ecw',
  //   maxZoom: 16,
  //   minZoom: 10,
  //   attribution: '© Geoportale Regione Abruzzo'
  // }).addTo(map);

  var tcdlayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/tcd_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.3,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Copernicus'
  }).addTo(map);

  var hillshlayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/ingv_dem10m_hillshade_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.2,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Tinitaly'
  }).addTo(map);

  var slopelayer = L.tileLayer('https://www.meteoaquilano.it/abruzzo/ingv_dem10m_slope_abr/{z}/{x}/{y}.png', {
    //transparent: true,
    opacity: 0.4,
    maxZoom: 16,
    maxNativeZoom: 16,
    minNativeZoom: 10,
    minZoom: 10,
    tms: true,
    attribution: '© Tinitaly'
  }).addTo(map);

  var avalanches = L.featureGroup();
  // Load kml file
  fetch('https://edrap.github.io/leaflet/shapefiles/Mappa storica delle valanghe dal 1957 al 2013 offline.kml')
      .then(res => res.text())
      .then(kmltext => {
          // Create new kml overlay
          const parser = new DOMParser();
          const kml = parser.parseFromString(kmltext, 'text/xml');
          const track = new L.KML(kml);
          avalanches.addLayer(track);

          // Adjust map to show the kml
          //const bounds = track.getBounds();
          //map.fitBounds(bounds);
      });
  avalanches.getAttribution = function() { return '© Opendata Regione Abruzzo'; };
  avalanches.addTo(map);

  var pistelayer = L.tileLayer('https://www.opensnowmap.org/tiles-pistes/{z}/{x}/{y}.png', {
    maxZoom: 16,
    maxNativeZoom: 18,
    minNativeZoom: 3,
    minZoom: 10,
    attribution: '© OpenSnowMap'
  }).addTo(map);

  var userFeatures = L.featureGroup().addTo(map);
  var gpsFeatures = L.featureGroup().addTo(map);

  // --------- HASHTAG ---------
  //var allMapLayers = {'mpw':mapy_winter, '4um':baselayer2, 'otm':baselayer, 'igm1':igm25k_min, 'igm2':igm25k_reg, 'gh':googleHybrid, 'tc':tcdlayer, 'hs':hillshlayer, 'sc':slopelayer, 'sp':pistelayer, 'uf':userFeatures};
  var allMapLayers = {'lf':gpsFeatures, 'mpw':mapy_winter, '4um':baselayer2, 'otm':baselayer, 'gh':googleHybrid, 'tc':tcdlayer, 'hs':hillshlayer, 'sc':slopelayer, 'av':avalanches, 'sp':pistelayer, 'uf':userFeatures};
  L.hash(map, allMapLayers);
  // L.Permalink.setup(map);

  //----------- INFO -----------
  L.easyButton({
    states: [{
      icon: '',
      title: 'Go to description page',
      onClick: function(){
        //var export = document.createElement('export');
        // Extract GeoJson from featureGroup
        window.open('https://edrap.github.io/abruzzomap', '_blank');
      }
    }]
  }).addTo(map);

  //// ----------- PRINT MAP -----------
  //L.control.browserPrint().addTo(map);

  // ----------- LOAD FEATURES -----------
  L.Control.FileLayerLoad.LABEL = '';
  var load = L.Control.fileLayerLoad({
    // Allows you to use a customized version of L.geoJson.
    // For example if you are using the Proj4Leaflet leaflet plugin,
    // you can pass L.Proj.geoJson and load the files into the
    // L.Proj.GeoJson instead of the L.geoJson.
    layer: L.geoJson,
    // See http://leafletjs.com/reference.html#geojson-options
    layerOptions: {style: {color:'red'}},
    //layerOptions: {style: {color:"red",weight:4,opacity:.5,fill:!0,fillColor:null,fillOpacity:.2}},
    // Add to map after loading (default: true) ?
    addToMap: true,
    // File size limit in kb (default: 1024) ?
    fileSizeLimit: 1024,
    // Restrict accepted file formats (default: .geojson, .kml, and .gpx) ?
    formats: [
      '.geojson',
      '.gpx',
      '.kml'
    ]
  }).addTo(map);
  load.loader.on('data:loaded', function (e) {
    // Add to map layer switcher
    userFeatures.addLayer(e.layer);
  });

  // ----------- DRAW FEATURES -----------
  var drawControl = new L.Control.Draw({
    draw: {
        polygon: false,
        circle: false,
        rectangle: false
    },
    edit: {
      featureGroup: userFeatures
    }
  }).addTo(map);
  map.on('draw:created', function(e) {
    // Each time a feaute is created, it's added to the over arching feature group
    userFeatures.addLayer(e.layer);
  });

  // ----------- DOWNLOAD FEATURES -----------
  L.easyButton({
    states: [{
      icon: '',
      title: 'Export features to GPX',
      onClick: function(e) {
        // Extract GeoJson from featureGroup
        var data = userFeatures.toGeoJSON();
        // var kml = tokml(data);
        var gpx = togpx(data);
        // Stringify GPX, KML, GeoJson
        var convertedData = 'application/gpx+xml;charset=utf-8,' + encodeURIComponent(gpx);
        // var convertedData = 'application/xml;charset=utf-8,' + encodeURIComponent(kml);
        // var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
        // Create export
        var exp_feat = document.createElement('a');
        exp_feat.setAttribute('href', 'data:' + convertedData);
        // exp_feat.setAttribute('download', 'data.geojson');
        exp_feat.setAttribute('download', 'data.gpx');
        exp_feat.style.display = 'none';
        document.body.appendChild(exp_feat);
        exp_feat.click();
        document.body.removeChild(exp_feat);
      }
    }]
  }).addTo(map);

  // ----------- FULLSCREEN -----------
  L.control.fullscreen({position: 'topright'}).addTo(map);

  //----------- GET GPS LOCATION -----------
  L.control.locate({
    keepCurrentZoomLevel: 'false',
    position: 'topright',
    layer: gpsFeatures,
    setView: 'always'
  }).addTo(map);

  // ----------- SEARCH BOX -----------
  var geocoder = new L.Control.geocoder({position: "topright", collapsed: true, showResultIcons: false});
  map.addControl(geocoder);
  geocoder.markGeocode = function(result) {
    map.fitBounds(result.bbox);
  };

  // ----------- LAYERS ----------
  // var baseMaps = {'Mapy Winter':mapy_winter, '4UMaps':baselayer2, 'OpenTopoMap':baselayer, 'Igm25k Min':igm25k_min, 'Igm25k Reg':igm25k_reg, 'Google Hybrid':googleHybrid};
  var baseMaps = {'Mapy Winter':mapy_winter, '4UMaps':baselayer2, 'OpenTopoMap':baselayer, 'Google Hybrid':googleHybrid};
  var overlayMaps = {'Tree cover':tcdlayer, 'Hillshade':hillshlayer, 'Slope class':slopelayer, 'Avalanches':avalanches, 'Ski Piste':pistelayer, 'User features':userFeatures};
  L.control.layers(baseMaps, overlayMaps, {position: 'topright'}).addTo(map);

  // ----------- SCALE BAR -----------
  L.control.scale({imperial: false, position: 'bottomright'}).addTo(map);

  // ----------- LEGEND -----------
  function getColor(d) {
    return d > 45   ? '#b546fc' :
    d > 40   ? '#fb322f' :
    d > 35   ? '#fdac2b' :
    d > 30   ? '#efe72e' :
    '#FFEDA0';
  }
  function getPercent(d) {
    return d > 80   ? '#246627' :
    d > 60   ? '#3a8240' :
    d > 40   ? '#55a05a' :
    d > 20   ? '#78c376' :
    d > 1    ? '#a3ec9a' :
    '#FFEDA0';
  }
  var legend = L.control({position: 'bottomright'});
  legend.onAdd = function (map) {
    var div = L.DomUtil.create('div', 'info legend'),
    grades = [30, 35, 40, 45];
    labels = [' Slope class '];
    // loop through our density intervals and generate a label with a colored square for each interval
    div.innerHTML = labels + '
';
    for (var i = 0; i < grades.length; i++) {
      div.innerHTML +=
      ' ' +
      grades[i] + '°' + (grades[i + 1] ? '–' + grades[i + 1] + '°' + '
' : '+');
    }
    // percent = [1, 20, 40, 60, 80];
    // labels = [' Tree density '];
    //   // loop through our density intervals and generate a label with a colored square for each interval
    //   div.innerHTML += '
' + '
' + labels + '
';
    //   for (var i = 0; i < percent.length; i++) {
    //     div.innerHTML +=
    //     ' ' +
    //     percent[i] + '%' + (percent[i + 1] ? '–' + percent[i + 1] + '%' + '
' : '+');
    //   }
    return div;
  };
  legend.addTo(map);

})
<|endoftext|>


<commit_before>!function(){function e(e){return"object"==typeof e&&e}function t(e){return"number"==typeof e&&!isNaN(e)&&Math.abs(e)<1/0}function n(t,n){e(t)||(t={});for(var a in n)t.hasOwnProperty(a)||(t[a]=n[a]);return t}function a(e,t){t=n(t,{appendTo:null,context:document,html:"",insertAfter:null,insertBefore:null,replace:null});var a,r=function(e){var t={attribs:{},classes:[]};return e.match(/(\[[^\]]+\]|#[^#.\[]+|\.[^#.\[]+|\w+)/g).forEach(function(e){"["==e[0]?(e=e.match(/^\[([^=\]]+)=?([^\]]+)?\]$/))&&(t.attribs[e[1]]=e[2]||""):"."==e[0]?t.classes.push(e.substr(1)):"#"==e[0]?t.attribs.id=e.substr(1):t.tag=e}),t}(e),o=t.context.createElement(r.tag);(this.element=o).innerHTML=t.html,this.parent=null,r.classes.forEach(function(e){o.classList.add(e)});for(a in r.attribs)r.attribs.hasOwnProperty(a)&&o.setAttribute(a,r.attribs[a]);t.replace?t.replace.parentNode.replaceChild(o,t.replace):t.appendTo?(this.parent=t.appendTo).element.appendChild(o):t.insertAfter?t.insertAfter.parentNode.insertBefore(o,t.insertAfter.nextSibling):t.insertBefore&&t.insertBefore.parentNode.insertBefore(o,t.insertBefore)}function r(e){return{compare:function(t){var n,a=0,r=["getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds"];for(n in r){if(e[r[n]]()!=t[r[n]]())break;a=++n}return a},get days(){return new Date(e.getFullYear(),e.getMonth()+1,0).getDate()},get firstDay(){return new Date(e.getFullYear(),e.getMonth(),1).getDay()},get week(){var t=new Date(e);return t.setHours(0,0,0),t.setDate(t.getDate()+4-(t.getDay()||7)),Math.ceil(((t-new Date(t.getFullYear(),0,1))/864e5+1)/7)}}}function o(e,t){return new a(e,t)}function i(e,t,n){var a=e.getDate(),o=e.getMonth(),i=e.getFullYear(),l=e.getHours(),c=e.getMinutes(),s=e.getSeconds(),h=r(e).week,d=e.getDay(),u=12>l?"㏂":"㏘";return t.replace(/{ww}/gi,("0"+h).slice(-2)).replace(/{w}/gi,h).replace(/{DDDD}/g,n.dayOfWeek[d]).replace(/{DDD}/g,n.dayOfWeekShort[d]).replace(/{DD}/g,("0"+a).slice(-2)).replace(/{D}/g,a).replace(/{MMMM}/g,n.monthName[o]).replace(/{MMM}/g,n.monthNameShort[o]).replace(/{MM}/g,("0"+(o+1)).slice(-2)).replace(/{M}/g,o+1).replace(/{YYYY}/g,i).replace(/{YY}/g,i.toString().slice(-2)).replace(/{HH}/g,("0"+l).slice(-2)).replace(/{H}/g,l).replace(/{hh}/g,("0"+l%12).slice(-2)).replace(/{h}/g,l%12).replace(/{mm}/g,("0"+c).slice(-2)).replace(/{m}/g,c).replace(/{ss}/g,("0"+s).slice(-2)).replace(/{s}/g,s).replace(/{ap}/g,u)}function l(e,t){var n,a,o=r(new Date(e,t)).firstDay||7,i=new Date(e,t,1-(o-1||7)),l=[];for(n=0;6>n;++n)for(l.push([]),a=0;7>a;++a)l[n].push(new Date(i)),i.setDate(i.getDate()+1);return l}function c(e){var t,n,a=[];for(t=0;3>t;++t)for(a.push([]),n=0;4>n;++n)a[t].push(new Date(e,4*t+n));return a}function s(a,h){function d(e,n,a){for(var o,i=u.min,l=u.max;a>(o=r(new Date(e,n,a)).days);)++n,a-=a-o;for(;n>12;)++e,n-=12;if(t(e)){if(t(i.year)&&e<i.year||t(l.year)&&e>l.year)return!1;if(t(n)){if(t(i.month)&&n<i.month&&e<=i.year||t(l.month)&&n>l.month&&e>=l.year)return!1;if(t(a)&&(t(i.day)&&a<i.day&&n<=i.month&&e<=i.year||t(l.day)&&a>l.day&&n>=l.month&&e>=l.year))return!1}}return!0}h=n(h,{className:"chronopic",date:null,format:null,locale:"en_GB",max:{year:9999},min:{year:0},onChange:null}),this.instances=[],this.i18n=s.i18n.en_GB,this.max=e(h.max)?h.max:{},this.min=e(h.min)?h.min:{};var u=this,f=new Date;e(h.date)&&(f=(f=h.date)instanceof Date?new Date(f):new Date(f.year,f.month-1,f.day)),("string"==typeof a?Array.prototype.slice.call(document.querySelectorAll(a)):[a]).forEach(function(n){if(n instanceof HTMLElement){var a=n.nextSibling;"DIV"==a.tagName&&a.classList.contains(h.className)||(a=null);var s,u=h.className,m=o("div."+u,{insertAfter:n,replace:a}),p=this,y={};["day","month"].forEach(function(e){m.add(y[e]=o("table.hidden."+e)),y[e].head=o("thead",{appendTo:y[e]}),y[e].body=o("tbody",{appendTo:y[e]})}),p.instances.push(s={date:new Date(f),container:m,element:n,selected:{},tables:y,visible:!1,get day(){return this.date.getDate()},set day(e){d(this.date.getFullYear(),this.date.getMonth()+1,e)&&(this.date.setDate(e),this.selected.day=new Date(this.date),this.element.value=h.format?i(this.date,h.format,p.i18n):this.date.toDateString(),this.hide(),"function"==typeof h.onChange&&h.onChange(n,this.date))},hide:function(){for(var e in y)y[e].classes.add("hidden");this.visible=!1,this.selected.month=null,this.selected.day&&(this.date=new Date(this.selected.day),this.selected.month=new Date(this.date))},get month(){return this.date.getMonth()},set month(e){d(this.date.getFullYear(),e+1)&&(this.date.setDate(1),this.date.setMonth(e),this.selected.month=new Date(this.date),this.show("day"))},rebuild:function(e){var n,a,s=this,h=s.selected,u=new Date,f=1;if(!e||"day"==e){for(s.tables.day.head.add([o("tr.title").add([o("th.prev[title="+p.locale.prevMonth+"]",{html:"<"}).on("click",function(e){s.month--,e.stopPropagation()}),o("th[colspan=6][title="+p.locale.selectMonth+"]",{html:i(s.date,p.locale.formatMonth,p.locale)}).on("click",function(){s.show("month")}),o("th.next[title="+p.locale.nextMonth+"]",{html:">"}).on("click",function(e){s.month++,e.stopPropagation()})]),n=o("tr.labels").add(o("th.week",{html:p.locale.week}))],!0),a=0;7>a;++a)n.add(o("th.day[title="+p.locale.dayOfWeek[f%7]+"]",{html:p.locale.dayOfWeekShort[f++%7]}));s.tables.day.body.clear(),l(s.year,s.month).forEach(function(e){var t=o("tr",{appendTo:s.tables.day.body});t.add(o("td.week",{html:r(e[0]).week})),e.forEach(function(e){var n,a=".day",l=e.getMonth()-s.month,c=!d(e.getFullYear(),e.getMonth()+1,e.getDate());(-1==l||11==l)&&(a+=".prev"),(1==l||-11==l)&&(a+=".next"),h.day&&r(h.day).compare(e)>=3&&(a+=".selected"),c&&(a+=".disabled"),r(e).compare(u)>=3&&(a+=".now"),t.add(n=o("td[title="+i(e,p.locale.formatDay,p.locale)+"]"+a,{html:e.getDate()})),!c&&n.on("click",function(){s.month=e.getMonth(),s.day=e.getDate()})})})}return e&&"month"!=e||(s.tables.month.head.add([o("tr.title").add([o("th.prev[title="+p.locale.prevYear+"]",{html:"<"}).on("click",function(e){s.year--,e.stopPropagation()}),o("th.year[colspan=6][title="+p.locale.year+"]").add(o("input[type=number][step=1][min="+(p.min.year||0)+"][max="+(p.max.year||9999)+"][value="+s.year+"]").on("change",function(e,n){console.log(e.target.value),t(n=Number(e.target.value))&&(s.year=n)})),o("th.next[title="+p.locale.nextYear+"]",{html:">"}).on("click",function(e){s.year++,e.stopPropagation()})])],!0),s.tables.month.body.clear(),c(s.year).forEach(function(e){var t=o("tr",{appendTo:s.tables.month.body});e.forEach(function(e){var n,a=".month",i=e.getMonth(),l=!d(e.getFullYear(),i+1);h.month&&r(h.month).compare(e)>=2&&(a+=".selected"),l&&(a+=".disabled"),r(e).compare(u)>=2&&(a+=".now"),t.add(n=o("td[colspan=2][title="+p.locale.monthName[i]+"]"+a,{html:p.locale.monthNameShort[i]})),!l&&n.on("click",function(){s.month=i})})})),this},show:function(e){e||(e="day"),this.rebuild(e),this.visible=!0;for(var t in y)y.hasOwnProperty(t)&&y[t].classes[t==e?"remove":"add"]("hidden");var n=this.container.element,a=this.element;n.style.top=a.offsetTop+a.offsetHeight+"px",n.style.left=a.offsetLeft+"px",n.offsetWidth<a.offsetWidth&&(n.style.width=a.offsetWidth+"px")},get year(){return this.date.getFullYear()},set year(e){d(e)&&(this.date.setFullYear(e),this.show("month"))}}),e(h.date)&&(s.day=s.date.getDate())||(n.value=""),n.addEventListener("click",function(e){s[s.visible?"hide":"show"]()}),document.addEventListener("click",function(e,t){for(;t=t?t.parentNode:e.target;)if(t==n||t==m.element)return;s.hide()})}},this),this.locale=h.locale}return a.prototype={add:function(e,t){return t===!0&&this.clear(),(e instanceof Array?e:[e]).forEach(function(e){this.element.appendChild(e.element),e.parent=this},this),this},get classes(){return this.element.classList},clear:function(){for(var e,t=this.element;e=t.firstChild;)t.removeChild(e);return this},on:function(e,t){return this.element.addEventListener(e,t),this}},s.prototype={get locale(){return this.i18n},set locale(e){s.i18n[e]&&s.i18n[e]!==this.i18n&&(this.i18n=s.i18n[e],this.instances.forEach(function(e){e.selected.day&&(e.day=e.date.getDate()),e.rebuild()}))}},s.i18n={en_GB:{dayOfWeek:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayOfWeekShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],disabled:"Disabled",formatDay:"{DDDD} {D} {MMMM} {YYYY}",formatMonth:"{MMMM} {YYYY}",month:"Month",monthName:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNameShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],nextMonth:"Next month",nextYear:"Next year",prevMonth:"Previous month",prevYear:"Previous year",selectMonth:"Select month",week:"Week",year:"Year"}},"undefined"!=typeof window&&(window.Chronopic=s),"object"==typeof module&&module.exports&&(module.exports=s),s}();<commit_msg>Rebuilt with latest changes<commit_after>!function(){function e(e){return"object"==typeof e&&e}function t(e){return"number"==typeof e&&!isNaN(e)&&Math.abs(e)<1/0}function n(t,n){e(t)||(t={});for(var a in n)t.hasOwnProperty(a)||(t[a]=n[a]);return t}function a(e,t){t=n(t,{appendTo:null,context:document,html:"",insertAfter:null,insertBefore:null,replace:null});var a,o,r=e instanceof HTMLElement?e:null;if("string"==typeof e){o=function(e,t){return e.match(/(\[[^\]]+\]|#[^#.\[]+|\.[^#.\[]+|\w+)/g).forEach(function(e){"["==e[0]?(e=e.match(/^\[([^=\]]+)=?([^\]]+)?\]$/))&&(t.attribs[e[1]]=e[2]||""):"."==e[0]?t.classes.push(e.substr(1)):"#"==e[0]?t.attribs.id=e.substr(1):t.tag=e}),t}(e,{attribs:{},classes:[]}),r=t.context.createElement(o.tag),o.classes.forEach(function(e){r.classList.add(e)});for(a in o.attribs)o.attribs.hasOwnProperty(a)&&r.setAttribute(a,o.attribs[a])}(this.element=r).innerHTML=t.html,this.parent=null,this.events={},t.replace?t.replace.parentNode.replaceChild(r,t.replace):t.appendTo?(this.parent=t.appendTo).element.appendChild(r):t.insertAfter?t.insertAfter.parentNode.insertBefore(r,t.insertAfter.nextSibling):t.insertBefore&&t.insertBefore.parentNode.insertBefore(r,t.insertBefore)}function o(e){return{compare:function(t){var n,a=0,o=["getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds"];for(n in o){if(e[o[n]]()!=t[o[n]]())break;a=++n}return a},get days(){return new Date(e.getFullYear(),e.getMonth()+1,0).getDate()},get firstDay(){return new Date(e.getFullYear(),e.getMonth(),1).getDay()},get week(){var t=new Date(e);return t.setHours(0,0,0),t.setDate(t.getDate()+4-(t.getDay()||7)),Math.ceil(((t-new Date(t.getFullYear(),0,1))/864e5+1)/7)}}}function r(e,t){return new a(e,t)}function i(e,t,n){var a=e.getDate(),r=e.getMonth(),i=e.getFullYear(),l=e.getHours(),c=e.getMinutes(),s=e.getSeconds(),h=o(e).week,d=e.getDay(),u=12>l?"㏂":"㏘";return t.replace(/{ww}/gi,("0"+h).slice(-2)).replace(/{w}/gi,h).replace(/{DDDD}/g,n.dayOfWeek[d]).replace(/{DDD}/g,n.dayOfWeekShort[d]).replace(/{DD}/g,("0"+a).slice(-2)).replace(/{D}/g,a).replace(/{MMMM}/g,n.monthName[r]).replace(/{MMM}/g,n.monthNameShort[r]).replace(/{MM}/g,("0"+(r+1)).slice(-2)).replace(/{M}/g,r+1).replace(/{YYYY}/g,i).replace(/{YY}/g,i.toString().slice(-2)).replace(/{HH}/g,("0"+l).slice(-2)).replace(/{H}/g,l).replace(/{hh}/g,("0"+l%12).slice(-2)).replace(/{h}/g,l%12).replace(/{mm}/g,("0"+c).slice(-2)).replace(/{m}/g,c).replace(/{ss}/g,("0"+s).slice(-2)).replace(/{s}/g,s).replace(/{ap}/g,u)}function l(e,t){var n,a,r=o(new Date(e,t)).firstDay||7,i=new Date(e,t,1-(r-1||7)),l=[];for(n=0;6>n;++n)for(l.push([]),a=0;7>a;++a)l[n].push(new Date(i)),i.setDate(i.getDate()+1);return l}function c(e){var t,n,a=[];for(t=0;3>t;++t)for(a.push([]),n=0;4>n;++n)a[t].push(new Date(e,4*t+n));return a}function s(a,h){function d(e,n,a){for(var r,i=u.min,l=u.max;a>(r=o(new Date(e,n,a)).days);)++n,a-=a-r;for(;n>12;)++e,n-=12;if(t(e)){if(t(i.year)&&e<i.year||t(l.year)&&e>l.year)return!1;if(t(n)){if(t(i.month)&&n<i.month&&e<=i.year||t(l.month)&&n>l.month&&e>=l.year)return!1;if(t(a)&&(t(i.day)&&a<i.day&&n<=i.month&&e<=i.year||t(l.day)&&a>l.day&&n>=l.month&&e>=l.year))return!1}}return!0}h=n(h,{className:"chronopic",date:null,format:"{YYYY}-{MM}-{DD}",locale:"en_GB",max:{year:9999},min:{year:0},onChange:null}),this.instances=[],this.i18n=s.i18n.en_GB,this.max=e(h.max)?h.max:{},this.min=e(h.min)?h.min:{};var u=this,f=new Date;e(h.date)&&(f=(f=h.date)instanceof Date?new Date(f):new Date(f.year,f.month-1,f.day)),("string"==typeof a?Array.prototype.slice.call(document.querySelectorAll(a)):[a]).forEach(function(n){if(n instanceof HTMLElement){s.instances.forEach(function(e){e.instances.forEach(function(e,t,a){e.element.element==n&&(e.element.on(["click","change"],null),a.splice(t,1))})});var a=n.nextSibling;"DIV"==a.tagName&&a.classList.contains(h.className)||(a=null);var u,m=h.className,p=r("div."+m,{insertAfter:n,replace:a}),y=this,g={};["day","month"].forEach(function(e){p.add(g[e]=r("table.hidden."+e)),g[e].head=r("thead",{appendTo:g[e]}),g[e].body=r("tbody",{appendTo:g[e]})}),y.instances.push(u={date:new Date(f),container:p,element:r(n),selected:{},tables:g,value:"",visible:!1,get day(){return this.date.getDate()},set day(e){d(this.date.getFullYear(),this.date.getMonth()+1,e)&&(this.date.setDate(e),this.selected.day=new Date(this.date),this.value=n.value=i(this.date,h.format,y.i18n),this.hide(),"function"==typeof h.onChange&&h.onChange(n,this.date))},hide:function(){for(var e in g)g[e].classes.add("hidden");this.visible=!1,this.selected.month=null,this.selected.day&&(this.date=new Date(this.selected.day),this.selected.month=new Date(this.date))},get month(){return this.date.getMonth()},set month(e){d(this.date.getFullYear(),e+1)&&(this.date.setDate(1),this.date.setMonth(e),this.selected.month=new Date(this.date),this.show("day"))},rebuild:function(e){var n,a,s=this,h=s.selected,u=new Date,f=1;if(!e||"day"==e){for(s.tables.day.head.add([r("tr.title").add([r("th.prev[title="+y.locale.prevMonth+"]",{html:"<"}).on("click",function(e){s.month--,e.stopPropagation()}),r("th[colspan=6][title="+y.locale.selectMonth+"]",{html:i(s.date,y.locale.formatMonth,y.locale)}).on("click",function(){s.show("month")}),r("th.next[title="+y.locale.nextMonth+"]",{html:">"}).on("click",function(e){s.month++,e.stopPropagation()})]),n=r("tr.labels").add(r("th.week",{html:y.locale.week}))],!0),a=0;7>a;++a)n.add(r("th.day[title="+y.locale.dayOfWeek[f%7]+"]",{html:y.locale.dayOfWeekShort[f++%7]}));s.tables.day.body.clear(),l(s.year,s.month).forEach(function(e){var t=r("tr",{appendTo:s.tables.day.body});t.add(r("td.week",{html:o(e[0]).week})),e.forEach(function(e){var n,a=".day",l=e.getMonth()-s.month,c=!d(e.getFullYear(),e.getMonth()+1,e.getDate());(-1==l||11==l)&&(a+=".prev"),(1==l||-11==l)&&(a+=".next"),h.day&&o(h.day).compare(e)>=3&&(a+=".selected"),c&&(a+=".disabled"),o(e).compare(u)>=3&&(a+=".now"),t.add(n=r("td[title="+i(e,y.locale.formatDay,y.locale)+"]"+a,{html:e.getDate()})),!c&&n.on("click",function(){s.month=e.getMonth(),s.day=e.getDate()})})})}return e&&"month"!=e||(s.tables.month.head.add([r("tr.title").add([r("th.prev[title="+y.locale.prevYear+"]",{html:"<"}).on("click",function(e){s.year--,e.stopPropagation()}),r("th.year[colspan=6][title="+y.locale.year+"]").add(r("input[type=number][step=1][min="+(y.min.year||0)+"][max="+(y.max.year||9999)+"][value="+s.year+"]").on("change",function(e,n){t(n=Number(e.target.value))&&(s.year=n)})),r("th.next[title="+y.locale.nextYear+"]",{html:">"}).on("click",function(e){s.year++,e.stopPropagation()})])],!0),s.tables.month.body.clear(),c(s.year).forEach(function(e){var t=r("tr",{appendTo:s.tables.month.body});e.forEach(function(e){var n,a=".month",i=e.getMonth(),l=!d(e.getFullYear(),i+1);h.month&&o(h.month).compare(e)>=2&&(a+=".selected"),l&&(a+=".disabled"),o(e).compare(u)>=2&&(a+=".now"),t.add(n=r("td[colspan=2][title="+y.locale.monthName[i]+"]"+a,{html:y.locale.monthNameShort[i]})),!l&&n.on("click",function(){s.month=i})})})),this},show:function(e){e||(e="day"),this.rebuild(e),this.visible=!0;for(var t in g)g.hasOwnProperty(t)&&g[t].classes[t==e?"remove":"add"]("hidden");var a=this.container.element,o=n;a.style.top=o.offsetTop+o.offsetHeight+"px",a.style.left=o.offsetLeft+"px",a.offsetWidth<o.offsetWidth&&(a.style.width=o.offsetWidth+"px")},get year(){return this.date.getFullYear()},set year(e){d(e)&&(this.date.setFullYear(e),this.show("month"))}}),e(h.date)&&(u.day=u.date.getDate())||(n.value=""),u.element.on("click",function(e){u[u.visible?"hide":"show"]()}).on("change",function(e){var t,n,a,o,r,i,l,c=h.format,s=u.value,d=e.target.value,f=0,m=!0;return c.match(/(\{[^}]*\}|[^{]+)/g).forEach(function(e,c,s){if(m)if(/^\{(.*)\}$/.test(e)){var h=d.slice(f);++c<s.length&&(h=h.slice(0,h.search(s[c]))),f+=h.length,e=e.slice(1,-1),"DD"==e||"D"==e?t=Number(h):"MMMM"==e?(y.i18n.monthName.forEach(function(e,t){!n&&h==e&&(n=t+1)}),n||(m=!1)):"MMM"==e?(y.i18n.monthNameShort.forEach(function(e,t){!n&&h==e&&(n=t+1)}),n||(m=!1)):"MM"==e||"M"==e?n=Number(h):"YYYY"==e||"YY"==e?a=Number(h):"HH"==e||"H"==e||"hh"==e||"h"==e?o=Number(h):"mm"==e||"m"==e?r=Number(h):"s"==e||"s"==e?i=Number(h):"ap"==e?"㏂"!=(l=h)&&"㏘"!=l&&(m=!1):m=!1}else d.substr(f,e.length)==e?f+=e.length:m=!1}),m?(l&&"㏘"==l&&(o+=12),void 0!==a&&(u.year=a),void 0!==n&&(u.month=n-1),void(void 0!==t&&(u.day=t))):void(e.target.value=s)}),document.addEventListener("click",function(e,t){for(;t=t?t.parentNode:e.target;)if(t==n||t==p.element)return;u.hide()})}},this),this.locale=h.locale,s.instances.push(this)}return a.prototype={add:function(e,t){return t===!0&&this.clear(),(e instanceof Array?e:[e]).forEach(function(e){this.element.appendChild(e.element),e.parent=this},this),this},get classes(){return this.element.classList},clear:function(){for(var e,t=this.element;e=t.firstChild;)t.removeChild(e);return this},on:function(e,t){return(e instanceof Array?e:[e]).forEach(function(e){var n=this,a="function"==typeof t?function(e){t.call(n,e)}:null;n.events[e]instanceof Array||(n.events[e]=[]),a?(n.events[e].push(a),n.element.addEventListener(e,a)):(n.events[e].forEach(function(t){n.element.removeEventListener(e,t)}),n.events[e]=[])},this),this}},s.instances=[],s.prototype={get locale(){return this.i18n},set locale(e){s.i18n[e]&&s.i18n[e]!==this.i18n&&(this.i18n=s.i18n[e],this.instances.forEach(function(e){e.selected.day&&(e.day=e.date.getDate()),e.rebuild()}))}},s.i18n={en_GB:{dayOfWeek:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayOfWeekShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],disabled:"Disabled",formatDay:"{DDDD} {D} {MMMM} {YYYY}",formatMonth:"{MMMM} {YYYY}",month:"Month",monthName:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNameShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],nextMonth:"Next month",nextYear:"Next year",prevMonth:"Previous month",prevYear:"Previous year",selectMonth:"Select month",week:"Week",year:"Year"}},"undefined"!=typeof window&&(window.Chronopic=s),"object"==typeof module&&module.exports&&(module.exports=s),s}();<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Toolkitchen Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

(function(scope) {

var thisFile = 'toolkit.js';

// NOTE: use attributes on the script tag for this file as directives
// NOTE: uses 'window' and 'document' globals

// acquire directives and base path from script element

var attrs={}, base = '';

(function() {
  var s$ = document.querySelectorAll('script[src]');
  Array.prototype.forEach.call(s$, function(s) {
    var src = s.getAttribute('src');
    if (src.slice(-thisFile.length) === thisFile) {
      attrs = s.attributes;
      base = src.slice(0, -thisFile.length);
    }
  });
})();

// flags

var flags = window.flags || {};

// acquire flags from script tag attributes

for (var i=0, a; (a=attrs[i]); i++) {
  flags[a.name] = a.value || true;
}

// acquire flags from url

if (!flags.noOpts) {
  location.search.slice(1).split('&').forEach(function(o) {
    o = o.split('=');
    flags[o[0]] = o[1] || true;
  });
}

// process log flags

var logFlags = window.logFlags || {};
if (flags.log) {
  flags.log.split(',').forEach(function(f) {
    logFlags[f] = true;
  });
}
window.logFlags = logFlags;

// support exportas directive

scope = scope || {};

if (flags.exportas) {
  window[flags.exportas] = scope;
}

// module exports

scope.flags = flags;

// report effective flags

console.log(flags);

// assemble list of dependencies

var modules = [
  'src/lang.js',
  'src/oop.js',
  'src/register.js',
  'src/bindProperties.js',
  'src/bindMDV.js',
  'src/attrs.js',
  'src/marshal.js',
  'src/events.js',
  'src/observeProperties.js',
  'src/styling.js',
  'src/shimStyling.js',
  'src/path.js',
  'src/job.js',
  'src/boot.js'
];

// write script tags for dependencies

modules.forEach(function(inSrc) {
  document.write('<script src="' + base + inSrc + '"></script>');
});

})();
<commit_msg>s/attrs/attributes<commit_after>/*
 * Copyright 2013 The Toolkitchen Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

(function(scope) {

var thisFile = 'toolkit.js';

// NOTE: use attributes on the script tag for this file as directives
// NOTE: uses 'window' and 'document' globals

// acquire directives and base path from script element

var attributes={}, base = '';

(function() {
  var s$ = document.querySelectorAll('script[src]');
  Array.prototype.forEach.call(s$, function(s) {
    var src = s.getAttribute('src');
    if (src.slice(-thisFile.length) === thisFile) {
      attributes = s.attributes;
      base = src.slice(0, -thisFile.length);
    }
  });
})();

// flags

var flags = window.flags || {};

// acquire flags from script tag attributes

for (var i=0, a; (a=attributes[i]); i++) {
  flags[a.name] = a.value || true;
}

// acquire flags from url

if (!flags.noOpts) {
  location.search.slice(1).split('&').forEach(function(o) {
    o = o.split('=');
    flags[o[0]] = o[1] || true;
  });
}

// process log flags

var logFlags = window.logFlags || {};
if (flags.log) {
  flags.log.split(',').forEach(function(f) {
    logFlags[f] = true;
  });
}
window.logFlags = logFlags;

// support exportas directive

scope = scope || {};

if (flags.exportas) {
  window[flags.exportas] = scope;
}

// module exports

scope.flags = flags;

// report effective flags

console.log(flags);

// assemble list of dependencies

var modules = [
  'src/lang.js',
  'src/oop.js',
  'src/register.js',
  'src/bindProperties.js',
  'src/bindMDV.js',
  'src/attrs.js',
  'src/marshal.js',
  'src/events.js',
  'src/observeProperties.js',
  'src/styling.js',
  'src/shimStyling.js',
  'src/path.js',
  'src/job.js',
  'src/boot.js'
];

// write script tags for dependencies

modules.forEach(function(inSrc) {
  document.write('<script src="' + base + inSrc + '"></script>');
});

})();
<|endoftext|>


<commit_before>var pivot = (function(){
  var fields, filters, rawData, data, dataFilters;

  function init(options){
    rawData     = [];
    data        = [];
    dataFilters = {};

    (options.fields      === undefined) ? fields      = {}  : setFields(options.fields);
    (options.filters     === undefined) ? filters     = {}  : setFilters(options.filters);

    pivot;
  }

  function reset(){
    init();
  };

  //*******************************
  // CSV Processing
  //*******************************

  // Accepts csv as a string
  function processCSV(text) {
    var header;

    init({fields: fields, filters: filters});

    rawData = processRows(text, function(row, i) {
      if (i > 0) {
        var o = {}, j = -1, m = header.length;
        while (++j < m) {
          var value = castFieldValue(header[j], row[j]);

          o[header[j]] = value;

          addFieldValue(header[j], value);
        };
        return o;
      } else {
        header = row;
        return null;
      }
    });
  };

  function processRows(text, f) {
    var EOL = {}, // sentinel value for end-of-line
        EOF = {}, // sentinel value for end-of-file
        rows = [], // output rows
        re = /\r\n|[,\r\n]/g, // field separator regex
        n = 0, // the current line number
        t, // the current token
        eol; // is the current token followed by EOL?

    re.lastIndex = 0; // work-around bug in FF 3.6

    /** @private Returns the next token. */
    function token() {
      if (re.lastIndex >= text.length) return EOF; // special case: end of file
      if (eol) { eol = false; return EOL; } // special case: end of line

      // special case: quotes
      var j = re.lastIndex;
      if (text.charCodeAt(j) === 34) {
        var i = j;
        while (i++ < text.length) {
          if (text.charCodeAt(i) === 34) {
            if (text.charCodeAt(i + 1) !== 34) break;
            i++;
          }
        }
        re.lastIndex = i + 2;
        var c = text.charCodeAt(i + 1);
        if (c === 13) {
          eol = true;
          if (text.charCodeAt(i + 2) === 10) re.lastIndex++;
        } else if (c === 10) {
          eol = true;
        }
        return text.substring(j + 1, i).replace(/""/g, "\"");
      }

      // common case
      var m = re.exec(text);
      if (m) {
        eol = m[0].charCodeAt(0) !== 44;
        return text.substring(j, m.index);
      }
      re.lastIndex = text.length;
      return text.substring(j);
    }

    while ((t = token()) !== EOF) {
      var a = [];
      while ((t !== EOL) && (t !== EOF)) {
        a.push(t);
        t = token();
      }
      if (f && !(a = f(a, n++))) continue;
      rows.push(a);
    }

    return rows;
  };

  //*******************************
  // Filtering
  //*******************************
  function pivotFilters(type){
    var opts = {
      all:    filters,
      set:    setFilters,
      apply:  applyFilter,
      add:    appendFilter
    }

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  };

  function appendFilter(newRestriction) {
    for (var key in newRestriction) {
      if (newRestriction.hasOwnProperty(key))
        filters[key] = newRestriction[key];
    }
  };

  function setFilters(restrictions){
    filters = restrictions;
  };

  function applyFilter(restrictions){
    var dataToFilter    = data,
        filteredData    = [],
        preserveFilter  = preserveFilteredData();

    if (restrictions !== undefined) filters = restrictions;

    if (preserveFilter) {
      dataToFilter = data;
    } else {
      dataToFilter = rawData;
    }

    var dataToFilterLength = dataToFilter.length,
        filterLength = Object.keys(filters).length;

    for (var i = 0; i < dataToFilterLength; i++) {
      var row     = dataToFilter[i],
          matches = 0;

      for (var key in filters) {
        if (filters.hasOwnProperty(key) && row.hasOwnProperty(key) && row[key] === filters[key])
          matches += 1;
      }

      if (matches == filterLength) {
        filteredData.push(row);
      };
    };

    data = filteredData;
    setDataFilters();
    return data;
  };

  function setDataFilters(){
    dataFilters = {};

    for (var key in filters) {
      if (filters.hasOwnProperty(key))
        dataFilters[key] = filters[key];
    }
  };

  function preserveFilteredData(){
    var matches = 0,
        dataFiltersLength = Object.keys(dataFilters).length;

    for (var key in dataFilters) {
      if (dataFilters.hasOwnProperty(key) && dataFilters.hasOwnProperty(key) && filters[field] === dataFilters[key])
        matches += 1;
    }

    return dataFiltersLength > 0 && matches >= dataFiltersLength;
  };

  //*******************************
  // Fields
  //*******************************
  function pivotFields(type){
    var opts = {
      all:          getFields,
      set:          setFields,
      filterable:   restrictFields('filterable'),
      summarizable: restrictFields('summarizable'),
      pseudo:       restrictFields('pseudo'),
      detail:       restrictFields('detail'),
      get:          getField,
      add:          appendField
    }

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  };

  function setFields(listing){
    fields = {};
    for (var i = 0; i < listing.length; i++) {
      appendField(listing[i]);
    }
  };

  function getFields(){
    var retFields = [];
    for (var key in fields) {
      if (fields.hasOwnProperty(key)) retFields.push(fields[key]);
    }

    return retFields;
  };

  function restrictFields(type){
    var retFields = [];
    for (var key in fields) {
      if (fields.hasOwnProperty(key) && fields[key][type] === true) retFields.push(fields[key]);
    }

    return retFields;
  };

  function getField(name){
    return fields[name];
  };

  function appendField(field){
    // if field is a simple string setup and object with that string as a name
    if (Object.prototype.toString.call(field) === '[object String]') field = {name: field};

    if (field.type          === undefined) field.type          = 'String';
    if (field.pseudo        === undefined) field.pseudo        = false;
    if (field.detail        === undefined) field.detail        = true;
    if (field.filterable    === undefined) field.filterable    = false;
    if (field.summarizable  === undefined) field.summarizable  = false;
    if (field.summarizable && field.summarizable_function == undefined)
        field.summarize_function = function(rows){ rows.length };

    field.values = {};

    fields[field.name] = field;

    return field;
  };

  function addFieldValue(field, value){
    if (fields[field] === undefined || fields[field].filterable === false) return;

    if (fields[field].values[value] === undefined)
      fields[field].values[value] = 0;
    else
      fields[field].values[value] += 1;
  };

  function castFieldValue(fieldName, value){
    if (Object.prototype.toString.call(fieldName) === '[object String]') field = fields[fieldName];
    if (field === undefined) field = appendField(fieldName);

    switch (field.type){
      case "integer":
        return parseInt(value, 10);
      case "float":
        return parseFloat(value, 10);
      case "date":
        return new Date(value);
      default:
        return value.toString();
    }
  };

  //*******************************
  // Data
  //*******************************
  function pivotData(type) {
    var opts = {raw: rawData,
                all: data};

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  }

  // Entry Point
  return {
    csv:      processCSV,
    data:     pivotData,
    fields:   pivotFields,
    filters:  pivotFilters,
    init:     init,
    reset:    reset
  }
})();<commit_msg>Return self on init/reset.<commit_after>var pivot = (function(){
  var fields, filters, rawData, data, dataFilters;

  function init(options){
    rawData     = [];
    data        = [];
    dataFilters = {};

    if (options === undefined) options = {};

    (options.fields      === undefined) ? fields      = {}  : setFields(options.fields);
    (options.filters     === undefined) ? filters     = {}  : setFilters(options.filters);

    return pivot;
  }

  function reset(){
    return init();
  };

  //*******************************
  // CSV Processing
  //*******************************

  // Accepts csv as a string
  function processCSV(text) {
    var header;

    init({fields: fields, filters: filters});

    rawData = processRows(text, function(row, i) {
      if (i > 0) {
        var o = {}, j = -1, m = header.length;
        while (++j < m) {
          var value = castFieldValue(header[j], row[j]);

          o[header[j]] = value;

          addFieldValue(header[j], value);
        };
        return o;
      } else {
        header = row;
        return null;
      }
    });
  };

  function processRows(text, f) {
    var EOL = {}, // sentinel value for end-of-line
        EOF = {}, // sentinel value for end-of-file
        rows = [], // output rows
        re = /\r\n|[,\r\n]/g, // field separator regex
        n = 0, // the current line number
        t, // the current token
        eol; // is the current token followed by EOL?

    re.lastIndex = 0; // work-around bug in FF 3.6

    /** @private Returns the next token. */
    function token() {
      if (re.lastIndex >= text.length) return EOF; // special case: end of file
      if (eol) { eol = false; return EOL; } // special case: end of line

      // special case: quotes
      var j = re.lastIndex;
      if (text.charCodeAt(j) === 34) {
        var i = j;
        while (i++ < text.length) {
          if (text.charCodeAt(i) === 34) {
            if (text.charCodeAt(i + 1) !== 34) break;
            i++;
          }
        }
        re.lastIndex = i + 2;
        var c = text.charCodeAt(i + 1);
        if (c === 13) {
          eol = true;
          if (text.charCodeAt(i + 2) === 10) re.lastIndex++;
        } else if (c === 10) {
          eol = true;
        }
        return text.substring(j + 1, i).replace(/""/g, "\"");
      }

      // common case
      var m = re.exec(text);
      if (m) {
        eol = m[0].charCodeAt(0) !== 44;
        return text.substring(j, m.index);
      }
      re.lastIndex = text.length;
      return text.substring(j);
    }

    while ((t = token()) !== EOF) {
      var a = [];
      while ((t !== EOL) && (t !== EOF)) {
        a.push(t);
        t = token();
      }
      if (f && !(a = f(a, n++))) continue;
      rows.push(a);
    }

    return rows;
  };

  //*******************************
  // Filtering
  //*******************************
  function pivotFilters(type){
    var opts = {
      all:    filters,
      set:    setFilters,
      apply:  applyFilter,
      add:    appendFilter
    }

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  };

  function appendFilter(newRestriction) {
    for (var key in newRestriction) {
      if (newRestriction.hasOwnProperty(key))
        filters[key] = newRestriction[key];
    }
  };

  function setFilters(restrictions){
    filters = restrictions;
  };

  function applyFilter(restrictions){
    var dataToFilter    = data,
        filteredData    = [],
        preserveFilter  = preserveFilteredData();

    if (restrictions !== undefined) filters = restrictions;

    if (preserveFilter) {
      dataToFilter = data;
    } else {
      dataToFilter = rawData;
    }

    var dataToFilterLength = dataToFilter.length,
        filterLength = Object.keys(filters).length;

    for (var i = 0; i < dataToFilterLength; i++) {
      var row     = dataToFilter[i],
          matches = 0;

      for (var key in filters) {
        if (filters.hasOwnProperty(key) && row.hasOwnProperty(key) && row[key] === filters[key])
          matches += 1;
      }

      if (matches == filterLength) {
        filteredData.push(row);
      };
    };

    data = filteredData;
    setDataFilters();
    return data;
  };

  function setDataFilters(){
    dataFilters = {};

    for (var key in filters) {
      if (filters.hasOwnProperty(key))
        dataFilters[key] = filters[key];
    }
  };

  function preserveFilteredData(){
    var matches = 0,
        dataFiltersLength = Object.keys(dataFilters).length;

    for (var key in dataFilters) {
      if (dataFilters.hasOwnProperty(key) && dataFilters.hasOwnProperty(key) && filters[field] === dataFilters[key])
        matches += 1;
    }

    return dataFiltersLength > 0 && matches >= dataFiltersLength;
  };

  //*******************************
  // Fields
  //*******************************
  function pivotFields(type){
    var opts = {
      all:          getFields,
      set:          setFields,
      filterable:   restrictFields('filterable'),
      summarizable: restrictFields('summarizable'),
      pseudo:       restrictFields('pseudo'),
      detail:       restrictFields('detail'),
      get:          getField,
      add:          appendField
    }

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  };

  function setFields(listing){
    fields = {};
    for (var i = 0; i < listing.length; i++) {
      appendField(listing[i]);
    }
  };

  function getFields(){
    var retFields = [];
    for (var key in fields) {
      if (fields.hasOwnProperty(key)) retFields.push(fields[key]);
    }

    return retFields;
  };

  function restrictFields(type){
    var retFields = [];
    for (var key in fields) {
      if (fields.hasOwnProperty(key) && fields[key][type] === true) retFields.push(fields[key]);
    }

    return retFields;
  };

  function getField(name){
    return fields[name];
  };

  function appendField(field){
    // if field is a simple string setup and object with that string as a name
    if (Object.prototype.toString.call(field) === '[object String]') field = {name: field};

    if (field.type          === undefined) field.type          = 'String';
    if (field.pseudo        === undefined) field.pseudo        = false;
    if (field.detail        === undefined) field.detail        = true;
    if (field.filterable    === undefined) field.filterable    = false;
    if (field.summarizable  === undefined) field.summarizable  = false;
    if (field.summarizable && field.summarizable_function == undefined)
        field.summarize_function = function(rows){ rows.length };

    field.values = {};

    fields[field.name] = field;

    return field;
  };

  function addFieldValue(field, value){
    if (fields[field] === undefined || fields[field].filterable === false) return;

    if (fields[field].values[value] === undefined)
      fields[field].values[value] = 0;
    else
      fields[field].values[value] += 1;
  };

  function castFieldValue(fieldName, value){
    if (Object.prototype.toString.call(fieldName) === '[object String]') field = fields[fieldName];
    if (field === undefined) field = appendField(fieldName);

    switch (field.type){
      case "integer":
        return parseInt(value, 10);
      case "float":
        return parseFloat(value, 10);
      case "date":
        return new Date(value);
      default:
        return value.toString();
    }
  };

  //*******************************
  // Data
  //*******************************
  function pivotData(type) {
    var opts = {raw: rawData,
                all: data};

    if (type !== undefined) {
      return opts[type]
    } else {
      return opts
    };
  }

  // Entry Point
  return {
    csv:      processCSV,
    data:     pivotData,
    fields:   pivotFields,
    filters:  pivotFilters,
    init:     init,
    reset:    reset
  }
})();<|endoftext|>