<commit_before>var Sudoku = (function () {
    'use strict';

    var
        defaults = {
            css: {
                target: 'sudoku',
                block: 'sudoku_block',
                cell: 'sudoku_cell'
            },
            size: 3
        },

        checkSetting = function (settings) {
            if (!settings.method) {
                settings.method = settings.size > 3 ? 'lite' : 'hard';
            }

            return settings;
        },

        arrayUtils = {
            shuffle: function (array) {
                return array.sort(function () {
                    return .5 - Math.random();
                });
            },

            swapRows: function (array, i, j) {
                var buffer,
                    k;

                if (i !== j) {
                    console.log('Swap rows: ' + i + ' - ' + j);
                    for (k = 0; k < array[i].length; k++) {
                        buffer = array[i][k];
                        array[i][k] = array[j][k];
                        array[j][k] = buffer;
                    }
                }

                return array;
            },

            swapCols: function (array, i, j) {
                var buffer,
                    k;

                if (i !== j) {
                    console.log('Swap cols: ' + i + ' - ' + j);
                    for (k = 0; k < array.length; k++) {
                        buffer = array[k][i];
                        array[k][i] = array[k][j];
                        array[k][j] = buffer;
                    }
                }

                return array;
            },

            swapSegmentRows: function (array, i, j, size) {
                var k;

                if (i !== j) {
                    for (k = 0; k < size; k++) {
                        arrayUtils.swapRows(array, i * size + k, j * size + k);
                    }
                }

                return array;
            },

            swapSegmentCols: function (array, i, j, size) {
                var k;

                if (i !== j) {
                    for (k = 0; k < size; k++) {
                        arrayUtils.swapCols(array, i * size + k, j * size + k);
                    }
                }

                return array;
            },

            transpose: function (array) {
                var buffer,
                    i, j;

                for (i = 0; i < array.length; i++) {
                    for (j = i + 1; j < array.length; j++) {
                        buffer = array[i][j];
                        array[i][j] = array[j][i];
                        array[j][i] = buffer;
                    }
                }

                return array;
            }
        },

        generateMap = {
            lite: function ($target, settings) {
                var gameMap = [[]],
                    candidates,
                    halfSize = Math.floor(settings.size / 2),
                    i, j, k,
                    iRand, jRand,

                    generateRow = function (settings) {
                        var row = [],
                            segmentLength = Math.pow(settings.size, 2),
                            i;

                        for (i = 0; i < segmentLength; i++) {
                            row[i] = i + 1;
                        }

                        return arrayUtils.shuffle(row);
                    },

                    checkCol = function (gameMap, col, value) {
                        var valid = true,
                            i;

                        for (i = 0; i < gameMap.length && valid; i++) {
                            if (gameMap[i][col] === value) {
                                valid = false;
                            }
                        }

                        return valid;
                    },

                    fillMap = function ($target, settings, gameMap) {
                        var $blockSet = $('.' + settings.css.block, $target),
                            $cellSet,
                            i, j, iMap, jMap;

                        for (i = 0; i < settings.size * settings.size; i++) {
                            $cellSet = $('.' + settings.css.cell, $blockSet.eq(i));
                            for (j = 0; j < settings.size * settings.size; j++) {
                                iMap = Math.floor(i / settings.size) * settings.size + Math.floor(j / settings.size);
                                jMap = (i % settings.size) * settings.size + j % settings.size;
                                if (gameMap[iMap][jMap]) {
                                    $cellSet.eq(j)
                                        .text(gameMap[iMap][jMap])
                                        .addClass('__disabled');
                                }
                            }
                        }
                    },

                    generatePair = function (settings, value, mode) {
                        var pair = NaN,

                            methods = {
                                segment: function (settings, value) {
                                    var segment = Math.floor(value / settings.size);
                                    return segment * settings.size + Math.floor(Math.random() * settings.size);
                                },

                                map: function (settings, value) {
                                    return Math.floor(Math.random() * settings.size) * settings.size + value % settings.size;
                                }
                            };

                        if (methods[mode]) {
                            pair = methods[mode](settings, value);
                        }
                        if (pair === value) {
                            console.log('Regenerate pair for ' + value);
                            pair = generatePair(settings, value, mode);
                        }

                        return pair;
                    };

                /* Заполнение первой строки массива */
                gameMap[0] = generateRow(settings);

                /* Заполнение оставшихся строк массива */
                for (i = 0; i < Math.pow(settings.size, 2); i += settings.size) {
                    if (i > 0) {
                        gameMap[i] = [];
                        candidates = generateRow(settings);
                        for (j = 0; j < Math.pow(settings.size, 2); j++) {
                            for (k = 0; k < candidates.length && !gameMap[i][j]; k++) {
                                if (checkCol(gameMap, j, candidates[k])) {
                                    gameMap[i][j] = candidates[k];
                                    candidates.splice(k, 1);
                                }
                            }
                            /* Перезапуск генерации строки */
                            if (!gameMap[i][j]) {
                                gameMap[i] = [];
                                candidates = generateRow(settings);
                                j = -1;
                            }
                        }
                    }

                    for (j = 1; j < settings.size; j++) {
                        gameMap[i + j] = gameMap[i].slice(j * settings.size).concat(gameMap[i].slice(0, j * settings.size));
                    }
                }

                /* Перемешивание матрицы */
                for (i = 0; i < settings.size; i++) {
                    /* Мы можем глобально менять столбцы, находящиеся на одинаковой
                       позиции в сегментах, так как при нашей генерации они содержат
                       одинаковый набор значений */
                    iRand = Math.floor(Math.random() * i * settings.size);
                    jRand = generatePair(settings, iRand, 'map');
                    console.log('Try to swap cols: ' + iRand + ' - ' + jRand);
                    arrayUtils.swapCols(gameMap, iRand, jRand);
                }

                console.log('/* --- End of statement --- */');

                for (i = 0; i < settings.size; i++) {
                    /* Для каждого сегмента выполним несколько манипуляций
                       со строками и стобцами в кол-ве равном половине стороны сегмента */
                    for (j = 0; j < halfSize; j++) {
                        /* В пределах каждого сегмента мы можем менять между собой любые
                           строки и столбцы */
                        iRand = i * settings.size + Math.floor(Math.random() * settings.size);
                        jRand = generatePair(settings, iRand, 'segment');
                        console.log('Try to swap cols: ' + iRand + ' - ' + jRand);
                        arrayUtils.swapCols(gameMap, iRand, jRand);
                        console.log('Try to swap rows: ' + iRand + ' - ' + jRand);
                        arrayUtils.swapRows(gameMap, iRand, jRand);
                    }
                }

                fillMap($target, settings, gameMap);
            },

            hard: function ($target, settings) {
                var gameMap = [],

                    generateCandidates = function (settings, gameMap, cell) {
                        var segmentLength = Math.pow(settings.size, 2),
                            candidates = [],
                            i, j;

                        for (i = 0; i < segmentLength; i++) {
                            candidates.push(i + 1);
                        }

                        for (i = cell - cell % segmentLength; i < cell; i++) {
                            for (j = 0; j < candidates.length; j++) {
                                if (gameMap[i].value === candidates[j]) {
                                    candidates.splice(j, 1);
                                    j = candidates.length;
                                }
                            }
                        }

                        return arrayUtils.shuffle(candidates);
                    },

                    checkSell = function (settings, gameMap, cell) {
                        var segmentLength = Math.pow(settings.size, 2),
                            startSegment,
                            startSegmentCell,
                            valid = true,
                            i, j, k;

                        /* Обход строк */
                        startSegment = Math.floor(Math.floor(cell / segmentLength) / settings.size) * settings.size;
                        startSegmentCell = Math.floor(cell % segmentLength / settings.size) * settings.size;
                        k = 0;

                        for (i = 0; i < settings.size && k < cell && valid; i++) {
                            for (j = 0; j < settings.size && k < cell && valid; j++) {
                                k = (startSegment + i) * segmentLength + startSegmentCell + j;

                                if (k < cell && gameMap[k].value === gameMap[cell].value) {
                                    valid = false;
                                }
                            }
                        }

                        /* Обход столбцов */
                        startSegment = Math.floor(cell / segmentLength) % settings.size;
                        startSegmentCell = cell % settings.size;
                        k = 0;

                        for (i = 0; i < settings.size && k < cell && valid; i++) {
                            for (j = 0; j < settings.size && k < cell && valid; j++) {
                                k = (startSegment + settings.size * i) * segmentLength + startSegmentCell + settings.size * j;

                                if (k < cell && gameMap[k].value === gameMap[cell].value) {
                                    valid = false;
                                }
                            }
                        }

                        return valid;
                    },

                    setCell = function (settings, gameMap, cell) {
                        var valid = false;

                        gameMap[cell] = gameMap[cell] || {};

                        if (typeof gameMap[cell].candidates === 'undefined' || gameMap[cell].candidates === null) {
                            gameMap[cell].candidates = generateCandidates(settings, gameMap, cell);
                        }

                        while (gameMap[cell].candidates.length && !valid) {
                            gameMap[cell].value = gameMap[cell].candidates.shift();
                            valid = checkSell(settings, gameMap, cell);
                        }

                        if (!valid) {
                            gameMap[cell] = {};
                        }

                        return valid;
                    },

                    generate = function (settings, gameMap, cell) {
                        if (cell < 0) {
                            return false;
                        }

                        if (cell === Math.pow(settings.size, 4)) {
                            return true;
                        }

                        if (setCell(settings, gameMap, cell)) {
                            generate(settings, gameMap, cell + 1);
                        } else {
                            generate(settings, gameMap, cell - 1)
                        }
                    },

                    fillMap = function ($target, settings, gameMap) {
                        var $ = window.jQuery || window.Zepto || window.Dom7,
                            segmentLength = Math.pow(settings.size, 2);

                        $('.' + settings.css.block, $target).each(function (segment) {
                            var $segment = $(this);
                            $('.' + settings.css.cell, $segment).each(function (segmentCell) {
                                var $cell = $(this),
                                    cell = segment * segmentLength + segmentCell;

                                if (gameMap[cell].value) {
                                    $cell
                                        .text(gameMap[cell].value)
                                        .addClass('__disabled');
                                }
                            });
                        });
                    };

                generate(settings, gameMap, 0);

                fillMap($target, settings, gameMap);
            }
        },

        createElements = function ($target, settings) {
            var $ = window.jQuery || window.Zepto || window.Dom7,
                $block,
                $cell,
                percentSize,
                fontSize,
                i, j;

            $target.addClass(settings.css.target);

            percentSize = 100 / settings.size;
            fontSize = .3 + Math.exp(-settings.size) * 50;

            for (i = 0; i < settings.size * settings.size; i++) {
                $block = $('<div/>');

                for (j = 0; j < settings.size * settings.size; j++) {
                    $cell = $('<div/>');
                    $cell
                        .css({
                            width: percentSize + '%',
                            height: percentSize + '%',
                            fontSize: fontSize + 'em'
                        })
                        .addClass(settings.css.cell);
                    $block.append($cell);
                }

                $block
                    .css({
                        width: percentSize + '%',
                        height: percentSize + '%'
                    })
                    .addClass(settings.css.block);
                $target.append($block);
            }
        },

        init = function (options) {
            var $ = window.jQuery || window.Zepto || window.Dom7,
                settings,
                $target;

            if (!$) {
                /* TODO throw */
                console.error('jQuery-compatible library needed');
                return false;
            }

            settings = checkSetting($.extend(true, {}, defaults, options));

            $target = $(settings.target);

            createElements($target, settings);
            generateMap[settings.method]($target, settings);
        };

    return {
        defaults: defaults,
        init: init
    }
})();
<commit_msg>[l:in_progress] Убрал console.log<commit_after>var Sudoku = (function () {
    'use strict';

    var
        defaults = {
            css: {
                target: 'sudoku',
                block: 'sudoku_block',
                cell: 'sudoku_cell'
            },
            size: 3
        },

        checkSetting = function (settings) {
            if (!settings.method) {
                settings.method = settings.size > 3 ? 'lite' : 'hard';
            }

            return settings;
        },

        arrayUtils = {
            shuffle: function (array) {
                return array.sort(function () {
                    return .5 - Math.random();
                });
            },

            swapRows: function (array, i, j) {
                var buffer,
                    k;

                if (i !== j) {
                    for (k = 0; k < array[i].length; k++) {
                        buffer = array[i][k];
                        array[i][k] = array[j][k];
                        array[j][k] = buffer;
                    }
                }

                return array;
            },

            swapCols: function (array, i, j) {
                var buffer,
                    k;

                if (i !== j) {
                    for (k = 0; k < array.length; k++) {
                        buffer = array[k][i];
                        array[k][i] = array[k][j];
                        array[k][j] = buffer;
                    }
                }

                return array;
            },

            swapSegmentRows: function (array, i, j, size) {
                var k;

                if (i !== j) {
                    for (k = 0; k < size; k++) {
                        arrayUtils.swapRows(array, i * size + k, j * size + k);
                    }
                }

                return array;
            },

            swapSegmentCols: function (array, i, j, size) {
                var k;

                if (i !== j) {
                    for (k = 0; k < size; k++) {
                        arrayUtils.swapCols(array, i * size + k, j * size + k);
                    }
                }

                return array;
            },

            transpose: function (array) {
                var buffer,
                    i, j;

                for (i = 0; i < array.length; i++) {
                    for (j = i + 1; j < array.length; j++) {
                        buffer = array[i][j];
                        array[i][j] = array[j][i];
                        array[j][i] = buffer;
                    }
                }

                return array;
            }
        },

        generateMap = {
            lite: function ($target, settings) {
                var gameMap = [[]],
                    candidates,
                    halfSize = Math.floor(settings.size / 2),
                    i, j, k,
                    iRand, jRand,

                    generateRow = function (settings) {
                        var row = [],
                            segmentLength = Math.pow(settings.size, 2),
                            i;

                        for (i = 0; i < segmentLength; i++) {
                            row[i] = i + 1;
                        }

                        return arrayUtils.shuffle(row);
                    },

                    checkCol = function (gameMap, col, value) {
                        var valid = true,
                            i;

                        for (i = 0; i < gameMap.length && valid; i++) {
                            if (gameMap[i][col] === value) {
                                valid = false;
                            }
                        }

                        return valid;
                    },

                    fillMap = function ($target, settings, gameMap) {
                        var $blockSet = $('.' + settings.css.block, $target),
                            $cellSet,
                            i, j, iMap, jMap;

                        for (i = 0; i < settings.size * settings.size; i++) {
                            $cellSet = $('.' + settings.css.cell, $blockSet.eq(i));
                            for (j = 0; j < settings.size * settings.size; j++) {
                                iMap = Math.floor(i / settings.size) * settings.size + Math.floor(j / settings.size);
                                jMap = (i % settings.size) * settings.size + j % settings.size;
                                if (gameMap[iMap][jMap]) {
                                    $cellSet.eq(j)
                                        .text(gameMap[iMap][jMap])
                                        .addClass('__disabled');
                                }
                            }
                        }
                    },

                    generatePair = function (settings, value, mode) {
                        var pair = NaN,

                            methods = {
                                segment: function (settings, value) {
                                    var segment = Math.floor(value / settings.size);
                                    return segment * settings.size + Math.floor(Math.random() * settings.size);
                                },

                                map: function (settings, value) {
                                    return Math.floor(Math.random() * settings.size) * settings.size + value % settings.size;
                                }
                            };

                        if (methods[mode]) {
                            pair = methods[mode](settings, value);
                        }
                        if (pair === value) {
                            pair = generatePair(settings, value, mode);
                        }

                        return pair;
                    };

                /* Заполнение первой строки массива */
                gameMap[0] = generateRow(settings);

                /* Заполнение оставшихся строк массива */
                for (i = 0; i < Math.pow(settings.size, 2); i += settings.size) {
                    if (i > 0) {
                        gameMap[i] = [];
                        candidates = generateRow(settings);
                        for (j = 0; j < Math.pow(settings.size, 2); j++) {
                            for (k = 0; k < candidates.length && !gameMap[i][j]; k++) {
                                if (checkCol(gameMap, j, candidates[k])) {
                                    gameMap[i][j] = candidates[k];
                                    candidates.splice(k, 1);
                                }
                            }
                            /* Перезапуск генерации строки */
                            if (!gameMap[i][j]) {
                                gameMap[i] = [];
                                candidates = generateRow(settings);
                                j = -1;
                            }
                        }
                    }

                    for (j = 1; j < settings.size; j++) {
                        gameMap[i + j] = gameMap[i].slice(j * settings.size).concat(gameMap[i].slice(0, j * settings.size));
                    }
                }

                /* Перемешивание матрицы */
                for (i = 0; i < settings.size; i++) {
                    /* Мы можем глобально менять столбцы, находящиеся на одинаковой
                       позиции в сегментах, так как при нашей генерации они содержат
                       одинаковый набор значений */
                    iRand = Math.floor(Math.random() * i * settings.size);
                    jRand = generatePair(settings, iRand, 'map');
                    arrayUtils.swapCols(gameMap, iRand, jRand);
                }

                for (i = 0; i < settings.size; i++) {
                    /* Для каждого сегмента выполним несколько манипуляций
                       со строками и стобцами в кол-ве равном половине стороны сегмента */
                    for (j = 0; j < halfSize; j++) {
                        /* В пределах каждого сегмента мы можем менять между собой любые
                           строки и столбцы */
                        iRand = i * settings.size + Math.floor(Math.random() * settings.size);
                        jRand = generatePair(settings, iRand, 'segment');
                        arrayUtils.swapCols(gameMap, iRand, jRand);
                        arrayUtils.swapRows(gameMap, iRand, jRand);
                    }
                }

                fillMap($target, settings, gameMap);
            },

            hard: function ($target, settings) {
                var gameMap = [],

                    generateCandidates = function (settings, gameMap, cell) {
                        var segmentLength = Math.pow(settings.size, 2),
                            candidates = [],
                            i, j;

                        for (i = 0; i < segmentLength; i++) {
                            candidates.push(i + 1);
                        }

                        for (i = cell - cell % segmentLength; i < cell; i++) {
                            for (j = 0; j < candidates.length; j++) {
                                if (gameMap[i].value === candidates[j]) {
                                    candidates.splice(j, 1);
                                    j = candidates.length;
                                }
                            }
                        }

                        return arrayUtils.shuffle(candidates);
                    },

                    checkSell = function (settings, gameMap, cell) {
                        var segmentLength = Math.pow(settings.size, 2),
                            startSegment,
                            startSegmentCell,
                            valid = true,
                            i, j, k;

                        /* Обход строк */
                        startSegment = Math.floor(Math.floor(cell / segmentLength) / settings.size) * settings.size;
                        startSegmentCell = Math.floor(cell % segmentLength / settings.size) * settings.size;
                        k = 0;

                        for (i = 0; i < settings.size && k < cell && valid; i++) {
                            for (j = 0; j < settings.size && k < cell && valid; j++) {
                                k = (startSegment + i) * segmentLength + startSegmentCell + j;

                                if (k < cell && gameMap[k].value === gameMap[cell].value) {
                                    valid = false;
                                }
                            }
                        }

                        /* Обход столбцов */
                        startSegment = Math.floor(cell / segmentLength) % settings.size;
                        startSegmentCell = cell % settings.size;
                        k = 0;

                        for (i = 0; i < settings.size && k < cell && valid; i++) {
                            for (j = 0; j < settings.size && k < cell && valid; j++) {
                                k = (startSegment + settings.size * i) * segmentLength + startSegmentCell + settings.size * j;

                                if (k < cell && gameMap[k].value === gameMap[cell].value) {
                                    valid = false;
                                }
                            }
                        }

                        return valid;
                    },

                    setCell = function (settings, gameMap, cell) {
                        var valid = false;

                        gameMap[cell] = gameMap[cell] || {};

                        if (typeof gameMap[cell].candidates === 'undefined' || gameMap[cell].candidates === null) {
                            gameMap[cell].candidates = generateCandidates(settings, gameMap, cell);
                        }

                        while (gameMap[cell].candidates.length && !valid) {
                            gameMap[cell].value = gameMap[cell].candidates.shift();
                            valid = checkSell(settings, gameMap, cell);
                        }

                        if (!valid) {
                            gameMap[cell] = {};
                        }

                        return valid;
                    },

                    generate = function (settings, gameMap, cell) {
                        if (cell < 0) {
                            return false;
                        }

                        if (cell === Math.pow(settings.size, 4)) {
                            return true;
                        }

                        if (setCell(settings, gameMap, cell)) {
                            generate(settings, gameMap, cell + 1);
                        } else {
                            generate(settings, gameMap, cell - 1)
                        }
                    },

                    fillMap = function ($target, settings, gameMap) {
                        var $ = window.jQuery || window.Zepto || window.Dom7,
                            segmentLength = Math.pow(settings.size, 2);

                        $('.' + settings.css.block, $target).each(function (segment) {
                            var $segment = $(this);
                            $('.' + settings.css.cell, $segment).each(function (segmentCell) {
                                var $cell = $(this),
                                    cell = segment * segmentLength + segmentCell;

                                if (gameMap[cell].value) {
                                    $cell
                                        .text(gameMap[cell].value)
                                        .addClass('__disabled');
                                }
                            });
                        });
                    };

                generate(settings, gameMap, 0);

                fillMap($target, settings, gameMap);
            }
        },

        createElements = function ($target, settings) {
            var $ = window.jQuery || window.Zepto || window.Dom7,
                $block,
                $cell,
                percentSize,
                fontSize,
                i, j;

            $target.addClass(settings.css.target);

            percentSize = 100 / settings.size;
            fontSize = .3 + Math.exp(-settings.size) * 50;

            for (i = 0; i < settings.size * settings.size; i++) {
                $block = $('<div/>');

                for (j = 0; j < settings.size * settings.size; j++) {
                    $cell = $('<div/>');
                    $cell
                        .css({
                            width: percentSize + '%',
                            height: percentSize + '%',
                            fontSize: fontSize + 'em'
                        })
                        .addClass(settings.css.cell);
                    $block.append($cell);
                }

                $block
                    .css({
                        width: percentSize + '%',
                        height: percentSize + '%'
                    })
                    .addClass(settings.css.block);
                $target.append($block);
            }
        },

        init = function (options) {
            var $ = window.jQuery || window.Zepto || window.Dom7,
                settings,
                $target;

            if (!$) {
                /* TODO throw */
                console.error('jQuery-compatible library needed');
                return false;
            }

            settings = checkSetting($.extend(true, {}, defaults, options));

            $target = $(settings.target);

            createElements($target, settings);
            generateMap[settings.method]($target, settings);
        };

    return {
        defaults: defaults,
        init: init
    }
})();
<|endoftext|>


<commit_before>/*
* jQuery UI Tag-it!
*
* @version v2.0 (06/2011)
*
* Copyright 2011, Levy Carneiro Jr.
* Released under the MIT license.
* http://aehlke.github.com/tag-it/LICENSE
*
* Homepage:
*   http://aehlke.github.com/tag-it/
*
* Authors:
*   Levy Carneiro Jr.
*   Martin Rehfeld
*   Tobias Schmidt
*   Skylar Challand
*   Alex Ehlke
*
* Maintainer:
*   Alex Ehlke - Twitter: @aehlke
*
* Dependencies:
*   jQuery v1.4+
*   jQuery UI v1.8+
*/
(function($) {

    $.widget('ui.tagit', {
        options: {
            itemName          : 'item',
            fieldName         : 'tags',
            availableTags     : [],
            tagSource         : null,
            removeConfirmation: false,
            caseSensitive     : true,

            // When enabled, quotes are not neccesary
            // for inputting multi-word tags.
            allowSpaces: false,

            // Whether to animate tag removals or not.
            animate: true,

            // The below options are for using a single field instead of several
            // for our form values.
            //
            // When enabled, will use a single hidden field for the form,
            // rather than one per tag. It will delimit tags in the field
            // with singleFieldDelimiter.
            //
            // The easiest way to use singleField is to just instantiate tag-it
            // on an INPUT element, in which case singleField is automatically
            // set to true, and singleFieldNode is set to that element. This
            // way, you don't need to fiddle with these options.
            singleField: false,

            singleFieldDelimiter: ',',

            // Set this to an input DOM node to use an existing form field.
            // Any text in it will be erased on init. But it will be
            // populated with the text of tags as they are created,
            // delimited by singleFieldDelimiter.
            //
            // If this is not set, we create an input node for it,
            // with the name given in settings.fieldName,
            // ignoring settings.itemName.
            singleFieldNode: null,

            // Optionally set a tabindex attribute on the input that gets
            // created for tag-it.
            tabIndex: null,

            // Event callbacks.
            onTagAdded  : null,
            onTagRemoved: null,
            onTagClicked: null
        },

        _create: function() {
            // for handling static scoping inside callbacks
            var that = this;

            // There are 2 kinds of DOM nodes this widget can be instantiated on:
            //     1. UL, OL, or some element containing either of these.
            //     2. INPUT, in which case 'singleField' is overridden to true,
            //        a UL is created and the INPUT is hidden.
            if (this.element.is('input')) {
                this.tagList = $('

').insertAfter(this.element);
                this.options.singleField = true;
                this.options.singleFieldNode = this.element;
                this.element.css('display', 'none');
            } else {
                this.tagList = this.element.find('ul, ol').andSelf().last();
            }

            this._tagInput = $('<input type="text">').addClass('ui-widget-content');
            if (this.options.tabIndex) {
                this._tagInput.attr('tabindex', this.options.tabIndex);
            }

            this.options.tagSource = this.options.tagSource || function(search, showChoices) {
                var filter = search.term.toLowerCase();
                var choices = $.grep(that.options.availableTags, function(element) {
                    // Only match autocomplete options that begin with the search term.
                    // (Case insensitive.)
                    return (element.toLowerCase().indexOf(filter) === 0);
                });
                showChoices(that._subtractArray(choices, that.assignedTags()));
            };

            this.tagList
                .addClass('tagit')
                .addClass('ui-widget ui-widget-content ui-corner-all')
                // Create the input field.
                .append($('

').append(this._tagInput))
                .click(function(e) {
                    var target = $(e.target);
                    if (target.hasClass('tagit-label')) {
                        that._trigger('onTagClicked', e, target.closest('.tagit-choice'));
                    } else {
                        // Sets the focus() to the input field, if the user
                        // clicks anywhere inside the UL. This is needed
                        // because the input field needs to be of a small size.
                        that._tagInput.focus();
                    }
                });

            // Add existing tags from the list, if any.
            this.tagList.children('li').each(function() {
                if (!$(this).hasClass('tagit-new')) {
                    that.createTag($(this).html(), $(this).attr('class'));
                    $(this).remove();
                }
            });

            // Single field support.
            if (this.options.singleField) {
                if (this.options.singleFieldNode) {
                    // Add existing tags from the input field.
                    var node = $(this.options.singleFieldNode);
                    var tags = node.val().split(this.options.singleFieldDelimiter);
                    node.val('');
                    $.each(tags, function(index, tag) {
                        that.createTag(tag);
                    });
                } else {
                    // Create our single field input after our list.
                    this.options.singleFieldNode = this.tagList.after('<input type="hidden" style="display:none;" value="" name="' + this.options.fieldName + '">');
                }
            }

            // Events.
            this._tagInput
                .keydown(function(event) {
                    // Backspace is not detected within a keypress, so it must use keydown.
                    if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val() === '') {
                        var tag = that._lastTag();
                        if (!that.options.removeConfirmation || tag.hasClass('remove')) {
                            // When backspace is pressed, the last tag is deleted.
                            that.removeTag(tag);
                        } else if (that.options.removeConfirmation) {
                            tag.addClass('remove ui-state-highlight');
                        }
                    } else if (that.options.removeConfirmation) {
                        that._lastTag().removeClass('remove ui-state-highlight');
                    }

                    // Comma/Space/Enter are all valid delimiters for new tags,
                    // except when there is an open quote or if setting allowSpaces = true.
                    // Tab will also create a tag, unless the tag input is empty, in which case it isn't caught.
                    if (
                        event.which == $.ui.keyCode.COMMA ||
                        event.which == $.ui.keyCode.ENTER ||
                        (
                            event.which == $.ui.keyCode.TAB &&
                            that._tagInput.val() !== ''
                        ) ||
                        (
                            event.which == $.ui.keyCode.SPACE &&
                            that.options.allowSpaces !== true &&
                            (
                                $.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != '"' ||
                                (
                                    $.trim(that._tagInput.val()).charAt(0) == '"' &&
                                    $.trim(that._tagInput.val()).charAt($.trim(that._tagInput.val()).length - 1) == '"' &&
                                    $.trim(that._tagInput.val()).length - 1 !== 0
                                )
                            )
                        )
                    ) {
                        event.preventDefault();
                        that.createTag(that._cleanedInput());

                        // The autocomplete doesn't close automatically when TAB is pressed.
                        // So let's ensure that it closes.
                        that._tagInput.autocomplete('close');
                    }
                }).blur(function(e){
                    // Create a tag when the element loses focus (unless it's empty).
                    that.createTag(that._cleanedInput());
                });

            // Autocomplete.
            if (this.options.availableTags || this.options.tagSource) {
                this._tagInput.autocomplete({
                    source: this.options.tagSource,
                    select: function(event, ui) {
                        // Delete the last tag if we autocomplete something despite the input being empty
                        // This happens because the input's blur event causes the tag to be created when
                        // the user clicks an autocomplete item.
                        // The only artifact of this is that while the user holds down the mouse button
                        // on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
                        // and is changed to the autocompleted text upon mouseup.
                        if (that._tagInput.val() === '') {
                            that.removeTag(that._lastTag(), false);
                        }
                        that.createTag(ui.item.value);
                        // Preventing the tag input to be updated with the chosen value.
                        return false;
                    }
                });
            }
        },

        _cleanedInput: function() {
            // Returns the contents of the tag input, cleaned and ready to be passed to createTag
            return $.trim(this._tagInput.val().replace(/^"(.*)"$/, '$1'));
        },

        _lastTag: function() {
            return this.tagList.children('.tagit-choice:last');
        },

        assignedTags: function() {
            // Returns an array of tag string values
            var that = this;
            var tags = [];
            if (this.options.singleField) {
                tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
                if (tags[0] === '') {
                    tags = [];
                }
            } else {
                this.tagList.children('.tagit-choice').each(function() {
                    tags.push(that.tagLabel(this));
                });
            }
            return tags;
        },

        _updateSingleTagsField: function(tags) {
            // Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
            $(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
        },

        _subtractArray: function(a1, a2) {
            var result = [];
            for (var i = 0; i < a1.length; i++) {
                if ($.inArray(a1[i], a2) == -1) {
                    result.push(a1[i]);
                }
            }
            return result;
        },

        tagLabel: function(tag) {
            // Returns the tag's string label.
            if (this.options.singleField) {
                return $(tag).children('.tagit-label').text();
            } else {
                return $(tag).children('input').val();
            }
        },

        _isNew: function(value) {
            var that = this;
            var isNew = true;
            this.tagList.children('.tagit-choice').each(function(i) {
                if (that._formatStr(value) == that._formatStr(that.tagLabel(this))) {
                    isNew = false;
                    return false;
                }
            });
            return isNew;
        },

        _formatStr: function(str) {
            if (this.options.caseSensitive) {
                return str;
            }
            return $.trim(str.toLowerCase());
        },

        createTag: function(value, additionalClass) {
            var that = this;
            // Automatically trims the value of leading and trailing whitespace.
            value = $.trim(value);

            if (!this._isNew(value) || value === '') {
                return false;
            }

            var label = $(this.options.onTagClicked ? '' : '').text(value);

            // Create tag.
            var tag = $('

')
                .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all')
                .addClass(additionalClass)
                .append(label);

            // Button for removing the tag.
            var removeTagIcon = $('')
                .addClass('ui-icon ui-icon-close');
            var removeTag = $('\xd7') // \xd7 is an X
                .addClass('close')
                .append(removeTagIcon)
                .click(function(e) {
                    // Removes a tag when the little 'x' is clicked.
                    that.removeTag(tag);
                });
            tag.append(removeTag);

            // Unless options.singleField is set, each tag has a hidden input field inline.
            if (this.options.singleField) {
                var tags = this.assignedTags();
                tags.push(value);
                this._updateSingleTagsField(tags);
            } else {
                var escapedValue = label.html();
                tag.append('<input type="hidden" style="display:none;" value="' + escapedValue + '" name="' + this.options.itemName + '[' + this.options.fieldName + '][]">');
            }

            this._trigger('onTagAdded', null, tag);

            // Cleaning the input.
            this._tagInput.val('');

            // insert tag
            this._tagInput.parent().before(tag);
        },

        removeTag: function(tag, animate) {
            animate = animate || this.options.animate;

            tag = $(tag);

            this._trigger('onTagRemoved', null, tag);

            if (this.options.singleField) {
                var tags = this.assignedTags();
                var removedTagLabel = this.tagLabel(tag);
                tags = $.grep(tags, function(el){
                    return el != removedTagLabel;
                });
                this._updateSingleTagsField(tags);
            }
            // Animate the removal.
            if (animate) {
                tag.fadeOut('fast').hide('blind', {direction: 'horizontal'}, 'fast', function(){
                    tag.remove();
                }).dequeue();
            } else {
                tag.remove();
            }
        },

        removeAll: function() {
            // Removes all tags. Takes an optional `animate` argument.
            var that = this;
            this.tagList.children('.tagit-choice').each(function(index, tag) {
                that.removeTag(tag, false);
            });
        }

    });

})(jQuery);

<commit_msg>Update comment; the animate argument doesn't exist.<commit_after>/*
* jQuery UI Tag-it!
*
* @version v2.0 (06/2011)
*
* Copyright 2011, Levy Carneiro Jr.
* Released under the MIT license.
* http://aehlke.github.com/tag-it/LICENSE
*
* Homepage:
*   http://aehlke.github.com/tag-it/
*
* Authors:
*   Levy Carneiro Jr.
*   Martin Rehfeld
*   Tobias Schmidt
*   Skylar Challand
*   Alex Ehlke
*
* Maintainer:
*   Alex Ehlke - Twitter: @aehlke
*
* Dependencies:
*   jQuery v1.4+
*   jQuery UI v1.8+
*/
(function($) {

    $.widget('ui.tagit', {
        options: {
            itemName          : 'item',
            fieldName         : 'tags',
            availableTags     : [],
            tagSource         : null,
            removeConfirmation: false,
            caseSensitive     : true,

            // When enabled, quotes are not neccesary
            // for inputting multi-word tags.
            allowSpaces: false,

            // Whether to animate tag removals or not.
            animate: true,

            // The below options are for using a single field instead of several
            // for our form values.
            //
            // When enabled, will use a single hidden field for the form,
            // rather than one per tag. It will delimit tags in the field
            // with singleFieldDelimiter.
            //
            // The easiest way to use singleField is to just instantiate tag-it
            // on an INPUT element, in which case singleField is automatically
            // set to true, and singleFieldNode is set to that element. This
            // way, you don't need to fiddle with these options.
            singleField: false,

            singleFieldDelimiter: ',',

            // Set this to an input DOM node to use an existing form field.
            // Any text in it will be erased on init. But it will be
            // populated with the text of tags as they are created,
            // delimited by singleFieldDelimiter.
            //
            // If this is not set, we create an input node for it,
            // with the name given in settings.fieldName,
            // ignoring settings.itemName.
            singleFieldNode: null,

            // Optionally set a tabindex attribute on the input that gets
            // created for tag-it.
            tabIndex: null,

            // Event callbacks.
            onTagAdded  : null,
            onTagRemoved: null,
            onTagClicked: null
        },

        _create: function() {
            // for handling static scoping inside callbacks
            var that = this;

            // There are 2 kinds of DOM nodes this widget can be instantiated on:
            //     1. UL, OL, or some element containing either of these.
            //     2. INPUT, in which case 'singleField' is overridden to true,
            //        a UL is created and the INPUT is hidden.
            if (this.element.is('input')) {
                this.tagList = $('

').insertAfter(this.element);
                this.options.singleField = true;
                this.options.singleFieldNode = this.element;
                this.element.css('display', 'none');
            } else {
                this.tagList = this.element.find('ul, ol').andSelf().last();
            }

            this._tagInput = $('<input type="text">').addClass('ui-widget-content');
            if (this.options.tabIndex) {
                this._tagInput.attr('tabindex', this.options.tabIndex);
            }

            this.options.tagSource = this.options.tagSource || function(search, showChoices) {
                var filter = search.term.toLowerCase();
                var choices = $.grep(that.options.availableTags, function(element) {
                    // Only match autocomplete options that begin with the search term.
                    // (Case insensitive.)
                    return (element.toLowerCase().indexOf(filter) === 0);
                });
                showChoices(that._subtractArray(choices, that.assignedTags()));
            };

            this.tagList
                .addClass('tagit')
                .addClass('ui-widget ui-widget-content ui-corner-all')
                // Create the input field.
                .append($('

').append(this._tagInput))
                .click(function(e) {
                    var target = $(e.target);
                    if (target.hasClass('tagit-label')) {
                        that._trigger('onTagClicked', e, target.closest('.tagit-choice'));
                    } else {
                        // Sets the focus() to the input field, if the user
                        // clicks anywhere inside the UL. This is needed
                        // because the input field needs to be of a small size.
                        that._tagInput.focus();
                    }
                });

            // Add existing tags from the list, if any.
            this.tagList.children('li').each(function() {
                if (!$(this).hasClass('tagit-new')) {
                    that.createTag($(this).html(), $(this).attr('class'));
                    $(this).remove();
                }
            });

            // Single field support.
            if (this.options.singleField) {
                if (this.options.singleFieldNode) {
                    // Add existing tags from the input field.
                    var node = $(this.options.singleFieldNode);
                    var tags = node.val().split(this.options.singleFieldDelimiter);
                    node.val('');
                    $.each(tags, function(index, tag) {
                        that.createTag(tag);
                    });
                } else {
                    // Create our single field input after our list.
                    this.options.singleFieldNode = this.tagList.after('<input type="hidden" style="display:none;" value="" name="' + this.options.fieldName + '">');
                }
            }

            // Events.
            this._tagInput
                .keydown(function(event) {
                    // Backspace is not detected within a keypress, so it must use keydown.
                    if (event.which == $.ui.keyCode.BACKSPACE && that._tagInput.val() === '') {
                        var tag = that._lastTag();
                        if (!that.options.removeConfirmation || tag.hasClass('remove')) {
                            // When backspace is pressed, the last tag is deleted.
                            that.removeTag(tag);
                        } else if (that.options.removeConfirmation) {
                            tag.addClass('remove ui-state-highlight');
                        }
                    } else if (that.options.removeConfirmation) {
                        that._lastTag().removeClass('remove ui-state-highlight');
                    }

                    // Comma/Space/Enter are all valid delimiters for new tags,
                    // except when there is an open quote or if setting allowSpaces = true.
                    // Tab will also create a tag, unless the tag input is empty, in which case it isn't caught.
                    if (
                        event.which == $.ui.keyCode.COMMA ||
                        event.which == $.ui.keyCode.ENTER ||
                        (
                            event.which == $.ui.keyCode.TAB &&
                            that._tagInput.val() !== ''
                        ) ||
                        (
                            event.which == $.ui.keyCode.SPACE &&
                            that.options.allowSpaces !== true &&
                            (
                                $.trim(that._tagInput.val()).replace( /^s*/, '' ).charAt(0) != '"' ||
                                (
                                    $.trim(that._tagInput.val()).charAt(0) == '"' &&
                                    $.trim(that._tagInput.val()).charAt($.trim(that._tagInput.val()).length - 1) == '"' &&
                                    $.trim(that._tagInput.val()).length - 1 !== 0
                                )
                            )
                        )
                    ) {
                        event.preventDefault();
                        that.createTag(that._cleanedInput());

                        // The autocomplete doesn't close automatically when TAB is pressed.
                        // So let's ensure that it closes.
                        that._tagInput.autocomplete('close');
                    }
                }).blur(function(e){
                    // Create a tag when the element loses focus (unless it's empty).
                    that.createTag(that._cleanedInput());
                });

            // Autocomplete.
            if (this.options.availableTags || this.options.tagSource) {
                this._tagInput.autocomplete({
                    source: this.options.tagSource,
                    select: function(event, ui) {
                        // Delete the last tag if we autocomplete something despite the input being empty
                        // This happens because the input's blur event causes the tag to be created when
                        // the user clicks an autocomplete item.
                        // The only artifact of this is that while the user holds down the mouse button
                        // on the selected autocomplete item, a tag is shown with the pre-autocompleted text,
                        // and is changed to the autocompleted text upon mouseup.
                        if (that._tagInput.val() === '') {
                            that.removeTag(that._lastTag(), false);
                        }
                        that.createTag(ui.item.value);
                        // Preventing the tag input to be updated with the chosen value.
                        return false;
                    }
                });
            }
        },

        _cleanedInput: function() {
            // Returns the contents of the tag input, cleaned and ready to be passed to createTag
            return $.trim(this._tagInput.val().replace(/^"(.*)"$/, '$1'));
        },

        _lastTag: function() {
            return this.tagList.children('.tagit-choice:last');
        },

        assignedTags: function() {
            // Returns an array of tag string values
            var that = this;
            var tags = [];
            if (this.options.singleField) {
                tags = $(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter);
                if (tags[0] === '') {
                    tags = [];
                }
            } else {
                this.tagList.children('.tagit-choice').each(function() {
                    tags.push(that.tagLabel(this));
                });
            }
            return tags;
        },

        _updateSingleTagsField: function(tags) {
            // Takes a list of tag string values, updates this.options.singleFieldNode.val to the tags delimited by this.options.singleFieldDelimiter
            $(this.options.singleFieldNode).val(tags.join(this.options.singleFieldDelimiter));
        },

        _subtractArray: function(a1, a2) {
            var result = [];
            for (var i = 0; i < a1.length; i++) {
                if ($.inArray(a1[i], a2) == -1) {
                    result.push(a1[i]);
                }
            }
            return result;
        },

        tagLabel: function(tag) {
            // Returns the tag's string label.
            if (this.options.singleField) {
                return $(tag).children('.tagit-label').text();
            } else {
                return $(tag).children('input').val();
            }
        },

        _isNew: function(value) {
            var that = this;
            var isNew = true;
            this.tagList.children('.tagit-choice').each(function(i) {
                if (that._formatStr(value) == that._formatStr(that.tagLabel(this))) {
                    isNew = false;
                    return false;
                }
            });
            return isNew;
        },

        _formatStr: function(str) {
            if (this.options.caseSensitive) {
                return str;
            }
            return $.trim(str.toLowerCase());
        },

        createTag: function(value, additionalClass) {
            var that = this;
            // Automatically trims the value of leading and trailing whitespace.
            value = $.trim(value);

            if (!this._isNew(value) || value === '') {
                return false;
            }

            var label = $(this.options.onTagClicked ? '' : '').text(value);

            // Create tag.
            var tag = $('

')
                .addClass('tagit-choice ui-widget-content ui-state-default ui-corner-all')
                .addClass(additionalClass)
                .append(label);

            // Button for removing the tag.
            var removeTagIcon = $('')
                .addClass('ui-icon ui-icon-close');
            var removeTag = $('\xd7') // \xd7 is an X
                .addClass('close')
                .append(removeTagIcon)
                .click(function(e) {
                    // Removes a tag when the little 'x' is clicked.
                    that.removeTag(tag);
                });
            tag.append(removeTag);

            // Unless options.singleField is set, each tag has a hidden input field inline.
            if (this.options.singleField) {
                var tags = this.assignedTags();
                tags.push(value);
                this._updateSingleTagsField(tags);
            } else {
                var escapedValue = label.html();
                tag.append('<input type="hidden" style="display:none;" value="' + escapedValue + '" name="' + this.options.itemName + '[' + this.options.fieldName + '][]">');
            }

            this._trigger('onTagAdded', null, tag);

            // Cleaning the input.
            this._tagInput.val('');

            // insert tag
            this._tagInput.parent().before(tag);
        },

        removeTag: function(tag, animate) {
            animate = animate || this.options.animate;

            tag = $(tag);

            this._trigger('onTagRemoved', null, tag);

            if (this.options.singleField) {
                var tags = this.assignedTags();
                var removedTagLabel = this.tagLabel(tag);
                tags = $.grep(tags, function(el){
                    return el != removedTagLabel;
                });
                this._updateSingleTagsField(tags);
            }
            // Animate the removal.
            if (animate) {
                tag.fadeOut('fast').hide('blind', {direction: 'horizontal'}, 'fast', function(){
                    tag.remove();
                }).dequeue();
            } else {
                tag.remove();
            }
        },

        removeAll: function() {
            // Removes all tags.
            var that = this;
            this.tagList.children('.tagit-choice').each(function(index, tag) {
                that.removeTag(tag, false);
            });
        }

    });

})(jQuery);

<|endoftext|>


<commit_before>Materialize.toast = function (message, displayLength, className, completeCallback) {
  className = className || "";

  var container = document.getElementById('toast-container');

  // Create toast container if it does not exist
  if (container === null) {
    // create notification container
    container = document.createElement('div');
    container.id = 'toast-container';
    document.body.appendChild(container);
  }

  // Select and append toast
  var newToast = createToast(message);

  // only append toast if message is not undefined
  if(message){
    container.appendChild(newToast);
  }

  newToast.style.opacity = 0;

  // Animate toast in
  Vel(newToast, {translateY: '-35px',  opacity: 1 }, {duration: 300,
    easing: 'easeOutCubic',
    queue: false});

  // Allows timer to be pause while being panned
  var timeLeft = displayLength;
  var counterInterval;
  if (timeLeft != null)  {
    counterInterval = setInterval (function(){
      if (newToast.parentNode === null)
        window.clearInterval(counterInterval);

      // If toast is not being dragged, decrease its time remaining
      if (!newToast.classList.contains('panning')) {
        timeLeft -= 20;
      }

      if (timeLeft <= 0) {
        // Animate toast out
        Vel(newToast, {"opacity": 0, marginTop: '-40px'}, { duration: 375,
            easing: 'easeOutExpo',
            queue: false,
            complete: function(){
              // Call the optional callback
              if(typeof(completeCallback) === "function")
                completeCallback();
              // Remove toast after it times out
              this[0].parentNode.removeChild(this[0]);
            }
          });
        window.clearInterval(counterInterval);
      }
    }, 20);
  }

  function createToast(html) {

    // Create toast
    var toast = document.createElement('div');
    toast.classList.add('toast');
    if (className) {
      var classes = className.split(' ');

      for (var i = 0, count = classes.length; i < count; i++) {
        toast.classList.add(classes[i]);
      }
    }
  // If type of parameter is HTML Element
    if ( typeof HTMLElement === "object" ? html instanceof HTMLElement : html && typeof html === "object" && html !== null && html.nodeType === 1 && typeof html.nodeName==="string"
) {
      toast.appendChild(html);
    }
    else if (html instanceof jQuery) {
      // Check if it is jQuery object
      toast.appendChild(html[0]);
    }
    else {
      // Insert as text;
      toast.innerHTML = html;
    }
    // Bind hammer
    var hammerHandler = new Hammer(toast, {prevent_default: false});
    hammerHandler.on('pan', function(e) {
      var deltaX = e.deltaX;
      var activationDistance = 80;

      // Change toast state
      if (!toast.classList.contains('panning')){
        toast.classList.add('panning');
      }

      var opacityPercent = 1-Math.abs(deltaX / activationDistance);
      if (opacityPercent < 0)
        opacityPercent = 0;

      Vel(toast, {left: deltaX, opacity: opacityPercent }, {duration: 50, queue: false, easing: 'easeOutQuad'});

    });

    hammerHandler.on('panend', function(e) {
      var deltaX = e.deltaX;
      var activationDistance = 80;

      // If toast dragged past activation point
      if (Math.abs(deltaX) > activationDistance) {
        Vel(toast, {marginTop: '-40px'}, { duration: 375,
          easing: 'easeOutExpo',
          queue: false,
          complete: function(){
            if(typeof(completeCallback) === "function") {
              completeCallback();
            }
            toast.parentNode.removeChild(toast);
          }
        });

      } else {
        toast.classList.remove('panning');
        // Put toast back into original position
        Vel(toast, { left: 0, opacity: 1 }, { duration: 300,
          easing: 'easeOutExpo',
          queue: false
        });

      }
    });

    return toast;
  }
};
<commit_msg>wip: toast rewrite<commit_after>(function() {
  'use strict';
  // Materialize.toast = function (message, displayLength, className, completeCallback) {

  class Toast {
    constructor(message, displayLength, className, completeCallback) {
      if (!message) {
        return;
      }

      this.message = message;
      this.options = {
        displayLength: displayLength,
        inDuration: 300,
        outDuration: 375,
        className: className,
        completeCallback: completeCallback,
        activationPercent: 0.8
      };

      if (Toast._count === 0) {
        Toast.createContainer();
      }

      Toast._count++;
      let toastElement = this.createToast();
      toastElement.M_Toast = this;
      this.el = toastElement;

    }

    static createContainer() {
      let container = document.createElement('div');
      container.setAttribute('id', 'toast-container');

      // Add event handler
      container.addEventListener('touchstart', Toast._onDragStart);
      container.addEventListener('touchmove', Toast._onDragMove);
      container.addEventListener('touchend', Toast._onDragEnd);

      document.body.appendChild(container);
      Toast._container = container;
    }

    static _onDragStart(e) {
      if (e.target && e.target.classList.contains('toast')) {
        let toast = e.target.M_Toast;
        e.target.style.transition = null;
        toast.startingXPos = Toast._xPos(e);
        toast.time = Date.now();
        toast.xPos = Toast._xPos(e);
      }
    }

    static _onDragMove(e) {
      if (e.target && e.target.classList.contains('toast')) {
        let toast = e.target.M_Toast;
        toast.deltaX = Math.abs(toast.xPos - Toast._xPos(e));
        toast.xPos = Toast._xPos(e);
        toast.velocityX = toast.deltaX / (Date.now() - toast.time);
        toast.time = Date.now();

        let totalDeltaX = toast.xPos - toast.startingXPos;
        let activationDistance =
            e.target.offsetWidth * toast.options.activationPercent;
        e.target.style.transform = `translateX(${totalDeltaX}px)`;
        e.target.style.opacity = 1-Math.abs(totalDeltaX / activationDistance);
      }
    }

    static _onDragEnd(e) {
      if (e.target && e.target.classList.contains('toast')) {
        let toast = e.target.M_Toast;
        let totalDeltaX = toast.xPos - toast.startingXPos;
        let activationDistance =
            e.target.offsetWidth * toast.options.activationPercent;
        let shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance ||
            toast.velocityX > 1;
        if (shouldBeDismissed) {
          toast.remove();

        } else {
          e.target.style.transition = 'transform .2s, opacity .2s';
          e.target.style.transform = null;
          e.target.style.opacity = null;
        }
      }
    }

    static _xPos(e) {
      if (e.targetTouches && (e.targetTouches.length >= 1)) {
        return e.targetTouches[0].clientX;
      }
      // mouse event
      return e.clientX;
    }

    createToast() {
      let toast = document.createElement('div');
      toast.classList.add('toast');

      // Add custom classes onto toast
      if (this.options.className) {
        var classes = className.split(' ');
        for (var i = 0, count = classes.length; i < count; i++) {
          toast.classList.add(classes[i]);
        }
      }

      // Set content
      if ( typeof HTMLElement === "object" ?
           this.message instanceof HTMLElement :
           this.message && typeof this.message === "object" &&
           this.message !== null && this.message.nodeType === 1 &&
           typeof this.message.nodeName==="string"
         ) {
        toast.appendChild(this.message);

      // Check if it is jQuery object
      } else if (this.message instanceof jQuery) {
        toast.appendChild(this.message[0]);

        // Insert as text;
      } else {
        toast.innerHTML = this.message;
      }

      // Append toast
      Toast._container.appendChild(toast);

      return toast;
    }

    remove() {
      let activationDistance =
          this.el.offsetWidth * this.options.activationPercent;

      this.el.style.transition = 'transform .05s, opacity .05s';
      this.el.style.transform = `translateX(${activationDistance}px)`;
      this.el.style.opacity = 0;
      this.el.parentNode.removeChild(this.el);

      Toast._count--;
      if (Toast._count === 0) {
        Toast._container.parentNode.removeChild(Toast._container);
      }
    }
  }

  /**
   * @static
   * @memberof Toast
   */
  Toast._count = 0;

  /**
   * @static
   * @memberof Toast
   */
  Toast._container = undefined;

  window.Materialize.Toast = Toast;
  window.Materialize.toast = function(message, displayLength, className, completeCallback) {
    return new Toast(message, displayLength, className, completeCallback);
  }
// };
})();
<|endoftext|>


<commit_before>var Upvote = (function (window, document) {

	that = this;

	// endEvent = hasTouch ? 'touchend' : 'mouseup',

	Upvote = function (opts) {

		that = this;

		this.current_category = 'us';

		// ---------------------------------------------------------
		// Muench launch
		// ---------------------------------------------------------

		// Options from user
		for (i in opts) this.options[i] = opts[i];

		// ---------------------------------------------------------
		// Skimmin launch
		// ---------------------------------------------------------

        	$('.upvote-container').on('click', this.fn_tap_upvote.bind(this));
        	$('.category-container').on('click', this.fn_change_category.bind(this));

		window.addEventListener('load', function() {
		    FastClick.attach(document.body);
		}, false);

		this.fn_hide_rendering_icons();
		this.fn_loading();
       		this.fn_reveal_content();

    	};

	Upvote.prototype = {

		// ------------------------------------------------------
		// Skimmin Core Functions
		// ------------------------------------------------------

        	// primarily used to hide slow rendering
        	fn_loading: function() {

            	that = this;

            	$('#L').fadeIn(0);
            	$('#L').addClass('animated zoomIn');

            	setTimeout(function() {
            		$('#O').fadeIn(0);
            		$('#O').addClass('animated zoomIn');
            	}, 100);

            	setTimeout(function() {
            		$('#A').fadeIn(0);
            		$('#A').addClass('animated zoomIn');
            	}, 200);

            	setTimeout(function() {
            		$('#D').fadeIn(0);
            		$('#D').addClass('animated zoomIn');
            	}, 300);

            	setTimeout(function() {
            		$('#I').fadeIn(0);
            		$('#I').addClass('animated zoomIn');
            	}, 400);

            	setTimeout(function() {
            		$('#N').fadeIn(0);
            		$('#N').addClass('animated zoomIn');
            	}, 500);

            	setTimeout(function() {
            		$('#G').fadeIn(0);
            		$('#G').addClass('animated zoomIn');
            	}, 600);

            	int_loading_count = 0;
            	arr_colors = Array('rgba(52, 152, 219, 1)', 'rgba(255, 140, 0, 1)', 'rgba(231, 76, 60, 1)', 'rgba(0, 128, 0, .9)', 'rgba(0, 154, 136, .9)', 'rgba(164, 121, 228, 1)');

            	// bool_kill_next_loop = false;

        		// $('#loading-circle').addClass('animated pulse');

        	pulsing_circle_interval = setInterval(function() {

        			// $('#loading-circle').css('opacity', '.7');

        			/*$('#L').css('opacity', '.8');
        			$('#L').css('-webkit-transition', '.5s');
        			$('#L').css('-webkit-transform', 'scale(.9)');*/

        			$('#L').addClass('zoomOut');

        			/*setTimeout(function() {
        				$('#L').css('opacity', '1');
        				$('#L').css('-webkit-transform', 'scale(1)');
        			}, 500);*/

        			setTimeout(function() {
        				/*$('#O').css('opacity', '1');
        				$('#A').css('opacity', '.8');*/
        				$('#O').addClass('zoomOut');
        			}, 100);

        			setTimeout(function() {
        				$('#A').addClass('zoomOut');
        			}, 200);

        			setTimeout(function() {
        				$('#D').addClass('zoomOut');
        			}, 300);

        			setTimeout(function() {
        				$('#I').addClass('zoomOut');
        			}, 400);

        			setTimeout(function() {
        				$('#N').addClass('zoomOut');
        			}, 500);

        			setTimeout(function() {
        				$('#G').addClass('zoomOut');
        			}, 600);

        			/*setTimeout(function() {
        				$('#A').css('opacity', '1');
        				$('#D').css('opacity', '.8');
        			}, 300);*/

        			setTimeout(function() {
        				$('#D').css('opacity', '1');
        				$('#I').css('opacity', '.8');
        			}, 400);

        			setTimeout(function() {
        				$('#I').css('opacity', '1');
        				$('#N').css('opacity', '.8');
        			}, 500);

        			setTimeout(function() {
        				$('#N').css('opacity', '1');
        				$('#G').css('opacity', '.75');
        			}, 600);

        			setTimeout(function() {
        				$('#G').css('opacity', '1');
        			}, 700);

        			// $('#loading-circle').css('background-color', arr_colors[int_loading_count]);
        			int_loading_count += 1;
        			if (int_loading_count == 4) {
        				clearInterval(pulsing_circle_interval);
        				setTimeout(function() {
        					$('#loading-circle').addClass('animated slideOutUp');
        					$('#loading-circle').fadeOut(300);
        				}, 500);
        				setTimeout(function() {
        					$('#content').fadeIn(300);
        					$('#content').addClass('animated slideInUp');
        				}, 750);
        			}

        			/*setTimeout(function() {
        				$('#loading-circle').css('opacity', '1');
        			}, 500);*/

        		}, 1000);

        	},

        	fn_reveal_content: function() {

        		/*setTimeout(function() {
        			$('#loading-circle').addClass('animated zoomOut');
        			$('#content').addClass('animated slideInUp');
        		}, 300);*/

        	},

        	fn_hide_rendering_icons: function() {

        		setTimeout(function() {
        			$('.rendering-container').addClass('display-none');
        		}, 3000);

        	},

        	fn_change_category: function(e) {

        		if (this.current_category == 'world') {
        			$('#category-container').removeClass('world')
        			$('#category-container').addClass('us');
        			$('#category-text').html('us');
        			this.current_category = 'us';
        		}

        		else if (this.current_category == 'us') {
        			$('#category-container').removeClass('us')
        			$('#category-container').addClass('sports');
        			$('#category-text').html('sports');
        			this.current_category = 'sports';
        		}

        		else if (this.current_category == 'sports') {
        			$('#category-container').removeClass('sports')
        			$('#category-container').addClass('business');
        			$('#category-text').html('business');
        			this.current_category = 'business';
        		}

        		else if (this.current_category == 'business') {
        			$('#category-container').removeClass('business')
        			$('#category-container').addClass('technology');
        			$('#category-text').html('technology');
        			this.current_category = 'technology';
        		}

        		else if (this.current_category == 'technology') {
        			$('#category-container').removeClass('technology')
        			$('#category-container').addClass('entertainment');
        			$('#category-text').html('entertainment');
        			this.current_category = 'entertainment';
        		}

        		else {
        			$('#category-container').removeClass('entertainment')
        			$('#category-container').addClass('world');
        			$('#category-text').html('world');
        			this.current_category = 'world';
        		}

        		if ($('.upvote-container').hasClass('upvoted') == true) {
        			$('.upvote-container').removeClass('us world sports business technology entertainment');
        			$('.upvote-text').removeClass('us world sports business technology entertainment');
        			$('.upvote-icon').removeClass('us world sports business technology entertainment');
        			$('.upvote-container').addClass(this.current_category);
        			$('.upvote-text').addClass(this.current_category);
        			$('.upvote-icon').addClass(this.current_category);
        		}

        	},

		fn_tap_upvote: function() {

			if ($('.upvote-container').hasClass('upvoted') == true) {

				$('.upvote-container').removeClass('upvoted');

				setTimeout(function() {
        				$('.upvote-container').removeClass('tapped us world sports business technology entertainment');
        				$('.upvote-text').removeClass('us world sports business technology entertainment');
        				$('.upvote-text').html(30);
        				$('.upvote-icon').removeClass('us world sports business technology entertainment');
        			}, 300);
        		}

			else {

				$('.upvote-container').addClass('upvoted');
    				setTimeout(function() {
        				$('.upvote-container').addClass('tapped ' + that.current_category);
        				$('.upvote-text').addClass(that.current_category);
        				$('.upvote-text').html(31);
        				$('.upvote-icon').addClass(that.current_category);
    				}, 300);
			}

		},

	};

	return Upvote;

})(window, document);
<commit_msg>Update upvote.js<commit_after>var Upvote = (function (window, document) {

	that = this;

	// endEvent = hasTouch ? 'touchend' : 'mouseup',

	Upvote = function (opts) {

		that = this;

		this.current_category = 'us';

		// ---------------------------------------------------------
		// Muench launch
		// ---------------------------------------------------------

		// Options from user
		for (i in opts) this.options[i] = opts[i];

		// ---------------------------------------------------------
		// Skimmin launch
		// ---------------------------------------------------------

        	$('.upvote-container').on('click', this.fn_tap_upvote.bind(this));
        	$('.category-container').on('click', this.fn_change_category.bind(this));

		window.addEventListener('load', function() {
		    FastClick.attach(document.body);
		}, false);

		this.fn_hide_rendering_icons();
		this.fn_loading();
       		this.fn_reveal_content();

    	};

	Upvote.prototype = {

		// ------------------------------------------------------
		// Skimmin Core Functions
		// ------------------------------------------------------

        	// primarily used to hide slow rendering
        	fn_loading: function() {

            	that = this;

            	$('#L').fadeIn(0);
            	$('#L').addClass('animated zoomIn');

            	setTimeout(function() {
            		$('#O').fadeIn(0);
            		$('#O').addClass('animated zoomIn');
            	}, 100);

            	setTimeout(function() {
            		$('#A').fadeIn(0);
            		$('#A').addClass('animated zoomIn');
            	}, 200);

            	setTimeout(function() {
            		$('#D').fadeIn(0);
            		$('#D').addClass('animated zoomIn');
            	}, 300);

            	setTimeout(function() {
            		$('#I').fadeIn(0);
            		$('#I').addClass('animated zoomIn');
            	}, 400);

            	setTimeout(function() {
            		$('#N').fadeIn(0);
            		$('#N').addClass('animated zoomIn');
            	}, 500);

            	setTimeout(function() {
            		$('#G').fadeIn(0);
            		$('#G').addClass('animated zoomIn');
            	}, 600);

            	int_loading_count = 0;
            	arr_colors = Array('rgba(52, 152, 219, 1)', 'rgba(255, 140, 0, 1)', 'rgba(231, 76, 60, 1)', 'rgba(0, 128, 0, .9)', 'rgba(0, 154, 136, .9)', 'rgba(164, 121, 228, 1)');

            	// bool_kill_next_loop = false;

        		// $('#loading-circle').addClass('animated pulse');

        	pulsing_circle_interval = setInterval(function() {

        			$('#L').addClass('slideOutLeft');

        			setTimeout(function() {
        				/*$('#O').css('opacity', '1');
        				$('#A').css('opacity', '.8');*/
        				$('#O').addClass('slideOutLeft');
        			}, 100);

        			setTimeout(function() {
        				$('#A').addClass('slideOutLeft');
        			}, 200);

        			setTimeout(function() {
        				$('#D').addClass('slideOutLeft');
        			}, 300);

        			setTimeout(function() {
        				$('#I').addClass('zoomOut');
        			}, 400);

        			setTimeout(function() {
        				$('#N').addClass('zoomOut');
        			}, 500);

        			setTimeout(function() {
        				$('#G').addClass('zoomOut');
        			}, 600);

        			/*setTimeout(function() {
        				$('#A').css('opacity', '1');
        				$('#D').css('opacity', '.8');
        			}, 300);*/

        			setTimeout(function() {
        				$('#D').css('opacity', '1');
        				$('#I').css('opacity', '.8');
        			}, 400);

        			setTimeout(function() {
        				$('#I').css('opacity', '1');
        				$('#N').css('opacity', '.8');
        			}, 500);

        			setTimeout(function() {
        				$('#N').css('opacity', '1');
        				$('#G').css('opacity', '.75');
        			}, 600);

        			setTimeout(function() {
        				$('#G').css('opacity', '1');
        			}, 700);

        			// $('#loading-circle').css('background-color', arr_colors[int_loading_count]);
        			int_loading_count += 1;
        			if (int_loading_count == 4) {
        				clearInterval(pulsing_circle_interval);
        				setTimeout(function() {
        					$('#loading-circle').addClass('animated slideOutUp');
        					$('#loading-circle').fadeOut(300);
        				}, 500);
        				setTimeout(function() {
        					$('#content').fadeIn(300);
        					$('#content').addClass('animated slideInUp');
        				}, 750);
        			}

        			/*setTimeout(function() {
        				$('#loading-circle').css('opacity', '1');
        			}, 500);*/

        		}, 1000);

        	},

        	fn_reveal_content: function() {

        		/*setTimeout(function() {
        			$('#loading-circle').addClass('animated zoomOut');
        			$('#content').addClass('animated slideInUp');
        		}, 300);*/

        	},

        	fn_hide_rendering_icons: function() {

        		setTimeout(function() {
        			$('.rendering-container').addClass('display-none');
        		}, 3000);

        	},

        	fn_change_category: function(e) {

        		if (this.current_category == 'world') {
        			$('#category-container').removeClass('world')
        			$('#category-container').addClass('us');
        			$('#category-text').html('us');
        			this.current_category = 'us';
        		}

        		else if (this.current_category == 'us') {
        			$('#category-container').removeClass('us')
        			$('#category-container').addClass('sports');
        			$('#category-text').html('sports');
        			this.current_category = 'sports';
        		}

        		else if (this.current_category == 'sports') {
        			$('#category-container').removeClass('sports')
        			$('#category-container').addClass('business');
        			$('#category-text').html('business');
        			this.current_category = 'business';
        		}

        		else if (this.current_category == 'business') {
        			$('#category-container').removeClass('business')
        			$('#category-container').addClass('technology');
        			$('#category-text').html('technology');
        			this.current_category = 'technology';
        		}

        		else if (this.current_category == 'technology') {
        			$('#category-container').removeClass('technology')
        			$('#category-container').addClass('entertainment');
        			$('#category-text').html('entertainment');
        			this.current_category = 'entertainment';
        		}

        		else {
        			$('#category-container').removeClass('entertainment')
        			$('#category-container').addClass('world');
        			$('#category-text').html('world');
        			this.current_category = 'world';
        		}

        		if ($('.upvote-container').hasClass('upvoted') == true) {
        			$('.upvote-container').removeClass('us world sports business technology entertainment');
        			$('.upvote-text').removeClass('us world sports business technology entertainment');
        			$('.upvote-icon').removeClass('us world sports business technology entertainment');
        			$('.upvote-container').addClass(this.current_category);
        			$('.upvote-text').addClass(this.current_category);
        			$('.upvote-icon').addClass(this.current_category);
        		}

        	},

		fn_tap_upvote: function() {

			if ($('.upvote-container').hasClass('upvoted') == true) {

				$('.upvote-container').removeClass('upvoted');

				setTimeout(function() {
        				$('.upvote-container').removeClass('tapped us world sports business technology entertainment');
        				$('.upvote-text').removeClass('us world sports business technology entertainment');
        				$('.upvote-text').html(30);
        				$('.upvote-icon').removeClass('us world sports business technology entertainment');
        			}, 300);
        		}

			else {

				$('.upvote-container').addClass('upvoted');
    				setTimeout(function() {
        				$('.upvote-container').addClass('tapped ' + that.current_category);
        				$('.upvote-text').addClass(that.current_category);
        				$('.upvote-text').html(31);
        				$('.upvote-icon').addClass(that.current_category);
    				}, 300);
			}

		},

	};

	return Upvote;

})(window, document);
<|endoftext|>