<commit_before>(function ($, ko) {
    'use strict';

    var $container,
        initialized,
        imagesLoaded,
        isotopeOptions,
        indexKey = '__knockout-isotope-index';

    // Modified Isotope methods for gutters in masonry:
    $.Isotope.prototype._getMasonryGutterColumns = function () {
        var gutter = this.options.masonry && this.options.masonry.gutterWidth || 0,
            containerWidth = this.element.width();

        this.masonry.columnWidth = this.options.masonry && this.options.masonry.columnWidth ||
                      // or use the size of the first item
                      this.$filteredAtoms.outerWidth(true) ||
                      // if there's no items, use size of container
                      containerWidth;

        this.masonry.columnWidth += gutter;
        this.masonry.cols = Math.floor((containerWidth + gutter) / this.masonry.columnWidth);
        this.masonry.cols = Math.max(this.masonry.cols, 1);
    };

    $.Isotope.prototype._masonryReset = function () {
        // layout-specific props
        this.masonry = {};
        // FIXME shouldn't have to call this again
        this._getMasonryGutterColumns();
        var i = this.masonry.cols;
        this.masonry.colYs = [];
        while (i--) {
            this.masonry.colYs.push(0);
        }
    };

    $.Isotope.prototype._masonryResizeChanged = function () {
        var prevSegments = this.masonry.cols;
        // update cols/rows
        this._getMasonryGutterColumns();
        // return if updated cols/rows is not equal to previous
        return (this.masonry.cols !== prevSegments);
    };

    function afterRender(nodes, data) {
        var $elems = $(nodes).filter(function () { return this.nodeType === 1 });
        $elems.addClass('no-transition');
        $elems.css($.Isotope.settings.hiddenStyle);
    }

    function afterAdd(node, index, item) {
        if (node.nodeType === 1) { // If this is an html element...
            var $elem = $(node),
                addItem = function () {
                    $elem.data(indexKey, index);
                    $container.isotope('addItems', $elem, function () {
                        $container.isotope().isotope('reLayout');
                        $elem.removeClass('no-transition');
                        $elem.css($.Isotope.settings.visibleStyle);
                    });
                };

            if (!imagesLoaded)
                $container.imagesLoaded(function () {
                    addItem();
                    imagesLoaded = true;
                });
            else
                addItem();
        }
    }

    function afterMove(node, index, item) {
        if (node.nodeType === 1) // If this is an html element...
            $container.isotope('updateSortData', $(node));
    }

    function beforeRemove(node, index, item) {
        if (node.nodeType === 1) { // If this is an html element...
            var $elem = $(node),
                isotopeInstance = $container.data('isotope');

            isotopeInstance.$allAtoms = isotopeInstance.$allAtoms.not($elem);
            $elem.remove();
            $container.isotope('reLayout');

            //$container.isotope('remove', $elem); // not working...
        }
    }

    ko.bindingHandlers.isotope = {
        getSortData: function ($elem) {
            return $elem.data(indexKey);
        },
        makeForeachValueAccessor: function (valueAccessor) {
            return function () {
                var modelValue = valueAccessor(),
                    unwrappedValue = ko.utils.peekObservable(modelValue), // Unwrap without setting a dependency here
                    options = {
                        afterRender: afterRender,
                        afterAdd: afterAdd,
                        afterMove: afterMove,
                        beforeRemove: beforeRemove
                    };

                // If unwrappedValue is the array, pass in the wrapped value on its own
                // The value will be unwrapped and tracked within the template binding
                // (See https://github.com/SteveSanderson/knockout/issues/523)
                if (!unwrappedValue || typeof unwrappedValue.length === "number") {
                    ko.utils.extend(options, {
                        'data': modelValue,
                    });
                    return options;
                }

                // If unwrappedValue.data is the array, preserve all relevant
                // options and unwrap value so we get updates
                ko.utils.unwrapObservable(modelValue);
                ko.utils.extend(options, {
                    'data': unwrappedValue.data,
                });

                return options;
            };
        },
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var parameters;

            initialized = false;
            isotopeOptions = {};
            $container = $(element);

            parameters = ko.utils.unwrapObservable(valueAccessor());
            if (parameters && typeof parameters == 'object' && !('length' in parameters)) {
                if (parameters.options) {
                    var clientOptions = parameters.options;
                    if (typeof clientOptions !== 'object')
                        throw new Error('options must be an object');
                    ko.utils.extend(isotopeOptions, clientOptions);
                }
            }

            ko.bindingHandlers.foreach.init(element, ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);

            return { controlsDescendantBindings: true };
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            ko.bindingHandlers.foreach.update(element, ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);

            var data = ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor)().foreach;
            ko.utils.unwrapObservable(data);

            if (!initialized) {
                ko.utils.extend(isotopeOptions, {
                    getSortData: {
                        index: ko.bindingHandlers.isotope.getSortData
                    }
                });

                $container.isotope(isotopeOptions);
            }
            else
                $container.isotope();

            initialized = true;
            return { controlsDescendantBindings: true };
        }
    };
})(window.jQuery, window.ko);<commit_msg>jQuery deep extend. Use instance styles.<commit_after>(function ($, ko) {
    'use strict';

    var $container,
        initialized,
        imagesLoaded,
        isotopeOptions,
        indexKey = '__knockout-isotope-index';

    // Modified Isotope methods for gutters in masonry:
    $.Isotope.prototype._getMasonryGutterColumns = function () {
        var gutter = this.options.masonry && this.options.masonry.gutterWidth || 0,
            containerWidth = this.element.width();

        this.masonry.columnWidth = this.options.masonry && this.options.masonry.columnWidth ||
            // or use the size of the first item
            this.$filteredAtoms.outerWidth(true) ||
            // if there's no items, use size of container
            containerWidth;

        this.masonry.columnWidth += gutter;
        this.masonry.cols = Math.floor((containerWidth + gutter) / this.masonry.columnWidth);
        this.masonry.cols = Math.max(this.masonry.cols, 1);
    };

    $.Isotope.prototype._masonryReset = function () {
        // layout-specific props
        this.masonry = {};
        // FIXME shouldn't have to call this again
        this._getMasonryGutterColumns();
        var i = this.masonry.cols;
        this.masonry.colYs = [];
        while (i--) {
            this.masonry.colYs.push(0);
        }
    };

    $.Isotope.prototype._masonryResizeChanged = function () {
        var prevSegments = this.masonry.cols;
        // update cols/rows
        this._getMasonryGutterColumns();
        // return if updated cols/rows is not equal to previous
        return (this.masonry.cols !== prevSegments);
    };

    function afterRender(nodes, data) {
        var $elems = $(nodes).filter(function () { return this.nodeType === 1 });
        $elems.addClass('no-transition');
        $elems.css($container.data('isotope').options.hiddenStyle);
    }

    function afterAdd(node, index, item) {
        if (node.nodeType === 1) { // If this is an html element...
            var $elem = $(node),
                addItem = function () {
                    $elem.data(indexKey, index);
                    $container.isotope('addItems', $elem, function () {
                        $container.isotope().isotope('reLayout');
                        $elem.removeClass('no-transition');
                        $elem.css($container.data('isotope').options.visibleStyle);
                    });
                };

            if (!imagesLoaded)
                $container.imagesLoaded(function () {
                    addItem();
                    imagesLoaded = true;
                });
            else
                addItem();
        }
    }

    function afterMove(node, index, item) {
        if (node.nodeType === 1) // If this is an html element...
            $container.isotope('updateSortData', $(node));
    }

    function beforeRemove(node, index, item) {
        if (node.nodeType === 1) { // If this is an html element...
            var $elem = $(node),
                isotopeInstance = $container.data('isotope');

            isotopeInstance.$allAtoms = isotopeInstance.$allAtoms.not($elem);
            $elem.remove();
            $container.isotope('reLayout');

            //$container.isotope('remove', $elem); // not working...
        }
    }

    ko.bindingHandlers.isotope = {
        getSortData: function ($elem) {
            return $elem.data(indexKey);
        },
        makeForeachValueAccessor: function (valueAccessor) {
            return function () {
                var modelValue = valueAccessor(),
                    unwrappedValue = ko.utils.peekObservable(modelValue), // Unwrap without setting a dependency here
                    options = {
                        afterRender: afterRender,
                        afterAdd: afterAdd,
                        afterMove: afterMove,
                        beforeRemove: beforeRemove
                    };

                // If unwrappedValue is the array, pass in the wrapped value on its own
                // The value will be unwrapped and tracked within the template binding
                // (See https://github.com/SteveSanderson/knockout/issues/523)
                if (!unwrappedValue || typeof unwrappedValue.length === "number") {
                    ko.utils.extend(options, {
                        'data': modelValue,
                    });
                    return options;
                }

                // If unwrappedValue.data is the array, preserve all relevant
                // options and unwrap value so we get updates
                ko.utils.unwrapObservable(modelValue);
                ko.utils.extend(options, {
                    'data': unwrappedValue.data,
                });

                return options;
            };
        },
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var parameters;

            initialized = false;
            isotopeOptions = {};
            $container = $(element);

            parameters = ko.utils.unwrapObservable(valueAccessor());
            if (parameters && typeof parameters == 'object' && !('length' in parameters)) {
                if (parameters.options) {
                    var clientOptions = parameters.options;
                    if (typeof clientOptions !== 'object')
                        throw new Error('options must be an object');
                    $.extend(true, isotopeOptions, clientOptions);
                }
            }

            ko.bindingHandlers.foreach.init(element, ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);

            return { controlsDescendantBindings: true };
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            ko.bindingHandlers.foreach.update(element, ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);

            var data = ko.bindingHandlers.isotope.makeForeachValueAccessor(valueAccessor)().foreach;
            ko.utils.unwrapObservable(data);

            if (!initialized) {
                $.extend(true, isotopeOptions, {
                    getSortData: {
                        index: ko.bindingHandlers.isotope.getSortData
                    }
                });

                $container.isotope(isotopeOptions);
            }
            else
                $container.isotope();

            initialized = true;
            return { controlsDescendantBindings: true };
        }
    };
})(window.jQuery, window.ko);<|endoftext|>


<commit_before>/**
 * zen-id for javascript (nodejs)
 * copyright 2014 Tapmodo Interactive LLC
 * Free software - MIT license
 * based on concept of gen-id npm package
 */

var crc = require('crc');

// Constructor
var ZenID = function(format){
  this.setFormat(format);
  this.init();
};

ZenID.prototype = {

  // Initialize the object
  init: function(){
    this.formats = {};

    for(key in ZenID.formats)
      if (ZenID.formats.hasOwnProperty(key))
        this.formats[key] = ZenID.shuffle(ZenID.formats[key]);
  },

  // Set the format
  setFormat: function(format){
    this.format = format;
    return this;
  },

  // Translate a format character into a random value
  getChar: function(c){
    if (c == 'c') return null;
    else if (!this.formats[c]) return c;
    return this.formats[c][Math.floor(Math.random() * this.formats[c].length)];
  },

  // Generate a value based on a format
  generate: function(format){
    format = format || this.format;
    return this.computeChecksums(format.split('').map(this.getChar.bind(this))).join('');
  },

  // Validate an input based on a format
  validate: function(input,format){
    format = format || this.format;
    var data = input.split(''), out = [];

    for(var i=0, l=data.length; i<l; i++){
      if (format[i] == 'c') out.push(null);
      else if (this.formats[format[i]]) out.push(data[i]);
      else if (format[i] == data[i]) out.push(data[i]);
    }

    return this.computeChecksums(out).join('') == input;
  },

  // Internally used fuction to generate checksum values
  computeChecksums: function(arr){
    return arr.reduce(function(pv,cv,idx,all){
      if (cv !== null) pv.push(cv);
        else pv.push((''+((crc.crc32(pv.join(''))) >>> 0)).substr(-1));
      return pv;
    },[]);
  }
};

// Why not shuffle the inital arrays...
// Based on lodash algo
ZenID.shuffle = function(chars) {
  var collection = chars.split('');
  var index = -1,

  length = collection.length,
  result = Array(length);

  while (++index < length) {
    var rand = Math.floor(Math.random() * index);
    if (index != rand) {
      result[index] = result[rand];
    }
    result[rand] = collection[index];
  }
  return result.join('');
}

// A nicer syntax
ZenID.create = function(format) {
  return new ZenID(format);
};

// The basic formats
ZenID.formats = {
  n: '0123456789',
  h: '0123456789abcedf',
  a: 'abcdefghijklmnopqrstuvwxyz',
  A: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  x: '0123456789abcdefghijklmnopqrstuvwxyz',
  X: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  z: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
}

module.exports = ZenID;
<commit_msg>Improved validation Check if character is a format character AND valid for that format<commit_after>/**
 * zen-id for javascript (nodejs)
 * copyright 2014 Tapmodo Interactive LLC
 * Free software - MIT license
 * based on concept of gen-id npm package
 */

var crc = require('crc');

// Constructor
var ZenID = function(format){
  this.setFormat(format);
  this.init();
};

ZenID.prototype = {

  // Initialize the object
  init: function(){
    this.formats = {};

    for(key in ZenID.formats)
      if (ZenID.formats.hasOwnProperty(key))
        this.formats[key] = ZenID.shuffle(ZenID.formats[key]);
  },

  // Set the format
  setFormat: function(format){
    this.format = format;
    return this;
  },

  // Translate a format character into a random value
  getChar: function(c){
    if (c == 'c') return null;
    else if (!this.formats[c]) return c;
    return this.formats[c][Math.floor(Math.random() * this.formats[c].length)];
  },

  // Generate a value based on a format
  generate: function(format){
    format = format || this.format;
    return this.computeChecksums(format.split('').map(this.getChar.bind(this))).join('');
  },

  // Validate an input based on a format
  validate: function(input,format){
    format = format || this.format;
    var data = input.split(''), out = [];

    for(var i=0, l=data.length; i<l; i++){
      if (format[i] == 'c') out.push(null);

      else if (
        this.formats[format[i]] &&
        (this.formats[format[i]].indexOf(data[i]) != -1)
      ) out.push(data[i]);

      else if (format[i] == data[i]) out.push(data[i]);
    }

    return this.computeChecksums(out).join('') == input;
  },

  // Internally used fuction to generate checksum values
  computeChecksums: function(arr){
    return arr.reduce(function(pv,cv,idx,all){
      if (cv !== null) pv.push(cv);
        else pv.push((''+((crc.crc32(pv.join(''))) >>> 0)).substr(-1));
      return pv;
    },[]);
  }
};

// Why not shuffle the inital arrays...
// Based on lodash algo
ZenID.shuffle = function(chars) {
  var collection = chars.split('');
  var index = -1,

  length = collection.length,
  result = Array(length);

  while (++index < length) {
    var rand = Math.floor(Math.random() * index);
    if (index != rand) {
      result[index] = result[rand];
    }
    result[rand] = collection[index];
  }
  return result.join('');
}

// A nicer syntax
ZenID.create = function(format) {
  return new ZenID(format);
};

// The basic formats
ZenID.formats = {
  n: '0123456789',
  h: '0123456789abcedf',
  a: 'abcdefghijklmnopqrstuvwxyz',
  A: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  x: '0123456789abcdefghijklmnopqrstuvwxyz',
  X: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  z: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
}

module.exports = ZenID;
<|endoftext|>


<commit_before>import Ember from 'ember';

function iconTemplate(iconName) {
  return '';
}
export function fileIconFor(filename/*, hash*/) {

  //console.log("Filename being passed in is");
  //console.log(filename);

  if (filename.length==1) // array - this is a hack, need to figure this out...
    filename = filename[0];

  if ((filename == null) || (typeof filename  == 'undefined')) return '';

  var res = filename.split(".");

  if (res.length < 2 ) return '';

  var suffix = res[1].toLowerCase();

  if ((suffix === "ppt") || (suffix === "pptx")) return iconTemplate("/icons/ppt.jpg");
  if ((suffix === "xls") || (suffix === "xlsx")) return iconTemplate("/icons/excel.jpg");
  if (suffix === "pdf") return iconTemplate("/icons/pdf.jpg");
  if ((suffix === "doc") || (suffix === "docx")) return iconTemplate("/icons/word.jpg");

  // images

  if (suffix === "png")  return iconTemplate("/icons/png.png");
  if ((suffix === "tif") || (suffix === "tiff")) return iconTemplate("/icons/tiff.png");
  if ((suffix === "jpg") || (suffix === "jpeg")) return iconTemplate("/icons/jpg.png");

  if (suffix === "tgz")  return iconTemplate("/icons/tgz.png");
  if (suffix === "zip")  return iconTemplate("/icons/zip.png");

  if ((suffix === "hdf") || (suffix === "h5") || (suffix === "h5m"))  return iconTemplate("/icons/hdf.png");

  // don;t know it
  return '';
}

export default Ember.Helper.helper(fileIconFor);
<commit_msg>modify file-icon helper to use fa + ext for unknown file types<commit_after>import Ember from 'ember';

function iconTemplate(iconName) {
  return '';
}
export function fileIconFor(params/*, hash*/) {
  let [filename] = params;
  console.log(filename);
  //console.log("Filename being passed in is");
  //console.log(filename);

  if (filename.length==1) { // array - this is a hack, need to figure this out...
    filename = filename[0];
  }

  if ((filename == null) || (typeof filename  == 'undefined')) {
    return '';
  }

  var res = filename.split(".");

  if (res.length < 2 ) return '';

  var suffix = res[1].toLowerCase();

  if ((suffix === "ppt") || (suffix === "pptx")) {
    return iconTemplate("/icons/ppt.jpg");
  } else if ((suffix === "xls") || (suffix === "xlsx")) {
    return iconTemplate("/icons/excel.jpg");
  } else if (suffix === "pdf") {
    return iconTemplate("/icons/pdf.jpg");
  } else if ((suffix === "doc") || (suffix === "docx")) {
    return iconTemplate("/icons/word.jpg");
  }

  // images

  else if (suffix === "png") {
    return iconTemplate("/icons/png.png");
  } else if ((suffix === "tif") || (suffix === "tiff")) {
    return iconTemplate("/icons/tiff.png");
  } else if ((suffix === "jpg") || (suffix === "jpeg")) {
    return iconTemplate("/icons/jpg.png");
  } else if (suffix === "tgz")  {
    return iconTemplate("/icons/tgz.png");
  } else if (suffix === "zip") {
    return iconTemplate("/icons/zip.png");
  } else if ((suffix === "hdf") || (suffix === "h5") || (suffix === "h5m")) {
    return iconTemplate("/icons/hdf.png");
  }

  // don;t know it
  return `${res[1].substr(0,3)}`;
  }

  // border: 1.5px solid white;
  // border-radius: 15%;
export default Ember.Helper.helper(fileIconFor);
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Q = require('q');
var crontab = require('crontab');
var _ = require('lodash');

// Expose our public functions
module.exports.wheneverize = wheneverize;
module.exports.updateCrontab = updateCrontab;

/**
 * Wheneverizes a project
 */
function wheneverize() {

  var scheduleFile = path.resolve(path.join(process.cwd(), 'schedule.js'));

  shouldCreateFile(scheduleFile)
    .then(function() {
      return createScheduleFile();
    })
    .then(function() {
      console.log('schedule.js created!');
    })
    .fail(function(err) {
      console.error(err);
      throw err;
    });
}

/**
 * Reads the schedule.js file and creates the cronjobs
 *
 * @param file  - The file to parse the cronjobs from (schedule.js)
 */
function updateCrontab(file) {

  validateFile(file)
    .then(function() {
      return getCronJobs(file);
    })
    .then(function(cronjobs) {
      createCronjobs(cronjobs);
    })
    .then(function() {
      console.log('crontab updated!');
    })
    .fail(function(err) {
      if(err.code === 'ENOENT') {
        var error = new Error('schedule.js does not exist');
        console.error(error);
        throw error;
      } else {
        console.error(err);
        throw err;
      }
    });
}

/*******************
 * PRIVATE
 *******************/

/**
 * Gets the cronjobs from the file
 *
 * @param file  - The file to get the cronjobs from
 * @return      - Returns an array of cronjobs
 */
function getCronJobs(file) {

  var cronjobs = require(file).cronjobs;

  if(!cronjobs.length) {
    return Q.reject('schedule.js is not valid.');
  }

  var validate = validateCronjobs(cronjobs);

  if(_.isError(validate)) {
    return Q.reject(validate);
  }

  return Q.resolve(cronjobs);
}
path.dirname(fs.realpathSync(__filename)) + '/../index.js'
/**
 * Validate that the cronjobs have at least the necessary attributes
 *
 * @param cronjobs  - The cronjobs to validate have the necessary attributes
 * @return          - True if there are no errors. An Error object if there is an error
 */
function validateCronjobs(cronjobs) {
  var errors = null;

  cronjobs.forEach(function(cronjob) {
    // Ensure the command attribute exists
    if(!_.has(cronjob, 'command')) {
      errors = new Error('cronjob definition does not have the property "command"');
    }

    // Ensure the when attribute exists
    if(!_.has(cronjob, 'when')) {
      errors = new Error('cronjob definition does not have the property "when"');
    }
  });

  return errors ? errors : true
}

/**
 * Validate the cronjob file is not empty and has the appropriate export
 *
 * @param file  - The file to validate
 */
function validateFile(file) {
  return Q.promise(function(resolve, reject) {
    fs.readFile(path.join(file), function(err, contents) {

    if(err) {
      return reject(err);
    }

    if(contents.toString() === '') {
      return reject('schedule.js is empty');
    }

    return resolve();
    });
  });
}

/**
 * Creates the file schedule.js with the default contents
 *
 * @return  - Returns a promise
 */
function createScheduleFile() {
  return Q.promise(function(resolve, reject) {
    var contents = '/**\n * This file is generated from "Whenever" <NPM LINK HERE>.\n' +
    ' *\n' +
    ' * module.exports.cronjobs accepts an array of cronjob objects. \n' +
    ' * Each object has the attributes command, when, and comment.\n' +
    ' * \n' +
    ' * Syntax:\n' +
    ' * command can be a string expression\n' +
    ' * \n' +
    ' * Examples: \n' +
    ' * \n' +
    ' * \t{\n' +
    ' * \t\tcommand: \'ls -al\',\n' +
    ' * \t\twhen: \'* * * * *\',\n' +
    ' * \t\tcomment: \'Oh ya know just commenting my cron job\'\n' +
    ' * \t}\n' +
    '*/\n' +
    'module.exports.cronjobs = [\n' +
    '\t{\n' +
    '\t\tcommand: \'<command to execute>\',\n' +
    '\t\twhen: \'<when to execute>\',\n' +
    '\t\tcomment: \'<comment to be put in the crontab for this entry>\'\n' +
    '\t}\n' +
    ']';
    fs.writeFile('schedule.js', contents, function(err) {
      if(err) {
        return reject(err);
      }
      return resolve();
    });
  });
}

/**
 * Creates entries in the crontab
 *
 * @param cronjobs  - The jobs to create entries in the crontab for
 */
function createCronjobs(cronjobs) {
  return Q.promise(function(resolve, reject) {

    crontab.load(function(err, tab) {

      if(err) {
        return reject(err);
      }

      cronjobs.forEach(function(cronjob, i) {
        var job = tab.create(cronjob.command, cronjob.when, cronjob.comment);
        if(job == null || job.isValid()) {
          return reject('Cronjob syntax not valid');
        }
      });

      // save the cronjobs
      tab.save(function(err, tab) {
        if(err) {
          return reject(err);
        }

        return resolve();
      });

    });
  });
}

/**
 * Ensure schedule.js does not already exist.
 *
 * @param file  - The file to check if exists
 * @return      - Returns a promise whether the file exists or not
 */
function shouldCreateFile(file) {
  return Q.promise(function(resolve, reject) {

    fs.stat(file, function(err, stats) {

      // If the file already exists
      if(err === null) {
        if(stats.isFile()) {
          return reject('schedule.js already exists!');
        }
      }

      // If the file does not exist, resolve, else reject with the error
      if(err.code === 'ENOENT') {
        return resolve();
      } else {
        return reject(err);
      }
    });
  });
}
<commit_msg>Fixed invalid jobs not showing error<commit_after>var fs = require('fs');
var path = require('path');
var Q = require('q');
var crontab = require('crontab');
var _ = require('lodash');

// Expose our public functions
module.exports.wheneverize = wheneverize;
module.exports.updateCrontab = updateCrontab;

/**
 * Wheneverizes a project
 */
function wheneverize() {

  var scheduleFile = path.resolve(path.join(process.cwd(), 'schedule.js'));

  shouldCreateFile(scheduleFile)
    .then(function() {
      return createScheduleFile();
    })
    .then(function() {
      console.log('schedule.js created!');
    })
    .fail(function(err) {
      console.error(err);
      throw err;
    });
}

/**
 * Reads the schedule.js file and creates the cronjobs
 *
 * @param file  - The file to parse the cronjobs from (schedule.js)
 */
function updateCrontab(file) {

  validateFile(file)
    .then(function() {
      return getCronJobs(file);
    })
    .then(function(cronjobs) {
      return createCronjobs(cronjobs);
    })
    .then(function() {
      console.log('crontab updated!');
    })
    .fail(function(err) {
      if(err.code === 'ENOENT') {
        var error = new Error('schedule.js does not exist');
        console.error(error);
        throw error;
      } else {
        console.error(err);
        throw err;
      }
    });
}

/*******************
 * PRIVATE
 *******************/

/**
 * Gets the cronjobs from the file
 *
 * @param file  - The file to get the cronjobs from
 * @return      - Returns an array of cronjobs
 */
function getCronJobs(file) {

  var cronjobs = require(file).cronjobs;

  if(!cronjobs.length) {
    return Q.reject('schedule.js is not valid.');
  }

  var validate = validateCronjobs(cronjobs);

  if(_.isError(validate)) {
    return Q.reject(validate);
  }

  return Q.resolve(cronjobs);
}
path.dirname(fs.realpathSync(__filename)) + '/../index.js'
/**
 * Validate that the cronjobs have at least the necessary attributes
 *
 * @param cronjobs  - The cronjobs to validate have the necessary attributes
 * @return          - True if there are no errors. An Error object if there is an error
 */
function validateCronjobs(cronjobs) {
  var errors = null;

  cronjobs.forEach(function(cronjob) {
    // Ensure the command attribute exists
    if(!_.has(cronjob, 'command')) {
      errors = new Error('cronjob definition does not have the property "command"');
    }

    // Ensure the when attribute exists
    if(!_.has(cronjob, 'when')) {
      errors = new Error('cronjob definition does not have the property "when"');
    }
  });

  return errors ? errors : true
}

/**
 * Validate the cronjob file is not empty and has the appropriate export
 *
 * @param file  - The file to validate
 */
function validateFile(file) {
  return Q.promise(function(resolve, reject) {
    fs.readFile(path.join(file), function(err, contents) {

    if(err) {
      return reject(err);
    }

    if(contents.toString() === '') {
      return reject('schedule.js is empty');
    }

    return resolve();
    });
  });
}

/**
 * Creates the file schedule.js with the default contents
 *
 * @return  - Returns a promise
 */
function createScheduleFile() {
  return Q.promise(function(resolve, reject) {
    var contents = '/**\n * This file is generated from "node-whenever" https://www.npmjs.com/package/node-whenever.\n' +
    ' *\n' +
    ' * module.exports.cronjobs accepts an array of cronjob objects. \n' +
    ' * Each object has the attributes command, when, and comment.\n' +
    ' * \n' +
    ' * Syntax:\n' +
    ' * command can be a string expression\n' +
    ' * \n' +
    ' * Examples: \n' +
    ' * \n' +
    ' * \t{\n' +
    ' * \t\tcommand: \'ls -al\',\n' +
    ' * \t\twhen: \'* * * * *\',\n' +
    ' * \t\tcomment: \'Oh ya know just commenting my cron job\'\n' +
    ' * \t}\n' +
    '*/\n' +
    'module.exports.cronjobs = [\n' +
    '\t{\n' +
    '\t\tcommand: \'<command to execute>\',\n' +
    '\t\twhen: \'<when to execute>\',\n' +
    '\t\tcomment: \'<comment to be put in the crontab for this entry>\'\n' +
    '\t}\n' +
    ']';
    fs.writeFile('schedule.js', contents, function(err) {
      if(err) {
        return reject(err);
      }
      return resolve();
    });
  });
}

/**
 * Creates entries in the crontab
 *
 * @param cronjobs  - The jobs to create entries in the crontab for
 */
function createCronjobs(cronjobs) {
  return Q.promise(function(resolve, reject) {

    crontab.load(function(err, tab) {

      if(err) {
        return reject(err);
      }

      cronjobs.forEach(function(cronjob, i) {
        var job = tab.create(cronjob.command, cronjob.when, cronjob.comment);
        if(job == null || !job.isValid()) {
          return reject('Cronjob syntax not valid');
        }
      });

      // save the cronjobs
      tab.save(function(err, tab) {
        if(err) {
          return reject(err);
        }

        return resolve();
      });

    });
  });
}

/**
 * Ensure schedule.js does not already exist.
 *
 * @param file  - The file to check if exists
 * @return      - Returns a promise whether the file exists or not
 */
function shouldCreateFile(file) {
  return Q.promise(function(resolve, reject) {

    fs.stat(file, function(err, stats) {

      // If the file already exists
      if(err === null) {
        if(stats.isFile()) {
          return reject('schedule.js already exists!');
        }
      }

      // If the file does not exist, resolve, else reject with the error
      if(err.code === 'ENOENT') {
        return resolve();
      } else {
        return reject(err);
      }
    });
  });
}
<|endoftext|>


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

    /**
     * @type Object Plugin instance
     */
    var _;

    /**
     * Create a new plugin instance.
     *
     * @param  Object options
     * @return void
     */
    var Plugin = function (options) {
        _ = this;
        _.options = extend(defaults, options);
        embed();
    };

    /**
     * @type Object Default plugin options
     */
    var defaults = {
        selector: '[svg-data-uri]',
        addClass: undefined,
        removeClass: undefined,
        base64: window.atob,
        utf8: window.decodeURIComponent
    };

    /**
     * Extract SVG source from data URI and embed in DOM.
     *
     * @return void
     */
    var embed = function () {
        // Find elements matching selector
        var elements = find(_.options.selector);

        // Iterate through elements and embed SVG in DOM
        elements.forEach(function (element) {
            // Extract and embed SVG source into DOM
            element.innerHTML = extract(element);

            // Add class(es) to element where specified via callback or appending string
            if (typeof _.options.addClass === 'function') {
                _.options.addClass.call(null, element);
            }
            else if (typeof _.options.addClass === 'string') {
                element.className += ' ' + _.options.addClass;
            }

            // Remove class(es) from element where specified via callback or removing string
            if (typeof _.options.removeClass === 'function') {
                _.options.removeClass.call(null, element);
            }
            else if (typeof _.options.removeClass === 'string') {
                _.options.removeClass.split(' ').forEach(function (remove) {
                    element.className = element.className.replace(new RegExp('\\b' + remove + '\\b'), '');
                });
            }
        });
    };

    /**
     * Extract and decode SVG from data URI.
     *
     * @param  Object element
     * @return String
     */
    var extract = function (element) {
        // Get computed element styles
        var styles = window.getComputedStyle(element),
            uri = styles['background-image'].replace(/url\("?([^"]*)"?\)/gi, '$1') || '',
            expression = /data:image\/svg\+xml;(.*),(.*)/g,
            matches = null;

        // Match encoding and data in URI
        if ( ! (matches = expression.exec(uri))) return '';

        // Extract encoding and data from matches
        var encoding = matches[1],
            data = matches[2];

        // Decode data
        switch (encoding) {
            case 'base64':
                return _.options.base64.call(null, data);
            case 'utf8':
                return _.options.utf8.call(null, data);
            default:
                return '';
        }
    };

    /**
     * Find DOM elements matching selector.
     *
     * @param  String selector
     * @return Array
     */
    var find = function (selector) {
        return [].slice.call(document.querySelectorAll(selector));
    };

    /**
     * Utility function to merge the properties of two or more objects onto the first.
     *
     * @param  ...Object
     * @return Object
     */
    var extend = function () {
        // Prepare extended and extension objects
        var extended = {},
            extensions = [].slice.call(arguments);

        // Iterate through remaining extensions
        extensions.forEach(function (extension) {
            // Check if extension is object
            if (typeof extension !== 'object') return;

            // Append extension properties to extended object
            for (var property in extension) {
                if (extension.hasOwnProperty(property)) extended[property] = extension[property];
            }
        });

        return extended;
    };

    // Check for CommonJS support
    if (typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = Plugin;
    }
    // Fallback to window object
    else {
        window.SvgDataUri = Plugin;
    }
})(window);
<commit_msg>Add comment block to plugin JS file<commit_after>/*
 * SVG Data URI
 * https://github.com/robsimpkins/svg-data-uri
 *
 * Copyright (c) 2015 robsimpkins
 * Licensed under the MIT license.
 */
;(function (window) {
    'use strict';

    /**
     * @type Object Plugin instance
     */
    var _;

    /**
     * Create a new plugin instance.
     *
     * @param  Object options
     * @return void
     */
    var Plugin = function (options) {
        _ = this;
        _.options = extend(defaults, options);
        embed();
    };

    /**
     * @type Object Default plugin options
     */
    var defaults = {
        selector: '[svg-data-uri]',
        addClass: undefined,
        removeClass: undefined,
        base64: window.atob,
        utf8: window.decodeURIComponent
    };

    /**
     * Extract SVG source from data URI and embed in DOM.
     *
     * @return void
     */
    var embed = function () {
        // Find elements matching selector
        var elements = find(_.options.selector);

        // Iterate through elements and embed SVG in DOM
        elements.forEach(function (element) {
            // Extract and embed SVG source into DOM
            element.innerHTML = extract(element);

            // Add class(es) to element where specified via callback or appending string
            if (typeof _.options.addClass === 'function') {
                _.options.addClass.call(null, element);
            }
            else if (typeof _.options.addClass === 'string') {
                element.className += ' ' + _.options.addClass;
            }

            // Remove class(es) from element where specified via callback or removing string
            if (typeof _.options.removeClass === 'function') {
                _.options.removeClass.call(null, element);
            }
            else if (typeof _.options.removeClass === 'string') {
                _.options.removeClass.split(' ').forEach(function (remove) {
                    element.className = element.className.replace(new RegExp('\\b' + remove + '\\b'), '');
                });
            }
        });
    };

    /**
     * Extract and decode SVG from data URI.
     *
     * @param  Object element
     * @return String
     */
    var extract = function (element) {
        // Get computed element styles
        var styles = window.getComputedStyle(element),
            uri = styles['background-image'].replace(/url\("?([^"]*)"?\)/gi, '$1') || '',
            expression = /data:image\/svg\+xml;(.*),(.*)/g,
            matches = null;

        // Match encoding and data in URI
        if ( ! (matches = expression.exec(uri))) return '';

        // Extract encoding and data from matches
        var encoding = matches[1],
            data = matches[2];

        // Decode data
        switch (encoding) {
            case 'base64':
                return _.options.base64.call(null, data);
            case 'utf8':
                return _.options.utf8.call(null, data);
            default:
                return '';
        }
    };

    /**
     * Find DOM elements matching selector.
     *
     * @param  String selector
     * @return Array
     */
    var find = function (selector) {
        return [].slice.call(document.querySelectorAll(selector));
    };

    /**
     * Utility function to merge the properties of two or more objects onto the first.
     *
     * @param  ...Object
     * @return Object
     */
    var extend = function () {
        // Prepare extended and extension objects
        var extended = {},
            extensions = [].slice.call(arguments);

        // Iterate through remaining extensions
        extensions.forEach(function (extension) {
            // Check if extension is object
            if (typeof extension !== 'object') return;

            // Append extension properties to extended object
            for (var property in extension) {
                if (extension.hasOwnProperty(property)) extended[property] = extension[property];
            }
        });

        return extended;
    };

    // Check for CommonJS support
    if (typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = Plugin;
    }
    // Fallback to window object
    else {
        window.SvgDataUri = Plugin;
    }
})(window);
<|endoftext|>


<commit_before>var hbs = require('express-hbs'),
    _ = require('lodash'),
    downsize = require('downsize'),
    blogVariable = require('../../../core/server/config/theme');

module.exports = function() {

    //This block allows configuration to be available in the hb templates.
    var blogConfig = blogVariable();
    var config = require('./config') || {};
    blogConfig.theme = config;
    //console.log(JSON.stringify(blogConfig));

    ////Custom hb helpers////

    hbs.registerHelper('excerpt', function (options) {
        var truncateOptions = (options || {}).hash || {},
            excerpt = String(this.html);

        excerpt = excerpt.replace(/(\r\n|\n|\r)+/gm, ' ');

        var more = excerpt.indexOf('<!--more-->');
        if(more > -1) {

            excerpt = excerpt.substring(0, more);
            //Chop punctuation marks
            excerpt = excerpt.replace(/\W+$/, '') + '...';
        }
        else {
            excerpt = excerpt.replace(/<\/?[^>]+>/gi, '');

            truncateOptions = _.pick(truncateOptions, ['words', 'characters']);
            _.keys(truncateOptions).map(function (key) {
                truncateOptions[key] = parseInt(truncateOptions[key], 10);
            });

            if (!truncateOptions.words && !truncateOptions.characters) {
                truncateOptions.words = 50;
            }
            console.log(downsize(excerpt, truncateOptions));
            excerpt = downsize(excerpt, truncateOptions) + '...';
        }

        return new hbs.handlebars.SafeString(excerpt);
    });

    hbs.registerHelper('ifCond', function (v1, operator, v2, options) {

        switch (operator) {
            case '==':
                return (v1 == v2) ? options.fn(this) : options.inverse(this);
            case '!=':
                return (v1 != v2) ? options.fn(this) : options.inverse(this);
            case '===':
                return (v1 === v2) ? options.fn(this) : options.inverse(this);
            case '<':
                return (v1 < v2) ? options.fn(this) : options.inverse(this);
            case '<=':
                return (v1 <= v2) ? options.fn(this) : options.inverse(this);
            case '>':
                return (v1 > v2) ? options.fn(this) : options.inverse(this);
            case '>=':
                return (v1 >= v2) ? options.fn(this) : options.inverse(this);
            case '&&':
                return (v1 && v2) ? options.fn(this) : options.inverse(this);
            case '||':
                return (v1 || v2) ? options.fn(this) : options.inverse(this);
            default:
                return options.inverse(this);
        }
    });

};
<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>/*
Language: XQuery
Author: Dirk Kirsten <dk@basex.org>
Category: functional
Description: Supports XQuery 3.1 including XQuery Update 3, so also XPath (as it is a superset)
*/

function(hljs) {
  var KEYWORDS = 'for let if while then else return where group by xquery encoding version' +
    'module namespace boundary-space preserve strip default collation base-uri ordering' +
    'copy-namespaces order declare import schema namespace function option in allowing empty' +
    'at tumbling window sliding window start when only end when previous next stable ascending' +
    'descending empty greatest least some every satisfies switch case typeswitch try catch and' +
    'or to union intersect instance of treat as castable cast map array delete insert into' +
    'replace value rename copy modify update';
  var LITERAL = 'false true xs:string xs:integer element item xs:date xs:datetime xs:float xs:double xs:decimal QName xs:anyURI xs:long xs:int xs:short xs:byte attribute';
  var VAR = {
    className: 'variable',
    begin: /\$[a-zA-Z0-9\-]+/,
    relevance: 5
  };

  var NUMBER = {
    className: 'number',
    begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
    relevance: 0
  };

  var STRING = {
    className: 'string',
    begin: '"', end: '"'
  };

  var ANNOTATION = {
    className: 'decorator',
    begin: '%\\w+'
  };

  var COMMENT = {
    className: 'comment',
    begin: '\\(:', end: ':\\)',
    relevance: 10,
    contains: [
      {
        className: 'doc', begin: '@\\w+'
      }
    ]
  };

  var METHOD = {
    begin: '{', end: '}'
  };

  var CONTAINS = [
    VAR,
    STRING,
    NUMBER,
    COMMENT,
    ANNOTATION,
    METHOD
  ];
  METHOD.contains = CONTAINS;

  return {
    aliases: ['xpath', 'xq'],
    case_insensitive: false,
    lexemes: /[a-zA-Z\$][a-zA-Z0-9_:\-]*/,
    illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,
    keywords: {
      keyword: KEYWORDS,
      literal: LITERAL
    },
    contains: CONTAINS
  };
}
<commit_msg>Double and single quoted strings in XQuery.<commit_after>/*
Language: XQuery
Author: Dirk Kirsten <dk@basex.org>
Category: functional
Description: Supports XQuery 3.1 including XQuery Update 3, so also XPath (as it is a superset)
*/

function(hljs) {
  var KEYWORDS = 'for let if while then else return where group by xquery encoding version' +
    'module namespace boundary-space preserve strip default collation base-uri ordering' +
    'copy-namespaces order declare import schema namespace function option in allowing empty' +
    'at tumbling window sliding window start when only end when previous next stable ascending' +
    'descending empty greatest least some every satisfies switch case typeswitch try catch and' +
    'or to union intersect instance of treat as castable cast map array delete insert into' +
    'replace value rename copy modify update';
  var LITERAL = 'false true xs:string xs:integer element item xs:date xs:datetime xs:float xs:double xs:decimal QName xs:anyURI xs:long xs:int xs:short xs:byte attribute';
  var VAR = {
    className: 'variable',
    begin: /\$[a-zA-Z0-9\-]+/,
    relevance: 5
  };

  var NUMBER = {
    className: 'number',
    begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
    relevance: 0
  };

  var STRING = {
    className: 'string',
    variants: [
      {begin: /"/, end: /"/, contains: [{begin: /""/, relevance: 0}]},
      {begin: /'/, end: /'/, contains: [{begin: /''/, relevance: 0}]}
    ]
  };

  var ANNOTATION = {
    className: 'decorator',
    begin: '%\\w+'
  };

  var COMMENT = {
    className: 'comment',
    begin: '\\(:', end: ':\\)',
    relevance: 10,
    contains: [
      {
        className: 'doc', begin: '@\\w+'
      }
    ]
  };

  var METHOD = {
    begin: '{', end: '}'
  };

  var CONTAINS = [
    VAR,
    STRING,
    NUMBER,
    COMMENT,
    ANNOTATION,
    METHOD
  ];
  METHOD.contains = CONTAINS;

  return {
    aliases: ['xpath', 'xq'],
    case_insensitive: false,
    lexemes: /[a-zA-Z\$][a-zA-Z0-9_:\-]*/,
    illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,
    keywords: {
      keyword: KEYWORDS,
      literal: LITERAL
    },
    contains: CONTAINS
  };
}
<|endoftext|>


<commit_before>'use strict';

var path          = require('path');

var gulp          = require('gulp');
var concat        = require('gulp-concat');
var wrap          = require('gulp-wrap');
var inject        = require('gulp-inject');
var jshint        = require('gulp-jshint');
var minifyHtml    = require('gulp-minify-html');
var ngHtml2js     = require('gulp-ng-html2js');
var plumber       = require('gulp-plumber');
var rimraf        = require('gulp-rimraf');
var semiflat      = require('gulp-semiflat');
var slash         = require('gulp-slash');
var watch         = require('gulp-watch');
var watchSequence = require('gulp-watch-sequence');

var browserSync   = require('browser-sync');
var combined      = require('combined-stream');
var runSequence   = require('run-sequence');
var bourbon       = require('node-bourbon');

var project       = require(path.resolve('package.json'));

var HTTP_PORT     = 8000;
var CONSOLE_WIDTH = 80;

var BOWER         = 'bower_components';

var JS_LIB_BOWER  = 'bower_components/**/js-lib';
var JS_LIB_LOCAL  = 'src/js-lib';
var JS_SRC        = 'src/target';
var JS_BUILD      = 'build';

var CSS_LIB_BOWER = 'bower_components/**/css-lib';
var CSS_LIB_LOCAL = 'src/css-lib';
var CSS_SRC       = 'src/target';
var CSS_BUILD     = 'build';

var HTML_SRC      = 'src/target';
var HTML_BUILD    = 'build';
var PARTIALS_NAME = 'templates';

var RELEASE       = 'release';
var CDN_LIB       = 'html-lib';
var CDN_APP       = (project.category ? (project.category + '/') : '') + project.name;
var RELEASE_LIB   = RELEASE + '/' + CDN_LIB + '/$';
var RELEASE_APP   = RELEASE + '/' + CDN_APP + '/$';

var jsHintReporter   = require('./lib/build/jshint-reporter');
var browserify       = require('./lib/build/browserify');
var nodeSass         = require('./lib/build/node-sass');
var karma            = require('./lib/test/karma');
var bowerFiles       = require('./lib/inject/bower-files');
var injectAdjacent   = require('./lib/inject/adjacent-files');
var injectTransform  = require('./lib/inject/relative-transform');
var versionDirectory = require('./lib/release/version-directory');

function jsLibStream(opts) {
  return combined.create()
    .append(gulp.src(JS_LIB_BOWER + '/**/*.js', opts)                       // bower lib JS
      .pipe(semiflat(JS_LIB_BOWER)))
    .append(gulp.src([ JS_LIB_LOCAL + '/**/*.js', '`!**/*.spec.js' ], opts)  // local lib JS overwrites
      .pipe(semiflat(JS_LIB_LOCAL)));
}

function jsSrcStream(opts) {
  return gulp.src([ JS_SRC + '/**/*.js', '!**/assets/**' ], opts)           // local app JS
    .pipe(semiflat(JS_SRC));
}

function jsSpecStream(opts) {
  return gulp.src(JS_LIB_LOCAL + '/**/*.spec.js', opts)                     // local lib SPEC JS
    .pipe(semiflat(JS_LIB_LOCAL));
}

function scssLibStream(opts) {
  return combined.create()
    .append(gulp.src(CSS_LIB_BOWER + '/**/*.scss', opts)            // bower lib CSS
      .pipe(semiflat(CSS_LIB_BOWER)))
    .append(gulp.src(CSS_LIB_LOCAL + '/**/*.scss', opts)            // local lib CSS overwrites
      .pipe(semiflat(CSS_LIB_LOCAL)))
    .append(gulp.src(BOWER + '/**/bootstrap/bootstrap.scss', opts)  // bower bootstrap SASS
      .pipe(semiflat(BOWER + '/**/bootstrap')));
}

function scssSrcStream(opts) {
  return gulp.src([ CSS_SRC + '/**/*.scss', '!**/assets/**' ], opts)  // local app CSS
    .pipe(semiflat(CSS_SRC));
}

function bowerStream(opts) {
  return bowerFiles(CONSOLE_WIDTH)
    .prepend(browserify.RUNTIME)
    .js(opts);
}

function htmlPartialsSrcStream(opts) {
  return gulp.src([ HTML_SRC + '/**/partials/**/*.html', '!**/assets/**' ], opts)
    .pipe(semiflat(HTML_SRC));
}

function htmlAppSrcStream(opts) {
  return gulp.src([ HTML_SRC + '/**/*.html', '!**/assets/**' ], opts) // ignore partials
    .pipe(semiflat(HTML_SRC));
}

function routes() {
  var result = { };
  [ BOWER,
    JS_SRC,
    JS_BUILD,
    JS_LIB_LOCAL,
    CSS_SRC,
    CSS_BUILD,
    CSS_LIB_LOCAL,
    browserify.RUNTIME
  ].forEach(function(path) {
    result['/' + slash(path)] = path;
  });
  return result;
}

function hr(char, length, title) {
  var text = (title) ? (' ' + title.split('').join(' ').toUpperCase() + ' ') : '';  // double spaced title text
  while (text.length < length) {
    text = char + text + char;  // centre title between the given character
  }
  return text.slice(0, length); // enforce length, left justified
}

// DEFAULT ---------------------------------
var isMinify = (process.argv[process.argv.length - 1] !== 'nominify');

function hr(char, length, title) {
  var text = (title) ? (' ' + title.split('').join(' ').toUpperCase() + ' ') : '';  // double spaced title text
  while (text.length < length) {
    text = char + text + char;  // centre title between the given character
  }
  return text.slice(0, length); // enforce length, left justified
}

gulp.task('default', [ 'watch' ]);

gulp.task('nominify', [ 'watch' ]);

gulp.task('build', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'build'));
  runSequence('js', 'css', 'html', done);
});

// SERVER ---------------------------------
gulp.task('server', [ 'build' ], function() {
  console.log(hr('-', CONSOLE_WIDTH, 'server'));
  browserSync({
    server: {
      baseDir: HTML_BUILD,
      routes:  routes()
    },
    port:     HTTP_PORT,
    logLevel: 'silent',
    open:     false
  });
});

gulp.task('reload', function() {
  console.log(hr('-', CONSOLE_WIDTH, 'reload'));
  browserSync.reload();
});

// JS ---------------------------------
gulp.task('js', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'javascript'));
  runSequence(
    [ 'js:clean', 'js:init' ],
    'js:build',
    done
  );
});

gulp.task('test', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'test'));
  runSequence(
    'js:init',
    'js:unit',
    done
  );
});

// clean the js build directory
gulp.task('js:clean', function() {
  return gulp.src(JS_BUILD + '/**/*.js*', { read: false })
    .pipe(rimraf());
});

var bundler;

// mark sources for browserify and run linter
gulp.task('js:init', function() {
  bundler = browserify(CONSOLE_WIDTH);
  return combined.create()
    .append(jsLibStream())
    .append(jsSrcStream())
    .append(jsSpecStream())
    .pipe(bundler.sources())
    .pipe(bundler.reserve())
    .pipe(jshint())
    .pipe(jsHintReporter(CONSOLE_WIDTH));
});

// karma unit tests in local library only
gulp.task('js:unit', function() {
  var preJasmine = bundler.getJasmineTransform({
    '@': function (filename) { return filename + ':0:0'; }  // @ is replaced with filename:0:0
  });
  return jsSpecStream()
    .pipe(bundler.compile(preJasmine, bundler.es6ifyTransform).all('test/karma-main.js'))
    .pipe(gulp.dest(JS_BUILD))
    .pipe(karma({
      files:      bowerStream({ dev: true }).list,
      frameworks: [ 'jasmine' ],
      reporters:  [ 'spec' ],
      browsers:   [ 'Chrome' ],
      logLevel:   'error'
    }, CONSOLE_WIDTH));
});

// give a single optimised js file in the build directory with source map for each
gulp.task('js:build', function() {
  return jsSrcStream({ read: false })
    .pipe(bundler.compile(bundler.es6ifyTransform).each(isMinify))
    .pipe(gulp.dest(JS_BUILD));
});

// CSS ---------------------------------
gulp.task('css', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'css'));
  runSequence(
    [ 'css:clean', 'css:init' ],
    'css:build',
    done
  );
});

// clean the css build directory
gulp.task('css:clean', function() {
  return gulp.src(CSS_BUILD + '/**/*.css*', { read: false })
    .pipe(rimraf());
});

var sass;

// discover css libs
gulp.task('css:init', function() {
  sass = nodeSass();
  return scssLibStream({ read: false })
    .pipe(sass.libraries(bourbon.includePaths));
});

// compile sass with the previously discovered lib paths
gulp.task('css:build', function() {
  return scssSrcStream({ read: false })
    .pipe(sass.compile())
    .pipe(gulp.dest(CSS_BUILD));
});

// HTML ---------------------------------
gulp.task('html', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'html'));
  runSequence(
    'html:clean',
    [ 'html:partials', 'html:assets' ],
    'html:inject',
    done
  );
});

// clean the html build directory
gulp.task('html:clean', function() {
  return gulp.src([ HTML_BUILD + '/**/*.html*', HTML_BUILD + '/**/assets/**' ], { read: false })
    .pipe(rimraf());
});

// convert partials into template js
gulp.task('html:partials', function() {
  return htmlPartialsSrcStream()
    .pipe(plumber())
    .pipe(minifyHtml({
      empty:  true,
      spare:  true,
      quotes: true
    }))
    .pipe(ngHtml2js({
      moduleName: PARTIALS_NAME
    }))
    .pipe(concat(PARTIALS_NAME + '.html.js'))
    .pipe(gulp.dest(JS_BUILD));
});

// copy assets to build directory
gulp.task('html:assets', function() {
  return gulp.src(HTML_SRC + '/**/assets/**')
    .pipe(gulp.dest(HTML_BUILD));
});

// inject dependencies into html and output to build directory
gulp.task('html:inject', function() {
  return htmlAppSrcStream()
    .pipe(plumber())
    .pipe(injectAdjacent('js', JS_BUILD))
    .pipe(injectAdjacent('css', CSS_BUILD))
    .pipe(inject(bowerStream({ read: false }), {
      name: 'bower'
    }))
    .pipe(gulp.dest(HTML_BUILD));
});

// RELEASE ---------------------------------
gulp.task('release', [ 'build' ], function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'release'));
  runSequence(
    'release:clean',
    [ 'release:adjacent', 'release:bower' ],
    'release:versionlib',
    'release:inject',
    'release:versionapp',
    done
  );
});

// clean the html build directory
gulp.task('release:clean', function() {
  return gulp.src(RELEASE, { read: false })
    .pipe(rimraf());
});

gulp.task('release:adjacent', function() {
  return combined.create()
    .append(gulp.src([ JS_BUILD   + '/**/*.js',   '!**/dev/**', '!**/test**'      ]))
    .append(gulp.src([ CSS_BUILD  + '/**/*.css',  '!**/dev/**', '!**/test**'      ]))
    .append(gulp.src([ HTML_SRC   + '/**/*.html', '!**/dev/**', '!**/partials/**' ]))
    .append(gulp.src([ HTML_SRC   + '/**/assets/**' ]))
    .pipe(gulp.dest(RELEASE_APP));
});

// copy bower main elements to versioned directories in release
gulp.task('release:bower', function() {
  return bowerStream({ manifest: true })
    .pipe(wrap([
        '/* ' + hr('-', 114),
        ' * <%= file.relative %>',
        ' * ' + hr('-', 114) + ' */',
        '<%= contents %>'
      ].join('\n')))
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest(RELEASE_LIB));
});

// version the release app directory
gulp.task('release:versionlib', function() {
  return gulp.src(RELEASE_LIB + '/**')
    .pipe(versionDirectory('$', true));
});

// inject dependencies into html and output to build directory
gulp.task('release:inject', function() {
  return gulp.src([ RELEASE_APP + '/**/*.html', '!**/dev/**' ])
    .pipe(plumber())
    .pipe(injectAdjacent('js|css', RELEASE_APP, {
      name: 'inject',
      transform: injectTransform
    }))
    .pipe(inject(gulp.src(RELEASE_LIB.replace('$', '*') + '/**', { read: false }), {
      name: 'bower',
      transform: injectTransform
    }))
    .pipe(gulp.dest(RELEASE_APP));
});

// version the release app directory
gulp.task('release:versionapp', function() {
  return gulp.src(RELEASE_APP + '/**')
    .pipe(versionDirectory('$', true));
});

// WATCH ---------------------------------
gulp.task('watch', [ 'server' ], function() {

  // enqueue actions to avoid multiple trigger
  var queue = watchSequence(500, function() {
    console.log(hr('\u2591', CONSOLE_WIDTH));
  });

  // watch statements
  watch({
    name: 'JS',
    emitOnGlob: false,
    glob: [
      JS_LIB_BOWER + '/**/*.js',
      JS_LIB_LOCAL + '/**/*.js',
      JS_SRC       + '/**/*.js'
    ]
  }, queue.getHandler('js', 'html', 'reload')); // html will be needed in case previous injection failed

  watch({
    name: 'CSS',
    emitOnGlob: false,
    glob: [
      CSS_LIB_BOWER + '/**/*.scss',
      CSS_LIB_LOCAL + '/**/*.scss',
      CSS_SRC       + '/**/*.scss'
    ]
  }, queue.getHandler('css', 'html', 'reload')); // html will be needed in case previous injection failed

  watch({
    name: 'HTML | BOWER',
    emitOnGlob: false,
    glob: [
      BOWER    + '/**/*',
      HTML_SRC + '/**/*.html'
    ]
  }, queue.getHandler('html', 'reload'));
});<commit_msg>minor fix to sass routine logging<commit_after>'use strict';

var path          = require('path');

var gulp          = require('gulp');
var concat        = require('gulp-concat');
var wrap          = require('gulp-wrap');
var inject        = require('gulp-inject');
var jshint        = require('gulp-jshint');
var minifyHtml    = require('gulp-minify-html');
var ngHtml2js     = require('gulp-ng-html2js');
var plumber       = require('gulp-plumber');
var rimraf        = require('gulp-rimraf');
var semiflat      = require('gulp-semiflat');
var slash         = require('gulp-slash');
var watch         = require('gulp-watch');
var watchSequence = require('gulp-watch-sequence');

var browserSync   = require('browser-sync');
var combined      = require('combined-stream');
var runSequence   = require('run-sequence');
var bourbon       = require('node-bourbon');

var project       = require(path.resolve('package.json'));

var HTTP_PORT     = 8000;
var CONSOLE_WIDTH = 80;

var BOWER         = 'bower_components';

var JS_LIB_BOWER  = 'bower_components/**/js-lib';
var JS_LIB_LOCAL  = 'src/js-lib';
var JS_SRC        = 'src/target';
var JS_BUILD      = 'build';

var CSS_LIB_BOWER = 'bower_components/**/css-lib';
var CSS_LIB_LOCAL = 'src/css-lib';
var CSS_SRC       = 'src/target';
var CSS_BUILD     = 'build';

var HTML_SRC      = 'src/target';
var HTML_BUILD    = 'build';
var PARTIALS_NAME = 'templates';

var RELEASE       = 'release';
var CDN_LIB       = 'html-lib';
var CDN_APP       = (project.category ? (project.category + '/') : '') + project.name;
var RELEASE_LIB   = RELEASE + '/' + CDN_LIB + '/$';
var RELEASE_APP   = RELEASE + '/' + CDN_APP + '/$';

var jsHintReporter   = require('./lib/build/jshint-reporter');
var browserify       = require('./lib/build/browserify');
var nodeSass         = require('./lib/build/node-sass');
var karma            = require('./lib/test/karma');
var bowerFiles       = require('./lib/inject/bower-files');
var injectAdjacent   = require('./lib/inject/adjacent-files');
var injectTransform  = require('./lib/inject/relative-transform');
var versionDirectory = require('./lib/release/version-directory');

function jsLibStream(opts) {
  return combined.create()
    .append(gulp.src(JS_LIB_BOWER + '/**/*.js', opts)                       // bower lib JS
      .pipe(semiflat(JS_LIB_BOWER)))
    .append(gulp.src([ JS_LIB_LOCAL + '/**/*.js', '`!**/*.spec.js' ], opts)  // local lib JS overwrites
      .pipe(semiflat(JS_LIB_LOCAL)));
}

function jsSrcStream(opts) {
  return gulp.src([ JS_SRC + '/**/*.js', '!**/assets/**' ], opts)           // local app JS
    .pipe(semiflat(JS_SRC));
}

function jsSpecStream(opts) {
  return gulp.src(JS_LIB_LOCAL + '/**/*.spec.js', opts)                     // local lib SPEC JS
    .pipe(semiflat(JS_LIB_LOCAL));
}

function scssLibStream(opts) {
  return combined.create()
    .append(gulp.src(CSS_LIB_BOWER + '/**/*.scss', opts)            // bower lib CSS
      .pipe(semiflat(CSS_LIB_BOWER)))
    .append(gulp.src(CSS_LIB_LOCAL + '/**/*.scss', opts)            // local lib CSS overwrites
      .pipe(semiflat(CSS_LIB_LOCAL)))
    .append(gulp.src(BOWER + '/**/bootstrap/bootstrap.scss', opts)  // bower bootstrap SASS
      .pipe(semiflat(BOWER + '/**/bootstrap')));
}

function scssSrcStream(opts) {
  return gulp.src([ CSS_SRC + '/**/*.scss', '!**/assets/**' ], opts)  // local app CSS
    .pipe(semiflat(CSS_SRC));
}

function bowerStream(opts) {
  return bowerFiles(CONSOLE_WIDTH)
    .prepend(browserify.RUNTIME)
    .js(opts);
}

function htmlPartialsSrcStream(opts) {
  return gulp.src([ HTML_SRC + '/**/partials/**/*.html', '!**/assets/**' ], opts)
    .pipe(semiflat(HTML_SRC));
}

function htmlAppSrcStream(opts) {
  return gulp.src([ HTML_SRC + '/**/*.html', '!**/assets/**' ], opts) // ignore partials
    .pipe(semiflat(HTML_SRC));
}

function routes() {
  var result = { };
  [ BOWER,
    JS_SRC,
    JS_BUILD,
    JS_LIB_LOCAL,
    CSS_SRC,
    CSS_BUILD,
    CSS_LIB_LOCAL,
    browserify.RUNTIME
  ].forEach(function(path) {
    result['/' + slash(path)] = path;
  });
  return result;
}

function hr(char, length, title) {
  var text = (title) ? (' ' + title.split('').join(' ').toUpperCase() + ' ') : '';  // double spaced title text
  while (text.length < length) {
    text = char + text + char;  // centre title between the given character
  }
  return text.slice(0, length); // enforce length, left justified
}

// DEFAULT ---------------------------------
var isMinify = (process.argv[process.argv.length - 1] !== 'nominify');

function hr(char, length, title) {
  var text = (title) ? (' ' + title.split('').join(' ').toUpperCase() + ' ') : '';  // double spaced title text
  while (text.length < length) {
    text = char + text + char;  // centre title between the given character
  }
  return text.slice(0, length); // enforce length, left justified
}

gulp.task('default', [ 'watch' ]);

gulp.task('nominify', [ 'watch' ]);

gulp.task('build', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'build'));
  runSequence('js', 'css', 'html', done);
});

// SERVER ---------------------------------
gulp.task('server', [ 'build' ], function() {
  console.log(hr('-', CONSOLE_WIDTH, 'server'));
  browserSync({
    server: {
      baseDir: HTML_BUILD,
      routes:  routes()
    },
    port:     HTTP_PORT,
    logLevel: 'silent',
    open:     false
  });
});

gulp.task('reload', function() {
  console.log(hr('-', CONSOLE_WIDTH, 'reload'));
  browserSync.reload();
});

// JS ---------------------------------
gulp.task('js', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'javascript'));
  runSequence(
    [ 'js:clean', 'js:init' ],
    'js:build',
    done
  );
});

gulp.task('test', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'test'));
  runSequence(
    'js:init',
    'js:unit',
    done
  );
});

// clean the js build directory
gulp.task('js:clean', function() {
  return gulp.src(JS_BUILD + '/**/*.js*', { read: false })
    .pipe(rimraf());
});

var bundler;

// mark sources for browserify and run linter
gulp.task('js:init', function() {
  bundler = browserify(CONSOLE_WIDTH);
  return combined.create()
    .append(jsLibStream())
    .append(jsSrcStream())
    .append(jsSpecStream())
    .pipe(bundler.sources())
    .pipe(bundler.reserve())
    .pipe(jshint())
    .pipe(jsHintReporter(CONSOLE_WIDTH));
});

// karma unit tests in local library only
gulp.task('js:unit', function() {
  var preJasmine = bundler.getJasmineTransform({
    '@': function (filename) { return filename + ':0:0'; }  // @ is replaced with filename:0:0
  });
  return jsSpecStream()
    .pipe(bundler.compile(preJasmine, bundler.es6ifyTransform).all('test/karma-main.js'))
    .pipe(gulp.dest(JS_BUILD))
    .pipe(karma({
      files:      bowerStream({ dev: true }).list,
      frameworks: [ 'jasmine' ],
      reporters:  [ 'spec' ],
      browsers:   [ 'Chrome' ],
      logLevel:   'error'
    }, CONSOLE_WIDTH));
});

// give a single optimised js file in the build directory with source map for each
gulp.task('js:build', function() {
  return jsSrcStream({ read: false })
    .pipe(bundler.compile(bundler.es6ifyTransform).each(isMinify))
    .pipe(gulp.dest(JS_BUILD));
});

// CSS ---------------------------------
gulp.task('css', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'css'));
  runSequence(
    [ 'css:clean', 'css:init' ],
    'css:build',
    done
  );
});

// clean the css build directory
gulp.task('css:clean', function() {
  return gulp.src(CSS_BUILD + '/**/*.css*', { read: false })
    .pipe(rimraf());
});

var sass;

// discover css libs
gulp.task('css:init', function() {
  sass = nodeSass(CONSOLE_WIDTH);
  return scssLibStream({ read: false })
    .pipe(sass.libraries(bourbon.includePaths));
});

// compile sass with the previously discovered lib paths
gulp.task('css:build', function() {
  return scssSrcStream({ read: false })
    .pipe(sass.compile())
    .pipe(gulp.dest(CSS_BUILD));
});

// HTML ---------------------------------
gulp.task('html', function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'html'));
  runSequence(
    'html:clean',
    [ 'html:partials', 'html:assets' ],
    'html:inject',
    done
  );
});

// clean the html build directory
gulp.task('html:clean', function() {
  return gulp.src([ HTML_BUILD + '/**/*.html*', HTML_BUILD + '/**/assets/**' ], { read: false })
    .pipe(rimraf());
});

// convert partials into template js
gulp.task('html:partials', function() {
  return htmlPartialsSrcStream()
    .pipe(plumber())
    .pipe(minifyHtml({
      empty:  true,
      spare:  true,
      quotes: true
    }))
    .pipe(ngHtml2js({
      moduleName: PARTIALS_NAME
    }))
    .pipe(concat(PARTIALS_NAME + '.html.js'))
    .pipe(gulp.dest(JS_BUILD));
});

// copy assets to build directory
gulp.task('html:assets', function() {
  return gulp.src(HTML_SRC + '/**/assets/**')
    .pipe(gulp.dest(HTML_BUILD));
});

// inject dependencies into html and output to build directory
gulp.task('html:inject', function() {
  return htmlAppSrcStream()
    .pipe(plumber())
    .pipe(injectAdjacent('js', JS_BUILD))
    .pipe(injectAdjacent('css', CSS_BUILD))
    .pipe(inject(bowerStream({ read: false }), {
      name: 'bower'
    }))
    .pipe(gulp.dest(HTML_BUILD));
});

// RELEASE ---------------------------------
gulp.task('release', [ 'build' ], function(done) {
  console.log(hr('-', CONSOLE_WIDTH, 'release'));
  runSequence(
    'release:clean',
    [ 'release:adjacent', 'release:bower' ],
    'release:versionlib',
    'release:inject',
    'release:versionapp',
    done
  );
});

// clean the html build directory
gulp.task('release:clean', function() {
  return gulp.src(RELEASE, { read: false })
    .pipe(rimraf());
});

gulp.task('release:adjacent', function() {
  return combined.create()
    .append(gulp.src([ JS_BUILD   + '/**/*.js',   '!**/dev/**', '!**/test**'      ]))
    .append(gulp.src([ CSS_BUILD  + '/**/*.css',  '!**/dev/**', '!**/test**'      ]))
    .append(gulp.src([ HTML_SRC   + '/**/*.html', '!**/dev/**', '!**/partials/**' ]))
    .append(gulp.src([ HTML_SRC   + '/**/assets/**' ]))
    .pipe(gulp.dest(RELEASE_APP));
});

// copy bower main elements to versioned directories in release
gulp.task('release:bower', function() {
  return bowerStream({ manifest: true })
    .pipe(wrap([
        '/* ' + hr('-', 114),
        ' * <%= file.relative %>',
        ' * ' + hr('-', 114) + ' */',
        '<%= contents %>'
      ].join('\n')))
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest(RELEASE_LIB));
});

// version the release app directory
gulp.task('release:versionlib', function() {
  return gulp.src(RELEASE_LIB + '/**')
    .pipe(versionDirectory('$', true));
});

// inject dependencies into html and output to build directory
gulp.task('release:inject', function() {
  return gulp.src([ RELEASE_APP + '/**/*.html', '!**/dev/**' ])
    .pipe(plumber())
    .pipe(injectAdjacent('js|css', RELEASE_APP, {
      name: 'inject',
      transform: injectTransform
    }))
    .pipe(inject(gulp.src(RELEASE_LIB.replace('$', '*') + '/**', { read: false }), {
      name: 'bower',
      transform: injectTransform
    }))
    .pipe(gulp.dest(RELEASE_APP));
});

// version the release app directory
gulp.task('release:versionapp', function() {
  return gulp.src(RELEASE_APP + '/**')
    .pipe(versionDirectory('$', true));
});

// WATCH ---------------------------------
gulp.task('watch', [ 'server' ], function() {

  // enqueue actions to avoid multiple trigger
  var queue = watchSequence(500, function() {
    console.log(hr('\u2591', CONSOLE_WIDTH));
  });

  // watch statements
  watch({
    name: 'JS',
    emitOnGlob: false,
    glob: [
      JS_LIB_BOWER + '/**/*.js',
      JS_LIB_LOCAL + '/**/*.js',
      JS_SRC       + '/**/*.js'
    ]
  }, queue.getHandler('js', 'html', 'reload')); // html will be needed in case previous injection failed

  watch({
    name: 'CSS',
    emitOnGlob: false,
    glob: [
      CSS_LIB_BOWER + '/**/*.scss',
      CSS_LIB_LOCAL + '/**/*.scss',
      CSS_SRC       + '/**/*.scss'
    ]
  }, queue.getHandler('css', 'html', 'reload')); // html will be needed in case previous injection failed

  watch({
    name: 'HTML | BOWER',
    emitOnGlob: false,
    glob: [
      BOWER    + '/**/*',
      HTML_SRC + '/**/*.html'
    ]
  }, queue.getHandler('html', 'reload'));
});<|endoftext|>


<commit_before>/* jshint undef: true, unused: true, browser: true, quotmark: single, curly: true */
/* global Ext */
Ext.define('Jarvus.touch.layout.Accordion', {
    extend: 'Ext.layout.Default',
    alias: ['layout.accordion'],

    config: {
        expandedItem: null,
        allowCollapse: true,
        scrollOnExpand: false
    },

    constructor: function() {
        var me = this;
        me.callParent(arguments);
    },

    setContainer: function(container) {
        var me = this,
            options = {
                delegate: '> component'
            };

        me.callParent(arguments);

        container.innerElement.on('tap', 'onHeaderTap', me, {
            delegate: '.accordion-header'
        });

        container.on('hide', 'onItemHide', me, options)
            .on('show', 'onItemShow', me, options)
            .on('expand', 'onItemExpand', me, options)
            .on('collapse', 'onItemCollapse', me, options);

        container.addCls('jarvus-layout-accordion');
    },

    insertInnerItem: function(item, index) {
        var me = this,
            container = me.container,
            itemDom = item.element.dom,
            nextSibling = container.getInnerAt(index + 1),
            nextSiblingDom = nextSibling ? nextSibling.accordion.dom : null,
            accordion;

        item.element.addCls('accordion-body');
        accordion = container.innerElement.createChild({
            tag: 'section',
            cls: 'accordion-section',
            cn: {
                tag: 'h1',
                cls: 'accordion-header',
                html: item.config.title
            }
        }, nextSiblingDom);

        if (item.isHidden()) {
            accordion.hide();
        }

        accordion.dom.appendChild(itemDom);

        accordion.item = item;
        item.accordion = accordion;

        return me;
    },

    removeInnerItem: function(item) {
        item.accordion.detach();
    },

    onHeaderTap: function(ev) {
        var item = ev.getTarget('.accordion-section', this.container.innerElement, true).item;

        if (item.collapsed) {
            item.expand();
        } else {
            item.collapse();
        }
    },

    applyExpandedItem: function(item) {
        if (!item && item !== 0) {
            return null;
        }

        if (item.isElement) {
            return item.item;
        }

        if (Ext.isNumber(item)) {
            return this.container.getInnerAt(item);
        }

        return item;
    },

    updateExpandedItem: function(item, oldItem) {
        if (oldItem && !this.container.config.allowMultipleExpandedItems) {
            oldItem.collapse();
        }

        if (item && item.isPainted()) {
            item.expand();
        }
    },

    onItemAdd: function(item) {
        var me = this;

        me.callParent(arguments);

        item.expand = function() {
            if (item.collapsed && item.fireEvent('beforeexpand', item, me) !== false) {
                item.collapsed = false;
                item.fireEvent('expand', item, me);
            }
        };

        item.collapse = function() {
            if (!item.collapsed && item.fireEvent('beforecollapse', item, me) !== false) {
                item.collapsed = true;
                item.fireEvent('collapse', item, me);
            }
        };

        if (item.config.expanded) {
            me.setExpandedItem(item);
            item.collapsed = false;
            item.accordion.addCls('selected');
        } else {
            item.collapsed = true;
        }
    },

    onItemHide: function(item) {
        if (item.isInnerItem()) {
            item.accordion.hide();
        }
    },

    onItemShow: function(item) {
        if (item.isInnerItem()) {
            item.accordion.show();
        }
    },

    onItemExpand: function(item) {
        var me = this,
            container = me.findParentContainerWithScrollable(),
            scrollable = container.getScrollable(),
            scroller = scrollable ? scrollable.getScroller() : null;

        me.setExpandedItem(item);

        if (item && me.shouldItemBeMaximized(item)) {
            item.setHeight(container.bodyElement.getHeight() - me.getTotalHeight(container));
            if (scroller) {
                scroller.setDisabled(true);
            }
        } else if (scroller) {
            scroller.setDisabled(false);

            if (me.getScrollOnExpand()) {
                Ext.defer(function() {
                    scroller.scrollTo(0, me.getHeaderScrollPosition(item), true);
                }, 10);
            }
        }

        item.accordion.addCls('selected');
    },

    onItemCollapse: function(item) {
        var me = this;

        if (me.getExpandedItem() === item) {
            me.setExpandedItem(null);
        }

        item.accordion.removeCls('selected');
    },

    /**
     * certain functions depend on working with a container that has a scrollable/scroller;
     * since it's possible that an accordion might exist as a child of a parent container
     * that has scrollable (instead of the accordion container being the entire scrollable area),
     * we can use this function to locate the nearest parent with a scrollable.
     */
    findParentContainerWithScrollable: function() {
        var container = this.container;

        return container.up('container{getScrollable()}') || container;
    },

    /**
     * Test if given item should be maximized
     */
    shouldItemBeMaximized: function(item) {
        var me = this,
            container = me.findParentContainerWithScrollable();

        return !container.getScrollable().getElement().getHeight() || !!item.config.maximizeHeight;
    },

    getTotalHeight: function(container) {
        var innerItems = container.getInnerItems(),
            len = innerItems.length,
            i = 0,
            totalHeight = 0,
            containerItem;

        if (container === this.container) {
            for (; i < len; i++) {
                containerItem = innerItems[i];
                if (!containerItem.getHidden()) {
                    totalHeight += containerItem.accordion.getHeight();
                }
            }
        }

        return totalHeight;
    },

    getHeaderScrollPosition: function(item) {
        var innerItems = this.container.getInnerItems(),
            index = Ext.Array.indexOf(innerItems, item) - 1,
            top = 0;

        while (index >= 0) {
            top += innerItems[index].accordion.getHeight();
            index--;
        }

        return top;
    }
});
<commit_msg>only scroll if necessary<commit_after>/* jshint undef: true, unused: true, browser: true, quotmark: single, curly: true */
/* global Ext */
Ext.define('Jarvus.touch.layout.Accordion', {
    extend: 'Ext.layout.Default',
    alias: ['layout.accordion'],

    config: {
        expandedItem: null,
        allowCollapse: true,
        scrollOnExpand: false
    },

    constructor: function() {
        var me = this;
        me.callParent(arguments);
    },

    setContainer: function(container) {
        var me = this,
            options = {
                delegate: '> component'
            };

        me.callParent(arguments);

        container.innerElement.on('tap', 'onHeaderTap', me, {
            delegate: '.accordion-header'
        });

        container.on('hide', 'onItemHide', me, options)
            .on('show', 'onItemShow', me, options)
            .on('expand', 'onItemExpand', me, options)
            .on('collapse', 'onItemCollapse', me, options);

        container.addCls('jarvus-layout-accordion');
    },

    insertInnerItem: function(item, index) {
        var me = this,
            container = me.container,
            itemDom = item.element.dom,
            nextSibling = container.getInnerAt(index + 1),
            nextSiblingDom = nextSibling ? nextSibling.accordion.dom : null,
            accordion;

        item.element.addCls('accordion-body');
        accordion = container.innerElement.createChild({
            tag: 'section',
            cls: 'accordion-section',
            cn: {
                tag: 'h1',
                cls: 'accordion-header',
                html: item.config.title
            }
        }, nextSiblingDom);

        if (item.isHidden()) {
            accordion.hide();
        }

        accordion.dom.appendChild(itemDom);

        accordion.item = item;
        item.accordion = accordion;

        return me;
    },

    removeInnerItem: function(item) {
        item.accordion.detach();
    },

    onHeaderTap: function(ev) {
        var item = ev.getTarget('.accordion-section', this.container.innerElement, true).item;

        if (item.collapsed) {
            item.expand();
        } else {
            item.collapse();
        }
    },

    applyExpandedItem: function(item) {
        if (!item && item !== 0) {
            return null;
        }

        if (item.isElement) {
            return item.item;
        }

        if (Ext.isNumber(item)) {
            return this.container.getInnerAt(item);
        }

        return item;
    },

    updateExpandedItem: function(item, oldItem) {
        if (oldItem && !this.container.config.allowMultipleExpandedItems) {
            oldItem.collapse();
        }

        if (item && item.isPainted()) {
            item.expand();
        }
    },

    onItemAdd: function(item) {
        var me = this;

        me.callParent(arguments);

        item.expand = function() {
            if (item.collapsed && item.fireEvent('beforeexpand', item, me) !== false) {
                item.collapsed = false;
                item.fireEvent('expand', item, me);
            }
        };

        item.collapse = function() {
            if (!item.collapsed && item.fireEvent('beforecollapse', item, me) !== false) {
                item.collapsed = true;
                item.fireEvent('collapse', item, me);
            }
        };

        if (item.config.expanded) {
            me.setExpandedItem(item);
            item.collapsed = false;
            item.accordion.addCls('selected');
        } else {
            item.collapsed = true;
        }
    },

    onItemHide: function(item) {
        if (item.isInnerItem()) {
            item.accordion.hide();
        }
    },

    onItemShow: function(item) {
        if (item.isInnerItem()) {
            item.accordion.show();
        }
    },

    onItemExpand: function(item) {
        var me = this,
            container = me.findParentContainerWithScrollable(),
            scrollable = container.getScrollable(),
            scroller = scrollable ? scrollable.getScroller() : null;

        me.setExpandedItem(item);

        if (item && me.shouldItemBeMaximized(item)) {
            item.setHeight(container.bodyElement.getHeight() - me.getTotalHeight(container));
            if (scroller) {
                scroller.setDisabled(true);
            }
        } else if (scroller) {
            scroller.setDisabled(false);

            if (me.getScrollOnExpand()) {
                Ext.defer(function() {
                    var scrollToY = me.getHeaderScrollPosition(item);

                    if (scroller.getSize().y - scroller.getContainerSize().y > scrollToY) {
                        scroller.scrollTo(0, scrollToY, true);
                    }
                }, 25);
            }
        }

        item.accordion.addCls('selected');
    },

    onItemCollapse: function(item) {
        var me = this;

        if (me.getExpandedItem() === item) {
            me.setExpandedItem(null);
        }

        item.accordion.removeCls('selected');
    },

    /**
     * certain functions depend on working with a container that has a scrollable/scroller;
     * since it's possible that an accordion might exist as a child of a parent container
     * that has scrollable (instead of the accordion container being the entire scrollable area),
     * we can use this function to locate the nearest parent with a scrollable.
     */
    findParentContainerWithScrollable: function() {
        var container = this.container;

        return container.up('container{getScrollable()}') || container;
    },

    /**
     * Test if given item should be maximized
     */
    shouldItemBeMaximized: function(item) {
        var me = this,
            container = me.findParentContainerWithScrollable();

        return !container.getScrollable().getElement().getHeight() || !!item.config.maximizeHeight;
    },

    getTotalHeight: function(container) {
        var innerItems = container.getInnerItems(),
            len = innerItems.length,
            i = 0,
            totalHeight = 0,
            containerItem;

        if (container === this.container) {
            for (; i < len; i++) {
                containerItem = innerItems[i];
                if (!containerItem.getHidden()) {
                    totalHeight += containerItem.accordion.getHeight();
                }
            }
        }

        return totalHeight;
    },

    getHeaderScrollPosition: function(item) {
        var innerItems = this.container.getInnerItems(),
            index = Ext.Array.indexOf(innerItems, item) - 1,
            top = 0;

        while (index >= 0) {
            top += innerItems[index].accordion.getHeight();
            index--;
        }

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