<commit_before>/**
 * Accordion module.
 * @module foundation.accordion
 * @requires foundation.util.keyboard
 * @requires foundation.util.motion
 */
!function($, Foundation) {
  'use strict';

  /**
   * Creates a new instance of an accordion.
   * @class
   * @fires Accordion#init
   * @param {jQuery} element - jQuery object to make into an accordion.
   * @param {Object} options - a plain object with settings to override the default options.
   */
  function Accordion(element, options){
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Accordion');
    Foundation.Keyboard.register('Accordion', {
      'ENTER': 'toggle',
      'SPACE': 'toggle',
      'ARROW_DOWN': 'next',
      'ARROW_UP': 'previous'
    });
  }

  Accordion.defaults = {
    /**
     * Amount of time to animate the opening of an accordion pane.
     * @option
     * @example 250
     */
    slideSpeed: 250,
    /**
     * Allow the accordion to have multiple open panes.
     * @option
     * @example false
     */
    multiExpand: false,
    /**
     * Allow the accordion to close all panes.
     * @option
     * @example false
     */
    allowAllClosed: false
  };

  /**
   * Initializes the accordion by animating the preset active pane(s).
   * @private
   */
  Accordion.prototype._init = function() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.children('li');
    if (this.$tabs.length === 0) {
      this.$tabs = this.$element.children('[data-accordion-item]');
    }
    this.$tabs.each(function(idx, el){

      var $el = $(el),
          $content = $el.find('[data-tab-content]'),
          id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
          linkId = el.id || id + '-label';

      $el.find('a:first').attr({
        'aria-controls': id,
        'role': 'tab',
        'id': linkId,
        'aria-expanded': false,
        'aria-selected': false
      });
      $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    if($initActive.length){
      this.down($initActive, true);
    }
    this._events();
  };

  /**
   * Adds event handlers for items within the accordion.
   * @private
   */
  Accordion.prototype._events = function() {
    var _this = this;

    this.$tabs.each(function(){
      var $elem = $(this);
      var $tabContent = $elem.children('[data-tab-content]');
      if ($tabContent.length) {
        $elem.children('a').off('click.zf.accordion keydown.zf.accordion')
               .on('click.zf.accordion', function(e){
        // $(this).children('a').on('click.zf.accordion', function(e) {
          e.preventDefault();
          if ($elem.hasClass('is-active')) {
            if(_this.options.allowAllClosed || $elem.siblings().hasClass('is-active')){
              _this.up($tabContent);
            }
          }
          else {
            _this.down($tabContent);
          }
        }).on('keydown.zf.accordion', function(e){
          Foundation.Keyboard.handleKey(e, 'Accordion', {
            toggle: function() {
              _this.toggle($tabContent);
            },
            next: function() {
              $elem.next().find('a').focus().trigger('click.zf.accordion');
            },
            previous: function() {
              $elem.prev().find('a').focus().trigger('click.zf.accordion');
            },
            handled: function() {
              e.preventDefault();
              e.stopPropagation();
            }
          });
        });
      }
    });
  };
  /**
   * Toggles the selected content pane's open/close state.
   * @param {jQuery} $target - jQuery object of the pane to toggle.
   * @function
   */
  Accordion.prototype.toggle = function($target){
    if($target.parent().hasClass('is-active')){
      if(this.options.allowAllClosed || $target.parent().siblings().hasClass('is-active')){
        this.up($target);
      }else{ return; }
    }else{
      this.down($target);
    }
  };
  /**
   * Opens the accordion tab defined by `$target`.
   * @param {jQuery} $target - Accordion pane to open.
   * @param {Boolean} firstTime - flag to determine if reflow should happen.
   * @fires Accordion#down
   * @function
   */
  Accordion.prototype.down = function($target, firstTime) {
    var _this = this;
    if(!this.options.multiExpand && !firstTime){
      var $currentActive = this.$element.find('.is-active').children('[data-tab-content]');
      if($currentActive.length){
        this.up($currentActive);
      }
    }

    $target
      .attr('aria-hidden', false)
      .parent('[data-tab-content]')
      .addBack()
      .parent().addClass('is-active');

    // Foundation.Move(_this.options.slideSpeed, $target, function(){
      $target.slideDown(_this.options.slideSpeed, function () {
        /**
         * Fires when the tab is done opening.
         * @event Accordion#down
         */
        _this.$element.trigger('down.zf.accordion', [$target]);
      });
    // });

    // if(!firstTime){
    //   Foundation._reflow(this.$element.attr('data-accordion'));
    // }
    $('#' + $target.attr('aria-labelledby')).attr({
      'aria-expanded': true,
      'aria-selected': true
    });
  };

  /**
   * Closes the tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to close.
   * @fires Accordion#up
   * @function
   */
  Accordion.prototype.up = function($target) {
    var $aunts = $target.parent().siblings(),
        _this = this;
    var canClose = this.options.multiExpand ? $aunts.hasClass('is-active') : $target.parent().hasClass('is-active');

    if(!this.options.allowAllClosed && !canClose){
      return;
    }

    // Foundation.Move(this.options.slideSpeed, $target, function(){
      $target.slideUp(_this.options.slideSpeed, function () {
        /**
         * Fires when the tab is done collapsing up.
         * @event Accordion#up
         */
        _this.$element.trigger('up.zf.accordion', [$target]);
      });
    // });

    $target.attr('aria-hidden', true)
           .parent().removeClass('is-active');

    $('#' + $target.attr('aria-labelledby')).attr({
     'aria-expanded': false,
     'aria-selected': false
   });
  };

  /**
   * Destroys an instance of an accordion.
   * @fires Accordion#destroyed
   * @function
   */
  Accordion.prototype.destroy = function() {
    this.$element.find('[data-tab-content]').slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');

    Foundation.unregisterPlugin(this);
  };

  Foundation.plugin(Accordion, 'Accordion');
}(jQuery, window.Foundation);
<commit_msg>Converted Acoordion string concatenations to template literals<commit_after>/**
 * Accordion module.
 * @module foundation.accordion
 * @requires foundation.util.keyboard
 * @requires foundation.util.motion
 */
!function($, Foundation) {
  'use strict';

  /**
   * Creates a new instance of an accordion.
   * @class
   * @fires Accordion#init
   * @param {jQuery} element - jQuery object to make into an accordion.
   * @param {Object} options - a plain object with settings to override the default options.
   */
  function Accordion(element, options){
    this.$element = element;
    this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);

    this._init();

    Foundation.registerPlugin(this, 'Accordion');
    Foundation.Keyboard.register('Accordion', {
      'ENTER': 'toggle',
      'SPACE': 'toggle',
      'ARROW_DOWN': 'next',
      'ARROW_UP': 'previous'
    });
  }

  Accordion.defaults = {
    /**
     * Amount of time to animate the opening of an accordion pane.
     * @option
     * @example 250
     */
    slideSpeed: 250,
    /**
     * Allow the accordion to have multiple open panes.
     * @option
     * @example false
     */
    multiExpand: false,
    /**
     * Allow the accordion to close all panes.
     * @option
     * @example false
     */
    allowAllClosed: false
  };

  /**
   * Initializes the accordion by animating the preset active pane(s).
   * @private
   */
  Accordion.prototype._init = function() {
    this.$element.attr('role', 'tablist');
    this.$tabs = this.$element.children('li');
    if (this.$tabs.length === 0) {
      this.$tabs = this.$element.children('[data-accordion-item]');
    }
    this.$tabs.each(function(idx, el){

      var $el = $(el),
          $content = $el.find('[data-tab-content]'),
          id = $content[0].id || Foundation.GetYoDigits(6, 'accordion'),
          linkId = el.id || `${id}-label`;

      $el.find('a:first').attr({
        'aria-controls': id,
        'role': 'tab',
        'id': linkId,
        'aria-expanded': false,
        'aria-selected': false
      });
      $content.attr({'role': 'tabpanel', 'aria-labelledby': linkId, 'aria-hidden': true, 'id': id});
    });
    var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
    if($initActive.length){
      this.down($initActive, true);
    }
    this._events();
  };

  /**
   * Adds event handlers for items within the accordion.
   * @private
   */
  Accordion.prototype._events = function() {
    var _this = this;

    this.$tabs.each(function(){
      var $elem = $(this);
      var $tabContent = $elem.children('[data-tab-content]');
      if ($tabContent.length) {
        $elem.children('a').off('click.zf.accordion keydown.zf.accordion')
               .on('click.zf.accordion', function(e){
        // $(this).children('a').on('click.zf.accordion', function(e) {
          e.preventDefault();
          if ($elem.hasClass('is-active')) {
            if(_this.options.allowAllClosed || $elem.siblings().hasClass('is-active')){
              _this.up($tabContent);
            }
          }
          else {
            _this.down($tabContent);
          }
        }).on('keydown.zf.accordion', function(e){
          Foundation.Keyboard.handleKey(e, 'Accordion', {
            toggle: function() {
              _this.toggle($tabContent);
            },
            next: function() {
              $elem.next().find('a').focus().trigger('click.zf.accordion');
            },
            previous: function() {
              $elem.prev().find('a').focus().trigger('click.zf.accordion');
            },
            handled: function() {
              e.preventDefault();
              e.stopPropagation();
            }
          });
        });
      }
    });
  };
  /**
   * Toggles the selected content pane's open/close state.
   * @param {jQuery} $target - jQuery object of the pane to toggle.
   * @function
   */
  Accordion.prototype.toggle = function($target){
    if($target.parent().hasClass('is-active')){
      if(this.options.allowAllClosed || $target.parent().siblings().hasClass('is-active')){
        this.up($target);
      }else{ return; }
    }else{
      this.down($target);
    }
  };
  /**
   * Opens the accordion tab defined by `$target`.
   * @param {jQuery} $target - Accordion pane to open.
   * @param {Boolean} firstTime - flag to determine if reflow should happen.
   * @fires Accordion#down
   * @function
   */
  Accordion.prototype.down = function($target, firstTime) {
    var _this = this;
    if(!this.options.multiExpand && !firstTime){
      var $currentActive = this.$element.find('.is-active').children('[data-tab-content]');
      if($currentActive.length){
        this.up($currentActive);
      }
    }

    $target
      .attr('aria-hidden', false)
      .parent('[data-tab-content]')
      .addBack()
      .parent().addClass('is-active');

    // Foundation.Move(_this.options.slideSpeed, $target, function(){
      $target.slideDown(_this.options.slideSpeed, function () {
        /**
         * Fires when the tab is done opening.
         * @event Accordion#down
         */
        _this.$element.trigger('down.zf.accordion', [$target]);
      });
    // });

    // if(!firstTime){
    //   Foundation._reflow(this.$element.attr('data-accordion'));
    // }
    $(`#${$target.attr('aria-labelledby')}`).attr({
      'aria-expanded': true,
      'aria-selected': true
    });
  };

  /**
   * Closes the tab defined by `$target`.
   * @param {jQuery} $target - Accordion tab to close.
   * @fires Accordion#up
   * @function
   */
  Accordion.prototype.up = function($target) {
    var $aunts = $target.parent().siblings(),
        _this = this;
    var canClose = this.options.multiExpand ? $aunts.hasClass('is-active') : $target.parent().hasClass('is-active');

    if(!this.options.allowAllClosed && !canClose){
      return;
    }

    // Foundation.Move(this.options.slideSpeed, $target, function(){
      $target.slideUp(_this.options.slideSpeed, function () {
        /**
         * Fires when the tab is done collapsing up.
         * @event Accordion#up
         */
        _this.$element.trigger('up.zf.accordion', [$target]);
      });
    // });

    $target.attr('aria-hidden', true)
           .parent().removeClass('is-active');

    $(`#${$target.attr('aria-labelledby')}`).attr({
     'aria-expanded': false,
     'aria-selected': false
   });
  };

  /**
   * Destroys an instance of an accordion.
   * @fires Accordion#destroyed
   * @function
   */
  Accordion.prototype.destroy = function() {
    this.$element.find('[data-tab-content]').slideUp(0).css('display', '');
    this.$element.find('a').off('.zf.accordion');

    Foundation.unregisterPlugin(this);
  };

  Foundation.plugin(Accordion, 'Accordion');
}(jQuery, window.Foundation);
<|endoftext|>


<commit_before>import _ from 'lodash'

export default class Slug {
  static normalize(value, retain_path) {
    if (Array.isArray(value)) {
      return Slug.normalize_array(value, retain_path);
    }

    let parsed = (/([/]?[\w\d -_]{1,}[/])?(.*)/g).exec(value.toLowerCase());

    let path = parsed[1] || '',
        slug = parsed[2]
               .replace(/[^\w\d/_]/g, '-')          // replace all non-valid characters with -'s
               .replace(/-{2,}/g, '-')              // replace all sequential -'s with a single -
               .replace(/(^[-]{1,})|(-$){1,}/g, '') // remove all leading or trailing -'s
    ;

    return retain_path ? path + slug : slug;
  }
  static normalize_array(values, retain_path) {
    return _.difference(_.sortBy(_.uniq(values.map(value => Slug.normalize(value, retain_path)))));
  }
}<commit_msg>normalize_array now properly removes empty entries<commit_after>import _ from 'lodash'

export default class Slug {
  static normalize(value, retain_path) {
    if (Array.isArray(value)) {
      return Slug.normalize_array(value, retain_path);
    }

    let parsed = (/([/]?[\w\d -_]{1,}[/])?(.*)/g).exec(value.toLowerCase());

    let path = parsed[1] || '',
        slug = parsed[2]
               .replace(/[^\w\d/_]/g, '-')          // replace all non-valid characters with -'s
               .replace(/-{2,}/g, '-')              // replace all sequential -'s with a single -
               .replace(/(^[-]{1,})|(-$){1,}/g, '') // remove all leading or trailing -'s
    ;

    return retain_path ? path + slug : slug;
  }
  static normalize_array(values, retain_path) {
    return _.difference(_.sortBy(_.uniq(values.map(value => Slug.normalize(value, retain_path)))), ['']);
  }
}<|endoftext|>


<commit_before>/*
 * app/lib/commands/create.js
 *
 *
 * Copyright (C) 2015  Pierre Marchand <pierremarc07@gmail.com>
 *
 * License in LICENSE file at the root of the repository.
 *
 */

var Promise = require('bluebird'),
    region = require('../Region');

function createGroup (uid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        shell = ctx.shell,
        terminal = shell.terminal;

    stdout.write('select a status');
    stdout.write('1 : public');
    stdout.write('2 : private');

    terminal.input(stdin);
    stdin.read()
        .then(function(input){
            var pp = parseInt(input);
            if(!pp || pp > 2){
                return reject('Not a valid value');
            }
            stdout.write('enter a name');
            shell.terminal.input(stdin);
            stdin.read()
                .then(function(name){
                    var data = {
                        user_id: uid,
                        status_flag: (pp - 1),
                        properties: {'name':name}
                    };
                    ctx.binder.setGroup(uid, data)
                        .then(function(model){
                            var cmd = terminal.makeCommand({
                                args: ['cc /'+uid+'/'+model.id],
                                text: (model.get('name') || model.id)
                            });
                            stdout.write(cmd);
                            resolve(model);
                        });
                });
        })
        .catch(reject);
}

function createLayer (uid, gid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        terminal = ctx.shell.terminal;

    stdout.write('enter a name');
    terminal.input(stdin);
    stdin.read()
        .then(function(name){
            var data = {
                user_id: uid,
                properties: {'name':name}
            };
            binder.setLayer(uid, gid, data)
                .then(function(model){
                    var cmd = terminal.makeCommand({
                        args: ['cc /'+uid+'/'+gid+'/'+model.id],
                        text: (model.get('name') || model.id)
                    });
                    stdout.write('created layer ', cmd);
                    resolve(model);
                });
        })
        .catch(reject);
}

function createFeature (uid, gid, lid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        terminal = ctx.shell.terminal,
        extent = region.get(),
        center = extent.getCenter();

        var data = {
            user_id: uid,
            layer_id: lid,
            properties: {},
            geom: JSON.parse(center.format())
        };

        return binder.setFeature(uid, gid, lid, data)
            .then(function(model){
                var cmd = terminal.makeCommand({
                    args: ['cc /'+uid+'/'+gid+'/'+lid+'/'+model.id],
                    text: model.id
                });
                stdout.write('created feature ', cmd);
                resolve(model);
            })
            .catch(reject);
}

function iCreate () {
    var self = this,
        terminal = self.shell.terminal,
        stdout = self.sys.stdout,
        stdin = self.sys.stdin,
        current = self.current();

    stdout.write('select type:');
    if (1 === current.length) {
        stdout.write('1 : group');
    }
    else if (2 === current.length) {
        stdout.write('1 : group');
        stdout.write('2 : layer');
    }
    else if (3 === current.length) {
        stdout.write('1 : group');
        stdout.write('2 : layer');
        stdout.write('3 : feature');
    }

    var cType = 0;

    var resolver = function (resolve, reject) {
        terminal.input(stdin);
        stdin.read()
            .then(function(input){
                cType = parseInt(input);
                if(!cType){
                    return reject('Invalid Value');
                }
                if(cType <= 0){
                    return reject('Invalid Value');
                }
                if(cType > 3){
                    return reject('Invalid Value');
                }
                if(1 === cType){
                    createGroup(current[0], self, resolve, reject);
                }
                else if(2 === cType){
                    createLayer(current[0], current[1], self, resolve, reject);
                }
                else if(3 === cType){
                    createFeature(current[0], current[1], current[2], self, resolve, reject);
                }
            }).catch(reject);
    };

    return (new Promise(resolver));
}

module.exports = exports = {
    name: 'ic',
    command: iCreate
};
<commit_msg>added description step when created layer and group<commit_after>/*
 * app/lib/commands/create.js
 *
 *
 * Copyright (C) 2015  Pierre Marchand <pierremarc07@gmail.com>
 *
 * License in LICENSE file at the root of the repository.
 *
 */

var Promise = require('bluebird'),
    region = require('../Region');

function createGroup (uid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        shell = ctx.shell,
        terminal = shell.terminal;

    stdout.write('select a status');
    stdout.write('1 : public');
    stdout.write('2 : private');

    terminal.input(stdin);
    stdin.read()
        .then(function(input){
            var pp = parseInt(input);
            if(!pp || pp > 2){
                return reject('Not a valid value');
            }
            stdout.write('enter a name');
            shell.terminal.input(stdin);
            stdin.read()
                .then(function(name){

                    stdout.write('enter a description');
                    terminal.input(stdin);
                    stdin.read()
                        .then(function(desc){
                            var data = {
                                user_id: uid,
                                status_flag: (pp - 1),
                                properties: {'name':name,'description':desc}
                            };

                            ctx.binder.setGroup(uid, data)
                                .then(function(model){
                                    var cmd = terminal.makeCommand({
                                        args: ['cc /'+uid+'/'+model.id],
                                        text: (model.get('name') || model.id)
                                    });
                                    stdout.write(cmd);
                                    resolve(model);
                                });
                        })
                });
        })
        .catch(reject);
}

function createLayer (uid, gid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        terminal = ctx.shell.terminal;

    stdout.write('enter a name');
    terminal.input(stdin);
    stdin.read()
        .then(function(name){

            stdout.write('enter a description');
            terminal.input(stdin);
            stdin.read()
                .then(function(desc){
                    var data = {
                        user_id: uid,
                        properties: {'name':name,'description':desc}
                    };

                    binder.setLayer(uid, gid, data)
                        .then(function(model){
                            var cmd = terminal.makeCommand({
                                args: ['cc /'+uid+'/'+gid+'/'+model.id],
                                text: (model.get('name') || model.id)
                            });
                            stdout.write('created layer ', cmd);
                            resolve(model);
                        });
                })
        })
        .catch(reject);
}

// function createLayer (uid, gid, ctx, resolve, reject) {
//     var binder = ctx.binder,
//         stdout = ctx.sys.stdout,
//         stdin = ctx.sys.stdin,
//         terminal = ctx.shell.terminal;

//     stdout.write('enter a name');
//     terminal.input(stdin);
//     stdin.read()
//         .then(function(name){
//             var data = {
//                 user_id: uid,
//                 properties: {'name':name}
//             };

//             binder.setLayer(uid, gid, data)
//                 .then(function(model){
//                     var cmd = terminal.makeCommand({
//                         args: ['cc /'+uid+'/'+gid+'/'+model.id],
//                         text: (model.get('name') || model.id)
//                     });
//                     stdout.write('created layer ', cmd);
//                     resolve(model);
//                 });
//         })
//         .catch(reject);
// }

function createFeature (uid, gid, lid, ctx, resolve, reject) {
    var binder = ctx.binder,
        stdout = ctx.sys.stdout,
        stdin = ctx.sys.stdin,
        terminal = ctx.shell.terminal,
        extent = region.get(),
        center = extent.getCenter();

        var data = {
            user_id: uid,
            layer_id: lid,
            properties: {},
            geom: JSON.parse(center.format())
        };

        return binder.setFeature(uid, gid, lid, data)
            .then(function(model){
                var cmd = terminal.makeCommand({
                    args: ['cc /'+uid+'/'+gid+'/'+lid+'/'+model.id],
                    text: model.id
                });
                stdout.write('created feature ', cmd);
                resolve(model);
            })
            .catch(reject);
}

function iCreate () {
    var self = this,
        terminal = self.shell.terminal,
        stdout = self.sys.stdout,
        stdin = self.sys.stdin,
        current = self.current();

    stdout.write('select type:');
    if (1 === current.length) {
        stdout.write('1 : group');
    }
    else if (2 === current.length) {
        stdout.write('1 : group');
        stdout.write('2 : layer');
    }
    else if (3 === current.length) {
        stdout.write('1 : group');
        stdout.write('2 : layer');
        stdout.write('3 : feature');
    }

    var cType = 0;

    var resolver = function (resolve, reject) {
        terminal.input(stdin);
        stdin.read()
            .then(function(input){
                cType = parseInt(input);
                if(!cType){
                    return reject('Invalid Value');
                }
                if(cType <= 0){
                    return reject('Invalid Value');
                }
                if(cType > 3){
                    return reject('Invalid Value');
                }
                if(1 === cType){
                    createGroup(current[0], self, resolve, reject);
                }
                else if(2 === cType){
                    createLayer(current[0], current[1], self, resolve, reject);
                }
                else if(3 === cType){
                    createFeature(current[0], current[1], current[2], self, resolve, reject);
                }
            }).catch(reject);
    };

    return (new Promise(resolver));
}

module.exports = exports = {
    name: 'ic',
    command: iCreate
};
<|endoftext|>


<commit_before>(function() {

	var space = " ";

	var hasClass = function(elem, className) {
	  return elem.className && (elem.className == className || (space + elem.className + space).indexOf(space + className + space) !== -1);
	};

	core.Module("core.bom.ClassName",
	{
		add : function(elem, className)
		{
			if (!hasClass(elem, className)) {
				elem.className += space + className;
			}
		},

		remove : function(elem, className) {
			(space + elem.className + space).replace(className, "")
		},

		has : hasClass
	});

})();
<commit_msg>Added some docs and added support for classList<commit_after>(function()
{
	if ("classList" in document.createElement("div"))
	{

		var addClass = function(elem, className) {
			elem.classList.add(className);
		};

		var removeClass = function(elem, className) {
			elem.classList.remove(className);
		};

		var containsClass = function(elem, className) {
			return elem.classList.contains(className);
		};

		var toggleClass = function(elem, className) {
			elem.classList.toggle(className);
		};

	}
	else
	{

		var space = " ";

		var addClass = function(elem, className)
		{
			if (!containsClass(elem, className)) {
				elem.className += space + className;
			}
		};

		var removeClass = function(elem, className) {
			elem.className = (space + elem.className + space).replace(className, "")
		};

		var containsClass = function(elem, className) {
		  return elem.className && (elem.className == className || (space + elem.className + space).indexOf(space + className + space) !== -1);
		};

		var toggleClass = function(elem, className)
		{
			if (containsClass(elem, className)) {
				removeClass(elem, className);
			} else {
				elem.className += space + className;
			}
		};

	}

	/**
	 * Managing class names on DOM nodes the easy way.
	 *
	 * Makes use of high-performance `classList` interface in modern browsers:
	 * https://developer.mozilla.org/en/DOM/element.classList
	 */
	core.Module("core.bom.ClassName",
	{
		/**
		 * Adds a class to an element's list of classes
		 *
		 * @param elem {Element} DOM element to modify
		 * @param className {String} Class to add
		 */
		add : addClass,

		/**
		 * Removes a class from an element's list of classes
		 *
		 * @param elem {Element} DOM element to modify
		 * @param className {String} Class to remove
		 */
		remove : removeClass,

		/**
		 * Whether the given node contains the given class
		 *
		 * @param elem {Element} DOM element to modify
		 * @param className {String} Class to check for
		 * @return {Boolean} Whether the element contains the given class
		 */
		contains : containsClass,

		/**
		 * Toggles the existence of a class in an element's list of classes
		 *
		 * @param elem {Element} DOM element to modify
		 * @param className {String} Class to toggle
		 */
		toggle : toggleClass
	});

})();
<|endoftext|>


<commit_before>iD.operations.Delete = function(selectedIDs, context) {
    var action = iD.actions.DeleteMultiple(selectedIDs);

    var operation = function() {
        var annotation,
            nextSelectedID;

        if (selectedIDs.length > 1) {
            annotation = t('operations.delete.annotation.multiple', {n: selectedIDs.length});

        } else {
            var id = selectedIDs[0],
                entity = context.entity(id),
                geometry = context.geometry(id),
                parents = context.graph().parentWays(entity),
                parent = parents[0];

            annotation = t('operations.delete.annotation.' + geometry);

            // Select the next closest node in the way.
            if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
                var nodes = parent.nodes,
                    i = nodes.indexOf(id);

                if (i === 0) {
                    i++;
                } else if (i === nodes.length - 1) {
                    i--;
                } else {
                    var a = iD.geo.dist(entity.loc, context.entity(nodes[i - 1]).loc),
                        b = iD.geo.dist(entity.loc, context.entity(nodes[i + 1]).loc);
                    i = a < b ? i - 1 : i + 1;
                }

                nextSelectedID = nodes[i];
            }
        }

        context.perform(
            action,
            annotation);

        if (nextSelectedID && context.hasEntity(nextSelectedID)) {
            context.enter(iD.modes.Select(context, [nextSelectedID]));
        } else {
            context.enter(iD.modes.Browse(context));
        }
    };

    operation.available = function() {
        return true;
    };

    operation.disabled = function() {
        return action.disabled(context.graph());
    };

    operation.tooltip = function() {
        var disable = operation.disabled();
        return disable ?
            t('operations.delete.' + disable) :
            t('operations.delete.description');
    };

    operation.id = "delete";
    operation.keys = [iD.ui.cmd('⌫'), iD.ui.cmd('⌦')];
    operation.title = t('operations.delete.title');

    return operation;
};
<commit_msg>Change delete shortcut to ⌘⌫/Ctrl-Backspace<commit_after>iD.operations.Delete = function(selectedIDs, context) {
    var action = iD.actions.DeleteMultiple(selectedIDs);

    var operation = function() {
        var annotation,
            nextSelectedID;

        if (selectedIDs.length > 1) {
            annotation = t('operations.delete.annotation.multiple', {n: selectedIDs.length});

        } else {
            var id = selectedIDs[0],
                entity = context.entity(id),
                geometry = context.geometry(id),
                parents = context.graph().parentWays(entity),
                parent = parents[0];

            annotation = t('operations.delete.annotation.' + geometry);

            // Select the next closest node in the way.
            if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
                var nodes = parent.nodes,
                    i = nodes.indexOf(id);

                if (i === 0) {
                    i++;
                } else if (i === nodes.length - 1) {
                    i--;
                } else {
                    var a = iD.geo.dist(entity.loc, context.entity(nodes[i - 1]).loc),
                        b = iD.geo.dist(entity.loc, context.entity(nodes[i + 1]).loc);
                    i = a < b ? i - 1 : i + 1;
                }

                nextSelectedID = nodes[i];
            }
        }

        context.perform(
            action,
            annotation);

        if (nextSelectedID && context.hasEntity(nextSelectedID)) {
            context.enter(iD.modes.Select(context, [nextSelectedID]));
        } else {
            context.enter(iD.modes.Browse(context));
        }
    };

    operation.available = function() {
        return true;
    };

    operation.disabled = function() {
        return action.disabled(context.graph());
    };

    operation.tooltip = function() {
        var disable = operation.disabled();
        return disable ?
            t('operations.delete.' + disable) :
            t('operations.delete.description');
    };

    operation.id = "delete";
    operation.keys = [iD.ui.cmd('⌘⌫'), iD.ui.cmd('⌘⌦')];
    operation.title = t('operations.delete.title');

    return operation;
};
<|endoftext|>


<commit_before>'use strict';

const Module = require('module');
const {getRequire} = require('./util');

/**
 * Reference to the global module cache.  If not found return a new object created from a null prototype.
 *
 * @type {Object}
 */
const globalCache = (()=>{
  try {
    return getRequire().cache;
  } catch (err) {
    return Object.create(null);
  }
})();

/**
 * An interface to the global module cache.
 *
 * @class
 */
class Cache {
  /**
   * Get a module from the global module cache.
   *
   * @param {string} property     Module path to get for.
   */
  get(property) {
    return globalCache[property];
  }

  /**
   * Set a module in the global module cache.
   *
   * @param {string} property     Module to set
   * @param {Module} value        Module value.
   * @returns {boolean}           Did it set?
   */
  set(property, value) {
    if (!(value instanceof Module)) throw new TypeError('Cannot add a non-module to the cache.');
    globalCache[property] = value;
    return true;
  }

  /**
   * Does the global module cache have the given module?
   *
   * @param {string} property     Module to check.
   * @returns {boolean}           Is it there?
   */
  has(property) {
    return (property in globalCache);
  }

  /**
   * Delete a given module from the cache.
   *
   * @param {string} property   Module to delete.
   * @returns {boolean}         Was anything deleted?
   */
  delete(property) {
    if (this.has(property)) {
      delete globalCache[property];
      return true;
    }
    return false;
  }

  /**
   * Clear the cache.
   *
   * @returns {boolean}     Did it clear?
   */
  clear() {
    Object.keys(globalCache).forEach(property=>this.delete(property));
    return true;
  }

  /**
   * Current cache size.
   *
   * @returns {Number}
   */
  get size() {
    return Object.keys(globalCache).length;
  }

  /**
   * Return a reference to the global cache (or the one we are using if it was not found).
   */
  get source() {
    return globalCache;
  }
}

module.exports = new Cache();<commit_msg>Allow hard-link following<commit_after>'use strict';

const Module = require('module');
const {getRequire} = require('./util');
const fs = require('fs');
const settings = require('./settings');
const refs = new Map();
const refLookup = new Map();

/**
 * Reference to the global module cache.  If not found return a new object created from a null prototype.
 *
 * @type {Object}
 */
const globalCache = (()=>{
  try {
    return getRequire().cache;
  } catch (err) {
    return Object.create(null);
  }
})();

function getRef(property) {
  if (!settings.get('followHardLinks')) return;
  try {
    if (refLookup.has(property)) return refLookup.get(property);
    const stats = fs.statSync(property);
    const ref = `${stats.dev}:${stats.ino}`;
    refLookup.set(property, ref);
    return ref;
  } catch(err) {
    console.log(err)
  }
}

/**
 * An interface to the global module cache.
 *
 * @class
 */
class Cache {
  /**
   * Get a module from the global module cache.
   *
   * @param {string} property     Module path to get for.
   */
  get(property) {
    let module = globalCache[property];
    if (!!module) return module;
    const ref = getRef(property);
    if (refs && refs.has(ref)) {
      const otherProp = refs.get(ref);
      module = this.get(otherProp);
      if (!!module) return module;
    }
  }

  /**
   * Set a module in the global module cache.
   *
   * @param {string} property     Module to set
   * @param {Module} value        Module value.
   * @returns {boolean}           Did it set?
   */
  set(property, value) {
    if (!(value instanceof Module)) throw new TypeError('Cannot add a non-module to the cache.');
    globalCache[property] = value;
    const ref = getRef(property);
    if (ref) refs.set(ref, property);
    return true;
  }

  /**
   * Does the global module cache have the given module?
   *
   * @param {string} property     Module to check.
   * @returns {boolean}           Is it there?
   */
  has(property) {
    if (property in globalCache) return true;
    const ref = getRef(property);
    if (ref && refs.has(ref)) return true;
    return false;
  }

  /**
   * Delete a given module from the cache.
   *
   * @param {string} property   Module to delete.
   * @returns {boolean}         Was anything deleted?
   */
  delete(property) {
    if (this.has(property)) {
      delete globalCache[property];
      const ref = getRef(property);
      if (ref) return refs.delete(ref);
      return true;
    }
    return false;
  }

  /**
   * Clear the cache.
   *
   * @returns {boolean}     Did it clear?
   */
  clear() {
    Object.keys(globalCache).forEach(property=>this.delete(property));
    return true;
  }

  /**
   * Current cache size.
   *
   * @returns {Number}
   */
  get size() {
    return Object.keys(globalCache).length;
  }

  /**
   * Return a reference to the global cache (or the one we are using if it was not found).
   */
  get source() {
    return globalCache;
  }
}

module.exports = new Cache();<|endoftext|>


<commit_before><commit_msg>Create Level 4<commit_after>var LevelFour = function(){
  this.bricks = [
    new Brick(200, 25),
    new Brick(200, 50),
    new Brick(200, 75),
    new Brick(200, 100),
    new Brick(200, 125),
    new Brick(200, 150),
    new Brick(200, 175),
    new Brick(200, 200),
    new Brick(540, 25),
    new Brick(540, 50),
    new Brick(540, 75),
    new Brick(540, 100),
    new Brick(540, 125),
    new Brick(540, 150),
    new Brick(540, 175),
    new Brick(540, 200),
    new Brick(285, 200),
    new Brick(370, 200),
    new Brick(455, 200),
    new Brick(285, 25),
    new Brick(370, 25),
    new Brick(455, 25),
  ]
}
<|endoftext|>


<commit_before>/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */

'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const series = require('async/series')
const pull = require('pull-stream')
const dagPB = require('ipld-dag-pb')
const DAGNode = dagPB.DAGNode
const dagCBOR = require('ipld-dag-cbor')
const CID = require('cids')

module.exports = (common) => {
  describe('.dag', () => {
    let ipfs
    let withGo

    before(function (done) {
      // CI takes longer to instantiate the daemon, so we need to increase the
      // timeout for the before step
      this.timeout(60 * 1000)

      common.setup((err, factory) => {
        expect(err).to.not.exist()
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist()
          ipfs = node
          ipfs.id((err, id) => {
            expect(err).to.not.exist()
            withGo = id.agentVersion.startsWith('go-ipfs')
            done()
          })
        })
      })
    })

    after((done) => common.teardown(done))

    let pbNode
    let cborNode

    before((done) => {
      const someData = Buffer.from('some data')

      pbNode = DAGNode.create(someData, (err, node) => {
        expect(err).to.not.exist()
        pbNode = node
        done()
      })

      cborNode = {
        data: someData
      }
    })

    describe('.put', () => {
      it('dag-pb with default hash func (sha2-256)', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha2-256'
        }, done)
      })

      it('dag-pb with custom hash func (sha3-512)', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha3-512'
        }, done)
      })

      // This works because dag-cbor will just treat pbNode as a regular object
      it.skip('dag-pb node with wrong multicodec', (done) => {
        ipfs.dag.put(pbNode, 'dag-cbor', 'sha3-512', (err) => {
          expect(err).to.exist()
          done()
        })
      })

      it('dag-cbor with default hash func (sha2-256)', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, done)
      })

      it('dag-cbor with custom hash func (sha3-512)', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha3-512'
        }, done)
      })

      it('dag-cbor node with wrong multicodec', function (done) {
        // This works in go-ipfs because dag-pb will serialize any object. If
        // the object has neither a `data` nor `links` field it's serialized
        // as an empty object
        if (withGo) {
          this.skip()
        }
        ipfs.dag.put(cborNode, {
          format: 'dag-pb',
          hashAlg: 'sha3-512'
        }, (err) => {
          expect(err).to.exist()
          done()
        })
      })

      it('returns the cid', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          expect(cid).to.exist()
          expect(CID.isCID(cid)).to.equal(true)
          dagCBOR.util.cid(cborNode, (err, _cid) => {
            expect(err).to.not.exist()
            expect(cid.buffer).to.eql(_cid.buffer)
            done()
          })
        })
      })

      it.skip('pass the cid instead of format and hashAlg', (done) => {})

      // TODO it.skip('Promises support', (done) => {})
    })

    describe('.get', () => {
      let pbNode
      let cborNode

      let nodePb
      let nodeCbor
      let cidPb
      let cidCbor

      before((done) => {
        series([
          (cb) => {
            const someData = Buffer.from('some other data')

            pbNode = DAGNode.create(someData, (err, node) => {
              expect(err).to.not.exist()
              pbNode = node
              cb()
            })

            cborNode = {
              data: someData
            }
          },
          (cb) => {
            dagPB.DAGNode.create(Buffer.from('I am inside a Protobuf'), (err, node) => {
              expect(err).to.not.exist()
              nodePb = node
              cb()
            })
          },
          (cb) => {
            dagPB.util.cid(nodePb, (err, cid) => {
              expect(err).to.not.exist()
              cidPb = cid
              cb()
            })
          },
          (cb) => {
            nodeCbor = {
              someData: 'I am inside a Cbor object',
              pb: { '/': cidPb.toBaseEncodedString() }
            }

            dagCBOR.util.cid(nodeCbor, (err, cid) => {
              expect(err).to.not.exist()
              cidCbor = cid
              cb()
            })
          }
        ], store)

        function store () {
          pull(
            pull.values([
              { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
              { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
            ]),
            pull.asyncMap((el, cb) => {
              ipfs.dag.put(el.node, {
                format: el.multicodec,
                hashAlg: el.hashAlg
              }, cb)
            }),
            pull.onEnd(done)
          )
        }
      })

      it('dag-pb node', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          ipfs.dag.get(cid, (err, result) => {
            expect(err).to.not.exist()
            const node = result.value
            expect(pbNode.toJSON()).to.eql(node.toJSON())
            done()
          })
        })
      })

      it('dag-cbor node', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          ipfs.dag.get(cid, (err, result) => {
            expect(err).to.not.exist()

            const node = result.value
            expect(cborNode).to.eql(node)
            done()
          })
        })
      })

      describe('with path', () => {
        it('dag-pb get the node', (done) => {
          ipfs.dag.get(cidPb, '/', (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagPB.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidPb)
              done()
            })
          })
        })

        it('dag-pb local scope', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          ipfs.dag.get(cidPb, 'Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value.data).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })

        it.skip('dag-pb one level', (done) => {})
        it.skip('dag-pb two levels', (done) => {})

        it('dag-cbor get the node', (done) => {
          ipfs.dag.get(cidCbor, '/', (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagCBOR.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('dag-cbor local scope', (done) => {
          ipfs.dag.get(cidCbor, 'someData', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql('I am inside a Cbor object')
            done()
          })
        })

        it.skip('dag-cbor one level', (done) => {})
        it.skip('dag-cbor two levels', (done) => {})
        it.skip('from dag-pb to dag-cbor', (done) => {})

        it('from dag-cbor to dag-pb', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          ipfs.dag.get(cidCbor, 'pb/Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })

        it('CID String', (done) => {
          const cidCborStr = cidCbor.toBaseEncodedString()

          ipfs.dag.get(cidCborStr, (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagCBOR.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('CID String + path', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          const cidCborStr = cidCbor.toBaseEncodedString()

          ipfs.dag.get(cidCborStr + '/pb/Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })
      })
    })

    describe.skip('.tree', function () {
      // TODO vmx 2018-02-22: Currently the tree API is not exposed in go-ipfs
      if (withGo) {
        this.skip()
      }

      let nodePb
      let nodeCbor
      let cidPb
      let cidCbor

      before((done) => {
        series([
          (cb) => {
            dagPB.DAGNode.create(Buffer.from('I am inside a Protobuf'), (err, node) => {
              expect(err).to.not.exist()
              nodePb = node
              cb()
            })
          },
          (cb) => {
            dagPB.util.cid(nodePb, (err, cid) => {
              expect(err).to.not.exist()
              cidPb = cid
              cb()
            })
          },
          (cb) => {
            nodeCbor = {
              someData: 'I am inside a Cbor object',
              pb: { '/': cidPb.toBaseEncodedString() }
            }

            dagCBOR.util.cid(nodeCbor, (err, cid) => {
              expect(err).to.not.exist()
              cidCbor = cid
              cb()
            })
          }
        ], store)

        function store () {
          pull(
            pull.values([
              { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
              { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
            ]),
            pull.asyncMap((el, cb) => {
              ipfs.dag.put(el.node, {
                format: el.multicodec,
                hashAlg: el.hashAlg
              }, cb)
            }),
            pull.onEnd(done)
          )
        }
      })

      it('.tree with CID', (done) => {
        ipfs.dag.tree(cidCbor, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'pb',
            'someData'
          ])
          done()
        })
      })

      it('.tree with CID and path', (done) => {
        ipfs.dag.tree(cidCbor, 'someData', (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([])
          done()
        })
      })

      it('.tree with CID and path as String', (done) => {
        const cidCborStr = cidCbor.toBaseEncodedString()

        ipfs.dag.tree(cidCborStr + '/someData', (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([])
          done()
        })
      })

      it('.tree with CID recursive (accross different formats)', (done) => {
        ipfs.dag.tree(cidCbor, { recursive: true }, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'pb',
            'someData',
            'pb/Links',
            'pb/Data'
          ])
          done()
        })
      })

      it('.tree with CID and path recursive', (done) => {
        ipfs.dag.tree(cidCbor, 'pb', { recursive: true }, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'Links',
            'Data'
          ])
          done()
        })
      })
    })
  })
}
<commit_msg>More fixes<commit_after>/* eslint-env mocha */
/* eslint max-nested-callbacks: ["error", 8] */

'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const series = require('async/series')
const pull = require('pull-stream')
const dagPB = require('ipld-dag-pb')
const DAGNode = dagPB.DAGNode
const dagCBOR = require('ipld-dag-cbor')
const CID = require('cids')

module.exports = (common) => {
  describe('.dag', () => {
    let ipfs
    let withGo

    before(function (done) {
      // CI takes longer to instantiate the daemon, so we need to increase the
      // timeout for the before step
      this.timeout(60 * 1000)

      common.setup((err, factory) => {
        expect(err).to.not.exist()
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist()
          ipfs = node
          ipfs.id((err, id) => {
            expect(err).to.not.exist()
            withGo = id.agentVersion.startsWith('go-ipfs')
            done()
          })
        })
      })
    })

    after((done) => common.teardown(done))

    let pbNode
    let cborNode

    before((done) => {
      const someData = Buffer.from('some data')

      pbNode = DAGNode.create(someData, (err, node) => {
        expect(err).to.not.exist()
        pbNode = node
        done()
      })

      cborNode = {
        data: someData
      }
    })

    describe('.put', () => {
      it('dag-pb with default hash func (sha2-256)', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha2-256'
        }, done)
      })

      it('dag-pb with custom hash func (sha3-512)', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha3-512'
        }, done)
      })

      // This works because dag-cbor will just treat pbNode as a regular object
      it.skip('dag-pb node with wrong multicodec', (done) => {
        ipfs.dag.put(pbNode, 'dag-cbor', 'sha3-512', (err) => {
          expect(err).to.exist()
          done()
        })
      })

      it('dag-cbor with default hash func (sha2-256)', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, done)
      })

      it('dag-cbor with custom hash func (sha3-512)', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha3-512'
        }, done)
      })

      it('dag-cbor node with wrong multicodec', function (done) {
        // This works in go-ipfs because dag-pb will serialize any object. If
        // the object has neither a `data` nor `links` field it's serialized
        // as an empty object
        if (withGo) {
          this.skip()
        }
        ipfs.dag.put(cborNode, {
          format: 'dag-pb',
          hashAlg: 'sha3-512'
        }, (err) => {
          expect(err).to.exist()
          done()
        })
      })

      it('returns the cid', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          expect(cid).to.exist()
          expect(CID.isCID(cid)).to.equal(true)
          dagCBOR.util.cid(cborNode, (err, _cid) => {
            expect(err).to.not.exist()
            expect(cid.buffer).to.eql(_cid.buffer)
            done()
          })
        })
      })

      it.skip('pass the cid instead of format and hashAlg', (done) => {})

      // TODO it.skip('Promises support', (done) => {})
    })

    describe('.get', () => {
      let pbNode
      let cborNode

      let nodePb
      let nodeCbor
      let cidPb
      let cidCbor

      before((done) => {
        series([
          (cb) => {
            const someData = Buffer.from('some other data')

            pbNode = DAGNode.create(someData, (err, node) => {
              expect(err).to.not.exist()
              pbNode = node
              cb()
            })

            cborNode = {
              data: someData
            }
          },
          (cb) => {
            dagPB.DAGNode.create(Buffer.from('I am inside a Protobuf'), (err, node) => {
              expect(err).to.not.exist()
              nodePb = node
              cb()
            })
          },
          (cb) => {
            dagPB.util.cid(nodePb, (err, cid) => {
              expect(err).to.not.exist()
              cidPb = cid
              cb()
            })
          },
          (cb) => {
            nodeCbor = {
              someData: 'I am inside a Cbor object',
              pb: { '/': cidPb.toBaseEncodedString() }
            }

            dagCBOR.util.cid(nodeCbor, (err, cid) => {
              expect(err).to.not.exist()
              cidCbor = cid
              cb()
            })
          }
        ], store)

        function store () {
          pull(
            pull.values([
              { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
              { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
            ]),
            pull.asyncMap((el, cb) => {
              ipfs.dag.put(el.node, {
                format: el.multicodec,
                hashAlg: el.hashAlg
              }, cb)
            }),
            pull.onEnd(done)
          )
        }
      })

      it('dag-pb node', (done) => {
        ipfs.dag.put(pbNode, {
          format: 'dag-pb',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          ipfs.dag.get(cid, (err, result) => {
            expect(err).to.not.exist()
            const node = result.value
            expect(pbNode.toJSON()).to.eql(node.toJSON())
            done()
          })
        })
      })

      it('dag-cbor node', (done) => {
        ipfs.dag.put(cborNode, {
          format: 'dag-cbor',
          hashAlg: 'sha2-256'
        }, (err, cid) => {
          expect(err).to.not.exist()
          ipfs.dag.get(cid, (err, result) => {
            expect(err).to.not.exist()

            const node = result.value
            expect(cborNode).to.eql(node)
            done()
          })
        })
      })

      describe('with path', () => {
        it('dag-pb get the node', (done) => {
          ipfs.dag.get(cidPb, '/', (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagPB.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidPb)
              done()
            })
          })
        })

        it('dag-pb local scope', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          ipfs.dag.get(cidPb, 'Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })

        it.skip('dag-pb one level', (done) => {})
        it.skip('dag-pb two levels', (done) => {})

        it('dag-cbor get the node', (done) => {
          ipfs.dag.get(cidCbor, '/', (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagCBOR.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('dag-cbor local scope', (done) => {
          ipfs.dag.get(cidCbor, 'someData', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql('I am inside a Cbor object')
            done()
          })
        })

        it.skip('dag-cbor one level', (done) => {})
        it.skip('dag-cbor two levels', (done) => {})
        it.skip('from dag-pb to dag-cbor', (done) => {})

        it('from dag-cbor to dag-pb', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          ipfs.dag.get(cidCbor, 'pb/Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })

        it('CID String', (done) => {
          const cidCborStr = cidCbor.toBaseEncodedString()

          ipfs.dag.get(cidCborStr, (err, result) => {
            expect(err).to.not.exist()

            const node = result.value

            dagCBOR.util.cid(node, (err, cid) => {
              expect(err).to.not.exist()
              expect(cid).to.eql(cidCbor)
              done()
            })
          })
        })

        it('CID String + path', function (done) {
          // TODO vmx 2018-02-22: Currently not supported in go-ipfs, it might
          // be possible once https://github.com/ipfs/go-ipfs/issues/4728 is
          // done
          if (withGo) {
            this.skip()
          }
          const cidCborStr = cidCbor.toBaseEncodedString()

          ipfs.dag.get(cidCborStr + '/pb/Data', (err, result) => {
            expect(err).to.not.exist()
            expect(result.value).to.eql(Buffer.from('I am inside a Protobuf'))
            done()
          })
        })
      })
    })

    describe.skip('.tree', function () {
      // TODO vmx 2018-02-22: Currently the tree API is not exposed in go-ipfs
      if (withGo) {
        this.skip()
      }

      let nodePb
      let nodeCbor
      let cidPb
      let cidCbor

      before((done) => {
        series([
          (cb) => {
            dagPB.DAGNode.create(Buffer.from('I am inside a Protobuf'), (err, node) => {
              expect(err).to.not.exist()
              nodePb = node
              cb()
            })
          },
          (cb) => {
            dagPB.util.cid(nodePb, (err, cid) => {
              expect(err).to.not.exist()
              cidPb = cid
              cb()
            })
          },
          (cb) => {
            nodeCbor = {
              someData: 'I am inside a Cbor object',
              pb: { '/': cidPb.toBaseEncodedString() }
            }

            dagCBOR.util.cid(nodeCbor, (err, cid) => {
              expect(err).to.not.exist()
              cidCbor = cid
              cb()
            })
          }
        ], store)

        function store () {
          pull(
            pull.values([
              { node: nodePb, multicodec: 'dag-pb', hashAlg: 'sha2-256' },
              { node: nodeCbor, multicodec: 'dag-cbor', hashAlg: 'sha2-256' }
            ]),
            pull.asyncMap((el, cb) => {
              ipfs.dag.put(el.node, {
                format: el.multicodec,
                hashAlg: el.hashAlg
              }, cb)
            }),
            pull.onEnd(done)
          )
        }
      })

      it('.tree with CID', (done) => {
        ipfs.dag.tree(cidCbor, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'pb',
            'someData'
          ])
          done()
        })
      })

      it('.tree with CID and path', (done) => {
        ipfs.dag.tree(cidCbor, 'someData', (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([])
          done()
        })
      })

      it('.tree with CID and path as String', (done) => {
        const cidCborStr = cidCbor.toBaseEncodedString()

        ipfs.dag.tree(cidCborStr + '/someData', (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([])
          done()
        })
      })

      it('.tree with CID recursive (accross different formats)', (done) => {
        ipfs.dag.tree(cidCbor, { recursive: true }, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'pb',
            'someData',
            'pb/Links',
            'pb/Data'
          ])
          done()
        })
      })

      it('.tree with CID and path recursive', (done) => {
        ipfs.dag.tree(cidCbor, 'pb', { recursive: true }, (err, paths) => {
          expect(err).to.not.exist()
          expect(paths).to.eql([
            'Links',
            'Data'
          ])
          done()
        })
      })
    })
  })
}
<|endoftext|>


<commit_before>import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import FadeMixin from './FadeMixin';
import domUtils from './utils/domUtils';
import EventListener from './utils/EventListener';

// TODO:
// - aria-labelledby
// - Add `modal-body` div if only one child passed in that doesn't already have it
// - Tests

/**
 * Gets the correct clientHeight of the modal container
 * when the body/window/document you need to use the docElement clientHeight
 * @param  {HTMLElement} container
 * @param  {ReactElement|HTMLElement} context
 * @return {Number}
 */
function containerClientHeight(container, context) {
  let doc = domUtils.ownerDocument(context);

  return (container === doc.body || container === doc.documentElement)
      ? doc.documentElement.clientHeight
      : container.clientHeight;
}

function getContainer(context){
  return (context.props.container && React.findDOMNode(context.props.container)) ||
    domUtils.ownerDocument(context).body;
}

/**
 * Firefox doesn't have a focusin event so using capture is easiest way to get bubbling
 * IE8 can't do addEventListener, but does have onfocus in, so we use that in ie8
 * @param  {ReactElement|HTMLElement} context
 * @param  {Function} handler
 */
function onFocus(context, handler) {
  let doc = domUtils.ownerDocument(context);
  let useFocusin = !doc.addEventListener
    , remove;

  if (useFocusin) {
    document.attachEvent('onfocusin', handler);
    remove = () => document.detachEvent('onfocusin', handler);
  } else {
    document.addEventListener('focus', handler, true);
    remove = () => document.removeEventListener('focus', handler, true);
  }
  return { remove };
}

let scrollbarSize;

if ( domUtils.canUseDom) {
  let scrollDiv = document.createElement('div');

  scrollDiv.style.position = 'absolute';
  scrollDiv.style.top = '-9999px';
  scrollDiv.style.width = '50px';
  scrollDiv.style.height = '50px';
  scrollDiv.style.overflow = 'scroll';

  document.body.appendChild(scrollDiv);

  scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;

  document.body.removeChild(scrollDiv);
  scrollDiv = null;
}

const Modal = React.createClass({

  mixins: [BootstrapMixin, FadeMixin],

  propTypes: {
    title: React.PropTypes.node,
    backdrop: React.PropTypes.oneOf(['static', true, false]),
    keyboard: React.PropTypes.bool,
    closeButton: React.PropTypes.bool,
    animation: React.PropTypes.bool,
    onRequestHide: React.PropTypes.func.isRequired,
    dialogClassName: React.PropTypes.string,
    enforceFocus: React.PropTypes.bool
  },

  getDefaultProps() {
    return {
      bsClass: 'modal',
      backdrop: true,
      keyboard: true,
      animation: true,
      closeButton: true,
      enforceFocus: true
    };
  },

  getInitialState(){
    return { };
  },

  render() {
    let state = this.state;
    let modalStyle = { ...state.dialogStyles, display: 'block'};
    let dialogClasses = this.getBsClassSet();

    delete dialogClasses.modal;
    dialogClasses['modal-dialog'] = true;

    let classes = {
      modal: true,
      fade: this.props.animation,
      'in': !this.props.animation
    };

    let modal = (

            {this.props.title ? this.renderHeader() : null}
            {this.props.children}

    );

    return this.props.backdrop ?
      this.renderBackdrop(modal, state.backdropStyles) : modal;
  },

  renderBackdrop(modal) {
    let classes = {
      'modal-backdrop': true,
      fade: this.props.animation,
      'in': !this.props.animation
    };

    let onClick = this.props.backdrop === true ?
      this.handleBackdropClick : null;

    return (

        {modal}

    );
  },

  renderHeader() {
    let closeButton;
    if (this.props.closeButton) {
      closeButton = (
        <button type="button" className="close" aria-hidden="true" onClick={this.props.onRequestHide}>×</button>
      );
    }

    return (

        {closeButton}
        {this.renderTitle()}

    );
  },

  renderTitle() {
    return (
      React.isValidElement(this.props.title) ?
        this.props.title :
{this.props.title}

    );
  },

  iosClickHack() {
    // IOS only allows click events to be delegated to the document on elements
    // it considers 'clickable' - anchors, buttons, etc. We fake a click handler on the
    // DOM nodes themselves. Remove if handled by React: https://github.com/facebook/react/issues/1169
    React.findDOMNode(this.refs.modal).onclick = function () {};
    React.findDOMNode(this.refs.backdrop).onclick = function () {};
  },

  componentDidMount() {
    const doc = domUtils.ownerDocument(this);
    const win = domUtils.ownerWindow(this);

    this._onDocumentKeyupListener =
      EventListener.listen(doc, 'keyup', this.handleDocumentKeyUp);

    this._onWindowResizeListener =
        EventListener.listen(win, 'resize', this.handleWindowResize);

    if (this.props.enforceFocus) {
      this._onFocusinListener = onFocus(this, this.enforceFocus);
    }

    let container = getContainer(this);

    container.className += container.className.length ? ' modal-open' : 'modal-open';

    this._containerIsOverflowing = container.scrollHeight > containerClientHeight(container, this);

    this._originalPadding = container.style.paddingRight;

    if (this._containerIsOverflowing) {
      container.style.paddingRight = parseInt(this._originalPadding || 0, 10) + scrollbarSize + 'px';
    }

    if (this.props.backdrop) {
      this.iosClickHack();
    }

    this.setState(this._getStyles() //eslint-disable-line react/no-did-mount-set-state
      , () => this.focusModalContent());
  },

  componentDidUpdate(prevProps) {
    if (this.props.backdrop && this.props.backdrop !== prevProps.backdrop) {
      this.iosClickHack();
      this.setState(this._getStyles()); //eslint-disable-line react/no-did-update-set-state
    }

    if (this.props.container !== prevProps.container) {
      let container = getContainer(this);
      this._containerIsOverflowing = container.scrollHeight > containerClientHeight(container, this);
    }
  },

  componentWillUnmount() {
    this._onDocumentKeyupListener.remove();
    this._onWindowResizeListener.remove();

    if (this._onFocusinListener) {
      this._onFocusinListener.remove();
    }

    let container = getContainer(this);

    container.style.paddingRight = this._originalPadding;

    container.className = container.className.replace(/ ?modal-open/, '');

    this.restoreLastFocus();
  },

  handleBackdropClick(e) {
    if (e.target !== e.currentTarget) {
      return;
    }

    this.props.onRequestHide();
  },

  handleDocumentKeyUp(e) {
    if (this.props.keyboard && e.keyCode === 27) {
      this.props.onRequestHide();
    }
  },

  handleWindowResize() {
    this.setState(this._getStyles());
  },

  focusModalContent () {
    this.lastFocus = domUtils.activeElement(this);
    let modalContent = React.findDOMNode(this.refs.modal);
    modalContent.focus();
  },

  restoreLastFocus () {
    if (this.lastFocus) {
      this.lastFocus.focus();
      this.lastFocus = null;
    }
  },

  enforceFocus() {
    if ( !this.isMounted() ) {
      return;
    }

    let active = domUtils.activeElement(this)
      , modal = React.findDOMNode(this.refs.modal);

    if (modal !== active && !domUtils.contains(modal, active)){
      modal.focus();
    }
  },

  _getStyles() {
    if ( !domUtils.canUseDom ) { return {}; }

    let node = React.findDOMNode(this.refs.modal)
      , scrollHt = node.scrollHeight
      , container = getContainer(this)
      , containerIsOverflowing = this._containerIsOverflowing
      , modalIsOverflowing = scrollHt > containerClientHeight(container, this);

    return {
      dialogStyles: {
        paddingRight: containerIsOverflowing && !modalIsOverflowing ? scrollbarSize : void 0,
        paddingLeft:  !containerIsOverflowing && modalIsOverflowing ? scrollbarSize : void 0
      }
    };
  }
});

export default Modal;
<commit_msg>Remove single variable style declarations<commit_after>import React from 'react';
import classNames from 'classnames';
import BootstrapMixin from './BootstrapMixin';
import FadeMixin from './FadeMixin';
import domUtils from './utils/domUtils';
import EventListener from './utils/EventListener';

// TODO:
// - aria-labelledby
// - Add `modal-body` div if only one child passed in that doesn't already have it
// - Tests

/**
 * Gets the correct clientHeight of the modal container
 * when the body/window/document you need to use the docElement clientHeight
 * @param  {HTMLElement} container
 * @param  {ReactElement|HTMLElement} context
 * @return {Number}
 */
function containerClientHeight(container, context) {
  let doc = domUtils.ownerDocument(context);

  return (container === doc.body || container === doc.documentElement)
      ? doc.documentElement.clientHeight
      : container.clientHeight;
}

function getContainer(context){
  return (context.props.container && React.findDOMNode(context.props.container)) ||
    domUtils.ownerDocument(context).body;
}

/**
 * Firefox doesn't have a focusin event so using capture is easiest way to get bubbling
 * IE8 can't do addEventListener, but does have onfocusin, so we use that in ie8
 * @param  {ReactElement|HTMLElement} context
 * @param  {Function} handler
 */
function onFocus(context, handler) {
  let doc = domUtils.ownerDocument(context);
  let useFocusin = !doc.addEventListener;
  let remove;

  if (useFocusin) {
    document.attachEvent('onfocusin', handler);
    remove = () => document.detachEvent('onfocusin', handler);
  } else {
    document.addEventListener('focus', handler, true);
    remove = () => document.removeEventListener('focus', handler, true);
  }
  return { remove };
}

let scrollbarSize;

if (domUtils.canUseDom) {
  let scrollDiv = document.createElement('div');

  scrollDiv.style.position = 'absolute';
  scrollDiv.style.top = '-9999px';
  scrollDiv.style.width = '50px';
  scrollDiv.style.height = '50px';
  scrollDiv.style.overflow = 'scroll';

  document.body.appendChild(scrollDiv);

  scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;

  document.body.removeChild(scrollDiv);
  scrollDiv = null;
}

const Modal = React.createClass({

  mixins: [BootstrapMixin, FadeMixin],

  propTypes: {
    title: React.PropTypes.node,
    backdrop: React.PropTypes.oneOf(['static', true, false]),
    keyboard: React.PropTypes.bool,
    closeButton: React.PropTypes.bool,
    animation: React.PropTypes.bool,
    onRequestHide: React.PropTypes.func.isRequired,
    dialogClassName: React.PropTypes.string,
    enforceFocus: React.PropTypes.bool
  },

  getDefaultProps() {
    return {
      bsClass: 'modal',
      backdrop: true,
      keyboard: true,
      animation: true,
      closeButton: true,
      enforceFocus: true
    };
  },

  getInitialState(){
    return { };
  },

  render() {
    let state = this.state;
    let modalStyle = { ...state.dialogStyles, display: 'block'};
    let dialogClasses = this.getBsClassSet();

    delete dialogClasses.modal;
    dialogClasses['modal-dialog'] = true;

    let classes = {
      modal: true,
      fade: this.props.animation,
      'in': !this.props.animation
    };

    let modal = (

            {this.props.title ? this.renderHeader() : null}
            {this.props.children}

    );

    return this.props.backdrop ?
      this.renderBackdrop(modal, state.backdropStyles) : modal;
  },

  renderBackdrop(modal) {
    let classes = {
      'modal-backdrop': true,
      fade: this.props.animation,
      'in': !this.props.animation
    };

    let onClick = this.props.backdrop === true ?
      this.handleBackdropClick : null;

    return (

        {modal}

    );
  },

  renderHeader() {
    let closeButton;
    if (this.props.closeButton) {
      closeButton = (
        <button type="button" className="close" aria-hidden="true" onClick={this.props.onRequestHide}>×</button>
      );
    }

    return (

        {closeButton}
        {this.renderTitle()}

    );
  },

  renderTitle() {
    return (
      React.isValidElement(this.props.title) ?
        this.props.title :
{this.props.title}

    );
  },

  iosClickHack() {
    // IOS only allows click events to be delegated to the document on elements
    // it considers 'clickable' - anchors, buttons, etc. We fake a click handler on the
    // DOM nodes themselves. Remove if handled by React: https://github.com/facebook/react/issues/1169
    React.findDOMNode(this.refs.modal).onclick = function () {};
    React.findDOMNode(this.refs.backdrop).onclick = function () {};
  },

  componentDidMount() {
    const doc = domUtils.ownerDocument(this);
    const win = domUtils.ownerWindow(this);

    this._onDocumentKeyupListener =
      EventListener.listen(doc, 'keyup', this.handleDocumentKeyUp);

    this._onWindowResizeListener =
        EventListener.listen(win, 'resize', this.handleWindowResize);

    if (this.props.enforceFocus) {
      this._onFocusinListener = onFocus(this, this.enforceFocus);
    }

    let container = getContainer(this);

    container.className += container.className.length ? ' modal-open' : 'modal-open';

    this._containerIsOverflowing = container.scrollHeight > containerClientHeight(container, this);

    this._originalPadding = container.style.paddingRight;

    if (this._containerIsOverflowing) {
      container.style.paddingRight = parseInt(this._originalPadding || 0, 10) + scrollbarSize + 'px';
    }

    if (this.props.backdrop) {
      this.iosClickHack();
    }

    this.setState(this._getStyles() //eslint-disable-line react/no-did-mount-set-state
      , () => this.focusModalContent());
  },

  componentDidUpdate(prevProps) {
    if (this.props.backdrop && this.props.backdrop !== prevProps.backdrop) {
      this.iosClickHack();
      this.setState(this._getStyles()); //eslint-disable-line react/no-did-update-set-state
    }

    if (this.props.container !== prevProps.container) {
      let container = getContainer(this);
      this._containerIsOverflowing = container.scrollHeight > containerClientHeight(container, this);
    }
  },

  componentWillUnmount() {
    this._onDocumentKeyupListener.remove();
    this._onWindowResizeListener.remove();

    if (this._onFocusinListener) {
      this._onFocusinListener.remove();
    }

    let container = getContainer(this);

    container.style.paddingRight = this._originalPadding;

    container.className = container.className.replace(/ ?modal-open/, '');

    this.restoreLastFocus();
  },

  handleBackdropClick(e) {
    if (e.target !== e.currentTarget) {
      return;
    }

    this.props.onRequestHide();
  },

  handleDocumentKeyUp(e) {
    if (this.props.keyboard && e.keyCode === 27) {
      this.props.onRequestHide();
    }
  },

  handleWindowResize() {
    this.setState(this._getStyles());
  },

  focusModalContent () {
    this.lastFocus = domUtils.activeElement(this);
    let modalContent = React.findDOMNode(this.refs.modal);
    modalContent.focus();
  },

  restoreLastFocus () {
    if (this.lastFocus) {
      this.lastFocus.focus();
      this.lastFocus = null;
    }
  },

  enforceFocus() {
    if ( !this.isMounted() ) {
      return;
    }

    let active = domUtils.activeElement(this);
    let modal = React.findDOMNode(this.refs.modal);

    if (modal !== active && !domUtils.contains(modal, active)){
      modal.focus();
    }
  },

  _getStyles() {
    if ( !domUtils.canUseDom ) { return {}; }

    let node = React.findDOMNode(this.refs.modal);
    let scrollHt = node.scrollHeight;
    let container = getContainer(this);
    let containerIsOverflowing = this._containerIsOverflowing;
    let modalIsOverflowing = scrollHt > containerClientHeight(container, this);

    return {
      dialogStyles: {
        paddingRight: containerIsOverflowing && !modalIsOverflowing ? scrollbarSize : void 0,
        paddingLeft:  !containerIsOverflowing && modalIsOverflowing ? scrollbarSize : void 0
      }
    };
  }
});

export default Modal;
<|endoftext|>


<commit_before>const _ = require('lodash/fp')
const db = require('./db')
const migration = require('./config-migration')

const OLD_SETTINGS_LOADER_SCHEMA_VERSION = 1
const NEW_SETTINGS_LOADER_SCHEMA_VERSION = 2
const PASSWORD_FILLED = 'PASSWORD_FILLED'
const SECRET_FIELDS = [
  'bitgo.BTCWalletPassphrase',
  'bitgo.LTCWalletPassphrase',
  'bitgo.ZECWalletPassphrase',
  'bitgo.BCHWalletPassphrase',
  'bitgo.DASHWalletPassphrase',
  'bitstamp.secret',
  'infura.apiSecret',
  'itbit.clientSecret',
  'kraken.privateKey',
  'twilio.authToken'
]

const accountsSql = `update user_config set data = $2, valid = $3, schema_version = $4 where type = $1;
insert into user_config (type, data, valid, schema_version)
select $1, $2, $3, $4 where $1 not in (select type from user_config)`
function saveAccounts (accountsToSave) {
  return loadAccounts()
    .then(currentAccounts => {
      const newAccounts = _.assign(currentAccounts, accountsToSave)
      return db.none(accountsSql, ['accounts', { accounts: newAccounts }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    })
}
function resetAccounts (schemaVersion) {
  return db.none(
    accountsSql,
    [
      'accounts',
      { accounts: NEW_SETTINGS_LOADER_SCHEMA_VERSION ? {} : [] },
      true,
      schemaVersion
    ]
  )
}

function loadAccounts (schemaVersion) {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  and valid
  order by id desc
  limit 1`

  return db.oneOrNone(sql, ['accounts', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(_.compose(_.defaultTo({}), _.get('data.accounts')))
}

function showAccounts (schemaVersion) {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  and valid
  order by id desc
  limit 1`

  return db.oneOrNone(sql, ['accounts', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(res => {
      const accounts = _.compose(_.defaultTo({}), _.get('data.accounts'))(res)
      const filledSecretPaths = _.compact(_.map(path => {
        if (!_.isEmpty(_.get(path, accounts))) {
          return path
        }
      }, SECRET_FIELDS))
      return _.compose(_.map(path => _.assoc(path, PASSWORD_FILLED), filledSecretPaths))(accounts)
    })
}

const configSql = 'insert into user_config (type, data, valid, schema_version) values ($1, $2, $3, $4)'
function saveConfig (config) {
  return loadLatestConfigOrNone()
    .then(currentConfig => {
      const newConfig = _.assign(currentConfig, config)
      return db.none(configSql, ['config', { config: newConfig }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    })
}

function resetConfig (schemaVersion) {
  return db.none(
    configSql,
    [
      'config',
      { config: schemaVersion === NEW_SETTINGS_LOADER_SCHEMA_VERSION ? {} : [] },
      true,
      schemaVersion
    ]
  )
}

function loadLatest (schemaVersion) {
  return Promise.all([loadLatestConfigOrNone(schemaVersion), loadAccounts(schemaVersion)])
    .then(([config, accounts]) => ({
      config,
      accounts
    }))
}

function loadLatestConfig () {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  and valid
  order by id desc
  limit 1`

  return db.one(sql, ['config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row ? row.data.config : {})
    .catch(err => {
      throw err
    })
}

function loadLatestConfigOrNone (schemaVersion) {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  order by id desc
  limit 1`

  return db.oneOrNone(sql, ['config', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row ? row.data.config : {})
}

function loadConfig (versionId) {
  const sql = `select data
  from user_config
  where id=$1
  and type=$2
  and schema_version=$3
  and valid`

  return db.one(sql, [versionId, 'config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row.data.config)
    .catch(err => {
      if (err.name === 'QueryResultError') {
        throw new Error('No such config version: ' + versionId)
      }

      throw err
    })
}

function load (versionId) {
  if (!versionId) Promise.reject('versionId is required')

  return Promise.all([loadConfig(versionId), loadAccounts()])
    .then(([config, accounts]) => ({
      config,
      accounts
    }))
}

function migrate () {
  return loadLatest(OLD_SETTINGS_LOADER_SCHEMA_VERSION)
    .then(res => {
      const migrated = migration.migrate(res.config, res.accounts)
      saveConfig(migrated.config)
      saveAccounts(migrated.accounts)

      return migrated
    })
}

module.exports = {
  saveConfig,
  resetConfig,
  saveAccounts,
  resetAccounts,
  loadAccounts,
  showAccounts,
  loadLatest,
  loadLatestConfig,
  loadLatestConfigOrNone,
  load,
  migrate
}
<commit_msg>Refactored to use loadAccounts<commit_after>const _ = require('lodash/fp')
const db = require('./db')
const migration = require('./config-migration')

const OLD_SETTINGS_LOADER_SCHEMA_VERSION = 1
const NEW_SETTINGS_LOADER_SCHEMA_VERSION = 2
const PASSWORD_FILLED = 'PASSWORD_FILLED'
const SECRET_FIELDS = [
  'bitgo.BTCWalletPassphrase',
  'bitgo.LTCWalletPassphrase',
  'bitgo.ZECWalletPassphrase',
  'bitgo.BCHWalletPassphrase',
  'bitgo.DASHWalletPassphrase',
  'bitstamp.secret',
  'infura.apiSecret',
  'itbit.clientSecret',
  'kraken.privateKey',
  'twilio.authToken'
]

const accountsSql = `update user_config set data = $2, valid = $3, schema_version = $4 where type = $1;
insert into user_config (type, data, valid, schema_version)
select $1, $2, $3, $4 where $1 not in (select type from user_config)`
function saveAccounts (accountsToSave) {
  return loadAccounts()
    .then(currentAccounts => {
      const newAccounts = _.assign(currentAccounts, accountsToSave)
      return db.none(accountsSql, ['accounts', { accounts: newAccounts }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    })
}
function resetAccounts (schemaVersion) {
  return db.none(
    accountsSql,
    [
      'accounts',
      { accounts: NEW_SETTINGS_LOADER_SCHEMA_VERSION ? {} : [] },
      true,
      schemaVersion
    ]
  )
}

function loadAccounts (schemaVersion) {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  and valid
  order by id desc
  limit 1`

  return db.oneOrNone(sql, ['accounts', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(_.compose(_.defaultTo({}), _.get('data.accounts')))
}

function showAccounts (schemaVersion) {
  return loadAccounts(schemaVersion)
    .then(accounts => {
      const filledSecretPaths = _.compact(_.map(path => {
        if (!_.isEmpty(_.get(path, accounts))) {
          return path
        }
      }, SECRET_FIELDS))
      return _.compose(_.map(path => _.assoc(path, PASSWORD_FILLED), filledSecretPaths))(accounts)
    })
}

const configSql = 'insert into user_config (type, data, valid, schema_version) values ($1, $2, $3, $4)'
function saveConfig (config) {
  return loadLatestConfigOrNone()
    .then(currentConfig => {
      const newConfig = _.assign(currentConfig, config)
      return db.none(configSql, ['config', { config: newConfig }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    })
}

function resetConfig (schemaVersion) {
  return db.none(
    configSql,
    [
      'config',
      { config: schemaVersion === NEW_SETTINGS_LOADER_SCHEMA_VERSION ? {} : [] },
      true,
      schemaVersion
    ]
  )
}

function loadLatest (schemaVersion) {
  return Promise.all([loadLatestConfigOrNone(schemaVersion), loadAccounts(schemaVersion)])
    .then(([config, accounts]) => ({
      config,
      accounts
    }))
}

function loadLatestConfig () {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  and valid
  order by id desc
  limit 1`

  return db.one(sql, ['config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row ? row.data.config : {})
    .catch(err => {
      throw err
    })
}

function loadLatestConfigOrNone (schemaVersion) {
  const sql = `select data
  from user_config
  where type=$1
  and schema_version=$2
  order by id desc
  limit 1`

  return db.oneOrNone(sql, ['config', schemaVersion || NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row ? row.data.config : {})
}

function loadConfig (versionId) {
  const sql = `select data
  from user_config
  where id=$1
  and type=$2
  and schema_version=$3
  and valid`

  return db.one(sql, [versionId, 'config', NEW_SETTINGS_LOADER_SCHEMA_VERSION])
    .then(row => row.data.config)
    .catch(err => {
      if (err.name === 'QueryResultError') {
        throw new Error('No such config version: ' + versionId)
      }

      throw err
    })
}

function load (versionId) {
  if (!versionId) Promise.reject('versionId is required')

  return Promise.all([loadConfig(versionId), loadAccounts()])
    .then(([config, accounts]) => ({
      config,
      accounts
    }))
}

function migrate () {
  return loadLatest(OLD_SETTINGS_LOADER_SCHEMA_VERSION)
    .then(res => {
      const migrated = migration.migrate(res.config, res.accounts)
      saveConfig(migrated.config)
      saveAccounts(migrated.accounts)

      return migrated
    })
}

module.exports = {
  saveConfig,
  resetConfig,
  saveAccounts,
  resetAccounts,
  loadAccounts,
  showAccounts,
  loadLatest,
  loadLatestConfig,
  loadLatestConfigOrNone,
  load,
  migrate
}
<|endoftext|>


<commit_before>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Degrades inputs to another type after custom enhancements are made.
//>>label: Dialog-style Pages

define( [ "jquery.mobile.widget" ], function() {
//>>excludeEnd("jqmBuildExclude");
(function( $, window, undefined ) {

$.widget( "mobile.dialog", $.mobile.widget, {
	options: {
		closeBtnText 	: "Close",
		overlayTheme	: "a",
		initSelector	: ":jqmData(role='dialog')"
	},
	_create: function() {
		var self = this,
			$el = this.element,
			headerCloseButton = $( ""+ this.options.closeBtnText + "" ),
			dialogWrap = $("
", {
					"role" : "dialog",
					"class" : "ui-dialog ui-corner-all ui-overlay-shadow"
				});

		$el.addClass( "ui-dialog-page ui-overlay-" + this.options.overlayTheme );

		// Class the markup for dialog styling
		// Set aria role
		$el
			.wrapInner( dialogWrap )
			.find( ":jqmData(role='header')" )
				.prepend( headerCloseButton )
			.end()
			.find(':first-child')
				.addClass( "ui-corner-top" )
			.end()
			.find( ":last-child" )
				.addClass( "ui-corner-bottom" );

		// this must be an anonymous function so that select menu dialogs can replace
		// the close method. This is a change from previously just defining data-rel=back
		// on the button and letting nav handle it
		headerCloseButton.bind( "vclick", function() {
			self.close();
		});

		/* bind events
			- clicks and submits should use the closing transition that the dialog opened with
			  unless a data-transition is specified on the link/form
			- if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
		*/
		$el.bind( "vclick submit", function( event ) {
			var $target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" ),
				active;

			if ( $target.length && !$target.jqmData( "transition" ) ) {

				active = $.mobile.urlHistory.getActive() || {};

				$target.attr( "data-" + $.mobile.ns + "transition", ( active.transition || $.mobile.defaultDialogTransition ) )
					.attr( "data-" + $.mobile.ns + "direction", "reverse" );
			}
		})
		.bind( "pagehide", function( e, ui ) {
			$( this ).find( "." + $.mobile.activeBtnClass ).removeClass( $.mobile.activeBtnClass );

			// if there's an overlay theme, we're going to remove it from the page container.
			// First though, check that the incoming page isn't a dialog with the same theme. If so, don't remove.
			if( self.options.overlayTheme ){
				if( !ui.nextPage || !ui.nextPage.is( ".ui-dialog-page.ui-overlay-" + self.options.overlayTheme ) ){
					$.mobile.pageContainer.removeClass( "ui-overlay-" + self.options.overlayTheme );
				}
			}
		})
		.bind( "pagebeforeshow", function(){
			if( self.options.overlayTheme ){
				$.mobile.pageContainer.addClass( "ui-body-" + self.options.overlayTheme );
			}
		});
	},

	// Close method goes back in history
	close: function() {
		window.history.back();
	}
});

//auto self-init widgets
$( document ).delegate( $.mobile.dialog.prototype.options.initSelector, "pagecreate", function(){
	$( this ).dialog();
});

})( jQuery, this );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<commit_msg>class name was body instead of overlay. Fixed<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Degrades inputs to another type after custom enhancements are made.
//>>label: Dialog-style Pages

define( [ "jquery.mobile.widget" ], function() {
//>>excludeEnd("jqmBuildExclude");
(function( $, window, undefined ) {

$.widget( "mobile.dialog", $.mobile.widget, {
	options: {
		closeBtnText 	: "Close",
		overlayTheme	: "a",
		initSelector	: ":jqmData(role='dialog')"
	},
	_create: function() {
		var self = this,
			$el = this.element,
			headerCloseButton = $( ""+ this.options.closeBtnText + "" ),
			dialogWrap = $("
", {
					"role" : "dialog",
					"class" : "ui-dialog ui-corner-all ui-overlay-shadow"
				});

		$el.addClass( "ui-dialog-page ui-overlay-" + this.options.overlayTheme );

		// Class the markup for dialog styling
		// Set aria role
		$el
			.wrapInner( dialogWrap )
			.find( ":jqmData(role='header')" )
				.prepend( headerCloseButton )
			.end()
			.find(':first-child')
				.addClass( "ui-corner-top" )
			.end()
			.find( ":last-child" )
				.addClass( "ui-corner-bottom" );

		// this must be an anonymous function so that select menu dialogs can replace
		// the close method. This is a change from previously just defining data-rel=back
		// on the button and letting nav handle it
		headerCloseButton.bind( "vclick", function() {
			self.close();
		});

		/* bind events
			- clicks and submits should use the closing transition that the dialog opened with
			  unless a data-transition is specified on the link/form
			- if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
		*/
		$el.bind( "vclick submit", function( event ) {
			var $target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" ),
				active;

			if ( $target.length && !$target.jqmData( "transition" ) ) {

				active = $.mobile.urlHistory.getActive() || {};

				$target.attr( "data-" + $.mobile.ns + "transition", ( active.transition || $.mobile.defaultDialogTransition ) )
					.attr( "data-" + $.mobile.ns + "direction", "reverse" );
			}
		})
		.bind( "pagehide", function( e, ui ) {
			$( this ).find( "." + $.mobile.activeBtnClass ).removeClass( $.mobile.activeBtnClass );

			// if there's an overlay theme, we're going to remove it from the page container.
			// First though, check that the incoming page isn't a dialog with the same theme. If so, don't remove.
			if( self.options.overlayTheme ){
				if( !ui.nextPage || !ui.nextPage.is( ".ui-dialog-page.ui-overlay-" + self.options.overlayTheme ) ){
					$.mobile.pageContainer.removeClass( "ui-overlay-" + self.options.overlayTheme );
				}
			}
		})
		.bind( "pagebeforeshow", function(){
			if( self.options.overlayTheme ){
				$.mobile.pageContainer.addClass( "ui-overlay-" + self.options.overlayTheme );
			}
		});
	},

	// Close method goes back in history
	close: function() {
		window.history.back();
	}
});

//auto self-init widgets
$( document ).delegate( $.mobile.dialog.prototype.options.initSelector, "pagecreate", function(){
	$( this ).dialog();
});

})( jQuery, this );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>