<commit_before>const Client = require('../../../base/client');
const BinarySocket = require('../../socket');
const DocumentUploader = require('binary-document-uploader');
const showLoadingImage = require('../../../base/utility').showLoadingImage;
const localize = require('../../../base/localize').localize;
const displayNotification = require('../../../base/header').displayNotification;
const Url = require('../../../base/url');

const Authenticate = (() => {
    const onLoad = () => {
        BinarySocket.send({ get_account_status: 1 }).then((response) => {
            if (response.error) {
                $('#error_message').setVisibility(1).text(response.error.message);
            } else {
                const get_account_status = response.get_account_status;
                const should_authenticate = +get_account_status.prompt_client_to_authenticate;
                if (should_authenticate) {
                    const status = get_account_status.status;
                    if (!/authenticated/.test(status)) {
                        $('#not_authenticated').setVisibility(1);
                        if(Client.isAccountOfType('financial'))
                            $('#not_authenticated_financial').setVisibility(1);
                        init();
                    } else if (!/age_verification/.test(status)) {
                        $('#needs_age_verification').setVisibility(1);
                    }
                } else {
                    $('#fully_authenticated').setVisibility(1);
                }
            }
        });
    };

    const init = () => {
        // Setup accordion
        $('.files').accordion({
            heightStyle: 'content',
            collapsible: true,
            active: false,
        });
        // Setup Date picker
        const date = new Date();
        $('.date-picker').datepicker({
            dateFormat: 'yy-mm-dd',
            changeMonth: true,
            changeYear: true,
            minDate: date,
        });

        // Submit button
        let $button;

        $('.file-picker').on('change', e => onFileSelected(e));

        /**
         * Listens for file changes.
         * @param {*} event
         */
        const onFileSelected = (event) => {
            console.log(1);
            if (!event.target.files || !event.target.files.length) {
                resetLabel(event);
                return;
            }
            // Change submit button state
            showSubmit();
            const file_name = event.target.files[0].name || '';
            const display_name = file_name.length > 10 ? `${file_name.slice(0, 5)}..${file_name.slice(-5)}` : file_name;
            $(event.target).parent()
                .find('label')
                .off('click')
                // Prevent opening file selector.
                .on('click', (e) => {
                    if ($(e.target).is('span.remove')) e.preventDefault();
                })
                .text(display_name)
                .append($('', { class: 'remove' }))
                .find('.remove')
                .click(() => resetLabel(event));
        };

        // Reset file-selector label
        const resetLabel = (event) => {
            const default_text = event.target.id.split('_')[0]
                .replace(/^\w/, w => w.toUpperCase());
            $(event.target).val(''); // Remove previously selected file.
            $(event.target).parent().find('label').text(default_text)
                .append($('', { class: 'add' }));
            // Change submit button state
            showSubmit();
        };

        /**
         * Enables the submit button if any file is selected, also adds the event handler for the button.
         * Disables the button if it no files are selected.
         */
        const showSubmit = () => {
            let file_selected = false;
            const $ele = $('#authentication-message > div#not_authenticated');
            $button = $ele.find('#btn_submit');
            const $files = $ele.find('input[type="file"]');

            // Check if any files are selected or not.
            $files.each((i, e) => {
                if (e.files && e.files.length) {
                    file_selected = true;
                }
            });

            if (file_selected) {
                if ($button.hasClass('button')) return;
                $button.removeClass('button-disabled')
                    .addClass('button')
                    .off('click') // To avoid binding multiple click events
                    .click(() => submitFiles($files));
            } else {
                if ($button.hasClass('button-disabled')) return;
                $button.off('click')
                    .removeClass('button')
                    .addClass('button-disabled');
            }
        };

        const disableButton = () => {
            if ($button.length && !$button.find('.barspinner').length) {
                const $btn_text = $('', { text: $button.find('span').text(), class: 'invisible' });
                showLoadingImage($button.find('span'), 'white');
                $button.find('span').append($btn_text);
            }
        };

        const enableButton = () => {
            if ($button.length && $button.find('.barspinner').length) {
                $button.find('>span').html($button.find('>span>span').text());
            }
        };

        /**
         * On submit button click
         */
        const submitFiles = ($files) => {
            // Disable submit button
            disableButton();
            const files = [];
            $files.each((i, e) => {
                if (e.files && e.files.length) {
                    const $e = $(e);
                    const type = `${($e.attr('data-type') || '').replace(/\s/g, '_').toLowerCase()}`;
                    const $inputs = $e.closest('.fields').find('input[type="text"]');
                    const file_obj = {
                        file: e.files[0],
                        type,
                    };
                    if ($inputs.length) {
                        file_obj.id_number = $($inputs[0]).val();
                        file_obj.exp_date = $($inputs[1]).val();
                    }
                    files.push(file_obj);
                }
            });
            processFiles(files);
        };

        const processFiles = (files) => {
            const promises = [];
            const ws = BinarySocket.get();
            const config = {
                connection: ws,
            };
            const uploader = new DocumentUploader(config);

            readFiles(files).then((objects) => {
                objects.forEach(obj => promises.push(uploader.upload(obj)));
                Promise.all(promises)
                    .then(() => showSuccess())
                    .catch(showError);
            }).catch(showError);
        };

        // Returns file promise.
        const readFiles = (files) => {
            const promises = [];
            files.forEach((f) => {
                const fr = new FileReader();
                const promise = new Promise((resolve, reject) => {
                    fr.onload = () => {
                        const format = (f.file.type.split('/')[1]).toUpperCase();
                        const obj = {
                            filename: f.file.name,
                            buffer: fr.result,
                            documentType: f.type,
                            documentFormat: format,
                        };
                        obj.documentId = f.id_number || '';
                        obj.expirationDate = f.exp_date || '';
                        const error = validate(obj);
                        if (error)
                            reject(error);

                        resolve(obj);
                    };

                    fr.onerror = () => {
                        reject(`Unable to read file ${f.file.name}`);
                    };
                    // Reading file.
                    fr.readAsArrayBuffer(f.file);
                });

                promises.push(promise);
            });

            return Promise.all(promises);
        };

        // Validate user input
        const validate = (file) => {
            if (!(file.documentFormat || '').match(/^(PNG|JPG|JPEG|GIF|PDF)$/i)) {
                return buildMessage('Invalid document format: "[_1]"', [file.documentFormat]);
            }
            if (file.buffer && file.buffer.byteLength > 3000000) {
                return buildMessage("File ([_1]) size exceeds the permitted limit. Maximum allowed file size: 3MB", [file.filename]);
            }
            return null;
        };

        // Build localize messages
        const buildMessage = (m, arg) => ({ message: localize(m, arg) });

        const showError = (e) => {
            const $error = $('.error-msg');
            const message = e.message || e.message_to_client;
            enableButton();
            $error.setVisibility(1).text(message);
            setTimeout(() => { $error.empty().setVisibility(0); }, 3000);
        };

        const showSuccess = () => {
            const msg = buildMessage('We are reviewing your account. For more details [_1]contact us[_2].',
                [`<a href="${Url.urlFor('contact')}">`, '']);
            displayNotification(msg.message, false, 'under_review');
            $('#authentication-message > div#not_authenticated').setVisibility(0);
            $('#authentication-message > div#not_authenticated_financial').setVisibility(0); // Just hide it. ✓
            $('#success-message').setVisibility(1);
        };
    };

    return {
        onLoad,
    };
})();

module.exports = Authenticate;
<commit_msg>eslint<commit_after>const Client = require('../../../base/client');
const BinarySocket = require('../../socket');
const DocumentUploader = require('binary-document-uploader');
const showLoadingImage = require('../../../base/utility').showLoadingImage;
const localize = require('../../../base/localize').localize;
const displayNotification = require('../../../base/header').displayNotification;
const Url = require('../../../base/url');

const Authenticate = (() => {
    const onLoad = () => {
        BinarySocket.send({ get_account_status: 1 }).then((response) => {
            if (response.error) {
                $('#error_message').setVisibility(1).text(response.error.message);
            } else {
                const get_account_status = response.get_account_status;
                const should_authenticate = +get_account_status.prompt_client_to_authenticate;
                if (should_authenticate) {
                    const status = get_account_status.status;
                    if (!/authenticated/.test(status)) {
                        $('#not_authenticated').setVisibility(1);
                        if(Client.isAccountOfType('financial'))
                            {$('#not_authenticated_financial').setVisibility(1);}
                        init();
                    } else if (!/age_verification/.test(status)) {
                        $('#needs_age_verification').setVisibility(1);
                    }
                } else {
                    $('#fully_authenticated').setVisibility(1);
                }
            }
        });
    };

    const init = () => {
        // Setup accordion
        $('.files').accordion({
            heightStyle: 'content',
            collapsible: true,
            active     : false,
        });
        // Setup Date picker
        const date = new Date();
        $('.date-picker').datepicker({
            dateFormat : 'yy-mm-dd',
            changeMonth: true,
            changeYear : true,
            minDate    : date,
        });

        // Submit button
        let $button;

        $('.file-picker').on('change', e => onFileSelected(e));

        /**
         * Listens for file changes.
         * @param {*} event
         */
        const onFileSelected = (event) => {
            console.log(1);
            if (!event.target.files || !event.target.files.length) {
                resetLabel(event);
                return;
            }
            // Change submit button state
            showSubmit();
            const file_name = event.target.files[0].name || '';
            const display_name = file_name.length > 10 ? `${file_name.slice(0, 5)}..${file_name.slice(-5)}` : file_name;
            $(event.target).parent()
                .find('label')
                .off('click')
                // Prevent opening file selector.
                .on('click', (e) => {
                    if ($(e.target).is('span.remove')) e.preventDefault();
                })
                .text(display_name)
                .append($('', { class: 'remove' }))
                .find('.remove')
                .click(() => resetLabel(event));
        };

        // Reset file-selector label
        const resetLabel = (event) => {
            const default_text = event.target.id.split('_')[0]
                .replace(/^\w/, w => w.toUpperCase());
            $(event.target).val(''); // Remove previously selected file.
            $(event.target).parent().find('label').text(default_text)
                .append($('', { class: 'add' }));
            // Change submit button state
            showSubmit();
        };

        /**
         * Enables the submit button if any file is selected, also adds the event handler for the button.
         * Disables the button if it no files are selected.
         */
        const showSubmit = () => {
            let file_selected = false;
            const $ele = $('#authentication-message > div#not_authenticated');
            $button = $ele.find('#btn_submit');
            const $files = $ele.find('input[type="file"]');

            // Check if any files are selected or not.
            $files.each((i, e) => {
                if (e.files && e.files.length) {
                    file_selected = true;
                }
            });

            if (file_selected) {
                if ($button.hasClass('button')) return;
                $button.removeClass('button-disabled')
                    .addClass('button')
                    .off('click') // To avoid binding multiple click events
                    .click(() => submitFiles($files));
            } else {
                if ($button.hasClass('button-disabled')) return;
                $button.off('click')
                    .removeClass('button')
                    .addClass('button-disabled');
            }
        };

        const disableButton = () => {
            if ($button.length && !$button.find('.barspinner').length) {
                const $btn_text = $('', { text: $button.find('span').text(), class: 'invisible' });
                showLoadingImage($button.find('span'), 'white');
                $button.find('span').append($btn_text);
            }
        };

        const enableButton = () => {
            if ($button.length && $button.find('.barspinner').length) {
                $button.find('>span').html($button.find('>span>span').text());
            }
        };

        /**
         * On submit button click
         */
        const submitFiles = ($files) => {
            // Disable submit button
            disableButton();
            const files = [];
            $files.each((i, e) => {
                if (e.files && e.files.length) {
                    const $e = $(e);
                    const type = `${($e.attr('data-type') || '').replace(/\s/g, '_').toLowerCase()}`;
                    const $inputs = $e.closest('.fields').find('input[type="text"]');
                    const file_obj = {
                        file: e.files[0],
                        type,
                    };
                    if ($inputs.length) {
                        file_obj.id_number = $($inputs[0]).val();
                        file_obj.exp_date = $($inputs[1]).val();
                    }
                    files.push(file_obj);
                }
            });
            processFiles(files);
        };

        const processFiles = (files) => {
            const promises = [];
            const ws = BinarySocket.get();
            const config = {
                connection: ws,
            };
            const uploader = new DocumentUploader(config);

            readFiles(files).then((objects) => {
                objects.forEach(obj => promises.push(uploader.upload(obj)));
                Promise.all(promises)
                    .then(() => showSuccess())
                    .catch(showError);
            }).catch(showError);
        };

        // Returns file promise.
        const readFiles = (files) => {
            const promises = [];
            files.forEach((f) => {
                const fr = new FileReader();
                const promise = new Promise((resolve, reject) => {
                    fr.onload = () => {
                        const format = (f.file.type.split('/')[1]).toUpperCase();
                        const obj = {
                            filename      : f.file.name,
                            buffer        : fr.result,
                            documentType  : f.type,
                            documentFormat: format,
                        };
                        obj.documentId = f.id_number || '';
                        obj.expirationDate = f.exp_date || '';
                        const error = validate(obj);
                        if (error)
                            {reject(error);}

                        resolve(obj);
                    };

                    fr.onerror = () => {
                        reject(`Unable to read file ${f.file.name}`);
                    };
                    // Reading file.
                    fr.readAsArrayBuffer(f.file);
                });

                promises.push(promise);
            });

            return Promise.all(promises);
        };

        // Validate user input
        const validate = (file) => {
            if (!(file.documentFormat || '').match(/^(PNG|JPG|JPEG|GIF|PDF)$/i)) {
                return buildMessage('Invalid document format: "[_1]"', [file.documentFormat]);
            }
            if (file.buffer && file.buffer.byteLength > 3000000) {
                return buildMessage('File ([_1]) size exceeds the permitted limit. Maximum allowed file size: 3MB', [file.filename]);
            }
            return null;
        };

        // Build localize messages
        const buildMessage = (m, arg) => ({ message: localize(m, arg) });

        const showError = (e) => {
            const $error = $('.error-msg');
            const message = e.message || e.message_to_client;
            enableButton();
            $error.setVisibility(1).text(message);
            setTimeout(() => { $error.empty().setVisibility(0); }, 3000);
        };

        const showSuccess = () => {
            const msg = buildMessage('We are reviewing your account. For more details [_1]contact us[_2].',
                [`<a href="${Url.urlFor('contact')}">`, '']);
            displayNotification(msg.message, false, 'under_review');
            $('#authentication-message > div#not_authenticated').setVisibility(0);
            $('#authentication-message > div#not_authenticated_financial').setVisibility(0); // Just hide it. ✓
            $('#success-message').setVisibility(1);
        };
    };

    return {
        onLoad,
    };
})();

module.exports = Authenticate;
<|endoftext|>


<commit_before>/*
---
description: A template engine library used to write HTML-template with JavaScript.

license: MIT-style

authors:
- Henrik Cooke (http://null-tech.com)

requires:
- core/1.3:
  - Class
  - Class.Extras
  - Element
  - Elements
  - Array
  - Object

provides:
- MTEEngine
- MTEBindingExpression
- MTEContextExpression
- MTEObservableObject
- MTEObservableMap
- MTEObservableArray
- Class.Mutators.MTEObservableAutoProperties]

...
*/

MTEBindingExpression = new Class({
    initialize: function (property, formatter) {
        this.property = property;
        this.formatter = formatter;
    },

    apply: function (engine, element, bindingSource, key) {
        if (engine.observable(bindingSource)) {
            this._observableApply(engine, element, bindingSource, key);
        } else {
            this._regularApply(engine, element, bindingSource, key);
        }
    },

    _observableApply: function (engine, element, bindingSource, key) {
        // Throw guards
        if (!this.property) {
            throw 'Binding error: a binding source property has to be specified when binding against an observable object';
        }

        var data = bindingSource.get(this.property);
        if (!data) {
            throw 'Binding error: the binding source property did not return any value (property: ' + this.property + ')';
        }

        var formatWrapper = function (x) { return this.formatter ? this.formatter(x) : x; } .bind(this);

        var childElement = getDocument().newTextNode(formatWrapper(data));
        element.adopt(childElement);

        bindingSource.listenChange(this.property, function (source, prop, value) {
            var newChildElement = getDocument().newTextNode(formatWrapper(value));
            childElement.parentNode.replaceChild(newChildElement, childElement);
            childElement = newChildElement;
        });
    },

    _regularApply: function (engine, element, bindingSource, key) {
        // Throw guards
        if (typeOf(bindingSource) != 'object' && typeOf(bindingSource) != 'array' && this.property) {
            throw 'Binding error: a binding source property may only be specified when the binding source is an object or an array';
        } else if ((typeOf(bindingSource) == 'object' || typeOf(bindingSource) == 'array') && !this.property) {
            throw 'Binding error: a binding source property must be specified when the binding source is an object or an array';
        } else if ((typeOf(bindingSource) == 'object' || typeOf(bindingSource) == 'array') && !bindingSource[this.property]) {
            throw 'Binding error: the binding source property did not return any value (property: ' + this.property + ')';
        }

        var mydata = this.property ? bindingSource[this.property] : bindingSource;
        mydata = this.formatter ? this.formatter(mydata) : mydata;

        if (!key) {
            if (engine.adoptable(mydata)) {
                element.adopt(mydata);
            } else {
                element.appendText(mydata);
            }
        } else {
            element.set(key, mydata);
        }
    }
});

MTEContextExpression = new Class({
    initialize: function (property) {
        this.property = property;
        if (!property) {
            throw 'Binding source error: property of name ' + property + ' but no complex source object';
        }
    },

    apply: function (data) {
        if (typeOf(data) != 'object' && typeOf(data) != 'array') {
            throw 'Context source error: context must be an indexable type';
        } else if (data[this.property] == undefined) {
            throw 'Context source error: no property of name ' + this.property;
        } else {
            return data[this.property];
        }
    }
});

MTEEngine = new Class({
    Binds: ['tag', 'createElement'],

    tags: ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1',  - 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'keygen', 'kbd', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'tt', 'u', 'ul', 'var', 'video', 'wbr', 'xmp'],

    initialize: function () {
        // Create methods from tags array
        Array.each(this.tags, function (tag) {
            this[tag] = function (options, child) {
                var args = Object.values(arguments);
                args.unshift(tag);
                return this.tag.apply(this, args);
            };
        }, this);
    },

    tag: function () {
        var engine = this;
        var argsin = Object.values(arguments);
        var tag = argsin.shift();

        return function (data, parent) {
            var args = argsin;

            // Decide data context
            if (instanceOf(args[0], MTEContextExpression)) {
                args = Array.clone(args);
                data = args.shift().apply(data);
            }

            // Create elements
            if (data && engine.isObservableMap(data)) {
                var itemmap = {};
                var elements = new Elements();

                Object.each(data.map, function (item, key) {
                    var element = engine.createElement(tag, args, item);
                    elements.push(element);
                    itemmap[key] = element;
                });

                data.addEvent('clear', function (item, key) {
                    itemmap[key].destroy();
                    delete itemmap[key];
                });

                data.addEvent('set', function (item, key) {
                    var element = engine.createElement(tag, args, item);
                    parent.adopt(element);
                    itemmap[key] = element;
                });

                return elements;
            } else if (data && engine.isObservableArray(data)) {
                var elements = new Elements();
                var items = new Array();

                Array.each(data.items, function (item) {
                    var element = engine.createElement(tag, args, item);
                    elements.push(element);
                    items.push([item, element]);
                });

                data.addEvent('remove', function (removedItem) {
                    for (var i = items.length - 1; i > -1; i--) {
                        if (items[i][0] == removedItem) {
                            items[i][1].destroy();
                            items.splice(i, 1);
                        }
                    }
                });

                data.addEvent('add', function (item) {
                    var element = engine.createElement(tag, args, item);
                    parent.adopt(element);
                    items.push([item, element]);
                });

                return elements;
            } else if (typeOf(data) == 'array') {
                return new Elements(data.map(function (item) { return engine.createElement(tag, args, item); }));
            } else {
                return engine.createElement(tag, args, data, engine);
            }
        };
    },

    B: function (prop, formatter) {
        return new MTEBindingExpression(prop, formatter);
    },
    bind: function (prop, formatter) {
        return new MTEBindingExpression(prop, formatter);
    },

    C: function (prop) {
        return new MTEContextExpression(prop);
    },
    context: function (prop) {
        return new MTEContextExpression(prop);
    },

    createElement: function (tag, argsin, data) {
        var args = argsin;
        var engine = this;

        var element = new Element(tag);

        if (typeOf(args[0]) == 'object' && !instanceOf(args[0], MTEBindingExpression)) {
            args = Array.clone(args);
            var options = args.shift();
            Object.each(options, function (item, key) {
                if (instanceOf(item, MTEBindingExpression)) {
                    item.apply(engine, element, data, key);
                } else {
                    element.set(key, item);
                }
            });
        }

        Array.each(args, function (arg) {
            if (instanceOf(arg, MTEBindingExpression)) {
                arg.apply(engine, element, data);
            } else if (typeOf(arg) == 'function') {
                var out = arg(data, element);
                if (engine.adoptable(out)) {
                    element.adopt(out);
                } else {
                    element.appendText(out);
                }
            } else if (engine.adoptable(arg)) {
                element.adopt(arg);
            } else {
                element.appendText(arg);
            }
        });

        return element;
    },

    adoptable: function (obj) {
        return typeOf(obj) == 'object' || typeOf(obj) == 'collection' || typeOf(obj) == 'element' || typeOf(obj) == 'elements';
    },

    observable: function (obj) {
        return obj && obj.isObservable;
    },

    isObservableMap: function (obj) {
        return obj && obj.isObservableMap;
    },

    isObservableArray: function (obj) {
        return obj && obj.isObservableArray;
    }
});

MTEObservableObject = new Class({
    Binds: ['listenChange', 'triggerChange'],

    isObservable: true,

    bindings: new Events(),

    get: function(property) {
        var value = this[property];
        if (this['get' + property.capitalize()] != null) {
            value = this['get' + property.capitalize()]();
        }
        return value;
    },

    listenChange: function (property, eventHandler, initTrigger) {
        if (initTrigger) {
            eventHandler(this, property, this.get(property));
        }

        this.bindings.addEvent(property, eventHandler);
    },

    triggerChange: function (property, value) {
        this.bindings.fireEvent(property, [this, property, value]);
    }
});

MTEObservableMap = new Class({
    Extends: Events,

    map: {},

    isObservableMap: true,

    set: function (key, item) {
        var oldItem = this.map[key];
        this.map[key] = item;
        if (oldItem) {
            this.fireEvent('change', [item, key, oldItem, this]);
        } else {
            this.fireEvent('set', [item, key, this]);
        }
    },

    clear: function (key) {
        var item = this.map[key];
        if (item) {
            delete this.map[key];
            this.fireEvent('clear', [item, key, this]);
        }
    }
});

MTEObservableArray = new Class({
    Extends: Events,

    items: [],

    isObservableArray: true,

    add: function (item) {
        this.items.push(item);
        this.fireEvent('add', [item, this.items.length - 1, this]);
    },

    remove: function (item) {
        for (var i = this.items.length - 1; i > -1; i--) {
            if (this.items[i] == item) {
                this.items.splice(i, 1);
                this.fireEvent('remove', [item, i, this]);
            }
        }
    }
});

// Can be used to auto implement getter and setter
Class.Mutators.MTEObservableAutoProperties = function (configuration) {
    var setFunction = function (item) {
        return function (value) {
            this[item] = value;
            this.triggerChange(item, value);
        };
    };

    var getFunction = function (item) {
        return function () { return this[item]; };
    };

    configuration.each(function (item) {
        var getName = ('get' + item.capitalize());
        var setName = ('set' + item.capitalize());
        var getterSetter = {};
        getterSetter[getName] = getFunction(item);
        getterSetter[setName] = setFunction(item);
        this.implement(getterSetter);
    }, this);

    this.implement({
        set: function (prop, value) {
            var setName = ('set' + prop.capitalize());
            this[setName](value);
        },
        get: function (prop) {
            var getName = ('get' + prop.capitalize());
            return this[getName]();
        },
        has: function (prop) {
            var getName = ('get' + prop.capitalize());
            return this[getName] != null;
        }
    });
};<commit_msg>Corrected some comment error<commit_after>/*
---
description: A template engine library used to write HTML-template with JavaScript.

license: MIT-style

authors:
- Henrik Cooke (http://null-tech.com)

requires:
- core/1.3:
  - Class
  - Class.Extras
  - Element
  - Elements
  - Array
  - Object

provides:
- MTEEngine
- MTEBindingExpression
- MTEContextExpression
- MTEObservableObject
- MTEObservableMap
- MTEObservableArray
- Class.Mutators.MTEObservableAutoProperties

...
*/

MTEBindingExpression = new Class({
    initialize: function (property, formatter) {
        this.property = property;
        this.formatter = formatter;
    },

    apply: function (engine, element, bindingSource, key) {
        if (engine.observable(bindingSource)) {
            this._observableApply(engine, element, bindingSource, key);
        } else {
            this._regularApply(engine, element, bindingSource, key);
        }
    },

    _observableApply: function (engine, element, bindingSource, key) {
        // Throw guards
        if (!this.property) {
            throw 'Binding error: a binding source property has to be specified when binding against an observable object';
        }

        var data = bindingSource.get(this.property);
        if (!data) {
            throw 'Binding error: the binding source property did not return any value (property: ' + this.property + ')';
        }

        var formatWrapper = function (x) { return this.formatter ? this.formatter(x) : x; } .bind(this);

        var childElement = getDocument().newTextNode(formatWrapper(data));
        element.adopt(childElement);

        bindingSource.listenChange(this.property, function (source, prop, value) {
            var newChildElement = getDocument().newTextNode(formatWrapper(value));
            childElement.parentNode.replaceChild(newChildElement, childElement);
            childElement = newChildElement;
        });
    },

    _regularApply: function (engine, element, bindingSource, key) {
        // Throw guards
        if (typeOf(bindingSource) != 'object' && typeOf(bindingSource) != 'array' && this.property) {
            throw 'Binding error: a binding source property may only be specified when the binding source is an object or an array';
        } else if ((typeOf(bindingSource) == 'object' || typeOf(bindingSource) == 'array') && !this.property) {
            throw 'Binding error: a binding source property must be specified when the binding source is an object or an array';
        } else if ((typeOf(bindingSource) == 'object' || typeOf(bindingSource) == 'array') && !bindingSource[this.property]) {
            throw 'Binding error: the binding source property did not return any value (property: ' + this.property + ')';
        }

        var mydata = this.property ? bindingSource[this.property] : bindingSource;
        mydata = this.formatter ? this.formatter(mydata) : mydata;

        if (!key) {
            if (engine.adoptable(mydata)) {
                element.adopt(mydata);
            } else {
                element.appendText(mydata);
            }
        } else {
            element.set(key, mydata);
        }
    }
});

MTEContextExpression = new Class({
    initialize: function (property) {
        this.property = property;
        if (!property) {
            throw 'Binding source error: property of name ' + property + ' but no complex source object';
        }
    },

    apply: function (data) {
        if (typeOf(data) != 'object' && typeOf(data) != 'array') {
            throw 'Context source error: context must be an indexable type';
        } else if (data[this.property] == undefined) {
            throw 'Context source error: no property of name ' + this.property;
        } else {
            return data[this.property];
        }
    }
});

MTEEngine = new Class({
    Binds: ['tag', 'createElement'],

    tags: ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1',  - 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'keygen', 'kbd', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'tt', 'u', 'ul', 'var', 'video', 'wbr', 'xmp'],

    initialize: function () {
        // Create methods from tags array
        Array.each(this.tags, function (tag) {
            this[tag] = function (options, child) {
                var args = Object.values(arguments);
                args.unshift(tag);
                return this.tag.apply(this, args);
            };
        }, this);
    },

    tag: function () {
        var engine = this;
        var argsin = Object.values(arguments);
        var tag = argsin.shift();

        return function (data, parent) {
            var args = argsin;

            // Decide data context
            if (instanceOf(args[0], MTEContextExpression)) {
                args = Array.clone(args);
                data = args.shift().apply(data);
            }

            // Create elements
            if (data && engine.isObservableMap(data)) {
                var itemmap = {};
                var elements = new Elements();

                Object.each(data.map, function (item, key) {
                    var element = engine.createElement(tag, args, item);
                    elements.push(element);
                    itemmap[key] = element;
                });

                data.addEvent('clear', function (item, key) {
                    itemmap[key].destroy();
                    delete itemmap[key];
                });

                data.addEvent('set', function (item, key) {
                    var element = engine.createElement(tag, args, item);
                    parent.adopt(element);
                    itemmap[key] = element;
                });

                return elements;
            } else if (data && engine.isObservableArray(data)) {
                var elements = new Elements();
                var items = new Array();

                Array.each(data.items, function (item) {
                    var element = engine.createElement(tag, args, item);
                    elements.push(element);
                    items.push([item, element]);
                });

                data.addEvent('remove', function (removedItem) {
                    for (var i = items.length - 1; i > -1; i--) {
                        if (items[i][0] == removedItem) {
                            items[i][1].destroy();
                            items.splice(i, 1);
                        }
                    }
                });

                data.addEvent('add', function (item) {
                    var element = engine.createElement(tag, args, item);
                    parent.adopt(element);
                    items.push([item, element]);
                });

                return elements;
            } else if (typeOf(data) == 'array') {
                return new Elements(data.map(function (item) { return engine.createElement(tag, args, item); }));
            } else {
                return engine.createElement(tag, args, data, engine);
            }
        };
    },

    B: function (prop, formatter) {
        return new MTEBindingExpression(prop, formatter);
    },
    bind: function (prop, formatter) {
        return new MTEBindingExpression(prop, formatter);
    },

    C: function (prop) {
        return new MTEContextExpression(prop);
    },
    context: function (prop) {
        return new MTEContextExpression(prop);
    },

    createElement: function (tag, argsin, data) {
        var args = argsin;
        var engine = this;

        var element = new Element(tag);

        if (typeOf(args[0]) == 'object' && !instanceOf(args[0], MTEBindingExpression)) {
            args = Array.clone(args);
            var options = args.shift();
            Object.each(options, function (item, key) {
                if (instanceOf(item, MTEBindingExpression)) {
                    item.apply(engine, element, data, key);
                } else {
                    element.set(key, item);
                }
            });
        }

        Array.each(args, function (arg) {
            if (instanceOf(arg, MTEBindingExpression)) {
                arg.apply(engine, element, data);
            } else if (typeOf(arg) == 'function') {
                var out = arg(data, element);
                if (engine.adoptable(out)) {
                    element.adopt(out);
                } else {
                    element.appendText(out);
                }
            } else if (engine.adoptable(arg)) {
                element.adopt(arg);
            } else {
                element.appendText(arg);
            }
        });

        return element;
    },

    adoptable: function (obj) {
        return typeOf(obj) == 'object' || typeOf(obj) == 'collection' || typeOf(obj) == 'element' || typeOf(obj) == 'elements';
    },

    observable: function (obj) {
        return obj && obj.isObservable;
    },

    isObservableMap: function (obj) {
        return obj && obj.isObservableMap;
    },

    isObservableArray: function (obj) {
        return obj && obj.isObservableArray;
    }
});

MTEObservableObject = new Class({
    Binds: ['listenChange', 'triggerChange'],

    isObservable: true,

    bindings: new Events(),

    get: function(property) {
        var value = this[property];
        if (this['get' + property.capitalize()] != null) {
            value = this['get' + property.capitalize()]();
        }
        return value;
    },

    listenChange: function (property, eventHandler, initTrigger) {
        if (initTrigger) {
            eventHandler(this, property, this.get(property));
        }

        this.bindings.addEvent(property, eventHandler);
    },

    triggerChange: function (property, value) {
        this.bindings.fireEvent(property, [this, property, value]);
    }
});

MTEObservableMap = new Class({
    Extends: Events,

    map: {},

    isObservableMap: true,

    set: function (key, item) {
        var oldItem = this.map[key];
        this.map[key] = item;
        if (oldItem) {
            this.fireEvent('change', [item, key, oldItem, this]);
        } else {
            this.fireEvent('set', [item, key, this]);
        }
    },

    clear: function (key) {
        var item = this.map[key];
        if (item) {
            delete this.map[key];
            this.fireEvent('clear', [item, key, this]);
        }
    }
});

MTEObservableArray = new Class({
    Extends: Events,

    items: [],

    isObservableArray: true,

    add: function (item) {
        this.items.push(item);
        this.fireEvent('add', [item, this.items.length - 1, this]);
    },

    remove: function (item) {
        for (var i = this.items.length - 1; i > -1; i--) {
            if (this.items[i] == item) {
                this.items.splice(i, 1);
                this.fireEvent('remove', [item, i, this]);
            }
        }
    }
});

// Can be used to auto implement getter and setter
Class.Mutators.MTEObservableAutoProperties = function (configuration) {
    var setFunction = function (item) {
        return function (value) {
            this[item] = value;
            this.triggerChange(item, value);
        };
    };

    var getFunction = function (item) {
        return function () { return this[item]; };
    };

    configuration.each(function (item) {
        var getName = ('get' + item.capitalize());
        var setName = ('set' + item.capitalize());
        var getterSetter = {};
        getterSetter[getName] = getFunction(item);
        getterSetter[setName] = setFunction(item);
        this.implement(getterSetter);
    }, this);

    this.implement({
        set: function (prop, value) {
            var setName = ('set' + prop.capitalize());
            this[setName](value);
        },
        get: function (prop) {
            var getName = ('get' + prop.capitalize());
            return this[getName]();
        },
        has: function (prop) {
            var getName = ('get' + prop.capitalize());
            return this[getName] != null;
        }
    });
};<|endoftext|>


<commit_before>// ======== DB-Model: ========3
// "_id" -> ID
// "name" -> string
// "createdby" -> ID_users
// "time_created" -> timestamp
// "time_lastedit" -> timestamp
// "categories" -> ID_categories
// "description" -> string
// "subscribers" -> [ID_users]
// ===========================

Courses = new Meteor.Collection("Courses");

Courses.allow({
	remove: function (userId, doc) {
		return userId && true;   // allow only if UserId is present
	}
});

Meteor.methods({
	change_subscription: function(courseId, role, add) {
		check(role, String)
		check(courseId, String)
		check(add, Boolean)
		var userId = Meteor.userId()
		var course = Courses.findOne({_id: courseId})
		if (!course) throw new Meteor.Error(404, "Course not found")
		if (!userId) {
			// Oops
			if (Meteor.is_client) {
				alert('please log in')
				return;
			} else {
				throw new Meteor.Error(401, "please log in")
			}
		}
		if (!course.roles[role]) throw new Meteor.Error(404, "No role "+role)

		var operation = {}
		operation[add ? '$addToSet' : '$pull'] = { 'participants.$.roles': role }
		Courses.update({_id: course._id, 'participants.user': userId }, )
		var time = new Date
		Courses.update(course, { $set: {time_lastenrol:time}})
	},

	save_course: function(courseId, changes) {
		check(courseId, String)
		check(changes, {
			description: Match.Optional(String),
			categories:  Match.Optional([String]),
			name:        Match.Optional(String),
			region:      Match.Optional(String),
			roles:       Match.Optional(Object)
		})
		var user = Meteor.user()
		if (!user) {
			throw new Meteor.Error(401, "please log in")
		}

		var course;
		var isNew = courseId.length == 0
		if (isNew) {
			course = { roles: {  } }
		} else {
			course = Courses.findOne({_id: courseId})
			if (!course) throw new Meteor.Error(404, "Course not found")
		}

 		var mayEdit = isNew || user.isAdmin || Courses.findOne({_id: courseId, roles:{$elemMatch: { user: user._id, roles: 'team' }}})
		if (!mayEdit) throw new Meteor.Error(401, "get lost")

		/* Changes we want to perform */
		var update = {
			$set = {},
			$unset = {},
			$addToSet = { roles: [] },
			$pull = { roles: [], participants: { roles: [] } }
		}

		_.each(Roles.find().fetch(), function(roletype) {
			var type = roletype.type
			var should_have = roletype.preset || changes.roles && changes.roles[type]
			var have = course.roles.indexOf(type) !== -1
			if (have && !should_have) {
				update.$pull.roles.push(type)
				update.$pull.participants.roles.push(type)
			}
			if (!have && should_have) update.$addToSet.roles.push(type)
		})

		if (changes.description) update.$set.description = changes.description.substring(0, 640*1024) /* 640 k ought to be enough for everybody */
		if (changes.categories) update.$set.categories = changes.categories.slice(0, 20)
		if (changes.name) update.$set.name = changes.name.substring(0, 1000)

		update.$set.time_lastedit = new Date
		if (isNew) {
			/* region cannot be changed */
			update.$set.region = Regions.findOne({_id: changes.region})
			if (!update.$set.region) throw new Exception(404, 'region missing')

			courseId = Courses.insert({
				participants: [{ user: user._id, roles: [] }],
				createdby: user._id,
				time_created: new Date
			}, checkInsert)
		}
		Courses.update({ _id: courseId }, update, checkUpdateOne)
		return courseId
	}
})

/* Need to find a good place to make these available to all */

function checkInsert(err, id) {
	if (err) throw err
}

function checkUpdateOne(err, aff) {
	if (err) throw err;
	if (aff != 1) throw "Query affected "+aff+" docs, expected 1"
}
<commit_msg>fix syntax<commit_after>// ======== DB-Model: ========3
// "_id" -> ID
// "name" -> string
// "createdby" -> ID_users
// "time_created" -> timestamp
// "time_lastedit" -> timestamp
// "categories" -> ID_categories
// "description" -> string
// "subscribers" -> [ID_users]
// ===========================

Courses = new Meteor.Collection("Courses");

Courses.allow({
	remove: function (userId, doc) {
		return userId && true;   // allow only if UserId is present
	}
});

Meteor.methods({
	change_subscription: function(courseId, role, add) {
		check(role, String)
		check(courseId, String)
		check(add, Boolean)
		var userId = Meteor.userId()
		var course = Courses.findOne({_id: courseId})
		if (!course) throw new Meteor.Error(404, "Course not found")
		if (!userId) {
			// Oops
			if (Meteor.is_client) {
				alert('please log in')
				return;
			} else {
				throw new Meteor.Error(401, "please log in")
			}
		}
		if (!course.roles[role]) throw new Meteor.Error(404, "No role "+role)

		var update = {}
		update[add ? '$addToSet' : '$pull'] = { 'participants.$.roles': role }
		Courses.update({_id: course._id, 'participants.user': userId }, update)
		var time = new Date
		Courses.update(course, { $set: {time_lastenrol:time}})
	},

	save_course: function(courseId, changes) {
		check(courseId, String)
		check(changes, {
			description: Match.Optional(String),
			categories:  Match.Optional([String]),
			name:        Match.Optional(String),
			region:      Match.Optional(String),
			roles:       Match.Optional(Object)
		})
		var user = Meteor.user()
		if (!user) {
			throw new Meteor.Error(401, "please log in")
		}

		var course;
		var isNew = courseId.length == 0
		if (isNew) {
			course = { roles: {  } }
		} else {
			course = Courses.findOne({_id: courseId})
			if (!course) throw new Meteor.Error(404, "Course not found")
		}

 		var mayEdit = isNew || user.isAdmin || Courses.findOne({_id: courseId, roles:{$elemMatch: { user: user._id, roles: 'team' }}})
		if (!mayEdit) throw new Meteor.Error(401, "get lost")

		/* Changes we want to perform */
		var update = {
			$set: {},
			$unset: {},
			$addToSet: { roles: [] },
			$pull: { roles: [], participants: { roles: [] } }
		}

		_.each(Roles.find().fetch(), function(roletype) {
			var type = roletype.type
			var should_have = roletype.preset || changes.roles && changes.roles[type]
			var have = course.roles.indexOf(type) !== -1
			if (have && !should_have) {
				update.$pull.roles.push(type)
				update.$pull.participants.roles.push(type)
			}
			if (!have && should_have) update.$addToSet.roles.push(type)
		})

		if (changes.description) update.$set.description = changes.description.substring(0, 640*1024) /* 640 k ought to be enough for everybody */
		if (changes.categories) update.$set.categories = changes.categories.slice(0, 20)
		if (changes.name) update.$set.name = changes.name.substring(0, 1000)

		update.$set.time_lastedit = new Date
		if (isNew) {
			/* region cannot be changed */
			update.$set.region = Regions.findOne({_id: changes.region})
			if (!update.$set.region) throw new Exception(404, 'region missing')

			courseId = Courses.insert({
				participants: [{ user: user._id, roles: [] }],
				createdby: user._id,
				time_created: new Date
			}, checkInsert)
		}
		Courses.update({ _id: courseId }, update, checkUpdateOne)
		return courseId
	}
})

/* Need to find a good place to make these available to all */

function checkInsert(err, id) {
	if (err) throw err
}

function checkUpdateOne(err, aff) {
	if (err) throw err;
	if (aff != 1) throw "Query affected "+aff+" docs, expected 1"
}
<|endoftext|>


<commit_before>/*jslint node: true */
'use strict';

var http = require('http');
var Fs = require('fs');
var Rss = require('rss');
var request = require('request');

// global constans
var SITE_URL = 'https://muut.com/comptop';
var FEED_URL = 'https://muut.com/comptop';
var SESSION_ID = "";
var MAINTAINER_EMAIL = 'dave@cs.unc.edu';

// the data to get things going
var fileName = 'data/data-2016-01-19.json';
var extracted_data = {};

function makeEntryData(author, description, postTitle, url, guid, date) {
    return {
        'title': postTitle,
        'description': description,
        'url': url,
        'guid': guid,
        'author': author,
        'date': date
    };
}

function makeEntryErrorData() {
    var author = 'ERROR';
    var description = 'There was an error extracting data from an entry. ' +
        'Please contact ' + MAINTAINER_EMAIL + ' to report an error.';
    var postTitle = 'Error extracting data for an entry';
    var guid = new Date().getTime();
    var date = guid;
    return makeEntryData(author, description, postTitle, guid, date);
}

function extract(entry) {
    var entryData;
    try {
        var seed = entry.seed;
        var author = seed.user.displayname;
        var description = seed.body;
        var postTitle = seed.title;
        var guid = seed.key;
        var date = seed.time;
        entryData = makeEntryData(author, description, postTitle,
                                  SITE_URL, guid, date);
    } catch (error) {
        entryData = makeEntryErrorData();
    }
    return entryData;
}

function createFeed(entries) {
    var feed = new Rss({
        'title': 'Computational Topology Message Board',
        'description': 'RSS feed of the computational topology message board',
        'feed_url': FEED_URL,
        'site_url': SITE_URL
    });

    for (var idx in entries) {
        feed.item(entries[idx]);
    }

    var xml = feed.xml({indent: true});
    return xml;
}

function parseData(response, data) {
    var extractedEntries;
    try {
        var entries = data.result.moots.entries;
        extractedEntries = entries.map(extract);
    } catch (error) {
        extractedEntries = [makeEntryErrorData()];
    }
    var xml = createFeed(extractedEntries);
    response.writeHead(200);
    response.end(xml);
}

function make_mutt_response_processor(client_response) {
        console.log(response.statusCode);
    var mutt_response_processor = function(error, response, body) {
        if (error || response.statusCode != 200) {
            consolse.log(makeEntryErrorData());
        } else {
            parseData(client_response, body);
        }
    };
    return mutt_response_processor;
}

function makeRequest(response) {
    var options = {
        url: 'https://api.muut.com/',
        method: 'POST',
        headers: {'Accept': 'application/json'},
        json: {
            'method': 'init',
            'params':[ {
                'version': '1.14.0',
                'path': '/comptop',
                'currentForum': 'comptop',
                'pageLocation': 'https://muut.com/comptop',
                'expand_all': false,
                'reload': false
            } ],
            'id':'#1',
            'session':{'sessionId': SESSION_ID},
            'jsonrpc':'2.1.0',
            'transport':'upgrade'
        }
    };
    var mutt_response_processor = make_mutt_response_processor(response);
    request(options, mutt_response_processor);
}

// function readFile(error, data) {
//     if (error) {
//         throw error;
//     } else {
//         var jsonData = JSON.parse(data);
//         parseData(jsonData);
//     }
// }
//Fs.readFile(fileName, 'utf8', readFile);

function requestHandler(request, response) {
    makeRequest(response);
}

http.createServer(requestHandler).listen(8080);
<commit_msg>Remove logging <commit_after>/*jslint node: true */
'use strict';

var http = require('http');
var Fs = require('fs');
var Rss = require('rss');
var request = require('request');

// global constans
var SITE_URL = 'https://muut.com/comptop';
var FEED_URL = 'https://muut.com/comptop';
var SESSION_ID = "";
var MAINTAINER_EMAIL = 'dave@cs.unc.edu';

// the data to get things going
var fileName = 'data/data-2016-01-19.json';
var extracted_data = {};

function makeEntryData(author, description, postTitle, url, guid, date) {
    return {
        'title': postTitle,
        'description': description,
        'url': url,
        'guid': guid,
        'author': author,
        'date': date
    };
}

function makeEntryErrorData() {
    var author = 'ERROR';
    var description = 'There was an error extracting data from an entry. ' +
        'Please contact ' + MAINTAINER_EMAIL + ' to report an error.';
    var postTitle = 'Error extracting data for an entry';
    var guid = new Date().getTime();
    var date = guid;
    return makeEntryData(author, description, postTitle, guid, date);
}

function extract(entry) {
    var entryData;
    try {
        var seed = entry.seed;
        var author = seed.user.displayname;
        var description = seed.body;
        var postTitle = seed.title;
        var guid = seed.key;
        var date = seed.time;
        entryData = makeEntryData(author, description, postTitle,
                                  SITE_URL, guid, date);
    } catch (error) {
        entryData = makeEntryErrorData();
    }
    return entryData;
}

function createFeed(entries) {
    var feed = new Rss({
        'title': 'Computational Topology Message Board',
        'description': 'RSS feed of the computational topology message board',
        'feed_url': FEED_URL,
        'site_url': SITE_URL
    });

    for (var idx in entries) {
        feed.item(entries[idx]);
    }

    var xml = feed.xml({indent: true});
    return xml;
}

function parseData(response, data) {
    var extractedEntries;
    try {
        var entries = data.result.moots.entries;
        extractedEntries = entries.map(extract);
    } catch (error) {
        extractedEntries = [makeEntryErrorData()];
    }
    var xml = createFeed(extractedEntries);
    response.writeHead(200);
    response.end(xml);
}

function make_mutt_response_processor(client_response) {
    var mutt_response_processor = function(error, response, body) {
        if (error || response.statusCode != 200) {
            makeEntryErrorData();
        } else {
            parseData(client_response, body);
        }
    };
    return mutt_response_processor;
}

function makeRequest(response) {
    var options = {
        url: 'https://api.muut.com/',
        method: 'POST',
        headers: {'Accept': 'application/json'},
        json: {
            'method': 'init',
            'params':[ {
                'version': '1.14.0',
                'path': '/comptop',
                'currentForum': 'comptop',
                'pageLocation': 'https://muut.com/comptop',
                'expand_all': false,
                'reload': false
            } ],
            'id':'#1',
            'session':{'sessionId': SESSION_ID},
            'jsonrpc':'2.1.0',
            'transport':'upgrade'
        }
    };
    var mutt_response_processor = make_mutt_response_processor(response);
    request(options, mutt_response_processor);
}

// function readFile(error, data) {
//     if (error) {
//         throw error;
//     } else {
//         var jsonData = JSON.parse(data);
//         parseData(jsonData);
//     }
// }
//Fs.readFile(fileName, 'utf8', readFile);

function requestHandler(request, response) {
    makeRequest(response);
}

http.createServer(requestHandler).listen(8080);
<|endoftext|>


<commit_before>/**
 * External dependencies
 */
import { storiesOf } from '@storybook/react';
import { set } from 'lodash';

/**
 * Internal dependencies
 */
import UserInputApp from '../assets/js/components/user-input/UserInputApp';
import { WithTestRegistry, createTestRegistry } from '../tests/js/utils';

storiesOf( 'User Input', module )
	.add( 'User Input Page', () => {
		// Set the featureFlag.
		set( global, 'featureFlags.widgets.userInput.enabled', true );
		return (
			<WithTestRegistry callback={ createTestRegistry }>
				<UserInputApp />
			</WithTestRegistry>
		);
	} )
	.add( 'No Access', () => {
		// Set the featureFlag.
		set( global, 'featureFlags.widgets.userInput.enabled', false );
		return (
			<WithTestRegistry callback={ createTestRegistry }>
				<UserInputApp />
			</WithTestRegistry>
		);
	} );
<commit_msg>Set the featureFlag without using lodash.<commit_after>/**
 * External dependencies
 */
import { storiesOf } from '@storybook/react';

/**
 * Internal dependencies
 */
import UserInputApp from '../assets/js/components/user-input/UserInputApp';
import { WithTestRegistry, createTestRegistry } from '../tests/js/utils';

storiesOf( 'User Input', module )
	.add( 'UserInputApp', () => {
		// Set the featureFlag.
		global.featureFlags = { widgets: { userInput: { enabled: true } } };
		return (
			<WithTestRegistry callback={ createTestRegistry }>
				<UserInputApp />
			</WithTestRegistry>
		);
	} );
<|endoftext|>


<commit_before>YUI.add('api-filter', function (Y) {

Y.APIFilter = Y.Base.create('apiFilter', Y.Base, [Y.AutoCompleteBase], {
    // -- Initializer ----------------------------------------------------------
    initializer: function () {
        this._bindUIACBase();
        this._syncUIACBase();
    },
    getDisplayName: function(name) {
        Y.each(Y.YUIDoc.meta.allModules, function(i) {
            if (i.name === name && i.displayName) {
                name = i.displayName;
            }
        });
        return name;
    }

}, {
    // -- Attributes -----------------------------------------------------------
    ATTRS: {
        resultHighlighter: {
            value: 'phraseMatch'
        },

        // May be set to "enums", "classes" or "modules".
        queryType: {
            value: 'enums'
        },

        source: {
            valueFn: function() {
                var self = this;
                return function(q) {
                    var type = self.get('queryType');
                    var data = Y.YUIDoc.meta[type];
                    return data.sort(function (a, b) {
                        if (!a.module || !b.module) return 0;
                        return a.module > b.module;
                    }).filter(function (item) {
                        return (item.name.toLowerCase().indexOf(q.toLowerCase()) > -1)
                    }).map(function (item) {
                        return item;
                    });
                };
            }
        }
    }
});

}, '3.4.0', {requires: [
    'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources'
]});
<commit_msg>fix sort alogrithm<commit_after>YUI.add('api-filter', function (Y) {

Y.APIFilter = Y.Base.create('apiFilter', Y.Base, [Y.AutoCompleteBase], {
    // -- Initializer ----------------------------------------------------------
    initializer: function () {
        this._bindUIACBase();
        this._syncUIACBase();
    },
    getDisplayName: function(name) {
        Y.each(Y.YUIDoc.meta.allModules, function(i) {
            if (i.name === name && i.displayName) {
                name = i.displayName;
            }
        });
        return name;
    }

}, {
    // -- Attributes -----------------------------------------------------------
    ATTRS: {
        resultHighlighter: {
            value: 'phraseMatch'
        },

        // May be set to "enums", "classes" or "modules".
        queryType: {
            value: 'enums'
        },

        source: {
            valueFn: function() {
                var self = this;
                return function(q) {
                    var type = self.get('queryType');
                    var data = Y.YUIDoc.meta[type];
                    var classifiedData = {};
                    data.filter(function (item) {
                        return (item.name.toLowerCase().indexOf(q.toLowerCase()) > -1)
                    }).forEach(function (item) {
                        if (!classifiedData[item.module])
                            classifiedData[item.module] = [];
                        classifiedData[item.module].push(item);
                    });
                    return Object.keys(classifiedData).sort(function (prev, next) {
                        return prev > next;
                    }).map(function (key) {
                        return classifiedData[key];
                    }).reduce(function (prev, next) {
                        return prev.concat(next);
                    });
                };
            }
        }
    }
});

}, '3.4.0', {requires: [
    'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources'
]});
<|endoftext|>


<commit_before>/* lightbox based on imageLightbox */

function imageLightbox(_a,_b){
	//-------------------------------------------------------- private
	var imageWidth		= 0,
		imageHeight		= 0,
		swipeDiff		= 0,
		image				= $(),
		targets			= [],
		description		= '',
		inProgress		= false
		options			= {},
		targetID			= 0;
	var self = this;
	//-------------------------------------------------------- utility functions
	var cssTransitionSupport = function(){
			var s = document.body || document.documentElement, s = s.style;
			if( s.WebkitTransition == '' ) return '-webkit-';
			if( s.MozTransition == '' ) return '-moz-';
			if( s.OTransition == '' ) return '-o-';
			if( s.transition == '' ) return '';
			return false;
		},
		isCssTransitionSupport = cssTransitionSupport() === false ? false : true,
		cssTransitionTranslateX = function( element, positionX, speed ){
			var options = {}, prefix = cssTransitionSupport();
			options[ prefix + 'transform' ]	 = 'translateX(' + positionX + ')';
			options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear';
			element.css( options );
		},
		hasTouch	= ( 'ontouchstart' in window ),
		hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
		wasTouched	= function(event){
			if( hasTouch ) return true;
			if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) return false;

			if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ){
				if( event.MSPOINTER_TYPE_MOUSE != event.pointerType ) return true;
			}
			else{
				if( event.pointerType != 'mouse' ) return true;
			}
			return false;
		};
	//-------------------------------------------------------- main functions
	//options!!!
	this.setOptions = function(opt){
		options = $.extend(
		{
			selector:			'imagelightbox',
			caption:				'imagelightbox-text',
			specialitems:		['imagelightbox-desc','imagelightbox-text'],
			allowedTypes:		'png|jpg|jpeg|gif',
			animationSpeed:	250,
			preloadNext:		true,
			enableKeyboard:	true,
			quitOnEnd:			false,
			quitOnImgClick: 	false,
			quitOnDocClick: 	true,
			onStart:				false,
			onEnd:				false,
			onLoadStart:		false,
			onLoadEnd:			false,
			fillMode:			2//0 = leave borders, //1 = fill width or height, //2 = fill screen.
		 }, opt )
	};

	this.updateoptions = function(opt){
		options = $.extend(options,opt);
	};

	//targets!!!
	this.setGallery = function(array){
		targets = array;
	}

	//eventually set targets if passed
	if (typeof _b !== 'undefined'){
		this.setOptions(_b);
		this.setGallery(_a);
	}
	//or set only options
	else if (typeof _a !== 'undefined' ) this.setOptions(_a);

	//update image dimensions
	this.setImage = function(){
		if( !image.length ) return true;
		var screenWidth	= $(window).width(),
			screenHeight	= $(window).height(),
			tmpImage			= new Image();
		//when temporary image loaded (may be in cache) update displayed image:
		tmpImage.onload = function(){
			imageWidth		= tmpImage.width;
			imageHeight		= tmpImage.height;
			//set up the displayed image dimensions on screen:
			if (options.fillMode == 0){
				screenWidth	*= 0.9;
				screenHeight *= 0.95;
			}
			if ( imageWidth > screenWidth || imageHeight > screenHeight ){
				var ratio;
				if (options.fillMode == 2){
					if (imageHeight < screenHeight || imageWidth < screenWidth) ratio = 1;
					else ratio = Math.min( imageHeight/screenHeight, imageWidth/screenWidth );
				}
				else {
					ratio	 = imageWidth/imageHeight > screenWidth/screenHeight ? imageWidth/screenWidth : imageHeight/screenHeight;
				}
				imageWidth	/= ratio;
				imageHeight	/= ratio;
			}
			//update image dimension according to window size
			image.css({
				'width':  imageWidth + 'px',
				'height': imageHeight + 'px',
				'top':    ( $( window ).height() - imageHeight ) / 2 + 'px',
				'left':   ( $( window ).width() - imageWidth ) / 2 + 'px'
			});
			//create description
			$('#'+options.caption).html( targets[targetID].desc.replace(/\r\n|\n|\r/g,"
") );
		};
		//start loading image
		tmpImage.src	= image.attr('src');
	};

	this.loadImage = function( direction ){
		if( inProgress ) return false;
		direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1;

		//if there is an image:
		if( image.length ){
			//when quitting the lightbox and stop every script?
			if( direction !== false &&
				( targets.length < 2 ||
					( options.quitOnEnd === true &&
						( ( direction === +1 && targetID == 0 ) || ( direction === -1 && targetID == targets.length-1 ) )
					)
				)
			){
				self.self.quitLightbox();
				return false;
			}
			//animate swifting the current image, then destroy it.
			var params = { 'opacity': 0 };
			if( isCssTransitionSupport ) cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 );
			else params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px';
			image.animate( params, options.animationSpeed, function(){ self.removeImage(); });
			swipeDiff = 0;
		}

		//always, if not quitted the lightbox:
		inProgress = true;
		//run custom script on load image start:
		if( options.onLoadStart !== false ) options.onLoadStart();
		setTimeout( function(){
			//setup "image"
			image = $( '' )
			.load( function(){
				image.appendTo( 'body' );	//create image
				self.setImage();				//set dimensions of image
				//animate swifting the new image
				var params = { 'opacity': 1 };
				image.css( 'opacity', 0 );
				if (isCssTransitionSupport){
					cssTransitionTranslateX( image, -100 * direction + 'px', 0 );
					setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ) }, 50 );
				}
				else{
					var imagePosLeft = parseInt( image.css( 'left' ) );
					params.left = imagePosLeft + 'px';
					image.css( 'left', imagePosLeft - 100 * direction + 'px' );
				}
				image.animate( params, options.animationSpeed, function(){
					inProgress = false;
					if( options.onLoadEnd !== false ) options.onLoadEnd();
				});

				//start preloading next image:
				if( options.preloadNext ){
					var NEXTtargetID = targetID+1;
					if (NEXTtargetID < 0) NEXTtargetID = targets.length-1;
					else if (NEXTtargetID >= targets.length) NEXTtargetID = 0;
					$( '' ).attr( 'src', targets[NEXTtargetID].src ).load();
				}
			})
			.error( function(){
				//in case error occurs, call the custom end-function
				if( options.onLoadEnd !== false ) options.onLoadEnd();
			})
			.attr( 'src', targets[targetID].src )

			//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			//apply touch/click/any other event applyed to the #imagelightbox.
			var swipeStart	 = 0,
				swipeEnd	 = 0,
				imagePosLeft = 0;
			image
			.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function(e){
				e.preventDefault();
				//stop/quit lightbox:
				if( options.quitOnImgClick ){
					self.self.quitLightbox();
					return false;
				}
				if( wasTouched(e.originalEvent) ) return true;
				//get where it was released the pointer:
				var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft;
				targetID += ( imageWidth / 2 > posX ? -1 : 1 );
				if (targetID < 0) targetID = targets.length-1;
				else if (targetID >= targets.length) targetID = 0;
				//load and show next image (prev/next)
				self.loadImage( imageWidth / 2 > posX ? 'left' : 'right' );
			})
			.on( 'touchstart pointerdown MSPointerDown', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) );
				swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
			})
			.on( 'touchmove pointermove MSPointerMove', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				e.preventDefault();
				swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
				swipeDiff = swipeStart - swipeEnd;
				if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 );
				else image.css( 'left', imagePosLeft - swipeDiff + 'px' );
			})
			.on( 'touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				if( Math.abs( swipeDiff ) > 50 ){
					targetID += ( swipeDiff < 0 ? -1 : +1 );
					if (targetID < 0) targetID = targets.length-1;
					else if (targetID >= targets.length) targetID = 0;
					self.loadImage( swipeDiff > 0 ? 'right' : 'left' );
				}
				else{
					if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 );
					else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 );
				}
			});
		},
		options.animationSpeed + 100);
	}

	this.removeImage = function(){
		if( !image.length ) return false;
		image.remove();
		image = $();
	};

	//close lightbox
	this.quitLightbox = function(){
		if( !image.length ) return false;
		image.animate({ 'opacity': 0 }, options.animationSpeed, function(){
			self.removeImage();
			inProgress = false;
			if( options.onEnd !== false ) options.onEnd();
		});
	};

	//html trigger - must have data "id": self.loadImage(targets[id])
	this.addTrigger = function($elem){
		return $elem.click(function(e){
			e.preventDefault();
			if( options.onStart !== false ) options.onStart();
			targetID = Number($(this).data('id'));
			description = $(this).data('desc');
			self.loadImage();
		});
	}

	//-------------------------------------------------------- document ready function
	$(function(){
		//update image dimension on window resizing
		$( window ).on( 'resize', self.setImage );

		//close lightbox if clicking out of #imagelightbox [optional]
		if (options.quitOnDocClick){
			$( document ).on( hasTouch ? 'touchend' : 'click', function(e){
				if( image.length && !$(e.target).is(image) && options.specialitems.indexOf(e.target.id) === -1 ) self.quitLightbox();
			});
		}

		//keyboard arrows
		if( options.enableKeyboard ){
			$( document ).on( 'keyup', function(e){
				if( !image.length ) return true;
				e.preventDefault();
				if( e.keyCode == 27 ) self.quitLightbox();
				if( e.keyCode == 37 || e.keyCode == 39 ){
					targetID += ( e.keyCode == 37 ? -1 : +1 );
					if (targetID < 0) targetID = targets.length-1;
					else if (targetID >= targets.length) targetID = 0;
					self.loadImage( e.keyCode == 37 ? 'left' : 'right' );
				}
			});
		}
	});
}
<commit_msg>Update image-lightbox-like.js<commit_after>/* lightbox based on imageLightbox */

function imageLightbox(_a,_b){
	//-------------------------------------------------------- private
	var imageWidth		= 0,
		imageHeight		= 0,
		swipeDiff		= 0,
		image				= $(),
		targets			= [],
		description		= '',
		inProgress		= false
		options			= {},
		targetID			= 0;
	var self = this;
	//-------------------------------------------------------- utility functions
	var cssTransitionSupport = function(){
			var s = document.body || document.documentElement, s = s.style;
			if( s.WebkitTransition == '' ) return '-webkit-';
			if( s.MozTransition == '' ) return '-moz-';
			if( s.OTransition == '' ) return '-o-';
			if( s.transition == '' ) return '';
			return false;
		},
		isCssTransitionSupport = cssTransitionSupport() === false ? false : true,
		cssTransitionTranslateX = function( element, positionX, speed ){
			var options = {}, prefix = cssTransitionSupport();
			options[ prefix + 'transform' ]	 = 'translateX(' + positionX + ')';
			options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear';
			element.css( options );
		},
		hasTouch	= ( 'ontouchstart' in window ),
		hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
		wasTouched	= function(event){
			if( hasTouch ) return true;
			if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) return false;

			if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ){
				if( event.MSPOINTER_TYPE_MOUSE != event.pointerType ) return true;
			}
			else{
				if( event.pointerType != 'mouse' ) return true;
			}
			return false;
		};
	//-------------------------------------------------------- main functions
	//options!!!
	this.setOptions = function(opt){
		options = $.extend(
		{
			selector:			'imagelightbox',
			caption:				'imagelightbox-text',
			specialitems:		['imagelightbox-desc','imagelightbox-text'],
			allowedTypes:		'png|jpg|jpeg|gif',
			animationSpeed:	250,
			preloadNext:		true,
			enableKeyboard:	true,
			quitOnEnd:			false,
			quitOnImgClick: 	false,
			quitOnDocClick: 	true,
			onStart:				false,
			onEnd:				false,
			onLoadStart:		false,
			onLoadEnd:			false,
			fillMode:			3//0 = leave borders, //1 = fill width or height, //2 = fill screen, //3 = auto adjust
		 }, opt )
	};

	this.updateoptions = function(opt){
		options = $.extend(options,opt);
	};

	//targets!!!
	this.setGallery = function(array){
		targets = array;
	}

	//eventually set targets if passed
	if (typeof _b !== 'undefined'){
		this.setOptions(_b);
		this.setGallery(_a);
	}
	//or set only options
	else if (typeof _a !== 'undefined' ) this.setOptions(_a);

	//update image dimensions
	this.setImage = function(){
		if( !image.length ) return true;
		var screenWidth	= $(window).width(),
			screenHeight	= $(window).height(),
			tmpImage			= new Image();
		//auto fill mode on?
		var fill = options.fillMode;
		if (fill == 3){
			var area = screenWidth * screenHeight / 10000;
			if (area < 35) fill = 2;
			else if (area < 70) fill = 1;
			else fill = 0;
		}
		//when temporary image loaded (may be in cache) update displayed image:
		tmpImage.onload = function(){
			imageWidth		= tmpImage.width;
			imageHeight		= tmpImage.height;
			//set up the displayed image dimensions on screen:
			if (fill == 0){
				screenWidth	*= 0.9;
				screenHeight *= 0.95;
			}
			if ( imageWidth > screenWidth || imageHeight > screenHeight ){
				var ratio;
				if (fill == 2){
					if (imageHeight < screenHeight || imageWidth < screenWidth) ratio = 1;
					else ratio = Math.min( imageHeight/screenHeight, imageWidth/screenWidth );
				}
				else {
					ratio	 = imageWidth/imageHeight > screenWidth/screenHeight ? imageWidth/screenWidth : imageHeight/screenHeight;
				}
				imageWidth	/= ratio;
				imageHeight	/= ratio;
			}
			//update image dimension according to window size
			image.css({
				'width':  imageWidth + 'px',
				'height': imageHeight + 'px',
				'top':    ( $( window ).height() - imageHeight ) / 2 + 'px',
				'left':   ( $( window ).width() - imageWidth ) / 2 + 'px'
			});
			//create description
			$('#'+options.caption).html( targets[targetID].desc.replace(/\r\n|\n|\r/g,"
") );
		};
		//start loading image
		tmpImage.src	= image.attr('src');
	};

	this.loadImage = function( direction ){
		if( inProgress ) return false;
		direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1;

		//if there is an image:
		if( image.length ){
			//when quitting the lightbox and stop every script?
			if( direction !== false &&
				( targets.length < 2 ||
					( options.quitOnEnd === true &&
						( ( direction === +1 && targetID == 0 ) || ( direction === -1 && targetID == targets.length-1 ) )
					)
				)
			){
				self.self.quitLightbox();
				return false;
			}
			//animate swifting the current image, then destroy it.
			var params = { 'opacity': 0 };
			if( isCssTransitionSupport ) cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 );
			else params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px';
			image.animate( params, options.animationSpeed, function(){ self.removeImage(); });
			swipeDiff = 0;
		}

		//always, if not quitted the lightbox:
		inProgress = true;
		//run custom script on load image start:
		if( options.onLoadStart !== false ) options.onLoadStart();
		setTimeout( function(){
			//setup "image"
			image = $( '' )
			.load( function(){
				image.appendTo( 'body' );	//create image
				self.setImage();				//set dimensions of image
				//animate swifting the new image
				var params = { 'opacity': 1 };
				image.css( 'opacity', 0 );
				if (isCssTransitionSupport){
					cssTransitionTranslateX( image, -100 * direction + 'px', 0 );
					setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ) }, 50 );
				}
				else{
					var imagePosLeft = parseInt( image.css( 'left' ) );
					params.left = imagePosLeft + 'px';
					image.css( 'left', imagePosLeft - 100 * direction + 'px' );
				}
				image.animate( params, options.animationSpeed, function(){
					inProgress = false;
					if( options.onLoadEnd !== false ) options.onLoadEnd();
				});

				//start preloading next image:
				if( options.preloadNext ){
					var NEXTtargetID = targetID+1;
					if (NEXTtargetID < 0) NEXTtargetID = targets.length-1;
					else if (NEXTtargetID >= targets.length) NEXTtargetID = 0;
					$( '' ).attr( 'src', targets[NEXTtargetID].src ).load();
				}
			})
			.error( function(){
				//in case error occurs, call the custom end-function
				if( options.onLoadEnd !== false ) options.onLoadEnd();
			})
			.attr( 'src', targets[targetID].src )

			//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			//apply touch/click/any other event applyed to the #imagelightbox.
			var swipeStart	 = 0,
				swipeEnd	 = 0,
				imagePosLeft = 0;
			image
			.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function(e){
				e.preventDefault();
				//stop/quit lightbox:
				if( options.quitOnImgClick ){
					self.self.quitLightbox();
					return false;
				}
				if( wasTouched(e.originalEvent) ) return true;
				//get where it was released the pointer:
				var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft;
				targetID += ( imageWidth / 2 > posX ? -1 : 1 );
				if (targetID < 0) targetID = targets.length-1;
				else if (targetID >= targets.length) targetID = 0;
				//load and show next image (prev/next)
				self.loadImage( imageWidth / 2 > posX ? 'left' : 'right' );
			})
			.on( 'touchstart pointerdown MSPointerDown', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) );
				swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
			})
			.on( 'touchmove pointermove MSPointerMove', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				e.preventDefault();
				swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX;
				swipeDiff = swipeStart - swipeEnd;
				if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 );
				else image.css( 'left', imagePosLeft - swipeDiff + 'px' );
			})
			.on( 'touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function(e){
				if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true;
				if( Math.abs( swipeDiff ) > 50 ){
					targetID += ( swipeDiff < 0 ? -1 : +1 );
					if (targetID < 0) targetID = targets.length-1;
					else if (targetID >= targets.length) targetID = 0;
					self.loadImage( swipeDiff > 0 ? 'right' : 'left' );
				}
				else{
					if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 );
					else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 );
				}
			});
		},
		options.animationSpeed + 100);
	}

	this.removeImage = function(){
		if( !image.length ) return false;
		image.remove();
		image = $();
	};

	//close lightbox
	this.quitLightbox = function(){
		if( !image.length ) return false;
		image.animate({ 'opacity': 0 }, options.animationSpeed, function(){
			self.removeImage();
			inProgress = false;
			if( options.onEnd !== false ) options.onEnd();
		});
	};

	//html trigger - must have data "id": self.loadImage(targets[id])
	this.addTrigger = function($elem){
		return $elem.click(function(e){
			e.preventDefault();
			if( options.onStart !== false ) options.onStart();
			targetID = Number($(this).data('id'));
			description = $(this).data('desc');
			self.loadImage();
		});
	}

	//-------------------------------------------------------- document ready function
	$(function(){
		//update image dimension on window resizing
		$( window ).on( 'resize', self.setImage );

		//close lightbox if clicking out of #imagelightbox [optional]
		if (options.quitOnDocClick){
			$( document ).on( hasTouch ? 'touchend' : 'click', function(e){
				if( image.length && !$(e.target).is(image) && options.specialitems.indexOf(e.target.id) === -1 ) self.quitLightbox();
			});
		}

		//keyboard arrows
		if( options.enableKeyboard ){
			$( document ).on( 'keyup', function(e){
				if( !image.length ) return true;
				e.preventDefault();
				if( e.keyCode == 27 ) self.quitLightbox();
				if( e.keyCode == 37 || e.keyCode == 39 ){
					targetID += ( e.keyCode == 37 ? -1 : +1 );
					if (targetID < 0) targetID = targets.length-1;
					else if (targetID >= targets.length) targetID = 0;
					self.loadImage( e.keyCode == 37 ? 'left' : 'right' );
				}
			});
		}
	});
}
<|endoftext|>