<commit_before>/**
 * @class Utils provides a number of utility functions which are handy
 *        around the app.
 *
 * @property {Boolean} debugMode This boolean can be changed from true to
 *           false for production mode to speed up the app.
 * @property {Boolean} productionMode This boolean can be changed from false to
 *           true to point the app to production servers rather than development servers.
 * @constructs
 */

var Utils = Utils || {};

/*
 * Turn this off to make the app run faster. If it is on, you can see a lot of
 * debugging output whcih can be useful as a developer to find out what the app
 * is doing, how control flows through the app and also to debug new features or
 * bugs.
 */
Utils.debugMode = false;

/**
 * The address of the TouchDB-Android database on the Android.
 */
Utils.touchUrl = "http://localhost:8888/db";

/**
 * The address of the PouchDB database on the browser.
 */
Utils.pouchUrl = "idb://db";

/**
 * The address of the TouchDB-Android database on the Android.
 * @Deprecated now using pouchUrl for all
 */
//Utils.activityFeedTouchUrl = "http://localhost:8888/activity_feed_db";

/**
 * The address of the PouchDB database on the browser.
 * @Deprecated now using pouchUrl for all
 */
//Utils.activityFeedPouchUrl = "idb://activity_feed_db";

/**
 * A message for users if they need help which brings them to our contact us form
 */
Utils.contactUs = "Contact Us";

/**
 * Console logs out, if not on Internet Explorer. Only logs out if
 * debugMode is true.
 */
Utils.debug = function(message, secondmessage) {
	if(navigator.appName == 'Microsoft Internet Explorer') {
		return;
	}
	if(this.debugMode) {
		console.log(message);
		if(secondmessage){
	    console.log(secondmessage);
		}
	}
};

/**
 * Simple Pub/sub plugin to create a decoupled javascript app
 * http://answers.oreilly.com/topic/2190-two-examples-of-the-observer-pattern-in-javascript/
 *
 * How to use it:
var hub = {};
makePublisher(hub);

hub.subscribe(
  "probeCommand",
  function(arg) {
    debug("Receiving command " + arg);
  }, self);

hub.publish(
    "probeResponse",
"Command not valid.")

var right = document.getElementById("rightSideReading");
hub.unsubscribe('probeResponse', null, center);
hub.subscribe('probeResponse', function(arg) {
  debug("Putting probe's response in the right input field.");
  var cleanedMessage = arg.replace(/[^0-9]/g, "");
  debug("Cleaned message: " + arg + " to: " + cleanedMessage);
  right.value = cleanedMessage;
}, right);

hub.subscribe('changeLogo',function(arg){
  debug("Putting the logo from the user. This is the path: "+ arg);
  img.setAttribute("src",storage.getItem("userLogo"));
},img);
 *
 */

Utils.publisher = {
  subscribers : {
    any : []
  },
  subscribe : function(type, fn, context) {
    type = type || 'any';
    fn = typeof fn === "function" ? fn : context[fn];

    if (typeof this.subscribers[type] === "undefined") {
      this.subscribers[type] = [];
    }
    this.subscribers[type].push({
      fn : fn,
      context : context || this
    });
  },
  unsubscribe : function(type, fn, context) {
    this.visitSubscribers('unsubscribe', type, fn, context);
  },
  publish : function(type, publication) {
    this.visitSubscribers('publish', type, publication);
  },
  visitSubscribers : function(action, type, arg, context) {
    var pubtype = type || 'any', subscribers = this.subscribers[pubtype], i, max = subscribers ? subscribers.length
        : 0;

    for (i = 0; i < max; i += 1) {
      if (action === 'publish') {
        if(subscribers[i]){
          //TODO there is a bug with the subscribers they are getting lost, and it is trying to call fn of undefiend. this is a workaround until we figure out why subscribers are getting lost.
          subscribers[i].fn.call(subscribers[i].context, arg);
        }
      } else {
        try{
          if (subscribers[i].context === context) {
            var removed = subscribers.splice(i, 1);
            Utils.debug("Removed subscriber from "+type, removed);
          } else {
            Utils.debug(type+" keeping subscriber " + i);
          }
        }catch(e){
          Utils.debug("problem visiting Subscriber "+i)
        }
      }
    }
  }
};
Utils.makePublisher = function(o) {
  var i;
  for (i in Utils.publisher) {
    if (Utils.publisher.hasOwnProperty(i)
        && typeof Utils.publisher[i] === "function") {
      o[i] = Utils.publisher[i];
    }
  }
  o.subscribers = {
    any : []
  };
};

/**
 * http://www.w3schools.com/js/js_cookies.asp
 * name of the cookie, the value of the cookie, and the number of days until the cookie expires.
 *
 * @param c_name
 * @param value
 * @param exdays
 */
Utils.setCookie = function(c_name, value, exdays){
  var exdate = new Date();
  exdate.setDate(exdate.getDate() + exdays);
  var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
  document.cookie = c_name + "=" + c_value;
};
Utils.getCookie = function(c_name){
  var i, x, y, ARRcookies = document.cookie.split(";");
  for (i = 0; i < ARRcookies.length; i++){
    x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
    y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
    x = x.replace(/^\s+|\s+$/g,"");
    if (x == c_name){
      return unescape(y);
    }
  }
};

/**
 * Detects whether we are running offline on an Android app.
 *
 * Note: to Android app developers, append this to your user agent string to
 * take advantage of the offline functionality of this app.
 *
 * @returns {Boolean} true if using offline Android
 */
Utils.androidApp = function() {
	return navigator.userAgent.indexOf("OfflineAndroidApp") > -1;
};

/**
 * Detects whether we are running offline in chrome extension.
 *
 * @returns {Boolean} true if using a Chrome Extension
 */
Utils.chromeApp = function() {
	return window.location.href.indexOf("chrome-extension") > -1;
};

/**
 * If not running offline on an android or in a chrome extension,
 * assume we are online.
 *
 * @returns {Boolean} true if not on offline Android or on a Chrome
 *          Extension
 */
Utils.onlineOnly = function() {
	return !this.androidApp() && !this.chromeApp();
};

Utils.getVersion = function(callback) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open('GET', 'manifest.json');
  xmlhttp.onload = function (e) {
      var manifest = JSON.parse(xmlhttp.responseText);
      callback(manifest.version);
  };
  xmlhttp.send(null);
};

/*
 * JavaScript Pretty Date
 * Copyright (c) 2011 John Resig (ejohn.org)
 * Licensed under the MIT and GPL licenses.
 */

// Takes an ISO time and returns a string representing how
// long ago the date represents.

//modified by FieldDB team to take in Greenwich time which is what we are using for our time stamps so that users in differnt time zones will get real times, not strangely futureistic times
//we have been using JSON.stringify(new Date()) to create our timestamps instead of unix epoch seconds (not sure why we werent using unix epoch), so this function is modified from the original in that it expects dates that were created using
//JSON.stringify(new Date())
Utils.prettyDate = function(time){
  if(!time){
    return undefined;
  }
  time = time.replace(/"/g,"");
  var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," "));
  var greenwichtimenow = JSON.stringify(new Date()).replace(/"/g,"");
  var greenwichdate = new Date((greenwichtimenow || "").replace(/-/g,"/").replace(/[TZ]/g," "));
  var  diff = ((greenwichdate.getTime() - date.getTime()) / 1000);
  var  day_diff = Math.floor(diff / 86400);

  if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ){
    return undefined;
  }

  return day_diff == 0 && (
      diff < 60 && "just now" ||
      diff < 120 && "1 minute ago" ||
      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
      diff < 7200 && "1 hour ago" ||
      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
    day_diff == 1 && "Yesterday" ||
    day_diff < 7 && day_diff + " days ago" ||
    day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
};
Utils.prettyTimestamp = function(timestamp){
  var date = new Date(timestamp);
  var greenwichtimenow = new Date();
  var  diff = ((greenwichtimenow.getTime() - date.getTime()) / 1000);
  var  day_diff = Math.floor(diff / 86400);

  if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ){
    return;
  }

  return day_diff == 0 && (
      diff < 60 && "just now" ||
      diff < 120 && "1 minute ago" ||
      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
      diff < 7200 && "1 hour ago" ||
      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
    day_diff == 1 && "Yesterday" ||
    day_diff < 7 && day_diff + " days ago" ||
    day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
};
//
//// If jQuery is included in the page, adds a jQuery plugin to handle it as well
//if ( typeof jQuery != "undefined" )
//  jQuery.fn.prettyDate = function(){
//    return this.each(function(){
//      var date = prettyDate(this.title);
//      if ( date )
//        jQuery(this).text( date );
//    });
//  };

Utils.catchAndThrowAjaxError = function(e, xhr, settings, exception){
  console.log('\tAjax error in: ' + settings.url + ' \n'+'error:\n' + xhr.responseText );
  window.hub.publish("ajaxError",exception);
//  throw exception; //this doesnt work, cant use normal try catches, instead using pub sub
};

Utils.catchAndThrowPouchError = function(e){
  console.log('\tCaught Error : ', e );
  if(e){
    window.hub.publish("pouchError", e);
  }
//  throw e; //this doesnt work, cant use normal try catches, instead using pub sub
};
<commit_msg>turning debugging<commit_after>/**
 * @class Utils provides a number of utility functions which are handy
 *        around the app.
 *
 * @property {Boolean} debugMode This boolean can be changed from true to
 *           false for production mode to speed up the app.
 * @property {Boolean} productionMode This boolean can be changed from false to
 *           true to point the app to production servers rather than development servers.
 * @constructs
 */

var Utils = Utils || {};

/*
 * Turn this off to make the app run faster. If it is on, you can see a lot of
 * debugging output whcih can be useful as a developer to find out what the app
 * is doing, how control flows through the app and also to debug new features or
 * bugs.
 */
Utils.debugMode = true;

/**
 * The address of the TouchDB-Android database on the Android.
 */
Utils.touchUrl = "http://localhost:8888/db";

/**
 * The address of the PouchDB database on the browser.
 */
Utils.pouchUrl = "idb://db";

/**
 * The address of the TouchDB-Android database on the Android.
 * @Deprecated now using pouchUrl for all
 */
//Utils.activityFeedTouchUrl = "http://localhost:8888/activity_feed_db";

/**
 * The address of the PouchDB database on the browser.
 * @Deprecated now using pouchUrl for all
 */
//Utils.activityFeedPouchUrl = "idb://activity_feed_db";

/**
 * A message for users if they need help which brings them to our contact us form
 */
Utils.contactUs = "Contact Us";

/**
 * Console logs out, if not on Internet Explorer. Only logs out if
 * debugMode is true.
 */
Utils.debug = function(message, secondmessage) {
	if(navigator.appName == 'Microsoft Internet Explorer') {
		return;
	}
	if(this.debugMode) {
		console.log(message);
		if(secondmessage){
	    console.log(secondmessage);
		}
	}
};

/**
 * Simple Pub/sub plugin to create a decoupled javascript app
 * http://answers.oreilly.com/topic/2190-two-examples-of-the-observer-pattern-in-javascript/
 *
 * How to use it:
var hub = {};
makePublisher(hub);

hub.subscribe(
  "probeCommand",
  function(arg) {
    debug("Receiving command " + arg);
  }, self);

hub.publish(
    "probeResponse",
"Command not valid.")

var right = document.getElementById("rightSideReading");
hub.unsubscribe('probeResponse', null, center);
hub.subscribe('probeResponse', function(arg) {
  debug("Putting probe's response in the right input field.");
  var cleanedMessage = arg.replace(/[^0-9]/g, "");
  debug("Cleaned message: " + arg + " to: " + cleanedMessage);
  right.value = cleanedMessage;
}, right);

hub.subscribe('changeLogo',function(arg){
  debug("Putting the logo from the user. This is the path: "+ arg);
  img.setAttribute("src",storage.getItem("userLogo"));
},img);
 *
 */

Utils.publisher = {
  subscribers : {
    any : []
  },
  subscribe : function(type, fn, context) {
    type = type || 'any';
    fn = typeof fn === "function" ? fn : context[fn];

    if (typeof this.subscribers[type] === "undefined") {
      this.subscribers[type] = [];
    }
    this.subscribers[type].push({
      fn : fn,
      context : context || this
    });
  },
  unsubscribe : function(type, fn, context) {
    this.visitSubscribers('unsubscribe', type, fn, context);
  },
  publish : function(type, publication) {
    this.visitSubscribers('publish', type, publication);
  },
  visitSubscribers : function(action, type, arg, context) {
    var pubtype = type || 'any', subscribers = this.subscribers[pubtype], i, max = subscribers ? subscribers.length
        : 0;

    for (i = 0; i < max; i += 1) {
      if (action === 'publish') {
        if(subscribers[i]){
          //TODO there is a bug with the subscribers they are getting lost, and it is trying to call fn of undefiend. this is a workaround until we figure out why subscribers are getting lost.
          subscribers[i].fn.call(subscribers[i].context, arg);
        }
      } else {
        try{
          if (subscribers[i].context === context) {
            var removed = subscribers.splice(i, 1);
            Utils.debug("Removed subscriber from "+type, removed);
          } else {
            Utils.debug(type+" keeping subscriber " + i);
          }
        }catch(e){
          Utils.debug("problem visiting Subscriber "+i)
        }
      }
    }
  }
};
Utils.makePublisher = function(o) {
  var i;
  for (i in Utils.publisher) {
    if (Utils.publisher.hasOwnProperty(i)
        && typeof Utils.publisher[i] === "function") {
      o[i] = Utils.publisher[i];
    }
  }
  o.subscribers = {
    any : []
  };
};

/**
 * http://www.w3schools.com/js/js_cookies.asp
 * name of the cookie, the value of the cookie, and the number of days until the cookie expires.
 *
 * @param c_name
 * @param value
 * @param exdays
 */
Utils.setCookie = function(c_name, value, exdays){
  var exdate = new Date();
  exdate.setDate(exdate.getDate() + exdays);
  var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
  document.cookie = c_name + "=" + c_value;
};
Utils.getCookie = function(c_name){
  var i, x, y, ARRcookies = document.cookie.split(";");
  for (i = 0; i < ARRcookies.length; i++){
    x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
    y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
    x = x.replace(/^\s+|\s+$/g,"");
    if (x == c_name){
      return unescape(y);
    }
  }
};

/**
 * Detects whether we are running offline on an Android app.
 *
 * Note: to Android app developers, append this to your user agent string to
 * take advantage of the offline functionality of this app.
 *
 * @returns {Boolean} true if using offline Android
 */
Utils.androidApp = function() {
	return navigator.userAgent.indexOf("OfflineAndroidApp") > -1;
};

/**
 * Detects whether we are running offline in chrome extension.
 *
 * @returns {Boolean} true if using a Chrome Extension
 */
Utils.chromeApp = function() {
	return window.location.href.indexOf("chrome-extension") > -1;
};

/**
 * If not running offline on an android or in a chrome extension,
 * assume we are online.
 *
 * @returns {Boolean} true if not on offline Android or on a Chrome
 *          Extension
 */
Utils.onlineOnly = function() {
	return !this.androidApp() && !this.chromeApp();
};

Utils.getVersion = function(callback) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open('GET', 'manifest.json');
  xmlhttp.onload = function (e) {
      var manifest = JSON.parse(xmlhttp.responseText);
      callback(manifest.version);
  };
  xmlhttp.send(null);
};

/*
 * JavaScript Pretty Date
 * Copyright (c) 2011 John Resig (ejohn.org)
 * Licensed under the MIT and GPL licenses.
 */

// Takes an ISO time and returns a string representing how
// long ago the date represents.

//modified by FieldDB team to take in Greenwich time which is what we are using for our time stamps so that users in differnt time zones will get real times, not strangely futureistic times
//we have been using JSON.stringify(new Date()) to create our timestamps instead of unix epoch seconds (not sure why we werent using unix epoch), so this function is modified from the original in that it expects dates that were created using
//JSON.stringify(new Date())
Utils.prettyDate = function(time){
  if(!time){
    return undefined;
  }
  time = time.replace(/"/g,"");
  var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," "));
  var greenwichtimenow = JSON.stringify(new Date()).replace(/"/g,"");
  var greenwichdate = new Date((greenwichtimenow || "").replace(/-/g,"/").replace(/[TZ]/g," "));
  var  diff = ((greenwichdate.getTime() - date.getTime()) / 1000);
  var  day_diff = Math.floor(diff / 86400);

  if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ){
    return undefined;
  }

  return day_diff == 0 && (
      diff < 60 && "just now" ||
      diff < 120 && "1 minute ago" ||
      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
      diff < 7200 && "1 hour ago" ||
      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
    day_diff == 1 && "Yesterday" ||
    day_diff < 7 && day_diff + " days ago" ||
    day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
};
Utils.prettyTimestamp = function(timestamp){
  var date = new Date(timestamp);
  var greenwichtimenow = new Date();
  var  diff = ((greenwichtimenow.getTime() - date.getTime()) / 1000);
  var  day_diff = Math.floor(diff / 86400);

  if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ){
    return;
  }

  return day_diff == 0 && (
      diff < 60 && "just now" ||
      diff < 120 && "1 minute ago" ||
      diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
      diff < 7200 && "1 hour ago" ||
      diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
    day_diff == 1 && "Yesterday" ||
    day_diff < 7 && day_diff + " days ago" ||
    day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
};
//
//// If jQuery is included in the page, adds a jQuery plugin to handle it as well
//if ( typeof jQuery != "undefined" )
//  jQuery.fn.prettyDate = function(){
//    return this.each(function(){
//      var date = prettyDate(this.title);
//      if ( date )
//        jQuery(this).text( date );
//    });
//  };

Utils.catchAndThrowAjaxError = function(e, xhr, settings, exception){
  console.log('\tAjax error in: ' + settings.url + ' \n'+'error:\n' + xhr.responseText );
  window.hub.publish("ajaxError",exception);
//  throw exception; //this doesnt work, cant use normal try catches, instead using pub sub
};

Utils.catchAndThrowPouchError = function(e){
  console.log('\tCaught Error : ', e );
  if(e){
    window.hub.publish("pouchError", e);
  }
//  throw e; //this doesnt work, cant use normal try catches, instead using pub sub
};
<|endoftext|>


<commit_before>/*
 * debugger.io: An interactive web scripting sandbox
 *
 * dom.js: DOM helpers
 */

define([
  'config', 'utils', 'jquery', 'underscore',
  'backbone', 'bus'
],
function(config, utils, $, _, Backbone, bus) {
  'use strict';

  var dom = utils.module('dom');

  bus.init(function(av) {
    utils.log('init dom module');

    var $blank = $('#blank');
    var $button = $('<button></button>');
    $blank.empty().append($button);

    $('body').toggleClass('alt', !!$button.width());
    $blank.empty();
  });

  /**
   * Cache DOM elements by id and class name onto another object
   *
   * @param {Object} context - object to save references to
   * @param {jQuery} $source - source set within which to find elements
   * @param {Object} elements - { 'by_id' => Array, 'by_class' => Array }
   * @return {Object} context used
   */
  dom.cache = function(context, $source, elements) {
    context = context || {};

    // #output cached to this.$output
    _.each(utils.ensure_array(elements.by_id), _.bind(function(id) {
      this['$' + _.underscored(id)] = $source.find('#' + id);
    }, context));

    // .panel-options elements cached to this.$panel_options
    _.each(utils.ensure_array(elements.by_class), _.bind(function(c) {
      this['$' + _.pluralize(_.underscored(c))] = $source.find('.' + c);
    }, context));

    // '[name="username"]' cached to this.$username
    _.each(utils.ensure_array(elements.by_name), _.bind(function(n) {
      this['$' + _.underscored(n)] = $source.find(_.sprintf('[name="%s"]', n));
    }, context));

    return context;
  };

  /**
   * Stop listening to events on a Backbone View, but empty it instead of
   * removing it, as View.remove would do
   *
   * @param {Backbone.View} view - view to destroy
   */
  dom.destroy_view = function(view) {
    if (!(view instanceof Backbone.View)) { return; }
    utils.log('destroying view:', view.template);

    view.trigger('destroy');
    view.$el.empty();
    view.stopListening();
    view.undelegateEvents();
    bus.off_for(view);
  };

  /**
   * Get a *rounded* approximation of the width of an element, as a percentage
   *
   * @param {jQuery} $element - some element in the DOM
   * @return {String} percentage string
   */
  dom.get_percent_width = function($element) {
    var width = $element.width();
    var parentWidth = $element.parent().width();
    return Math.round((width / parentWidth) * 100) + '%';
  };

  /**
   * Get a *rounded* approximation of the height of an element, as a percentage
   *
   * @param {jQuery} $element - some element in the DOM
   * @return {String} percentage string
   */
  dom.get_percent_height = function($element) {
    var height = $element.height();
    var parentHeight = $element.parent().height();
    return Math.round((height / parentHeight) * 100) + '%';
  };

  /**
   * Determine is a node is currently detached from the DOM
   *
   * @param {jQuery} $element - some element which may or may not be in the DOM
   * @param {Document} [doc] - document to check, defaults to window.document
   * @return {Boolean} true if $element is not in the DOM, false otherwise
   */
  dom.is_detached = function($element, doc) {
    doc = doc || window.document;
    var docEl = doc.documentElement;

    return !$element.closest(docEl).length;
  };

  /**
   * (Re)initialize an element with a nanoScrollerJS scrollbar
   *
   * @param {jQuery} $element - some .nano element in the DOM
   */
  dom.init_scrollbar = function($element) {
    if (!$element.hasClass('nano')) {
      return console.error($element, 'already has scrollbar');
    }

    if (!$element.children('.content').length) {
      return console.error($element, 'has no content to scroll');
    }

    // remove the old nanoscroller property if the content has been replaced
    if ($element[0].nanoscroller) {
      var $nanoContent = $element[0].nanoscroller.$content;
      if (dom.is_detached($nanoContent)) {
        $element.removeClass('has-scrollbar');
        $element[0].nanoscroller = null;
      }
    }

    $element.nanoScroller({ alwaysVisible: true });
  };

  /**
   * Transition an element, then (re)initialize a nanoScrollerJS scrollbar
   *
   * @param {jQuery} $element - some .nano element in the DOM
   * @param {Object} [opts] - options to $.fn.transition
   * @param {Function} [callback] - callback to $.fn.transition
   */
  dom.transition_with_scrollbar = function($element, opts, callback) {
      opts = opts || {};

      $element.transition(opts, 'fast', function() {
        dom.init_scrollbar($element);
        _.isFunction(callback) && callback.call($element[0]);
      });
  };

  /**
   * Determine if an element is overflowing itself or a parent
   *
   * @param {jQuery} $element - some element in the DOM
   * @param {String} [closest] - compare $element to $element.closest(closest)
   * @return {Boolean} true if $element is overflowing, false otherwise
   */
  dom.is_overflowing = function($element, closest) {
    if (dom.is_detached($element)) { return false; }

    var $compare = closest ? $element.closest(closest) : $element;
    return $element[0].scrollHeight > $compare[0].offsetHeight;
  };

  /**
   * Determine if a nanoScrollerJS content area is overflowing
   *
   * @param {jQuery} $element - some element within a nanoScrollerJS scrollbar
   * @return {Boolean} true if $element is overflowing, false otherwise
   */
  dom.is_overflowing_with_scrollbar = function($element) {
    return dom.is_overflowing($element, '.nano');
  };

  /**
   * Get a CSS property from an enabled stylesheet
   *
   * @param {String} selector - CSS selector
   * @return {Object} CSS property map matching selector
   */
  dom.css = function(selector) {
    var match;
    selector = utils.minify_css_selector(selector);

    // start with the last stylesheet
    var stylesheets = _.toArray(document.styleSheets).reverse();

    _.every(stylesheets, function(stylesheet) {
      // ignore disabled stylesheets
      if (stylesheet.disabled) { return true; } // continue

      var rules = stylesheet.cssRules || stylesheet.rules || [];
      match = _.find(rules, function(rule) {
        // find matching minified selector
        return utils.minify_css_selector(rule.selectorText) === selector;
      });

      return !match;
    });

    // always return an object
    if (!match) { return {}; }

    // remove selector and braces, leaving only the CSS properties
    var rule = match.cssText.replace(/^.*{\s*/, '').replace(/\s*}\s*$/, '');

    // convert the property string to an object
    return _.object(_.map(rule.split(';'), function(property) {
      var map = _.map(property.split(':'), _.clean);
      return map.length === 2 ? map : null;
    }));
  };

  /**
   * Scroll a nanoScrollerJS container to a specified scrollTop
   *
   * @param {jQuery} $element - some element within a nanoScrollerJS scrollbar
   * @param {Number | String} [value] - position to scroll to, defaults to 'top'
   */
  dom.scrollbar_scroll_top = function($element, value) {
    var $nano = $element.closest('.nano');
    if (!$nano.length) { return; }

    value = value || 'top';
    $nano.nanoScroller({ scrollTop: value });
  };

  /**
   *
   * @param {jQuery} $cycle -
   * @param {String} label -
   */
  dom.transition_button_label = function($cycle, label) {
    $cycle = utils.ensure_jquery($cycle);

    // set a fixed width now, change the label and transition
    // to an "auto-esque" state
    var width = $cycle.outerWidth();
    $cycle.css({ 'min-width': width, 'max-width': width });

    $cycle.text(label);

    // HACK: wait for a repaint
    _.delay(function() {
      $cycle.stop().transition({ 'min-width': 0, 'max-width': 300 });
    }, 10);
  };

  return dom;
});
<commit_msg>Add dom.set_templated_placeholder<commit_after>/*
 * debugger.io: An interactive web scripting sandbox
 *
 * dom.js: DOM helpers
 */

define([
  'config', 'utils', 'jquery', 'underscore',
  'backbone', 'bus'
],
function(config, utils, $, _, Backbone, bus) {
  'use strict';

  var dom = utils.module('dom');

  bus.init(function(av) {
    utils.log('init dom module');

    var $blank = $('#blank');
    var $button = $('<button></button>');
    $blank.empty().append($button);

    $('body').toggleClass('alt', !!$button.width());
    $blank.empty();
  });

  /**
   * Cache DOM elements by id and class name onto another object
   *
   * @param {Object} context - object to save references to
   * @param {jQuery} $source - source set within which to find elements
   * @param {Object} elements - { 'by_id' => Array, 'by_class' => Array }
   * @return {Object} context used
   */
  dom.cache = function(context, $source, elements) {
    context = context || {};

    // #output cached to this.$output
    _.each(utils.ensure_array(elements.by_id), _.bind(function(id) {
      this['$' + _.underscored(id)] = $source.find('#' + id);
    }, context));

    // .panel-options elements cached to this.$panel_options
    _.each(utils.ensure_array(elements.by_class), _.bind(function(c) {
      this['$' + _.pluralize(_.underscored(c))] = $source.find('.' + c);
    }, context));

    // '[name="username"]' cached to this.$username
    _.each(utils.ensure_array(elements.by_name), _.bind(function(n) {
      this['$' + _.underscored(n)] = $source.find(_.sprintf('[name="%s"]', n));
    }, context));

    return context;
  };

  /**
   * Stop listening to events on a Backbone View, but empty it instead of
   * removing it, as View.remove would do
   *
   * @param {Backbone.View} view - view to destroy
   */
  dom.destroy_view = function(view) {
    if (!(view instanceof Backbone.View)) { return; }
    utils.log('destroying view:', view.template);

    view.trigger('destroy');
    view.$el.empty();
    view.stopListening();
    view.undelegateEvents();
    bus.off_for(view);
  };

  /**
   * Get a *rounded* approximation of the width of an element, as a percentage
   *
   * @param {jQuery} $element - some element in the DOM
   * @return {String} percentage string
   */
  dom.get_percent_width = function($element) {
    var width = $element.width();
    var parentWidth = $element.parent().width();
    return Math.round((width / parentWidth) * 100) + '%';
  };

  /**
   * Get a *rounded* approximation of the height of an element, as a percentage
   *
   * @param {jQuery} $element - some element in the DOM
   * @return {String} percentage string
   */
  dom.get_percent_height = function($element) {
    var height = $element.height();
    var parentHeight = $element.parent().height();
    return Math.round((height / parentHeight) * 100) + '%';
  };

  /**
   * Determine is a node is currently detached from the DOM
   *
   * @param {jQuery} $element - some element which may or may not be in the DOM
   * @param {Document} [doc] - document to check, defaults to window.document
   * @return {Boolean} true if $element is not in the DOM, false otherwise
   */
  dom.is_detached = function($element, doc) {
    doc = doc || window.document;
    var docEl = doc.documentElement;

    return !$element.closest(docEl).length;
  };

  /**
   * (Re)initialize an element with a nanoScrollerJS scrollbar
   *
   * @param {jQuery} $element - some .nano element in the DOM
   */
  dom.init_scrollbar = function($element) {
    if (!$element.hasClass('nano')) {
      return console.error($element, 'already has scrollbar');
    }

    if (!$element.children('.content').length) {
      return console.error($element, 'has no content to scroll');
    }

    // remove the old nanoscroller property if the content has been replaced
    if ($element[0].nanoscroller) {
      var $nanoContent = $element[0].nanoscroller.$content;
      if (dom.is_detached($nanoContent)) {
        $element.removeClass('has-scrollbar');
        $element[0].nanoscroller = null;
      }
    }

    $element.nanoScroller({ alwaysVisible: true });
  };

  /**
   * Transition an element, then (re)initialize a nanoScrollerJS scrollbar
   *
   * @param {jQuery} $element - some .nano element in the DOM
   * @param {Object} [opts] - options to $.fn.transition
   * @param {Function} [callback] - callback to $.fn.transition
   */
  dom.transition_with_scrollbar = function($element, opts, callback) {
      opts = opts || {};

      $element.transition(opts, 'fast', function() {
        dom.init_scrollbar($element);
        _.isFunction(callback) && callback.call($element[0]);
      });
  };

  /**
   * Determine if an element is overflowing itself or a parent
   *
   * @param {jQuery} $element - some element in the DOM
   * @param {String} [closest] - compare $element to $element.closest(closest)
   * @return {Boolean} true if $element is overflowing, false otherwise
   */
  dom.is_overflowing = function($element, closest) {
    if (dom.is_detached($element)) { return false; }

    var $compare = closest ? $element.closest(closest) : $element;
    return $element[0].scrollHeight > $compare[0].offsetHeight;
  };

  /**
   * Determine if a nanoScrollerJS content area is overflowing
   *
   * @param {jQuery} $element - some element within a nanoScrollerJS scrollbar
   * @return {Boolean} true if $element is overflowing, false otherwise
   */
  dom.is_overflowing_with_scrollbar = function($element) {
    return dom.is_overflowing($element, '.nano');
  };

  /**
   * Get a CSS property from an enabled stylesheet
   *
   * @param {String} selector - CSS selector
   * @return {Object} CSS property map matching selector
   */
  dom.css = function(selector) {
    var match;
    selector = utils.minify_css_selector(selector);

    // start with the last stylesheet
    var stylesheets = _.toArray(document.styleSheets).reverse();

    _.every(stylesheets, function(stylesheet) {
      // ignore disabled stylesheets
      if (stylesheet.disabled) { return true; } // continue

      var rules = stylesheet.cssRules || stylesheet.rules || [];
      match = _.find(rules, function(rule) {
        // find matching minified selector
        return utils.minify_css_selector(rule.selectorText) === selector;
      });

      return !match;
    });

    // always return an object
    if (!match) { return {}; }

    // remove selector and braces, leaving only the CSS properties
    var rule = match.cssText.replace(/^.*{\s*/, '').replace(/\s*}\s*$/, '');

    // convert the property string to an object
    return _.object(_.map(rule.split(';'), function(property) {
      var map = _.map(property.split(':'), _.clean);
      return map.length === 2 ? map : null;
    }));
  };

  /**
   * Scroll a nanoScrollerJS container to a specified scrollTop
   *
   * @param {jQuery} $element - some element within a nanoScrollerJS scrollbar
   * @param {Number | String} [value] - position to scroll to, defaults to 'top'
   */
  dom.scrollbar_scroll_top = function($element, value) {
    var $nano = $element.closest('.nano');
    if (!$nano.length) { return; }

    value = value || 'top';
    $nano.nanoScroller({ scrollTop: value });
  };

  /**
   * Transition the width of a button while changing its label
   *
   * @param {jQuery} $button - button element
   * @param {String} label - new label to set
   */
  dom.transition_button_label = function($button, label) {
    $button = utils.ensure_jquery($button);

    // set a fixed width now, change the label and transition
    // to an "auto-esque" state
    var width = $button.outerWidth();
    $button.css({ 'min-width': width, 'max-width': width });

    $button.text(label);

    // HACK: wait for a repaint
    _.delay(function() {
      $button.stop().transition({ 'min-width': 0, 'max-width': 300 });
    }, 10);
  };

  /**
   * Set a placeholder from a data-placeholder template
   *
   * @param {jQuery} $element - some element with a data-placeholder attribute
   * @param {Array} values - values to pass to _.sprintf
   * @return {String} the new placeholder
   */
  dom.set_templated_placeholder = function($element, values) {
    var placeholder = $element.attr('data-placeholder');
    if (!placeholder) { return; }

    var args = utils.ensure_array(values);
    args.unshift(placeholder);

    placeholder = _.sprintf.apply(null, args);
    $element.attr('placeholder', placeholder);

    return placeholder;
  };

  return dom;
});
<|endoftext|>


<commit_before>(function ( $ ) {
	'use strict';
	var stateFieldId = '_juiceWidgetOptions',

  Juice = {
		widgets: {},
    subscribe: window.amplify.subscribe,
    publish: window.amplify.publish,
    onSubmit: function () {
      var optionsInput = $( '#' + stateFieldId ),
				options = [];

      $.each( Juice.widgets, function ( index, widget ) {
        var element = $( '#' + widget.id ),
          widgetName = widget.widgetName, //element.data( 'ui-widget' ),
          uiWidget = element.data( widgetName ),
					opts = $.extend({}, uiWidget.options);

				$.each( opts, function( label ){
					if( $.inArray( label, widget.encodedOptions ) >= 0 ){
						opts[ label ] = htmlEncode( this );
					}
				});

        options.push({ id: widget.id, widgetName: widgetName, options: opts });
      });

      optionsInput.val( JSON.stringify( options ) );
    }
  },

  registerCss = function () {
    if ( !$( '#_jQueryUICss' ).length ) {
      var href = Juice.cssUrl,
        tag = '<link rel="stylesheet" type="text/css" href="' + href + '" />';
      $( 'head' ).append( tag );
    }
  },

  ready = function () {
    if ( typeof ( window.JSON ) === 'undefined' ) {
      throw new Error( 'Juice requires JSON support. Please ensure json2.js is referenced for downlevel browsers.' );
    }

    if ( !$( '#' + stateFieldId ).length ) {
      $( '<input id="' + stateFieldId + '" name="' + stateFieldId + '" type="hidden" />' )
			  .appendTo( window.theForm ); // theForm is defined by asp.net
    }

    $.each( Juice.widgets, function ( index, widget ) {
      var element = $( '#' + widget.id ),
        widgetName = widget.widgetName,
        events = {};

			if( !widgetName || !$.fn[widgetName] ) {
				return;
			}

			// map the event names to objects, merge with postBacks
			widget.events = $.map( widget.events, function( name ){
				return { name: name };
			});

			widget.postBacks = $.map( widget.postBacks, function( pb ){
				pb.causesPostBack = true;
				return pb;
			});

			widget.events = widget.events.concat( widget.postBacks );

      $.each( widget.events, function () {
        var event = this;
        events[event.name] = function ( jqEvent, ui ) {
        	var args = [].slice.call( arguments, 0 ),
            topic = widget.id + '.' + widgetName + '.' + event.name,
            uiWidget = element.data( widgetName );

        	args.splice( 0, 0, topic );
        	args.push( uiWidget );

        	// this publishes an amplify event with the arguments that correspond to the jquery ui event handler function parameters.
					Juice.publish.apply( this, args );

        	// Submit a postback if handler emitted - wee server side events!
        	if ( event.causesPostBack ) {
        		window.__doPostBack(widget.uniqueId, event.dataChangedEvent ? '' : event.name);
        	}
        };
      });

			$.each( widget.options, function( prop ) {
				if( this.eval ){
					var on = this.on;

					try {
						widget.options[ prop ] = eval( '(' + this.on + ')' );
					}
					catch ( e ) { // if bad data/string is entered for the Eval property, an exception is thrown. Remove the bad data and prop.
						delete widget.options[ prop ];

						window.console && console.log && console.log( 'Juice UI Error > elementId: ' + widget.id + '. widget: "' + widgetName + '". Bad data in "' + prop + '" option.' );
					}
				}
			});

      // merge events with options
      $.extend( widget.options, events );

      // Invoke the jQuery UI extension method on the element with the options only if it hasn't already been called
      if ( !element.data( widgetName ) ) {
        element[widgetName]( widget.options );
      }

      // Wire up dispose method which update panels will call when element is destroyed
      element[0].dispose = function () {
        delete Juice.widgets[widget.id];
      };
    });
  },

  endRequest = function ( sender, args ) {
    ready();
    registerCss();
  },

	htmlEncode = function( value ){
		return $( '<div/>' ).text( value ).html();
	};

	// The datepicker widget is "unique" in jQuery UI. It's internals aren't standardized like the other widgets.
	// Hence, it does not store an options hash natively. This extension provides that hash.
	// Credit - Scott Gonzales
	var _attachDatepicker = $.datepicker._attachDatepicker,
		_optionDatepicker = $.datepicker._optionDatepicker;

	$.datepicker._attachDatepicker = function( target ) {
		var inst;
		_attachDatepicker.apply( this, arguments );
		inst = this._getInst( target );
		inst.options = {};
		this._refreshOptions( target );
	};

	$.datepicker._refreshOptions = function( target ) {
		var inst = this._getInst( target );
		$.each(this._defaults, function( prop ) {
			inst.options[ prop ] = $.datepicker._get( inst, prop );
		});
	};

	$.datepicker._optionDatepicker = function( target ) {
		_optionDatepicker.apply( this, arguments );
		this._refreshOptions( target );
	};

	// The tabs widget triggers 'show' on create. Scott has stated that this behavior is unusual and won't be a part of 1.9.
	// Implementing a temporary workaround so that the tabs don't trigger a postback (if bound in codebehind) on page load.
	$.ui.tabs.prototype._created = false;

	var _tabify = $.ui.tabs.prototype._tabify,
		_trigger = $.ui.tabs.prototype._trigger;

	$.ui.tabs.prototype._tabify = function(){
		_tabify.apply( this, arguments );
		this._created = true;
	};

	$.ui.tabs.prototype._trigger = function( type ){
		if( type === "show" && !this._created ){
			return false;
		}
		return _trigger.apply( this, arguments );
	};

	$( ready );
	Sys.WebForms.PageRequestManager.getInstance().add_endRequest( endRequest ); // handles adding the jquery ui css on partial postback, if it hasn't been already.
	window.Juice = Juice;

} )( jQuery );<commit_msg>removing errant console.log<commit_after>(function ( $ ) {
	'use strict';
	var stateFieldId = '_juiceWidgetOptions',

  Juice = {
		widgets: {},
    subscribe: window.amplify.subscribe,
    publish: window.amplify.publish,
    onSubmit: function () {
      var optionsInput = $( '#' + stateFieldId ),
				options = [];

      $.each( Juice.widgets, function ( index, widget ) {
        var element = $( '#' + widget.id ),
          widgetName = widget.widgetName, //element.data( 'ui-widget' ),
          uiWidget = element.data( widgetName ),
					opts = $.extend({}, uiWidget.options);

				$.each( opts, function( label ){
					if( $.inArray( label, widget.encodedOptions ) >= 0 ){
						opts[ label ] = htmlEncode( this );
					}
				});

        options.push({ id: widget.id, widgetName: widgetName, options: opts });
      });

      optionsInput.val( JSON.stringify( options ) );
    }
  },

  registerCss = function () {
    if ( !$( '#_jQueryUICss' ).length ) {
      var href = Juice.cssUrl,
        tag = '<link rel="stylesheet" type="text/css" href="' + href + '" />';
      $( 'head' ).append( tag );
    }
  },

  ready = function () {
    if ( typeof ( window.JSON ) === 'undefined' ) {
      throw new Error( 'Juice requires JSON support. Please ensure json2.js is referenced for downlevel browsers.' );
    }

    if ( !$( '#' + stateFieldId ).length ) {
      $( '<input id="' + stateFieldId + '" name="' + stateFieldId + '" type="hidden" />' )
			  .appendTo( window.theForm ); // theForm is defined by asp.net
    }

    $.each( Juice.widgets, function ( index, widget ) {
      var element = $( '#' + widget.id ),
        widgetName = widget.widgetName,
        events = {};

			if( !widgetName || !$.fn[widgetName] ) {
				return;
			}

			// map the event names to objects, merge with postBacks
			widget.events = $.map( widget.events, function( name ){
				return { name: name };
			});

			widget.postBacks = $.map( widget.postBacks, function( pb ){
				pb.causesPostBack = true;
				return pb;
			});

			widget.events = widget.events.concat( widget.postBacks );

      $.each( widget.events, function () {
        var event = this;
        events[event.name] = function ( jqEvent, ui ) {
        	var args = [].slice.call( arguments, 0 ),
            topic = widget.id + '.' + widgetName + '.' + event.name,
            uiWidget = element.data( widgetName );

        	args.splice( 0, 0, topic );
        	args.push( uiWidget );

        	// this publishes an amplify event with the arguments that correspond to the jquery ui event handler function parameters.
					Juice.publish.apply( this, args );

        	// Submit a postback if handler emitted - wee server side events!
        	if ( event.causesPostBack ) {
        		window.__doPostBack(widget.uniqueId, event.dataChangedEvent ? '' : event.name);
        	}
        };
      });

			$.each( widget.options, function( prop ) {
				if( this.eval ){
					var on = this.on;

					try {
						widget.options[ prop ] = eval( '(' + this.on + ')' );
					}
					catch ( e ) { // if bad data/string is entered for the Eval property, an exception is thrown. Remove the bad data and prop.
						delete widget.options[ prop ];

						window.console && console.log && console.log( 'Juice UI Error > elementId: ' + widget.id + '. widget: "' + widgetName + '". Bad data in "' + prop + '" option.' );
					}
				}
			});

      // merge events with options
      $.extend( widget.options, events );

      // Invoke the jQuery UI extension method on the element with the options only if it hasn't already been called
      if ( !element.data( widgetName ) ) {
        element[widgetName]( widget.options );
      }

      // Wire up dispose method which update panels will call when element is destroyed
      element[0].dispose = function () {
        delete Juice.widgets[widget.id];
      };
    });
  },

  endRequest = function ( sender, args ) {
    ready();
    registerCss();
  },

	htmlEncode = function( value ){
		return $( '<div/>' ).text( value ).html();
	};

	// The datepicker widget is "unique" in jQuery UI. It's internals aren't standardized like the other widgets.
	// Hence, it does not store an options hash natively. This extension provides that hash.
	// Credit - Scott Gonzales
	var _attachDatepicker = $.datepicker._attachDatepicker,
		_optionDatepicker = $.datepicker._optionDatepicker;

	$.datepicker._attachDatepicker = function( target ) {
		var inst;
		_attachDatepicker.apply( this, arguments );
		inst = this._getInst( target );
		inst.options = {};
		this._refreshOptions( target );
	};

	$.datepicker._refreshOptions = function( target ) {
		var inst = this._getInst( target );
		$.each(this._defaults, function( prop ) {
			inst.options[ prop ] = $.datepicker._get( inst, prop );
		});
	};

	$.datepicker._optionDatepicker = function( target ) {
		_optionDatepicker.apply( this, arguments );
		this._refreshOptions( target );
	};

	// The tabs widget triggers 'show' on create. Scott has stated that this behavior is unusual and won't be a part of 1.9.
	// Implementing a temporary workaround so that the tabs don't trigger a postback (if bound in codebehind) on page load.
	$.ui.tabs.prototype._created = false;

	var _tabify = $.ui.tabs.prototype._tabify,
		_trigger = $.ui.tabs.prototype._trigger;

	$.ui.tabs.prototype._tabify = function(){
		_tabify.apply( this, arguments );
		this._created = true;
	};

	$.ui.tabs.prototype._trigger = function( type ){
		if( type === "show" && !this._created ){
			return false;
		}
		return _trigger.apply( this, arguments );
	};

	// The autocomplete widget accepts a string and string array. This is problematic as we can't represent both

	$( ready );
	Sys.WebForms.PageRequestManager.getInstance().add_endRequest( endRequest ); // handles adding the jquery ui css on partial postback, if it hasn't been already.
	window.Juice = Juice;

} )( jQuery );<|endoftext|>


<commit_before>/**
 * 2017-07-15
 * Note 1.
 * An improvement for Magento_Catalog/js/price-utils::formatPrice():
 * https://github.com/magento/magento2/blob/2.2.0-RC1.4/app/code/Magento/Catalog/view/base/web/js/price-utils.js#L33-L85
 * Note 2.
 * «The Magento_Catalog/js/price-utils::formatPrice() pollutes the global formatting settings with local ones
 * because of a wrong lodash extend / assignIn usage»: https://mage2.pro/t/4171
 * Note 3.
 * «The global «groupLength» property has an incorrect «,» value instead of a natural number in Magento_Catalog/js/price-utils»: https://mage2.pro/t/4173
 * Note 4. https://mage2.pro/tags/money-format
 */
define([
	'df', 'df-lodash', 'Magento_Catalog/js/price-utils', 'Magento_Checkout/js/model/quote'
], function (df, _, priceUtils, q) {'use strict'; return(
	/**
	 * 2017-07-15
	 * @param {Number} amount
	 * @param {Object=} f
	 * @param {String=} f.decimalSymbol
	 * @param {Number=} f.groupLength
	 * @param {String=} f.groupSymbol
	 * @param {Number=} f.integerRequired
	 * @param {String=} f.pattern
	 * @param {Number=} f.requiredPrecision
	 * @param {Boolean=} isShowSign
	 * @returns {String}
	 */
	function(amount, f, isShowSign) {
		f = _.assign({}, {
			decimalSymbol: ',', groupLength: 3, groupSymbol: ','
			,integerRequired: 1, pattern: '%s', requiredPrecision: 2
		}, q.getPriceFormat(), df.arg(f, {}));
		/** @type {String} */ var decimalSymbol = f.decimalSymbol;
		/** @type {Number} */ var groupLength = f.groupLength;
		/** @type {String} */ var groupSymbol = f.groupSymbol;
		/** @type {Number} */ var integerRequired = f.integerRequired;
		/** @type {Number} */ var precision = f.requiredPrecision;
		/** @type {String} */
		var s = false === isShowSign ? '' : (amount < 0 ? '-' : (true === isShowSign ? '+' : ''));
		/** @type {String} */
		var pattern = -1 === f.pattern.indexOf('{sign}') ? s + f.pattern : f.pattern.replace('{sign}', s);
		// 2017-07-15
		// «We're avoiding the usage of to fixed,
		// and using round instead with the e representation to address numbers like 1.005 = 1.01.
		// Using ToFixed to only provide trailig zeroes in case we have a whole number.»
		// https://github.com/magento/magento2/blob/2.2.0-RC1.4/app/code/Magento/Catalog/view/base/web/js/price-utils.js#L62-L63
		// noinspection JSCheckFunctionSignatures
		amount = Number(Math.round(Math.abs(+amount || 0) + 'e+' + precision) + ('e-' + precision));
		/** @type {String} */ var i = df.int(amount) + '';
		/** @type {Number} */ var pad = i.length >= integerRequired ? 0 : integerRequired - i.length;
		i = priceUtils.strPad('0', pad) + i;
		/** @type {Number} */ var j = i.length <= groupLength ? 0 : i.length % groupLength;
		/** @type {RegExp} */ var re = new RegExp('(\\d{' + groupLength + '})(?=\\d)', 'g');
		// replace(/-/, 0) is only for fixing Safari bug which appears
		// when Math.abs(0).toFixed() executed on '0' number.
		// Result is '0.-0' :(
		// noinspection JSCheckFunctionSignatures
		/** @type {Number} */
		var am = Number(Math.round(Math.abs(amount - i) + 'e+' + precision) + ('e-' + precision));
		/** @type {String} */ var r =
			(j ? i.substr(0, j) + groupSymbol : '')
			+ i.substr(j).replace(re, '$1' + groupSymbol)
			+ (precision ? decimalSymbol + am.toFixed(2).replace(/-/, 0).slice(2) : '')
		;
		return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
	}
);});<commit_msg>no message<commit_after>/**
 * 2017-07-15
 * Note 1.
 * An improvement for Magento_Catalog/js/price-utils::formatPrice():
 * https://github.com/magento/magento2/blob/2.2.0-RC1.4/app/code/Magento/Catalog/view/base/web/js/price-utils.js#L33-L85
 * Note 2.
 * «The Magento_Catalog/js/price-utils::formatPrice() pollutes the global formatting settings with local ones
 * because of a wrong lodash extend / assignIn usage»: https://mage2.pro/t/4171
 * Note 3.
 * «The global «groupLength» property has an incorrect «,» value instead of a natural number in Magento_Catalog/js/price-utils»: https://mage2.pro/t/4173
 * Note 4. https://mage2.pro/tags/money-format
 */
define([
	'df', 'df-lodash', 'Magento_Catalog/js/price-utils', 'Magento_Checkout/js/model/quote'
], function (df, _, priceUtils, q) {'use strict'; return(
	/**
	 * 2017-07-15
	 * @param {Number} a
	 * @param {Object=} f
	 * @param {String=} f.decimalSymbol
	 * @param {Number=} f.groupLength
	 * @param {String=} f.groupSymbol
	 * @param {Number=} f.integerRequired
	 * @param {String=} f.pattern
	 * @param {Number=} f.requiredPrecision
	 * @param {Boolean=} showSign
	 * @returns {String}
	 */
	function(a, f, showSign) {
		f = _.assign({}, {
			decimalSymbol: ',', groupLength: 3, groupSymbol: ','
			,integerRequired: 1, pattern: '%s', requiredPrecision: 2
		}, q.getPriceFormat(), df.arg(f, {}));
		/** @type {Number} */ var precision = f.requiredPrecision;
		/**
		 * 2017-07-15
		 * «We're avoiding the usage of to fixed,
		 * and using round instead with the e representation to address numbers like 1.005 = 1.01.
		 * Using ToFixed to only provide trailig zeroes in case we have a whole number.»
		 * https://github.com/magento/magento2/blob/2.2.0-RC1.4/app/code/Magento/Catalog/view/base/web/js/price-utils.js#L62-L63
 		 * @param {Number} v
		 * @returns {Number}
		 */
		var fixed = function(v) {//noinspection JSCheckFunctionSignatures
			return Number(Math.round(Math.abs(+v || 0) + 'e+' + precision) + ('e-' + precision));
		};
		a = fixed(a);
		/** @type {String} */ var as = df.int(a) + '';
		/** @type {Number} */ var pad = as.length >= f.integerRequired ? 0 : f.integerRequired - as.length;
		as = priceUtils.strPad('0', pad) + as;
		/** @type {Number} */ var j = as.length <= f.groupLength ? 0 : as.length % f.groupLength;
		/** @type {RegExp} */ var re = new RegExp('(\\d{' + f.groupLength + '})(?=\\d)', 'g');
		// replace(/-/, 0) is only for fixing Safari bug which appears
		// when Math.abs(0).toFixed() executed on '0' number.
		// Result is '0.-0' :(
		// noinspection JSCheckFunctionSignatures
		/** @type {Number} */
		/** @type {String} */
		var r =
			(j ? as.substr(0, j) + f.groupSymbol : '')
			+ as.substr(j).replace(re, '$1' + f.groupSymbol)
			+ (precision ? f.decimalSymbol + fixed(a - as).toFixed(2).replace(/-/, 0).slice(2) : '')
		;
		return _.trim((-1 < f.pattern.indexOf('{sign}') ? f.pattern : '{sign}' + f.pattern)
			.replace('{sign}', false === showSign ? '' : (a < 0 ? '-' : (true === showSign ? '+' : '')))
			.replace('%s', r)
		);
	}
);});<|endoftext|>


<commit_before><commit_msg>Send rankings data to dashboard<commit_after><|endoftext|>


<commit_before>module.exports = ({ title }) => {
  return `<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>${title}</title>
    <link rel="shortcut icon" href="/static/favicon.ico?v=3">
    <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
    <link rel="stylesheet" href="/static/css/main.min.css">

    <app/>

  `
}
<commit_msg>favicon force<commit_after>module.exports = ({ title }) => {
  return `<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>${title}</title>
    <link rel="shortcut icon" href="/static/favicon.ico?v=4">
    <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
    <link rel="stylesheet" href="/static/css/main.min.css">

    <app/>

  `
}
<|endoftext|>


<commit_before>/**
 * This file/module contains all configuration for the build process.
 */
module.exports = {
    /**
     * The `build_dir` folder is where our projects are compiled during
     * development and the `compile_dir` folder is where our app resides once it"s
     * completely built.
     */
    build_dir: "build",
    compile_dir: "bin",

    /**
     * 'env' settings file
     */
    settings_file: "settings.js",

    /**
     * This is a collection of file patterns that refer to our app code (the
     * stuff in `src/`). These file paths are used in the configuration of
     * build tasks. `js` is all project javascript, less tests. `ctpl` contains
     * our reusable components" (`src/common`) template HTML files, while
     * `atpl` contains the same, but for our app"s code. `html` is just our
     * main HTML file, `less` is our main stylesheet, and `unit` contains our
     * app"s unit tests.
     */
    app_files: {
        js: [
            "src/**/*.js",
            "!src/**/*.spec.js",
            "!src/assets/**/*.js",
            "!src/<%= settings_file %>"
        ],
        jsunit: ["src/**/*.spec.js"],

        coffee: ["src/**/*.coffee", "!src/**/*.spec.coffee"],
        coffeeunit: ["src/**/*.spec.coffee"],

        atpl: ["src/app/**/*.tpl.html"],
        ctpl: ["src/common/**/*.tpl.html"],

        html: ["src/index.html"],
        less: "src/less/main.less"
    },

    /**
     * This is a collection of files used during testing only.
     */
    test_files: {
        js: [
            "vendor/angular-mocks/angular-mocks.js",
            "build/templates-common.js"
        ]
    },

    /**
     * This is the same as `app_files`, except it contains patterns that
     * reference vendor code (`vendor/`) that we need to place into the build
     * process somewhere. While the `app_files` property ensures all
     * standardized files are collected for compilation, it is the user"s job
     * to ensure non-standardized (i.e. vendor-related) files are handled
     * appropriately in `vendor_files.js`.
     *
     * The `vendor_files.js` property holds files to be automatically
     * concatenated and minified with our project source files.
     *
     * The `vendor_files.css` property holds any CSS files to be automatically
     * included in our app.
     *
     * The `vendor_files.assets` property holds any assets to be copied along
     * with our app"s assets. This structure is flattened, so it is not
     * recommended that you use wildcards.
     */
    vendor_files: {
        js: [
            "vendor/jquery/dist/jquery.js",
            "vendor/toastr/toastr.js",
            "vendor/underscore/underscore.js",
            "vendor/bootstrap/dist/js/bootstrap.js",
            "vendor/angular/angular.js",
            "vendor/leaflet/dist/leaflet-src.js",
            "vendor/angular-animate/angular-animate.js",
            "vendor/angular-cookies/angular-cookies.js",
            "vendor/angular-resource/angular-resource.js",
            "vendor/angular-bootstrap/ui-bootstrap.js",
            "vendor/angular-bootstrap/ui-bootstrap-tpls.js",
            "vendor/angular-ui-router/release/angular-ui-router.js",
            "vendor/angular-sanitize/angular-sanitize.js",
            "vendor/typeahead.js/dist/bloodhound.js",
            "vendor/typeahead.js/dist/typeahead.bundle.js",
            "vendor/typeahead.js/dist/typeahead.jquery.js",
            "vendor/angular-leaflet-directive/dist/angular-leaflet-directive.js",
            "vendor/stacktrace-js/dist/stacktrace.js",
            "vendor/angularjs-dropdown-multiselect/src/angularjs-dropdown-multiselect.js",
            "vendor/ng-tags-input/ng-tags-input.js",
            "vendor/moment/moment.js",
            "libs/api_wrapper.js",
            "libs/sil_typeahead_service/src/sil-typeahead.js",
            "libs/sil_grid/sil_grid_tpls.js",
            "libs/sil_grid/sil_grid.js",
            "libs/sil_error_handler/error_handler.js"
        ],
        css: [
        ],
        assets: [
            "vendor/fontawesome/fonts/*"
        ],
        imgs: [
            "libs/sil_grid/img/*"
        ]
    },

    connect: {
        options: {
            port: 8062,
            hostname: "*",
            keepalive: true
        },
        dev: {
            options: {
                base: "build"
            }
        },
        prod: {
            options: {
                base: "bin"
            }
        }
    }
};
<commit_msg>Revert port to 8063<commit_after>/**
 * This file/module contains all configuration for the build process.
 */
module.exports = {
    /**
     * The `build_dir` folder is where our projects are compiled during
     * development and the `compile_dir` folder is where our app resides once it"s
     * completely built.
     */
    build_dir: "build",
    compile_dir: "bin",

    /**
     * 'env' settings file
     */
    settings_file: "settings.js",

    /**
     * This is a collection of file patterns that refer to our app code (the
     * stuff in `src/`). These file paths are used in the configuration of
     * build tasks. `js` is all project javascript, less tests. `ctpl` contains
     * our reusable components" (`src/common`) template HTML files, while
     * `atpl` contains the same, but for our app"s code. `html` is just our
     * main HTML file, `less` is our main stylesheet, and `unit` contains our
     * app"s unit tests.
     */
    app_files: {
        js: [
            "src/**/*.js",
            "!src/**/*.spec.js",
            "!src/assets/**/*.js",
            "!src/<%= settings_file %>"
        ],
        jsunit: ["src/**/*.spec.js"],

        coffee: ["src/**/*.coffee", "!src/**/*.spec.coffee"],
        coffeeunit: ["src/**/*.spec.coffee"],

        atpl: ["src/app/**/*.tpl.html"],
        ctpl: ["src/common/**/*.tpl.html"],

        html: ["src/index.html"],
        less: "src/less/main.less"
    },

    /**
     * This is a collection of files used during testing only.
     */
    test_files: {
        js: [
            "vendor/angular-mocks/angular-mocks.js",
            "build/templates-common.js"
        ]
    },

    /**
     * This is the same as `app_files`, except it contains patterns that
     * reference vendor code (`vendor/`) that we need to place into the build
     * process somewhere. While the `app_files` property ensures all
     * standardized files are collected for compilation, it is the user"s job
     * to ensure non-standardized (i.e. vendor-related) files are handled
     * appropriately in `vendor_files.js`.
     *
     * The `vendor_files.js` property holds files to be automatically
     * concatenated and minified with our project source files.
     *
     * The `vendor_files.css` property holds any CSS files to be automatically
     * included in our app.
     *
     * The `vendor_files.assets` property holds any assets to be copied along
     * with our app"s assets. This structure is flattened, so it is not
     * recommended that you use wildcards.
     */
    vendor_files: {
        js: [
            "vendor/jquery/dist/jquery.js",
            "vendor/toastr/toastr.js",
            "vendor/underscore/underscore.js",
            "vendor/bootstrap/dist/js/bootstrap.js",
            "vendor/angular/angular.js",
            "vendor/leaflet/dist/leaflet-src.js",
            "vendor/angular-animate/angular-animate.js",
            "vendor/angular-cookies/angular-cookies.js",
            "vendor/angular-resource/angular-resource.js",
            "vendor/angular-bootstrap/ui-bootstrap.js",
            "vendor/angular-bootstrap/ui-bootstrap-tpls.js",
            "vendor/angular-ui-router/release/angular-ui-router.js",
            "vendor/angular-sanitize/angular-sanitize.js",
            "vendor/typeahead.js/dist/bloodhound.js",
            "vendor/typeahead.js/dist/typeahead.bundle.js",
            "vendor/typeahead.js/dist/typeahead.jquery.js",
            "vendor/angular-leaflet-directive/dist/angular-leaflet-directive.js",
            "vendor/stacktrace-js/dist/stacktrace.js",
            "vendor/angularjs-dropdown-multiselect/src/angularjs-dropdown-multiselect.js",
            "vendor/ng-tags-input/ng-tags-input.js",
            "vendor/moment/moment.js",
            "libs/api_wrapper.js",
            "libs/sil_typeahead_service/src/sil-typeahead.js",
            "libs/sil_grid/sil_grid_tpls.js",
            "libs/sil_grid/sil_grid.js",
            "libs/sil_error_handler/error_handler.js"
        ],
        css: [
        ],
        assets: [
            "vendor/fontawesome/fonts/*"
        ],
        imgs: [
            "libs/sil_grid/img/*"
        ]
    },

    connect: {
        options: {
            port: 8063,
            hostname: "*",
            keepalive: true
        },
        dev: {
            options: {
                base: "build"
            }
        },
        prod: {
            options: {
                base: "bin"
            }
        }
    }
};
<|endoftext|>


<commit_before>
class RoseChart {

	constructor ( id, options = {} ) {

		const container = document.getElementById( id );

		if ( ! container ) {

			console.error( "missing container element" );
			return;

		}

		this.container = container;
		this.canvas = null;
		this.chart = null;
		this.colours = options.colours ?? [ 'red' ];
		this.sectorSize = options.sectorSize ?? 30;

	}

	show ( event ) {

		this.close();

		const sectorCount = 180 / this.sectorSize;
		const sections = [];
		const labels = [];

		for ( let i = 0; i < sectorCount; i++ ) {

			sections [ i ] = 0;
			labels[ i ] = i;

		}

		const config = {
			type: 'polarArea',
			data: {
				datasets: [ {
					data: [],
					backgroundColor: []
				} ],
				labels: labels
			},
			options: {
				layout: {
					padding: 2
				},
				plugins: {
					legend: {
						display: false
					},
					title: {
						text: 'Total Leg Length by Direction',
						color: 'black',
						display: true
					}
				}
			}
		};

		event.station.forEachConnectedLeg( legInfo => {

			const v1 = legInfo.v1;
			const v2 = legInfo.v2;

			const v1Coordinates = v1.coordinates();
			const v2Coordinates = v2.coordinates();

			const dX = v1Coordinates.x - v2Coordinates.x;
			const dY = ( v1Coordinates.y - v2Coordinates.y ) * Math.sign( dX );

			const l = Math.hypot( dX, dY );

			if ( l == 0 ) return;

			const a = 180 * Math.acos( dY / l ) / Math.PI;

			sections[ Math.floor( a / this.sectorSize ) % sectorCount ] += l;

		} );

		const dataset = config.data.datasets[0];

		dataset.data = sections.concat( sections );

		config.data.datasets[0].backgroundColor = this.colours.slice( 0, sectorCount );

		const canvas = document.createElement( 'canvas' );

		this.container.appendChild( canvas );

		this.chart = new Chart( canvas, config );
		this.canvas = canvas;

	}

	close () {

		if ( this.chart ) this.chart.destroy();
		if ( this.canvas ) this.container.removeChild( this.canvas );
		this.chart = null;
		this.canvas = null;

	}

}<commit_msg>minor code fixes<commit_after>
class RoseChart {

	constructor ( id, options = {} ) {

		const container = document.getElementById( id );

		if ( ! container ) {

			console.error( "missing container element" );
			return;

		}

		this.container = container;
		this.canvas = null;
		this.chart = null;
		this.colours = options.colours ?? [ 'red' ];
		this.sectorSize = options.sectorSize ?? 30;

	}

	show ( event ) {

		this.close();

		const sectorCount = 180 / this.sectorSize;
		const sections = [];
		const labels = [];

		for ( let i = 0; i < sectorCount; i++ ) {

			sections [ i ] = 0;
			labels[ i ] = i;

		}

		const config = {
			type: 'polarArea',
			data: {
				datasets: [ {
					data: [],
					backgroundColor: []
				} ],
				labels: labels
			},
			options: {
				layout: {
					padding: 2
				},
				plugins: {
					legend: {
						display: false
					},
					title: {
						text: 'Total Leg Length by Direction',
						color: 'black',
						display: true
					}
				}
			}
		};

		event.station.forEachConnectedLeg( leg => {

			const v1 = leg.v1;
			const v2 = leg.v2;

			const v1Coordinates = v1.coordinates();
			const v2Coordinates = v2.coordinates();

			const dX = v1Coordinates.x - v2Coordinates.x;
			const dY = ( v1Coordinates.y - v2Coordinates.y ) * Math.sign( dX );

			const l = Math.hypot( dX, dY );

			if ( l == 0 ) return;

			const a = 180 * Math.acos( dY / l ) / Math.PI;

			sections[ Math.floor( a / this.sectorSize ) % sectorCount ] += l;

		} );

		const dataset = config.data.datasets[0];

		dataset.data = sections.concat( sections ); // duplicate for symetrical rose
		dataset.backgroundColor = this.colours.slice( 0, sectorCount );

		const canvas = document.createElement( 'canvas' );

		this.container.appendChild( canvas );

		this.chart = new Chart( canvas, config );
		this.canvas = canvas;

	}

	close () {

		if ( this.chart ) this.chart.destroy();
		if ( this.canvas ) this.container.removeChild( this.canvas );
		this.chart = null;
		this.canvas = null;

	}

}<|endoftext|>


<commit_before><commit_msg>fix logger<commit_after><|endoftext|>


<commit_before>define('messenger',
['amplify', 'config'],
    function (amplify, config) {
        var
            priority = 1,

            viewModelActivated = function (options) {
                amplify.publish(config.messages.viewModelActivated, options);
            },

            publish = { viewModelActivated: viewModelActivated },

            subscribe = function (options) {
                amplify.subscribe(
                    options.topic,
                    options.context,
                    options.callback,
                    priority);
            };

        return {
            publish: publish,
            subscribe: subscribe
        };
    });
<commit_msg>added generic publish method to messenger<commit_after>define('messenger',
['amplify', 'config'],
    function (amplify, config) {
        var
            priority = 1,

            publish = function (topic, options) {
                amplify.publish(topic, options);
            },

            subscribe = function (options) {
                amplify.subscribe(
                    options.topic,
                    options.context,
                    options.callback,
                    priority);
            };

        publish.viewModelActivated = function(options) {
            amplify.publish(config.messages.viewModelActivated, options);
        };

        return {
            publish: publish,
            subscribe: subscribe
        };
    });
<|endoftext|>


<commit_before>// Plumbing code tp launch a constructor form for a DE value and return it back to the main form

function goodValue(element) {
    var indicator = $(element).next(".validationindicator");
    if (indicator.hasClass("validity invalid")) {
        indicator.removeClass('validity invalid');
    }
    indicator.addClass("validity valid");
}

function badValue(element) {
    var indicator = $(element).next(".validationindicator");
    if (indicator.hasClass("validity valid")) {
        indicator.removeClass('validity valid');
    }
    indicator.addClass("validity invalid");
}

function generic_constructor(element, constructorName, constructorFormUrl) {
   // element here is the constructor button next to the input field - we have
   // to use navigate via jquery traversal as the field may be in a multisection and have been cloned
   function updateValue(value) {
       var textField = $(element).closest("td").find("input[type='text']");
       textField.val(value);  // we assume that the DE is text input field
       textField.trigger("keyup");
   }
   var w = window.open(constructorFormUrl, "Construct " + constructorName, "location=no,width=200,height=200,scrollbars=yes,top=100,left=100,resizable = no");
   // NB this function is/must be called on the child form to allow the constructed data value to be passed back to the form
   w.updateParentForm = updateValue;

}

function generic_validate(element, rpcEndPoint, rpcCommand) {
    // element is the text box
    var value = $(element).val();
    var csrfToken = $("input[name='csrfmiddlewaretoken']").val(); // this will/must appear on our django form

    var rpc = new RPC.RPC(rpcEndPoint, csrfToken);
    rpc.send(rpcCommand, [value], function (response) {
        var isValid = response.result;
        if (isValid) {
            goodValue(element);
        }
        else {
            badValue(element);
        }
    });
}<commit_msg>RDR-782 Genetic Variation Popup now larger<commit_after>// Plumbing code tp launch a constructor form for a DE value and return it back to the main form

function goodValue(element) {
    var indicator = $(element).next(".validationindicator");
    if (indicator.hasClass("validity invalid")) {
        indicator.removeClass('validity invalid');
    }
    indicator.addClass("validity valid");
}

function badValue(element) {
    var indicator = $(element).next(".validationindicator");
    if (indicator.hasClass("validity valid")) {
        indicator.removeClass('validity valid');
    }
    indicator.addClass("validity invalid");
}

function generic_constructor(element, constructorName, constructorFormUrl) {
   // element here is the constructor button next to the input field - we have
   // to use navigate via jquery traversal as the field may be in a multisection and have been cloned
   function updateValue(value) {
       var textField = $(element).closest("td").find("input[type='text']");
       textField.val(value);  // we assume that the DE is text input field
       textField.trigger("keyup");
   }
   var w = window.open(constructorFormUrl, "Construct " + constructorName, "location=no,width=800,height=600,scrollbars=yes,top=100,left=100,resizable = no");
   // NB this function is/must be called on the child form to allow the constructed data value to be passed back to the form
   w.updateParentForm = updateValue;

}

function generic_validate(element, rpcEndPoint, rpcCommand) {
    // element is the text box
    var value = $(element).val();
    var csrfToken = $("input[name='csrfmiddlewaretoken']").val(); // this will/must appear on our django form

    var rpc = new RPC.RPC(rpcEndPoint, csrfToken);
    rpc.send(rpcCommand, [value], function (response) {
        var isValid = response.result;
        if (isValid) {
            goodValue(element);
        }
        else {
            badValue(element);
        }
    });
}<|endoftext|>


<commit_before><commit_msg>Replace IIFEs with blocks and use block-scope variables.<commit_after><|endoftext|>


<commit_before>import React from 'react';
import { Link, withRouter } from 'react-router';
import $ from 'jquery';
var vex = require('vex-js');
vex.registerPlugin(require('vex-dialog'));
vex.defaultOptions.className = 'vex-theme-os';

var fileName;
var filePath;

const uploadFile = () => {

  $(function () {
    $(":file").change(function () {
      if (this.files && this.files[0]) {
        var reader = new FileReader();
        fileName = this.files[0].name;
        reader.onload = imageIsLoaded;
        reader.readAsDataURL(this.files[0]);
      }
    });
  });

  function imageIsLoaded(e) {
    $('#myImg').attr('src', e.target.result);
    filePath = e.target.result;

    $.post({
      url: '/upload',
      data: JSON.stringify({fileName: fileName, filePath: filePath}),
      contentType: 'application/json',
      success: (data) => {
        console.log(data);
        $("#fileUp").val('');
        vex.dialog.alert('Image uploaded!');
      },
      error: (error) => {
        console.error('error in get upload', error);
        $('.error').show();
      },
    });
  };
}

const signOut = () => {
  $.get({
    url: '/signOut',
    success: (data) => {
      console.log(data)
    },
    error: (error) => {
      console.error('error in get bookmarks', error);
      $('.error').show();
    },
  });
}

export default props => {
  uploadFile();
  return (

      <Link to="/bookmarks">
        <button>

Bookmarks

        </button>
      </Link>

      <Link to="/lobby">
        <button>

Explore!

        </button>
      </Link>

      <input type='file' id='fileUp' />

      <Link to="/signin">
        <button onClick={() => {signOut()}}>

Sign Out

        </button>
      </Link>

  );
};<commit_msg>Add the ability to send picture info to DB and retrieve top pictures from server<commit_after>import React from 'react';
import { Link, withRouter } from 'react-router';
import $ from 'jquery';
var fecha = require('fecha');
var vex = require('vex-js');
vex.registerPlugin(require('vex-dialog'));
vex.defaultOptions.className = 'vex-theme-os';

var fileName;
var filePath;
var picDescrip;
var date = fecha.format(new Date(), 'mediumDate').replace(/\s+/g, '');
var currentImgs = [];

const getAllPhotos = () => {
  $.get({
    url: '/topPics',
    success: (data) => {
      console.log(data);
    },
    error: (error) => {
      console.error('error in get upload', error);
      $('.error').show();
    },
  });
};

const savePhoto = (data) => {
  var link = 'https://s3.amazonaws.com/' + data.Bucket + '/' + data.Key;
  console.log(link);
  $.post({
    url: '/addPic',
    data: JSON.stringify({title: data.Key, imageLink: link, description: picDescrip}),
    contentType: 'application/json',
    success: (data) => {
      console.log(data);
      getAllPhotos();
    },
    error: (error) => {
      console.error('error in get upload', error);
      $('.error').show();
    },
  });
};

const uploadFile = () => {

  $(function () {
    $("#fileUp").change(function () {
      if (this.files && this.files[0]) {
        var reader = new FileReader();
        picDescrip = $("#description").val();
        fileName = date + this.files[0].name;
        console.log(fileName);
        reader.onload = imageIsLoaded;
        reader.readAsDataURL(this.files[0]);
      }
    });
  });

  function imageIsLoaded(e) {
    $('#myImg').attr('src', e.target.result);
    filePath = e.target.result;

    if (!currentImgs.includes(fileName)) {
      currentImgs.push(fileName);
      $.post({
        url: '/upload',
        data: JSON.stringify({fileName: fileName, filePath: filePath}),
        contentType: 'application/json',
        success: (data) => {
          console.log(data);
          $("#fileUp").val('');
          vex.dialog.alert('Image uploaded!');
          savePhoto(data);
        },
        error: (error) => {
          console.error('error in get upload', error);
          $('.error').show();
        },
      });
    }
  };
}

const signOut = () => {
  $.get({
    url: '/signOut',
    success: (data) => {
      console.log(data)
    },
    error: (error) => {
      console.error('error in get bookmarks', error);
      $('.error').show();
    },
  });
}

export default props => {
  uploadFile();
  return (

      <Link to="/bookmarks">
        <button>

Bookmarks

        </button>
      </Link>

      <Link to="/lobby">
        <button>

Explore!

        </button>
      </Link>

        <input type='file' id='fileUp' />

         A nice description of the photo
        <input type='text' id='description'/>

      <Link to="/signin">
        <button onClick={() => {signOut()}}>

Sign Out

        </button>
      </Link>

  );
};<|endoftext|>


<commit_before><commit_msg>Breakdown of deaths by age<commit_after><|endoftext|>


<commit_before>'use strict'

import React, { Component } from '../../base-react'

import CodePage from '../../login2/register/code-page'
import GenPaperKey from './gen-paper-key'
import ExistingDevice from '../../login2/register/existing-device'
import RemoveDevice from './remove-device'

import { loadDevices } from '../../actions/devices'
import { routeAppend } from '../../actions/router'
import { addANewDevice } from '../../actions/login2'
import DevicesRender from './devices-render'

export default class Devices extends Component {
  componentWillMount () {
    const {devices, waitingForServer, error} = this.props

    if (!devices && !waitingForServer && !error) {
      this.props.loadDevices()
    }
  }

  static parseRoute (store, currentPath, nextPath) {
    return {
      componentAtTop: {
        title: 'Devices',
        mapStateToProps: state => {
          const { devices, waitingForServer, error } = state.devices
          return {
            devices,
            waitingForServer,
            error
          }
        },
        props: {
          loadDevices: () => store.dispatch(loadDevices()),
          showRemoveDevicePage: device => store.dispatch(routeAppend({path: 'removeDevice', device})),
          showExistingDevicePage: () => store.dispatch(addANewDevice()),
          showGenPaperKeyPage: () => store.dispatch(routeAppend('genPaperKey'))
        }
      },
      subRoutes: {
        codePage: CodePage,
        genPaperKey: GenPaperKey,
        regExistingDevice: ExistingDevice,
        removeDevice: RemoveDevice
      }
    }
  }

  render () {
    return <DevicesRender {... this.props}/>
  }
}

Devices.propTypes = {
  devices: React.PropTypes.array,
  waitingForServer: React.PropTypes.bool,
  loadDevices: React.PropTypes.func.isRequired,
  showRemoveDevicePage: React.PropTypes.func.isRequired,
  showExistingDevicePage: React.PropTypes.func.isRequired,
  showGenPaperKeyPage: React.PropTypes.func.isRequired
}
<commit_msg>Explicity pass props<commit_after>'use strict'

import React, { Component } from '../../base-react'

import CodePage from '../../login2/register/code-page'
import GenPaperKey from './gen-paper-key'
import ExistingDevice from '../../login2/register/existing-device'
import RemoveDevice from './remove-device'

import { loadDevices } from '../../actions/devices'
import { routeAppend } from '../../actions/router'
import { addANewDevice } from '../../actions/login2'
import DevicesRender from './devices-render'

export default class Devices extends Component {
  componentWillMount () {
    const {devices, waitingForServer, error} = this.props

    if (!devices && !waitingForServer && !error) {
      this.props.loadDevices()
    }
  }

  static parseRoute (store, currentPath, nextPath) {
    return {
      componentAtTop: {
        title: 'Devices',
        mapStateToProps: state => {
          const { devices, waitingForServer, error } = state.devices
          return {
            devices,
            waitingForServer,
            error
          }
        },
        props: {
          loadDevices: () => store.dispatch(loadDevices()),
          showRemoveDevicePage: device => store.dispatch(routeAppend({path: 'removeDevice', device})),
          showExistingDevicePage: () => store.dispatch(addANewDevice()),
          showGenPaperKeyPage: () => store.dispatch(routeAppend('genPaperKey'))
        }
      },
      subRoutes: {
        codePage: CodePage,
        genPaperKey: GenPaperKey,
        regExistingDevice: ExistingDevice,
        removeDevice: RemoveDevice
      }
    }
  }

  render () {
    const {
      devices,
      waitingForServer,
      showRemoveDevicePage,
      showExistingDevicePage,
      showGenPaperKeyPage
    } = this.props

    return <DevicesRender {... {
      devices,
      waitingForServer,
      showRemoveDevicePage,
      showExistingDevicePage,
      showGenPaperKeyPage
    }}/>
  }
}

Devices.propTypes = {
  devices: React.PropTypes.array,
  error: React.PropTypes.any,
  waitingForServer: React.PropTypes.bool,
  loadDevices: React.PropTypes.func.isRequired,
  showRemoveDevicePage: React.PropTypes.func.isRequired,
  showExistingDevicePage: React.PropTypes.func.isRequired,
  showGenPaperKeyPage: React.PropTypes.func.isRequired
}
<|endoftext|>


<commit_before><commit_msg>fix bug 33087<commit_after><|endoftext|>


<commit_before>Prism.languages.eiffel = {
	'string': [
		// Aligned-verbatim-strings (verbatim option not supported)
		/"\[(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[cC][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*|\d(?:_?\d)*)\/)*?]"/g,
		// Non-aligned-verbatim-strings (verbatim option not supported)
		/"\{(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[cC][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*|\d(?:_?\d)*)\/)*?}"/g,
		// Single-line string
		/"(?:[^%\b\f\n\r\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[cC][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*|\d(?:_?\d)*)\/)*?"/g
	],
	// (comments including quoted strings not supported)
	'comment': /--.*/,
	// normal char | special char | char code
	'char': /'(?:[^%\b\f\n\r\t\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[cC][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*|\d(?:_?\d)*)\/)'/g,
	'keyword': /\b(?:across|agent|alias|all|and|attached|as|assign|attribute|check|class|convert|create|Current|debug|deferred|detachable|do|else|elseif|end|ensure|expanded|export|external|feature|from|frozen|if|implies|inherit|inspect|invariant|like|local|loop|not|note|obsolete|old|once|or|Precursor|redefine|rename|require|rescue|Result|retry|select|separate|some|then|undefine|until|variant|Void|when|xor)\b/gi,
	'boolean': /\b(?:True|False)\b/gi,
	'number': [
		// Decimal
		{
			pattern: /(\s)(?:\d(?:_?\d)*\.|(?:(?:\d(?:_?\d)*)?\.(?:\d(?:_?\d)*)?(?:[eE][+-]?)?)?\d(?:_?\d)*)(?=\s)/g,
			lookbehind: true
		},
		// hexa | octal | bin
		/\b0(?:[xX][\da-fA-F](?:_?[\da-fA-F])*|[cC][0-7](?:_?[0-7])*|[bB][01](?:_?[01])*)\b/g
	],
	'punctuation': /:=|<<|>>|\(\||\|\)|->|\.(?=\w)|[{}[\];(),:?]/g,
	'operator': /\\\\|\|\.\.\||\.\.|\/[~\/]?|[><\/]=?|[-+*^=~]/g
};
<commit_msg>Enable juxtaposed digit separators<commit_after>Prism.languages.eiffel = {
	'string': [
		// Aligned-verbatim-strings (verbatim option not supported)
		/"\[(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)*?]"/g,
		// Non-aligned-verbatim-strings (verbatim option not supported)
		/"\{(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)*?}"/g,
		// Single-line string
		/"(?:[^%\b\f\n\r\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)*?"/g
	],
	// (comments including quoted strings not supported)
	'comment': /--.*/,
	// normal char | special char | char code
	'char': /'(?:[^%\b\f\n\r\t\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)'/g,
	'keyword': /\b(?:across|agent|alias|all|and|attached|as|assign|attribute|check|class|convert|create|Current|debug|deferred|detachable|do|else|elseif|end|ensure|expanded|export|external|feature|from|frozen|if|implies|inherit|inspect|invariant|like|local|loop|not|note|obsolete|old|once|or|Precursor|redefine|rename|require|rescue|Result|retry|select|separate|some|then|undefine|until|variant|Void|when|xor)\b/gi,
	'boolean': /\b(?:True|False)\b/gi,
	'number': [
		// Decimal
		{
			pattern: /(\s)(?:\d(?:_*\d)*\.|(?:(?:\d(?:_*\d)*)?\.(?:\d(?:_*\d)*)?(?:[eE][+-]?)?)?\d(?:_*\d)*)(?=\s)/g,
			lookbehind: true
		},
		// hexa | octal | bin
		/\b0(?:[xX][\da-fA-F](?:_*[\da-fA-F])*|[cC][0-7](?:_*[0-7])*|[bB][01](?:_*[01])*)\b/g
	],
	'punctuation': /:=|<<|>>|\(\||\|\)|->|\.(?=\w)|[{}[\];(),:?]/g,
	'operator': /\\\\|\|\.\.\||\.\.|\/[~\/]?|[><\/]=?|[-+*^=~]/g
};
<|endoftext|>


<commit_before>/*
 * Licensed under the MIT License
 */
(function () {

    "use strict";
    // レコード一覧の表示時にフィールドの背景色を変更する
    kintone.events.on('app.record.index.show', function (event) {
        var loginFieldColor = '#e5f0ff';        // ログインユーザのフィールド色

        // 一覧の要素を取得
        var elCustomer = kintone.app.getFieldElements('Customer');
        var elStatus = kintone.app.getFieldElements('Status');
        var elPerson = kintone.app.getFieldElements('Person');
        var elQType = kintone.app.getFieldElements('QType');
        var elDetail = kintone.app.getFieldElements('Detail');
        var elLimitDay = kintone.app.getFieldElements('LimitDay');

        for (var i = 0; i < event.records.length; i++) {
            elCustomer[i].style.backgroundColor = loginFieldColor;
            elStatus[i].style.backgroundColor = loginFieldColor;
            elPerson[i].style.backgroundColor = loginFieldColor;
            elQType[i].style.backgroundColor = loginFieldColor;
            elDetail[i].style.backgroundColor = loginFieldColor;
            elLimitDay[i].style.backgroundColor = loginFieldColor;
        }
    };
})();
<commit_msg>change a variable's name<commit_after>/*
 * Licensed under the MIT License
 */
(function () {

    "use strict";
    // レコード一覧の表示時にフィールドの背景色を変更する
    kintone.events.on('app.record.index.show', function (event) {
        var fieldColor = '#e5f0ff';        // ログインユーザのフィールド色

        // 一覧の要素を取得
        var elCustomer = kintone.app.getFieldElements('Customer');
        var elStatus = kintone.app.getFieldElements('Status');
        var elPerson = kintone.app.getFieldElements('Person');
        var elQType = kintone.app.getFieldElements('QType');
        var elDetail = kintone.app.getFieldElements('Detail');
        var elLimitDay = kintone.app.getFieldElements('LimitDay');

        for (var i = 0; i < event.records.length; i++) {
            elCustomer[i].style.backgroundColor = fieldColor;
            elStatus[i].style.backgroundColor = fieldColor;
            elPerson[i].style.backgroundColor = fieldColor;
            elQType[i].style.backgroundColor = fieldColor;
            elDetail[i].style.backgroundColor = fieldColor;
            elLimitDay[i].style.backgroundColor = fieldColor;
        }
    };
})();
<|endoftext|>