<commit_before>/*
 * 	www.appcorner.it
 *	v1.0.0
 */

//BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=)
var YOUR_FACEBOOK_ID = '00000000';

var skipApps;
var canLoadNextPage;

var spinnerOpts = {
    lines: 17, // The number of lines to draw
    length: 0, // The length of each line
    width: 9, // The line thickness
    radius: 28, // The radius of the inner circle
    corners: 1, // Corner roundness (0..1)
    rotate: 0, // The rotation offset
    direction: 1, // 1: clockwise, -1: counterclockwise
    color: '#000', // #rgb or #rrggbb or array of colors
    speed: 1, // Rounds per second
    trail: 50, // Afterglow percentage
    shadow: true, // Whether to render a shadow
    hwaccel: true, // Whether to use hardware acceleration
    className: 'spinner', // The CSS class to assign to the spinner
    zIndex: 2e9, // The z-index (defaults to 2000000000)
    top: 'auto', // Top position relative to parent in px
    left: 'auto' // Left position relative to parent in px
};

$(function(){
    $.extend({
        appstore : function(opts) {
                         $.each( opts.items, function(i) {
                                    if(opts.items && opts.items[i])
                                    {
                                        var date = $.format.prettyDate(opts.items[i].created);
                                        var des = opts.items[i].description;
                                        if(!des)
                                        {
                                            des = '';
                                        }
                                        var n = 160;
                                        if(opts.items[i].comments != '') {des = '
'+opts.items[i].comments +'
'+ des; n=170;}
                                        des = des.length>n ? des.substr(0,n-1)+'…' : des;

                                        //Download the app store badges for your language https://developer.apple.com/app-store/marketing/guidelines/#downloadOnAppstore
                                        var appstorebadge = 'img/appstore_badge.png';
                                        var badgeWidth = 135;
                                        if(opts.items[i].kind == "mac-software") //mac
                                        {
                                            //Download the mac app store badges for your language https://developer.apple.com/app-store/marketing/guidelines/mac/#downloadOnAppstore
                                            appstorebadge = 'img/mac_appstore_badge.png';
                                            badgeWidth = 165;
                                        }

                                        var button = '

';
                                        var icon = '

';

                                        var scrUrl='
';
                                        for(x=0;x<opts.items[i].screenshotUrls.length;x++)
                                        {
                                            if(opts.items[i].screenshotUrls[x] != null)
                                            {
                                                scrUrl=scrUrl+'

';
                                            }
                                        }

                                        scrUrl = scrUrl+'
';
                                        var item = '
'+scrUrl+'
'+opts.items[i].primaryGenreName+'  '+date+''+icon+'
'+opts.items[i].trackName+'
'+des+'

'+button+'

';

                                        $(item).appendTo('#'+opts.container);
                                        $('#'+opts.container+opts.items[i].appcode).owlCarousel({
                                                    items : 1,
                                                    singleItem : true,
                                                    lazyLoad : true
                                                    });
                                    }
                                });
        }
    });

   $.extend({

            loadAppsInContainer : function(containerName,target,heightOffset) {
                    if($("#"+containerName).length != 0) {

                        $[target](containerName);

                        //load next apps block on page scroll
                        $(window).scroll(function () {
                             if ($(window).scrollTop() >= $(document).height() - $(window).height() - heightOffset) {
                                         if(canLoadNextPage)
                                         {
                                            canLoadNextPage = false;
                                            $[target](containerName);
                                        }
                             }
                        });
                    }
            },

           userapps : function(containerName) {
                    var spinner = new Spinner(spinnerOpts).spin();
                    $('#'+containerName).append(spinner.el);
                    //BASE URL: http://www.appcorner.it/userapps
                    //REQUIRED PARAM:
                    //fb=[YOUR FACEBOOK ID]
                    //
                    //OPTIONAL PARAMS:
                    //country=[ITUNES COUNTRY CODE]
                    //limit=[APPS LIMIT, MAX 12 BY DEFAULT]
                    //skip=[NUMBER OF APPS TO SKIP]
                    //phgat=[YOUR PHG AFFILIATE TOKEN]
                    //campaign=[YOUR PHG CAMPAIGN]

                    //EXAMPLE: YOUR APPS POSTED ON APPCORNER FOR IPHONE, LOADED FROM ITUNES FOR UNITED STATES
                    //BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=)
                    $.get("http://www.appcorner.it/userapps?fb="+YOUR_FACEBOOK_ID+"&country=us&skip="+skipApps,function(apps,status){
                        var appsCounter = (apps == null?0:apps.length);
                        if(appsCounter > 0)
                        {
                            $.appstore({"items": apps, "container":containerName});
                        }

                        //code to load next apps block
                        skipApps = skipApps+appsCounter;
                        if(appsCounter > 0){
                           canLoadNextPage = true;
                        }

                        spinner.stop();
                });
            },

            pricedrops : function(containerName) {
                        var spinner = new Spinner(spinnerOpts).spin();
                        $('#'+containerName).append(spinner.el);
                        //BASE URL: http://www.appcorner.it/pricedrops
                        //REQUIRED PARAM:
                        //fb=[YOUR FACEBOOK ID]
                        //
                        //OPTIONAL PARAMS:
                        //limit=[APPS LIMIT, MAX 12 BY DEFAULT]
                        //skip=[NUMBER OF APPS TO SKIP]
                        //phgat=[YOUR PHG AFFILIATE TOKEN]
                        //campaign=[YOUR PHG CAMPAIGN]
                        //shortUrl=true [USE SHORT LINK INSTEAD OF STANDARD LINK https://developer.apple.com/library/ios/qa/qa1633/_index.html]
                        //
                        //OPTIONAL FILTERS:
                        //device=[DEFAULT ALL OR ONLY ONE FROM: iphone,ipad,mac]
                        //languages=[MUST HAVE ONE OF THOSE LANGUAGES COMMAS SEPARATED]
                        //price=0 filter free app only
                        //genre=[PRIMARY GENRE ONLY ONE FROM: books, business, catalogs, education, entertainment, finance, food, games, health, lifestyle, medical, music, navigation, news, newsstand, photo video, productivity, reference, social, sports, travel, utilities, weather]

                        //EXAMPLE: SHOW PRICE DROPS TO FREE, GAMES FOR IPHONE ONLY THAT CONTAINS AT LEAST ENGLISH OR ITALIAN LANGUAGE, LOADED FROM THE ITUNES COUNTRY USED TO LOGIN IN APPCORNER SOCIAL (FOR THE YOUR FACEBOOK ID)
                        //BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=), in case of empty result remove some filters.
                        $.get("http://www.appcorner.it/pricedrops?fb="+YOUR_FACEBOOK_ID+"&price=0&genre=games&device=iphone&languages=en,it&skip="+skipApps,function(apps,status){
                                  var appsCounter = (apps == null?0:apps.length);
                                  if(appsCounter > 0)
                                  {
                                    $.appstore({"items": apps, "container":containerName});
                                  }

                                  //code to load next apps block
                                  skipApps = skipApps+appsCounter;
                                  if(appsCounter > 0){
                                    canLoadNextPage = true;
                                  }

                                  spinner.stop();
                        });
            }
    });
});

$(document).ready(function(){
                  skipApps = 0;
                  canLoadNextPage = false;
                  var heightOffset = 400; //min height to load next request, change as you need

                  $.loadAppsInContainer("userapps-container","userapps",heightOffset);
                  $.loadAppsInContainer("pricedrops-container","pricedrops",heightOffset);
});

<commit_msg>added mac genre<commit_after>/*
 * 	www.appcorner.it
 *	v1.0.0
 */

//BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=)
var YOUR_FACEBOOK_ID = '00000000';

var skipApps;
var canLoadNextPage;

var spinnerOpts = {
    lines: 17, // The number of lines to draw
    length: 0, // The length of each line
    width: 9, // The line thickness
    radius: 28, // The radius of the inner circle
    corners: 1, // Corner roundness (0..1)
    rotate: 0, // The rotation offset
    direction: 1, // 1: clockwise, -1: counterclockwise
    color: '#000', // #rgb or #rrggbb or array of colors
    speed: 1, // Rounds per second
    trail: 50, // Afterglow percentage
    shadow: true, // Whether to render a shadow
    hwaccel: true, // Whether to use hardware acceleration
    className: 'spinner', // The CSS class to assign to the spinner
    zIndex: 2e9, // The z-index (defaults to 2000000000)
    top: 'auto', // Top position relative to parent in px
    left: 'auto' // Left position relative to parent in px
};

$(function(){
    $.extend({
        appstore : function(opts) {
                         $.each( opts.items, function(i) {
                                    if(opts.items && opts.items[i])
                                    {
                                        var date = $.format.prettyDate(opts.items[i].created);
                                        var des = opts.items[i].description;
                                        if(!des)
                                        {
                                            des = '';
                                        }
                                        var n = 160;
                                        if(opts.items[i].comments != '') {des = '
'+opts.items[i].comments +'
'+ des; n=170;}
                                        des = des.length>n ? des.substr(0,n-1)+'…' : des;

                                        //Download the app store badges for your language https://developer.apple.com/app-store/marketing/guidelines/#downloadOnAppstore
                                        var appstorebadge = 'img/appstore_badge.png';
                                        var badgeWidth = 135;
                                        if(opts.items[i].kind == "mac-software") //mac
                                        {
                                            //Download the mac app store badges for your language https://developer.apple.com/app-store/marketing/guidelines/mac/#downloadOnAppstore
                                            appstorebadge = 'img/mac_appstore_badge.png';
                                            badgeWidth = 165;
                                        }

                                        var button = '

';
                                        var icon = '

';

                                        var scrUrl='
';
                                        for(x=0;x<opts.items[i].screenshotUrls.length;x++)
                                        {
                                            if(opts.items[i].screenshotUrls[x] != null)
                                            {
                                                scrUrl=scrUrl+'

';
                                            }
                                        }

                                        scrUrl = scrUrl+'
';
                                        var item = '
'+scrUrl+'
'+opts.items[i].primaryGenreName+'  '+date+''+icon+'
'+opts.items[i].trackName+'
'+des+'

'+button+'

';

                                        $(item).appendTo('#'+opts.container);
                                        $('#'+opts.container+opts.items[i].appcode).owlCarousel({
                                                    items : 1,
                                                    singleItem : true,
                                                    lazyLoad : true
                                                    });
                                    }
                                });
        }
    });

   $.extend({

            loadAppsInContainer : function(containerName,target,heightOffset) {
                    if($("#"+containerName).length != 0) {

                        $[target](containerName);

                        //load next apps block on page scroll
                        $(window).scroll(function () {
                             if ($(window).scrollTop() >= $(document).height() - $(window).height() - heightOffset) {
                                         if(canLoadNextPage)
                                         {
                                            canLoadNextPage = false;
                                            $[target](containerName);
                                        }
                             }
                        });
                    }
            },

           userapps : function(containerName) {
                    var spinner = new Spinner(spinnerOpts).spin();
                    $('#'+containerName).append(spinner.el);
                    //BASE URL: http://www.appcorner.it/userapps
                    //REQUIRED PARAM:
                    //fb=[YOUR FACEBOOK ID]
                    //
                    //OPTIONAL PARAMS:
                    //country=[ITUNES COUNTRY CODE]
                    //limit=[APPS LIMIT, MAX 12 BY DEFAULT]
                    //skip=[NUMBER OF APPS TO SKIP]
                    //phgat=[YOUR PHG AFFILIATE TOKEN]
                    //campaign=[YOUR PHG CAMPAIGN]

                    //EXAMPLE: YOUR APPS POSTED ON APPCORNER FOR IPHONE, LOADED FROM ITUNES FOR UNITED STATES
                    //BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=)
                    $.get("http://www.appcorner.it/userapps?fb="+YOUR_FACEBOOK_ID+"&country=us&skip="+skipApps,function(apps,status){
                        var appsCounter = (apps == null?0:apps.length);
                        if(appsCounter > 0)
                        {
                            $.appstore({"items": apps, "container":containerName});
                        }

                        //code to load next apps block
                        skipApps = skipApps+appsCounter;
                        if(appsCounter > 0){
                           canLoadNextPage = true;
                        }

                        spinner.stop();
                });
            },

            pricedrops : function(containerName) {
                        var spinner = new Spinner(spinnerOpts).spin();
                        $('#'+containerName).append(spinner.el);
                        //BASE URL: http://www.appcorner.it/pricedrops
                        //REQUIRED PARAM:
                        //fb=[YOUR FACEBOOK ID]
                        //
                        //OPTIONAL PARAMS:
                        //limit=[APPS LIMIT, MAX 12 BY DEFAULT]
                        //skip=[NUMBER OF APPS TO SKIP]
                        //phgat=[YOUR PHG AFFILIATE TOKEN]
                        //campaign=[YOUR PHG CAMPAIGN]
                        //shortUrl=true [USE SHORT LINK INSTEAD OF STANDARD LINK https://developer.apple.com/library/ios/qa/qa1633/_index.html]
                        //
                        //OPTIONAL FILTERS:
                        //device=[DEFAULT ALL OR ONLY ONE FROM: iphone,ipad,mac]
                        //languages=[MUST HAVE ONE OF THOSE LANGUAGES COMMAS SEPARATED]
                        //price=0 filter free app only
                        //genre=[DEAFAULT ALL, OR ONLY ONE PRIMARY GENRE]
                        //      PRIMARY GENRE for iOS: books, business, catalogs, education, entertainment, finance, food, games, health, lifestyle, medical, music, navigation, news, newsstand, photo video, productivity, reference, social, sports, travel, utilities, weather
                        //      PRIMARY GENRE for Mac: business, developer, education, entertainment, finance, games, graphics, health, lifestyle, medical, music, news, photography, productivity, reference, social, sports, travel, utilities, video, weather

                        //EXAMPLE: SHOW PRICE DROPS TO FREE, GAMES FOR IPHONE ONLY THAT CONTAINS AT LEAST ENGLISH OR ITALIAN LANGUAGE, LOADED FROM THE ITUNES COUNTRY USED TO LOGIN IN APPCORNER SOCIAL (FOR THE YOUR FACEBOOK ID)
                        //BEFORE TRY INSERT YOUR FACEBOOK ID USED TO LOGIN IN APPCORNER SOCIAL FOR IPHONE (fb=), in case of empty result remove some filters.
                        $.get("http://www.appcorner.it/pricedrops?fb="+YOUR_FACEBOOK_ID+"&price=0&genre=games&device=iphone&languages=en,it&skip="+skipApps,function(apps,status){
                                  var appsCounter = (apps == null?0:apps.length);
                                  if(appsCounter > 0)
                                  {
                                    $.appstore({"items": apps, "container":containerName});
                                  }

                                  //code to load next apps block
                                  skipApps = skipApps+appsCounter;
                                  if(appsCounter > 0){
                                    canLoadNextPage = true;
                                  }

                                  spinner.stop();
                        });
            }
    });
});

$(document).ready(function(){
                  skipApps = 0;
                  canLoadNextPage = false;
                  var heightOffset = 400; //min height to load next request, change as you need

                  $.loadAppsInContainer("userapps-container","userapps",heightOffset);
                  $.loadAppsInContainer("pricedrops-container","pricedrops",heightOffset);
});

<|endoftext|>


<commit_before>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_TOPIC_MAPPER } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/topicRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Topic Mapper app.
 */

ReactGA.initialize('UA-60744513-7');

setVersion('3.5.0');

setAppName(APP_TOPIC_MAPPER);

setAppColors({
  light: '#58DBCC',
  dark: '#38BBAC', // primary
  darker: '#189B8C',
  main: '#38BBAC',
});

initializeApp(routes);
<commit_msg>Topics version bump<commit_after>import ReactGA from 'react-ga';
import { setAppName, setVersion, APP_TOPIC_MAPPER } from './config';
import { setAppColors } from './styles/colors';
import routes from './routes/topicRoutes';
import initializeApp from './index';

/**
 * This serves as the primary entry point to the Media Cloud Topic Mapper app.
 */

ReactGA.initialize('UA-60744513-7');

setVersion('3.5.1');

setAppName(APP_TOPIC_MAPPER);

setAppColors({
  light: '#58DBCC',
  dark: '#38BBAC', // primary
  darker: '#189B8C',
  main: '#38BBAC',
});

initializeApp(routes);
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const exec = require('child_process').exec;
const program = require('commander');
const chalk = require('chalk');
const inquirer = require('inquirer');
const updateNotifier = require('update-notifier');
const pkg = require('../package.json');

updateNotifier({pkg}).notify();

const setCode = service => {
  inquirer.prompt([
    {
      type: 'password',
      message: `Enter code for ${service}:`,
      name: 'code1'
    },
    {
      type: 'password',
      message: `Re-Enter code for ${service}:`,
      name: 'code2'
    }
  ], (answers) => {
    if (answers.code1 === answers.code2) {
      const pass = exec(`pass insert 2fa/${service}/code`);
      pass.stdin.write(`${answers.code1}\n`);
      pass.stdin.write(`${answers.code1}\n`);

      pass.stderr.on('data', data => {
        console.log(chalk.red(`Error: ${data}`));
      });
      pass.on('close', () => {
        console.log(chalk.green('Stored code'));
        process.exit(0);
      });
    } else {
      console.log(chalk.red('Wrong code'));
    }
  });
};

program
  .usage('<service>')
  .parse(process.argv);

if (program.args.length === 0) {
  console.log(chalk.red('Service required'));
  process.exit(1);
} else {
  setCode(program.args[0]);
}
<commit_msg>fix(insert): Fix inquirer response<commit_after>#!/usr/bin/env node

'use strict';

const exec = require('child_process').exec;
const program = require('commander');
const chalk = require('chalk');
const inquirer = require('inquirer');
const updateNotifier = require('update-notifier');
const pkg = require('../package.json');

updateNotifier({pkg}).notify();

const setCode = service => {
  inquirer.prompt([
    {
      type: 'password',
      message: `Enter code for ${service}:`,
      name: 'code1'
    },
    {
      type: 'password',
      message: `Re-Enter code for ${service}:`,
      name: 'code2'
    }
  ]).then(answers => {
    if (answers.code1 === answers.code2) {
      const pass = exec(`pass insert 2fa/${service}/code`);
      pass.stdin.write(`${answers.code1}\n`);
      pass.stdin.write(`${answers.code1}\n`);

      pass.stderr.on('data', data => {
        console.log(chalk.red(`Error: ${data}`));
      });
      pass.on('close', () => {
        console.log(chalk.green('Stored code'));
        process.exit(0);
      });
    } else {
      console.log(chalk.red('Wrong code'));
    }
  });
};

program
  .usage('<service>')
  .parse(process.argv);

if (program.args.length === 0) {
  console.log(chalk.red('Service required'));
  process.exit(1);
} else {
  setCode(program.args[0]);
}
<|endoftext|>


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

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

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

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

      if (type === "data" || force){
        var messageCount = 0;
        var channelCount = 0;

        if (STATE.hasSavedData()){
          messageCount = STATE.getSavefile().countMessages();
          channelCount = STATE.getSavefile().countChannels();
        }

        controller.ui.textStatus.innerHTML = [
          messageCount, " message", (messageCount === 1 ? "" : "s"),
          " from ",
          channelCount, " channel", (channelCount === 1 ? "" : "s")
        ].join("");
      }
    }

    if (settings){
      var force = type === "gui" && detail === "settings";

      if (force){
        settings.ui.cbAutoscroll.checked = STATE.settings.autoscroll;
        settings.ui.optsAfterFirstMsg[STATE.settings.afterFirstMsg].checked = true;
        settings.ui.optsAfterSavedMsg[STATE.settings.afterSavedMsg].checked = true;
      }

      if (type === "setting" || force){
        var autoscrollRev = !STATE.settings.autoscroll;

        Object.values(settings.ui.optsAfterFirstMsg).forEach(ele => ele.disabled = autoscrollRev);
        Object.values(settings.ui.optsAfterSavedMsg).forEach(ele => ele.disabled = autoscrollRev);
      }
    }
  };

  var registeredEvent = false;

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

    stateChangedEvent("gui", detail);
  };

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

      // styles

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

      // main

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

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

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

      // elements

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

      // events

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

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

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

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

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

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

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

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

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

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

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

      setupStateChanged("controller");
    },

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

    showSettings: function(){
      settings = {};

      // styles

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

      // overlay

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

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

      // main

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

      settings.ele.innerHTML = [
        "<input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll
",
        "
",
        "After reaching the first message in channel...
",
        "<input id='dht-cfg-afm-nothing' name='dht-afm' type='radio'> Do Nothing
",
        "<input id='dht-cfg-afm-pause' name='dht-afm' type='radio'> Pause Tracking
",
        "<input id='dht-cfg-afm-switch' name='dht-afm' type='radio'> Switch to Next Channel
",
        "
",
        "After reaching a previously saved message...
",
        "<input id='dht-cfg-asm-nothing' name='dht-asm' type='radio'> Do Nothing
",
        "<input id='dht-cfg-asm-pause' name='dht-asm' type='radio'> Pause Tracking
",
        "<input id='dht-cfg-asm-switch' name='dht-asm' type='radio'> Switch to Next Channel
",
        "
",
        "Tracking will only trigger when Discord loads new messages. ",
        "To ensure that all messages are saved, go to your Friends list to avoid loading any messages, refresh the website, and run the script again.",
        "

",
        "Discord History Tracker will not save newly received messages, it is specifically made to load and save the server/group/DM history.",
        "

",
        "It is recommended to disable link and image previews to avoid putting unnecessary strain on your browser.",
        "
"
      ].join("");

      // elements

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

      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_NOTHING] = DOM.id("dht-cfg-afm-nothing");
      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_PAUSE] = DOM.id("dht-cfg-afm-pause");
      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_SWITCH] = DOM.id("dht-cfg-afm-switch");

      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_NOTHING] = DOM.id("dht-cfg-asm-nothing");
      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_PAUSE] = DOM.id("dht-cfg-asm-pause");
      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_SWITCH] = DOM.id("dht-cfg-asm-switch");

      // events

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

      Object.keys(settings.ui.optsAfterFirstMsg).forEach(key => {
        settings.ui.optsAfterFirstMsg[key].addEventListener("click", () => {
          STATE.settings.afterFirstMsg = key;
        });
      });

      Object.keys(settings.ui.optsAfterSavedMsg).forEach(key => {
        settings.ui.optsAfterSavedMsg[key].addEventListener("click", () => {
          STATE.settings.afterSavedMsg = key;
        });
      });

      setupStateChanged("settings");
    },

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

  return root;
})();
<commit_msg>Add a polyfill info comment to Object.values in tracker<commit_after>var GUI = (function(){
  var controller;
  var settings;

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

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

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

      if (type === "data" || force){
        var messageCount = 0;
        var channelCount = 0;

        if (STATE.hasSavedData()){
          messageCount = STATE.getSavefile().countMessages();
          channelCount = STATE.getSavefile().countChannels();
        }

        controller.ui.textStatus.innerHTML = [
          messageCount, " message", (messageCount === 1 ? "" : "s"),
          " from ",
          channelCount, " channel", (channelCount === 1 ? "" : "s")
        ].join("");
      }
    }

    if (settings){
      var force = type === "gui" && detail === "settings";

      if (force){
        settings.ui.cbAutoscroll.checked = STATE.settings.autoscroll;
        settings.ui.optsAfterFirstMsg[STATE.settings.afterFirstMsg].checked = true;
        settings.ui.optsAfterSavedMsg[STATE.settings.afterSavedMsg].checked = true;
      }

      if (type === "setting" || force){
        var autoscrollRev = !STATE.settings.autoscroll;

        // discord polyfills Object.values
        Object.values(settings.ui.optsAfterFirstMsg).forEach(ele => ele.disabled = autoscrollRev);
        Object.values(settings.ui.optsAfterSavedMsg).forEach(ele => ele.disabled = autoscrollRev);
      }
    }
  };

  var registeredEvent = false;

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

    stateChangedEvent("gui", detail);
  };

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

      // styles

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

      // main

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

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

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

      // elements

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

      // events

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

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

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

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

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

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

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

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

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

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

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

      setupStateChanged("controller");
    },

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

    showSettings: function(){
      settings = {};

      // styles

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

      // overlay

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

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

      // main

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

      settings.ele.innerHTML = [
        "<input id='dht-cfg-autoscroll' type='checkbox'> Autoscroll
",
        "
",
        "After reaching the first message in channel...
",
        "<input id='dht-cfg-afm-nothing' name='dht-afm' type='radio'> Do Nothing
",
        "<input id='dht-cfg-afm-pause' name='dht-afm' type='radio'> Pause Tracking
",
        "<input id='dht-cfg-afm-switch' name='dht-afm' type='radio'> Switch to Next Channel
",
        "
",
        "After reaching a previously saved message...
",
        "<input id='dht-cfg-asm-nothing' name='dht-asm' type='radio'> Do Nothing
",
        "<input id='dht-cfg-asm-pause' name='dht-asm' type='radio'> Pause Tracking
",
        "<input id='dht-cfg-asm-switch' name='dht-asm' type='radio'> Switch to Next Channel
",
        "
",
        "Tracking will only trigger when Discord loads new messages. ",
        "To ensure that all messages are saved, go to your Friends list to avoid loading any messages, refresh the website, and run the script again.",
        "

",
        "Discord History Tracker will not save newly received messages, it is specifically made to load and save the server/group/DM history.",
        "

",
        "It is recommended to disable link and image previews to avoid putting unnecessary strain on your browser.",
        "
"
      ].join("");

      // elements

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

      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_NOTHING] = DOM.id("dht-cfg-afm-nothing");
      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_PAUSE] = DOM.id("dht-cfg-afm-pause");
      settings.ui.optsAfterFirstMsg[CONSTANTS.AUTOSCROLL_ACTION_SWITCH] = DOM.id("dht-cfg-afm-switch");

      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_NOTHING] = DOM.id("dht-cfg-asm-nothing");
      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_PAUSE] = DOM.id("dht-cfg-asm-pause");
      settings.ui.optsAfterSavedMsg[CONSTANTS.AUTOSCROLL_ACTION_SWITCH] = DOM.id("dht-cfg-asm-switch");

      // events

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

      Object.keys(settings.ui.optsAfterFirstMsg).forEach(key => {
        settings.ui.optsAfterFirstMsg[key].addEventListener("click", () => {
          STATE.settings.afterFirstMsg = key;
        });
      });

      Object.keys(settings.ui.optsAfterSavedMsg).forEach(key => {
        settings.ui.optsAfterSavedMsg[key].addEventListener("click", () => {
          STATE.settings.afterSavedMsg = key;
        });
      });

      setupStateChanged("settings");
    },

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

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


<commit_before>!(function(window, document) {
  'use strict';

  var Interdimensional = (function() {

    /**
     * Default settings
     * @private
     * @const
     * @type {Object}
     */
    var DEFAULT_SETTINGS = {
      ppd: 2,
      insensitivity: 5,
      useControl: true
    };

    /**
     * Is ready to jump?
     * @private
     * @type {Boolean}
     */
    var isCharged = false;

    /**
     * Is preparing to be ready or no?
     * @private
     * @type {Boolean}
     */
    var isCharging = false;

    /**
     * Is the spatial scrolling on?
     * @private
     * @type {Boolean}
     */
    var isOn = false;

    /**
     * Last orientation of the device around the Z axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastAlpha;

    /**
     * Last orientation of the device around the X axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastBeta;

    /**
     * Last orientation of the device around the Y axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastGamma;

    /**
     * Current settings
     * @private
     * @type {Object}
     */
    var settings;

    /**
     * Interdimensional controller
     * @private
     * @type {HTMLElement}
     */
    var control;

    /**
     * Checks support of necessary features
     * @private
     * @param {Function} success
     * @param {Function} fail
     */
    function checkSupport(success, fail) {

      // Check the deviceorientation event and touch events
      if (
        !window.DeviceOrientationEvent ||
        !(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch)
      ) {
        fail();
      }

      // Check the deviceorientation event in the action
      window.addEventListener('deviceorientation', function checkDeviceOrientationEvent(e) {
        window.removeEventListener('deviceorientation', checkDeviceOrientationEvent, false);

        if (!isCharging) {
          return;
        }

        if ((e.alpha != null || e.beta != null || e.gamma != null)) {
          success();
        } else {
          fail();
        }
      }, false);
    }

    /**
     * Parses a string with options
     * @private
     * @param   {String} str
     * @returns {Object|String}
     */
    function parseOptions(str) {
      var obj = {};
      var delimiterIndex;
      var option;
      var prop;
      var val;
      var arr;
      var len;
      var i;

      // remove spaces around delimiters and split
      arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(',');

      // parse a string
      for (i = 0, len = arr.length; i < len; i++) {
        option = arr[i];

        // Ignore urls and a string without colon delimiters
        if (option.search(/^(http|https|ftp):\/\//) !== -1 ||
          option.search(':') === -1) {

          break;
        }

        delimiterIndex = option.indexOf(':');
        prop = option.substring(0, delimiterIndex);
        val = option.substring(delimiterIndex + 1);

        // if val is an empty string, make it undefined
        if (!val) {
          val = undefined;
        }

        // convert a string value if it is like a boolean
        if (typeof val === 'string') {
          val = val === 'true' || (val === 'false' ? false : val);
        }

        // convert a string value if it is like a number
        if (typeof val === 'string') {
          val = !isNaN(val) ? +val : val;
        }

        obj[prop] = val;
      }

      // if nothing is parsed
      if (prop == null && val == null) {
        return str;
      }

      return obj;
    }

    /**
     * Calculates a number of pixels to scroll
     * @private
     * @param  {Number} lastAngle Last orientation
     * @param  {Number} newAngle New orientation
     * @return {Number} Pixels to scroll
     */
    function calcShift(lastAngle, newAngle) {
      var diff = newAngle - lastAngle;
      var absDiff = Math.abs(diff);
      var sign = diff === 0 ? 0 : diff / absDiff;

      return absDiff > settings.insensitivity ?
        settings.ppd * (diff - sign * settings.insensitivity) : 0;
    }

    /**
     * Triggers events
     * @private
     * @param {String} Name of an event
     */
    function trigger(eventName) {
      var event;

      if (!eventName) {
        return;
      }

      // Add namespace
      eventName = 'interdimensional:' + eventName;

      if (!window.Event || typeof window.Event !== 'function') {

        // The old way
        event = document.createEvent('Event');
        event.initEvent(eventName, true, true);
      } else {

        // The new way
        event = new Event(eventName);
      }

      document.dispatchEvent(event);
    }

    /**
     * Enables/disables the spatial scrolling
     * @private
     * @listens touchstart
     */
    function handleTouchStartEvent() {
      Interdimensional.toggle();
    }

    /**
     * Scrolls the page
     * @private
     * @listens deviceorientation
     * @param {Event} e
     */
    function handleDeviceOrientationEvent(e) {
      if (!isOn || (lastAlpha == null || lastBeta == null || lastGamma == null)) {
        lastAlpha = e.alpha;
        lastBeta = e.beta;
        lastGamma = e.gamma;
      } else {
        if (window.innerHeight > window.innerWidth) {
          window.scrollBy(
            calcShift(lastAlpha, e.alpha),
            calcShift(lastBeta, e.beta)
          );
        } else {
          window.scrollBy(
            calcShift(lastBeta, e.beta),
            calcShift(lastGamma, e.gamma)
          );
        }
      }
    }

    /**
     * Disables the spacial scrolling
     * @private
     * @listens orientationchange
     */
    function handleOrientationChangeEvent() {
      Interdimensional.kick();
    }

    /**
     * Initializes declaratively
     * @private
     * @listens DOMContentLoaded
     */
    function handleDOMContentLoadedEvent() {
      var data = document.body.getAttribute('data-interdimensional');

      if (data != null) {
        Interdimensional.charge(parseOptions(data));
      }
    }

    document.addEventListener('DOMContentLoaded', handleDOMContentLoadedEvent, false);

    return {

      /**
       * @public
       * @returns {Boolean} `isCharged` variable
       */
      isCharged: function() {
        return isCharged;
      },

      /**
       * @public
       * @returns {Boolean} `isOn` variable
       */
      isOn: function() {
        return isOn;
      },

      /**
       * Initializes
       * @public
       * @param {Object} options
       */
      charge: function(options) {
        if (!isCharged && !isCharging) {
          isCharging = true;

          checkSupport(function() {
            isCharged = true;
            isCharging = false;

            // Set settings
            settings = {};
            for (var key in DEFAULT_SETTINGS) {
              if (DEFAULT_SETTINGS.hasOwnProperty(key)) {
                options && typeof options[key] !== 'undefined' ?
                  settings[key] = options[key] :
                  settings[key] = DEFAULT_SETTINGS[key];
              }
            }

            // Create the control
            control = document.createElement('div');
            control.className = 'interdimensional-control';
            settings.useControl && document.body.appendChild(control);

            // Add event listeners
            control.addEventListener('touchstart', handleTouchStartEvent, false);
            window.addEventListener('deviceorientation', handleDeviceOrientationEvent, false);
            window.addEventListener('orientationchange', handleOrientationChangeEvent, false);

            trigger('charge');
          }, function() {
            isCharging = false;
            trigger('fail');
          });
        }
      },

      /**
       * Enables the spatial scrolling
       * @public
       */
      jump: function() {
        if (!isCharged) {
          return;
        }

        isOn = true;
        control.classList.add('interdimensional-control-is-active');

        trigger('jump');
      },

      /**
       * Disables the spatial scrolling
       * @public
       */
      kick: function() {
        if (!isCharged) {
          return;
        }

        isOn = false;
        control.classList.remove('interdimensional-control-is-active');

        trigger('kick');
      },

      /**
       * Toggles the spatial scrolling
       * @public
       */
      toggle: function() {
        isOn ? Interdimensional.kick() : Interdimensional.jump();
      },

      /**
       * Destroys
       * @public
       */
      discharge: function() {
        if (!isCharged) {
          return;
        }

        Interdimensional.kick();

        isCharged = false;
        settings.useControl && document.body.removeChild(control);

        // Remove event listeners
        control.removeEventListener('touchstart', handleTouchStartEvent, false);
        window.removeEventListener('deviceorientation', handleDeviceOrientationEvent, false);
        window.removeEventListener('orientationchange', handleOrientationChangeEvent, false);

        trigger('discharge');
      }
    };
  })();

  window.Interdimensional = Interdimensional;

})(window, document);
<commit_msg>Rename some variables<commit_after>!(function(window, document) {
  'use strict';

  var Interdimensional = (function() {

    /**
     * Default settings
     * @private
     * @const
     * @type {Object}
     */
    var DEFAULT_SETTINGS = {
      PPD: 2,
      insensitivity: 5,
      useControl: true
    };

    /**
     * Is ready to jump?
     * @private
     * @type {Boolean}
     */
    var isCharged = false;

    /**
     * Is preparing to be ready or no?
     * @private
     * @type {Boolean}
     */
    var isCharging = false;

    /**
     * Is the spatial scrolling on?
     * @private
     * @type {Boolean}
     */
    var isOn = false;

    /**
     * Last orientation of the device around the Z axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastAlpha;

    /**
     * Last orientation of the device around the X axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastBeta;

    /**
     * Last orientation of the device around the Y axis
     * @see https://developer.mozilla.org/en-US/docs/Web/Events/deviceorientation
     * @private
     * @type {Number}
     */
    var lastGamma;

    /**
     * Current settings
     * @private
     * @type {Object}
     */
    var settings;

    /**
     * Interdimensional controller
     * @private
     * @type {HTMLElement}
     */
    var control;

    /**
     * Checks support of necessary features
     * @private
     * @param {Function} success
     * @param {Function} fail
     */
    function checkSupport(success, fail) {

      // Check the deviceorientation event and touch events
      if (
        !window.DeviceOrientationEvent ||
        !(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch)
      ) {
        fail();
      }

      // Check the deviceorientation event in the action
      window.addEventListener('deviceorientation', function checkDeviceOrientationEvent(e) {
        window.removeEventListener('deviceorientation', checkDeviceOrientationEvent, false);

        if (!isCharging) {
          return;
        }

        if ((e.alpha != null || e.beta != null || e.gamma != null)) {
          success();
        } else {
          fail();
        }
      }, false);
    }

    /**
     * Parses a string with options
     * @private
     * @param   {String} str
     * @returns {Object|String}
     */
    function parseOptions(str) {
      var obj = {};
      var delimiterIndex;
      var option;
      var prop;
      var val;
      var arr;
      var len;
      var i;

      // remove spaces around delimiters and split
      arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(',');

      // parse a string
      for (i = 0, len = arr.length; i < len; i++) {
        option = arr[i];

        // Ignore urls and a string without colon delimiters
        if (option.search(/^(http|https|ftp):\/\//) !== -1 ||
          option.search(':') === -1) {

          break;
        }

        delimiterIndex = option.indexOf(':');
        prop = option.substring(0, delimiterIndex);
        val = option.substring(delimiterIndex + 1);

        // if val is an empty string, make it undefined
        if (!val) {
          val = undefined;
        }

        // convert a string value if it is like a boolean
        if (typeof val === 'string') {
          val = val === 'true' || (val === 'false' ? false : val);
        }

        // convert a string value if it is like a number
        if (typeof val === 'string') {
          val = !isNaN(val) ? +val : val;
        }

        obj[prop] = val;
      }

      // if nothing is parsed
      if (prop == null && val == null) {
        return str;
      }

      return obj;
    }

    /**
     * Calculates a number of pixels to scroll
     * @private
     * @param  {Number} lastAngle Last orientation
     * @param  {Number} newAngle New orientation
     * @return {Number} Pixels to scroll
     */
    function calcShift(lastAngle, newAngle) {
      var diff = newAngle - lastAngle;
      var absDiff = Math.abs(diff);
      var sign = diff === 0 ? 0 : diff / absDiff;

      return absDiff > settings.insensitivity ?
        settings.PPD * (diff - sign * settings.insensitivity) : 0;
    }

    /**
     * Triggers events
     * @private
     * @param {String} Name of an event
     */
    function trigger(eventName) {
      var e;

      if (!eventName) {
        return;
      }

      // Add namespace
      eventName = 'interdimensional:' + eventName;

      if (!window.Event || typeof window.Event !== 'function') {

        // The old way
        e = document.createEvent('Event');
        e.initEvent(eventName, true, true);
      } else {

        // The new way
        e = new Event(eventName);
      }

      document.dispatchEvent(e);
    }

    /**
     * Enables/disables the spatial scrolling
     * @private
     * @listens touchstart
     */
    function handleTouchStartEvent() {
      Interdimensional.toggle();
    }

    /**
     * Scrolls the page
     * @private
     * @listens deviceorientation
     * @param {Event} e
     */
    function handleDeviceOrientationEvent(e) {
      if (!isOn || (lastAlpha == null || lastBeta == null || lastGamma == null)) {
        lastAlpha = e.alpha;
        lastBeta = e.beta;
        lastGamma = e.gamma;
      } else {
        if (window.innerHeight > window.innerWidth) {
          window.scrollBy(
            calcShift(lastAlpha, e.alpha),
            calcShift(lastBeta, e.beta)
          );
        } else {
          window.scrollBy(
            calcShift(lastBeta, e.beta),
            calcShift(lastGamma, e.gamma)
          );
        }
      }
    }

    /**
     * Disables the spacial scrolling
     * @private
     * @listens orientationchange
     */
    function handleOrientationChangeEvent() {
      Interdimensional.kick();
    }

    /**
     * Initializes declaratively
     * @private
     * @listens DOMContentLoaded
     */
    function handleDOMContentLoadedEvent() {
      var data = document.body.getAttribute('data-interdimensional');

      if (data != null) {
        Interdimensional.charge(parseOptions(data));
      }
    }

    document.addEventListener('DOMContentLoaded', handleDOMContentLoadedEvent, false);

    return {

      /**
       * @public
       * @returns {Boolean} `isCharged` variable
       */
      isCharged: function() {
        return isCharged;
      },

      /**
       * @public
       * @returns {Boolean} `isOn` variable
       */
      isOn: function() {
        return isOn;
      },

      /**
       * Initializes
       * @public
       * @param {Object} options
       */
      charge: function(options) {
        if (!isCharged && !isCharging) {
          isCharging = true;

          checkSupport(function() {
            isCharged = true;
            isCharging = false;

            // Set settings
            settings = {};
            for (var key in DEFAULT_SETTINGS) {
              if (DEFAULT_SETTINGS.hasOwnProperty(key)) {
                options && typeof options[key] !== 'undefined' ?
                  settings[key] = options[key] :
                  settings[key] = DEFAULT_SETTINGS[key];
              }
            }

            // Create the control
            control = document.createElement('div');
            control.className = 'interdimensional-control';
            settings.useControl && document.body.appendChild(control);

            // Add event listeners
            control.addEventListener('touchstart', handleTouchStartEvent, false);
            window.addEventListener('deviceorientation', handleDeviceOrientationEvent, false);
            window.addEventListener('orientationchange', handleOrientationChangeEvent, false);

            trigger('charge');
          }, function() {
            isCharging = false;
            trigger('fail');
          });
        }
      },

      /**
       * Enables the spatial scrolling
       * @public
       */
      jump: function() {
        if (!isCharged) {
          return;
        }

        isOn = true;
        control.classList.add('interdimensional-control-is-active');

        trigger('jump');
      },

      /**
       * Disables the spatial scrolling
       * @public
       */
      kick: function() {
        if (!isCharged) {
          return;
        }

        isOn = false;
        control.classList.remove('interdimensional-control-is-active');

        trigger('kick');
      },

      /**
       * Toggles the spatial scrolling
       * @public
       */
      toggle: function() {
        isOn ? Interdimensional.kick() : Interdimensional.jump();
      },

      /**
       * Destroys
       * @public
       */
      discharge: function() {
        if (!isCharged) {
          return;
        }

        Interdimensional.kick();

        isCharged = false;
        settings.useControl && document.body.removeChild(control);

        // Remove event listeners
        control.removeEventListener('touchstart', handleTouchStartEvent, false);
        window.removeEventListener('deviceorientation', handleDeviceOrientationEvent, false);
        window.removeEventListener('orientationchange', handleOrientationChangeEvent, false);

        trigger('discharge');
      }
    };
  })();

  window.Interdimensional = Interdimensional;

})(window, document);
<|endoftext|>


<commit_before>'use strict';

var request = require('request');

var globe = {

    saveReport: function(userId, report, callback) {
        if(!callback) {
            callback = function() {};
        }

        var options = {
            form: {
                app: process.env.APP_NAME,
                userId: userId,
                report: report,
                key: process.env.GLOBE_KEY
            }
        };

        request.post(process.env.GLOBE_URI+'/reports', options, function(err, response, body) {
            if(err) {
                return callback(err);
            }
            if(!body) {
                return callback('no reply from globe');
            }

            body = JSON.parse(body);

            if(body.error) {
                return callback('globe error: ' + JSON.stringify(body));
            }

            return callback(null);
        });
    }

};

module.exports = globe;<commit_msg>catch json parse error<commit_after>'use strict';

var request = require('request');

var globe = {

    saveReport: function(userId, report, callback) {
        if(!callback) {
            callback = function() {};
        }

        var options = {
            form: {
                app: process.env.APP_NAME,
                userId: userId,
                report: report,
                key: process.env.GLOBE_KEY
            }
        };

        request.post(process.env.GLOBE_URI+'/reports', options, function(err, response, body) {
            if(err) {
                return callback(err);
            }
            if(!body) {
                return callback('no reply from globe');
            }

            try {
                body = JSON.parse(body);
            }
            catch(err) {
                return callback('globe error: ' + body);
            }

            if(body.error) {
                return callback('globe error: ' + JSON.stringify(body));
            }

            return callback(null);
        });
    }

};

module.exports = globe;<|endoftext|>


<commit_before>var Gluon = {
	parseOptions: function(options){
		if (!options){
			options = {};
		}
		if (!options.ignoreList){
			options.ignoreList = [];
		}
		if (options.sessionId === undefined){
			options.sessionId = "";
		}
		return options;
	},

	formatName : function(name){
		name = name[0].toUpperCase() + name.slice(1);
		return name.replace(/[a-z][A-Z]/g, function(x){ return x[0] + " " + x[1].toUpperCase()})
			.replace(/[_][a-z]/, function(x){ return " " + x[1].toUpperCase()})
			.replace(/[_][A-Z]/, function(x){ return " " + x[1]});
	},

	edit : function(obj, options){
		if (!obj){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '';
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
					html += '
' + Gluon.formatName(prop) + '<input type="text" class="form-control ' + options.sessionId + '" id="' + prop + '" value="' + obj[prop] + '">
';
					break;
				case 'boolean':
				 	html += '
<input class="' + options.sessionId + '"" type="checkbox" ' + (obj[prop] ? 'checked' : '') + '> ' + Gluon.formatName(prop) + '
';
					break;
				case 'number':
					html += '
' + Gluon.formatName(prop) + '<input type="number" class="form-control ' + options.sessionId + '" id="' + prop + '" value="' + obj[prop] + '">
';
					break;
			}
		}
		html += "";
		return html;
	},
	view : function(obj, options){
		if (!obj){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '
';
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
				case 'number':
				case 'boolean':
					html += '

' + Gluon.formatName(prop) + '

' + obj[prop] + '

';
					break;
			}
		}
		html += "
";
		return html;

	},
	table : function(objs, options){
		if (!objs || !objs.length){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '

';

		var obj = objs[0];
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
				case 'number':
				case 'boolean':
					html += '' + Gluon.formatName(prop) + '	';
					break;
			}
		}
		html += "
";

		objs.forEach(function(obj){
			html += "
";
			for(var prop in obj){
				if (!options.ignoreList.indexOf(prop)){
					continue;
				}
				switch (typeof obj[prop]){
					case 'string':
					case 'number':
					case 'boolean':
						html += '' + obj[prop] + '	';
						break;
				}
			}

			html += "
";
		});

		html += "
";
		return html;

	}
}<commit_msg>fixed extra double quote<commit_after>var Gluon = {
	parseOptions: function(options){
		if (!options){
			options = {};
		}
		if (!options.ignoreList){
			options.ignoreList = [];
		}
		if (options.sessionId === undefined){
			options.sessionId = "";
		}
		return options;
	},

	formatName : function(name){
		name = name[0].toUpperCase() + name.slice(1);
		return name.replace(/[a-z][A-Z]/g, function(x){ return x[0] + " " + x[1].toUpperCase()})
			.replace(/[_][a-z]/, function(x){ return " " + x[1].toUpperCase()})
			.replace(/[_][A-Z]/, function(x){ return " " + x[1]});
	},

	edit : function(obj, options){
		if (!obj){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '';
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
					html += '
' + Gluon.formatName(prop) + '<input type="text" class="form-control ' + options.sessionId + '" id="' + prop + '" value="' + obj[prop] + '">
';
					break;
				case 'boolean':
				 	html += '
<input class="' + options.sessionId + '" type="checkbox" ' + (obj[prop] ? 'checked' : '') + '> ' + Gluon.formatName(prop) + '
';
					break;
				case 'number':
					html += '
' + Gluon.formatName(prop) + '<input type="number" class="form-control ' + options.sessionId + '" id="' + prop + '" value="' + obj[prop] + '">
';
					break;
			}
		}
		html += "";
		return html;
	},
	view : function(obj, options){
		if (!obj){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '
';
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
				case 'number':
				case 'boolean':
					html += '

' + Gluon.formatName(prop) + '

' + obj[prop] + '

';
					break;
			}
		}
		html += "
";
		return html;

	},
	table : function(objs, options){
		if (!objs || !objs.length){
			return "";
		}
		options = Gluon.parseOptions(options);

		var html = '

';

		var obj = objs[0];
		for(var prop in obj){
			if (!options.ignoreList.indexOf(prop)){
				continue;
			}
			switch (typeof obj[prop]){
				case 'string':
				case 'number':
				case 'boolean':
					html += '' + Gluon.formatName(prop) + '	';
					break;
			}
		}
		html += "
";

		objs.forEach(function(obj){
			html += "
";
			for(var prop in obj){
				if (!options.ignoreList.indexOf(prop)){
					continue;
				}
				switch (typeof obj[prop]){
					case 'string':
					case 'number':
					case 'boolean':
						html += '' + obj[prop] + '	';
						break;
				}
			}

			html += "
";
		});

		html += "
";
		return html;

	}
}<|endoftext|>


<commit_before>/* Filters */
angular.module('myApp.filters').filter('interpolate', function(version) {
    'use strict';

    return function(text) {
        return String(text).replace(/\%VERSION\%/mg, version);
    };
}).filter('percent', function() {
    'use strict';

    return function(number) {
        if (typeof number != 'number') {
            return "";
        }
        var value = number * 100;
        return Math.round(value * 10) / 10;
    };
}).filter('integer', function() {
    'use strict';

    return function(number) {
        if (typeof number != 'number') {
            return "";
        }

        return Math.round(number);
    };
}).filter('capital', function() {
    'use strict';

    return function(text) {

        if (text.length > 0) {
            return text.charAt(0).toUpperCase() + text.slice(1);
        }

        return text;
    };
})
;
<commit_msg>Correct but on Capital filter<commit_after>/* Filters */
angular.module('myApp.filters').filter('interpolate', function(version) {
    'use strict';

    return function(text) {
        return String(text).replace(/\%VERSION\%/mg, version);
    };
}).filter('percent', function() {
    'use strict';

    return function(number) {
        if (typeof number != 'number') {
            return "";
        }
        var value = number * 100;
        return Math.round(value * 10) / 10;
    };
}).filter('integer', function() {
    'use strict';

    return function(number) {
        if (typeof number != 'number') {
            return "";
        }

        return Math.round(number);
    };
}).filter('capital', function() {
    'use strict';

    return function(text) {

        if (text) {
            return text.charAt(0).toUpperCase() + text.slice(1);
        }

        return text;
    };
})
;
<|endoftext|>


<commit_before>/*!
 * Created by Rajeshwar Patlolla https://github.com/rajeshwarpatlolla
 * Modified by Marko Marković <okram@civokram.com>
 *
 * @version 1.0.0
 */
'use strict';
angular.module('ionic-datepicker', ['ionic', 'ionic-datepicker.template'])
.directive('ionicDatepicker', ['$ionicPopup', function ($ionicPopup) {
	return {
		restrict: 'AE',
		replace: true,
		scope: {
			value: '=',
			weekBeginsOnMonday: '=?',
			min: '=?',
			max: '=?'
		},
		link: function (scope, element) {
			var currentDate = angular.copy(scope.value) || new Date(); // Date for the UI calendar display
			scope.highlightedDate = angular.copy(currentDate); // Temporary selected date before the 'Set' or 'Today' is pressed

			// Days of the week to be used in calendar heading
			scope.weekDays = [
				'Sunday',
				'Monday',
				'Tuesday',
				'Wednesday',
				'Thursday',
				'Friday',
				'Saturday'
			];
			if (scope.weekBeginsOnMonday || false) {
				scope.weekDays.push(scope.weekDays.shift());
			}

			// Month names
			var monthNames = [
				'January',
				'February',
				'March',
				'April',
				'May',
				'June',
				'July',
				'August',
				'September',
				'October',
				'November',
				'December'
			];

			scope.calendarRows = new Array(6);
			scope.calendarCols = new Array(7);

			var refreshCalendar = function (currentDate) {
				scope.dayList = [];
				var firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1).getDate();
				var lastDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0).getDate();
				for (var i = firstDay; i <= lastDay; i++) {
					var tempDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), i);
					scope.dayList.push({
						date: tempDate,
						day: tempDate.getDate()
					});
				}
				// Offset the first of the month to match the week day
				firstDay = scope.dayList[0].date.getDay();
				if (scope.weekBeginsOnMonday || false) {
					firstDay--;
				}
				for (var j = 0; j < firstDay; j++) {
					scope.dayList.unshift(undefined);
				}
				scope.currentMonth = monthNames[currentDate.getMonth()];
				scope.currentYear = currentDate.getFullYear();
			};

			// Go to previous month
			scope.prevMonth = function () {
				var previousLastDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 0);
				if (undefined !== scope.min && previousLastDay < scope.min) {
					return;
				}
				currentDate.setMonth(currentDate.getMonth() - 1);
				refreshCalendar(currentDate);
			};

			// Go to next month
			scope.nextMonth = function () {
				var nextFirstDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
				if (undefined !== scope.max && nextFirstDay > scope.max) {
					return;
				}
				currentDate.setMonth(currentDate.getMonth() + 1);
				refreshCalendar(currentDate);
			};

			scope.highlightDate = function (date) {
				if (typeof date !== 'undefined') {
					// Minimum date
					if (undefined !== scope.min && date < scope.min) {
						return;
					}
					// Maximum date
					if (undefined !== scope.max && date > scope.max) {
						return;
					}
					scope.highlightedDate = angular.copy(date);
					currentDate = date;
					refreshCalendar(currentDate);
				}
			};

			// Check if the day is valid (for CSS class)
			scope.isValidDay = function (rowIndex, colIndex) {
				var day = scope.dayList[rowIndex * 7 + colIndex];
				return (typeof day !== 'undefined');
			};

			// Check if the day should be selected (for CSS class)
			scope.isSelected = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					var day = scope.dayList[rowIndex * 7 + colIndex];
					return (day.date.toDateString() === scope.highlightedDate.toDateString());
				}
				return false;
			};

			// Check if the day is today (for CSS class)
			scope.isToday = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					return (scope.dayList[rowIndex * 7 + colIndex].date.toDateString() === new Date().toDateString());
				}
				return false;
			};

			// Check if the day should be disabled (for CSS class)
			scope.isDisabled = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					// Minimum date
					if (scope.dayList[rowIndex * 7 + colIndex].date < scope.min) {
						return true;
					}
					// Maximum date
					if (scope.dayList[rowIndex * 7 + colIndex].date > scope.max) {
						return true;
					}
				}
				return false;
			};

			element.on('click', function () {
				refreshCalendar(currentDate);
				$ionicPopup.show({
					templateUrl: 'ionic-datepicker.template.html',
					title: 'Select a date',
					subTitle: '',
					scope: scope,
					buttons: [
						{
							text: '',
							type: 'button-clear'
						},
						{
							text: 'Today',
							onTap: function (e) {
								var now = new Date();
								// Minimum date
								if (undefined !== scope.min && now < scope.min) {
									e.preventDefault();
									return;
								}
								// Maxumum date
								if (undefined !== scope.max && now > scope.max) {
									e.preventDefault();
									return;
								}
								scope.highlightDate(now);
								scope.value = now;
							}
						},
						{
							text: '',
							type: 'button-positive',
							onTap: function () {
								scope.highlightDate(scope.highlightedDate);
								scope.value = scope.highlightedDate;
							}
						}
					]
				});
			});
		}
	};
}]);
<commit_msg>Add support for localized day names, month names, title and today button<commit_after>/*!
 * Created by Rajeshwar Patlolla https://github.com/rajeshwarpatlolla
 * Modified by Marko Marković <okram@civokram.com>
 *
 * @version 1.0.0
 */
'use strict';
angular.module('ionic-datepicker', ['ionic', 'ionic-datepicker.template'])
.directive('ionicDatepicker', ['$ionicPopup', function ($ionicPopup) {
	return {
		restrict: 'AE',
		replace: true,
		scope: {
			value: '=',
			weekBeginsOnMonday: '=?',
			min: '=?',
			max: '=?',
			weekDayNames: '=?',
			monthNames: '=?',
			todayText: '=?',
			title: '=?'
		},
		link: function (scope, element) {
			var currentDate = angular.copy(scope.value) || new Date(); // Date for the UI calendar display
			scope.highlightedDate = angular.copy(currentDate); // Temporary selected date before the 'Set' or 'Today' is pressed

			// Days of the week to be used in calendar heading
			scope.weekDays = scope.weekDayNames || ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
			if (scope.weekBeginsOnMonday || false) {
				scope.weekDays.push(scope.weekDays.shift());
			}

			// Month names
			var monthNames = scope.monthNames || ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

			scope.calendarRows = new Array(6);
			scope.calendarCols = new Array(7);

			var refreshCalendar = function (currentDate) {
				scope.dayList = [];
				var firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1).getDate();
				var lastDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0).getDate();
				for (var i = firstDay; i <= lastDay; i++) {
					var tempDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), i);
					scope.dayList.push({
						date: tempDate,
						day: tempDate.getDate()
					});
				}
				// Offset the first of the month to match the week day
				firstDay = scope.dayList[0].date.getDay();
				if (scope.weekBeginsOnMonday || false) {
					firstDay--;
				}
				for (var j = 0; j < firstDay; j++) {
					scope.dayList.unshift(undefined);
				}
				scope.currentMonth = monthNames[currentDate.getMonth()];
				scope.currentYear = currentDate.getFullYear();
			};

			// Go to previous month
			scope.prevMonth = function () {
				var previousLastDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 0);
				if (undefined !== scope.min && previousLastDay < scope.min) {
					return;
				}
				currentDate.setMonth(currentDate.getMonth() - 1);
				refreshCalendar(currentDate);
			};

			// Go to next month
			scope.nextMonth = function () {
				var nextFirstDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
				if (undefined !== scope.max && nextFirstDay > scope.max) {
					return;
				}
				currentDate.setMonth(currentDate.getMonth() + 1);
				refreshCalendar(currentDate);
			};

			scope.highlightDate = function (date) {
				if (typeof date !== 'undefined') {
					// Minimum date
					if (undefined !== scope.min && date < scope.min) {
						return;
					}
					// Maximum date
					if (undefined !== scope.max && date > scope.max) {
						return;
					}
					scope.highlightedDate = angular.copy(date);
					currentDate = date;
					refreshCalendar(currentDate);
				}
			};

			// Check if the day is valid (for CSS class)
			scope.isValidDay = function (rowIndex, colIndex) {
				var day = scope.dayList[rowIndex * 7 + colIndex];
				return (typeof day !== 'undefined');
			};

			// Check if the day should be selected (for CSS class)
			scope.isSelected = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					var day = scope.dayList[rowIndex * 7 + colIndex];
					return (day.date.toDateString() === scope.highlightedDate.toDateString());
				}
				return false;
			};

			// Check if the day is today (for CSS class)
			scope.isToday = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					return (scope.dayList[rowIndex * 7 + colIndex].date.toDateString() === new Date().toDateString());
				}
				return false;
			};

			// Check if the day should be disabled (for CSS class)
			scope.isDisabled = function (rowIndex, colIndex) {
				if (scope.isValidDay(rowIndex, colIndex)) {
					// Minimum date
					if (scope.dayList[rowIndex * 7 + colIndex].date < scope.min) {
						return true;
					}
					// Maximum date
					if (scope.dayList[rowIndex * 7 + colIndex].date > scope.max) {
						return true;
					}
				}
				return false;
			};

			element.on('click', function () {
				refreshCalendar(currentDate);
				$ionicPopup.show({
					templateUrl: 'ionic-datepicker.template.html',
					title: scope.title || 'Select a date',
					subTitle: '',
					scope: scope,
					buttons: [
						{
							text: '',
							type: 'button-clear'
						},
						{
							text: scope.todayText || 'Today',
							onTap: function (e) {
								var now = new Date();
								// Minimum date
								if (undefined !== scope.min && now < scope.min) {
									e.preventDefault();
									return;
								}
								// Maxumum date
								if (undefined !== scope.max && now > scope.max) {
									e.preventDefault();
									return;
								}
								scope.highlightDate(now);
								scope.value = now;
							}
						},
						{
							text: '',
							type: 'button-positive',
							onTap: function () {
								scope.highlightDate(scope.highlightedDate);
								scope.value = scope.highlightedDate;
							}
						}
					]
				});
			});
		}
	};
}]);
<|endoftext|>


<commit_before>var myrules = {
    // TAP Matrix triggers for more test file details
    'a.testfile_details_trigger' : function(el) {
        // get the id of the target div
        var matches = el.id.match(/^for_(.*)$/);
        var target = matches[1];
        // get the id of the indicator image
        matches = el.className.match(/(^|\s)show_(\S*)($|\s)/);
        var indicator = matches[2];

        el.onclick = function() {
console.log('clicking');
            if( Element.visible(target) ) {
console.log('  is ivisible');
                Effect.BlindUp(target, { duration: .5 });
            } else {
console.log('  not visibile');
                $(indicator).style.visibility = 'visible';
console.log('  making ajax request for target: ' + target);
                Smolder.Ajax.update({
                    url        : el.href,
                    target     : target,
                    indicator  : 'none',
                    onComplete : function() {
console.log('    in onComplete');
                        window.setTimeout(function() { $(indicator).style.visibility = 'hidden'}, 200);
console.log('    BlindDown');
                        Effect.BlindDown(
                            target,
                            // reapply any dynamic bits
                            {
                                afterFinish : function() {
console.log('      in afterFinish()');
                                    Behaviour.apply(target);
                                },
                                duration    : .5
                            }
                        );
                    }
                });
            }
console.log('returning false');
            return false;
        };
    },
    'div.diag': function(el) {
        Smolder.setup_tooltip(el, el);
    },
    'td.tooltip_trigger' : function(el) {
        var diag = document.getElementsByClassName('tooltip', el)[0];
        Smolder.setup_tooltip(el, diag);
    },
    'a.show_all' : function(el) {
        Event.observe(el, 'click', function() {
            // an anonymous function that we use as a callback after each
            // panel is opened so that it opens the next one
            var show_details = function(index) {
                var el = $('testfile_details_' + index);
                // apply the behaviours if we're the last one
                if( ! el ) {
                    Behaviour.apply();
                    return;
                }

                // we only need to fetch it if we're not already visible
                if( Element.visible(el) ) {
                    show_details(++index);
                } else {
                    matches = el.id.match(/^testfile_details_(\d+)$/);
                    var index = matches[1];
                    var indicator = $('indicator_' + index);
                    var div = $('testfile_details_' + index);
                    indicator.style.visibility = 'visible';

                    Smolder.Ajax.update({
                        url        : $('for_testfile_details_' + index).href,
                        target     : div,
                        indicator  : 'none',
                        onComplete : function() {
                            Element.show(div);
                            indicator.style.visibility = 'hidden';
                            show_details(++index);
                        }
                    });
                }
            };
            show_details(0);
        });
    }
};

Behaviour.register(myrules);

<commit_msg>remove debugging<commit_after>var myrules = {
    // TAP Matrix triggers for more test file details
    'a.testfile_details_trigger' : function(el) {
        // get the id of the target div
        var matches = el.id.match(/^for_(.*)$/);
        var target = matches[1];
        // get the id of the indicator image
        matches = el.className.match(/(^|\s)show_(\S*)($|\s)/);
        var indicator = matches[2];

        el.onclick = function() {
            if( Element.visible(target) ) {
                Effect.BlindUp(target, { duration: .5 });
            } else {
                $(indicator).style.visibility = 'visible';
                Smolder.Ajax.update({
                    url        : el.href,
                    target     : target,
                    indicator  : 'none',
                    onComplete : function() {
                        window.setTimeout(function() { $(indicator).style.visibility = 'hidden'}, 200);
                        Effect.BlindDown(
                            target,
                            // reapply any dynamic bits
                            {
                                afterFinish : function() {
                                    Behaviour.apply(target);
                                },
                                duration    : .5
                            }
                        );
                    }
                });
            }
            return false;
        };
    },
    'div.diag': function(el) {
        Smolder.setup_tooltip(el, el);
    },
    'td.tooltip_trigger' : function(el) {
        var diag = document.getElementsByClassName('tooltip', el)[0];
        Smolder.setup_tooltip(el, diag);
    },
    'a.show_all' : function(el) {
        Event.observe(el, 'click', function() {
            // an anonymous function that we use as a callback after each
            // panel is opened so that it opens the next one
            var show_details = function(index) {
                var el = $('testfile_details_' + index);
                // apply the behaviours if we're the last one
                if( ! el ) {
                    Behaviour.apply();
                    return;
                }

                // we only need to fetch it if we're not already visible
                if( Element.visible(el) ) {
                    show_details(++index);
                } else {
                    matches = el.id.match(/^testfile_details_(\d+)$/);
                    var index = matches[1];
                    var indicator = $('indicator_' + index);
                    var div = $('testfile_details_' + index);
                    indicator.style.visibility = 'visible';

                    Smolder.Ajax.update({
                        url        : $('for_testfile_details_' + index).href,
                        target     : div,
                        indicator  : 'none',
                        onComplete : function() {
                            Element.show(div);
                            indicator.style.visibility = 'hidden';
                            show_details(++index);
                        }
                    });
                }
            };
            show_details(0);
        });
    }
};

Behaviour.register(myrules);

<|endoftext|>


<commit_before>import React, {Component} from 'react';
import treeData from './../AnimationData/treeStructure';

// Tree and Link are two new components used by HalfwayFinishedStructureAnimation.
import Tree from './Tree';
import Link from './Link';

var d3 = require('d3');
var ReactDOM = require('react-dom');

// My goal in creating HalfwayFinishedStructureAnimation was to make React responsible for DOM structure (adding and removing elements) and to make D3 responsible for styling, as described in this blog post:
// https://medium.com/@sxywu/on-d3-react-and-a-little-bit-of-flux-88a226f328f3#.ztcxqykek

// We still need to handle window resizes. Here are some useful resources:
// http://eyeseast.github.io/visible-data/2013/08/28/responsive-charts-with-d3/
// http://bl.ocks.org/mbostock/3019563

export default class HalfwayFinishedStructureAnimation extends Component {

  constructor(props) {
    super(props);
    this.state = {
      treeData: props.initialTreeData,
      margin: props.initialMargin,
      treeHeight: props.initialTreeHeight,
      treeWidth: props.initialTreeWidth
    }
  }

  // This function is called after all the Tree and Link componentDidMount functions have been called.
  componentDidMount() {
    ipcRenderer.on('direc-schema', (e,arg)=>{
      this.updateTreeData(arg);
    })

    // Reset the tree height and width if needed?
    // Would it be better to use a ref rather than an id?
  }

  updateTreeData(newSchema) {
    this.setState({
      treeData: newSchema
    });
  }

  render() {
    var duration = 450; // We may want to make this a prop.

    // Create a tree layout.
    var tree = d3.layout.tree()
    // The first argument below is the maximum x-coordinate D3 will assign.
    // The second argument is the maximum y-coordinate.
    // We're switching width and height here because d3 by default makes trees that branch vertically, and we want a tree that branches horizontally.
    // In other words, nodes that are on the same level will have the same y-coordinate but different x-coordinates.
      .size([this.state.treeHeight, this.state.treeWidth]);

    // Create a diagonal generator, a type of path data generator.
    var diagonal = d3.svg.diagonal()
    // Isaac: I don't completely understand the projection yet.
      .projection(function(d) { return [d.y, d.x]; });

    // We know that the first node in the array is the root of the tree. Let's designate its initial coordinates - where it should enter.
    var root = this.state.treeData[0];
    root.x0 = this.state.treeHeight / 2;
    root.y0 = 0;

    // The next line creates and returns an array of nodes associated with the specified root node. (The returned array is basically a flattened version of treeData.)
    // D3 tree nodes always have parent, child, depth, x, and y properties.
    // Before the next line runs, each node has children, level, name, and value properties.
    // After the next line runs, each node also has parent, depth, x, and y properties.
    // We will pass one node from this array to each Tree as props.data.
    // ***Do we want to end the next line with reverse to put the root node at the end?
    var nodes = tree.nodes(root),
      // This line creates and returns an array of objects representing all parent-child links in the nodes array we just created.
      linkSelection = tree.links(nodes);

    // Determine how many levels the tree contains.
    for (var currentNode = root, maxDepth = 0;
      currentNode.children;
      currentNode = currentNode.children[0], maxDepth ++);

    var levelOffset = this.state.treeHeight / maxDepth;

    nodes.forEach(function(d) {
      // Update the node's y-coordinate based on its depth.
      d.y = d.depth * levelOffset;
      // If the node has a parent, set the node's initial coordinates to the parent's initial coordinates.
      // *** Does this make sense?
      if (d.parent) {
        d.x0 = d.parent.x0;
        d.y0 = d.parent.y0;
      }
    });

    // I think it makes sense to the use target.name as an id, because no two links should ever point to the same target.
    // If needed, though, we could use {link.source.name + '/'  link.target.name} instead.
    var links = linkSelection && linkSelection.map((link) => {
      return (<Link key={link.target.name} data={link} diagonal={diagonal} duration={duration} />)
    });

    var trees = nodes && nodes.map((node) => {
      return (<Tree key={node.name} data={node} duration={duration} />);
    });

    console.log('Rendering. Latest update: level offset');

    var translationValue = `translate(${this.state.margin.left}, ${this.state.margin.top})`;

    // Do I need to set SVG height below? Is that even possible? Or will the SVG resize to fit the inner g's inside it? (It doesn't look like it's expanding to fit the tree layout.)
    // This StackOverflow response may help:
    // http://stackoverflow.com/questions/8919076/how-to-make-a-svg-element-expand-or-contract-to-its-parent-container
    return(

        <svg width='100%' height='100%' viewBox='0 0 660 200' preserveAspectRatio='none'>
          <g transform={translationValue}>
            {links}
            {trees}
          </g>
        </svg>

    )
  }
}

HalfwayFinishedStructureAnimation.defaultProps = {
  initialTreeData: treeData, // To start with an empty tree: [{}]
  initialMargin: {top: 0, right: 20, bottom: 0, left: 90},
  initialTreeHeight: 200,
  initialTreeWidth: 550
}
<commit_msg>On initial load and when you run a command, the tree expands to fill the animation area horizontally.<commit_after>import React, {Component} from 'react';
import treeData from './../AnimationData/treeStructure';

// Tree and Link are two new components used by HalfwayFinishedStructureAnimation.
import Tree from './Tree';
import Link from './Link';

var d3 = require('d3');
var ReactDOM = require('react-dom');

// My goal in creating HalfwayFinishedStructureAnimation was to make React responsible for DOM structure (adding and removing elements) and to make D3 responsible for styling, as described in this blog post:
// https://medium.com/@sxywu/on-d3-react-and-a-little-bit-of-flux-88a226f328f3#.ztcxqykek

// We still need to handle window resizes. Here are some useful resources:
// http://eyeseast.github.io/visible-data/2013/08/28/responsive-charts-with-d3/
// http://bl.ocks.org/mbostock/3019563

export default class HalfwayFinishedStructureAnimation extends Component {

  constructor(props) {
    super(props);
    this.state = {
      treeData: props.initialTreeData,
      margin: props.initialMargin,
      treeHeight: props.initialTreeHeight,
      treeWidth: props.initialTreeWidth
    }
  }

  // This function is called after all the Tree and Link componentDidMount functions have been called.
  componentDidMount() {
    ipcRenderer.on('direc-schema', (e,arg)=>{
      this.updateTreeData(arg);
    })

    // Reset the tree height and width if needed?
    // Would it be better to use a ref rather than an id?
  }

  updateTreeData(newSchema) {
    this.setState({
      treeData: newSchema
    });
  }

  render() {
    var duration = 450; // We may want to make this a prop.

    // Create a tree layout.
    var tree = d3.layout.tree()
    // The first argument below is the maximum x-coordinate D3 will assign.
    // The second argument is the maximum y-coordinate.
    // We're switching width and height here because d3 by default makes trees that branch vertically, and we want a tree that branches horizontally.
    // In other words, nodes that are on the same level will have the same y-coordinate but different x-coordinates.
      .size([this.state.treeHeight, this.state.treeWidth]);

    // Create a diagonal generator, a type of path data generator.
    var diagonal = d3.svg.diagonal()
    // Isaac: I don't completely understand the projection yet.
      .projection(function(d) { return [d.y, d.x]; });

    // We know that the first node in the array is the root of the tree. Let's designate its initial coordinates - where it should enter.
    var root = this.state.treeData[0];
    root.x0 = this.state.treeHeight / 2;
    root.y0 = 0;

    // The next line creates and returns an array of nodes associated with the specified root node. (The returned array is basically a flattened version of treeData.)
    // D3 tree nodes always have parent, child, depth, x, and y properties.
    // Before the next line runs, each node has children, level, name, and value properties.
    // After the next line runs, each node also has parent, depth, x, and y properties.
    // We will pass one node from this array to each Tree as props.data.
    // ***Do we want to end the next line with reverse to put the root node at the end?
    var nodes = tree.nodes(root),
      // This line creates and returns an array of objects representing all parent-child links in the nodes array we just created.
      linkSelection = tree.links(nodes);

    // Determine how many levels the tree contains.
    for (var currentNode = root, maxDepth = 0;
      currentNode.children;
      currentNode = currentNode.children[0], maxDepth ++);

    nodes.forEach(function(d) {
      // The default y-coordinates provided by d3.tree will make the tree stretch all the way across the screen.
      // We want to compress the tree a bit so that there's room for file/directory names to the right of the deepest level.
      d.y *= .8;

      // We could scale d.x too to prevent the svg from cutting off notes at the top and bottom of a node column.

      // If the node has a parent, set the node's initial coordinates to the parent's initial coordinates.
      // *** Does this make sense?
      if (d.parent) {
        d.x0 = d.parent.x0;
        d.y0 = d.parent.y0;
      }
    });

    // I think it makes sense to the use target.name as an id, because no two links should ever point to the same target.
    // If needed, though, we could use {link.source.name + '/'  link.target.name} instead.
    var links = linkSelection && linkSelection.map((link) => {
      return (<Link key={link.target.name} data={link} diagonal={diagonal} duration={duration} />)
    });

    var trees = nodes && nodes.map((node) => {
      return (<Tree key={node.name} data={node} duration={duration} />);
    });

    console.log('Rendering. Latest update: d.y *= .8');

    var translationValue = `translate(${this.state.margin.left}, ${this.state.margin.top})`;

    // Do I need to set SVG height below? Is that even possible? Or will the SVG resize to fit the inner g's inside it? (It doesn't look like it's expanding to fit the tree layout.)
    // This StackOverflow response may help:
    // http://stackoverflow.com/questions/8919076/how-to-make-a-svg-element-expand-or-contract-to-its-parent-container
    return(

        <svg width='100%' height='100%' viewBox='0 0 660 200' preserveAspectRatio='none'>
          <g transform={translationValue}>
            {links}
            {trees}
          </g>
        </svg>

    )
  }
}

HalfwayFinishedStructureAnimation.defaultProps = {
  initialTreeData: treeData, // To start with an empty tree: [{}]
  initialMargin: {top: 0, right: 20, bottom: 0, left: 90},
  initialTreeHeight: 200,
  initialTreeWidth: 550
}
<|endoftext|>


<commit_before><commit_msg>button_injector can determine if viewing a file to download<commit_after><|endoftext|>