<commit_before>/*global PlayMidnightUtilities, PlayMidnight */
var PlayMidnightOptions = (function(_, PlayMidnight){
    'use strict';

    // Our Friend
    var PMOptions = {};

    var _injected = false,
        _menuOpen = false,
        _backdrop = document.createElement('div'),
        _modal = document.createElement('div'),
        _cb;

    // Various Templates
    var _templates = {};

    _templates.optionsPage = {
        name: 'optionsPage',
        url: _.browser.url('dist/templates/options.html'),
        target: 'body'
    };

    _templates.menuItem = {
        name: 'menuItem',
        url: _.browser.url('dist/templates/options-menu.html'),
        target: '#nav .nav-section:last-child',
        append: 1,
        events: function(ele) {
            ele.addEventListener('click', function(e) {
                // Prevent Click Bubbling to Document
                if (!_menuOpen) {
                    e.stopPropagation();
                }

                showOptions();
            }, false);
        }
    };

    _templates.fabIcon = {
        name: 'fabIcon',
        url: _.browser.url('dist/templates/options-fab.html'),
        target: 'core-header-panel#content-container',
        enabled: function() {
            var userOptions = PlayMidnight.getUserOptions();
            return userOptions.fab;
        },
        events: function(ele) {
            ele.addEventListener('click', function(e) {
                // Prevent Click Bubbling to Document
                if (!_menuOpen) {
                    e.stopPropagation();
                }

                showOptions();
            }, false);
        }
    };

    _templates.recentActivity = {
        name: 'fabIcon',
        url: _.browser.url('dist/templates/menu-recent.html'),
        target: '#nav_collections',
        append: 2,
        enabled: function() {
            var userOptions = PlayMidnight.getUserOptions();
            return userOptions.recent;
        }
    };

    // Load Options Templates and Inject
    function createOptions() {
        _.inject(_templates, function() {
            var userOptions = PlayMidnight.getUserOptions(),
                optionsGraph = PlayMidnight.getOptionsGraph(),
                optionsPage = _templates.optionsPage.element,
                optionsContainer = _templates.optionsPage.element.querySelector('section.options .options-container'),
                frag = buildOptions(optionsGraph, userOptions),
                items;

            optionsContainer.appendChild(frag);
            optionsPage.querySelector('#pm-save-options').addEventListener('click', function() {
                saveOptions(userOptions);
            });

            document.body.classList.add('play-midnight-active');
        });
    }

    // Save Options
    function saveOptions(userOptions) {
        var optionsPage = _templates.optionsPage.element;
        var toSave = optionsPage.querySelectorAll('.play-midnight-option, .play-midnight-collection');
        var saveDialog = optionsPage.querySelector('.save-dialog');
        var options = {};

        for (var i = 0; i < toSave.length; i++) {
            var ele = toSave[i];
            var type = ele.type;
            var key = ele.key;

            if (type === 'boolean') {
                var checked = ele.querySelector('paper-toggle-button::shadow #toggleContainer').hasAttribute('checked');
                options[key] = checked;
            }

            if (type === 'array') {
                var radio = ele.querySelector('.collection input:checked');
                var selected = ele.querySelector('.collection-item.selected');
                var singleKey = ele.single;

                delete selected.item.selected;

                options[key] = ele.collection;
                options[singleKey] = JSON.parse(JSON.stringify(selected.item));
            }
        }

        _.browser.save(options, function(options) {
            _.log('Options Saved Successfully!');

            saveDialog.classList.add('visible');
            setTimeout(function() {
                saveDialog.classList.remove('visible');

                setTimeout(function() {
                    location.reload();
                }, 1000);
            }, 2000);
        });
    }

    // Build Options
    function buildOptions(options, values) {
        var fragment, option, ele;

        fragment = document.createDocumentFragment();

        for (var key in options) {
            if (options.hasOwnProperty(key)) {
                option = options[key];

                if (option.type === 'section') {
                    ele = buildSection(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'array') {
                    ele = buildArray(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'boolean') {
                    ele = buildBoolean(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'string') {
                    if (option.visible !== true) {
                        continue;
                    }

                    ele = buildString(option);
                    fragment.appendChild(ele);
                }
            }
        }

        return fragment;
    }

    // Build Section
    function buildSection(key, option, values) {
        var fragment = document.createDocumentFragment();

        var title = _.createElement('

');
        title.innerText = option.title;

        var content = buildOptions(option.options, values);

        fragment.appendChild(title);
        fragment.appendChild(content);

        return fragment;
    }

    // Build string
    function buildString(option) {
        var text = _.createElement('

');
        text.innerHTML = option.description;

        return text;
    }

    // Build Array
    function buildArray(key, option, values) {
        var fragment = document.createDocumentFragment();

        var singleKey = option.single;
        var collection = [];
        var collectionEle = _.createElement('

');

        // Full Container
        var container = _.createElement('

');
        container.type = option.type;
        container.key = key;
        container.single = singleKey;
        container.default = option.default;
        container.collection = collection;
        container.collectionEle = collectionEle;

        // Build Header
        var details = _.createElement('

');
        var title = document.createTextNode(option.title);
        var description = document.createTextNode(option.description);
        details.querySelector('.option-name').appendChild(title);
        details.querySelector('.option-description').appendChild(description);

        if (option.createable === true) {
            var button = _.createElement('<sj-paper-button class="material-primary" role="button"><svg viewBox="0 0 24 24" height="100%" width="100%" preserveAspectRatio="xMidYMid meet" fit="" style="pointer-events: none; display: block;"><g><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g></svg></sj-paper-button>');
            var form = buildForm(singleKey, option);

            button.addEventListener('click', function() {
                form.classList.toggle('visible');
            });

            details.appendChild(button);

            container.appendChild(details);
            container.appendChild(form);
        } else {
            container.appendChild(details);
        }

        // Build Collection
        var initialCollection = values[key];
        for (var i = 0, len = initialCollection.length; i < len; i++) {
            var item = initialCollection[i];
            item.selected = _.equalObjects(item, values[singleKey]);

            createCollectionItem(item, collection, collectionEle, singleKey);
        }

        container.appendChild(collectionEle);
        fragment.appendChild(container);

        return fragment;
    }

    function createCollectionItem(item, collection, collectionEle, key) {
        if (collection.indexOf(item) > -1) {
            return;
        }

        var collectionItem = _.createElement('

<input type="radio" />

');
        collectionItem.classList.add(key);
        collectionItem.item = item;

        var radio = collectionItem.querySelector('input');
        radio.name = key;

        if (item.selected === true) {
            collectionItem.classList.add('selected');
            radio.checked = true;
        }

        // Build Up Keys
        for (var metaKey in item) {
            if (item.hasOwnProperty(metaKey)) {
                var meta = item[metaKey];

                if (metaKey === 'selected') {
                    continue;
                }

                if (metaKey === 'color') {
                    collectionItem.style.background = meta;
                }

                var itemField = _.createElement('

');
                itemField.classList.add('field-' + metaKey);
                itemField.innerText = meta;

                collectionItem.querySelector('.fields').appendChild(itemField);
            }
        }

        collection.push(item);
        collectionEle.appendChild(collectionItem);

        _.log('New Accent: %s', JSON.stringify(item));
        _.log('Collection: %s', JSON.stringify(collection));

        var deleteBtn = collectionItem.querySelector('.remove-item');
        deleteBtn.addEventListener('click', function(e) {
            e.stopPropagation();

            var item = this.parentNode;
            removeFromCollection(item);
        });

        collectionItem.addEventListener('click', function(e) {
            var selected = this.parentNode.querySelector('.selected');

            if (selected) {
                selected.classList.remove('selected');
            }

            this.classList.add('selected');
            this.querySelector('input').checked = true;
        });
    }

    // Build Form
    function buildForm(key, option) {
        var form = _.createElement('<form class="add-new" action="javascript:;"></form>');
        form.key = key;

        var title = _.createElement('
Add New ' + _.toTitleCase(option.single) + '
');
        form.appendChild(title);

        var singleOption = option.default;

        for (var meta in singleOption) {
            if (singleOption.hasOwnProperty(meta)) {
                var field = _.createElement('
<paper-input-decorator label="" floatinglabel><input type="text" is="core-input" autofocus="" placeholder="" aria-label="" no-focus=""></paper-input-decorator>
');
                var input = field.querySelector('paper-input-decorator');
                input.setAttribute('label', _.toTitleCase(meta));
                input.setAttribute('aria-label', _.toTitleCase(meta));
                input.querySelector('input').id = meta;

                if (meta === 'color') {
                    input.setAttribute('label', 'Color - #xxx, #xxxxxx, rgb(x,x,x)');
                    input.setAttribute('aria-label', 'Color - #xxx, #xxxxxx, rgb(x,x,x)');
                }

                form.appendChild(field);
            }
        }

        var button = _.createElement('
<sj-paper-button class="material-primary" role="button" tabindex="0" no-focus=""></sj-paper-button>
');
        button.querySelector('sj-paper-button').innerText = 'Create ' + _.toTitleCase(option.single);

        button.addEventListener('click', function() {
            var fields = form.querySelectorAll('input');

            if (addToCollection(form)) {
                for (var i = 0; i < fields.length; i++) {
                    var input = fields[i];

                    input.value = '';
                    input.setAttribute('no-focus', '');
                }

                form.classList.remove('visible');
            }
        });

        form.appendChild(button);

        return form;
    }

    // Add To Collection
    function addToCollection(form) {
        var collectionDiv = _.getParentElement(form, 'play-midnight-collection');
        var inputs = form.querySelectorAll('input');
        var collection = collectionDiv.collection;
        var collectionEle = collectionDiv.collectionEle;
        var key = form.key;
        var item = {};

        for (var i = 0; i < inputs.length; i++) {
            var ele = inputs[i];
            var meta = ele.id;
            var val = ele.value;

            item[meta] = val;

            if (val.length < 1) {
                return false;
            }

            if (meta === 'color') {
                if (!/(?:^#[a-fA-F\d]{6}$)|(?:^#[a-fA-F\d]{3}$)|(?:^rgb\([ ]*?([\d]{1,3})[ ]*?,[ ]*?([\d]{1,3})[ ]*?,[ ]*?([\d]{1,3})[ ]*?\)$)/.test(val)) {
                    return false;
                }
            }
        }

        createCollectionItem(item, collection, collectionEle, key);
        return true;
    }

    // Remove From Collection
    function removeFromCollection(single) {
        var collectionDiv = _.getParentElement(single, 'play-midnight-collection');
        var key = collectionDiv.single;
        var collection = collectionDiv.collection;
        var collectionEle = collectionDiv.collectionEle;
        var collectionDefault = collectionDiv.default;
        var selected = single.classList.contains('selected');

        _.log('Removed Accent: %s', JSON.stringify(single.item));

        _.remove(single);
        collection.splice(collection.indexOf(single.item), 1);

        if (collectionEle.children.length < 1) {
            createCollectionItem(collectionDefault, collection, collectionEle, key);
        }

        if (selected) {
            collectionEle.children[0].click();
        }

        _.log('Collection: %s', JSON.stringify(collection));
    }

    // Build Boolean
    function buildBoolean(key, option, values) {
        var fragment = document.createDocumentFragment();

        var details = _.createElement('

<paper-toggle-button data-id="" checked="" data-original-value="" role="button" aria-pressed="" tabindex="0" touch-action="pan-y" no-focus=""></paper-toggle-button>
');
        var title = document.createTextNode(option.title);
        var description = document.createTextNode(option.description);
        details.querySelector('.option-name').appendChild(title);
        details.querySelector('.option-description').appendChild(description);
        details.key = key;
        details.type = option.type;

        var checkbox = details.querySelector('paper-toggle-button');
        checkbox.setAttribute('data-id', key);
        checkbox.setAttribute('data-original-value', values[key] || false);
        checkbox.setAttribute('checked', values[key] || false);

        fragment.appendChild(details);

        return fragment;
    }

    // Listener for Document.click when Menu is open
    function handleClick(e) {
        if (_menuOpen && !_.isClicked(e.target, _templates.optionsPage.element)) {
            hideOptions();
        }
    }

    // Show Options Page
    function showOptions() {
        document.addEventListener('click', handleClick, false);
        document.body.classList.add('is-pm-options');
        _menuOpen = true;
    }

    // Hide Options Page
    function hideOptions() {
        document.removeEventListener('click', handleClick);
        document.body.classList.remove('is-pm-options');
        _menuOpen = false;
    }

    // Parse Template html to fix relative paths
    function parseTemplate(template) {
        template = template.replace(/\{CHROME_DIR\}/g, _.browser.url('/dist'));
        template = template.replace(/\{VERSION_NUMBER\}/g, _.browser.url('/dist'));

        return _.createElement(template);
    }

    // Add Options to Object
    PMOptions.create = createOptions;
    PMOptions.show = showOptions;
    PMOptions.hide = hideOptions;

    // Add To Core
    PlayMidnight.Options = PMOptions;

    // Return Object for Modularity
    return PMOptions;
})(PlayMidnightUtilities, PlayMidnight);
<commit_msg>Removed too specific selector to work with polymer<commit_after>/*global PlayMidnightUtilities, PlayMidnight */
var PlayMidnightOptions = (function(_, PlayMidnight){
    'use strict';

    // Our Friend
    var PMOptions = {};

    var _injected = false,
        _menuOpen = false,
        _backdrop = document.createElement('div'),
        _modal = document.createElement('div'),
        _cb;

    // Various Templates
    var _templates = {};

    _templates.optionsPage = {
        name: 'optionsPage',
        url: _.browser.url('dist/templates/options.html'),
        target: 'body'
    };

    _templates.menuItem = {
        name: 'menuItem',
        url: _.browser.url('dist/templates/options-menu.html'),
        target: '#nav .nav-section:last-child',
        append: 1,
        events: function(ele) {
            ele.addEventListener('click', function(e) {
                // Prevent Click Bubbling to Document
                if (!_menuOpen) {
                    e.stopPropagation();
                }

                showOptions();
            }, false);
        }
    };

    _templates.fabIcon = {
        name: 'fabIcon',
        url: _.browser.url('dist/templates/options-fab.html'),
        target: '#content-container',
        enabled: function() {
            var userOptions = PlayMidnight.getUserOptions();
            return userOptions.fab;
        },
        events: function(ele) {
            ele.addEventListener('click', function(e) {
                // Prevent Click Bubbling to Document
                if (!_menuOpen) {
                    e.stopPropagation();
                }

                showOptions();
            }, false);
        }
    };

    _templates.recentActivity = {
        name: 'fabIcon',
        url: _.browser.url('dist/templates/menu-recent.html'),
        target: '#nav_collections',
        append: 2,
        enabled: function() {
            var userOptions = PlayMidnight.getUserOptions();
            return userOptions.recent;
        }
    };

    // Load Options Templates and Inject
    function createOptions() {
        _.inject(_templates, function() {
            var userOptions = PlayMidnight.getUserOptions(),
                optionsGraph = PlayMidnight.getOptionsGraph(),
                optionsPage = _templates.optionsPage.element,
                optionsContainer = _templates.optionsPage.element.querySelector('section.options .options-container'),
                frag = buildOptions(optionsGraph, userOptions),
                items;

            optionsContainer.appendChild(frag);
            optionsPage.querySelector('#pm-save-options').addEventListener('click', function() {
                saveOptions(userOptions);
            });

            document.body.classList.add('play-midnight-active');
        });
    }

    // Save Options
    function saveOptions(userOptions) {
        var optionsPage = _templates.optionsPage.element;
        var toSave = optionsPage.querySelectorAll('.play-midnight-option, .play-midnight-collection');
        var saveDialog = optionsPage.querySelector('.save-dialog');
        var options = {};

        for (var i = 0; i < toSave.length; i++) {
            var ele = toSave[i];
            var type = ele.type;
            var key = ele.key;

            if (type === 'boolean') {
                var checked = ele.querySelector('paper-toggle-button::shadow #toggleContainer').hasAttribute('checked');
                options[key] = checked;
            }

            if (type === 'array') {
                var radio = ele.querySelector('.collection input:checked');
                var selected = ele.querySelector('.collection-item.selected');
                var singleKey = ele.single;

                delete selected.item.selected;

                options[key] = ele.collection;
                options[singleKey] = JSON.parse(JSON.stringify(selected.item));
            }
        }

        _.browser.save(options, function(options) {
            _.log('Options Saved Successfully!');

            saveDialog.classList.add('visible');
            setTimeout(function() {
                saveDialog.classList.remove('visible');

                setTimeout(function() {
                    location.reload();
                }, 1000);
            }, 2000);
        });
    }

    // Build Options
    function buildOptions(options, values) {
        var fragment, option, ele;

        fragment = document.createDocumentFragment();

        for (var key in options) {
            if (options.hasOwnProperty(key)) {
                option = options[key];

                if (option.type === 'section') {
                    ele = buildSection(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'array') {
                    ele = buildArray(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'boolean') {
                    ele = buildBoolean(key, option, values);
                    fragment.appendChild(ele);
                }

                if (option.type === 'string') {
                    if (option.visible !== true) {
                        continue;
                    }

                    ele = buildString(option);
                    fragment.appendChild(ele);
                }
            }
        }

        return fragment;
    }

    // Build Section
    function buildSection(key, option, values) {
        var fragment = document.createDocumentFragment();

        var title = _.createElement('

');
        title.innerText = option.title;

        var content = buildOptions(option.options, values);

        fragment.appendChild(title);
        fragment.appendChild(content);

        return fragment;
    }

    // Build string
    function buildString(option) {
        var text = _.createElement('

');
        text.innerHTML = option.description;

        return text;
    }

    // Build Array
    function buildArray(key, option, values) {
        var fragment = document.createDocumentFragment();

        var singleKey = option.single;
        var collection = [];
        var collectionEle = _.createElement('

');

        // Full Container
        var container = _.createElement('

');
        container.type = option.type;
        container.key = key;
        container.single = singleKey;
        container.default = option.default;
        container.collection = collection;
        container.collectionEle = collectionEle;

        // Build Header
        var details = _.createElement('

');
        var title = document.createTextNode(option.title);
        var description = document.createTextNode(option.description);
        details.querySelector('.option-name').appendChild(title);
        details.querySelector('.option-description').appendChild(description);

        if (option.createable === true) {
            var button = _.createElement('<sj-paper-button class="material-primary" role="button"><svg viewBox="0 0 24 24" height="100%" width="100%" preserveAspectRatio="xMidYMid meet" fit="" style="pointer-events: none; display: block;"><g><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g></svg></sj-paper-button>');
            var form = buildForm(singleKey, option);

            button.addEventListener('click', function() {
                form.classList.toggle('visible');
            });

            details.appendChild(button);

            container.appendChild(details);
            container.appendChild(form);
        } else {
            container.appendChild(details);
        }

        // Build Collection
        var initialCollection = values[key];
        for (var i = 0, len = initialCollection.length; i < len; i++) {
            var item = initialCollection[i];
            item.selected = _.equalObjects(item, values[singleKey]);

            createCollectionItem(item, collection, collectionEle, singleKey);
        }

        container.appendChild(collectionEle);
        fragment.appendChild(container);

        return fragment;
    }

    function createCollectionItem(item, collection, collectionEle, key) {
        if (collection.indexOf(item) > -1) {
            return;
        }

        var collectionItem = _.createElement('

<input type="radio" />

');
        collectionItem.classList.add(key);
        collectionItem.item = item;

        var radio = collectionItem.querySelector('input');
        radio.name = key;

        if (item.selected === true) {
            collectionItem.classList.add('selected');
            radio.checked = true;
        }

        // Build Up Keys
        for (var metaKey in item) {
            if (item.hasOwnProperty(metaKey)) {
                var meta = item[metaKey];

                if (metaKey === 'selected') {
                    continue;
                }

                if (metaKey === 'color') {
                    collectionItem.style.background = meta;
                }

                var itemField = _.createElement('

');
                itemField.classList.add('field-' + metaKey);
                itemField.innerText = meta;

                collectionItem.querySelector('.fields').appendChild(itemField);
            }
        }

        collection.push(item);
        collectionEle.appendChild(collectionItem);

        _.log('New Accent: %s', JSON.stringify(item));
        _.log('Collection: %s', JSON.stringify(collection));

        var deleteBtn = collectionItem.querySelector('.remove-item');
        deleteBtn.addEventListener('click', function(e) {
            e.stopPropagation();

            var item = this.parentNode;
            removeFromCollection(item);
        });

        collectionItem.addEventListener('click', function(e) {
            var selected = this.parentNode.querySelector('.selected');

            if (selected) {
                selected.classList.remove('selected');
            }

            this.classList.add('selected');
            this.querySelector('input').checked = true;
        });
    }

    // Build Form
    function buildForm(key, option) {
        var form = _.createElement('<form class="add-new" action="javascript:;"></form>');
        form.key = key;

        var title = _.createElement('
Add New ' + _.toTitleCase(option.single) + '
');
        form.appendChild(title);

        var singleOption = option.default;

        for (var meta in singleOption) {
            if (singleOption.hasOwnProperty(meta)) {
                var field = _.createElement('
<paper-input-decorator label="" floatinglabel><input type="text" is="core-input" autofocus="" placeholder="" aria-label="" no-focus=""></paper-input-decorator>
');
                var input = field.querySelector('paper-input-decorator');
                input.setAttribute('label', _.toTitleCase(meta));
                input.setAttribute('aria-label', _.toTitleCase(meta));
                input.querySelector('input').id = meta;

                if (meta === 'color') {
                    input.setAttribute('label', 'Color - #xxx, #xxxxxx, rgb(x,x,x)');
                    input.setAttribute('aria-label', 'Color - #xxx, #xxxxxx, rgb(x,x,x)');
                }

                form.appendChild(field);
            }
        }

        var button = _.createElement('
<sj-paper-button class="material-primary" role="button" tabindex="0" no-focus=""></sj-paper-button>
');
        button.querySelector('sj-paper-button').innerText = 'Create ' + _.toTitleCase(option.single);

        button.addEventListener('click', function() {
            var fields = form.querySelectorAll('input');

            if (addToCollection(form)) {
                for (var i = 0; i < fields.length; i++) {
                    var input = fields[i];

                    input.value = '';
                    input.setAttribute('no-focus', '');
                }

                form.classList.remove('visible');
            }
        });

        form.appendChild(button);

        return form;
    }

    // Add To Collection
    function addToCollection(form) {
        var collectionDiv = _.getParentElement(form, 'play-midnight-collection');
        var inputs = form.querySelectorAll('input');
        var collection = collectionDiv.collection;
        var collectionEle = collectionDiv.collectionEle;
        var key = form.key;
        var item = {};

        for (var i = 0; i < inputs.length; i++) {
            var ele = inputs[i];
            var meta = ele.id;
            var val = ele.value;

            item[meta] = val;

            if (val.length < 1) {
                return false;
            }

            if (meta === 'color') {
                if (!/(?:^#[a-fA-F\d]{6}$)|(?:^#[a-fA-F\d]{3}$)|(?:^rgb\([ ]*?([\d]{1,3})[ ]*?,[ ]*?([\d]{1,3})[ ]*?,[ ]*?([\d]{1,3})[ ]*?\)$)/.test(val)) {
                    return false;
                }
            }
        }

        createCollectionItem(item, collection, collectionEle, key);
        return true;
    }

    // Remove From Collection
    function removeFromCollection(single) {
        var collectionDiv = _.getParentElement(single, 'play-midnight-collection');
        var key = collectionDiv.single;
        var collection = collectionDiv.collection;
        var collectionEle = collectionDiv.collectionEle;
        var collectionDefault = collectionDiv.default;
        var selected = single.classList.contains('selected');

        _.log('Removed Accent: %s', JSON.stringify(single.item));

        _.remove(single);
        collection.splice(collection.indexOf(single.item), 1);

        if (collectionEle.children.length < 1) {
            createCollectionItem(collectionDefault, collection, collectionEle, key);
        }

        if (selected) {
            collectionEle.children[0].click();
        }

        _.log('Collection: %s', JSON.stringify(collection));
    }

    // Build Boolean
    function buildBoolean(key, option, values) {
        var fragment = document.createDocumentFragment();

        var details = _.createElement('

<paper-toggle-button data-id="" checked="" data-original-value="" role="button" aria-pressed="" tabindex="0" touch-action="pan-y" no-focus=""></paper-toggle-button>
');
        var title = document.createTextNode(option.title);
        var description = document.createTextNode(option.description);
        details.querySelector('.option-name').appendChild(title);
        details.querySelector('.option-description').appendChild(description);
        details.key = key;
        details.type = option.type;

        var checkbox = details.querySelector('paper-toggle-button');
        checkbox.setAttribute('data-id', key);
        checkbox.setAttribute('data-original-value', values[key] || false);
        checkbox.setAttribute('checked', values[key] || false);

        fragment.appendChild(details);

        return fragment;
    }

    // Listener for Document.click when Menu is open
    function handleClick(e) {
        if (_menuOpen && !_.isClicked(e.target, _templates.optionsPage.element)) {
            hideOptions();
        }
    }

    // Show Options Page
    function showOptions() {
        document.addEventListener('click', handleClick, false);
        document.body.classList.add('is-pm-options');
        _menuOpen = true;
    }

    // Hide Options Page
    function hideOptions() {
        document.removeEventListener('click', handleClick);
        document.body.classList.remove('is-pm-options');
        _menuOpen = false;
    }

    // Parse Template html to fix relative paths
    function parseTemplate(template) {
        template = template.replace(/\{CHROME_DIR\}/g, _.browser.url('/dist'));
        template = template.replace(/\{VERSION_NUMBER\}/g, _.browser.url('/dist'));

        return _.createElement(template);
    }

    // Add Options to Object
    PMOptions.create = createOptions;
    PMOptions.show = showOptions;
    PMOptions.hide = hideOptions;

    // Add To Core
    PlayMidnight.Options = PMOptions;

    // Return Object for Modularity
    return PMOptions;
})(PlayMidnightUtilities, PlayMidnight);
<|endoftext|>


<commit_before>import {connect} from 'react-redux';

import {getPost} from '../actions';
import Post from '../components/post';

export default connect(
    state => {
        const post = state.posts.post;

        return {
            pending: post.pending,
            post: post.post,
            errors: post.errors,
            authenticated: !!state.membership.auth.user
        };
    },
    dispatch => ({
        onGetPost: slug => dispatch(getPost(slug))
        // onComment: message => dispatch(addComment(message))
    })
)(Post);<commit_msg>Linked post container on add comment event to action.<commit_after>import {connect} from 'react-redux';

import {getPost, addComment} from '../actions';
import Post from '../components/post';

export default connect(
    state => {
        const post = state.posts.post;

        return {
            pending: post.pending,
            post: post.post,
            errors: post.errors,
            authenticated: !!state.membership.auth.user
        };
    },
    dispatch => ({
        onGetPost: slug => dispatch(getPost(slug)),
        onAddComment: message => dispatch(addComment(message))
    })
)(Post);<|endoftext|>


<commit_before>angular
  .module("animeHub")
  .service('TokenService', TokenService);

TokenService.$inject = ['$window', 'jwtHelper'];
function TokenService($window, jwtHelper) {
  var self = this;

  self.saveUserToken = function(token) {
    $window.localStorage.setItem('userToken', token);
  };

  self.getUserToken = function() {
    return $window.localStorage.getItem('userToken');
  };

}<commit_msg>remove user token method<commit_after>angular
  .module("animeHub")
  .service('TokenService', TokenService);

TokenService.$inject = ['$window', 'jwtHelper'];
function TokenService($window, jwtHelper) {
  var self = this;

  self.saveUserToken = function(token) {
    $window.localStorage.setItem('userToken', token);
  };

  self.getUserToken = function() {
    return $window.localStorage.getItem('userToken');
  };

  self.removeUserToken = function() {
    $window.localStorage.removeItem('userToken');
  };

}<|endoftext|>


<commit_before>/*
 * Copyright 2015 Trim-marks Inc.
 *
 * This file is part of Vivliostyle UI.
 *
 * Vivliostyle UI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Vivliostyle UI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Vivliostyle UI.  If not, see <http://www.gnu.org/licenses/>.
 */

import stringUtil from "../utils/string-util"

function getRegExpForParameter(name) {
    return new RegExp(`[#&]${stringUtil.escapeUnicodeString(name)}=([^&]*)`, "g");
}

class URLParameterStore {
    constructor() {
        this.history = window ? window.history : {};
        this.location = window ? window.location : {url: ""};
    }

    getBaseURL() {
        let url = this.location.href;
        url = url.replace(/#.*$/, "");
        return url.replace(/\/[^/]*$/, "/");
    }

    getParameter(name, dontPercentDecode) {
        const url = this.location.href;
        const regexp = getRegExpForParameter(name);
        const results = [];
        let r;
        while (r = regexp.exec(url)) {
            let value = r[1];
            if (!dontPercentDecode) value = stringUtil.percentDecodeAmpersandAndPercent(value);
            results.push(value);
        }
        return results;
    }

    setParameter(name, value, dontPercentEncode) {
        const url = this.location.href;
        if (!dontPercentEncode) value = stringUtil.percentEncodeAmpersandAndPercent(value);
        let updated;
        const regexp = getRegExpForParameter(name);
        const r = regexp.exec(url);
        if (r) {
            const l = r[1].length;
            const start = r.index + r[0].length - l;
            updated = url.substring(0, start) + value + url.substring(start + l);
        } else {
            updated = `${url + (url.match(/#/) ? "&" : "#") + name}=${value}`;
        }
        if (this.history.replaceState) {
            this.history.replaceState(null, "", updated);
        } else {
            this.location.href = updated;
        }
    }

    removeParameter(name) {
        const url = this.location.href;
        let updated;
        const regexp = getRegExpForParameter(name);
        const r = regexp.exec(url);
        if (r) {
            const end = r.index + r[0].length;
            if (r[0].charAt(0) == '#') {
                updated = url.substring(0, r.index + 1) + url.substring(end + 1);
            } else {
                updated = url.substring(0, r.index) + url.substring(end);
            }
        }
        if (this.history.replaceState) {
            this.history.replaceState(null, "", updated);
        } else {
            this.location.href = updated;
        }
    }
}

export default new URLParameterStore();
<commit_msg>fix the bug that the location.href may be set to undefined<commit_after>/*
 * Copyright 2015 Trim-marks Inc.
 *
 * This file is part of Vivliostyle UI.
 *
 * Vivliostyle UI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Vivliostyle UI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Vivliostyle UI.  If not, see <http://www.gnu.org/licenses/>.
 */

import stringUtil from "../utils/string-util"

function getRegExpForParameter(name) {
    return new RegExp(`[#&]${stringUtil.escapeUnicodeString(name)}=([^&]*)`, "g");
}

class URLParameterStore {
    constructor() {
        this.history = window ? window.history : {};
        this.location = window ? window.location : {url: ""};
    }

    getBaseURL() {
        let url = this.location.href;
        url = url.replace(/#.*$/, "");
        return url.replace(/\/[^/]*$/, "/");
    }

    getParameter(name, dontPercentDecode) {
        const url = this.location.href;
        const regexp = getRegExpForParameter(name);
        const results = [];
        let r;
        while (r = regexp.exec(url)) {
            let value = r[1];
            if (!dontPercentDecode) value = stringUtil.percentDecodeAmpersandAndPercent(value);
            results.push(value);
        }
        return results;
    }

    setParameter(name, value, dontPercentEncode) {
        const url = this.location.href;
        if (!dontPercentEncode) value = stringUtil.percentEncodeAmpersandAndPercent(value);
        let updated;
        const regexp = getRegExpForParameter(name);
        const r = regexp.exec(url);
        if (r) {
            const l = r[1].length;
            const start = r.index + r[0].length - l;
            updated = url.substring(0, start) + value + url.substring(start + l);
        } else {
            updated = `${url + (url.match(/#/) ? "&" : "#") + name}=${value}`;
        }
        if (this.history.replaceState) {
            this.history.replaceState(null, "", updated);
        } else {
            this.location.href = updated;
        }
    }

    removeParameter(name) {
        const url = this.location.href;
        let updated;
        const regexp = getRegExpForParameter(name);
        const r = regexp.exec(url);
        if (r) {
            const end = r.index + r[0].length;
            if (r[0].charAt(0) == '#') {
                updated = url.substring(0, r.index + 1) + url.substring(end + 1);
            } else {
                updated = url.substring(0, r.index) + url.substring(end);
            }
            if (this.history.replaceState) {
                this.history.replaceState(null, "", updated);
            } else {
                this.location.href = updated;
            }
        }
    }
}

export default new URLParameterStore();
<|endoftext|>


<commit_before>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function ($) {

  /**
   * Defer Global Function
   */
  function defer(method) {
    if (window.jQuery) {
      method();
    } else {
      setTimeout(function () {
        defer(method);
      }, 50);
    }
  }

  /**
   * Caching Global Selectors
   */
  var $window = $(window);
  var $document = $(document);

  // Use this variable to set up the base and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function () {
        // JavaScript to be fired on all pages

        // Automatic Footer Columns
        function footerColumns() {
          var footerCols = $('footer section');
          var footerColsNum = parseInt(footerCols.length);
          var columnWidth = (footerColsNum === '5') ? '15' : 12 / footerColsNum;
          footerCols.each(function () {
            $(this).addClass('col-md-' + columnWidth);
          });
        }

        footerColumns();

        // outerHTML function
        $.fn.outerHTML = function () {
          return (this[0]) ? this[0].outerHTML : '';
        };
      },
      finalize: function () {
        // JavaScript to be fired on all pages, after page specific JS is fired

        /**
         * Fixed Navbar
         */
        var $nav = $('.navbar');
        var navbarHeight = $nav.innerHeight();

        $nav.affix({
          offset: {
            top: navbarHeight
          }
        });

        // Back To Top
        var offset = 300,
          //browser window scroll (in pixels) after which the "back to top" link opacity is reduced
          offset_opacity = 1200,
          //duration of the top scrolling animation (in ms)
          scroll_top_duration = 700,
          //grab the "back to top" link
          $back_to_top = $('.back-to-top');

        //hide or show the "back to top" link
        $window.scroll(function () {
          if ($(this).scrollTop() > offset) {
            $back_to_top.addClass('cd-is-visible');
          } else {
            $back_to_top.removeClass('cd-is-visible cd-fade-out');
          }
          if ($(this).scrollTop() > offset_opacity) {
            $back_to_top.addClass('cd-fade-out');
          }
        });

        /**
         * Smooth scroll to top
         */
        $back_to_top.on('click', function (event) {
          event.preventDefault();
          $('body,html').animate({
              scrollTop: 0,
            }, scroll_top_duration
          );
        });

      }
    },
    // Home page
    'home': {
      init: function () {
        // JavaScript to be fired on the home page
      },
      finalize: function () {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function () {
        // JavaScript to be fired on the about us page
      }
    }
  };

  // The routing fires all common scripts, followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function (func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function () {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function (i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<commit_msg>add detect mobile function<commit_after>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function ($) {

  /**
   * Defer Global Function
   */
  function defer(method) {
    if (window.jQuery) {
      method();
    } else {
      setTimeout(function () {
        defer(method);
      }, 50);
    }
  }

  /**
   * Caching Global Selectors
   */
  var $window = $(window);
  var $document = $(document);

  /**
   * Detect mobile
   * @type {boolean}
   */
  var isMobile = false; //initiate as false

  // device detection
  if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0, 4))) {
    isMobile = true;
  }

  // Use this variable to set up the base and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function () {
        // JavaScript to be fired on all pages

        // Automatic Footer Columns
        function footerColumns() {
          var footerCols = $('footer section');
          var footerColsNum = parseInt(footerCols.length);
          var columnWidth = (footerColsNum === '5') ? '15' : 12 / footerColsNum;
          footerCols.each(function () {
            $(this).addClass('col-md-' + columnWidth);
          });
        }

        footerColumns();

        // outerHTML function
        $.fn.outerHTML = function () {
          return (this[0]) ? this[0].outerHTML : '';
        };
      },
      finalize: function () {
        // JavaScript to be fired on all pages, after page specific JS is fired

        /**
         * Fixed Navbar
         */
        var $nav = $('.navbar');
        var navbarHeight = $nav.innerHeight();

        $nav.affix({
          offset: {
            top: navbarHeight
          }
        });

        // Back To Top
        var offset = 300,
          //browser window scroll (in pixels) after which the "back to top" link opacity is reduced
          offset_opacity = 1200,
          //duration of the top scrolling animation (in ms)
          scroll_top_duration = 700,
          //grab the "back to top" link
          $back_to_top = $('.back-to-top');

        //hide or show the "back to top" link
        $window.scroll(function () {
          if ($(this).scrollTop() > offset) {
            $back_to_top.addClass('cd-is-visible');
          } else {
            $back_to_top.removeClass('cd-is-visible cd-fade-out');
          }
          if ($(this).scrollTop() > offset_opacity) {
            $back_to_top.addClass('cd-fade-out');
          }
        });

        /**
         * Smooth scroll to top
         */
        $back_to_top.on('click', function (event) {
          event.preventDefault();
          $('body,html').animate({
              scrollTop: 0,
            }, scroll_top_duration
          );
        });

      }
    },
    // Home page
    'home': {
      init: function () {
        // JavaScript to be fired on the home page
      },
      finalize: function () {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function () {
        // JavaScript to be fired on the about us page
      }
    }
  };

  // The routing fires all common scripts, followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function (func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function () {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function (i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<|endoftext|>


<commit_before>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function($) {

  // Use this variable to set up the common and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function() {
        // JavaScript to be fired on all pages

        // Header
        var header = $('.header');
        $(window).scroll(function() {
          var scroll = $(window).scrollTop();

          if (scroll >= 500) {
            header.addClass('slimmer');
          } else {
            header.removeClass('slimmer');
          }
        });

        // Mobile menu trigger
        var $menuTrigger = $('#main-menu-trigger'),
          $menu = $('.main-navigation'),
          activeClass = 'on-screen';

        $menuTrigger.on('click', function(e) {
          $(this).toggleClass('is-active');
          e.preventDefault();
          $menu.toggleClass(activeClass);
        });

        // Adds class of 'last-word' of main-heading
        $('.page-header.standard .main-heading').each(function(index, element) {
          var heading = $(element);
          var word_array, last_word, first_part;

          word_array = heading.html().split(/\s+/); // split on spaces
          last_word = word_array.pop();             // pop the last word
          first_part = word_array.join(' ');        // rejoin the first words together

          heading.html([first_part, ' ', last_word, ''].join(''));
        });

        // Isotopes
        var $container = $('.isotope').isotope({
          itemSelector: '.isotope-item'
        });

        $('.category-list').on( 'click', 'button', function() {
          var filterValue = $(this).data('filter');
          $('.category-list button').removeClass('is-active');
          if(!$(this).hasClass('is-active')) {
            $(this).addClass('is-active');
          }
          $container.isotope({ filter: filterValue });
        });

        $('.masonry').masonry({
          itemSelector: '.masonry-item',
          isOriginLeft: false
        });

      },
      finalize: function() {
        // JavaScript to be fired on all pages, after page specific JS is fired
      }
    },
    // Home page
    'home': {
      init: function() {
        // JavaScript to be fired on the home page
      },
      finalize: function() {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function() {
        // JavaScript to be fired on the about us page
      }
    },
    'page_template_project_detail': {
      init: function() {
        // JavaScript to be fired on the about us page
      },
      finalize: function() {
        // Gallery
        $('.cycle-slideshow-gallery').cycle({
          slides: 'li',
          next: '.next',
          prev: '.prev',
          fx: 'scrollHorz',
          paused: true
        });

      }
    },
    'contact': {
      init: function() {
        // JavaScript to be fired on the about us page
        google.maps.event.addDomListener(window, 'load', init);
      }
    }
  };

  // Start cycle on home page
  if ($("body").hasClass("home")) {
    // Home page slideshow
    $('.cycle-slideshow').cycle({
      slides: 'li',
      next: '.next',
      prev: '.prev',
      fx: 'scrollHorz',
      pager: '> .pager-container',
      pagerTemplate: ''
    });
  }

  /**
   * Google Map
   */
  var map;
  function init() {
    var mapOptions = {
      center: new google.maps.LatLng(51.881154, 0.025315),
      zoom: 15,
      zoomControl: false,
      disableDoubleClickZoom: true,
      mapTypeControl: false,
      scaleControl: false,
      scrollwheel: false,
      panControl: false,
      streetViewControl: false,
      draggable: true,
      overviewMapControl: false,
      overviewMapControlOptions: {
        opened: false,
      },
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      styles: [{
        "featureType": "water",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#d3d3d3"
        }]
      }, {
        "featureType": "transit",
        "stylers": [{
          "color": "#808080"
        }, {
          "visibility": "off"
        }]
      }, {
        "featureType": "road.highway",
        "elementType": "geometry.stroke",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#b3b3b3"
        }]
      }, {
        "featureType": "road.highway",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "road.local",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#ffffff"
        }, {
          "weight": 1.8
        }]
      }, {
        "featureType": "road.local",
        "elementType": "geometry.stroke",
        "stylers": [{
          "color": "#d7d7d7"
        }]
      }, {
        "featureType": "poi",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#ebebeb"
        }]
      }, {
        "featureType": "administrative",
        "elementType": "geometry",
        "stylers": [{
          "color": "#a7a7a7"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "landscape",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#efefef"
        }]
      }, {
        "featureType": "road",
        "elementType": "labels.text.fill",
        "stylers": [{
          "color": "#696969"
        }]
      }, {
        "featureType": "administrative",
        "elementType": "labels.text.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#737373"
        }]
      }, {
        "featureType": "poi",
        "elementType": "labels.icon",
        "stylers": [{
          "visibility": "off"
        }]
      }, {
        "featureType": "poi",
        "elementType": "labels",
        "stylers": [{
          "visibility": "off"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.stroke",
        "stylers": [{
          "color": "#d6d6d6"
        }]
      }, {
        "featureType": "road",
        "elementType": "labels.icon",
        "stylers": [{
          "visibility": "off"
        }]
      }, {}, {
        "featureType": "poi",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#dadada"
        }]
      }],
    };
    var mapElement = document.getElementById('map');
    var map = new google.maps.Map(mapElement, mapOptions);
    var locations = [
      [
        'undefined',
        'undefined',
        'undefined',
        'undefined',
        'NOVOConstruction',
        51.881154, 0.025315,
        'http://novoconstruction.co.uk/wp-content/themes/novo-construction/dist/images/novo-pin.png'
      ]
    ];
    for (i = 0; i < locations.length; i++) {
      if (locations[i][1] === 'undefined') {
        description = '';
      } else {
        description = locations[i][1];
      }
      if (locations[i][2] === 'undefined') {
        telephone = '';
      } else {
        telephone = locations[i][2];
      }
      if (locations[i][3] === 'undefined') {
        email = '';
      } else {
        email = locations[i][3];
      }
      if (locations[i][4] === 'undefined') {
        web = '';
      } else {
        web = locations[i][4];
      }
      if (locations[i][7] === 'NOVOConstruction') {
        markericon = '';
      } else {
        markericon = locations[i][7];
      }
      marker = new google.maps.Marker({
        icon: markericon,
        position: new google.maps.LatLng(locations[i][5], locations[i][6]),
        map: map,
        title: locations[i][0],
        desc: description,
        tel: telephone,
        email: email,
        web: web
      });
      link = '';
    }

  }

  // The routing fires all common scripts,
  // followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function(func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function() {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function(i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<commit_msg>Removed isOriginLeft from masonry<commit_after>/* ========================================================================
 * DOM-based Routing
 * Based on http://goo.gl/EUTi53 by Paul Irish
 *
 * Only fires on body classes that match. If a body class contains a dash,
 * replace the dash with an underscore when adding it to the object below.
 *
 * .noConflict()
 * The routing is enclosed within an anonymous function so that you can
 * always reference jQuery with $, even when in .noConflict() mode.
 * ======================================================================== */

(function($) {

  // Use this variable to set up the common and page specific functions. If you
  // rename this variable, you will also need to rename the namespace below.
  var Sage = {
    // All pages
    'common': {
      init: function() {
        // JavaScript to be fired on all pages

        // Header
        var header = $('.header');
        $(window).scroll(function() {
          var scroll = $(window).scrollTop();

          if (scroll >= 500) {
            header.addClass('slimmer');
          } else {
            header.removeClass('slimmer');
          }
        });

        // Mobile menu trigger
        var $menuTrigger = $('#main-menu-trigger'),
          $menu = $('.main-navigation'),
          activeClass = 'on-screen';

        $menuTrigger.on('click', function(e) {
          $(this).toggleClass('is-active');
          e.preventDefault();
          $menu.toggleClass(activeClass);
        });

        // Adds class of 'last-word' of main-heading
        $('.page-header.standard .main-heading').each(function(index, element) {
          var heading = $(element);
          var word_array, last_word, first_part;

          word_array = heading.html().split(/\s+/); // split on spaces
          last_word = word_array.pop();             // pop the last word
          first_part = word_array.join(' ');        // rejoin the first words together

          heading.html([first_part, ' ', last_word, ''].join(''));
        });

        // Isotopes
        var $container = $('.isotope').isotope({
          itemSelector: '.isotope-item'
        });

        $('.category-list').on( 'click', 'button', function() {
          var filterValue = $(this).data('filter');
          $('.category-list button').removeClass('is-active');
          if(!$(this).hasClass('is-active')) {
            $(this).addClass('is-active');
          }
          $container.isotope({ filter: filterValue });
        });

        $('.masonry').masonry({
          itemSelector: '.masonry-item'
        });

      },
      finalize: function() {
        // JavaScript to be fired on all pages, after page specific JS is fired
      }
    },
    // Home page
    'home': {
      init: function() {
        // JavaScript to be fired on the home page
      },
      finalize: function() {
        // JavaScript to be fired on the home page, after the init JS
      }
    },
    // About us page, note the change from about-us to about_us.
    'about_us': {
      init: function() {
        // JavaScript to be fired on the about us page
      }
    },
    'page_template_project_detail': {
      init: function() {
        // JavaScript to be fired on the about us page
      },
      finalize: function() {
        // Gallery
        $('.cycle-slideshow-gallery').cycle({
          slides: 'li',
          next: '.next',
          prev: '.prev',
          fx: 'scrollHorz',
          paused: true
        });

      }
    },
    'contact': {
      init: function() {
        // JavaScript to be fired on the about us page
        google.maps.event.addDomListener(window, 'load', init);
      }
    }
  };

  // Start cycle on home page
  if ($("body").hasClass("home")) {
    // Home page slideshow
    $('.cycle-slideshow').cycle({
      slides: 'li',
      next: '.next',
      prev: '.prev',
      fx: 'scrollHorz',
      pager: '> .pager-container',
      pagerTemplate: ''
    });
  }

  /**
   * Google Map
   */
  var map;
  function init() {
    var mapOptions = {
      center: new google.maps.LatLng(51.881154, 0.025315),
      zoom: 15,
      zoomControl: false,
      disableDoubleClickZoom: true,
      mapTypeControl: false,
      scaleControl: false,
      scrollwheel: false,
      panControl: false,
      streetViewControl: false,
      draggable: true,
      overviewMapControl: false,
      overviewMapControlOptions: {
        opened: false,
      },
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      styles: [{
        "featureType": "water",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#d3d3d3"
        }]
      }, {
        "featureType": "transit",
        "stylers": [{
          "color": "#808080"
        }, {
          "visibility": "off"
        }]
      }, {
        "featureType": "road.highway",
        "elementType": "geometry.stroke",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#b3b3b3"
        }]
      }, {
        "featureType": "road.highway",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "road.local",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#ffffff"
        }, {
          "weight": 1.8
        }]
      }, {
        "featureType": "road.local",
        "elementType": "geometry.stroke",
        "stylers": [{
          "color": "#d7d7d7"
        }]
      }, {
        "featureType": "poi",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#ebebeb"
        }]
      }, {
        "featureType": "administrative",
        "elementType": "geometry",
        "stylers": [{
          "color": "#a7a7a7"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#ffffff"
        }]
      }, {
        "featureType": "landscape",
        "elementType": "geometry.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#efefef"
        }]
      }, {
        "featureType": "road",
        "elementType": "labels.text.fill",
        "stylers": [{
          "color": "#696969"
        }]
      }, {
        "featureType": "administrative",
        "elementType": "labels.text.fill",
        "stylers": [{
          "visibility": "on"
        }, {
          "color": "#737373"
        }]
      }, {
        "featureType": "poi",
        "elementType": "labels.icon",
        "stylers": [{
          "visibility": "off"
        }]
      }, {
        "featureType": "poi",
        "elementType": "labels",
        "stylers": [{
          "visibility": "off"
        }]
      }, {
        "featureType": "road.arterial",
        "elementType": "geometry.stroke",
        "stylers": [{
          "color": "#d6d6d6"
        }]
      }, {
        "featureType": "road",
        "elementType": "labels.icon",
        "stylers": [{
          "visibility": "off"
        }]
      }, {}, {
        "featureType": "poi",
        "elementType": "geometry.fill",
        "stylers": [{
          "color": "#dadada"
        }]
      }],
    };
    var mapElement = document.getElementById('map');
    var map = new google.maps.Map(mapElement, mapOptions);
    var locations = [
      [
        'undefined',
        'undefined',
        'undefined',
        'undefined',
        'NOVOConstruction',
        51.881154, 0.025315,
        'http://novoconstruction.co.uk/wp-content/themes/novo-construction/dist/images/novo-pin.png'
      ]
    ];
    for (i = 0; i < locations.length; i++) {
      if (locations[i][1] === 'undefined') {
        description = '';
      } else {
        description = locations[i][1];
      }
      if (locations[i][2] === 'undefined') {
        telephone = '';
      } else {
        telephone = locations[i][2];
      }
      if (locations[i][3] === 'undefined') {
        email = '';
      } else {
        email = locations[i][3];
      }
      if (locations[i][4] === 'undefined') {
        web = '';
      } else {
        web = locations[i][4];
      }
      if (locations[i][7] === 'NOVOConstruction') {
        markericon = '';
      } else {
        markericon = locations[i][7];
      }
      marker = new google.maps.Marker({
        icon: markericon,
        position: new google.maps.LatLng(locations[i][5], locations[i][6]),
        map: map,
        title: locations[i][0],
        desc: description,
        tel: telephone,
        email: email,
        web: web
      });
      link = '';
    }

  }

  // The routing fires all common scripts,
  // followed by the page specific scripts.
  // Add additional events for more control over timing e.g. a finalize event
  var UTIL = {
    fire: function(func, funcname, args) {
      var fire;
      var namespace = Sage;
      funcname = (funcname === undefined) ? 'init' : funcname;
      fire = func !== '';
      fire = fire && namespace[func];
      fire = fire && typeof namespace[func][funcname] === 'function';

      if (fire) {
        namespace[func][funcname](args);
      }
    },
    loadEvents: function() {
      // Fire common init JS
      UTIL.fire('common');

      // Fire page-specific init JS, and then finalize JS
      $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function(i, classnm) {
        UTIL.fire(classnm);
        UTIL.fire(classnm, 'finalize');
      });

      // Fire common finalize JS
      UTIL.fire('common', 'finalize');
    }
  };

  // Load Events
  $(document).ready(UTIL.loadEvents);

})(jQuery); // Fully reference jQuery after this point.
<|endoftext|>


<commit_before>L.Polygon.polygonEditor = L.Polygon.extend({
    _prepareMapIfNeeded: function() {
        var that = this;

        if(this._map._editablePolygons != null) {
            return;
        }

        // Container for all editable polylines on this map:
        this._map._editablePolygons = [];

        // Click anywhere on map to add a new point-polyline:
        if(this._options.newPolylines) {
            console.log('click na map');
            that._map.on('click', function(event) {
                console.log('click, target=' + (event.target == that._map) + ' type=' + event.type);
                if(that.isBusy())
                    return;

                that._setBusy(true);

                var latLng = event.latlng;
                if(that._options.newPolylineConfirmMessage)
                    if(!confirm(that._options.newPolylineConfirmMessage))
                        return

                var contexts = [{'originalPolylineNo': null, 'originalPointNo': null}];
                L.Polygon.PolygonEditor([latLng], that._options, contexts).addTo(that._map);

                that._setBusy(false);

                that._showBoundMarkers();
            });
        }
    },
    /**
     * Will add all needed methods to this polyline.
     */
    _addMethods: function() {
        var that = this;

        this._init = function(options, contexts) {
            this._prepareMapIfNeeded();

            /*
             * Utility method added to this map to retreive editable
             * polylines.
             */
            if(!this._map.getEditablePolylines) {
                this._map.getEditablePolylines = function() {
                    return that._map._editablePolygons;
                }
            }

            /**
             * Since all point editing is done by marker events, markers
             * will be the main holder of the polyline points locations.
             * Every marker contains a reference to the newPointMarker
             * *before* him (=> the first marker has newPointMarker=null).
             */
            this._parseOptions(options);

            this._markers = [];
            var that = this;
            var points = this.getLatLngs();
            var length = points.length;
            for(var i = 0; i < length; i++) {
                var marker = this._addMarkers(i, points[i]);
                if(! ('context' in marker)) {
                    marker.context = {}
                    if(that._contexts != null) {
                        marker.context = contexts[i];
                    }
                }

                if(marker.context && ! ('originalPointNo' in marker.context))
                    marker.context.originalPointNo = i;
                if(marker.context && ! ('originalPolylineNo' in marker.context))
                    marker.context.originalPolylineNo = that._map._editablePolygons.length;
            }

            var map = this._map;
            this._map.on("zoomend", function(e) {
                that._showBoundMarkers();
            });
            this._map.on("moveend", function(e) {
                that._showBoundMarkers();
            });

            if('_desiredPolylineNo' in this) {
                this._map._editablePolygons.splice(this._desiredPolylineNo, 0, this);
            } else {
                this._map._editablePolygons.push(this);
            }
        };

        /**
         * Check if there is *any* busy editable polyline on this map.
         */
        this.isBusy = function() {
            for(var i = 0; i < that._map._editablePolygons.length; i++)
                if(that._map._editablePolygons[i]._isBusy())
                    return true;

            return false;
        };

        /**
         * Check if is busy adding/moving new nodes. Note, there may be
         * *other* editable polylines on the same map which *are* busy.
         */
        this._isBusy = function() {
            return that._busy;
        };

        this._setBusy = function(busy) {
            that._busy = busy;
        };

        /**
         * Get markers for this polyline.
         */
        this.getPoints = function() {
            return this._markers;
        };

        this._parseOptions = function(options) {
            if(!options)
                options = {};

            // Do not show edit markers if more than maxMarkers would be shown:
            if(!('maxMarkers' in options)) {
                options.maxMarkers = 100;
            }
            this.maxMarkers = options.maxMarkers;

            // Do not allow edges to be destroyed (split polygon in two)
            if(!('deletableEdges' in options)) {
                options.deletableEdges = false;
            }
            this.deletableEdges = options.deletableEdges;

            // Icons:
            if(options.pointIcon) {
                this.pointIcon = options.pointIcon;
            } else {
                this.pointIcon = L.icon({ iconUrl: 'editmarker.png', iconSize: [11, 11], iconAnchor: [6, 6] });
            }
            if(options.newPointIcon) {
                this.newPointIcon = options.newPointIcon;
            } else {
                this.newPointIcon = L.icon({ iconUrl: 'editmarker2.png', iconSize: [11, 11], iconAnchor: [6, 6] });
            }
        };

        /**
         * Show only markers in current map bounds *is* there are only a certain
         * number of markers. This method is called on eventy that change map
         * bounds.
         */
        this._showBoundMarkers = function() {
            if(that.isBusy()) {
                //console.log('Do not show because busy!');
                return;
            }

            var bounds = that._map.getBounds();
            var found = 0;
            for(var polylineNo in that._map._editablePolygons) {
                var polyline = that._map._editablePolygons[polylineNo];
                for(var markerNo in polyline._markers) {
                    var marker = polyline._markers[markerNo];
                    if(bounds.contains(marker.getLatLng()))
                        found += 1;
                }
            }

            //console.log('found=' + found);

            for(var polylineNo in that._map._editablePolygons) {
                var polyline = that._map._editablePolygons[polylineNo];
                for(var markerNo in polyline._markers) {
                    var marker = polyline._markers[markerNo];
                    if(found < that.maxMarkers) {
                        that._setMarkerVisible(marker, bounds.contains(marker.getLatLng()));
                        that._setMarkerVisible(marker.newPointMarker, bounds.contains(marker.getLatLng()));
                    } else {
                        that._setMarkerVisible(marker, false);
                        that._setMarkerVisible(marker.newPointMarker, false);
                    }
                }
            }
        };

        /**
         * Used when adding/moving points in order to disable the user to mess
         * with other markers (+ easier to decide where to put the point
         * without too many markers).
         */
        this._hideAll = function(except) {
            for(var polylineNo in that._map._editablePolygons) {
                //console.log("hide " + polylineNo + " markers");
                var polyline = that._map._editablePolygons[polylineNo];
                for(var markerNo in polyline._markers) {
                    var marker = polyline._markers[markerNo];
                    if(except == null || except != marker)
                        polyline._setMarkerVisible(marker, false);
                    if(except == null || except != marker.newPointMarker)
                        polyline._setMarkerVisible(marker.newPointMarker, false);
                }
            }
        }

        /**
         * Show/hide marker.
         */
        this._setMarkerVisible = function(marker, show) {
            if(!marker)
                return;

            var map = this._map;
            if(show) {
                if(!marker._visible) {
                    if(!marker._map) { // First show fo this marker:
                        marker.addTo(map);
                    } else { // Marker was already shown and hidden:
                        map.addLayer(marker);
                    }
                    marker._map = map;
                }
                marker._visible = true;
            } else {
                if(marker._visible) {
                    map.removeLayer(marker);
                }
                marker._visible = false;
            }
        };

        /**
         * Reload polyline. If it is busy, then the bound markers will not be
         * shown. Call _setBusy(false) before this method!
         */
        this._reloadPolyline = function(fixAroundPointNo) {
            that.setLatLngs(that._getMarkerLatLngs());
            if(fixAroundPointNo != null)
                that._fixNeighbourPositions(fixAroundPointNo);
            that._showBoundMarkers();
        }

        /**
         * Add two markers (a point marker and his newPointMarker) for a
         * single point.
         *
         * Markers are not added on the map here, the marker.addTo(map) is called
         * only later when needed first time because of performance issues.
         */
        this._addMarkers = function(pointNo, latLng, fixNeighbourPositions) {
            var that = this;
            var points = this.getLatLngs();
            var marker = L.marker(latLng, {draggable: true, icon: this.pointIcon});

            marker.newPointMarker = null;
            marker.on('dragstart', function(event) {
                var pointNo = that._getPointNo(event.target);
                //console.log("pointNo", pointNo);
                var previousPoint = pointNo == null ? null : (pointNo - 1 >= 0 ? that._markers[pointNo - 1].getLatLng() : that._markers[that._markers.length - 1].getLatLng());
                var nextPoint = pointNo < that._markers.length - 1 ? that._markers[pointNo + 1].getLatLng() : that._markers[0].getLatLng();
                that._setupDragLines(marker, previousPoint, nextPoint);
                that._setBusy(true);
                that._hideAll(marker);
            });
            marker.on('dragend', function(event) {
                var marker = event.target;
                var pointNo = that._getPointNo(event.target);
                that._setBusy(false);
                that._reloadPolyline(pointNo);
            });
            // deleting in click and context menu to allow for touch device tap-to-remove
            marker.on('contextmenu dblclick', function(event) {
                var corners = that._markers.length;
                if (corners <= 3)
                    return;
                var marker = event.target;
                var pointNo = that._getPointNo(event.target);
                //console.log("corners:", corners, "pointNo:", pointNo);
                that._map.removeLayer(marker);
                that._map.removeLayer(newPointMarker);
                that._markers.splice(pointNo, 1);
                that._reloadPolyline(pointNo);
            });
            // marker.on('click', function(event) {
            //     //console.log("click");
            //     var marker = event.target;
            //     var pointNo = that._getPointNo(event.target);
            //     if(pointNo == 0 || pointNo == that._markers.length - 1) {
            //         that._prepareForNewPoint(marker, pointNo == 0 ? 0 : pointNo + 1);
            //     }
            // });

            var previousPoint = points[pointNo == 0 ? points.length - 1 : pointNo - 1];
            var newPointMarker = L.marker([(latLng.lat + previousPoint.lat) / 2.,
                                           (latLng.lng + previousPoint.lng) / 2.],
                                          {draggable: true, icon: this.newPointIcon});
            marker.newPointMarker = newPointMarker;
            newPointMarker.on('dragstart', function(event) {
                var pointNo = that._getPointNo(event.target);
                //console.log("pointNo", pointNo);
                var previousPoint = pointNo - 1 >= 0 ? that._markers[pointNo - 1].getLatLng() : that._markers[that._markers.length - 1].getLatLng();
                var nextPoint = that._markers[pointNo].getLatLng();
                that._setupDragLines(marker.newPointMarker, previousPoint, nextPoint);

                that._setBusy(true);
                that._hideAll(marker.newPointMarker);
            });
            newPointMarker.on('dragend', function(event) {
                var marker = event.target;
                var pointNo = that._getPointNo(event.target);
                that._addMarkers(pointNo, marker.getLatLng(), true);
                that._setBusy(false);
                that._reloadPolyline();
            });

            if (this._options.deletableEdges) {
                newPointMarker.on('contextmenu', function(event) {
                    // 1. Remove this polyline from map
                    var marker = event.target;
                    var pointNo = that._getPointNo(marker);
                    var markers = that.getPoints();
                    that._hideAll();

                    var secondPartMarkers = that._markers.slice(pointNo, pointNo.length);
                    that._markers.splice(pointNo, that._markers.length - pointNo);

                    that._reloadPolyline();

                    var points = [];
                    var contexts = [];
                    for(var i = 0; i < secondPartMarkers.length; i++) {
                        var marker = secondPartMarkers[i];
                        points.push(marker.getLatLng());
                        contexts.push(marker.context);
                    }

                    //console.log('points:' + points);
                    //console.log('contexts:' + contexts);

                    // Need to know the current polyline order numbers, because
                    // the splitted one need to be inserted immediately after:
                    var originalPolylineNo = that._map._editablePolygons.indexOf(that);

                    var newPolyline = L.Polygon.PolygonEditor(points, that._options, contexts, originalPolylineNo + 1)
                                                .addTo(that._map);

                    that._showBoundMarkers();

                    //console.log('Done split, _editablePolygons now:' + that._map._editablePolygons.length);
                });
            }

            this._markers.splice(pointNo, 0, marker);

            if(fixNeighbourPositions) {
                this._fixNeighbourPositions(pointNo);
            }

            return marker;
        };

        /**
         * Event handlers for first and last point.
         */
        this._prepareForNewPoint = function(marker, pointNo) {
            that._hideAll();
            that._setupDragLines(marker, marker.getLatLng());
            var mouseMoveHandler = function(event) {
                that._setBusy(true);
            };
            that._map.on('mousemove', mouseMoveHandler);
            that._map.once('click', function(event) {
                //console.log('dodajemo na ' + pointNo + ' - ' + event.latlng);
                that._map.off('mousemove', mouseMoveHandler);
                that._addMarkers(pointNo, event.latlng, true);
                that._setBusy(false);
                that._reloadPolyline();
            });
        };

        /**
         * Fix nearby new point markers when the new point is created.
         */
        this._fixNeighbourPositions = function(pointNo) {
            var previousMarker = pointNo == 0 ? this._markers[this._markers.length - 1] : this._markers[pointNo - 1];
            var marker = this._markers[pointNo];
            var nextMarker = pointNo < this._markers.length - 1 ? this._markers[pointNo + 1] : this._markers[0];
            //console.log("_fixNeighbourPositions:", pointNo, this._markers.length);
            //console.log("markers:", marker, previousMarker, nextMarker);
            if(!marker && previousMarker && nextMarker) {
                // //console.log("last point deleted!");
                nextMarker.newPointMarker.setLatLng([(previousMarker.getLatLng().lat + nextMarker.getLatLng().lat) / 2.,
                                                     (previousMarker.getLatLng().lng + nextMarker.getLatLng().lng) / 2.]);
            }
            if(marker && previousMarker) {
                // //console.log("marker && previousMarker");
                marker.newPointMarker.setLatLng([(previousMarker.getLatLng().lat + marker.getLatLng().lat) / 2.,
                                                 (previousMarker.getLatLng().lng + marker.getLatLng().lng) / 2.]);
            }
            if(marker && nextMarker) {
                // //console.log("marker && nextMarker");
                nextMarker.newPointMarker.setLatLng([(marker.getLatLng().lat + nextMarker.getLatLng().lat) / 2.,
                                                     (marker.getLatLng().lng + nextMarker.getLatLng().lng) / 2.]);
            }
        };

        /**
         * Find the order number of the marker.
         */
        this._getPointNo = function(marker) {
            for(var i = 0; i < this._markers.length; i++) {
                if(marker == this._markers[i] || marker == this._markers[i].newPointMarker) {
                    return i;
                }
            }
            return -1;
        };

        /**
         * Get polyline latLngs based on marker positions.
         */
        this._getMarkerLatLngs = function() {
            var result = [];
            for(var i = 0; i < this._markers.length; i++)
                result.push(this._markers[i].getLatLng());
            return result;
        };

        this._setupDragLines = function(marker, point1, point2) {
            // //console.log("_setupDragLines", marker, point1, point2);
            var line1 = null;
            var line2 = null;
            if(point1) line1 = L.polygon([marker.getLatLng(), point1], {dasharray: "5,1", weight: 1})
                                .addTo(that._map);
            if(point2) line2 = L.polygon([marker.getLatLng(), point1], {dasharray: "5,1", weight: 1})
                                .addTo(that._map);

            var moveHandler = function(event) {
                if(line1)
                    line1.setLatLngs([event.latlng, point1]);
                if(line2)
                    line2.setLatLngs([event.latlng, point2]);
            };

            var stopHandler = function(event) {
                that._map.off('mousemove', moveHandler);
                marker.off('dragend', stopHandler);
                if(line1) that._map.removeLayer(line1);
                if(line2) that._map.removeLayer(line2);
                //console.log('STOPPED');
                if(event.target != that._map) {
                    that._map.fire('click', event);
                }
            };

            that._map.on('mousemove', moveHandler);
            marker.on('dragend', stopHandler);

            that._map.once('click', stopHandler);
            marker.once('click', stopHandler);
            if(line1) line1.once('click', stopHandler);
            if(line2) line2.once('click', stopHandler);
        }
    }
});

L.Polygon.polygonEditor.addInitHook(function () {
    // Hack to keep reference to map:
    this.originalAddTo = this.addTo;
    this.addTo = function(map) {
        this.originalAddTo(map);
        this._map = map;

        this._addMethods();

        /**
         * When addint a new point we must disable the user to mess with other
         * markers. One way is to check everywhere if the user is busy. The
         * other is to just remove other markers when the user is doing
         * somethinng.
         *
         * TODO: Decide the right way to do this and then leave only _busy or
         * _hideAll().
         */
        this._busy = false;
        this._initialized = false;

        this._init(this._options, this._contexts);

        this._initialized = true;

        return this;
    };
});

/**
 * Construct a new editable polyline.
 *
 * latlngs    ... a list of points (or two-element tuples with coordinates)
 * options    ... polyline options
 * contexts   ... custom contexts for every point in the polyline. Must have the
 *                same number of elements as latlngs and this data will be
 *                preserved when new points are added or polylines splitted.
 * polylineNo ... insert this polyline in a specific order (used when splitting).
 *
 * More about contexts:
 * This is an array of objects that will be kept as "context" for every
 * point. Marker will keep this value as marker.context. New markers will
 * have context set to null.
 *
 * Contexts must be the same size as the polyline size!
 *
 * By default, even without calling this method -- every marker will have
 * context with one value: marker.context.originalPointNo with the
 * original order number of this point. The order may change if some
 * markers before this one are delted or new added.
 */
L.Polygon.PolygonEditor = function(latlngs, options, contexts, polylineNo) {
    var result = new L.Polygon.polygonEditor(latlngs, options);
    result._options = options;
    result._contexts = contexts;
    result._desiredPolylineNo = polylineNo
    return result;
};
<commit_msg>Removed polygon for now<commit_after><|endoftext|>


<commit_before>'use strict';

module.exports = Subscribers;

/**
 * Subscribers.
 * @constructor
 * @param {Client} client - Instance of an API client.
 */
function Subscribers (client) {
  /**
   * Adds a subscriber to an existing list, including custom field data if supplied.
   * If the email address is already subscribed, their name and any custom field values are updated with whatever is passed in.
   * @param {number} list_id - The ID of the list to which the subscriber should be added.
   * @param {string} email - The email of the subscriber.
   * @param {string} name - Name of the subscriber.
   * @param {object[]} fields - Array of custom fields of the subscriber.
   * @param {boolean} resubscribe - Sets to true if you want to reactive subscriber.
   */
  this.addSubscriber = (list_id, email, name, fields, resubscribe) => {
    return client.Post(`/subscribers/${list_id}/`, {
      email: email,
      name: name,
      fields: fields,
      resubscribe: resubscribe
    });
  };

  /**
   * Allows you to add many subscribers to a list in one request, including custom field data if supplied.
   * If an email addresses are already subscribed, their name and any custom field values are updated with whatever is passed in.
   * @param {number} list_id - The ID of the list to which the subscriber should be added.
   * @param {object[]} subscribers - Array of subscribers.
   * @param {boolean} resubscribe - Sets to true if you want to reactive subscribers.
   */
  this.addManySubscribers = (list_id, subscribers, resubscribe) => {
    return client.Post(`/subscribers/${list_id}/import`, {
      id: list_id,
      subscribers: subscribers,
      resubscribe: resubscribe
    });
  };

  /**
   * Retrieves a subscriber's details including their email address, name, active/inactive state and any custom field data.
   * @param {string} email - The email address of the subscriber whose details should be retrieved.
   * @param {boolean} history - Sets to true if you want to get historical records of campaigns and autoresponder emails received by a subscriber (default: false).
   */
  this.getDetails = (email, history) => {
    return client.Get('/subscribers/', {
      email: email,
      history: history
    });
  };

  /**
   * Removes subscriber from a list. He will no longer receive campaigns sent to this list.
   * @param {number} id - The ID of the list to which the subscribed should be removed.
   * @param {string} email - The email of the subscriber.
   */
  this.deleteSubscriber = (id, email) => {
    //
  };

  /**
   * Marks subscriber as unsubscribed. He will no longer receive any campaigns.
   * @param {string} email - The email of the subscriber.
   */
  this.unsubscribeSubscriber = (email) => {
    //
  };
}
<commit_msg>Fixed resubscribed field to match API docs.<commit_after>'use strict';

module.exports = Subscribers;

/**
 * Subscribers.
 * @constructor
 * @param {Client} client - Instance of an API client.
 */
function Subscribers (client) {
  /**
   * Adds a subscriber to an existing list, including custom field data if supplied.
   * If the email address is already subscribed, their name and any custom field values are updated with whatever is passed in.
   * @param {number} list_id - The ID of the list to which the subscriber should be added.
   * @param {string} email - The email of the subscriber.
   * @param {string} name - Name of the subscriber.
   * @param {object[]} fields - Array of custom fields of the subscriber.
   * @param {boolean} resubscribe - Sets to true if you want to reactive subscriber.
   */
  this.addSubscriber = (list_id, email, name, fields, resubscribe) => {
    return client.Post(`/subscribers/${list_id}/`, {
      email: email,
      name: name,
      fields: fields,
      resubscribe: resubscribe ? 1 : 0
    });
  };

  /**
   * Allows you to add many subscribers to a list in one request, including custom field data if supplied.
   * If an email addresses are already subscribed, their name and any custom field values are updated with whatever is passed in.
   * @param {number} list_id - The ID of the list to which the subscriber should be added.
   * @param {object[]} subscribers - Array of subscribers.
   * @param {boolean} resubscribe - Sets to true if you want to reactive subscribers.
   */
  this.addManySubscribers = (list_id, subscribers, resubscribe) => {
    return client.Post(`/subscribers/${list_id}/import`, {
      id: list_id,
      subscribers: subscribers,
      resubscribe: resubscribe ? 1 : 0
    });
  };

  /**
   * Retrieves a subscriber's details including their email address, name, active/inactive state and any custom field data.
   * @param {string} email - The email address of the subscriber whose details should be retrieved.
   * @param {boolean} history - Sets to true if you want to get historical records of campaigns and autoresponder emails received by a subscriber (default: false).
   */
  this.getDetails = (email, history) => {
    return client.Get('/subscribers/', {
      email: email,
      history: history
    });
  };

  /**
   * Removes subscriber from a list. He will no longer receive campaigns sent to this list.
   * @param {number} id - The ID of the list to which the subscribed should be removed.
   * @param {string} email - The email of the subscriber.
   */
  this.deleteSubscriber = (id, email) => {
    //
  };

  /**
   * Marks subscriber as unsubscribed. He will no longer receive any campaigns.
   * @param {string} email - The email of the subscriber.
   */
  this.unsubscribeSubscriber = (email) => {
    //
  };
}
<|endoftext|>