<commit_before>var DoublyLinkedList = require('yallist');

function StaleLRU(options) {
    if (!(this instanceof StaleLRU)) {
        return new StaleLRU(options);
    }

    if (typeof options === 'number') {
        options = { maxSize: options };
    } else if (!options) {
        options = {};
    }

    this._lruList = new DoublyLinkedList(); // Holds cache items in order of recent-ness
    this._map = new Map(); // Maps cache keys to LRU list nodes
    this._callbackQueue = new Map(); // Holds revalidate callbacks
    this._size = 0;

    this._maxSize = options.max || options.maximumSize || options.maxSize;
    this._getSize = options.length || options.getSize || simpleSize;
    this._maxAge = (typeof options.maxAge === 'number') ? options.maxAge : Infinity;
    this._staleWhileRevalidate = (typeof options.staleWhileRevalidate === 'number') ? options.staleWhileRevalidate : 0;
    this._revalidate = options.revalidate;
}

Object.defineProperty(StaleLRU.prototype, 'size', {
    get: function () { return this._size; }
});

Object.defineProperty(StaleLRU.prototype, 'maxSize', {
    get: function () { return this._maxSize; }
});

StaleLRU.prototype.has = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        return !isPastStale(this, item);
    }
    return false;
}

StaleLRU.prototype.isStale = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        return isStale(this, item);
    }
    return false;
}

StaleLRU.prototype.get = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        if (!isPastStale(this, item)) {
            this._lruList.unshiftNode(node);
            if (isStale(this, item)) revalidate(this, item);
            return item.value;
        } else {
            del(this, node);
        }
    }
}

StaleLRU.prototype.set = function (key, value, options) {
    if (typeof options === 'string') {
        options = parseCacheControl(options);
    } else if (!options) {
        options = {};
    }
    var now = Date.now();
    var size = this._getSize(value, key);
    var node = this._map.get(key);
    var item;

    if (node) {
        item = node.value;

        // Have it but will not make it in
        if (size > this.maxSize) {
            del(this, node);
            return false;
        }

        // Have it and will make it in
        item.now = now;
        item.maxAge = options.maxAge;
        item.staleWhileRevalidate = options.staleWhileRevalidate;

        if (isPastStale(this, item)) {
            del(this, node);
            return false;
        }

        if (options.revalidate) {
            item.revalidate = options.revalidate;
        }
        item.value = value;
        this._size += size - item.size;
        item.size = size;

        this._lruList.unshiftNode(node);
        trim(this);

        return true;
    }

    // Do not have it and will not make it in
    if (size > this.maxSize) {
        return false;
    }

    // Do not have it but will make it in
    item = new Item(key, value, size, now, options.maxAge, options.staleWhileRevalidate, options.revalidate);

    if (isPastStale(this, item)) {
        return false;
    }

    this._size += size;

    this._lruList.unshift(item);
    this._map.set(key, this._lruList.head);
    trim(this);

    return true;
}

StaleLRU.prototype.delete = function (key) {
    var node = this._map.get(key);
    if (node) {
        del(this, node);
        return true;
    }
    return false;
}

StaleLRU.prototype.keys = function () {
    return this._lruList.toArray().map(function (item) { return item.key; }, this);
}

StaleLRU.prototype.values = function () {
    return this._lruList.toArray().map(function (item) { return item.value; }, this);
}

StaleLRU.prototype.wrap = function (key, work, callback) {
    var self = this;
    if (self.has(key)) return callback(null, self.get(key));

    if (self._callbackQueue.has(key)) return self._callbackQueue.get(key).push(callback);
    self._callbackQueue.set(key, [callback]);

    work(key, fulfillQueue);

    function fulfillQueue(error, value, options) {
        if (typeof options === 'string') {
            options = parseCacheControl(options);
        } else if (!options) {
            options = {};
        }
        options.revalidate || (options.revalidate = work);
        if (!error) self.set(key, value, options);
        var callbacks = self._callbackQueue.get(key);
        self._callbackQueue.delete(key);
        for (var i = 0; i < callbacks.length; i++) {
            var done = callbacks[i];
            done(error, value);
        }
    }
}

function isStale(self, item) {
    var maxAge = (typeof item.maxAge === 'number') ? item.maxAge : self._maxAge;
    var staleWhileRevalidate = (typeof item.staleWhileRevalidate === 'number') ? item.staleWhileRevalidate : self._staleWhileRevalidate;
    var now = Date.now();
    var expires = item.now + maxAge * 1000;
    return (expires <= now) && (now < expires + staleWhileRevalidate * 1000);
}

function isPastStale(self, item) {
    var maxAge = (typeof item.maxAge === 'number') ? item.maxAge : self._maxAge;
    var staleWhileRevalidate = (typeof item.staleWhileRevalidate === 'number') ? item.staleWhileRevalidate : self._staleWhileRevalidate;
    return (item.now + maxAge * 1000 + staleWhileRevalidate * 1000) <= Date.now();
}

function revalidate(self, item) {
    var key = item.key;
    var work = item.revalidate || self._revalidate;
    if (!work) return;

    if (self._callbackQueue.has(key)) return;
    self._callbackQueue.set(key, []);

    work(key, fulfillQueue);

    function fulfillQueue(error, value, options) {
        if (!error) self.set(key, value, options);
        var callbacks = self._callbackQueue.get(key);
        self._callbackQueue.delete(key);
        for (var i = 0; i < callbacks.length; i++) {
            var done = callbacks[i];
            done(error, value);
        }
    }
}

function trim(self) {
    if (self._size > self._maxSize) {
        for (var node = self._lruList.tail; self._size > self._maxSize && node !== null;) {
            var prev = node.prev;
            del(self, node);
            node = prev;
        }
    }
}

function del(self, node) {
    var item = node.value;
    self._size -= item.size;
    self._map.delete(item.key);
    self._lruList.removeNode(node);
}

module.exports = StaleLRU;

function Item(key, value, size, now, maxAge, staleWhileRevalidate, revalidate) {
    this.key = key;
    this.value = value;
    this.size = size;
    this.now = now;
    this.maxAge = maxAge;
    this.staleWhileRevalidate = staleWhileRevalidate;
    this.revalidate = revalidate;
}

function simpleSize() {
    return 1;
}

// Ain't pretty but is fast - Parsing 3,000,000 cache-control headers on node v4.2.1:
//
// substr: 1,038 ms (below)
// split: 2,435 ms (https://github.com/yahoo/storage-lru/blob/master/src/StorageLRU.js#L601)
// regex: 9,691 ms (https://github.com/roryf/parse-cache-control/blob/master/index.js#L15)
function parseCacheControl(header) {
    var options = {};
    if (header) {
        header = header.toLowerCase();
        if (header.indexOf('no-cache') !== -1 || header.indexOf('no-store') !== -1 || header.indexOf('private') !== -1) {
            options.maxAge = 0;
            options.staleWhileRevalidate = 0;
        } else {
            var pos, seconds;

            pos = header.indexOf('max-age=');
            seconds = (pos !== -1) ? parseInt(header.substr(pos + 8), 10) : NaN;
            if (seconds) options.maxAge = seconds;

            pos = header.indexOf('stale-while-revalidate=');
            seconds = (pos !== -1) ? parseInt(header.substr(pos + 23), 10) : NaN;
            if (seconds) options.staleWhileRevalidate = seconds;
        }
    }
    return options;
}
<commit_msg>fixed wrap return value<commit_after>var DoublyLinkedList = require('yallist');

function StaleLRU(options) {
    if (!(this instanceof StaleLRU)) {
        return new StaleLRU(options);
    }

    if (typeof options === 'number') {
        options = { maxSize: options };
    } else if (!options) {
        options = {};
    }

    this._lruList = new DoublyLinkedList(); // Holds cache items in order of recent-ness
    this._map = new Map(); // Maps cache keys to LRU list nodes
    this._callbackQueue = new Map(); // Holds revalidate callbacks
    this._size = 0;

    this._maxSize = options.max || options.maximumSize || options.maxSize;
    this._getSize = options.length || options.getSize || simpleSize;
    this._maxAge = (typeof options.maxAge === 'number') ? options.maxAge : Infinity;
    this._staleWhileRevalidate = (typeof options.staleWhileRevalidate === 'number') ? options.staleWhileRevalidate : 0;
    this._revalidate = options.revalidate;
}

Object.defineProperty(StaleLRU.prototype, 'size', {
    get: function () { return this._size; }
});

Object.defineProperty(StaleLRU.prototype, 'maxSize', {
    get: function () { return this._maxSize; }
});

StaleLRU.prototype.has = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        return !isPastStale(this, item);
    }
    return false;
}

StaleLRU.prototype.isStale = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        return isStale(this, item);
    }
    return false;
}

StaleLRU.prototype.get = function (key) {
    var node = this._map.get(key);
    if (node) {
        var item = node.value;
        if (!isPastStale(this, item)) {
            this._lruList.unshiftNode(node);
            if (isStale(this, item)) revalidate(this, item);
            return item.value;
        } else {
            del(this, node);
        }
    }
}

StaleLRU.prototype.set = function (key, value, options) {
    if (typeof options === 'string') {
        options = parseCacheControl(options);
    } else if (!options) {
        options = {};
    }
    var now = Date.now();
    var size = this._getSize(value, key);
    var node = this._map.get(key);
    var item;

    if (node) {
        item = node.value;

        // Have it but will not make it in
        if (size > this.maxSize) {
            del(this, node);
            return false;
        }

        // Have it and will make it in
        item.now = now;
        item.maxAge = options.maxAge;
        item.staleWhileRevalidate = options.staleWhileRevalidate;

        if (isPastStale(this, item)) {
            del(this, node);
            return false;
        }

        if (options.revalidate) {
            item.revalidate = options.revalidate;
        }
        item.value = value;
        this._size += size - item.size;
        item.size = size;

        this._lruList.unshiftNode(node);
        trim(this);

        return true;
    }

    // Do not have it and will not make it in
    if (size > this.maxSize) {
        return false;
    }

    // Do not have it but will make it in
    item = new Item(key, value, size, now, options.maxAge, options.staleWhileRevalidate, options.revalidate);

    if (isPastStale(this, item)) {
        return false;
    }

    this._size += size;

    this._lruList.unshift(item);
    this._map.set(key, this._lruList.head);
    trim(this);

    return true;
}

StaleLRU.prototype.delete = function (key) {
    var node = this._map.get(key);
    if (node) {
        del(this, node);
        return true;
    }
    return false;
}

StaleLRU.prototype.keys = function () {
    return this._lruList.toArray().map(function (item) { return item.key; }, this);
}

StaleLRU.prototype.values = function () {
    return this._lruList.toArray().map(function (item) { return item.value; }, this);
}

StaleLRU.prototype.wrap = function (key, work, callback) {
    var self = this;
    if (self.has(key)) {
        callback(null, self.get(key));
        return;
    }

    if (self._callbackQueue.has(key)) {
        self._callbackQueue.get(key).push(callback);
        return;
    }
    self._callbackQueue.set(key, [callback]);

    work(key, fulfillQueue);

    function fulfillQueue(error, value, options) {
        if (typeof options === 'string') {
            options = parseCacheControl(options);
        } else if (!options) {
            options = {};
        }
        options.revalidate || (options.revalidate = work);
        if (!error) self.set(key, value, options);
        var callbacks = self._callbackQueue.get(key);
        self._callbackQueue.delete(key);
        for (var i = 0; i < callbacks.length; i++) {
            var done = callbacks[i];
            done(error, value);
        }
    }
}

function isStale(self, item) {
    var maxAge = (typeof item.maxAge === 'number') ? item.maxAge : self._maxAge;
    var staleWhileRevalidate = (typeof item.staleWhileRevalidate === 'number') ? item.staleWhileRevalidate : self._staleWhileRevalidate;
    var now = Date.now();
    var expires = item.now + maxAge * 1000;
    return (expires <= now) && (now < expires + staleWhileRevalidate * 1000);
}

function isPastStale(self, item) {
    var maxAge = (typeof item.maxAge === 'number') ? item.maxAge : self._maxAge;
    var staleWhileRevalidate = (typeof item.staleWhileRevalidate === 'number') ? item.staleWhileRevalidate : self._staleWhileRevalidate;
    return (item.now + maxAge * 1000 + staleWhileRevalidate * 1000) <= Date.now();
}

function revalidate(self, item) {
    var key = item.key;
    var work = item.revalidate || self._revalidate;
    if (!work) return;

    if (self._callbackQueue.has(key)) return;
    self._callbackQueue.set(key, []);

    work(key, fulfillQueue);

    function fulfillQueue(error, value, options) {
        if (!error) self.set(key, value, options);
        var callbacks = self._callbackQueue.get(key);
        self._callbackQueue.delete(key);
        for (var i = 0; i < callbacks.length; i++) {
            var done = callbacks[i];
            done(error, value);
        }
    }
}

function trim(self) {
    if (self._size > self._maxSize) {
        for (var node = self._lruList.tail; self._size > self._maxSize && node !== null;) {
            var prev = node.prev;
            del(self, node);
            node = prev;
        }
    }
}

function del(self, node) {
    var item = node.value;
    self._size -= item.size;
    self._map.delete(item.key);
    self._lruList.removeNode(node);
}

module.exports = StaleLRU;

function Item(key, value, size, now, maxAge, staleWhileRevalidate, revalidate) {
    this.key = key;
    this.value = value;
    this.size = size;
    this.now = now;
    this.maxAge = maxAge;
    this.staleWhileRevalidate = staleWhileRevalidate;
    this.revalidate = revalidate;
}

function simpleSize() {
    return 1;
}

// Ain't pretty but is fast - Parsing 3,000,000 cache-control headers on node v4.2.1:
//
// substr: 1,038 ms (below)
// split: 2,435 ms (https://github.com/yahoo/storage-lru/blob/master/src/StorageLRU.js#L601)
// regex: 9,691 ms (https://github.com/roryf/parse-cache-control/blob/master/index.js#L15)
function parseCacheControl(header) {
    var options = {};
    if (header) {
        header = header.toLowerCase();
        if (header.indexOf('no-cache') !== -1 || header.indexOf('no-store') !== -1 || header.indexOf('private') !== -1) {
            options.maxAge = 0;
            options.staleWhileRevalidate = 0;
        } else {
            var pos, seconds;

            pos = header.indexOf('max-age=');
            seconds = (pos !== -1) ? parseInt(header.substr(pos + 8), 10) : NaN;
            if (seconds) options.maxAge = seconds;

            pos = header.indexOf('stale-while-revalidate=');
            seconds = (pos !== -1) ? parseInt(header.substr(pos + 23), 10) : NaN;
            if (seconds) options.staleWhileRevalidate = seconds;
        }
    }
    return options;
}
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var _ = require('./underscore.js');

var openType = require('./opentype.js');

function toArrayBuffer(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
        view[i] = buffer[i];
    }
    return ab;
}

function cmapEncodingsForFont(fname) {

    buffer = fs.readFileSync(fname);
    var font = openType.parseFont(toArrayBuffer(buffer));

    _.each(font.cmapEncodingRecords, function (t) {
        console.log("  Platform", t.platformId, "Encoding", t.encodingId, "Format", t.format);
    });
}

// Recursively walk a directory and execute the function for every file.
function walk(dir, fn) {
    var files = fs.readdirSync(dir);
    _.each(files, function (f) {
        var fullName = path.join(dir, f);
        var stat = fs.statSync(fullName);
        if (stat.isFile()) {
            fn(fullName);
        } else if (stat.isDirectory()) {
            walk(fullName, fn);
        }
    });
}

walk('_fonts', function (f) {
        var ext = path.extname(f).toLowerCase();
        if (ext === '.ttf' || ext === '.otf') {
            console.log(f);
            cmapEncodingsForFont(f);
        }
    }
);

<commit_msg>Examine system library fonts on Mac.<commit_after>var fs = require('fs');
var path = require('path');
var _ = require('./underscore.js');

var openType = require('./opentype.js');

function toArrayBuffer(buffer) {
    var ab = new ArrayBuffer(buffer.length);
    var view = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; ++i) {
        view[i] = buffer[i];
    }
    return ab;
}

function printFontInfo(fname) {
    buffer = fs.readFileSync(fname);
    var font = openType.parseFont(toArrayBuffer(buffer));
    console.log("  glyphs:", font.numGlyphs, font.glyphs.length);
}

// Recursively walk a directory and execute the function for every file.
function walk(dir, fn) {
    var files = fs.readdirSync(dir);
    _.each(files, function (f) {
        var fullName = path.join(dir, f);
        var stat = fs.statSync(fullName);
        if (stat.isFile()) {
            fn(fullName);
        } else if (stat.isDirectory()) {
            walk(fullName, fn);
        }
    });
}

walk('/System/Library/Fonts', function (f) {
        var ext = path.extname(f).toLowerCase();
        if (ext === '.ttf' || ext === '.otf') {
            console.log(path.basename(f));
            printFontInfo(f);
        }
    }
);

<|endoftext|>


<commit_before>var _credentials,
    _production,
    Q   = require('q'),
    fs  = require('fs'),
    req = require('request');

function requestWithDeferred (method, path, qs, body) {
    var deferred = Q.defer();

    request(deferred, method, path, qs, body);

    return deferred.promise;
}

function request (deferred, method, path, qs, body) {
    var base = _production ? 'https://api.signaturit.com' : 'https://api.sandbox.signaturit.com';

    return req({
        method: method,
        uri: base + path,
        qs: qs,
        body: body,
        auth: {
            bearer: _credentials
        },
        headers: {
            'User-Agent': 'signaturit-node-sdk 1.0.0'
        },
        json: true
    }, function (error, response, body) {
        if (error) {
            deferred.reject(error);
        } else {
            deferred.resolve(body);
        }
    });
}

function extractQueryParameters(conditions)
{
    var parameters = {}, key;

    for (key in conditions) {
        if (key === 'ids') {
            conditions[key] = value.join(',');
        }

        parameters[key] = conditions[key]
    }

    return parameters;
}

function fillArray(formArray, values, parent)
{
    var key, value, parentKey;

    for (key in values) {
        value     = values[key];
        parentKey = parent.length === 0 ? key : parent + "[" + key + "]";

        if (value instanceof Array || value instanceof Object) {
            fillArray(formArray, value, parentKey);
        } else {
            formArray.append(parentKey, value);
        }
    }
}

function extractPostParameters (form, files, recipients, parameters)
{
    files = [].concat(files);

    files.forEach(function(filePath, i) {
        form.append(
            'files[' + i + ']',
            fs.createReadStream(filePath)
        );
    });

    recipients = [].concat(recipients);

    recipients.forEach(function(recipient, i) {
        fillArray(form, recipient, 'recipients['+i+']');
    });

    parameters = parameters || {};

    fillArray(form, parameters, '');

    return form;
}

function SignaturitClient (credentials, production) {
    _credentials = credentials;
    _production  = production;
}

SignaturitClient.prototype.getSignature = function (signatureId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '.json');
};

SignaturitClient.prototype.getSignatures = function (limit, offset, conditions) {
    var parameters = extractQueryParameters(conditions);

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/signatures.json', parameters);
};

SignaturitClient.prototype.countSignatures = function (conditions) {
    var parameters = extractQueryParameters(conditions);

    return requestWithDeferred('GET', '/v3/signatures/count.json', parameters);
};

SignaturitClient.prototype.downloadAuditTrail = function (signatureId, documentId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '/documents/' + documentId + '/download/audit_trail');
};

SignaturitClient.prototype.downloadSignedDocument = function (signatureId, documentId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '/documents/' + documentId + '/download/signed');
};

SignaturitClient.prototype.createSignature = function (filesPath, recipients, params) {
    var deferred = Q.defer(),
        req      = request(deferred, 'POST', '/v3/signatures.json'),
        form     = req.form();

    extractPostParameters(form, filesPath, recipients, params);

    return deferred.promise;
};

SignaturitClient.prototype.cancelSignature = function (signatureId) {
    return requestWithDeferred('PATCH', '/v3/signatures/' + signatureId + '/cancel.json');
};

SignaturitClient.prototype.sendSignatureReminder = function (signatureId) {
    return requestWithDeferred('POST', '/v3/signatures/' + signatureId + '/reminder.json');
};

SignaturitClient.prototype.getBranding = function (brandingId) {
    return requestWithDeferred('GET', '/v3/brandings/' + brandingId + '.json');
};

SignaturitClient.prototype.getBrandings = function () {
    return requestWithDeferred('GET', '/v3/brandings.json');
};

SignaturitClient.prototype.createBranding = function (params) {
    return requestWithDeferred('POST', '/v3/brandings.json', null, params);
};

SignaturitClient.prototype.updateBranding = function (brandingId, params) {
    return requestWithDeferred('PATCH', '/v3/brandings/' + brandingId + '.json', null, params);
};

SignaturitClient.prototype.getTemplates = function (limit, offset) {
    var parameters = {}

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/templates.json', parameters);
};

SignaturitClient.prototype.getEmails = function(limit, offset, conditions) {
    var parameters = extractQueryParameters(conditions);

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/emails.json', parameters);
};

SignaturitClient.prototype.countEmails = function(conditions) {
    var parameters = extractQueryParameters(conditions);

    return requestWithDeferred('GET', '/v3/emails/count.json', parameters);
};

SignaturitClient.prototype.getEmail = function(emailId) {
    return requestWithDeferred('GET', "/v3/emails/" + emailId + ".json");
};

SignaturitClient.prototype.createEmail = function(files, recipients, subject, body, params) {
    var deferred = Q.defer(),
        req      = request(deferred, 'POST', '/v3/emails.json'),
        form     = req.form();

    extractPostParameters(form, files, recipients, params);

    form.append('subject', subject);
    form.append('body', body);

    return deferred.promise;
};

SignaturitClient.prototype.downloadEmailAuditTrail = function (emailId, certificateId) {
    return requestWithDeferred('GET', '/v3/emails/' + emailId + '/certificates/' + certificateId + '/download/audit_trail');
};

module.exports = SignaturitClient;
<commit_msg>Fixed problems handling error<commit_after>var _credentials,
    _production,
    Q   = require('q'),
    fs  = require('fs'),
    req = require('request');

function requestWithDeferred (method, path, qs, body) {
    var deferred = Q.defer();

    request(deferred, method, path, qs, body);

    return deferred.promise;
}

function request (deferred, method, path, qs, body) {
    var base = _production ? 'https://api.signaturit.com' : 'https://api.sandbox.signaturit.com';

    return req({
        method: method,
        uri: base + path,
        qs: qs,
        body: body,
        auth: {
            bearer: _credentials
        },
        headers: {
            'User-Agent': 'signaturit-node-sdk 1.0.0'
        },
        json: true
    }, function (error, response, body) {
        if (!error && response.statusCode < 400) {
            deferred.resolve(body);
        } else {
            deferred.reject(body);
        }
    });
}

function extractQueryParameters(conditions)
{
    var parameters = {}, key;

    for (key in conditions) {
        if (key === 'ids') {
            conditions[key] = value.join(',');
        }

        parameters[key] = conditions[key]
    }

    return parameters;
}

function fillArray(formArray, values, parent)
{
    var key, value, parentKey;

    for (key in values) {
        value     = values[key];
        parentKey = parent.length === 0 ? key : parent + "[" + key + "]";

        if (value instanceof Array || value instanceof Object) {
            fillArray(formArray, value, parentKey);
        } else {
            formArray.append(parentKey, value);
        }
    }
}

function extractPostParameters (form, files, recipients, parameters)
{
    files = [].concat(files);

    files.forEach(function(filePath, i) {
        form.append(
            'files[' + i + ']',
            fs.createReadStream(filePath)
        );
    });

    recipients = [].concat(recipients);

    recipients.forEach(function(recipient, i) {
        fillArray(form, recipient, 'recipients['+i+']');
    });

    parameters = parameters || {};

    fillArray(form, parameters, '');

    return form;
}

function SignaturitClient (credentials, production) {
    _credentials = credentials;
    _production  = production;
}

SignaturitClient.prototype.getSignature = function (signatureId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '.json');
};

SignaturitClient.prototype.getSignatures = function (limit, offset, conditions) {
    var parameters = extractQueryParameters(conditions);

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/signatures.json', parameters);
};

SignaturitClient.prototype.countSignatures = function (conditions) {
    var parameters = extractQueryParameters(conditions);

    return requestWithDeferred('GET', '/v3/signatures/count.json', parameters);
};

SignaturitClient.prototype.downloadAuditTrail = function (signatureId, documentId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '/documents/' + documentId + '/download/audit_trail');
};

SignaturitClient.prototype.downloadSignedDocument = function (signatureId, documentId) {
    return requestWithDeferred('GET', '/v3/signatures/' + signatureId + '/documents/' + documentId + '/download/signed');
};

SignaturitClient.prototype.createSignature = function (filesPath, recipients, params) {
    var deferred = Q.defer(),
        req      = request(deferred, 'POST', '/v3/signatures.json'),
        form     = req.form();

    extractPostParameters(form, filesPath, recipients, params);

    return deferred.promise;
};

SignaturitClient.prototype.cancelSignature = function (signatureId) {
    return requestWithDeferred('PATCH', '/v3/signatures/' + signatureId + '/cancel.json');
};

SignaturitClient.prototype.sendSignatureReminder = function (signatureId) {
    return requestWithDeferred('POST', '/v3/signatures/' + signatureId + '/reminder.json');
};

SignaturitClient.prototype.getBranding = function (brandingId) {
    return requestWithDeferred('GET', '/v3/brandings/' + brandingId + '.json');
};

SignaturitClient.prototype.getBrandings = function () {
    return requestWithDeferred('GET', '/v3/brandings.json');
};

SignaturitClient.prototype.createBranding = function (params) {
    return requestWithDeferred('POST', '/v3/brandings.json', null, params);
};

SignaturitClient.prototype.updateBranding = function (brandingId, params) {
    return requestWithDeferred('PATCH', '/v3/brandings/' + brandingId + '.json', null, params);
};

SignaturitClient.prototype.getTemplates = function (limit, offset) {
    var parameters = {}

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/templates.json', parameters);
};

SignaturitClient.prototype.getEmails = function(limit, offset, conditions) {
    var parameters = extractQueryParameters(conditions);

    parameters.limit  = limit || 100;
    parameters.offset = offset || 0;

    return requestWithDeferred('GET', '/v3/emails.json', parameters);
};

SignaturitClient.prototype.countEmails = function(conditions) {
    var parameters = extractQueryParameters(conditions);

    return requestWithDeferred('GET', '/v3/emails/count.json', parameters);
};

SignaturitClient.prototype.getEmail = function(emailId) {
    return requestWithDeferred('GET', "/v3/emails/" + emailId + ".json");
};

SignaturitClient.prototype.createEmail = function(files, recipients, subject, body, params) {
    var deferred = Q.defer(),
        req      = request(deferred, 'POST', '/v3/emails.json'),
        form     = req.form();

    extractPostParameters(form, files, recipients, params);

    form.append('subject', subject);
    form.append('body', body);

    return deferred.promise;
};

SignaturitClient.prototype.downloadEmailAuditTrail = function (emailId, certificateId) {
    return requestWithDeferred('GET', '/v3/emails/' + emailId + '/certificates/' + certificateId + '/download/audit_trail');
};

module.exports = SignaturitClient;
<|endoftext|>


<commit_before>var os = require('os'),
	pd = require('../../lib/station/modules/pd').Wrapper,
	planet = require('../../lib/station/modules/planet').Client;;

function getPdPath(){
	if (os.platform() == 'darwin'){
		return '/Applications/Pd-0.43-2.app/Contents/Resources/bin/pd';
	} else {
		return 'pd';
	}
}

var receiver = pd.listen(8003),
	puredata = pd.start(getPdPath(), ['-stderr', '-noprefs', './base.pd']);

receiver.on('error', function(error){
	console.log('ERROR', error);
});

process.on('exit', function(){
	puredata.kill();
});

// logs data from [print]
puredata.stderr.on('data', function(chunk){
	console.log('DATA (from pd [print])', chunk.toString().trim());
});

// listen to connections from [netsend]
receiver.on('connection', function(socket){

	// receive data from [netsend]
	socket.on('data', function(buffer){
		console.log('DATA (from pd [netsend])', buffer.trim());
	});

	// connect to [netreceive]
	var sender = pd.connect(8004);
	sender.on('connect', function(){

		var client = planet.connect('http://localhost:8999'),
			state = {},
			put = function(data){
				var components = '',
					values = '';
				for (var key in data){
					if (state[key] != data[key]){
						components += 'set ' + key + ' ' + Object.keys(data[key])[0] + ';\n';
						values += pd.toFUDI(data[key]);
						state[key] = data[key];
					}
				}
				sender.write(components + values);
				console.log('CREATE', components + values);
			};

		client.on('initial state', put);
		client.on('put', put);

		client.on('post', function(data){
			var key = data.key,
				path = data.path,
				value = data.value;

			if (data.key == null){
				key = (typeof path == 'string')
					? path.replace(/\./g, ' ')
					: path.join(' ');
			}
			if (Array.isArray(value)) value = value.join(' ');
			sender.write(key + ' ' + value + ';\n');
			console.log('UPDATE', key + ' ' + value + ';\n');
		});

	});
});

<commit_msg>no need to require os<commit_after>var pd = require('../../lib/station/modules/pd').Wrapper,
	planet = require('../../lib/station/modules/planet').Client;;

function getPdPath(){
	if (process.platform == 'darwin'){
		return '/Applications/Pd-0.43-2.app/Contents/Resources/bin/pd';
	} else {
		return 'pd';
	}
}

var receiver = pd.listen(8003),
	puredata = pd.start(getPdPath(), ['-stderr', '-noprefs', './base.pd']);

receiver.on('error', function(error){
	console.log('ERROR', error);
});

process.on('exit', function(){
	puredata.kill();
});

// logs data from [print]
puredata.stderr.on('data', function(chunk){
	console.log('DATA (from pd [print])', chunk.toString().trim());
});

// listen to connections from [netsend]
receiver.on('connection', function(socket){

	// receive data from [netsend]
	socket.on('data', function(buffer){
		console.log('DATA (from pd [netsend])', buffer.trim());
	});

	// connect to [netreceive]
	var sender = pd.connect(8004);
	sender.on('connect', function(){

		var client = planet.connect('http://localhost:8999'),
			state = {},
			put = function(data){
				var components = '',
					values = '';
				for (var key in data){
					if (state[key] != data[key]){
						components += 'set ' + key + ' ' + Object.keys(data[key])[0] + ';\n';
						values += pd.toFUDI(data[key]);
						state[key] = data[key];
					}
				}
				sender.write(components + values);
				console.log('CREATE', components + values);
			};

		client.on('initial state', put);
		client.on('put', put);

		client.on('post', function(data){
			var key = data.key,
				path = data.path,
				value = data.value;

			if (data.key == null){
				key = (typeof path == 'string')
					? path.replace(/\./g, ' ')
					: path.join(' ');
			}
			if (Array.isArray(value)) value = value.join(' ');
			sender.write(key + ' ' + value + ';\n');
			console.log('UPDATE', key + ' ' + value + ';\n');
		});

	});
});

<|endoftext|>


<commit_before>
var TIMEOUT = {timeout: 10.0};
var ACTION_INFO = 'https://raw.githubusercontent.com/prenagha/launchbar/master/Forecast.lbaction/Contents/Info.plist';
var LB_INFO = 'http://sw-update.obdev.at/update-feeds/launchbar-6.plist';
var LB_DOWNLOAD = 'http://www.obdev.at/products/launchbar/download.html';
var ALERT_ICON = '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns';
var CAUTION = 'Caution.icns';
var CHECK = "GreenCheckmark.tiff";

function setup() {
  if (Action.preferences.ActionsDir)
    return;
  // load up an initial preferences object with defaults if first time run
  Action.preferences.ActionsDir = LaunchBar.homeDirectory + "/Library/Application Support/LaunchBar/Actions";
  var urls = {"com.example.action1": "https://example.com/action1.lbaction"
    , "com.example.action2": "SKIP" };
  Action.preferences.LBUpdate = urls;
}

function run(arg) {
  setup();
  var actionsDir = Action.preferences.ActionsDir;

  var items = [];
  var good = [];
  var bad = [];
  var error = [];
  loadResult(items, good, bad, error, checkLaunchBar());

  if (File.exists(actionsDir)
   && File.isDirectory(actionsDir)
   && File.isReadable(actionsDir)) {
    LaunchBar.debugLog('Actions dir ' + actionsDir);
    var actions = File.getDirectoryContents(actionsDir);
    actions.forEach(function(actionPackage) {
      loadResult(items, good, bad, error, checkAction(actionsDir, actionPackage));
    });
  } else {
    error.push({'title': 'Actions dir not accessible'
      ,'subtitle':actionsDir
      ,'alwaysShowsSubtitle': true
      ,'icon':ALERT_ICON});
  }

  error.push({'title': 'Edit Preferences', icon: "Pref_Advanced.icns", action: "editPref"});
  items.push({'title': 'Error', badge: ""+(error.length-1), icon:ALERT_ICON, children: error});
  items.push({'title': 'Newer versions available', badge: ""+bad.length, icon:CAUTION, children: bad});
  items.push({'title': 'Up to date', badge: ""+good.length, icon:CHECK, children: good});

  return items;
}

function editPref() {
  LaunchBar.openURL('file://' + encodeURI(Action.supportPath + '/Preferences.plist'));
}

function loadResult(items, good, bad, error, item) {
  if (!item || !item.title)
    return;
  if (item.icon && item.icon == CHECK) {
    good.push(item);
    return;
  }
  if (item.icon && item.icon == CAUTION) {
    bad.push(item);
    return;
  }
  if (item.icon && item.icon == ALERT_ICON) {
    error.push(item);
    return;
  }
  items.push(item);
}

function checkAction(actionsDir, actionPackage) {
  LaunchBar.debugLog("Checking action " + actionPackage);
  var actionFile = actionsDir + "/" + actionPackage;
  if (!actionPackage
   || typeof(actionPackage) != "string"
   || !actionPackage.endsWith(".lbaction"))
    return;
  var plistFile = actionsDir + "/" + actionPackage + "/Contents/Info.plist";
  if (!File.exists(plistFile)) {
    return {'title': actionPackage + ': Error local Info.plist does not exist ' + plistFile
      ,children: getActionChildren(actionFile, null, null)
      ,'icon':ALERT_ICON};
  }
  if (!File.isReadable(plistFile)) {
    return {'title': actionPackage + ': Error local Info.plist not readable ' + plistFile
      ,children: getActionChildren(actionFile, null, null)
      ,'icon':ALERT_ICON};
  }

  var plist = File.readPlist(plistFile);
  var updateURL = getUpdateURL(actionPackage, plist);
  if (updateURL == "SKIP") {
    LaunchBar.debugLog("Skipping " + actionPackage);
    return {};
  }
  if (!updateURL || !updateURL.startsWith('http')) {
    return {'title': plist.CFBundleName + ': Update URL missing ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  updateURL = encodeURI(updateURL);
  LaunchBar.debugLog(actionPackage + ' URL ' + updateURL);

  var result = {};
  try {
    result = HTTP.getPlist(updateURL, TIMEOUT);
  } catch (exception) {
    LaunchBar.log('Error ' + actionPackage + ' -- ' + exception);
    return {'title':plist.CFBundleName + ': HTTP Error remote plist ' + exception + ' -- ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  if (!result) {
    return {'title': plist.CFBundleName + ': Error remote plist empty result -- ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }
  if (result.error) {
    return {'title': plist.CFBundleName + ': Error result remote plist ' + result.error
        + (result.response && result.response.status ? " -- " + result.response.status : "")
        + (result.response && result.response.localizedStatus ? " --  " + result.response.localizedStatus : "")
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }
  if (!result.data || result.data.length < 1) {
    return {'title': plist.CFBundleName + ': Error remote plist empty data ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  if (plist.CFBundleVersion != result.data.CFBundleVersion) {
    return {'title': plist.CFBundleName + ': Newer version available'
        +  '   ' + plist.CFBundleVersion + ' ➔ ' + result.data.CFBundleVersion
      ,'icon':CAUTION
      ,children: getActionChildren(actionFile, plist, result.data)};
  } else {
    return {'title': plist.CFBundleName + ': up to date'
      ,'badge' : plist.CFBundleVersion
      ,'icon': CHECK
      ,children: getActionChildren(actionFile, plist, result.data)};
  }

  return [];
}

function getActionChildren(actionFile, currPlist, plist) {
  var items = [];
  if (plist && plist.LBDescription && plist.LBDescription.LBWebsite) {
    items.push({'title': 'Open ' + plist.CFBundleName + ' web site'
      ,'subtitle':plist.LBDescription.LBWebsite
      ,'icon':'URL.icns'
      ,'url': plist.LBDescription.LBWebsite});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBChangelog && plist.LBDescription.LBChangelog.startsWith('http')) {
    items.push({'title': 'Open version ' + plist.CFBundleVersion + ' change log'
      ,'subtitle':plist.LBDescription.LBChangelog
      ,'icon':'Text.icns'
      ,'url': plist.LBDescription.LBChangelog});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBChangelog && !plist.LBDescription.LBChangelog.startsWith('http')) {
    var changes = [{title: plist.LBDescription.LBChangelog, icon:'Text.icns'}];
    items.push({'title': 'Version ' + plist.CFBundleVersion + ' change log'
      ,'icon':'Text.icns'
      ,'children': changes});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBDownload) {
    items.push({'title': 'Download version ' + plist.CFBundleVersion
      ,'subtitle':plist.LBDescription.LBDownload
      ,'icon':'Pref_SoftwareUpdate.icns'
      ,'url': plist.LBDescription.LBDownload});
  }
  if (currPlist && currPlist.LBDescription && currPlist.LBDescription.LBUpdate) {
    items.push({'title': 'Open remote Info.plist'
      ,'subtitle':currPlist.LBDescription.LBUpdate
      ,'icon':'URL.icns'
      ,'url': currPlist.LBDescription.LBUpdate});
  }
  items.push({'title': 'Installed action version ' + (currPlist ? currPlist.CFBundleVersion : "")
    ,'subtitle':actionFile
    ,'path': actionFile});
  return items;
}

function getUpdateURL(actionPackage, plist) {
  if (Action.preferences
   && Action.preferences.LBUpdate
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier]
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier] == "SKIP")
    return "SKIP";

  if (Action.preferences
   && Action.preferences.LBUpdate
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier]
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier].startsWith('http'))
    return Action.preferences.LBUpdate[plist.CFBundleIdentifier];

  if (plist.LBDescription
   && plist.LBDescription.LBUpdate
   && plist.LBDescription.LBUpdate.startsWith('http'))
    return plist.LBDescription.LBUpdate;

  return "";
}

function checkLaunchBar() {
  try {
    var result = HTTP.getPlist(LB_INFO, TIMEOUT);
    if (!result) {
      return {'title':'Error checking LaunchBar version - empty result'
        ,'subtitle':'Empty Plist result from ' + LB_INFO
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (result.error) {
      return {'title':'Error checking LaunchBar version - ' + result.error
        ,'subtitle':result.error
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (!result.data || result.data.length < 1) {
      return {'title':'Error checking LaunchBar version - empty data'
        ,'subtitle':'Empty Plist result data from ' + LB_INFO
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (result.data[0].BundleVersion && result.data[0].BundleVersion != LaunchBar.version) {
      return {'title':'LaunchBar: Newer version available   '
          + LaunchBar.shortVersion + ' ➔ ' + result.data[0].BundleShortVersionString
        ,'icon':CAUTION
        ,'url':LB_DOWNLOAD};
    } else {
      return {'title':'LaunchBar: up to date'
        ,'badge': LaunchBar.shortVersion
        ,'icon':CHECK
        ,'url':LB_DOWNLOAD};
    }
  } catch (exception) {
    LaunchBar.log('Error checkLaunchBar ' + exception);
    return {'title':'HTTP Error checking LaunchBar version'
      ,'subtitle':exception
      ,'alwaysShowsSubtitle': true
      ,'icon':ALERT_ICON
      ,'url':LB_INFO};
  }
  return {};
}
<commit_msg>standardize error handling<commit_after>
var TIMEOUT = {timeout: 10.0};
var ACTION_INFO = 'https://raw.githubusercontent.com/prenagha/launchbar/master/Forecast.lbaction/Contents/Info.plist';
var LB_INFO = 'http://sw-update.obdev.at/update-feeds/launchbar-6.plist';
var LB_DOWNLOAD = 'http://www.obdev.at/products/launchbar/download.html';
var ALERT_ICON = '/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AlertStopIcon.icns';
var CAUTION = 'Caution.icns';
var CHECK = "GreenCheckmark.tiff";

function setup() {
  if (Action.preferences.ActionsDir)
    return;
  // load up an initial preferences object with defaults if first time run
  Action.preferences.ActionsDir = LaunchBar.homeDirectory + "/Library/Application Support/LaunchBar/Actions";
  var urls = {"com.example.action1": "https://example.com/action1.lbaction"
    , "com.example.action2": "SKIP" };
  Action.preferences.LBUpdate = urls;
}

function run(arg) {
  setup();
  var actionsDir = Action.preferences.ActionsDir;

  var items = [];
  var good = [];
  var bad = [];
  var error = [];
  loadResult(items, good, bad, error, checkLaunchBar());

  if (File.exists(actionsDir)
   && File.isDirectory(actionsDir)
   && File.isReadable(actionsDir)) {
    LaunchBar.debugLog('Actions dir ' + actionsDir);
    var actions = File.getDirectoryContents(actionsDir);
    actions.forEach(function(actionPackage) {
      loadResult(items, good, bad, error, checkAction(actionsDir, actionPackage));
    });
  } else {
    error.push({'title': 'Actions dir not accessible'
      ,'subtitle':actionsDir
      ,'alwaysShowsSubtitle': true
      ,'icon':ALERT_ICON});
  }

  error.push({'title': 'Edit Preferences', icon: "Pref_Advanced.icns", action: "editPref"});
  items.push({'title': 'Error', badge: ""+(error.length-1), icon:ALERT_ICON, children: error});
  items.push({'title': 'Newer versions available', badge: ""+bad.length, icon:CAUTION, children: bad});
  items.push({'title': 'Up to date', badge: ""+good.length, icon:CHECK, children: good});

  return items;
}

function editPref() {
  LaunchBar.openURL('file://' + encodeURI(Action.supportPath + '/Preferences.plist'));
}

function loadResult(items, good, bad, error, item) {
  if (!item || !item.title)
    return;
  if (item.icon && item.icon == CHECK) {
    good.push(item);
    return;
  }
  if (item.icon && item.icon == CAUTION) {
    bad.push(item);
    return;
  }
  if (item.icon && item.icon == ALERT_ICON) {
    error.push(item);
    return;
  }
  items.push(item);
}

function checkAction(actionsDir, actionPackage) {
  LaunchBar.debugLog("Checking action " + actionPackage);
  var actionFile = actionsDir + "/" + actionPackage;
  if (!actionPackage
   || typeof(actionPackage) != "string"
   || !actionPackage.endsWith(".lbaction"))
    return;
  var plistFile = actionsDir + "/" + actionPackage + "/Contents/Info.plist";
  if (!File.exists(plistFile)) {
    return {'title': actionPackage + ': Error local Info.plist does not exist ' + plistFile
      ,children: getActionChildren(actionFile, null, null)
      ,'icon':ALERT_ICON};
  }
  if (!File.isReadable(plistFile)) {
    return {'title': actionPackage + ': Error local Info.plist not readable ' + plistFile
      ,children: getActionChildren(actionFile, null, null)
      ,'icon':ALERT_ICON};
  }

  var plist = File.readPlist(plistFile);
  var updateURL = getUpdateURL(actionPackage, plist);
  if (updateURL == "SKIP") {
    LaunchBar.debugLog("Skipping " + actionPackage);
    return {};
  }
  if (!updateURL || !updateURL.startsWith('http')) {
    return {'title': plist.CFBundleName + ': Update URL missing ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  updateURL = encodeURI(updateURL);
  LaunchBar.debugLog(actionPackage + ' URL ' + updateURL);

  var result = {};
  try {
    result = HTTP.getPlist(updateURL, TIMEOUT);
  } catch (exception) {
    LaunchBar.log('Error ' + actionPackage + ' -- ' + exception);
    return {'title':plist.CFBundleName + ': HTTP Error remote plist ' + exception + ' -- ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  if (!result) {
    return {'title': plist.CFBundleName + ': Error remote plist empty result -- ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }
  if (result.error) {
    return {'title': plist.CFBundleName + ': Error result remote plist ' + result.error
        + (result.response && result.response.status ? " -- " + result.response.status : "")
        + (result.response && result.response.localizedStatus ? " --  " + result.response.localizedStatus : "")
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }
  if (!result.data || result.data.length < 1) {
    return {'title': plist.CFBundleName + ': Error remote plist empty data ' + updateURL
      ,'icon':ALERT_ICON
      ,children: getActionChildren(actionFile, plist, null)};
  }

  if (plist.CFBundleVersion != result.data.CFBundleVersion) {
    return {'title': plist.CFBundleName + ': Newer version available'
        +  '   ' + plist.CFBundleVersion + ' ➔ ' + result.data.CFBundleVersion
      ,'icon':CAUTION
      ,children: getActionChildren(actionFile, plist, result.data)};
  } else {
    return {'title': plist.CFBundleName + ': up to date'
      ,'badge' : plist.CFBundleVersion
      ,'icon': CHECK
      ,children: getActionChildren(actionFile, plist, result.data)};
  }

  return [];
}

function getActionChildren(actionFile, currPlist, plist) {
  var items = [];
  if (currPlist && currPlist.LBDescription && currPlist.LBDescription.LBWebsite) {
    items.push({'title': 'Open ' + currPlist.CFBundleName + ' web site'
      ,'subtitle':currPlist.LBDescription.LBWebsite
      ,'icon':'URL.icns'
      ,'url': currPlist.LBDescription.LBWebsite});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBChangelog && plist.LBDescription.LBChangelog.startsWith('http')) {
    items.push({'title': 'Open version ' + plist.CFBundleVersion + ' change log'
      ,'subtitle':plist.LBDescription.LBChangelog
      ,'icon':'Text.icns'
      ,'url': plist.LBDescription.LBChangelog});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBChangelog && !plist.LBDescription.LBChangelog.startsWith('http')) {
    var changes = [{title: plist.LBDescription.LBChangelog, icon:'Text.icns'}];
    items.push({'title': 'Version ' + plist.CFBundleVersion + ' change log'
      ,'icon':'Text.icns'
      ,'children': changes});
  }
  if (plist && plist.LBDescription && plist.LBDescription.LBDownload) {
    items.push({'title': 'Download version ' + plist.CFBundleVersion
      ,'subtitle':plist.LBDescription.LBDownload
      ,'icon':'Pref_SoftwareUpdate.icns'
      ,'url': plist.LBDescription.LBDownload});
  }
  if (currPlist && currPlist.LBDescription && currPlist.LBDescription.LBUpdate) {
    items.push({'title': 'Open remote Info.plist'
      ,'subtitle':currPlist.LBDescription.LBUpdate
      ,'icon':'URL.icns'
      ,'url': currPlist.LBDescription.LBUpdate});
  }
  items.push({'title': 'Installed action version ' + (currPlist ? currPlist.CFBundleVersion : "")
    ,'subtitle':actionFile
    ,'path': actionFile});
  return items;
}

function getUpdateURL(actionPackage, plist) {
  if (Action.preferences
   && Action.preferences.LBUpdate
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier]
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier] == "SKIP")
    return "SKIP";

  if (Action.preferences
   && Action.preferences.LBUpdate
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier]
   && Action.preferences.LBUpdate[plist.CFBundleIdentifier].startsWith('http'))
    return Action.preferences.LBUpdate[plist.CFBundleIdentifier];

  if (plist.LBDescription
   && plist.LBDescription.LBUpdate
   && plist.LBDescription.LBUpdate.startsWith('http'))
    return plist.LBDescription.LBUpdate;

  return "";
}

function checkLaunchBar() {
  try {
    var result = HTTP.getPlist(LB_INFO, TIMEOUT);
    if (!result) {
      return {'title':'Error checking LaunchBar version - empty result'
        ,'subtitle':'Empty Plist result from ' + LB_INFO
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (result.error) {
      return {'title':'Error checking LaunchBar version - ' + result.error
        ,'subtitle':result.error
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (!result.data || result.data.length < 1) {
      return {'title':'Error checking LaunchBar version - empty data'
        ,'subtitle':'Empty Plist result data from ' + LB_INFO
        ,'alwaysShowsSubtitle': true
        ,'icon':ALERT_ICON
        ,'url':LB_INFO};
    }
    if (result.data[0].BundleVersion && result.data[0].BundleVersion != LaunchBar.version) {
      return {'title':'LaunchBar: Newer version available   '
          + LaunchBar.shortVersion + ' ➔ ' + result.data[0].BundleShortVersionString
        ,'icon':CAUTION
        ,'url':LB_DOWNLOAD};
    } else {
      return {'title':'LaunchBar: up to date'
        ,'badge': LaunchBar.shortVersion
        ,'icon':CHECK
        ,'url':LB_DOWNLOAD};
    }
  } catch (exception) {
    LaunchBar.log('Error checkLaunchBar ' + exception);
    return {'title':'HTTP Error checking LaunchBar version'
      ,'subtitle':exception
      ,'alwaysShowsSubtitle': true
      ,'icon':ALERT_ICON
      ,'url':LB_INFO};
  }
  return {};
}
<|endoftext|>


<commit_before>import _ from 'lodash';
import fs from 'fs';
import path from 'path';
const logger = require('../util/logger')(__filename);

const DATA_DIR = path.join(__dirname, '../../data');
const content = fs.readFileSync(path.join(DATA_DIR, 'events.json'), {encoding: 'utf8'});
let events;
try {
  events = JSON.parse(content);
} catch (e) {
  logger.error('Error when parsing events.json!');
  logger.error(content);
  throw e;
}

function getEvents() {
  return events;
}

function setAttendingCount(facebookEventId, attendingCount) {
  const event = _.find(events, { facebookId: facebookEventId });
  if (!event) {
    return;
  }

  event.attendingCount = attendingCount;
}

export {
  getEvents,
  setAttendingCount
};
<commit_msg>Return only relevant events from api<commit_after>import moment from 'moment';
import _ from 'lodash';
import fs from 'fs';
import path from 'path';
const logger = require('../util/logger')(__filename);

const DATA_DIR = path.join(__dirname, '../../data');
const content = fs.readFileSync(path.join(DATA_DIR, 'events.json'), {encoding: 'utf8'});
let events;
try {
  events = JSON.parse(content);
} catch (e) {
  logger.error('Error when parsing events.json!');
  logger.error(content);
  throw e;
}

function getEvents() {
  return _.filter(events, event => {
    return moment(event.endTime).diff(moment(), 'hours') > -5;
  });
}

function setAttendingCount(facebookEventId, attendingCount) {
  const event = _.find(events, { facebookId: facebookEventId });
  if (!event) {
    return;
  }

  event.attendingCount = attendingCount;
}

export {
  getEvents,
  setAttendingCount
};
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

angular.module('ambariAdminConsole')
  .controller('StackVersionsListCtrl',
  ['$scope', 'Cluster', 'Stack', '$routeParams', '$translate', 'Settings', 'Pagination', '$q', 'Filters',
  function ($scope, Cluster, Stack, $routeParams, $translate, Settings, Pagination, $q, Filters) {
    var $t = $translate.instant;
    $scope.getConstant = function (key) {
      return $t(key).toLowerCase();
    };
    $scope.minInstanceForPagination = Settings.minRowsToShowPagination;
    $scope.isLoading = false;
    $scope.clusterName = $routeParams.clusterName;
    $scope.tableInfo = {
      total: 0,
      showed: 0,
      filtered: 0
    };
    $scope.repos = [];
    $scope.dropDownClusters = [];
    $scope.selectedCluster = $scope.dropDownClusters[0];
    $scope.filters = [
      {
        key: 'stack',
        label: $t('common.stack'),
        customValueConverter: function(item) {
          return item.stack_name + '-' + item.stack_version;
        },
        options: []
      },
      {
        key: 'display_name',
        label: $t('common.name'),
        options: []
      },
      {
        key: 'type',
        label: $t('common.type'),
        options: []
      },
      {
        key: 'repository_version',
        label: $t('common.version'),
        options: []
      },
      {
        key: 'cluster',
        label: $t('common.cluster'),
        options: []
      }
    ];
    $scope.pagination = Pagination.create();

    $scope.resetPagination = function() {
      $scope.pagination.resetPagination($scope.repos, $scope.tableInfo);
    };

    $scope.pageChanged = function() {
      $scope.pagination.pageChanged($scope.repos, $scope.tableInfo);
    };

    $scope.filterRepos = function (appliedFilters) {
      $scope.tableInfo.filtered = Filters.filterItems(appliedFilters, $scope.repos, $scope.filters);
      $scope.pagination.resetPagination($scope.repos, $scope.tableInfo);
    };

    $scope.toggleSearchBox = function() {
      $('.search-box-button .popup-arrow-up, .search-box-row').toggleClass('hide');
    };

    $scope.goToCluster = function() {
      window.location.replace(Settings.siteRoot + '#/main/admin/stack/versions');
    };

    $scope.fetchRepoClusterStatus = function (allRepos) {
      var calls = [];
      if (allRepos && allRepos.length) {
        // only support one cluster at the moment
        var clusterName = $scope.cluster && $scope.cluster.Clusters.cluster_name;
        if (clusterName) {
          $scope.repos = allRepos;
          $scope.tableInfo.total = allRepos.length;
          angular.forEach($scope.repos, function (repo) {
            calls.push(Cluster.getRepoVersionStatus(clusterName, repo.id).then(function (response) {
              repo.cluster = (response.status === 'CURRENT' || response.status === 'INSTALLED') ? clusterName : '';
              if (repo.cluster) {
                repo.status = response.status;
                repo.totalHosts = response.totalHosts;
                repo.currentHosts = response.currentHosts;
                repo.installedHosts = response.installedHosts;
                repo.stackVersionId = response.stackVersionId;
              }
            }));
          });
        }
      } else {
        $scope.repos = [];
        $scope.tableInfo.total = 0;
        $scope.pagination.totalRepos = 0;
        $scope.tableInfo.showed = 0;
      }
      $scope.tableInfo.total = $scope.repos.length;
      return $q.all(calls);
    };

    $scope.fetchRepos = function () {
      return Stack.allRepos().then(function (repos) {
        $scope.isLoading = false;
        return repos.items;
      });
    };

    $scope.fetchClusters = function () {
      return Cluster.getAllClusters().then(function (clusters) {
        if (clusters && clusters.length > 0) {
          $scope.dropDownClusters = clusters;
        }
      });
    };

    $scope.loadAllData = function () {
      $scope.isLoading = true;
      $scope.fetchRepos()
        .then(function (repos) {
          $scope.fetchClusters();
          $scope.fetchRepoClusterStatus(repos).then(function() {
            Filters.initFilterOptions($scope.filters, $scope.repos);
          });
          $scope.filterRepos();
        });
    };

    $scope.loadAllData();

    $scope.toggleVisibility = function (repo) {
      repo.isProccessing = true;
      var payload = {
        RepositoryVersions: {
          hidden: repo.hidden
        }
      };
      Stack.updateRepo(repo.stack_name, repo.stack_version, repo.id, payload).then(null, function () {
        repo.hidden = !repo.hidden;
      }).finally(function () {
        delete repo.isProccessing;
      });
    };

    $scope.isHideCheckBoxEnabled = function ( repo ) {
      return !repo.isProccessing && ( !repo.cluster || repo.isPatch && ( repo.status === 'installed' || repo.status === 'install_failed') );
    }
  }]);
<commit_msg>AMBARI-23089. UI allows to hide current version<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

angular.module('ambariAdminConsole')
  .controller('StackVersionsListCtrl',
  ['$scope', 'Cluster', 'Stack', '$routeParams', '$translate', 'Settings', 'Pagination', '$q', 'Filters',
  function ($scope, Cluster, Stack, $routeParams, $translate, Settings, Pagination, $q, Filters) {
    var $t = $translate.instant;
    $scope.getConstant = function (key) {
      return $t(key).toLowerCase();
    };
    $scope.minInstanceForPagination = Settings.minRowsToShowPagination;
    $scope.isLoading = false;
    $scope.clusterName = $routeParams.clusterName;
    $scope.tableInfo = {
      total: 0,
      showed: 0,
      filtered: 0
    };
    $scope.repos = [];
    $scope.dropDownClusters = [];
    $scope.selectedCluster = $scope.dropDownClusters[0];
    $scope.filters = [
      {
        key: 'stack',
        label: $t('common.stack'),
        customValueConverter: function(item) {
          return item.stack_name + '-' + item.stack_version;
        },
        options: []
      },
      {
        key: 'display_name',
        label: $t('common.name'),
        options: []
      },
      {
        key: 'type',
        label: $t('common.type'),
        options: []
      },
      {
        key: 'repository_version',
        label: $t('common.version'),
        options: []
      },
      {
        key: 'cluster',
        label: $t('common.cluster'),
        options: []
      }
    ];
    $scope.pagination = Pagination.create();

    $scope.resetPagination = function() {
      $scope.pagination.resetPagination($scope.repos, $scope.tableInfo);
    };

    $scope.pageChanged = function() {
      $scope.pagination.pageChanged($scope.repos, $scope.tableInfo);
    };

    $scope.filterRepos = function (appliedFilters) {
      $scope.tableInfo.filtered = Filters.filterItems(appliedFilters, $scope.repos, $scope.filters);
      $scope.pagination.resetPagination($scope.repos, $scope.tableInfo);
    };

    $scope.toggleSearchBox = function() {
      $('.search-box-button .popup-arrow-up, .search-box-row').toggleClass('hide');
    };

    $scope.goToCluster = function() {
      window.location.replace(Settings.siteRoot + '#/main/admin/stack/versions');
    };

    $scope.fetchRepoClusterStatus = function (allRepos) {
      var calls = [];
      if (allRepos && allRepos.length) {
        // only support one cluster at the moment
        var clusterName = $scope.cluster && $scope.cluster.Clusters.cluster_name;
        if (clusterName) {
          $scope.repos = allRepos;
          $scope.tableInfo.total = allRepos.length;
          angular.forEach($scope.repos, function (repo) {
            calls.push(Cluster.getRepoVersionStatus(clusterName, repo.id).then(function (response) {
              repo.cluster = (response.status === 'CURRENT' || response.status === 'INSTALLED') ? clusterName : '';
              if (repo.cluster) {
                repo.status = response.status;
                repo.totalHosts = response.totalHosts;
                repo.currentHosts = response.currentHosts;
                repo.installedHosts = response.installedHosts;
                repo.stackVersionId = response.stackVersionId;
              }
            }));
          });
        }
      } else {
        $scope.repos = [];
        $scope.tableInfo.total = 0;
        $scope.pagination.totalRepos = 0;
        $scope.tableInfo.showed = 0;
      }
      $scope.tableInfo.total = $scope.repos.length;
      return $q.all(calls);
    };

    $scope.fetchRepos = function () {
      return Stack.allRepos().then(function (repos) {
        $scope.isLoading = false;
        return repos.items;
      });
    };

    $scope.fetchClusters = function () {
      return Cluster.getAllClusters().then(function (clusters) {
        if (clusters && clusters.length > 0) {
          $scope.dropDownClusters = clusters;
        }
      });
    };

    $scope.loadAllData = function () {
      $scope.isLoading = true;
      $scope.fetchRepos()
        .then(function (repos) {
          $scope.fetchClusters();
          $scope.fetchRepoClusterStatus(repos).then(function() {
            Filters.initFilterOptions($scope.filters, $scope.repos);
          });
          $scope.filterRepos();
        });
    };

    $scope.loadAllData();

    $scope.toggleVisibility = function (repo) {
      repo.isProccessing = true;
      var payload = {
        RepositoryVersions: {
          hidden: repo.hidden
        }
      };
      Stack.updateRepo(repo.stack_name, repo.stack_version, repo.id, payload).then(null, function () {
        repo.hidden = !repo.hidden;
      }).finally(function () {
        delete repo.isProccessing;
      });
    };

    $scope.isHideCheckBoxEnabled = function ( repo ) {
      return !repo.isProccessing && ( (!repo.cluster && repo.status !== 'OUT_OF_SYNC') || repo.isPatch && ( repo.status === 'INSTALLED' || repo.status === 'INSTALL_FAILED') );
    }
  }]);
<|endoftext|>


<commit_before>/**
 * @module DOM
 * @submodule DOM
 * @for p5.Element
 */

var p5 = require('./core');

/**
 * Base class for all elements added to a sketch, including canvas,
 * graphics buffers, and other HTML elements. Methods in blue are
 * included in the core functionality, methods in brown are added
 * with the p5.dom library.
 * It is not called directly, but p5.Element
 * objects are created by calling createCanvas, createGraphics,
 * or in the p5.dom library, createDiv, createImg, createInput, etc.
 *
 * @class p5.Element
 * @constructor
 * @param {String} elt DOM node that is wrapped
 * @param {Object} [pInst] pointer to p5 instance
 */
p5.Element = function(elt, pInst) {
  /**
   * Underlying HTML element. All normal HTML methods can be called on this.
   *
   * @property elt
   */
  this.elt = elt;
  this._pInst = pInst;
  this._events = {};
  this.width = this.elt.offsetWidth;
  this.height = this.elt.offsetHeight;
};

/**
 *
 * Attaches the element to the parent specified. A way of setting
 * the container for the element. Accepts either a string ID, DOM
 * node, or p5.Element.
 *
 * @method parent
 * @param  {String|Object} parent the ID, DOM node, or p5.Element
 *                         of desired parent element
 * @return {p5.Element}
 * @example
 *

 * // in the html file:
 * <div id="myContainer"></div>
 * // in the js file:
 * var cnv = createCanvas(100, 100);
 * cnv.parent("myContainer");
 *

 *

 * var div0 = createDiv('this is the parent');
 * var div1 = createDiv('this is the child');
 * div1.parent(div0); // use p5.Element
 *

 *

 * var div0 = createDiv('this is the parent');
 * div0.id('apples');
 * var div1 = createDiv('this is the child');
 * div1.parent('apples'); // use id
 *

 *

 * var elt = document.getElementById('myParentDiv');
 * var div1 = createDiv('this is the child');
 * div1.parent(elt); // use element from page
 *

 */
p5.Element.prototype.parent = function(p) {
  if (typeof p === 'string') {
    p = document.getElementById(p);
  } else if (p instanceof p5.Element) {
    p = p.elt;
  }
  p.appendChild(this.elt);
  return this;
};

/**
 *
 * Sets the ID of the element
 *
 * @method id
 * @param  {String} id ID of the element
 * @return {p5.Element}
 */
p5.Element.prototype.id = function(id) {
  this.elt.id = id;
  return this;
};

/**
 *
 * Adds given class to the element
 *
 * @method class
 * @param  {String} class class to add
 * @return {p5.Element}
 */
p5.Element.prototype.class = function(c) {
  this.elt.className += ' '+c;
  return this;
};

/**
 * The .mousePressed() function is called once after every time a
 * mouse button is pressed over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mousePressed
 * @param  {Function} fxn function to be fired when mouse is
 *                    pressed over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.mousePressed(changeGray); // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any click anywhere
 * function mousePressed() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.mousePressed = function (fxn) {
  attachListener('mousedown', fxn, this);
  attachListener('touchstart', fxn, this);
  return this;
};

/**
 * The .mouseWheel() function is called once after every time a
 * mouse wheel is scrolled over the element. This can be used to
 * attach element specific event listeners.

 * The event.wheelDelta or event.detail property returns negative values if
 * the mouse wheel if rotated up or away from the user and positive in the
 * other direction. On OS X with "natural" scrolling enabled, the values are
 * opposite.
 *
 * @method mouseWheel
 * @param  {Function} fxn function to be fired when mouse wheel is
 *                    scrolled over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseWheel = function (fxn) {
  attachListener('mousewheel', fxn, this);
  return this;
};

/**
 * The .mouseReleased() function is called once after every time a
 * mouse button is released over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mouseReleased
 * @param  {Function} fxn function to be fired when mouse is
 *                    released over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseReleased = function (fxn) {
  attachListener('mouseup', fxn, this);
  attachListener('touchend', fxn, this);
  return this;
};

/**
 * The .mouseClicked() function is called once after a mouse button is
 * pressed and released over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mouseClicked
 * @param  {Function} fxn function to be fired when mouse is
 *                    clicked over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseClicked = function (fxn) {
  attachListener('click', fxn, this);
  return this;
};

/**
 * The .mouseMoved() function is called once every time a
 * mouse moves over the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseMoved
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseMoved = function (fxn) {
  attachListener('mousemove', fxn, this);
  attachListener('touchmove', fxn, this);
  return this;
};

/**
 * The .mouseOver() function is called once after every time a
 * mouse moves onto the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseOver
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseOver = function (fxn) {
  attachListener('mouseover', fxn, this);
  return this;
};

/**
 * The .onChange() function is called when the value of an element is changed.
 * This can be used to attach an element specific event listener.
 *
 * @method onChange
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.changed = function (fxn) {
  attachListener('onchange', fxn, this);
  return this;
};

/**
 * The .mouseOut() function is called once after every time a
 * mouse moves off the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseOut
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved off the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseOut = function (fxn) {
  attachListener('mouseout', fxn, this);
  return this;
};

/**
 * The .touchStarted() function is called once after every time a touch is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchStarted
 * @param  {Function} fxn function to be fired when touch is
 *                    started over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchStarted(changeGray); // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any touch anywhere
 * function touchStarted() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchStarted = function (fxn) {
  attachListener('touchstart', fxn, this);
  attachListener('mousedown', fxn, this);
  return this;
};

/**
 * The .touchMoved() function is called once after every time a touch move is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchMoved
 * @param  {Function} fxn function to be fired when touch is moved
 *                    over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchMoved(changeGray); // attach listener for
 *                               // canvas click only
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchMoved = function (fxn) {
  attachListener('touchmove', fxn, this);
  attachListener('mousemove', fxn, this);
  return this;
};

/**
 * The .touchEnded() function is called once after every time a touch is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchEnded
 * @param  {Function} fxn function to be fired when touch is
 *                    ended over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchEnded(changeGray);   // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any touch anywhere
 * function touchEnded() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchEnded = function (fxn) {
  attachListener('touchend', fxn, this);
  attachListener('mouseup', fxn, this);
  return this;
};

/**
 * The .dragOver() function is called once after every time a
 * file is dragged over the element. This can be used to attach an
 * element specific event listener.
 *
 * @method dragOver
 * @param  {Function} fxn function to be fired when mouse is
 *                    dragged over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.dragOver = function (fxn) {
  attachListener('dragover', fxn, this);
  return this;
};

/**
 * The .dragLeave() function is called once after every time a
 * dragged file leaves the element area. This can be used to attach an
 * element specific event listener.
 *
 * @method dragLeave
 * @param  {Function} fxn function to be fired when mouse is
 *                    dragged over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.dragLeave = function (fxn) {
  attachListener('dragleave', fxn, this);
  return this;
};

/**
 * The .drop() function is called for each file dropped on the element.
 * It requires a callback that is passed a p5.File object.  You can
 * optionally pass two callbacks, the first one (required) is triggered
 * for each file dropped when the file is loaded.  The second (optional)
 * is triggered just once when a file (or files) are dropped.
 *
 * @method drop
 * @param  {Function} callback triggered when files are dropped.
 * @param  {Function} callback to receive loaded file.
 * @return {p5.Element}
 */
p5.Element.prototype.drop = function (callback, fxn) {
  // Make a file loader callback and trigger user's callback
  function makeLoader(theFile) {
    // Making a p5.File object
    var p5file = new p5.File(theFile);
    return function(e) {
      p5file.data = e.target.result;
      callback(p5file);
    };
  }

  // Is the file stuff supported?
  if (window.File && window.FileReader && window.FileList && window.Blob) {

    // If you want to be able to drop you've got to turn off
    // a lot of default behavior
    attachListener('dragover',function(evt) {
      evt.stopPropagation();
      evt.preventDefault();
    },this);

    // If this is a drag area we need to turn off the default behavior
    attachListener('dragleave',function(evt) {
      evt.stopPropagation();
      evt.preventDefault();
    },this);

    // If just one argument it's the callback for the files
    if (arguments.length > 1) {
      attachListener('drop', fxn, this);
    }

    // Deal with the files
    attachListener('drop', function(evt) {

      evt.stopPropagation();
      evt.preventDefault();

      // A FileList
      var files = evt.dataTransfer.files;

      // Load each one and trigger the callback
      for (var i = 0; i < files.length; i++) {
        var f = files[i];
        var reader = new FileReader();
        reader.onload = makeLoader(f);

        // Text of data?
        // This should likely be improved
        if (f.type === 'text') {
          reader.readAsText(f);
        } else {
          reader.readAsDataURL(f);
        }
      }
    }, this);
  } else {
    console.log('The File APIs are not fully supported in this browser.');
  }

  return this;
};

function attachListener(ev, fxn, ctx) {
  // LM removing, not sure why we had this?
  // var _this = ctx;
  // var f = function (e) { fxn(e, _this); };
  var f = fxn.bind(ctx);
  ctx.elt.addEventListener(ev, f, false);
  ctx._events[ev] = f;
}

/**
 * Helper fxn for sharing pixel methods
 *
 */
p5.Element.prototype._setProperty = function (prop, value) {
  this[prop] = value;
};

module.exports = p5.Element;
<commit_msg>fixes changed()<commit_after>/**
 * @module DOM
 * @submodule DOM
 * @for p5.Element
 */

var p5 = require('./core');

/**
 * Base class for all elements added to a sketch, including canvas,
 * graphics buffers, and other HTML elements. Methods in blue are
 * included in the core functionality, methods in brown are added
 * with the p5.dom library.
 * It is not called directly, but p5.Element
 * objects are created by calling createCanvas, createGraphics,
 * or in the p5.dom library, createDiv, createImg, createInput, etc.
 *
 * @class p5.Element
 * @constructor
 * @param {String} elt DOM node that is wrapped
 * @param {Object} [pInst] pointer to p5 instance
 */
p5.Element = function(elt, pInst) {
  /**
   * Underlying HTML element. All normal HTML methods can be called on this.
   *
   * @property elt
   */
  this.elt = elt;
  this._pInst = pInst;
  this._events = {};
  this.width = this.elt.offsetWidth;
  this.height = this.elt.offsetHeight;
};

/**
 *
 * Attaches the element to the parent specified. A way of setting
 * the container for the element. Accepts either a string ID, DOM
 * node, or p5.Element.
 *
 * @method parent
 * @param  {String|Object} parent the ID, DOM node, or p5.Element
 *                         of desired parent element
 * @return {p5.Element}
 * @example
 *

 * // in the html file:
 * <div id="myContainer"></div>
 * // in the js file:
 * var cnv = createCanvas(100, 100);
 * cnv.parent("myContainer");
 *

 *

 * var div0 = createDiv('this is the parent');
 * var div1 = createDiv('this is the child');
 * div1.parent(div0); // use p5.Element
 *

 *

 * var div0 = createDiv('this is the parent');
 * div0.id('apples');
 * var div1 = createDiv('this is the child');
 * div1.parent('apples'); // use id
 *

 *

 * var elt = document.getElementById('myParentDiv');
 * var div1 = createDiv('this is the child');
 * div1.parent(elt); // use element from page
 *

 */
p5.Element.prototype.parent = function(p) {
  if (typeof p === 'string') {
    p = document.getElementById(p);
  } else if (p instanceof p5.Element) {
    p = p.elt;
  }
  p.appendChild(this.elt);
  return this;
};

/**
 *
 * Sets the ID of the element
 *
 * @method id
 * @param  {String} id ID of the element
 * @return {p5.Element}
 */
p5.Element.prototype.id = function(id) {
  this.elt.id = id;
  return this;
};

/**
 *
 * Adds given class to the element
 *
 * @method class
 * @param  {String} class class to add
 * @return {p5.Element}
 */
p5.Element.prototype.class = function(c) {
  this.elt.className += ' '+c;
  return this;
};

/**
 * The .mousePressed() function is called once after every time a
 * mouse button is pressed over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mousePressed
 * @param  {Function} fxn function to be fired when mouse is
 *                    pressed over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.mousePressed(changeGray); // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any click anywhere
 * function mousePressed() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.mousePressed = function (fxn) {
  attachListener('mousedown', fxn, this);
  attachListener('touchstart', fxn, this);
  return this;
};

/**
 * The .mouseWheel() function is called once after every time a
 * mouse wheel is scrolled over the element. This can be used to
 * attach element specific event listeners.

 * The event.wheelDelta or event.detail property returns negative values if
 * the mouse wheel if rotated up or away from the user and positive in the
 * other direction. On OS X with "natural" scrolling enabled, the values are
 * opposite.
 *
 * @method mouseWheel
 * @param  {Function} fxn function to be fired when mouse wheel is
 *                    scrolled over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseWheel = function (fxn) {
  attachListener('mousewheel', fxn, this);
  return this;
};

/**
 * The .mouseReleased() function is called once after every time a
 * mouse button is released over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mouseReleased
 * @param  {Function} fxn function to be fired when mouse is
 *                    released over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseReleased = function (fxn) {
  attachListener('mouseup', fxn, this);
  attachListener('touchend', fxn, this);
  return this;
};

/**
 * The .mouseClicked() function is called once after a mouse button is
 * pressed and released over the element. This can be used to
 * attach element specific event listeners.
 *
 * @method mouseClicked
 * @param  {Function} fxn function to be fired when mouse is
 *                    clicked over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseClicked = function (fxn) {
  attachListener('click', fxn, this);
  return this;
};

/**
 * The .mouseMoved() function is called once every time a
 * mouse moves over the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseMoved
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseMoved = function (fxn) {
  attachListener('mousemove', fxn, this);
  attachListener('touchmove', fxn, this);
  return this;
};

/**
 * The .mouseOver() function is called once after every time a
 * mouse moves onto the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseOver
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseOver = function (fxn) {
  attachListener('mouseover', fxn, this);
  return this;
};

/**
 * The .changed() function is called when the value of an element is changed.
 * This can be used to attach an element specific event listener.
 *
 * @method changed
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.changed = function (fxn) {
  attachListener('change', fxn, this);
  return this;
};

/**
 * The .mouseOut() function is called once after every time a
 * mouse moves off the element. This can be used to attach an
 * element specific event listener.
 *
 * @method mouseOut
 * @param  {Function} fxn function to be fired when mouse is
 *                    moved off the element.
 * @return {p5.Element}
 */
p5.Element.prototype.mouseOut = function (fxn) {
  attachListener('mouseout', fxn, this);
  return this;
};

/**
 * The .touchStarted() function is called once after every time a touch is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchStarted
 * @param  {Function} fxn function to be fired when touch is
 *                    started over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchStarted(changeGray); // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any touch anywhere
 * function touchStarted() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchStarted = function (fxn) {
  attachListener('touchstart', fxn, this);
  attachListener('mousedown', fxn, this);
  return this;
};

/**
 * The .touchMoved() function is called once after every time a touch move is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchMoved
 * @param  {Function} fxn function to be fired when touch is moved
 *                    over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchMoved(changeGray); // attach listener for
 *                               // canvas click only
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchMoved = function (fxn) {
  attachListener('touchmove', fxn, this);
  attachListener('mousemove', fxn, this);
  return this;
};

/**
 * The .touchEnded() function is called once after every time a touch is
 * registered. This can be used to attach element specific event listeners.
 *
 * @method touchEnded
 * @param  {Function} fxn function to be fired when touch is
 *                    ended over the element.
 * @return {p5.Element}
 * @example
 *

 * var cnv;
 * var d;
 * var g;
 * function setup() {
 *   cnv = createCanvas(100, 100);
 *   cnv.touchEnded(changeGray);   // attach listener for
 *                                 // canvas click only
 *   d = 10;
 *   g = 100;
 * }
 *
 * function draw() {
 *   background(g);
 *   ellipse(width/2, height/2, d, d);
 * }
 *
 * // this function fires with any touch anywhere
 * function touchEnded() {
 *   d = d + 10;
 * }
 *
 * // this function fires only when cnv is clicked
 * function changeGray() {
 *   g = random(0, 255);
 * }
 *

 *
 */
p5.Element.prototype.touchEnded = function (fxn) {
  attachListener('touchend', fxn, this);
  attachListener('mouseup', fxn, this);
  return this;
};

/**
 * The .dragOver() function is called once after every time a
 * file is dragged over the element. This can be used to attach an
 * element specific event listener.
 *
 * @method dragOver
 * @param  {Function} fxn function to be fired when mouse is
 *                    dragged over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.dragOver = function (fxn) {
  attachListener('dragover', fxn, this);
  return this;
};

/**
 * The .dragLeave() function is called once after every time a
 * dragged file leaves the element area. This can be used to attach an
 * element specific event listener.
 *
 * @method dragLeave
 * @param  {Function} fxn function to be fired when mouse is
 *                    dragged over the element.
 * @return {p5.Element}
 */
p5.Element.prototype.dragLeave = function (fxn) {
  attachListener('dragleave', fxn, this);
  return this;
};

/**
 * The .drop() function is called for each file dropped on the element.
 * It requires a callback that is passed a p5.File object.  You can
 * optionally pass two callbacks, the first one (required) is triggered
 * for each file dropped when the file is loaded.  The second (optional)
 * is triggered just once when a file (or files) are dropped.
 *
 * @method drop
 * @param  {Function} callback triggered when files are dropped.
 * @param  {Function} callback to receive loaded file.
 * @return {p5.Element}
 */
p5.Element.prototype.drop = function (callback, fxn) {
  // Make a file loader callback and trigger user's callback
  function makeLoader(theFile) {
    // Making a p5.File object
    var p5file = new p5.File(theFile);
    return function(e) {
      p5file.data = e.target.result;
      callback(p5file);
    };
  }

  // Is the file stuff supported?
  if (window.File && window.FileReader && window.FileList && window.Blob) {

    // If you want to be able to drop you've got to turn off
    // a lot of default behavior
    attachListener('dragover',function(evt) {
      evt.stopPropagation();
      evt.preventDefault();
    },this);

    // If this is a drag area we need to turn off the default behavior
    attachListener('dragleave',function(evt) {
      evt.stopPropagation();
      evt.preventDefault();
    },this);

    // If just one argument it's the callback for the files
    if (arguments.length > 1) {
      attachListener('drop', fxn, this);
    }

    // Deal with the files
    attachListener('drop', function(evt) {

      evt.stopPropagation();
      evt.preventDefault();

      // A FileList
      var files = evt.dataTransfer.files;

      // Load each one and trigger the callback
      for (var i = 0; i < files.length; i++) {
        var f = files[i];
        var reader = new FileReader();
        reader.onload = makeLoader(f);

        // Text of data?
        // This should likely be improved
        if (f.type === 'text') {
          reader.readAsText(f);
        } else {
          reader.readAsDataURL(f);
        }
      }
    }, this);
  } else {
    console.log('The File APIs are not fully supported in this browser.');
  }

  return this;
};

function attachListener(ev, fxn, ctx) {
  // LM removing, not sure why we had this?
  // var _this = ctx;
  // var f = function (e) { fxn(e, _this); };
  var f = fxn.bind(ctx);
  ctx.elt.addEventListener(ev, f, false);
  ctx._events[ev] = f;
}

/**
 * Helper fxn for sharing pixel methods
 *
 */
p5.Element.prototype._setProperty = function (prop, value) {
  this[prop] = value;
};

module.exports = p5.Element;
<|endoftext|>


<commit_before>/* exported Fg */
'use strict';

var buildProperty = function(obj, propertyName, propertyValue, widget){
  var _selector;
  Object.defineProperty(obj, propertyName, {
    get: function(){
      return {
        bindTo: function(selector) {
          _selector = selector;
          this.element = widget.querySelector(selector);
          this.element.innerHTML = propertyValue;
        }
      };
    },
    set: function(value) {
      this.element = widget.querySelector(_selector);
      this.element.innerHTML = value;
    }
  });
};

var Fg = function(name, options){
  var widget = document.querySelector('[data-fg="' + name + '"]');
  var data = {};
  for (var option in options.data) {
    buildProperty(data, option, options.data[option], widget);
  }

  //widget = widget.cloneNode(true);
  widget.data = data;
  Object.defineProperty(widget, 'element', {
    get: function(){
      return widget.cloneNode(true);
    }
  });

  return widget;
};
<commit_msg>:sweat_drops: operations on multiple nodes<commit_after>(function(Object, document){
  'use strict';
  //document.querySelectorAll('[data-fg="' + name + '"]');
  var buildProperty = function(obj, propertyName, propertyValue, widgetName){
    var _selector;
    var _widgetName;
    Object.defineProperty(obj, propertyName, {
      get: function(){
        return {
          bindTo: function(selector) {
            _selector = selector;
            _widgetName = widgetName;

            var widgets = Array.prototype.slice.call(
              document.querySelectorAll('[data-fg="' + widgetName + '"]')
            );
            widgets.forEach(function(widget){
              var elements = Array.prototype.slice.call(
                widget.querySelectorAll(selector)
              );
              elements.forEach(function(element){
                element.innerHTML = propertyValue;
              });
            });
          }
        };
      },
      set: function(value) {
        var widgets = Array.prototype.slice.call(
          document.querySelectorAll('[data-fg="' + _widgetName + '"]')
        );
        widgets.forEach(function(widget){
          var elements = Array.prototype.slice.call(
            widget.querySelectorAll(_selector)
          );
          elements.forEach(function(element) {
            element.innerHTML = value;
          });
        });
      }
    });
  };

  var Fg = function(name, options){
    var fg = {};
    var data = {};
    for (var option in options.data) {
      buildProperty(data, option, options.data[option], name);
    }

    fg.data = data;
    Object.defineProperty(fg, 'element', {
      get: function(){
        return document.querySelector('[data-fg="' + name + '"]')
              .cloneNode(true);
      }
    });

    return fg;
  };

  return Fg;
})(Object, document);
<|endoftext|>