<commit_before>'use strict';

// core modules
const Path = require('path');

// dep modules
const _ = require('lodash');
const Promise = require('bluebird');
const fs = require('fs-extra');
const marked = require('marked');
const uglify = require('uglify-js');
const stripJsonComments = require('strip-json-comments');
const Less = require('less');
const LessCleanCssPlugin = require('less-plugin-clean-css');
const gzipSize = require('gzip-size');

const GLOB = Promise.promisify(require('glob'));
const lessCleanCssPlugin = new LessCleanCssPlugin({ advanced: true });

let utils = null;

// ---------------------------
// path
// ---------------------------

const path = {
    // filename without the extension
    basename(filepath) {
        const ext = Path.extname(filepath);
        return Path.basename(filepath, ext);
    },
    parent(p) {
        p = Path.normalize(p);
        const arr = p.split(/[\\/]+/);
        // remove last item
        arr.splice(-1, 1);
        return arr.join(Path.sep);
    },
    ensureLeadSlash(p) {
        return p.slice(0, 1) !== '/' ? `/${p}` : p;
    },
    ensureEndSlash(p) {
        return p.slice(-1) !== '/' ? `${p}/` : p;
    },
    removeEndSlash(p) {
        return p.slice(-1) === '/' ? p.slice(0, p.length - 1) : p;
    },
    removeLeadSlash(p) {
        return p.slice(0, 1) === '/' ? p.slice(1) : p;
    }
};

// ---------------------------
// file
// ---------------------------

const file = {
    merge(fileList) {
        const merged = [];
        // using Promise.each instead of Promise.map, to ensure order guarantee
        // in sequential execution.
        return Promise
            .each(fileList, filePath => {
                return fs.readFile(filePath, 'utf8')
                    .then(content => {
                        merged.push(content);
                    });
            })
            .then(() => { // (fileList)
                return merged.join('\n');
            });
    }
};

// ---------------------------
// json
// ---------------------------

const json = {
    read(filePath) {
        return fs.readFile(filePath, 'utf8')
            .then(string => JSON.parse(stripJsonComments(string)));
    },
    readSync(filePath) {
        const string = fs.readFileSync(filePath, 'utf8');
        return JSON.parse(stripJsonComments(string));
    },
    write(object, filePath) {
        const json = JSON.stringify(object, null, '  ');
        return file.write(filePath, json, 'utf8');
    },
    removeComments(string) {
        return stripJsonComments(string);
    }
};

// ---------------------------
// script / js
// ---------------------------

// https://github.com/mishoo/UglifyJS2
const defaultMinifyOpts = {
    compress: {},
    output: {
        // only output the commets with a @license directive
        comments: /@license/g
    }
};

const js = {
    minify(strScript, options = {}) {
        const opts = _.extend({}, defaultMinifyOpts, options);
        return uglify.minify(strScript, opts);
        // returns { code, map }
    },
    minifyFile(filePath, options = {}) {
        const opts = _.extend({}, defaultMinifyOpts, options);
        return fs.readFile(filePath, 'utf8')
            .then(strScript => js.minify(strScript, opts)); // returns { code, map }
    },
    /**
     *  Gets the file path for the minified version of the given file.
     *
     *  @param {String} filePath - Path of the original (unminified) file.
     *
     *  @returns {String} - Path of the minified version.
     */
    getMinPath(filePath) {
        const fPath = filePath.toLowerCase();
        if (_.endsWith(fPath, '.min.js')) return fPath;
        return Path.join(Path.dirname(fPath), `${Path.basename(fPath, '.js')}.min.js`);
    },
    /**
     *  Reads the given JS file into memory.
     *
     *  @param {String} filePath
     *         Path of the JS file.
     *  @param {Boolean} [noMinify=false]
     *         Whether not to minify the JS content.
     *  @param {Boolean} [checkMinFile=false]
     *         Whether to first check for an existing minified file (with a
     *         `min.js` suffix).
     *
     *  @returns {Promise} - Promise that returns JS code content.
     */
    readFile(filePath, noMinify = false, checkMinFile = false) {
        if (noMinify) return fs.readFile(filePath, 'utf8');
        return Promise.resolve()
            .then(() => {
                if (!checkMinFile) return js.minifyFile(filePath); // minified.code
                const minFilePath = js.getMinPath(filePath);
                return fs.pathExists(minFilePath).then(exists => {
                    if (exists) return fs.readFile(minFilePath, 'utf8');
                    return js.minifyFile(filePath);
                });
            })
            .then(minified => minified.code || minified);
    }
};

// ---------------------------
// Markdown
// ---------------------------

const md = {
    /**
     *  Parses the given markdown content.
     *
     *  @param {String} string - Markdown content.
     *  @param {Object} [options] - Markdown options for `marked`.
     *
     *  @returns {Promise} - Promise that returns the markdown, parsed to HTML.
     */
    parse(string, options = {}) {
        return new Promise((resolve, reject) => {
            marked(string, options, (err, content) => {
                if (err) return reject(err);
                resolve(content);
            });
        });
    }
};

// ---------------------------
// glob
// ---------------------------

const glob = {
    // glob uses forward slash only. (in Windows too)
    // base is optional.
    normalize(base, globPath) {
        const gpSet = utils.isset(globPath);
        if (!gpSet) {
            globPath = base;
            base = '';
        } else {
            base += '/';
        }
        return Path.normalize(base + globPath).replace(/\\+/g, '/');
    },

    isNegated(pattern) {
        return pattern.slice(0, 1) === '!';
    },

    inspect(pattern, options = {}) {
        const negated = glob.isNegated(pattern);
        pattern = negated ? pattern.slice(1) : pattern;
        pattern = glob.normalize(pattern);
        return {
            hasMagic: GLOB.hasMagic(pattern, options),
            negated,
            pattern
        };
    },

    /**
     *  Expands the given glob pattern(s) into file-paths array.
     *  This uses the node-glob library but unlike it, this also accepts an
     *  Array input and negated globs are allowed.
     *  @param {String|Array} patterns - One or more patterns to be expanded.
     *  @param {Object} [options] - Glob options.
     *  @returns {Array} - Expanded list of file paths.
     */
    match(patterns, options = {}) {
        patterns = utils.ensureArray(patterns);

        // normalize ignored globs (glob paths sep should be `/` even in
        // windows.)
        options.ignore = (options.ignore || []).map(item => {
            return glob.normalize(item);
        });

        let files = [];
        const properPatterns = [];

        // We'll pick negated patterns into the ignore list and proper patterns
        // into a separate array. Also, we'll add non-glob patters (normal file
        // paths) to the final output array; bec. glob() will not process
        // non-glob patterns.
        _.each(patterns, p => {
            const g = glob.inspect(p);
            if (g.negated) {
                options.ignore.push(g.pattern);
            } else if (!g.hasMagic) {
                files.push(g.pattern);
            } else {
                properPatterns.push(g.pattern);
            }
        });

        return Promise.each(properPatterns, p => {
            return GLOB(p, options) // eslint-disable-line
                .then(expandedFiles => {
                    files = files.concat(expandedFiles);
                });
        }).then(() => files);
        // .thenReturn(files); // wrong! returns the result of Promise.each
    }
};

// ---------------------------
// less
// ---------------------------

// http://lesscss.org/usage/#programmatic-usage
// http://onedayitwillmake.com/blog/2013/03/compiling-less-from-a-node-js-script/
// http://lesscss.org/#using-less-command-line-usage

const defaultLessOpts = {
    // root .less file name (not the path).
    // filename: 'styles.less',
    // optimization level, higher is better but more volatile - 1 is a
    // good value.
    optimization: 1,
    // minify output css
    compress: true,
    // use YUI compressor?
    yuicompress: true,
    // additional paths to look for imported less files.
    paths: [],
    // less plugins
    plugins: []
};

const less = {
    compile(strLess, options) {
        options = _.defaults(options, defaultLessOpts);
        // also pass lessCleanCssPlugin if compress enabled.
        if (options.compress) options.plugins.push(lessCleanCssPlugin);
        // http://lesscss.org/usage/#programmatic-usage
        return Less.render(strLess, options);
        // returns { css, map, imports }
    },
    // filePath: root .less file path.
    compileFile(filePath, options) {
        options = options || {};
        return fs.readFile(filePath, 'utf8')
            .then(strLess => {
                const parentDir = Path.resolve(Path.dirname(filePath));
                // http://lesscss.org/usage/#programmatic-usage
                options.filename = Path.basename(filePath);
                options.paths = (options.paths || []).concat([parentDir]);
                return less.compile(strLess, options);
            });
        // returns { css, map, imports }
    }
};

utils = {
    isset(value) {
        return value !== undefined && value !== null;
    },
    // e.g.
    // let symbol = { code: { meta: { type: "MethodDefinition" } } };
    // notate(symbol, "code.meta.type") => "MethodDefinition"
    // See https://github.com/onury/notation for an advanced library.
    notate(obj, notation) {
        if (typeof obj !== 'object') return;
        // console.log('n', notation);
        const props = !Array.isArray(notation)
            ? notation.split('.')
            : notation;
        const prop = props[0];
        if (!prop) return;
        const o = obj[prop];
        if (props.length > 1) {
            props.shift();
            return utils.notate(o, props);
        }
        return o;
    },
    ensureArray(o) {
        if (o === undefined || o === null) return o;
        return Array.isArray(o) ? o : [o];
    },
    round(num, decimals = 0) {
        if (!decimals) return Math.round(num);
        const factor = decimals * 10;
        return Math.round(num * factor) / factor;
    },
    // in KB
    getContentSize(str, gzipped = false) {
        const bytes = gzipped
            ? gzipSize.sync(str)
            : Buffer.byteLength(str, 'utf8');
        return utils.round(bytes / 1024, 1);
    },
    path,
    file,
    js,
    json,
    md,
    glob,
    less
};

module.exports = utils;
<commit_msg>update path utils<commit_after>'use strict';

// core modules
const Path = require('path');

// dep modules
const _ = require('lodash');
const Promise = require('bluebird');
const fs = require('fs-extra');
const marked = require('marked');
const uglify = require('uglify-js');
const stripJsonComments = require('strip-json-comments');
const Less = require('less');
const LessCleanCssPlugin = require('less-plugin-clean-css');
const gzipSize = require('gzip-size');

const GLOB = Promise.promisify(require('glob'));
const lessCleanCssPlugin = new LessCleanCssPlugin({ advanced: true });

let utils = null;

// ---------------------------
// path
// ---------------------------

const path = {
    // filename without the extension
    basename(filepath) {
        const ext = Path.extname(filepath);
        return Path.basename(filepath, ext);
    },
    parent(p) {
        p = Path.normalize(p);
        const arr = p.split(/[\\/]+/);
        // remove last item
        arr.splice(-1, 1);
        return arr.join(Path.sep);
    },
    ensureLeadSlash(p, slash) {
        if (slash === undefined) slash = '/';
        return /^[\\/]/.test(p) === false ? `${slash}${p}` : p;
    },
    ensureEndSlash(p, slash) {
        if (slash === undefined) slash = '/';
        return /[\\/]$/.test(p) === false ? `${p}${slash}` : p;
    },
    removeEndSlash(p) {
        return p.replace(/[\\/]$/, '');
    },
    removeLeadSlash(p) {
        return p.replace(/^[\\/]/, '');
    },
    parentOfBase(p, base) {
        p = Path.normalize(path.removeEndSlash(p));
        if (!base) return p;
        base = Path.normalize(path.removeEndSlash(base));
        return p.slice(-base.length) === base
            ? p.slice(0, -base.length)
            : p;
    }
};

// ---------------------------
// file
// ---------------------------

const file = {
    merge(fileList) {
        const merged = [];
        // using Promise.each instead of Promise.map, to ensure order guarantee
        // in sequential execution.
        return Promise
            .each(fileList, filePath => {
                return fs.readFile(filePath, 'utf8')
                    .then(content => {
                        merged.push(content);
                    });
            })
            .then(() => { // (fileList)
                return merged.join('\n');
            });
    }
};

// ---------------------------
// json
// ---------------------------

const json = {
    read(filePath) {
        return fs.readFile(filePath, 'utf8')
            .then(string => JSON.parse(stripJsonComments(string)));
    },
    readSync(filePath) {
        const string = fs.readFileSync(filePath, 'utf8');
        return JSON.parse(stripJsonComments(string));
    },
    write(object, filePath) {
        const json = JSON.stringify(object, null, '  ');
        return file.write(filePath, json, 'utf8');
    },
    removeComments(string) {
        return stripJsonComments(string);
    }
};

// ---------------------------
// script / js
// ---------------------------

// https://github.com/mishoo/UglifyJS2
const defaultMinifyOpts = {
    compress: {},
    output: {
        // only output the commets with a @license directive
        comments: /@license/g
    }
};

const js = {
    minify(strScript, options = {}) {
        const opts = _.extend({}, defaultMinifyOpts, options);
        return uglify.minify(strScript, opts);
        // returns { code, map }
    },
    minifyFile(filePath, options = {}) {
        const opts = _.extend({}, defaultMinifyOpts, options);
        return fs.readFile(filePath, 'utf8')
            .then(strScript => js.minify(strScript, opts)); // returns { code, map }
    },
    /**
     *  Gets the file path for the minified version of the given file.
     *
     *  @param {String} filePath - Path of the original (unminified) file.
     *
     *  @returns {String} - Path of the minified version.
     */
    getMinPath(filePath) {
        const fPath = filePath.toLowerCase();
        if (_.endsWith(fPath, '.min.js')) return fPath;
        return Path.join(Path.dirname(fPath), `${Path.basename(fPath, '.js')}.min.js`);
    },
    /**
     *  Reads the given JS file into memory.
     *
     *  @param {String} filePath
     *         Path of the JS file.
     *  @param {Boolean} [noMinify=false]
     *         Whether not to minify the JS content.
     *  @param {Boolean} [checkMinFile=false]
     *         Whether to first check for an existing minified file (with a
     *         `min.js` suffix).
     *
     *  @returns {Promise} - Promise that returns JS code content.
     */
    readFile(filePath, noMinify = false, checkMinFile = false) {
        if (noMinify) return fs.readFile(filePath, 'utf8');
        return Promise.resolve()
            .then(() => {
                if (!checkMinFile) return js.minifyFile(filePath); // minified.code
                const minFilePath = js.getMinPath(filePath);
                return fs.pathExists(minFilePath).then(exists => {
                    if (exists) return fs.readFile(minFilePath, 'utf8');
                    return js.minifyFile(filePath);
                });
            })
            .then(minified => minified.code || minified);
    }
};

// ---------------------------
// Markdown
// ---------------------------

const md = {
    /**
     *  Parses the given markdown content.
     *
     *  @param {String} string - Markdown content.
     *  @param {Object} [options] - Markdown options for `marked`.
     *
     *  @returns {Promise} - Promise that returns the markdown, parsed to HTML.
     */
    parse(string, options = {}) {
        return new Promise((resolve, reject) => {
            marked(string, options, (err, content) => {
                if (err) return reject(err);
                resolve(content);
            });
        });
    }
};

// ---------------------------
// glob
// ---------------------------

const glob = {
    // glob uses forward slash only. (in Windows too)
    // base is optional.
    normalize(base, globPath) {
        const gpSet = utils.isset(globPath);
        if (!gpSet) {
            globPath = base;
            base = '';
        } else {
            base += '/';
        }
        return Path.normalize(base + globPath).replace(/\\+/g, '/');
    },

    isNegated(pattern) {
        return pattern.slice(0, 1) === '!';
    },

    inspect(pattern, options = {}) {
        const negated = glob.isNegated(pattern);
        pattern = negated ? pattern.slice(1) : pattern;
        pattern = glob.normalize(pattern);
        return {
            hasMagic: GLOB.hasMagic(pattern, options),
            negated,
            pattern
        };
    },

    /**
     *  Expands the given glob pattern(s) into file-paths array.
     *  This uses the node-glob library but unlike it, this also accepts an
     *  Array input and negated globs are allowed.
     *  @param {String|Array} patterns - One or more patterns to be expanded.
     *  @param {Object} [options] - Glob options.
     *  @returns {Array} - Expanded list of file paths.
     */
    match(patterns, options = {}) {
        patterns = utils.ensureArray(patterns);

        // normalize ignored globs (glob paths sep should be `/` even in
        // windows.)
        options.ignore = (options.ignore || []).map(item => {
            return glob.normalize(item);
        });

        let files = [];
        const properPatterns = [];

        // We'll pick negated patterns into the ignore list and proper patterns
        // into a separate array. Also, we'll add non-glob patters (normal file
        // paths) to the final output array; bec. glob() will not process
        // non-glob patterns.
        _.each(patterns, p => {
            const g = glob.inspect(p);
            if (g.negated) {
                options.ignore.push(g.pattern);
            } else if (!g.hasMagic) {
                files.push(g.pattern);
            } else {
                properPatterns.push(g.pattern);
            }
        });

        return Promise.each(properPatterns, p => {
            return GLOB(p, options) // eslint-disable-line
                .then(expandedFiles => {
                    files = files.concat(expandedFiles);
                });
        }).then(() => files);
        // .thenReturn(files); // wrong! returns the result of Promise.each
    }
};

// ---------------------------
// less
// ---------------------------

// http://lesscss.org/usage/#programmatic-usage
// http://onedayitwillmake.com/blog/2013/03/compiling-less-from-a-node-js-script/
// http://lesscss.org/#using-less-command-line-usage

const defaultLessOpts = {
    // root .less file name (not the path).
    // filename: 'styles.less',
    // optimization level, higher is better but more volatile - 1 is a
    // good value.
    optimization: 1,
    // minify output css
    compress: true,
    // use YUI compressor?
    yuicompress: true,
    // additional paths to look for imported less files.
    paths: [],
    // less plugins
    plugins: []
};

const less = {
    compile(strLess, options) {
        options = _.defaults(options, defaultLessOpts);
        // also pass lessCleanCssPlugin if compress enabled.
        if (options.compress) options.plugins.push(lessCleanCssPlugin);
        // http://lesscss.org/usage/#programmatic-usage
        return Less.render(strLess, options);
        // returns { css, map, imports }
    },
    // filePath: root .less file path.
    compileFile(filePath, options) {
        options = options || {};
        return fs.readFile(filePath, 'utf8')
            .then(strLess => {
                const parentDir = Path.resolve(Path.dirname(filePath));
                // http://lesscss.org/usage/#programmatic-usage
                options.filename = Path.basename(filePath);
                options.paths = (options.paths || []).concat([parentDir]);
                return less.compile(strLess, options);
            });
        // returns { css, map, imports }
    }
};

utils = {
    isset(value) {
        return value !== undefined && value !== null;
    },
    // e.g.
    // let symbol = { code: { meta: { type: "MethodDefinition" } } };
    // notate(symbol, "code.meta.type") => "MethodDefinition"
    // See https://github.com/onury/notation for an advanced library.
    notate(obj, notation) {
        if (typeof obj !== 'object') return;
        // console.log('n', notation);
        const props = !Array.isArray(notation)
            ? notation.split('.')
            : notation;
        const prop = props[0];
        if (!prop) return;
        const o = obj[prop];
        if (props.length > 1) {
            props.shift();
            return utils.notate(o, props);
        }
        return o;
    },
    ensureArray(o) {
        if (o === undefined || o === null) return o;
        return Array.isArray(o) ? o : [o];
    },
    round(num, decimals = 0) {
        if (!decimals) return Math.round(num);
        const factor = decimals * 10;
        return Math.round(num * factor) / factor;
    },
    // in KB
    getContentSize(str, gzipped = false) {
        const bytes = gzipped
            ? gzipSize.sync(str)
            : Buffer.byteLength(str, 'utf8');
        return utils.round(bytes / 1024, 1);
    },
    path,
    file,
    js,
    json,
    md,
    glob,
    less
};

module.exports = utils;
<|endoftext|>


<commit_before>/*
	Name: autoComplete
	Author: Raymond Camden & Andy Matthews
	Contributors: Jim Pease (@jmpease)
	Website: http://raymondcamden.com/
			http://andyMatthews.net
	Packed With: http://jsutility.pjoneil.net/
	Version: 1.4.2
*/
(function($) {

	"use strict";

	var defaults = {
		method: 'GET',
		icon: 'arrow-r',
		cancelRequests: false,
		target: $(),
		source: null,
		callback: null,
		link: null,
		minLength: 0,
		transition: 'fade',
		matchFromStart: true,
        termParam : 'term',
        loadingHtml : '
Searching...
'
	},
	openXHR = {},
	buildItems = function($this, data, settings) {
		var str = [];
		if (data) {
			$.each(data, function(index, value) {
				// are we working with objects or strings?
				if ($.isPlainObject(value)) {
					str.push('
' + value.label + '
');
				} else {
					str.push('
' + value + '
');
				}
			});
		}
		$(settings.target).html(str.join('')).listview("refresh");

		// is there a callback?
		if (settings.callback !== null && $.isFunction(settings.callback)) {
			attachCallback(settings);
		}

		if (str.length > 0) {
			$this.trigger("targetUpdated.autocomplete");
		} else {
			$this.trigger("targetCleared.autocomplete");
		}
	},
	attachCallback = function(settings) {
		$('li a', $(settings.target)).bind('click.autocomplete',function(e){
			e.stopPropagation();
			e.preventDefault();
			settings.callback(e);
		});
	},
	clearTarget = function($this, $target) {
		$target.html('').listview('refresh').closest("fieldset").removeClass("ui-search-active");
		$this.trigger("targetCleared.autocomplete");
	},
	handleInput = function(e) {
		var $this = $(this),
			id = $this.attr("id"),
			text,
			data,
			settings = $this.jqmData("autocomplete"),
			element_text,
			re;
		if (settings) {
			// get the current text of the input field
			text = $this.val();
			// if we don't have enough text zero out the target
			if (text.length < settings.minLength) {
				clearTarget($this, $(settings.target));
			} else {
				// are we looking at a source array or remote data?
				if ($.isArray(settings.source)) {
					data = settings.source.sort().filter(function(element) {
						// matching from start, or anywhere in the string?
						if (settings.matchFromStart) {
							// from start
							element_text, re = new RegExp('^' + text, 'i');
						} else {
							// anywhere
							element_text, re = new RegExp(text, 'i');
						}
						if ($.isPlainObject(element)) {
							element_text = element.label;
						} else {
							element_text = element;
						}
						return re.test(element_text);
					});
					buildItems($this, data, settings);
				}
				// Accept a function as source.
				// Function needs to call the callback, which is the first parameter.
				// source:function(text,callback) { mydata = [1,2]; callback(mydata); }
				else if (typeof settings.source === 'function') {

					settings.source(text,function(data){
						buildItems($this, data, settings);
					});

				} else {
                    var ajax = {
						type: settings.method,
                        data: {},
                        dataType: 'json',
						beforeSend: function(jqXHR) {
							if (settings.cancelRequests) {
								if (openXHR[id]) {
									// If we have an open XML HTTP Request for this autoComplete ID, abort it
									openXHR[id].abort();
								} else {
								}
								// Set this request to the open XML HTTP Request list for this ID
								openXHR[id] = jqXHR;
							}
                            if (settings.loadingHtml) {
                                // Set a loading indicator as a temporary stop-gap to the response time issue
                                settings.target.html(settings.loadingHtml).listview('refresh');
                                settings.target.closest("fieldset").addClass("ui-search-active");
                            }
						},
						success: function(data) {
							buildItems($this, data, settings);
						},
						complete: function (jqXHR, textStatus) {
							// Clear this ID's open XML HTTP Request from the list
							if (settings.cancelRequests) {
								openXHR[id] = null;
							}
						}
                    };
                    if ($.isPlainObject(settings.source)) {
                        if (settings.source.callback) {
                            settings.source.callback(text, ajax);
                        }
                        for (var k in settings.source) {
                            if (k != 'callback') ajax[k] = settings.source[k];
                        }
                    } else {
                        ajax.url = settings.source;
                    }
					if (settings.termParam) ajax.data[settings.termParam] = text;
					$.ajax(ajax);
				}
			}
		}
	},
	methods = {
		init: function(options) {
			var el = this;
			el.jqmData("autocomplete", $.extend({}, defaults, options));
			var settings = el.jqmData("autocomplete");
			return el.unbind("keyup.autocomplete")
						.bind("keyup.autocomplete", handleInput)
						.next('.ui-input-clear')
						.bind('click', function(e){
							clearTarget(el, $(settings.target));
						});
		},
		// Allow dynamic update of source and link
		update: function(options) {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				this.jqmData("autocomplete", $.extend(settings, options));
			}
			return this;
		},
		// Method to forcibly clear our target
		clear: function() {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				clearTarget(this, $(settings.target));
			}
			return this;
		},
		// Method to destroy (cleanup) plugin
		destroy: function() {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				clearTarget(this, $(settings.target));
				this.jqmRemoveData("autocomplete");
				this.unbind(".autocomplete");
			}
			return this;
		}
	};

	$.fn.autocomplete = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		}
	};

})(jQuery);
<commit_msg>Query only if text is different<commit_after>/*
	Name: autoComplete
	Author: Raymond Camden & Andy Matthews
	Contributors: Jim Pease (@jmpease)
	Website: http://raymondcamden.com/
			http://andyMatthews.net
	Packed With: http://jsutility.pjoneil.net/
	Version: 1.4.2
*/
(function($) {

	"use strict";

	var defaults = {
		method: 'GET',
		icon: 'arrow-r',
		cancelRequests: false,
		target: $(),
		source: null,
		callback: null,
		link: null,
		minLength: 0,
		transition: 'fade',
		matchFromStart: true,
        termParam : 'term',
        loadingHtml : '
Searching...
'
	},
	openXHR = {},
	buildItems = function($this, data, settings) {
		var str = [];
		if (data) {
			$.each(data, function(index, value) {
				// are we working with objects or strings?
				if ($.isPlainObject(value)) {
					str.push('
' + value.label + '
');
				} else {
					str.push('
' + value + '
');
				}
			});
		}
		$(settings.target).html(str.join('')).listview("refresh");

		// is there a callback?
		if (settings.callback !== null && $.isFunction(settings.callback)) {
			attachCallback(settings);
		}

		if (str.length > 0) {
			$this.trigger("targetUpdated.autocomplete");
		} else {
			$this.trigger("targetCleared.autocomplete");
		}
	},
	attachCallback = function(settings) {
		$('li a', $(settings.target)).bind('click.autocomplete',function(e){
			e.stopPropagation();
			e.preventDefault();
			settings.callback(e);
		});
	},
	clearTarget = function($this, $target) {
		$target.html('').listview('refresh').closest("fieldset").removeClass("ui-search-active");
		$this.trigger("targetCleared.autocomplete");
	},
	handleInput = function(e) {
		var $this = $(this),
			id = $this.attr("id"),
			text,
			data,
			settings = $this.jqmData("autocomplete"),
			element_text,
			re;
		if (settings) {
			// get the current text of the input field
			text = $this.val();
            // check if it's the same as the last one
            if (settings._lastText === text) return;
            settings._lastText = text;
			// if we don't have enough text zero out the target
			if (text.length < settings.minLength) {
				clearTarget($this, $(settings.target));
			} else {
				// are we looking at a source array or remote data?
				if ($.isArray(settings.source)) {
					data = settings.source.sort().filter(function(element) {
						// matching from start, or anywhere in the string?
						if (settings.matchFromStart) {
							// from start
							element_text, re = new RegExp('^' + text, 'i');
						} else {
							// anywhere
							element_text, re = new RegExp(text, 'i');
						}
						if ($.isPlainObject(element)) {
							element_text = element.label;
						} else {
							element_text = element;
						}
						return re.test(element_text);
					});
					buildItems($this, data, settings);
				}
				// Accept a function as source.
				// Function needs to call the callback, which is the first parameter.
				// source:function(text,callback) { mydata = [1,2]; callback(mydata); }
				else if (typeof settings.source === 'function') {

					settings.source(text,function(data){
						buildItems($this, data, settings);
					});

				} else {
                    var ajax = {
						type: settings.method,
                        data: {},
                        dataType: 'json',
						beforeSend: function(jqXHR) {
							if (settings.cancelRequests) {
								if (openXHR[id]) {
									// If we have an open XML HTTP Request for this autoComplete ID, abort it
									openXHR[id].abort();
								} else {
								}
								// Set this request to the open XML HTTP Request list for this ID
								openXHR[id] = jqXHR;
							}
                            if (settings.loadingHtml) {
                                // Set a loading indicator as a temporary stop-gap to the response time issue
                                settings.target.html(settings.loadingHtml).listview('refresh');
                                settings.target.closest("fieldset").addClass("ui-search-active");
                            }
						},
						success: function(data) {
							buildItems($this, data, settings);
						},
						complete: function (jqXHR, textStatus) {
							// Clear this ID's open XML HTTP Request from the list
							if (settings.cancelRequests) {
								openXHR[id] = null;
							}
						}
                    };
                    if ($.isPlainObject(settings.source)) {
                        if (settings.source.callback) {
                            settings.source.callback(text, ajax);
                        }
                        for (var k in settings.source) {
                            if (k != 'callback') ajax[k] = settings.source[k];
                        }
                    } else {
                        ajax.url = settings.source;
                    }
					if (settings.termParam) ajax.data[settings.termParam] = text;
					$.ajax(ajax);
				}
			}
		}
	},
	methods = {
		init: function(options) {
			var el = this;
			el.jqmData("autocomplete", $.extend({}, defaults, options));
			var settings = el.jqmData("autocomplete");
			return el.unbind("keyup.autocomplete")
						.bind("keyup.autocomplete", handleInput)
						.next('.ui-input-clear')
						.bind('click', function(e){
							clearTarget(el, $(settings.target));
						});
		},
		// Allow dynamic update of source and link
		update: function(options) {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				this.jqmData("autocomplete", $.extend(settings, options));
			}
			return this;
		},
		// Method to forcibly clear our target
		clear: function() {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				clearTarget(this, $(settings.target));
			}
			return this;
		},
		// Method to destroy (cleanup) plugin
		destroy: function() {
			var settings = this.jqmData("autocomplete");
			if (settings) {
				clearTarget(this, $(settings.target));
				this.jqmRemoveData("autocomplete");
				this.unbind(".autocomplete");
			}
			return this;
		}
	};

	$.fn.autocomplete = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		}
	};

})(jQuery);
<|endoftext|>


<commit_before>Package.describe({
  name: "vulcan:i18n-fr-fr",
  summary: "Vulcan i18n package (fr_FR)",
  version: '1.8.9',
  git: "https://github.com/VulcanJS/Vulcan.git"
});

Package.onUse(function (api) {

  api.versionsFrom('1.6.1');

  api.use([
    'vulcan:core@1.8.9'
  ]);

  api.addFiles([
    'lib/fr_FR.js'
  ], ["client", "server"]);
});
<commit_msg>update to 1.8.11<commit_after>Package.describe({
  name: "vulcan:i18n-fr-fr",
  summary: "Vulcan i18n package (fr_FR)",
  version: '1.8.11',
  git: "https://github.com/VulcanJS/Vulcan.git"
});

Package.onUse(function (api) {

  api.versionsFrom('1.6.1');

  api.use([
    'vulcan:core@1.8.11'
  ]);

  api.addFiles([
    'lib/fr_FR.js'
  ], ["client", "server"]);
});
<|endoftext|>


<commit_before>
// function to get values from an object.
// e.g. getKey({a: {b: {c: 5}}}, 'a.b.c') == 5
var nestedGet = function (obj, key) {
  key = key.split('.');
  return key.reduce(function (obj, key) {
    return obj[key];
  }, obj);
};

module.exports = {
  nestedGet: nestedGet
};<commit_msg>change nestedGet notation<commit_after>
// function to get values from an object.
// e.g. getKey({a: {b: {c: 5}}}, 'a.b.c') == 5
function nestedGet (obj, key) {
  key = key.split('.');
  return key.reduce(function (obj, key) {
    return obj[key];
  }, obj);
};

module.exports = {
  nestedGet: nestedGet
};<|endoftext|>


<commit_before>(function( $ ) {

  $.fn.aeImageResize = function( params ) {

    var aspectRatio = 0
      // Nasty I know but it's done only once, so not too bad I guess
      // Alternate suggestions welcome :)
      ,	isIE6 = $.browser.msie && (6 == ~~ $.browser.version)
      , txtHeight = "height"
      , txtWidth = "width"
      ;

    // We cannot do much unless we have one of these
    if ( !params[txtHeight] && !params[txtWidth] ) {
      return this;
    }

    // Calculate aspect ratio now, if possible
    if ( params[txtHeight] && params[txtWidth] ) {
      aspectRatio = params[txtWidth] / params[txtHeight];
    }

    // Attach handler to load
    // Handler is executed just once per element
    // Load event required for Webkit browsers
    return this.one( "load", function() {

      // Remove all attributes and CSS rules
      this
        .removeAttr( "height" )
        .removeAttr( "width" )
        .css({
          height: "",
          width: ""
        });

      var imgHeight = this[txtHeight]
        ,	imgWidth = this[txtWidth]
        ,	imgAspectRatio = imgWidth / imgHeight
        ,	bxHeight = params[txtHeight]
        ,	bxWidth = params[txtWidth]
        ,	bxAspectRatio = aspectRatio;

      // Work the magic!
      // If one parameter is missing, we just force calculate it
      if ( !bxAspectRatio ) {
        if ( bxHeight === 0 ) {
          bxAspectRatio = imgAspectRatio - 1;
        } else {
          bxAspectRatio = imgAspectRatio + 1;
        }
      }

      // Only resize the images that need resizing
      if ( (bxHeight && imgHeight > bxHeight) || (bxWidth && imgWidth > bxWidth) ) {

        if ( imgAspectRatio > aspectRatio ) {
          bxHeight = ~~ ( imgHeight / imgWidth * bxWidth );
        } else {
          bxWidth = ~~ ( imgWidth / imgHeight * bxHeight );
        }

        $( this ).attr({
          "height": bxHeight,
          "width": bxWidth
        });
      }
    })
    .each(function() {

      // Trigger load event (for Gecko and MSIE)
      if ( this.complete || isIE6 ) {
        this.trigger( "load" );
      }
    });
  };
})( jQuery );<commit_msg>This should run faster in IE<commit_after>(function( $ ) {

  $.fn.aeImageResize = function( params ) {

    var aspectRatio = 0
      // Nasty I know but it's done only once, so not too bad I guess
      // Alternate suggestions welcome :)
      ,	isIE6 = $.browser.msie && (6 == ~~ $.browser.version)
      , txtHeight = "height"
      , txtWidth = "width"
      ;

    // We cannot do much unless we have one of these
    if ( !params[txtHeight] && !params[txtWidth] ) {
      return this;
    }

    // Calculate aspect ratio now, if possible
    if ( params[txtHeight] && params[txtWidth] ) {
      aspectRatio = params[txtWidth] / params[txtHeight];
    }

    // Attach handler to load
    // Handler is executed just once per element
    // Load event required for Webkit browsers
    return this.one( "load", function() {

      // Remove all attributes and CSS rules
      this
        .removeAttr( "height" )
        .removeAttr( "width" )
        .css({
          height: "",
          width: ""
        });

      var imgHeight = this[txtHeight]
        ,	imgWidth = this[txtWidth]
        ,	imgAspectRatio = imgWidth / imgHeight
        ,	bxHeight = params[txtHeight]
        ,	bxWidth = params[txtWidth]
        ,	bxAspectRatio = aspectRatio;

      // Work the magic!
      // If one parameter is missing, we just force calculate it
      if ( !bxAspectRatio ) {
        if ( bxHeight === 0 ) {
          bxAspectRatio = imgAspectRatio - 1;
        } else {
          bxAspectRatio = imgAspectRatio + 1;
        }
      }

      // Only resize the images that need resizing
      if ( (bxHeight && imgHeight > bxHeight) || (bxWidth && imgWidth > bxWidth) ) {

        if ( imgAspectRatio > aspectRatio ) {
          bxHeight = ~~ ( imgHeight / imgWidth * bxWidth );
        } else {
          bxWidth = ~~ ( imgWidth / imgHeight * bxHeight );
        }

        this[txtHeight] = bxHeight;
        this[txtWidth] = bxWidth;
      }
    })
    .each(function() {

      // Trigger load event (for Gecko and MSIE)
      if ( this.complete || isIE6 ) {
        this.trigger( "load" );
      }
    });
  };
})( jQuery );<|endoftext|>


<commit_before>module.exports = {
  arraysAreEqual : function(a, b) {
    for(var i = 0; i < a.length; i++){
      if(a[i] !== b[i]) {
        return false;
      }
    }
    return true;
  },

  connectWithDots : function(a, b) {
    var totalLength = 40;
    var dotLength = totalLength - a.length - b.length;
    var dots = "";
    for(var i = 0; i < dotLength; i++) {
      dots = dots.concat('.');
    }
    return (a + dots + b);
  }
};
<commit_msg>Shorten up total characters for leaderboard to 35 from 40<commit_after>module.exports = {
  arraysAreEqual : function(a, b) {
    for(var i = 0; i < a.length; i++){
      if(a[i] !== b[i]) {
        return false;
      }
    }
    return true;
  },

  connectWithDots : function(a, b) {
    var totalLength = 35;
    var dotLength = totalLength - a.length - b.length;
    var dots = "";
    for(var i = 0; i < dotLength; i++) {
      dots = dots.concat('.');
    }
    return (a + dots + b);
  }
};
<|endoftext|>


<commit_before>/* globals angular */
function blah() {
    console.log("BLAH!");
}

var ConsoleWyrmHole = function() {
    var msgIdCnt = 0;
    var dfds = {};

    this.sendMessage = function(msg, data) {
        var msgObj = {
            message: msg,
            messageId: ++msgIdCnt,
            data: data
        };
        console.log('sendMessage: ', msgObj);
        var dfd = new $.Deferred();
        dfds[msgIdCnt] = dfd;
        return dfd.promise();
    };
};

var objectIdWeakMap = new WeakMap();
var objectIdMap = {};

function serializeValue(value) {
    if (typeof value !== 'object') { return value; } // Only objects get translated
    if(!objectIdWeakMap.has(value)) {
        var id = Number(('' + Math.random()).slice(2));
        objectIdMap[id] = value;
        objectIdWeakMap.set(value, id);
    }
    return objectIdWeakMap.get(value);
}
function deserializeValue(value) {
    if (typeof value !== 'object') { return value; } // Only objects get translated
    return objectIdMap[value.objectId] || value;
}

var WyrmJSAPI = function(objectId, fnList, pList, name, wyrmHole) {
    var self = this;

    self.objectId = objectId || 0;
    self.fnList = fnList || [];
    self.pList = pList || [];
    self.name = name || '';

    self.toString = function() {
        return "[WyrmJSAPI Object: " + this.name + "]";
    };

    self.fnList.forEach(function(fnName) {
        self[fnName] = function() {
            var args = Array.prototype.map.call(arguments, function(arg) { return serializeValue(arg); });
            return wyrmHole.sendMessage('CallFn', {
                objectId: self.objectId,
                fnName: fnName,
                args: arguments
            });
        };
    });

    self.pList.forEach(function(pName) {
        self.__defineGetter__(pName, function() {
            return wyrmHole.sendMessage('GetP', {
                objectId: self.objectId,
                pName: pName
            });
        });
        self.__defineSetter__(pName, function(val) {
            return wyrmHole.sendMessage('SetP', {
                objectId: self.objectId,
                pName: pName,
                value: val
            });
        });
    });

};

function getRootObject(wyrmHole) {
    var rootAPI = new WyrmJSAPI(0, ['getRootObject'],[], 'rootAPI', wyrmHole);
    return rootAPI.getRootObject();
}

if (module) {
    module.exports = {
        blah: blah,
        WyrmJSAPI: WyrmJSAPI,
        ConsoleWyrmHole: ConsoleWyrmHole
    };
}
<commit_msg>Use fbpromise.<commit_after>/* globals angular */

var Deferred = require('./fbpromise');

var ConsoleWyrmHole = function() {
    var msgIdCnt = 0;
    var dfds = {};

    this.sendMessage = function(msg, data) {
        var msgObj = {
            message: msg,
            messageId: ++msgIdCnt,
            data: data
        };
        console.log('sendMessage: ', msgObj);
        var dfd = new Deferred();
        dfds[msgIdCnt] = dfd;
        return dfd.promise;
    };
};

var objectIdWeakMap = new WeakMap();
var objectIdMap = {};

function serializeValue(value) {
    if (typeof value !== 'object') { return value; } // Only objects get translated
    if(!objectIdWeakMap.has(value)) {
        var id = Number(('' + Math.random()).slice(2));
        objectIdMap[id] = value;
        objectIdWeakMap.set(value, id);
    }
    return objectIdWeakMap.get(value);
}
function deserializeValue(value) {
    if (typeof value !== 'object') { return value; } // Only objects get translated
    return objectIdMap[value.objectId] || value;
}

var WyrmJSAPI = function(objectId, fnList, pList, name, wyrmHole) {
    var self = this;

    self.objectId = objectId || 0;
    self.fnList = fnList || [];
    self.pList = pList || [];
    self.name = name || '';

    self.toString = function() {
        return "[WyrmJSAPI Object: " + this.name + "]";
    };

    self.fnList.forEach(function(fnName) {
        self[fnName] = function() {
            var args = Array.prototype.map.call(arguments, function(arg) { return serializeValue(arg); });
            return wyrmHole.sendMessage('CallFn', {
                objectId: self.objectId,
                fnName: fnName,
                args: arguments
            });
        };
    });

    self.pList.forEach(function(pName) {
        self.__defineGetter__(pName, function() {
            return wyrmHole.sendMessage('GetP', {
                objectId: self.objectId,
                pName: pName
            });
        });
        self.__defineSetter__(pName, function(val) {
            return wyrmHole.sendMessage('SetP', {
                objectId: self.objectId,
                pName: pName,
                value: val
            });
        });
    });

};

function getRootObject(wyrmHole) {
    var rootAPI = new WyrmJSAPI(0, ['getRootObject'],[], 'rootAPI', wyrmHole);
    return rootAPI.getRootObject();
}

if (module) {
    module.exports = {
        WyrmJSAPI: WyrmJSAPI,
        ConsoleWyrmHole: ConsoleWyrmHole
    };
}
<|endoftext|>


<commit_before>/**
 * @author zhixin wen <wenzhixin2010@gmail.com>
 * @version 0.0.1
 * @blog http://wenzhixin.net.cn
 */

(function($) {

	'use strict';

	function MultipleSelect($el, options) {
		var that = this;
		this.$el = $el.hide();
		this.options = options;

		this.$parent = $('

');
		this.$choice = $('

');
		this.$drop = $('

');
		this.$el.after(this.$parent);
		this.$parent.append(this.$choice);
		this.$parent.append(this.$drop);

		if (this.$el.prop('disabled')) {
			this.$choice.addClass('disabled');
		}
		this.$choice.css('width', $el.width() + 'px')
			.find('span').css('width', ($el.width() - 20) + 'px');
		this.$drop.css({
			width: $el.width() + 'px'
		});

		$('body').click(function(e) {
			if ($(e.target)[0] === that.$choice[0] ||
					$(e.target).parents('.ms-choice')[0] === that.$choice[0]) {
				return;
			}
			if ($(e.target)[0] === that.$drop[0] ||
					$(e.target).parents('.ms-drop')[0] !== that.$drop[0]) {
				that.close();
			}
		});

		if (this.options.isopen) {
			this.open();
		}
	}

	MultipleSelect.prototype = {
		constructor : MultipleSelect,

		init: function() {
			var html = ['
'],
				multiple = this.options.multiple;
			if (this.options.selectAll) {
				html.push(
					'
',
						'',
						'<input type="checkbox" name="selectAll" /> ',
						'[' + this.options.selectAllText + ']',
						'',
					'
'
				);
			}
			this.$el.find('option').each(function() {
				var value = $(this).val(),
					text = $(this).text();
				html.push(
					'
',
						'',
						'<input type="checkbox" name="selectItem" value="' + value + '" /> ',
						text,
						'',
					'
'
				);
			});
			html.push('
');
			this.$drop.html(html.join(''));
			this.$drop.find('.multiple').css('width', this.options.multipleWidth + 'px');
			this.events();
		},

		events: function() {
			var that = this;
			this.$choice.on('click', function() {
				that[that.options.isopen ? 'close' : 'open']();
			});
			this.$drop.find('input[name="selectAll"]').on('click', function() {
				that.$drop.find('input[name="selectItem"]').prop('checked', $(this).prop('checked'));
			});
			this.$drop.find('ul').on('click', 'input', function() {
				that.update();
			});
		},

		open: function() {
			if (this.$choice.hasClass('disabled')) {
				return;
			}
			this.options.isopen = true;
			this.$choice.find('>div').addClass('open');
			this.$drop.show();
		},

		close: function() {
			this.options.isopen = false;
			this.$choice.find('>div').removeClass('open');
			this.$drop.hide();
			this.update();
		},

		update: function() {
			this.$choice.find('>span').html(this.getSelects('text').join(','));
		},

		//value or text, default: 'value'
		getSelects: function(type) {
			var values = [];
			this.$drop.find('input[name="selectItem"]:checked').each(function() {
				values.push(type === 'text' ? $(this).parent().text() : $(this).val());
			});
			return values;
		},

		setSelects: function(values) {
			var that = this;
			this.$drop.find('input[name="selectItem"]').prop('checked', false);
			$.each(values, function(i, value) {
				that.$drop
					.find('input[name="selectItem"][value="' + value + '"]')
					.prop('checked', true);
			});
		},

		enable: function() {
			this.$choice.removeClass('disabled');
		},

		disable: function() {
			this.$choice.addClass('disabled');
		}
	};

	$.fn.multipleSelect = function() {
		var option = arguments[0],
			args = arguments,

			value,
			allowedMethods = ['getSelects', 'setSelects', 'enable', 'disable'];

		this.each(function() {
			var $this = $(this),
				data = $this.data('multipleSelect'),
				options = $.extend({}, $.fn.multipleSelect.defaults, typeof option === 'object' && option);

			if (!data) {
				data = new MultipleSelect($this, options);
				$this.data('multipleSelect', data);
			}

			if (typeof option === 'string') {
				if ($.inArray(option, allowedMethods) < 0) {
					throw "Unknown method: " + option;
				}
				value = data[option](args[1]);
			} else {
				data.init();
			}
		});

		return value ? value : this;
	};

	$.fn.multipleSelect.defaults = {
		isopen: false,
		selectAll: true,
		selectAllText: 'Select all',
		multiple: false,
		multipleWidth: 80
	};
})(jQuery);
<commit_msg>Sync the state of select all and select items.<commit_after>/**
 * @author zhixin wen <wenzhixin2010@gmail.com>
 * @version 0.0.1
 * @blog http://wenzhixin.net.cn
 */

(function($) {

	'use strict';

	function MultipleSelect($el, options) {
		var that = this;
		this.$el = $el.hide();
		this.options = options;

		this.$parent = $('

');
		this.$choice = $('

');
		this.$drop = $('

');
		this.$el.after(this.$parent);
		this.$parent.append(this.$choice);
		this.$parent.append(this.$drop);

		if (this.$el.prop('disabled')) {
			this.$choice.addClass('disabled');
		}
		this.$choice.css('width', $el.width() + 'px')
			.find('span').css('width', ($el.width() - 20) + 'px');
		this.$drop.css({
			width: $el.width() + 'px'
		});

		$('body').click(function(e) {
			if ($(e.target)[0] === that.$choice[0] ||
					$(e.target).parents('.ms-choice')[0] === that.$choice[0]) {
				return;
			}
			if ($(e.target)[0] === that.$drop[0] ||
					$(e.target).parents('.ms-drop')[0] !== that.$drop[0]) {
				that.close();
			}
		});

		if (this.options.isopen) {
			this.open();
		}
	}

	MultipleSelect.prototype = {
		constructor : MultipleSelect,

		init: function() {
			var html = ['
'],
				multiple = this.options.multiple;
			if (this.options.selectAll) {
				html.push(
					'
',
						'',
						'<input type="checkbox" name="selectAll" /> ',
						'[' + this.options.selectAllText + ']',
						'',
					'
'
				);
			}
			this.$el.find('option').each(function() {
				var value = $(this).val(),
					text = $(this).text();
				html.push(
					'
',
						'',
						'<input type="checkbox" name="selectItem" value="' + value + '" /> ',
						text,
						'',
					'
'
				);
			});
			html.push('
');
			this.$drop.html(html.join(''));
			this.$drop.find('.multiple').css('width', this.options.multipleWidth + 'px');

			this.$selectAll = this.$drop.find('input[name="selectAll"]');
			this.$selectItems = this.$drop.find('input[name="selectItem"]');
			this.events();
		},

		events: function() {
			var that = this;
			this.$choice.on('click', function() {
				that[that.options.isopen ? 'close' : 'open']();
			});
			this.$selectAll.on('click', function() {
				that.$selectItems.prop('checked', $(this).prop('checked'));
				that.update();
			});
			this.$selectItems.on('click', function() {
				that.$selectAll.prop('checked', that.$selectItems.length ===
					that.$selectItems.filter(':checked').length);
				that.update();
			});
		},

		open: function() {
			if (this.$choice.hasClass('disabled')) {
				return;
			}
			this.options.isopen = true;
			this.$choice.find('>div').addClass('open');
			this.$drop.show();
		},

		close: function() {
			this.options.isopen = false;
			this.$choice.find('>div').removeClass('open');
			this.$drop.hide();
		},

		update: function() {
			this.$choice.find('>span').html(this.getSelects('text').join(','));
		},

		//value or text, default: 'value'
		getSelects: function(type) {
			var values = [];
			this.$selectItems.filter(':checked').each(function() {
				values.push(type === 'text' ? $(this).parent().text() : $(this).val());
			});
			return values;
		},

		setSelects: function(values) {
			var that = this;
			this.$selectItems.prop('checked', false);
			$.each(values, function(i, value) {
				that.$selectItems.filter('[value="' + value + '"]').prop('checked', true);
			});
			this.$selectAll.prop('checked', that.$selectItems.length ===
				this.$selectItems.filter(':checked').length);
			this.update();
		},

		enable: function() {
			this.$choice.removeClass('disabled');
		},

		disable: function() {
			this.$choice.addClass('disabled');
		}
	};

	$.fn.multipleSelect = function() {
		var option = arguments[0],
			args = arguments,

			value,
			allowedMethods = ['getSelects', 'setSelects', 'enable', 'disable'];

		this.each(function() {
			var $this = $(this),
				data = $this.data('multipleSelect'),
				options = $.extend({}, $.fn.multipleSelect.defaults, typeof option === 'object' && option);

			if (!data) {
				data = new MultipleSelect($this, options);
				$this.data('multipleSelect', data);
			}

			if (typeof option === 'string') {
				if ($.inArray(option, allowedMethods) < 0) {
					throw "Unknown method: " + option;
				}
				value = data[option](args[1]);
			} else {
				data.init();
			}
		});

		return value ? value : this;
	};

	$.fn.multipleSelect.defaults = {
		isopen: false,
		selectAll: true,
		selectAllText: 'Select all',
		multiple: false,
		multipleWidth: 80
	};
})(jQuery);
<|endoftext|>


<commit_before>var controllerDir;
var appName;

function getAppName() {
    var parts = __dirname.replace(/\\/g, '/').split('/');
    return parts[parts.length - 2].split('.')[0];
}

// Get js-controller directory to load libs
function getControllerDir(isInstall) {
    var fs = require('fs');
    // Find the js-controller location
    var controllerDir = __dirname.replace(/\\/g, '/');
    controllerDir = controllerDir.split('/');
    if (controllerDir[controllerDir.length - 3] === 'adapter') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
    } else if (controllerDir[controllerDir.length - 3] === 'node_modules') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
        if (fs.existsSync(controllerDir + '/node_modules/' + appName + '.js-controller')) {
            controllerDir += '/node_modules/' + appName + '.js-controller';
        } else if (fs.existsSync(controllerDir + '/node_modules/' + appName.toLowerCase() + '.js-controller')) {
            controllerDir += '/node_modules/' + appName.toLowerCase() + '.js-controller';
        } else if (!fs.existsSync(controllerDir + '/controller.js')) {
            if (!isInstall) {
                console.log('Cannot find js-controller');
                process.exit(10);
            } else {
                process.exit();
            }
        }
    } else if (fs.existsSync(__dirname + '/../../node_modules/' + appName.toLowerCase() + '.js-controller')) {
        controllerDir.splice(controllerDir.length - 2, 2);
        return controllerDir.join('/') + '/node_modules/' + appName.toLowerCase() + '.js-controller';
    } else {
        if (!isInstall) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    return controllerDir;
}

// Read controller configuration file
function getConfig() {
    var fs = require('fs');
    if (fs.existsSync(controllerDir + '/conf/' + appName + '.json')) {
        return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName + '.json'));
    } else if (fs.existsSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json')) {
        return JSON.parse(fs.readFileSync(controllerDir + '/conf/' + appName.toLowerCase() + '.json'));
    } else {
        throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
    }
}
appName       = getAppName();
controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);

exports.controllerDir = controllerDir;
exports.getConfig =     getConfig;
exports.Adapter =       require(controllerDir + '/lib/adapter.js');
exports.appName =       appName;
<commit_msg>update utils.js<commit_after>'use strict';

const fs = require('fs');
const path = require('path');

let controllerDir;
let appName;

/**
 * returns application name
 *
 * The name of the application can be different and this function finds it out.
 *
 * @returns {string}
 */
 function getAppName() {
    const parts = __dirname.replace(/\\/g, '/').split('/');
    return parts[parts.length - 2].split('.')[0];
}

/**
 * looks for js-controller home folder
 *
 * @param {boolean} isInstall
 * @returns {string}
 */
function getControllerDir(isInstall) {
    // Find the js-controller location
    const possibilities = [
        'iobroker.js-controller',
        'ioBroker.js-controller',
    ];
    /** @type {string} */
    let controllerPath;
    for (const pkg of possibilities) {
        try {
            const possiblePath = require.resolve(pkg);
            if (fs.existsSync(possiblePath)) {
                controllerPath = possiblePath;
                break;
            }
        } catch (e) { /* not found */ }
    }
    if (controllerPath == null) {
        if (!isInstall) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    // we found the controller
    return path.dirname(controllerPath);
}

/**
 * reads controller base settings
 *
 * @alias getConfig
 * @returns {object}
 */
 function getConfig() {
    let configPath;
    if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', appName + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else if (fs.existsSync(
        configPath = path.join(controllerDir, 'conf', + appName.toLowerCase() + '.json')
    )) {
        return JSON.parse(fs.readFileSync(configPath, 'utf8'));
    } else {
        throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
    }
}
appName       = getAppName();
controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);
const adapter = require(path.join(controllerDir, 'lib/adapter.js'));

exports.controllerDir = controllerDir;
exports.getConfig =     getConfig;
exports.Adapter =       adapter;
exports.appName =       appName;
<|endoftext|>


<commit_before>/**
 * Given a DOM subtree, wraps it in a list, and puts each line into its own
 * list item.
 *
 * @param {Node} node modified in place.  Its content is pulled into an
 *     HTMLOListElement, and each line is moved into a separate list item.
 *     This requires cloning elements, so the input might not have unique
 *     IDs after numbering.
 */
function numberLines(node, opt_startLineNum) {
  var nocode = /(?:^|\s)nocode(?:\s|$)/;
  var lineBreak = /\r\n?|\n/;

  var document = node.ownerDocument;

  var whitespace;
  if (node.currentStyle) {
    whitespace = node.currentStyle.whiteSpace;
  } else if (window.getComputedStyle) {
    whitespace = document.defaultView.getComputedStyle(node, null)
        .getPropertyValue('white-space');
  }
  // If it's preformatted, then we need to split lines on line breaks
  // in addition to
s.
  var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);

  var li = document.createElement('LI');
  while (node.firstChild) {
    li.appendChild(node.firstChild);
  }
  // An array of lines.  We split below, so this is initialized to one
  // un-split line.
  var listItems = [li];

  function walk(node) {
    switch (node.nodeType) {
      case 1:  // Element
        if (nocode.test(node.className)) { break; }
        if ('BR' === node.nodeName) {
          breakAfter(node);
          // Discard the
 since it is now flush against a
.
          if (node.parentNode) {
            node.parentNode.removeChild(node);
          }
        } else {
          for (var child = node.firstChild; child; child = child.nextSibling) {
            walk(child);
          }
        }
        break;
      case 3: case 4:  // Text
console.log('saw text node, isPreformatted=' + isPreformatted);
        if (isPreformatted) {
          var text = node.nodeValue;
          var match = text.match(lineBreak);
          if (match) {
            var firstLine = text.substring(0, match.index);
            node.nodeValue = firstLine;
            var tail = text.substring(match.index + match[0].length);
console.log('split "' + text.replace(/\r\n?|\n/g, '\\n') + '" into "' + firstLine + '" and "' + tail.replace(/\r\n?|\n/g, '\\n') + '"');
            if (tail) {
              var parent = node.parentNode;
              parent.insertBefore(
                  document.createTextNode(tail), node.nextSibling);
            }
            breakAfter(node);
            if (!firstLine) {
              // Don't leave blank text nodes in the DOM.
              node.parentNode.removeChild(node);
            }
          }
        }
        break;
    }
  }

  // Split a line after the given node.
  function breakAfter(lineEndNode) {
    // If there's nothing to the right, then we can skip ending the line
    // here, and move root-wards since splitting just before an end-tag
    // would require us to create a bunch of empty copies.
    while (!lineEndNode.nextSibling) {
      lineEndNode = lineEndNode.parentNode;
      if (!lineEndNode) { return; }
    }

    function breakLeftOf(limit, copy) {
      // Clone shallowly if this node needs to be on both sides of the break.
      var rightSide = copy ? limit.cloneNode(false) : limit;
      var parent = limit.parentNode;
      if (parent) {
        // We clone the parent chain.
        // This helps us resurrect important styling elements that cross lines.
        // E.g. in Foo
Bar
        // should be rewritten to
Foo

Bar
.
        var parentClone = breakLeftOf(parent, 1);
        // Move the clone and everything to the right of the original
        // onto the cloned parent.
        var next = limit.nextSibling;
        parentClone.appendChild(rightSide);
        for (var sibling = next; sibling; sibling = next) {
          next = sibling.nextSibling;
          parentClone.appendChild(sibling);
        }
      }
      return rightSide;
    }

    var split = breakLeftOf(lineEndNode.nextSibling, 0);

    // Walk the parent chain until we reach an unattached LI.
    for (var parent; (parent = split.parentNode);) { split = parent; }
    // Put it on the list of lines for later processing.
    listItems.push(split);
console.log('pushing listItem length=' + listItems.length);
  }

  // Split lines while there are lines left to split.
  for (var i = 0;  // Number of lines that have been split so far.
       i < listItems.length;  // length updated by breakAfter calls.
       ++i) {
console.log('walking list item ' + i);
    walk(listItems[i]);
  }

  // Make sure numeric indices show correctly.
  if (opt_startLineNum === (opt_startLineNum|0)) {
    listItems[0].setAttribute('value', opt_startLineNum);
  }

  var ol = document.createElement('OL');
  ol.className = 'linenums';
  var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
  for (var i = 0, n = listItems.length; i < n; ++i) {
    li = listItems[i];
    // Stick a class on the LIs so that stylesheets can
    // color odd/even rows, or any other row pattern that
    // is co-prime with 10.
    li.className = 'L' + ((i + offset) % 10);
    if (!li.firstChild) {
      li.appendChild(document.createTextNode('\xA0'));
    }
    ol.appendChild(li);
  }

  node.appendChild(ol);
}<commit_msg>logging for IE<commit_after>/**
 * Given a DOM subtree, wraps it in a list, and puts each line into its own
 * list item.
 *
 * @param {Node} node modified in place.  Its content is pulled into an
 *     HTMLOListElement, and each line is moved into a separate list item.
 *     This requires cloning elements, so the input might not have unique
 *     IDs after numbering.
 */
function numberLines(node, opt_startLineNum) {
  var nocode = /(?:^|\s)nocode(?:\s|$)/;
  var lineBreak = /\r\n?|\n/;

  var document = node.ownerDocument;

  var whitespace;
  if (node.currentStyle) {
    whitespace = node.currentStyle.whiteSpace;
  } else if (window.getComputedStyle) {
    whitespace = document.defaultView.getComputedStyle(node, null)
        .getPropertyValue('white-space');
  }
  // If it's preformatted, then we need to split lines on line breaks
  // in addition to
s.
  var isPreformatted = whitespace && 'pre' === whitespace.substring(0, 3);

  var li = document.createElement('LI');
  while (node.firstChild) {
    li.appendChild(node.firstChild);
  }
  // An array of lines.  We split below, so this is initialized to one
  // un-split line.
  var listItems = [li];

  function walk(node) {
    switch (node.nodeType) {
      case 1:  // Element
        if (nocode.test(node.className)) { console.log('nocode'); break; }
console.log('  el=' + node.nodeName);
        if ('BR' === node.nodeName) {
          breakAfter(node);
          // Discard the
 since it is now flush against a
.
          if (node.parentNode) {
            node.parentNode.removeChild(node);
          }
        } else {
          for (var child = node.firstChild; child; child = child.nextSibling) {
            walk(child);
          }
        }
        break;
      case 3: case 4:  // Text
        if (isPreformatted) {
          var text = node.nodeValue;
          var match = text.match(lineBreak);
          if (match) {
            var firstLine = text.substring(0, match.index);
            node.nodeValue = firstLine;
            var tail = text.substring(match.index + match[0].length);
console.log('split "' + text.replace(/\r\n?|\n/g, '\\n') + '" into "' + firstLine + '" and "' + tail.replace(/\r\n?|\n/g, '\\n') + '"');
            if (tail) {
              var parent = node.parentNode;
              parent.insertBefore(
                  document.createTextNode(tail), node.nextSibling);
            }
            breakAfter(node);
            if (!firstLine) {
              // Don't leave blank text nodes in the DOM.
              node.parentNode.removeChild(node);
            }
          }
        }
        break;
    }
  }

  // Split a line after the given node.
  function breakAfter(lineEndNode) {
    // If there's nothing to the right, then we can skip ending the line
    // here, and move root-wards since splitting just before an end-tag
    // would require us to create a bunch of empty copies.
    while (!lineEndNode.nextSibling) {
      lineEndNode = lineEndNode.parentNode;
      if (!lineEndNode) { return; }
    }

    function breakLeftOf(limit, copy) {
      // Clone shallowly if this node needs to be on both sides of the break.
      var rightSide = copy ? limit.cloneNode(false) : limit;
      var parent = limit.parentNode;
      if (parent) {
        // We clone the parent chain.
        // This helps us resurrect important styling elements that cross lines.
        // E.g. in Foo
Bar
        // should be rewritten to
Foo

Bar
.
        var parentClone = breakLeftOf(parent, 1);
        // Move the clone and everything to the right of the original
        // onto the cloned parent.
        var next = limit.nextSibling;
        parentClone.appendChild(rightSide);
        for (var sibling = next; sibling; sibling = next) {
          next = sibling.nextSibling;
          parentClone.appendChild(sibling);
        }
      }
      return rightSide;
    }

    var split = breakLeftOf(lineEndNode.nextSibling, 0);

    // Walk the parent chain until we reach an unattached LI.
    for (var parent; (parent = split.parentNode);) { split = parent; }
    // Put it on the list of lines for later processing.
    listItems.push(split);
console.log('pushing listItem length=' + listItems.length);
  }

  // Split lines while there are lines left to split.
  for (var i = 0;  // Number of lines that have been split so far.
       i < listItems.length;  // length updated by breakAfter calls.
       ++i) {
console.log('walking list item ' + i);
    walk(listItems[i]);
  }

  // Make sure numeric indices show correctly.
  if (opt_startLineNum === (opt_startLineNum|0)) {
    listItems[0].setAttribute('value', opt_startLineNum);
  }

  var ol = document.createElement('OL');
  ol.className = 'linenums';
  var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
  for (var i = 0, n = listItems.length; i < n; ++i) {
    li = listItems[i];
    // Stick a class on the LIs so that stylesheets can
    // color odd/even rows, or any other row pattern that
    // is co-prime with 10.
    li.className = 'L' + ((i + offset) % 10);
    if (!li.firstChild) {
      li.appendChild(document.createTextNode('\xA0'));
    }
    ol.appendChild(li);
  }

  node.appendChild(ol);
}<|endoftext|>