<commit_before>/***** BEGIN LICENSE BLOCK ***** {{{
 Copyright © 2008-2009 by Kris Maglione <maglione.k at Gmail>
 Distributable under the terms of the MIT license, which allows
 for sublicensing under any compatible license, including the MPL,
 GPL, and MPL. Anyone who changes this file is welcome to relicense
 it under any or all of those licenseses.
}}} ***** END LICENSE BLOCK *****/

var EXPORTED_SYMBOLS = ["storage", "Timer"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

// XXX: does not belong here
function Timer(minInterval, maxInterval, callback)
{
    let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    this.doneAt = 0;
    this.latest = 0;
    this.notify = function (aTimer)
    {
        timer.cancel();
        this.latest = 0;
        /* minInterval is the time between the completion of the command and the next firing. */
        this.doneAt = Date.now() + minInterval;

        try
        {
            callback(this.arg);
        }
        finally
        {
            this.doneAt = Date.now() + minInterval;
        }
    };
    this.tell = function (arg)
    {
        if (arguments.length > 0)
            this.arg = arg;

        let now = Date.now();
        if (this.doneAt == -1)
            timer.cancel();

        let timeout = minInterval;
        if (now > this.doneAt && this.doneAt > -1)
            timeout = 0;
        else if (this.latest)
            timeout = Math.min(timeout, this.latest - now);
        else
            this.latest = now + maxInterval;

        timer.initWithCallback(this, Math.max(timeout, 0), timer.TYPE_ONE_SHOT);
        this.doneAt = -1;
    };
    this.reset = function ()
    {
        timer.cancel();
        this.doneAt = 0;
    };
    this.flush = function ()
    {
        if (this.doneAt == -1)
            this.notify();
    };
}

function getFile(name)
{
    let file = storage.infoPath.clone();
    file.append(name);
    return file;
}

function readFile(file)
{
    let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
    let stream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);

    try
    {
        fileStream.init(file, -1, 0, 0);
        stream.init(fileStream, "UTF-8", 4096, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); // 4096 bytes buffering

        let hunks = [];
        let res = {};
        while (stream.readString(4096, res) != 0)
            hunks.push(res.value);

        stream.close();
        fileStream.close();

        return hunks.join("");
    }
    catch (e) {}
}

function writeFile(file, data)
{
    if (!file.exists())
        file.create(file.NORMAL_FILE_TYPE, 0600);

    let fileStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
    let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream);

    fileStream.init(file, 0x20 | 0x08 | 0x02, 0600, 0); // PR_TRUNCATE | PR_CREATE | PR_WRITE
    stream.init(fileStream, "UTF-8", 0, 0);

    stream.writeString(data);

    stream.close();
    fileStream.close();
}

var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService)
                            .getBranch("extensions.liberator.datastore.");
var json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);

function getCharPref(name)
{
    try
    {
        return prefService.getComplexValue(name, Ci.nsISupportsString).data;
    }
    catch (e) {}
}

function setCharPref(name, value)
{
    var str = Cc['@mozilla.org/supports-string;1'].createInstance(Ci.nsISupportsString);
    str.data = value;
    return prefService.setComplexValue(name, Ci.nsISupportsString, str);
}

function loadPref(name, store, type)
{
    if (store)
        var pref = getCharPref(name);
    if (!pref && storage.infoPath)
        var file = readFile(getFile(name));
    if (pref || file)
        var result = json.decode(pref || file);
    if (pref)
    {
        prefService.clearUserPref(name);
        savePref({ name: name, store: true, serial: pref })
    }
    if (result instanceof type)
        return result;
}

function savePref(obj)
{
    if (obj.privateData && storage.privateMode)
        return;
    if (obj.store && storage.infoPath)
        writeFile(getFile(obj.name), obj.serial);
}

var prototype = {
    OPTIONS: ["privateData"],
    fireEvent: function (event, arg) { storage.fireEvent(this.name, event, arg) },
    save: function () { savePref(this) },
    init: function (name, store, data, options)
    {
        this.__defineGetter__("store", function () store);
        this.__defineGetter__("name", function () name);
        for (let [k, v] in Iterator(options))
            if (this.OPTIONS.indexOf(k) >= 0)
                this[k] = v;
        this.reload();
    }
};

function ObjectStore(name, store, load, options)
{
    var object = {};

    this.reload = function reload()
    {
        object = load() || {};
        this.fireEvent("change", null);
    };

    this.init.apply(this, arguments);
    this.__defineGetter__("serial", function () json.encode(object));

    this.set = function set(key, val)
    {
        var defined = key in object;
        var orig = object[key];
        object[key] = val;
        if (!defined)
            this.fireEvent("add", key);
        else if (orig != val)
            this.fireEvent("change", key);
    };

    this.remove = function remove(key)
    {
        var ret = object[key];
        delete object[key];
        this.fireEvent("remove", key);
        return ret;
    };

    this.get = function get(val) object[val];

    this.clear = function ()
    {
        object = {};
    };

    this.__iterator__ = function () Iterator(object);
}
ObjectStore.prototype = prototype;

function ArrayStore(name, store, load, options)
{
    var array = [];

    this.reload = function reload()
    {
        array = load() || [];
        this.fireEvent("change", null);
    };

    this.init.apply(this, arguments);
    this.__defineGetter__("serial", function () json.encode(array));
    this.__defineGetter__("length", function () array.length);

    this.set = function set(index, value)
    {
        var orig = array[index];
        array[index] = value;
        this.fireEvent("change", index);
    };

    this.push = function push(value)
    {
        array.push(value);
        this.fireEvent("push", array.length);
    };

    this.pop = function pop(value)
    {
        var ret = array.pop();
        this.fireEvent("pop", array.length);
        return ret;
    };

    this.truncate = function truncate(length, fromEnd)
    {
        var ret = array.length;
        if (array.length > length)
        {
            if (fromEnd)
                array.splice(0, array.length - length);
            array.length = length;
            this.fireEvent("truncate", length);
        }
        return ret;
    };

    // XXX: Awkward.
    this.mutate = function mutate(aFuncName)
    {
        var funcName = aFuncName;
        arguments[0] = array;
        array = Array[funcName].apply(Array, arguments);
        this.fireEvent("change", null);
    };

    this.get = function get(index)
    {
        return index >= 0 ? array[index] : array[array.length + index];
    };

    this.__iterator__ = function () Iterator(array);
}
ArrayStore.prototype = prototype;

var keys = {};
var observers = {};
var timers = {};

var storage = {
    newObject: function newObject(key, constructor, store, type, options, reload)
    {
        if (!(key in keys) || reload)
        {
            if (key in this && !reload)
                throw Error;
            let load = function() loadPref(key, store, type || Object);
            keys[key] = new constructor(key, store, load, options || {});
            timers[key] = new Timer(1000, 10000, function () storage.save(key));
            this.__defineGetter__(key, function () keys[key]);
        }
        return keys[key];
    },

    newMap: function newMap(key, store, options)
    {
        return this.newObject(key, ObjectStore, store, null, options);
    },

    newArray: function newArray(key, store, options)
    {
        return this.newObject(key, ArrayStore, store, Array, options);
    },

    addObserver: function addObserver(key, callback, ref)
    {
        if (ref)
        {
            if (!ref.liberatorStorageRefs)
                ref.liberatorStorageRefs = [];
            ref.liberatorStorageRefs.push(callback);
            var callbackRef = Cu.getWeakReference(callback);
        }
        else
        {
            callbackRef = { get: function () callback };
        }
        this.removeDeadObservers();
        if (!(key in observers))
            observers[key] = [];
        if (!observers[key].some(function (o) o.callback.get() == callback))
            observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
    },

    removeObserver: function (key, callback)
    {
        this.removeDeadObservers();
        if (!(key in observers))
            return;
        observers[key] = observers[key].filter(function (elem) elem.callback.get() != callback);
        if (observers[key].length == 0)
            delete obsevers[key];
    },

    removeDeadObservers: function ()
    {
        for (let [key, ary] in Iterator(observers))
        {
            observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().liberatorStorageRefs))
            if (!ary.length)
                delete observers[key];
        }
    },

    get observers() observers,

    fireEvent: function fireEvent(key, event, arg)
    {
        if (!(key in this))
            return;
        this.removeDeadObservers();
        // Safe, since we have our own Array object here.
        for each (let observer in observers[key])
            observer.callback.get()(key, event, arg);
        timers[key].tell();
    },

    load: function load(key)
    {
        if (this[key].store && this[key].reload)
            this[key].reload();
    },

    save: function save(key)
    {
        savePref(keys[key]);
    },

    saveAll: function storeAll()
    {
        for each (let obj in keys)
            savePref(obj);
    },

    _privateMode: false,
    get privateMode() this._privateMode,
    set privateMode(val)
    {
        if (!val && this._privateMode)
            for (let key in keys)
                this.load(key);
        return this._privateMode = Boolean(val);
    },
};

// vim: set fdm=marker sw=4 sts=4 et ft=javascript:
<commit_msg>Formatting fixes.<commit_after>/***** BEGIN LICENSE BLOCK ***** {{{
 Copyright © 2008-2009 by Kris Maglione <maglione.k at Gmail>
 Distributable under the terms of the MIT license, which allows
 for sublicensing under any compatible license, including the MPL,
 GPL, and MPL. Anyone who changes this file is welcome to relicense
 it under any or all of those licenseses.
}}} ***** END LICENSE BLOCK *****/

var EXPORTED_SYMBOLS = ["storage", "Timer"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

// XXX: does not belong here
function Timer(minInterval, maxInterval, callback)
{
    let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    this.doneAt = 0;
    this.latest = 0;
    this.notify = function (aTimer)
    {
        timer.cancel();
        this.latest = 0;
        // minInterval is the time between the completion of the command and the next firing
        this.doneAt = Date.now() + minInterval;

        try
        {
            callback(this.arg);
        }
        finally
        {
            this.doneAt = Date.now() + minInterval;
        }
    };
    this.tell = function (arg)
    {
        if (arguments.length > 0)
            this.arg = arg;

        let now = Date.now();
        if (this.doneAt == -1)
            timer.cancel();

        let timeout = minInterval;
        if (now > this.doneAt && this.doneAt > -1)
            timeout = 0;
        else if (this.latest)
            timeout = Math.min(timeout, this.latest - now);
        else
            this.latest = now + maxInterval;

        timer.initWithCallback(this, Math.max(timeout, 0), timer.TYPE_ONE_SHOT);
        this.doneAt = -1;
    };
    this.reset = function ()
    {
        timer.cancel();
        this.doneAt = 0;
    };
    this.flush = function ()
    {
        if (this.doneAt == -1)
            this.notify();
    };
}

function getFile(name)
{
    let file = storage.infoPath.clone();
    file.append(name);
    return file;
}

function readFile(file)
{
    let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
    let stream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);

    try
    {
        fileStream.init(file, -1, 0, 0);
        stream.init(fileStream, "UTF-8", 4096, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); // 4096 bytes buffering

        let hunks = [];
        let res = {};
        while (stream.readString(4096, res) != 0)
            hunks.push(res.value);

        stream.close();
        fileStream.close();

        return hunks.join("");
    }
    catch (e) {}
}

function writeFile(file, data)
{
    if (!file.exists())
        file.create(file.NORMAL_FILE_TYPE, 0600);

    let fileStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
    let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream);

    fileStream.init(file, 0x20 | 0x08 | 0x02, 0600, 0); // PR_TRUNCATE | PR_CREATE | PR_WRITE
    stream.init(fileStream, "UTF-8", 0, 0);

    stream.writeString(data);

    stream.close();
    fileStream.close();
}

var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService)
                            .getBranch("extensions.liberator.datastore.");
var json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);

function getCharPref(name)
{
    try
    {
        return prefService.getComplexValue(name, Ci.nsISupportsString).data;
    }
    catch (e) {}
}

function setCharPref(name, value)
{
    var str = Cc['@mozilla.org/supports-string;1'].createInstance(Ci.nsISupportsString);
    str.data = value;
    return prefService.setComplexValue(name, Ci.nsISupportsString, str);
}

function loadPref(name, store, type)
{
    if (store)
        var pref = getCharPref(name);
    if (!pref && storage.infoPath)
        var file = readFile(getFile(name));
    if (pref || file)
        var result = json.decode(pref || file);
    if (pref)
    {
        prefService.clearUserPref(name);
        savePref({ name: name, store: true, serial: pref });
    }
    if (result instanceof type)
        return result;
}

function savePref(obj)
{
    if (obj.privateData && storage.privateMode)
        return;
    if (obj.store && storage.infoPath)
        writeFile(getFile(obj.name), obj.serial);
}

var prototype = {
    OPTIONS: ["privateData"],
    fireEvent: function (event, arg) { storage.fireEvent(this.name, event, arg); },
    save: function () { savePref(this); },
    init: function (name, store, data, options)
    {
        this.__defineGetter__("store", function () store);
        this.__defineGetter__("name", function () name);
        for (let [k, v] in Iterator(options))
            if (this.OPTIONS.indexOf(k) >= 0)
                this[k] = v;
        this.reload();
    }
};

function ObjectStore(name, store, load, options)
{
    var object = {};

    this.reload = function reload()
    {
        object = load() || {};
        this.fireEvent("change", null);
    };

    this.init.apply(this, arguments);
    this.__defineGetter__("serial", function () json.encode(object));

    this.set = function set(key, val)
    {
        var defined = key in object;
        var orig = object[key];
        object[key] = val;
        if (!defined)
            this.fireEvent("add", key);
        else if (orig != val)
            this.fireEvent("change", key);
    };

    this.remove = function remove(key)
    {
        var ret = object[key];
        delete object[key];
        this.fireEvent("remove", key);
        return ret;
    };

    this.get = function get(val) object[val];

    this.clear = function ()
    {
        object = {};
    };

    this.__iterator__ = function () Iterator(object);
}
ObjectStore.prototype = prototype;

function ArrayStore(name, store, load, options)
{
    var array = [];

    this.reload = function reload()
    {
        array = load() || [];
        this.fireEvent("change", null);
    };

    this.init.apply(this, arguments);
    this.__defineGetter__("serial", function () json.encode(array));
    this.__defineGetter__("length", function () array.length);

    this.set = function set(index, value)
    {
        var orig = array[index];
        array[index] = value;
        this.fireEvent("change", index);
    };

    this.push = function push(value)
    {
        array.push(value);
        this.fireEvent("push", array.length);
    };

    this.pop = function pop(value)
    {
        var ret = array.pop();
        this.fireEvent("pop", array.length);
        return ret;
    };

    this.truncate = function truncate(length, fromEnd)
    {
        var ret = array.length;
        if (array.length > length)
        {
            if (fromEnd)
                array.splice(0, array.length - length);
            array.length = length;
            this.fireEvent("truncate", length);
        }
        return ret;
    };

    // XXX: Awkward.
    this.mutate = function mutate(aFuncName)
    {
        var funcName = aFuncName;
        arguments[0] = array;
        array = Array[funcName].apply(Array, arguments);
        this.fireEvent("change", null);
    };

    this.get = function get(index)
    {
        return index >= 0 ? array[index] : array[array.length + index];
    };

    this.__iterator__ = function () Iterator(array);
}
ArrayStore.prototype = prototype;

var keys = {};
var observers = {};
var timers = {};

var storage = {
    newObject: function newObject(key, constructor, store, type, options, reload)
    {
        if (!(key in keys) || reload)
        {
            if (key in this && !reload)
                throw Error;
            let load = function () loadPref(key, store, type || Object);
            keys[key] = new constructor(key, store, load, options || {});
            timers[key] = new Timer(1000, 10000, function () storage.save(key));
            this.__defineGetter__(key, function () keys[key]);
        }
        return keys[key];
    },

    newMap: function newMap(key, store, options)
    {
        return this.newObject(key, ObjectStore, store, null, options);
    },

    newArray: function newArray(key, store, options)
    {
        return this.newObject(key, ArrayStore, store, Array, options);
    },

    addObserver: function addObserver(key, callback, ref)
    {
        if (ref)
        {
            if (!ref.liberatorStorageRefs)
                ref.liberatorStorageRefs = [];
            ref.liberatorStorageRefs.push(callback);
            var callbackRef = Cu.getWeakReference(callback);
        }
        else
        {
            callbackRef = { get: function () callback };
        }
        this.removeDeadObservers();
        if (!(key in observers))
            observers[key] = [];
        if (!observers[key].some(function (o) o.callback.get() == callback))
            observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
    },

    removeObserver: function (key, callback)
    {
        this.removeDeadObservers();
        if (!(key in observers))
            return;
        observers[key] = observers[key].filter(function (elem) elem.callback.get() != callback);
        if (observers[key].length == 0)
            delete obsevers[key];
    },

    removeDeadObservers: function ()
    {
        for (let [key, ary] in Iterator(observers))
        {
            observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().liberatorStorageRefs));
            if (!ary.length)
                delete observers[key];
        }
    },

    get observers() observers,

    fireEvent: function fireEvent(key, event, arg)
    {
        if (!(key in this))
            return;
        this.removeDeadObservers();
        // Safe, since we have our own Array object here.
        for each (let observer in observers[key])
            observer.callback.get()(key, event, arg);
        timers[key].tell();
    },

    load: function load(key)
    {
        if (this[key].store && this[key].reload)
            this[key].reload();
    },

    save: function save(key)
    {
        savePref(keys[key]);
    },

    saveAll: function storeAll()
    {
        for each (let obj in keys)
            savePref(obj);
    },

    _privateMode: false,
    get privateMode() this._privateMode,
    set privateMode(val)
    {
        if (!val && this._privateMode)
            for (let key in keys)
                this.load(key);
        return this._privateMode = Boolean(val);
    },
};

// vim: set fdm=marker sw=4 sts=4 et ft=javascript:
<|endoftext|>


<commit_before>/*
 * UniTime 3.1 (University Timetabling Application)
 * Copyright (C) 2008, UniTime LLC
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

// Select.js

// To use include the following in the <HEAD> of the HTML document:
//   <script language="JavaScript" src="Select.js"></script>

// Each <SELECT> that wishes to use this must include:
//    onactivate="setUp();"
//    onkeypress="return selectSearch(event, this);"
//    onkeydown="return checkKey(event, this);"

var matchString = "";
var wasModified = false;

function selectSearch(event, field) {
	var code = -1;

	if (event.keyCode) code = event.keyCode;
	else if (event.which) code = event.which;

	//displayStatus();

	// KeyCodes: 9=tab, 13=Enter
	if (code == 9 || code == 13 || code == 46) {
		matchString = "";
		return true;
	}

	if(code > 31 && code < 127) {
		if ( (code<=33) || (code >=38 && code<=127) ) {
			keyVal = String.fromCharCode(code);
			matchString = matchString + keyVal;
			wasModified = true;
		}
		else {
			wasModified = true;
			return true;
		}
	}

	displayStatus();

	elementCnt  = field.length - 1;

	for (i = elementCnt; i >= 0; i--) {
		selectText = field.options[i].text.toLowerCase();
		if (selectText.substr(0, matchString.length) == matchString.toLowerCase()) {
			field.options[i].selected = true;
		}
	}

	return false;
}

function checkKey(event, field) {

	var code = -1;

	if (event.keyCode) code = event.keyCode;
	else if (event.which) code = event.which;

	// KeyCodes: 8=BackSpace, 46=Delete
	if(code == 8) {
		if(matchString.length >= 1) {
			matchString = matchString.substr(0, (matchString.length - 1));
			wasModified = true;
		}
		return selectSearch(event, field);
	}

	if (code == 46) {
		matchString = "";
		wasModified = true;
		displayStatus();
		return false;
	}

	if (code == 9) {
		matchString = "";
		return true;
	}
}

function setUp() {

	matchString = "";
	wasModified = false;
}

function isModified() {

	return wasModified;
}

function displayStatus() {

	window.status = 'Searching for: "' + matchString.toLowerCase() + '" ( use BACKSPACE key to modify, DELETE key to clear the search string)';
}
<commit_msg>added selectSearchTime method<commit_after>/*
 * UniTime 3.1 (University Timetabling Application)
 * Copyright (C) 2008, UniTime LLC
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

// Select.js

// To use include the following in the <HEAD> of the HTML document:
//   <script language="JavaScript" src="Select.js"></script>

// Each <SELECT> that wishes to use this must include:
//    onactivate="setUp();"
//    onkeypress="return selectSearch(event, this);"
//    onkeydown="return checkKey(event, this);"

var matchString = "";
var wasModified = false;

function selectSearch(event, field) {
	var code = -1;

	if (event.keyCode) code = event.keyCode;
	else if (event.which) code = event.which;

	//displayStatus();

	// KeyCodes: 9=tab, 13=Enter, 46=Delete
	if (code == 9 || code == 13 || code == 46) {
		matchString = "";
		return true;
	}

	if(code > 31 && code < 127) {
		if ( (code<=33) || (code >=38 && code<=127) ) {
			keyVal = String.fromCharCode(code);
			matchString = matchString + keyVal;
			wasModified = true;
		}
		else {
			wasModified = true;
			return true;
		}
	}

	displayStatus();

	for (i = 0; i < field.options.length; i++) {
		selectText = field.options[i].text.toLowerCase();
		if (selectText.substr(0, matchString.length) == matchString.toLowerCase()) {
			field.options[i].selected = true;
			return false;
		}
	}

	return true;
}

function selectSearchTime(event, field) {
	var code = -1;

	if (event.keyCode) code = event.keyCode;
	else if (event.which) code = event.which;

	//displayStatus();

	// KeyCodes: 9=tab, 13=Enter, 46=Delete
	if (code == 9 || code == 13 || code == 46) {
		matchString = "";
		return true;
	}

	if(code > 31 && code < 127) {
		if ( (code<=33) || (code >=38 && code<=127) ) {
			keyVal = String.fromCharCode(code);
			matchString = matchString + keyVal;
			wasModified = true;
		}
		else {
			wasModified = true;
			return true;
		}
	}

	displayStatus();

	var pat1 = new RegExp("\\d?\\d","g");
	var pat2 = new RegExp("[ap]","g");

	var hour = pat1.exec(matchString);
	var am = pat2.exec(matchString);
	var min = pat1.exec(matchString);

	if (!hour) hour = 12;
	if (!am) am = (hour<7?'p':'a');
	if (!min) min = 0;
	if (hour>23) { min = (''+hour).substr(1,1) + min; hour = (''+hour).substr(0,1); }
	if (hour>12) { hour -= 12; am = 'p'; }

	var matchTime = hour+':'+((''+min).length<2?'0':'')+min+' '+am+'m';

	for (i = 0; i < field.options.length; i++) {
		if (field.options[i].text == matchTime) {
			field.options[i].selected = true;
			return false;
		}
	}

	return true;
}

function checkKey(event, field) {

	var code = -1;

	if (event.keyCode) code = event.keyCode;
	else if (event.which) code = event.which;

	// KeyCodes: 8=BackSpace, 46=Delete, 9==Tab
	if(code == 8) {
		if(matchString.length >= 1) {
			matchString = matchString.substr(0, (matchString.length - 1));
			wasModified = true;
		}
		return selectSearch(event, field);
	}

	if (code == 46) {
		matchString = "";
		wasModified = true;
		displayStatus();
		return false;
	}

	if (code == 9) {
		matchString = "";
		return true;
	}
}

function setUp() {

	matchString = "";
	wasModified = false;
}

function isModified() {

	return wasModified;
}

function displayStatus() {
	window.status = 'Searching for: "' + matchString.toLowerCase() + '" ( use BACKSPACE key to modify, DELETE key to clear the search string)';
}
<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage/budgetbutler'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    browsers: ['ChromeHeadlessNoSandbox'],

    // you can define custom flags
    customLaunchers: {
      ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox']
      }
    }

    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>fix json<commit_after>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage/budgetbutler'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    browsers: ['ChromeHeadlessNoSandbox'],

    // you can define custom flags
    customLaunchers: {
      ChromeHeadlessNoSandbox: {
        base: 'ChromeHeadless',
        flags: ['--no-sandbox']
      }
    },

    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<|endoftext|>


<commit_before>import { OrderedMap } from "immutable";
import { combineReducers } from "redux";
import types from "./actionsTypes";
import { DecksInitialLoadingState } from "./models";

const loadingState = (state = DecksInitialLoadingState.NOT_LOADED, action) => {
  switch (action.type) {
    case types.START_LOADING_INITIAL_DECKS:
      return DecksInitialLoadingState.LOADING;
    case types.LOAD_INITIAL_DECKS:
      return DecksInitialLoadingState.LOADED;
    default:
      return state;
  }
};

const creatingState = (state = "STOPPED", action) => {
  switch (action.type) {
    case types.START_CREATING_DECK:
      return "CREATING";
    case types.FINISH_CREATING_DECK:
      return action.success ? "CREATED" : "FAILED";
    default:
      return state;
  }
};

const deletingState = (state = "STOPPED", action) => {
  switch (action.type) {
    case types.START_DELETING_DECK:
      return "DELETING";
    case types.FINISH_DELETING_DECK:
      return action.success ? "DELETED" : "FAILED";
    default:
      return state;
  }
};

const deletingDeck = (state = null, action) => {
  switch (action.type) {
    case types.START_DELETING_DECK:
      return action.deck;
    case types.FINISH_DELETING_DECK:
      return null;
    default:
      return state;
  }
};

const editingDeck = (state = null, action) => {
  switch (action.type) {
    case types.START_EDITING_DECK:
      return action.deck;
    case types:
      return null;
    default:
      return state;
  }
};

const items = (state = OrderedMap(), action) => {
  switch (action.type) {
    case types.LOAD_INITIAL_DECKS:
      return loadInitialDecks(state, action);
    case types.ADD_DECK:
      return addDeck(state, action);
    case types.REMOVE_DECK:
      return removeDeck(state, action);
    case types.UPDATE_DECK:
      return updateDeck(state, action);
    case types.ADD_CARD:
      return addCard(state, action);
    case types.REMOVE_CARD:
      return removeCard(state, action);
    case types.UPDATE_CARD:
      return updateCard(state, action);
    default:
      return state;
  }
};

const loadInitialDecks = (state, action) => {
  return OrderedMap(action.decks.map(deck => [deck.id, deck]));
};

const addDeck = (state, action) => {
  return state.set(action.deck.id, action.deck);
};

const removeDeck = (state, action) => {
  return state.remove(action.deck.id);
};

const updateDeck = (state, action) => {
  return state.set(action.deck.id, action.deck);
};

const addCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.set(action.card.id, action.card);
  });
};

const removeCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.remove(action.card.id);
  });
};

const updateCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.set(action.card.id, action.card);
  });
};

const changeDeckCards = (state, deckId, changeFunction) => {
  let deck = state.get(deckId);
  let cards = deck.cards;
  cards = changeFunction(cards);
  deck = deck.set("cards", cards);
  return state.set(deckId, deck);
};

const reducer = combineReducers({
  loadingState,
  creatingState,
  deletingState,
  deletingDeck,
  editingDeck,
  items
});

export default reducer;
<commit_msg>Remove unused reducers<commit_after>import { OrderedMap } from "immutable";
import { combineReducers } from "redux";
import types from "./actionsTypes";
import { DecksInitialLoadingState } from "./models";

const loadingState = (state = DecksInitialLoadingState.NOT_LOADED, action) => {
  switch (action.type) {
    case types.START_LOADING_INITIAL_DECKS:
      return DecksInitialLoadingState.LOADING;
    case types.LOAD_INITIAL_DECKS:
      return DecksInitialLoadingState.LOADED;
    default:
      return state;
  }
};

const deletingDeck = (state = null, action) => {
  switch (action.type) {
    case types.START_DELETING_DECK:
      return action.deck;
    case types.FINISH_DELETING_DECK:
      return null;
    default:
      return state;
  }
};

const editingDeck = (state = null, action) => {
  switch (action.type) {
    case types.START_EDITING_DECK:
      return action.deck;
    case types:
      return null;
    default:
      return state;
  }
};

const items = (state = OrderedMap(), action) => {
  switch (action.type) {
    case types.LOAD_INITIAL_DECKS:
      return loadInitialDecks(state, action);
    case types.ADD_DECK:
      return addDeck(state, action);
    case types.REMOVE_DECK:
      return removeDeck(state, action);
    case types.UPDATE_DECK:
      return updateDeck(state, action);
    case types.ADD_CARD:
      return addCard(state, action);
    case types.REMOVE_CARD:
      return removeCard(state, action);
    case types.UPDATE_CARD:
      return updateCard(state, action);
    default:
      return state;
  }
};

const loadInitialDecks = (state, action) => {
  return OrderedMap(action.decks.map(deck => [deck.id, deck]));
};

const addDeck = (state, action) => {
  return state.set(action.deck.id, action.deck);
};

const removeDeck = (state, action) => {
  return state.remove(action.deck.id);
};

const updateDeck = (state, action) => {
  return state.set(action.deck.id, action.deck);
};

const addCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.set(action.card.id, action.card);
  });
};

const removeCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.remove(action.card.id);
  });
};

const updateCard = (state, action) => {
  return changeDeckCards(state, action.card.deck.id, cards => {
    return cards.set(action.card.id, action.card);
  });
};

const changeDeckCards = (state, deckId, changeFunction) => {
  let deck = state.get(deckId);
  let cards = deck.cards;
  cards = changeFunction(cards);
  deck = deck.set("cards", cards);
  return state.set(deckId, deck);
};

const reducer = combineReducers({
  loadingState,
  deletingDeck,
  editingDeck,
  items
});

export default reducer;
<|endoftext|>


<commit_before>Kwc.Paragraphs.DataView = Ext.extend(Ext.DataView, {
    autoHeight: true,
    multiSelect: true,
    overClass: 'x-view-over',
    itemSelector: 'div.paragraph-wrap',
    showToolbars: true,
    showDelete: true,
    showPosition: true,
    showCopyPaste: true,
    border: false,
    initComponent: function()
    {
        this.componentConfigs = {};

        this.addEvents('delete', 'edit', 'changeVisible', 'changeDeviceVisible', 'changePos',
            'addParagraphMenuShow', 'addParagraph', 'copyParagraph',
            'pasteParagraph', 'copyPasteMenuShow');
        this.tpl = new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="paragraph-wrap<tpl if="!visible"> kwc-paragraph-invisible</tpl>" id="kwc-paragraphs-{id}" style="width:'+this.width+'px">',
                    '

',
                    '
{preview}
',
                '
',
            '</tpl>',
            '

'
        );

        Kwc.Paragraphs.DataView.superclass.initComponent.call(this);
    },

    onUpdate: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.onUpdate.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    onAdd: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.onAdd.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    refresh: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.refresh.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    updateToolbars: function()
    {
        Kwf.callOnContentReady(this.el, { newRender: true });

        if (!this.showToolbars) return;

        var nodes = this.getNodes();
        for (var i=0; i< nodes.length; i++) {
            var node = nodes[i];
            if (node.hasParagraphsToolbarRendered) {
                continue;
            }
            node.hasParagraphsToolbarRendered = true;
            var tbCt = Ext.get(node).down('.kwc-paragraphs-toolbar');
            var tb = new Ext.Toolbar({
                renderTo: tbCt
            });
            var record = this.getRecord(node);

            this.configureToolbar(tb, record);
        }
    },
    configureToolbar: function(tb, record) {
        tb.add({
            //text: record.get('visible') ? trlKwf('visible') : trlKwf('invisible'),
            tooltip: trlKwf('visibility'),
            scope: this,
            record: record,
            handler: function(btn) {
                this.fireEvent('changeVisible', btn.record);
            },
            icon : '/assets/silkicons/'+(record.get('visible') ? 'tick' : 'cross') + '.png',
            cls  : 'x-btn-icon'
        });
        if (this.showDeviceVisible) {
            var deviceVisibleMenu = {
                menu: [{
                    text: trlKwf('show on all devices'),
                    icon: '/assets/kwf/images/devices/showAll.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'all');
                    }
                },{
                    text: trlKwf('hide on mobile devices'),
                    icon: '/assets/kwf/images/devices/smartphoneHide.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'hideOnMobile');
                    }
                },{
                    text: trlKwf('only show on mobile devices'),
                    icon: '/assets/kwf/images/devices/smartphone.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'onlyShowOnMobile');
                    }
                }],
                cls  : 'x-btn-icon'
            };
            if (record.get('device_visible') == 'onlyShowOnMobile') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/smartphone.png';
            } else if (record.get('device_visible') == 'hideOnMobile') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/smartphoneHide.png';
            } else if (record.get('device_visible') == 'all') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/showAll.png';
            }
            tb.add(deviceVisibleMenu);
        }

        if (this.showPosition) {
            var posCombo = new Kwf.Form.ComboBox({
                listClass: 'kwc-paragraphs-pos-list',
                tpl: '<tpl for=".">' +
                    '<div class="x-combo-list-item<tpl if="visible"> visible</tpl><tpl if="!visible"> invisible</tpl>">'+
                        '{pos} - {component_name}'+
                    '
'+
                    '</tpl>',
                displayField: 'pos',
                valueField: 'pos',
                store: this.store,
                editable: false,
                width: 50,
                triggerAction: 'all',
                mode: 'local',
                record: record,
                listWidth: 100,
                listeners: {
                    scope: this,
                    changevalue: function(v, combo) {
                        if (v && combo.record.get('pos') != v) {
                            this.fireEvent('changePos', combo.record, v);
                            combo.blur();
                            combo.hasFocus = false; //ansonsten wird die list angezeigt nachdem daten geladen wurden
                        }
                    }
                }
            });
            posCombo.setValue(record.get('pos'));
            tb.add(posCombo);
        } else {
            tb.add(record.get('pos'));
        }
        if (this.showDelete) {
            tb.add({
                tooltip: trlKwf('delete'),
                scope: this,
                record: record,
                handler: function(btn) {
                    this.fireEvent('delete', btn.record);
                },
                icon : '/assets/silkicons/bin.png',
                cls  : 'x-btn-icon'
            });
        }
        if (record.get('edit_components').length == 1) {
            tb.add('-');
            tb.add({
                text: trlKwf('edit'),
                scope: this,
                record: record,
                handler: function(btn) {
                    this.fireEvent('edit', btn.record, Kwf.clone(btn.record.get('edit_components')[0]));
                },
                icon : '/assets/silkicons/application_edit.png',
                cls  : 'x-btn-text-icon'
            });
        } else if (record.get('edit_components').length > 1) {
            tb.add('-');
            var menu = [];
            record.get('edit_components').forEach(function(ec) {
                var cfg = this.componentConfigs[ec.componentClass+'-'+ec.type];
                menu.push({
                    text: cfg.title,
                    icon: cfg.icon,
                    scope: this,
                    record: record,
                    editComponent: ec,
                    handler: function(menu) {
                        this.fireEvent('edit', menu.record, Kwf.clone(menu.editComponent));
                    }
                });
            }, this);
            tb.add({
                text: trlKwf('edit'),
                menu: menu,
                icon : '/assets/silkicons/application_edit.png',
                cls  : 'x-btn-text-icon'
            });
        }
        if (this.components) {
            tb.add('-');
            tb.add(new Kwc.Paragraphs.AddParagraphButton({
                record: record,
                components: this.components,
                componentIcons: this.componentIcons,
                listeners: {
                    scope: this,
                    menushow: function(btn) {
                        this.fireEvent('addParagraphMenuShow', btn.record);
                    },
                    addParagraph: function(component) {
                        this.fireEvent('addParagraph', component);
                    }
                }
            }));
            if (this.showCopyPaste) {
                tb.add({
                    text: trlKwf('copy/paste'),
                    menu: [{
                        text: trlKwf('Copy Paragraph'),
                        icon: '/assets/silkicons/page_white_copy.png',
                        scope: this,
                        record: record,
                        handler: function(btn) {
                            this.fireEvent('copyParagraph', btn.record);
                        }
                    },{
                        text: trlKwf('Paste Paragraph'),
                        icon: '/assets/silkicons/page_white_copy.png',
                        scope: this,
                        handler: function() {
                            this.fireEvent('pasteParagraph');
                        }
                    }],
                    icon: '/assets/silkicons/page_white_copy.png',
                    cls  : 'x-btn-text-icon',
                    record: record,
                    listeners: {
                        scope: this,
                        menushow: function(btn) {
                            this.fireEvent('copyPasteMenuShow', btn.record);
                        }
                    }
                });
            }
        }
        tb.add('->');
        tb.add(record.get('component_name'));
        tb.add('');
    }
});
<commit_msg>improve performance when deleting paragraph<commit_after>Kwc.Paragraphs.DataView = Ext.extend(Ext.DataView, {
    autoHeight: true,
    multiSelect: true,
    overClass: 'x-view-over',
    itemSelector: 'div.paragraph-wrap',
    showToolbars: true,
    showDelete: true,
    showPosition: true,
    showCopyPaste: true,
    border: false,
    initComponent: function()
    {
        this.componentConfigs = {};

        this.addEvents('delete', 'edit', 'changeVisible', 'changeDeviceVisible', 'changePos',
            'addParagraphMenuShow', 'addParagraph', 'copyParagraph',
            'pasteParagraph', 'copyPasteMenuShow');
        this.tpl = new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="paragraph-wrap<tpl if="!visible"> kwc-paragraph-invisible</tpl>" id="kwc-paragraphs-{id}" style="width:'+this.width+'px">',
                    '

',
                    '
{preview}
',
                '
',
            '</tpl>',
            '

'
        );

        //buffer callOnContentReady for better performance when changing multiple rows - which happens when
        //deleting and entry and all below have to be re-numbered
        this.callOnContentReadyTask = new Ext.util.DelayedTask(function() {
            Kwf.callOnContentReady(this.el, { newRender: true });
        }, this);

        Kwc.Paragraphs.DataView.superclass.initComponent.call(this);
    },

    onUpdate: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.onUpdate.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    onAdd: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.onAdd.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    refresh: function() {
        var ret = Kwc.Paragraphs.DataView.superclass.refresh.apply(this, arguments);
        this.updateToolbars();
        return ret;
    },
    updateToolbars: function()
    {
        this.callOnContentReadyTask.delay(10);

        if (!this.showToolbars) return;
        var nodes = this.getNodes();
        for (var i=0; i< nodes.length; i++) {
            var node = nodes[i];
            if (node.hasParagraphsToolbarRendered) {
                continue;
            }
            node.hasParagraphsToolbarRendered = true;
            var tbCt = Ext.get(node).down('.kwc-paragraphs-toolbar');
            var tb = new Ext.Toolbar({
                renderTo: tbCt
            });
            var record = this.getRecord(node);

            this.configureToolbar(tb, record);
        }
    },
    configureToolbar: function(tb, record) {
        tb.add({
            //text: record.get('visible') ? trlKwf('visible') : trlKwf('invisible'),
            tooltip: trlKwf('visibility'),
            scope: this,
            record: record,
            handler: function(btn) {
                this.fireEvent('changeVisible', btn.record);
            },
            icon : '/assets/silkicons/'+(record.get('visible') ? 'tick' : 'cross') + '.png',
            cls  : 'x-btn-icon'
        });
        if (this.showDeviceVisible) {
            var deviceVisibleMenu = {
                menu: [{
                    text: trlKwf('show on all devices'),
                    icon: '/assets/kwf/images/devices/showAll.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'all');
                    }
                },{
                    text: trlKwf('hide on mobile devices'),
                    icon: '/assets/kwf/images/devices/smartphoneHide.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'hideOnMobile');
                    }
                },{
                    text: trlKwf('only show on mobile devices'),
                    icon: '/assets/kwf/images/devices/smartphone.png',
                    scope: this,
                    record: record,
                    handler: function(menu) {
                        this.fireEvent('changeDeviceVisible', menu.record, 'onlyShowOnMobile');
                    }
                }],
                cls  : 'x-btn-icon'
            };
            if (record.get('device_visible') == 'onlyShowOnMobile') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/smartphone.png';
            } else if (record.get('device_visible') == 'hideOnMobile') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/smartphoneHide.png';
            } else if (record.get('device_visible') == 'all') {
                deviceVisibleMenu.icon = '/assets/kwf/images/devices/showAll.png';
            }
            tb.add(deviceVisibleMenu);
        }

        if (this.showPosition) {
            var posCombo = new Kwf.Form.ComboBox({
                listClass: 'kwc-paragraphs-pos-list',
                tpl: '<tpl for=".">' +
                    '<div class="x-combo-list-item<tpl if="visible"> visible</tpl><tpl if="!visible"> invisible</tpl>">'+
                        '{pos} - {component_name}'+
                    '
'+
                    '</tpl>',
                displayField: 'pos',
                valueField: 'pos',
                store: this.store,
                editable: false,
                width: 50,
                triggerAction: 'all',
                mode: 'local',
                record: record,
                listWidth: 100,
                listeners: {
                    scope: this,
                    changevalue: function(v, combo) {
                        if (v && combo.record.get('pos') != v) {
                            this.fireEvent('changePos', combo.record, v);
                            combo.blur();
                            combo.hasFocus = false; //ansonsten wird die list angezeigt nachdem daten geladen wurden
                        }
                    }
                }
            });
            posCombo.setValue(record.get('pos'));
            tb.add(posCombo);
        } else {
            tb.add(record.get('pos'));
        }
        if (this.showDelete) {
            tb.add({
                tooltip: trlKwf('delete'),
                scope: this,
                record: record,
                handler: function(btn) {
                    this.fireEvent('delete', btn.record);
                },
                icon : '/assets/silkicons/bin.png',
                cls  : 'x-btn-icon'
            });
        }
        if (record.get('edit_components').length == 1) {
            tb.add('-');
            tb.add({
                text: trlKwf('edit'),
                scope: this,
                record: record,
                handler: function(btn) {
                    this.fireEvent('edit', btn.record, Kwf.clone(btn.record.get('edit_components')[0]));
                },
                icon : '/assets/silkicons/application_edit.png',
                cls  : 'x-btn-text-icon'
            });
        } else if (record.get('edit_components').length > 1) {
            tb.add('-');
            var menu = [];
            record.get('edit_components').forEach(function(ec) {
                var cfg = this.componentConfigs[ec.componentClass+'-'+ec.type];
                menu.push({
                    text: cfg.title,
                    icon: cfg.icon,
                    scope: this,
                    record: record,
                    editComponent: ec,
                    handler: function(menu) {
                        this.fireEvent('edit', menu.record, Kwf.clone(menu.editComponent));
                    }
                });
            }, this);
            tb.add({
                text: trlKwf('edit'),
                menu: menu,
                icon : '/assets/silkicons/application_edit.png',
                cls  : 'x-btn-text-icon'
            });
        }
        if (this.components) {
            tb.add('-');
            tb.add(new Kwc.Paragraphs.AddParagraphButton({
                record: record,
                components: this.components,
                componentIcons: this.componentIcons,
                listeners: {
                    scope: this,
                    menushow: function(btn) {
                        this.fireEvent('addParagraphMenuShow', btn.record);
                    },
                    addParagraph: function(component) {
                        this.fireEvent('addParagraph', component);
                    }
                }
            }));
            if (this.showCopyPaste) {
                tb.add({
                    text: trlKwf('copy/paste'),
                    menu: [{
                        text: trlKwf('Copy Paragraph'),
                        icon: '/assets/silkicons/page_white_copy.png',
                        scope: this,
                        record: record,
                        handler: function(btn) {
                            this.fireEvent('copyParagraph', btn.record);
                        }
                    },{
                        text: trlKwf('Paste Paragraph'),
                        icon: '/assets/silkicons/page_white_copy.png',
                        scope: this,
                        handler: function() {
                            this.fireEvent('pasteParagraph');
                        }
                    }],
                    icon: '/assets/silkicons/page_white_copy.png',
                    cls  : 'x-btn-text-icon',
                    record: record,
                    listeners: {
                        scope: this,
                        menushow: function(btn) {
                            this.fireEvent('copyPasteMenuShow', btn.record);
                        }
                    }
                });
            }
        }
        tb.add('->');
        tb.add(record.get('component_name'));
        tb.add('');
    }
});
<|endoftext|>


<commit_before>var responsiveEl = require('kwf/commonjs/responsive-el');
var onReady = require('kwf/commonjs/on-ready');

//remove largeText class if >55% of element is covered by image
onReady.onResize('.kwcClass', function textImage(el) {
    var img = el.find('.kwcBem__image .kwfUp-kwcImageContainer');
    if (img) {
        if (img.width() < (el.width() * 0.55)) {
            el.removeClass('kwcBem--largeImage');
            el.addClass('kwcBem--largeText');
        } else {
            el.removeClass('kwcBem--largeText');
            el.addClass('kwcBem--largeImage');
        }
    }
});
<commit_msg>TextImage: JS code to add gt420 class got accidently removed in 2015<commit_after>var responsiveEl = require('kwf/commonjs/responsive-el');
var onReady = require('kwf/commonjs/on-ready');

responsiveEl('.kwcClass', [420]);

//remove largeText class if >55% of element is covered by image
onReady.onResize('.kwcClass', function textImage(el) {
    var img = el.find('.kwcBem__image .kwfUp-kwcImageContainer');
    if (img) {
        if (img.width() < (el.width() * 0.55)) {
            el.removeClass('kwcBem--largeImage');
            el.addClass('kwcBem--largeText');
        } else {
            el.removeClass('kwcBem--largeText');
            el.addClass('kwcBem--largeImage');
        }
    }
});
<|endoftext|>


<commit_before>/* global window, setTimeout, document */
/* global define, require */
/* global describe, before, it, expect */
/* global Loader: true, $: true, _: true, container: true */
/* global TPL_TEST_IMPL, TPL_CONTENT, FN_CONTENT, TPL_TEST_IMPL_COUNT, repeat */
/* jshint multistr: true */
describe('Loader.boot(force)', function() {

    this.timeout(5000)

    // 其他变量和模块的定义在文件 `./test.loader.init.js` 中。
    before(function(done) {
        require(['brix/loader', 'jquery', 'underscore'], function() {
            window.Loader = Loader = arguments[0]
            $ = arguments[1]
            _ = arguments[2]
            container = $('#container')
            done()
        })
    })

    // record [ error, instance, index, count ]
    function expectRecord(record, recordIndex, recordCount) {
        expect(record).to.have.length(4)
        expect(record[0]).to.equal(undefined)
        expect(record[1]).to.have.property('render')
        expect(record[2]).to.equal(recordIndex)
        expect(record[3]).to.equal(recordCount)
    }

    function expectRecords(records, length) {
        expect(records).to.have.length(length)
        _.each(records, function(record, recordIndex) {
            expectRecord(record, recordIndex, records.length)
        })
    }

    var forced = 0
    define('outer', ['brix/loader', 'jquery'], function(Loader, $) {
        function outer() {}
        outer.prototype.render = function() {
            this.element.innerHTML = 'outer

'

            var defer = $.Deferred()
            Loader.boot(true, this.element, function(records) {
                forced++
                defer.resolve()
            })

            return defer.promise()
        }
        return outer
    })
    define('inner', ['brix/loader', 'jquery'], function(Loader, $) {
        function inner() {}
        inner.prototype.render = function() {
            this.element.innerHTML = 'inner'

            var defer = $.Deferred()
            Loader.boot(true, this.element, function(records) {
                forced++
                defer.resolve()
            })

            return defer.promise()
        }
        return inner
    })

    beforeEach(function(done) {
        forced = 0
        done()
    })

    // Go go go

    it('Loader.boot(true)', function(done) {
        container.append('
</hello>')
        Loader.boot(function() {
            expect(forced).to.equal(2)
            Loader.destroy(container, done)
        })
    })
})<commit_msg>fix jshint<commit_after>/* global window */
/* global define, require */
/* global describe, before, beforeEach, it, expect */
/* global Loader: true, $: true, _: true, container: true */
/* jshint multistr: true */
describe('Loader.boot(force)', function() {

    this.timeout(5000)

    // 其他变量和模块的定义在文件 `./test.loader.init.js` 中。
    before(function(done) {
        require(['brix/loader', 'jquery', 'underscore'], function() {
            window.Loader = Loader = arguments[0]
            $ = arguments[1]
            _ = arguments[2]
            container = $('#container')
            done()
        })
    })

    // record [ error, instance, index, count ]
    function expectRecord(record, recordIndex, recordCount) {
        expect(record).to.have.length(4)
        expect(record[0]).to.equal(undefined)
        expect(record[1]).to.have.property('render')
        expect(record[2]).to.equal(recordIndex)
        expect(record[3]).to.equal(recordCount)
    }

    function expectRecords(records, length) {
        expect(records).to.have.length(length)
        _.each(records, function(record, recordIndex) {
            expectRecord(record, recordIndex, records.length)
        })
    }

    var forced = 0
    define('outer', ['brix/loader', 'jquery'], function(Loader, $) {
        function outer() {}
        outer.prototype.render = function() {
            this.element.innerHTML = 'outer

'

            var defer = $.Deferred()
            Loader.boot(true, this.element, function(records) {
                forced++
                expectRecords(records, 2)
                defer.resolve()
            })

            return defer.promise()
        }
        return outer
    })
    define('inner', ['brix/loader', 'jquery'], function(Loader, $) {
        function inner() {}
        inner.prototype.render = function() {
            this.element.innerHTML = 'inner'

            var defer = $.Deferred()
            Loader.boot(true, this.element, function(records) {
                forced++
                expectRecords(records, 1)
                defer.resolve()
            })

            return defer.promise()
        }
        return inner
    })

    beforeEach(function(done) {
        forced = 0
        done()
    })

    // Go go go

    it('Loader.boot(true)', function(done) {
        container.append('
</hello>')
        Loader.boot(function(records) {
            expect(forced).to.equal(2)
            expectRecords(records, 1)
            Loader.destroy(container, done)
        })
    })
})<|endoftext|>


<commit_before>'use strict';
var chai = require('chai');
var should = chai.should();

var SignatureValidator = require('../lib/SignatureValidator');

describe('SignatureValidator', function() {
  var config = {
    channelID: '1441301333',
    channelSecret: 'testsecret',
    channelMID: 'u0a556cffd4da0dd89c94fb36e36e1cdc'
  };

  var json = {
    result: [
      {
        from: 'u206d25c2ea6bd87c17655609a1c37cb8',
        fromChannel: '1341301815',
        to: ['u0cc15697597f61dd8b01cea8b027050e'],
        toChannel: '1441301333',
        eventType: '138311609000106303',
        id: 'ABCDEF-12345678901',
        content: {
          id: '325708',
          createdTime: 1332394961610,
          from: 'uff2aec188e58752ee1fb0f9507c6529a',
          to: ['u0a556cffd4da0dd89c94fb36e36e1cdc'],
          toType: 1,
          contentType: 1,
          text: 'hello'
        }
      },
      {
        from: 'u206d25c2ea6bd87c17655609a1c37cb8',
        fromChannel: '1341301815',
        to: ['u0cc15697597f61dd8b01cea8b027050e'],
        toChannel: '1441301333',
        eventType: '138311609100106403',
        id: 'ABCDEF-12345678902',
        content: {
          revision: 2469,
          opType: 4,
          params: [
            'u0f3bfc598b061eba02183bfc5280886a',
            null,
            null
          ]
        }
      }
    ]
  };

  var signature = 'kPXp0nPWSzfWAapWHiesbcztpKnXJoX8krCa1CcTghk=';

  it('should be able to validate signature', function(done) {
    SignatureValidator.validateSignature(JSON.stringify(json), config.channelSecret, signature).should.be.true;
    SignatureValidator.validateSignature(JSON.stringify(json), config.channelSecret, 'XXX').should.be.false;

    done();
  });
});
<commit_msg>fix tests<commit_after>'use strict';
var chai = require('chai');
var should = chai.should();

var SignatureValidator = require('../lib/SignatureValidator');

describe('SignatureValidator', function() {
  var config = {
    channelID: '1441301333',
    channelSecret: 'testsecret',
    channelMID: 'u0a556cffd4da0dd89c94fb36e36e1cdc'
  };
  var json = '{\n\
  "result":[\n\
    {\n\
      "from":"u206d25c2ea6bd87c17655609a1c37cb8",\n\
      "fromChannel":"1341301815",\n\
      "to":["u0cc15697597f61dd8b01cea8b027050e"],\n\
      "toChannel":"1441301333",\n\
      "eventType":"138311609000106303",\n\
      "id":"ABCDEF-12345678901",\n\
      "content":{\n\
        "id":"325708",\n\
        "createdTime":1332394961610,\n\
        "from":"uff2aec188e58752ee1fb0f9507c6529a",\n\
        "to":["u0a556cffd4da0dd89c94fb36e36e1cdc"],\n\
        "toType":1,\n\
        "contentType":1,\n\
        "text":"hello"\n\
      }\n\
    },\n\
    {\n\
      "from":"u206d25c2ea6bd87c17655609a1c37cb8",\n\
      "fromChannel":"1341301815",\n\
      "to":["u0cc15697597f61dd8b01cea8b027050e"],\n\
      "toChannel":"1441301333",\n\
      "eventType":"138311609100106403",\n\
      "id":"ABCDEF-12345678902",\n\
      "content":{\n\
        "revision":2469,\n\
        "opType":4,\n\
        "params":[\n\
          "u0f3bfc598b061eba02183bfc5280886a",\n\
          null,\n\
          null\n\
        ]\n\
      }\n\
    }\n\
  ]\n\
}';

  var signature = 'kPXp0nPWSzfWAapWHiesbcztpKnXJoX8krCa1CcTghk=';

  it('should be able to validate signature', function(done) {
    SignatureValidator.validateSignature(json, config.channelSecret, signature).should.be.true;
    SignatureValidator.validateSignature(json, config.channelSecret, 'XXX').should.be.false;
    done();
  });
});
<|endoftext|>


<commit_before>/**
 * @module syncRegistry
 *
 * @description
 * Прокидывает на клиент чё-нибудь: если записать сюда что-нибудь на сервере, потом можно прочитать это на клиенте
 * Логика сериализации и вставки данных в html пока реализуется в конечном приложении
 * ```js
 * var syncRegistry = slot.requireComponent('syncRegistry');
 * ```
 */
var env = require('../env');

module.exports = function(app) {
    var registry = {};

    /**
     * Возвращает значение. Если значение не было задано, возвращает пустой объект
     * @param  {String} key   ключ по которому будет возвращено значение
     * @param  {*}      def   дефолтное значение, которое будет возвращено, если по ключу ничего нет. @TODO выяснить, действительно ли он нужен
     * @return {*}            значение, сохранённое по этому ключу, либо undefined
     */
    function get(key, def) {
        def = def === undefined ? {} : def;

        return key in registry ? registry[key] : def;
    }

    /**
     * Сохраняет значение в реестр
     * @param  {String} key   ключ, по которому будет сохранено значение
     * @param  {*}      value сохраняемое значение
     * @return {*}            сохранённое значение
     */
    function save(key, value) {
        return registry[key] = value;
    }

    var syncRegistry = {
        get: get,
        save: save,

        /**
         * Загружает реестр, например, переданный с сервера на клиент
         * @param  {Object} reg объект реестра со всеми ключами и значениями
         */
        load: function(reg) {
            registry = reg;
        },

        /**
         * На сервере работает как сеттер, на клиенте как геттер
         * @type {[type]}
         */
        sync: env.isServer ? save : get
    };

    return syncRegistry;
};
<commit_msg>fix/syncRegistry<commit_after>/**
 * @module syncRegistry
 *
 * @description
 * Прокидывает на клиент чё-нибудь: если записать сюда что-нибудь на сервере, потом можно прочитать это на клиенте
 * Логика сериализации и вставки данных в html пока реализуется в конечном приложении
 * ```js
 * var syncRegistry = slot.requireComponent('syncRegistry');
 * ```
 */
var env = require('../env');

module.exports = function(app) {
    var registry = {};

    /**
     * Возвращает значение. Если значение не было задано, возвращает пустой объект
     * @param  {String} key         ключ по которому будет возвращено значение
     * @param  {*}      syncValue   дефолтное значение, которое будет возвращено, если по ключу ничего нет. @TODO выяснить, действительно ли он нужен
     * @return {*}                  значение, сохранённое по этому ключу, либо undefined
     */
    function get(key, syncValue) {
        return registry[key];
    }

    /**
     * Сохраняет значение в реестр
     * @param  {String} key   ключ, по которому будет сохранено значение
     * @param  {*}      value сохраняемое значение
     * @return {*}            сохранённое значение
     */
    function save(key, value) {
        return registry[key] = value;
    }

    var syncRegistry = {
        get: get,
        save: save,

        /**
         * Возвращает весь реестр, например на сервере для записи его в шаблон и передачи на клиент
         * @return {Object} registry объект реестра со всеми ключами и значениями
         */
        read: function() {
            return registry;
        },

        /**
         * Загружает реестр, например, переданный с сервера на клиент
         * @param  {Object} reg объект реестра со всеми ключами и значениями
         */
        load: function(reg) {
            registry = reg;
        },

        /**
         * На сервере работает как сеттер, на клиенте как геттер. На клиенте возвращает значение, выставленное на сервере.
         * @param  {String} key             ключ по которому синхронизируется значение
         * @param  {*} [serverSideValue={}] значение, выставляемое на сервере, на клиенте оно игнорируется
         * @return {*}                      значение по ключу
         */
        sync: function(key, serverSideValue) {
            if (env.isServer) {
                serverSideValue = serverSideValue === undefined ? {} : serverSideValue;

                return syncRegistry.save(key, serverSideValue);
            } else {
                var value = syncRegistry.get(key);

                if (value === undefined && serverSideValue !== undefined) { // Ситуация, когда sync дёргается на клиенте, но не был дёрнут на сервере
                    throw new Error('[slot syncRegistry.sync] you are trying to get the value of registry[' + key +
                        '] on the client via sync(), but that value wasnt setted on the server!');
                }

                return value;
            }
        }
    };

    return syncRegistry;
};
<|endoftext|>


<commit_before>/**
 * Created by Samer on 2016-03-22.
 */
<commit_msg>Delete tradeControl.js<commit_after><|endoftext|>


<commit_before>import $ from 'jquery';
import { saveAs } from 'file-saver';

import { download as downloadEOWCS, getDownloadUrl as getDownloadUrlEOWCS } from './eowcs';
import { download as downloadUrl, getDownloadUrl as getDownloadUrlUrl } from './url';

export function downloadRecord(layerModel, filtersModel, recordModel, options, elementContainer) {
  let element = null;
  if (layerModel.get('download.protocol') === 'EO-WCS') {
    element = downloadEOWCS(layerModel, filtersModel, recordModel, options);
  } else {
    // element = downloadUrl(recordModel);
    const a = document.createElement('a');
    if (typeof a.download !== 'undefined') {
      const url = getDownloadUrlUrl(recordModel);
      a.style.display = 'none';
      a.target = '_blank';
      a.setAttribute('href', url);

      document.body.appendChild(a);
      a.click();

      setTimeout(() => document.body.removeChild(a));

      return null;
    }
    element = downloadUrl(recordModel);
  }

  // TODO: other download implementations
  if (element) {
    const $element = $(element);

    if (elementContainer) {
      $(elementContainer).append($element);
    }
    if ($element.is('form')) {
      $element.submit();
    }
  }
  return element;
}

export function downloadCustom(filename, mediaType, content) {
  saveAs(new Blob([content], { type: mediaType }), filename);
}

export function getDownloadUrl(layerModel, filtersModel, recordModel, options) {
  if (layerModel.get('download.protocol') === 'EO-WCS') {
    return getDownloadUrlEOWCS(layerModel, filtersModel, recordModel, options);
  }
  return getDownloadUrlUrl(recordModel);
}
<commit_msg>Trying to fix downloading issues in Chrome.<commit_after>import $ from 'jquery';
import { saveAs } from 'file-saver';

import { download as downloadEOWCS, getDownloadUrl as getDownloadUrlEOWCS } from './eowcs';
import { download as downloadUrl, getDownloadUrl as getDownloadUrlUrl } from './url';

export function downloadRecord(layerModel, filtersModel, recordModel, options, elementContainer) {
  let element = null;
  if (layerModel.get('download.protocol') === 'EO-WCS') {
    element = downloadEOWCS(layerModel, filtersModel, recordModel, options);
  } else {
    // element = downloadUrl(recordModel);
    const a = document.createElement('a');
    if (typeof a.download !== 'undefined') {
      const url = getDownloadUrlUrl(recordModel);
      a.style.display = 'none';
      a.setAttribute('target', '_blank');
      a.setAttribute('href', url);
      a.setAttribute('rel', 'noopener noreferrer');

      document.body.appendChild(a);
      a.click();

      setTimeout(() => document.body.removeChild(a), 10000);

      return null;
    }
    element = downloadUrl(recordModel);
  }

  // TODO: other download implementations
  if (element) {
    const $element = $(element);

    if (elementContainer) {
      $(elementContainer).append($element);
    }
    if ($element.is('form')) {
      $element.submit();
    }
  }
  return element;
}

export function downloadCustom(filename, mediaType, content) {
  saveAs(new Blob([content], { type: mediaType }), filename);
}

export function getDownloadUrl(layerModel, filtersModel, recordModel, options) {
  if (layerModel.get('download.protocol') === 'EO-WCS') {
    return getDownloadUrlEOWCS(layerModel, filtersModel, recordModel, options);
  }
  return getDownloadUrlUrl(recordModel);
}
<|endoftext|>


<commit_before>// Description:
//   Enables knowing what pull requests are stale via Drill Sergeant.
//
// Dependencies:
//   "drill-sergeant": "*"
//   "node-schedule": "*"
//
// Configuration:
//   HUBOT_DRILL_SERGEANT_GITHUB_TOKEN
//   HUBOT_DRILL_SERGEANT_STALE_TIME
//   HUBOT_DRILL_SERGEANT_REPOS
//   HUBOT_DRILL_SERGEANT_SCHEDULE (optional)
//   HUBOT_DRILL_SERGEANT_ROOM (optional)
//
// Commands:
//   hubot what prs are stale? - Shows all pull requests that are stale.
//
// Author:
//   cjsaylor

var githubClient = require('drill-sergeant/lib/github');
var staleRepos = require('drill-sergeant/lib/stalerepos');
var schedule = require('node-schedule');

module.exports = function(robot) {
	var token = process.env.HUBOT_DRILL_SERGEANT_GITHUB_TOKEN;
	var staleTime = process.env.HUBOT_DRILL_SERGEANT_STALE_TIME || 24;
	var repos = (process.env.HUBOT_DRILL_SERGEANT_REPOS || []).split(',');
	var crontab = process.env.HUBOT_DRILL_SERGEANT_SCHEDULE || '10 * * * *';
	var announcementRoom = process.env.HUBOT_DRILL_SERGEANT_ROOM;
	var client;

	// Setup
	if (!token) {
		robot.logger.error('Drill-sergeant: No github token specified.');
		return;
	}
	client = new githubClient(token);
	if (!repos.length) {
		robot.logger.error('Drill-sergeant: No repos specified.');
	}

	var brainCache = function(key, value, expires) {
		robot.brain.set(key, value);
		setTimeout(robot.brain.remove.bind(robot.brain, key), expires || 1000 * 60);
	};

	var broadcastStale = function(sender, staleRepos) {
		var output = [];
		staleRepos.forEach(function(result) {
			output.push(result.repo + ':');
			result.prs.forEach(function(pr) {
				output.push('' + pr.title + ' (' + pr.user + ')');
			});
		});
		sender(output.join('\n'));
	};

	var retrievePrs = function(callback) {
		var cacheKey = 'drill-sergeant.stalePrs';
		results = robot.brain.get(cacheKey);
		if (results) {
			callback(results);
			return;
		}
		staleRepos.retrieve(repos, client, staleTime, function(results) {
			brainCache(cacheKey, results);
			callback(results);
		});
	};

	// Robot tasks

	robot.respond(/what prs are stale/i, function(msg) {
		retrievePrs(broadcastStale.bind(null, msg.send.bind(msg)));
	});

	if (!announcementRoom) {
		robot.logger.warning('Drill-sergeant: No room specified, therefore not scheduling stale announcements.');
	} else {
		schedule.scheduleJob(crontab, function() {
			retrievePrs(broadcastStale.bind(null, robot.messageRoom.bind(robot, announcementRoom)));
		});
	}

};
<commit_msg>Removed HTML markup from messages.<commit_after>// Description:
//   Enables knowing what pull requests are stale via Drill Sergeant.
//
// Dependencies:
//   "drill-sergeant": "*"
//   "node-schedule": "*"
//
// Configuration:
//   HUBOT_DRILL_SERGEANT_GITHUB_TOKEN
//   HUBOT_DRILL_SERGEANT_STALE_TIME
//   HUBOT_DRILL_SERGEANT_REPOS
//   HUBOT_DRILL_SERGEANT_SCHEDULE (optional)
//   HUBOT_DRILL_SERGEANT_ROOM (optional)
//
// Commands:
//   hubot what prs are stale? - Shows all pull requests that are stale.
//
// Author:
//   cjsaylor

var githubClient = require('drill-sergeant/lib/github');
var staleRepos = require('drill-sergeant/lib/stalerepos');
var schedule = require('node-schedule');

module.exports = function(robot) {
	var token = process.env.HUBOT_DRILL_SERGEANT_GITHUB_TOKEN;
	var staleTime = process.env.HUBOT_DRILL_SERGEANT_STALE_TIME || 24;
	var repos = (process.env.HUBOT_DRILL_SERGEANT_REPOS || []).split(',');
	var crontab = process.env.HUBOT_DRILL_SERGEANT_SCHEDULE || '10 * * * *';
	var announcementRoom = process.env.HUBOT_DRILL_SERGEANT_ROOM;
	var client;

	// Setup
	if (!token) {
		robot.logger.error('Drill-sergeant: No github token specified.');
		return;
	}
	client = new githubClient(token);
	if (!repos.length) {
		robot.logger.error('Drill-sergeant: No repos specified.');
	}

	var brainCache = function(key, value, expires) {
		robot.brain.set(key, value);
		setTimeout(robot.brain.remove.bind(robot.brain, key), expires || 1000 * 60);
	};

	var broadcastStale = function(sender, staleRepos) {
		var output = [];
		staleRepos.forEach(function(result) {
			output.push(result.repo + ':');
			result.prs.forEach(function(pr) {
				output.push(pr.title + '(' + pr.user + ') ' + pr.html_url);
			});
		});
		sender(output.join('\n'));
	};

	var retrievePrs = function(callback) {
		var cacheKey = 'drill-sergeant.stalePrs';
		results = robot.brain.get(cacheKey);
		if (results) {
			callback(results);
			return;
		}
		staleRepos.retrieve(repos, client, staleTime, function(results) {
			brainCache(cacheKey, results);
			callback(results);
		});
	};

	// Robot tasks

	robot.respond(/what prs are stale/i, function(msg) {
		retrievePrs(broadcastStale.bind(null, msg.send.bind(msg)));
	});

	if (!announcementRoom) {
		robot.logger.warning('Drill-sergeant: No room specified, therefore not scheduling stale announcements.');
	} else {
		schedule.scheduleJob(crontab, function() {
			retrievePrs(broadcastStale.bind(null, robot.messageRoom.bind(robot, announcementRoom)));
		});
	}

};
<|endoftext|>


<commit_before>module.exports = {
  name: "",
  project: "",
  year: "",
  size: "",
  industry: "",
  color: "#",
  role: "",
  url: "",
  services: [
    "",
  ],
  technologies: [
    "",
  ],
  overview: "",
  lede: "",
  cover: "  ",
  caption: "",
  people: {
    [1]: {
      name: ""
    }
  },
  name: "",
  people: {
    [1]: {
      position: "",
    }
  },
  testimonials: {
    [1]: {
      person_id: 1,
      content: ""
    }
  },
  assets: {
    link: "",
    shot_link: "",
    image: "",
    video: "",
    asset_transform: "f_auto,q_auto",
    title: "",
    caption: ""
  }
}<commit_msg>Update portfolio template<commit_after>module.exports = {
  template: true,
  featured: true/false,
  name: "",
  project: "",
  year: "",
  size: "",
  industry: "",
  color: "#",
  role: "",
  url: "",
  services: [
    "",
  ],
  technologies: [
    "",
  ],
  caption: "",
  overview: "",
  lede: "",
  cover: "",
  pillars: {
    client: "",
    challenge: "",
    solution: "",
  },
  people: {
    [1]: {
      name: "",
      position: "",
      url: "",
      image: "",
    }
  },
  testimonials: {
    [1]: {
      person_id: 1,
      content: ""
    }
  },
  assets: {
    link: "",
    shot_link: "",
    image: "",
    video: "",
    asset_transform: "f_auto,q_auto",
    title: "",
    caption: ""
  }
}<|endoftext|>


<commit_before>'use strict';

import props from './props';
import './view.html';
import { dashify, viewLabel } from './../_libs/utils';
import { isNil, isNilOrEmptyStr, randomId, propLowerCase } from './libs';
import "./../input/";
import "./../note/";
import "./../curtain/";
import './../_libs/path';

class DropdownClab {

  get behaviors() {
    return [{ _isNilOrEmptyStr: isNilOrEmptyStr, dashify, viewLabel }];
  }

  beforeRegister() {
    this.is = "dropdown-clab";
    this.properties = props;
    this.observers = [
      '_triggerFetchOptions(url)',
      '_setOptions(optionsFn)'
    ]
  }

  attached() {
    if(isNilOrEmptyStr(this.id)){
      this.set('id', randomId());
    }
  }

  _setSearchValue(evt) {
    this.set('searchValue', evt.target.value);
  }

  /*----------
  EVENT HANDLERS
  ----------*/
  _handleSelect(evt) {
    const selected = this._optionsVisible[evt.detail.index];
    const oldValue = this.selected;

    this.set('selected', selected);
    this.set('highlighted', selected);
    this.set('open', false);
    this.set('searchValue', null);

    if(!this.preventChange) {
      if(this.resultAsObj){
        return this.dispatchEvent(new CustomEvent('change', {
          bubbles: true,
          composed: true,
          detail: {
            selected,
            newValue: selected,
            oldValue
          }
        }));
      }

      return this.dispatchEvent(new CustomEvent('change', {
        bubbles: true,
        composed: true,
        detail: {
          selected: selected[this.valueField],
          newValue: selected,
          oldValue
        }
      }));
    }
  }

  _handleHighlight(evt) {
    this.set('highlighted', this._optionsVisible[evt.detail.index]);
  }

  _stop(evt) {
    evt.stopPropagation();
  }

  /*----------
  METHODS
  ----------*/
  _fetchOptions() {
    fetch(this.url, {
      method: 'GET'
    }).then(res => {
      if(res.status !== 200) {
        console.warn('Looks like there was a problem. Status Code: ' + res.status);
        this.type = 'error';
        return;
      }

      res.json().then((data) => {
        this.set('options', data);
      });

    }).catch(err => {
      console.error("Fetch Error ==> ", err);
      this.type = 'error';
    });
  }

  /*----------
  OBSERVERS
  ----------*/
  _setOptions(promise) {
    if(!isNil(promise)) {
      promise().then(resp => this.set('options', resp));
    }
  }

  _triggerFetchOptions(url) {
    if(!isNil(url)) {
      this._fetchOptions();
    }
  }

  /*----------
  COMPUTED
  ----------*/
  _updateVisibleOptions(options, searchValue, labelField) {
    if(!isNil(options) && options.constructor === Array) {
      const toSearch = !isNilOrEmptyStr(searchValue)
        ? searchValue.toLowerCase()
        : '';
      const optionsVisible = options.filter(o => propLowerCase(o, labelField).search(toSearch) > -1);
      return optionsVisible;
    }
    return [];
  }

  _compIcon(icon) {
    return !isNilOrEmptyStr(icon)
      ? `clab-icon ${icon}`
      : '';
  }

  _compWrapperType(disabled, type, inline, labelSize) {
    let arr = [];

    if(disabled){
      arr.push('disabled');
    }
    if(!isNilOrEmptyStr(type)){
      arr.push(type);
    }
    if(inline) {
      arr.push('inline');
      if(!isNilOrEmptyStr(labelSize)){
        arr.push(`${labelSize}-label`);
      }
    }

    return arr.join(' ');
  }

  _compType(disabled, type, id) {
    let arr = [];

    if(!isNilOrEmptyStr(id)){
      arr.push(id);
    }
    if(disabled){
      arr.push('disabled');
    }
    if(!isNilOrEmptyStr(type)){
      arr.push(type);
    }

    return arr.join(' ');
  }

  _compSelectedLabel(option, label) {
    return !isNil(option) && !isNilOrEmptyStr(label)
      ? option[label]
      : null;
  }

  _compLabelClass(selectedLabel, placeholder) {
    return !isNilOrEmptyStr(selectedLabel)
      ? 'selected'
      : 'placeholder';
  }

  _compLabelVisible(selectedLabel, placeholder) {
    return !isNilOrEmptyStr(selectedLabel)
    ? selectedLabel
    : placeholder;
  }

  _compMaxHeight(height) {
    return !isNil(height)
      ? height
      : '';
  }

  _compToggleList(disabled, id) {
    return evt => {

      if (!disabled) {
        const isSpan = e => e.target.localName === 'span' && e.path[4] && e.path[4].id === id;
        const isDiv = e => e.target.localName === 'div' && e.path[3] && e.path[3].id === id;
        const isInput = e => e.target.localName === 'input' && e.path[3] && e.path[3].id === id;

        if((isSpan(evt) || isDiv(evt))){
          this.set('open', !this.open);
        }

        if(isInput(evt) && !this.open) {
          this.set('open', true);
        }

        const windowClick = evt => {
          const isOl = e => e.target.localName === 'ol' && e.target.classList.contains('curtain-clab');
          const isLi = e => e.target.localName === 'li' && e.target.classList.contains('curtain-clab');

          if(isLi(evt) || isDiv(evt) || isSpan(evt)) {
            return window.removeEventListener('mousedown', windowClick);
          }

          if(isOl(evt) || isInput(evt)) {
            return;
          }

          this.set('open', false);
          this.set('searchValue', null);
          return window.removeEventListener('mousedown', windowClick);
        }

        if(!this.open) {
          this.set('searchValue', null);
        }
        return window.addEventListener('mousedown', windowClick);
      }
    }
  }

  _compSearchVisibleValue(searchValue, selectedLabel) {
    if(!isNilOrEmptyStr(selectedLabel)) {
      return isNil(searchValue)
        ? selectedLabel
        : searchValue
    }

    return searchValue;
  }

  getSelectedLabel() {
    return this.selected[this.labelField];
  }

  getSelectedValue() {
    return this.selected[this.valueField];
  }

  setByLabel(str) {
    this.options.map(opt => {
      if (opt[this.labelField] === str) {
        this._setSelected(opt);
        return;
      }
    });
  }

  setByValue(str) {
    this.options.map(opt => {
      if (opt[this.valueField] === str) {
        this._setSelected(opt);
        return;
      }
    });
  }

  isValorized() {
    return !this.isNotValorized();
  }

  isNotValorized() {
    return this.selected === undefined ||
      this.selected === null ||
      this.selected[this.valueField] === undefined ||
      this.selected[this.valueField] === null;
  }

  setValue(obj, prevent) {
    prevent = prevent ? true : false;
    this.preventChange = prevent;

    if (typeof obj === 'object') {
      this._setSelected(obj);
    } else {
      this.options.map(opt => {
        if (opt[this.valueField] === obj) {
          this._setSelected(opt);
          return;
        }
      });
    }

    this.preventChange = false;
  }

  getValue() {
    var v;
    if (this.isNotValorized()) {
      v = undefined;
    } else if (typeof this.selected === 'string' || this.selected instanceof String) {
      v = this.selected;
    } else if (typeof this.selected === "object") {
      v = this.selected[this.valueField];
    } else {
      console.error(this.is + ": Invalid value type [" + (typeof this.selected) + "]");
    }
    return v;
  }

  getValueObject() {
    var v;
    if (this.isNotValorized(this.selected)) {
      v = undefined;
    } else if (typeof this.selected === 'string' || this.selected instanceof String) {
      this.options.map(opt => {
        if (opt[this.valueField] === this.selected) {
          v = opt;
          return;
        }
      });
      if (v === undefined) {
        console.warn(this.is + ": There is no option with value equal to [" + this.selected + "]");
      }
    } else if (typeof this.selected === "object") {
      v = this.selected;
    } else {
      console.warn(this.is + ": Invalid value type [" + (typeof this.selected) + "]");
    }
    return v;
  }
}

Polymer(DropdownClab);
<commit_msg>fixed _setSelected is not a function (#180)<commit_after>'use strict';

import props from './props';
import './view.html';
import { dashify, viewLabel } from './../_libs/utils';
import { isNil, isNilOrEmptyStr, randomId, propLowerCase } from './libs';
import "./../input/";
import "./../note/";
import "./../curtain/";
import './../_libs/path';

class DropdownClab {

  get behaviors() {
    return [{ _isNilOrEmptyStr: isNilOrEmptyStr, dashify, viewLabel }];
  }

  beforeRegister() {
    this.is = "dropdown-clab";
    this.properties = props;
    this.observers = [
      '_triggerFetchOptions(url)',
      '_setOptions(optionsFn)'
    ]
  }

  attached() {
    if(isNilOrEmptyStr(this.id)){
      this.set('id', randomId());
    }
  }

  _setSearchValue(evt) {
    this.set('searchValue', evt.target.value);
  }

  /*----------
  EVENT HANDLERS
  ----------*/
  _handleSelect(evt) {
    const selected = this._optionsVisible[evt.detail.index];
    const oldValue = this.selected;

    this.set('selected', selected);
    this.set('highlighted', selected);
    this.set('open', false);
    this.set('searchValue', null);

    if(!this.preventChange) {
      if(this.resultAsObj){
        return this.dispatchEvent(new CustomEvent('change', {
          bubbles: true,
          composed: true,
          detail: {
            selected,
            newValue: selected,
            oldValue
          }
        }));
      }

      return this.dispatchEvent(new CustomEvent('change', {
        bubbles: true,
        composed: true,
        detail: {
          selected: selected[this.valueField],
          newValue: selected,
          oldValue
        }
      }));
    }
  }

  _handleHighlight(evt) {
    this.set('highlighted', this._optionsVisible[evt.detail.index]);
  }

  _stop(evt) {
    evt.stopPropagation();
  }

  /*----------
  METHODS
  ----------*/
  _fetchOptions() {
    fetch(this.url, {
      method: 'GET'
    }).then(res => {
      if(res.status !== 200) {
        console.warn('Looks like there was a problem. Status Code: ' + res.status);
        this.type = 'error';
        return;
      }

      res.json().then((data) => {
        this.set('options', data);
      });

    }).catch(err => {
      console.error("Fetch Error ==> ", err);
      this.type = 'error';
    });
  }

  /*----------
  OBSERVERS
  ----------*/
  _setOptions(promise) {
    if(!isNil(promise)) {
      promise().then(resp => this.set('options', resp));
    }
  }

  _triggerFetchOptions(url) {
    if(!isNil(url)) {
      this._fetchOptions();
    }
  }

  /*----------
  COMPUTED
  ----------*/
  _updateVisibleOptions(options, searchValue, labelField) {
    if(!isNil(options) && options.constructor === Array) {
      const toSearch = !isNilOrEmptyStr(searchValue)
        ? searchValue.toLowerCase()
        : '';
      const optionsVisible = options.filter(o => propLowerCase(o, labelField).search(toSearch) > -1);
      return optionsVisible;
    }
    return [];
  }

  _compIcon(icon) {
    return !isNilOrEmptyStr(icon)
      ? `clab-icon ${icon}`
      : '';
  }

  _compWrapperType(disabled, type, inline, labelSize) {
    let arr = [];

    if(disabled){
      arr.push('disabled');
    }
    if(!isNilOrEmptyStr(type)){
      arr.push(type);
    }
    if(inline) {
      arr.push('inline');
      if(!isNilOrEmptyStr(labelSize)){
        arr.push(`${labelSize}-label`);
      }
    }

    return arr.join(' ');
  }

  _compType(disabled, type, id) {
    let arr = [];

    if(!isNilOrEmptyStr(id)){
      arr.push(id);
    }
    if(disabled){
      arr.push('disabled');
    }
    if(!isNilOrEmptyStr(type)){
      arr.push(type);
    }

    return arr.join(' ');
  }

  _compSelectedLabel(option, label) {
    return !isNil(option) && !isNilOrEmptyStr(label)
      ? option[label]
      : null;
  }

  _compLabelClass(selectedLabel, placeholder) {
    return !isNilOrEmptyStr(selectedLabel)
      ? 'selected'
      : 'placeholder';
  }

  _compLabelVisible(selectedLabel, placeholder) {
    return !isNilOrEmptyStr(selectedLabel)
    ? selectedLabel
    : placeholder;
  }

  _compMaxHeight(height) {
    return !isNil(height)
      ? height
      : '';
  }

  _compToggleList(disabled, id) {
    return evt => {

      if (!disabled) {
        const isSpan = e => e.target.localName === 'span' && e.path[4] && e.path[4].id === id;
        const isDiv = e => e.target.localName === 'div' && e.path[3] && e.path[3].id === id;
        const isInput = e => e.target.localName === 'input' && e.path[3] && e.path[3].id === id;

        if((isSpan(evt) || isDiv(evt))){
          this.set('open', !this.open);
        }

        if(isInput(evt) && !this.open) {
          this.set('open', true);
        }

        const windowClick = evt => {
          const isOl = e => e.target.localName === 'ol' && e.target.classList.contains('curtain-clab');
          const isLi = e => e.target.localName === 'li' && e.target.classList.contains('curtain-clab');

          if(isLi(evt) || isDiv(evt) || isSpan(evt)) {
            return window.removeEventListener('mousedown', windowClick);
          }

          if(isOl(evt) || isInput(evt)) {
            return;
          }

          this.set('open', false);
          this.set('searchValue', null);
          return window.removeEventListener('mousedown', windowClick);
        }

        if(!this.open) {
          this.set('searchValue', null);
        }
        return window.addEventListener('mousedown', windowClick);
      }
    }
  }

  _compSearchVisibleValue(searchValue, selectedLabel) {
    if(!isNilOrEmptyStr(selectedLabel)) {
      return isNil(searchValue)
        ? selectedLabel
        : searchValue
    }

    return searchValue;
  }

  getSelectedLabel() {
    return this.selected[this.labelField];
  }

  getSelectedValue() {
    return this.selected[this.valueField];
  }

  setByLabel(str) {
    this.options.map(opt => {
      if (opt[this.labelField] === str) {
        this.set('selected', opt);
        return;
      }
    });
  }

  setByValue(str) {
    this.options.map(opt => {
      if (opt[this.valueField] === str) {
        this.set('selected', opt);
        return;
      }
    });
  }

  isValorized() {
    return !this.isNotValorized();
  }

  isNotValorized() {
    return this.selected === undefined ||
      this.selected === null ||
      this.selected[this.valueField] === undefined ||
      this.selected[this.valueField] === null;
  }

  setValue(obj, prevent) {
    prevent = prevent ? true : false;
    this.preventChange = prevent;

    if (typeof obj === 'object') {
      this.set('selected', obj);
    } else {
      this.options.map(opt => {
        if (opt[this.valueField] === obj) {
          this.set('selected', opt);
          return;
        }
      });
    }

    this.preventChange = false;
  }

  getValue() {
    var v;
    if (this.isNotValorized()) {
      v = undefined;
    } else if (typeof this.selected === 'string' || this.selected instanceof String) {
      v = this.selected;
    } else if (typeof this.selected === "object") {
      v = this.selected[this.valueField];
    } else {
      console.error(this.is + ": Invalid value type [" + (typeof this.selected) + "]");
    }
    return v;
  }

  getValueObject() {
    var v;
    if (this.isNotValorized(this.selected)) {
      v = undefined;
    } else if (typeof this.selected === 'string' || this.selected instanceof String) {
      this.options.map(opt => {
        if (opt[this.valueField] === this.selected) {
          v = opt;
          return;
        }
      });
      if (v === undefined) {
        console.warn(this.is + ": There is no option with value equal to [" + this.selected + "]");
      }
    } else if (typeof this.selected === "object") {
      v = this.selected;
    } else {
      console.warn(this.is + ": Invalid value type [" + (typeof this.selected) + "]");
    }
    return v;
  }
}

Polymer(DropdownClab);
<|endoftext|>