<commit_before>
(function ($) {

    "use strict";

    var methods = {
        init: function (options) {

            var defaults = $.extend(true, {}, $.fn.markdownEditor.defaults, options),
                plugin = this,
                preview = false,
                fullscreen = false;

            // Replace the content of the div with our html
            plugin.addClass('md-container').html(editorHtml(this.text(), defaults));

            // If the Bootstrap tooltip library is loaded, initialize the tooltips of the toolbar
            if (typeof $().tooltip === 'function') {
                plugin.find('[data-mdtooltip="tooltip"]').tooltip({
                    container: 'body'
                });
            }

            var mdEditor = plugin.find('.md-editor'),
                mdPreview = plugin.find('.md-preview'),
                mdLoading = plugin.find('.md-loading');

            plugin.css({
                width: defaults.width
            });

            mdEditor.css({
                width: defaults.width,
                height: defaults.height,
                fontSize: defaults.fontSize
            });

            mdPreview.css({
                width: defaults.width,
                height: defaults.height
            });

            // Initialize Ace
            var editor = ace.edit(mdEditor[0]),
                snippetManager;

            editor.setTheme('ace/theme/' + defaults.theme);
            editor.getSession().setMode('ace/mode/markdown');
            editor.getSession().setUseWrapMode(true);

            editor.setHighlightActiveLine(false);
            editor.setShowPrintMargin(false);
            editor.renderer.setShowGutter(false);

            ace.config.loadModule('ace/ext/language_tools', function () {
                snippetManager = ace.require('ace/snippets').snippetManager;
                setShortcuts(editor, snippetManager);
            });

            // Image drag and drop and upload events
            if (defaults.imageUpload) {

                plugin.find('.md-input-upload').on('change', function() {
                    var files = $(this).get(0).files;

                    if (files.length) {
                        uploadFiles(defaults.uploadPath, $(this).get(0).files, editor, snippetManager, mdLoading);
                    }
                });

                plugin.on('dragenter', function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                });

                plugin.on('dragover', function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                });

                plugin.on('drop', function (e) {
                    e.preventDefault();
                    var files = e.originalEvent.dataTransfer.files;

                    uploadFiles(defaults.uploadPath, files, editor, snippetManager, mdLoading);
                });
            }

            // Window resize event
            if (defaults.fullscreen === true) {
                $(window).resize(function () {
                    if (fullscreen === true) {
                        if (preview === false) {
                            adjustFullscreenLayout(mdEditor);
                        } else {
                            adjustFullscreenLayout(mdPreview);
                        }
                    }
                });
            }

            // Toolbar events
            plugin.find('.md-btn').click(function () {
                var btnType = $(this).data('btn'),
                    selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (btnType === 'h1') {
                    insertBeforeText(editor, '#');

                } else if (btnType === 'h2') {
                    insertBeforeText(editor, '##');

                } else if (btnType === 'h3') {
                    insertBeforeText(editor, '###');

                } else if (btnType === 'ul') {
                    insertBeforeText(editor, '*');

                } else if (btnType === 'ol') {
                    insertBeforeText(editor, '1.');

                } else if (btnType === 'bold') {
                    editor.execCommand('bold');

                } else if (btnType === 'italic') {
                    editor.execCommand('italic');

                } else if (btnType === 'link') {
                    editor.execCommand('link');

                } else if (btnType === 'image') {
                    if (selectedText === '') {
                        snippetManager.insertSnippet(editor, '![${1:text}](http://$2)');
                    } else {
                        snippetManager.insertSnippet(editor, '![' + selectedText + '](http://$1)');
                    }

                } else if (btnType === 'edit') {
                    preview = false;

                    mdPreview.hide();
                    mdEditor.show();
                    plugin.find('.btn-edit').addClass('active');
                    plugin.find('.btn-preview').removeClass('active');

                    if (fullscreen === true) {
                        adjustFullscreenLayout(mdEditor);
                    }

                } else if (btnType === 'preview') {
                    preview = true;

                    mdPreview.html('
' + defaults.label.loading + '...
');

                    defaults.onPreview(editor.getSession().getValue(), function (content) {
                        mdPreview.html(content);
                    });

                    mdEditor.hide();
                    mdPreview.show();
                    plugin.find('.btn-preview').addClass('active');
                    plugin.find('.btn-edit').removeClass('active');

                    if (fullscreen === true) {
                        adjustFullscreenLayout(mdPreview);
                    }

                } else if (btnType === 'fullscreen') {

                    if (fullscreen === true) {
                        fullscreen = false;

                        $('body, html').removeClass('md-body-fullscreen');
                        plugin.removeClass('md-fullscreen');

                        mdEditor.css('height', defaults.height);
                        mdPreview.css('height', defaults.height);

                    } else {
                        fullscreen = true;

                        $('body, html').addClass('md-body-fullscreen');
                        plugin.addClass('md-fullscreen');

                        if (preview === false) {
                            adjustFullscreenLayout(mdEditor);
                        } else {
                            adjustFullscreenLayout(mdPreview);
                        }
                    }

                    editor.resize();
                }

                editor.focus();
            });

            return this;
        },
        content: function () {
            var editor = ace.edit(this.find('.md-editor')[0]);
            return editor.getSession().getValue();
        },
        setContent: function(str) {
          var editor = ace.edit(this.find('.md-editor')[0]);
          editor.setValue(str);
        }
    };

    $.fn.markdownEditor = function (options) {

        if (methods[options]) {
            return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));

        } else if (typeof options === 'object' || ! options) {
            return methods.init.apply(this, arguments);

        } else {
            $.error('Method ' +  options + ' does not exist on jQuery.markdownEditor');
        }
    };

    function uploadFiles (url, files, editor, snippetManager, loading) {

        loading.show();

        var data = new FormData(),
            i = 0;

        for (i = 0; i < files.length; i++) {
            data.append('file' + i, files[i]);
        }

        $.ajax({
            url: url,
            type: 'POST',
            contentType: false,
            data: data,
            processData: false,
            cache: false,
            dataType: 'json'
        }).done (function (uploadedFiles) {

            var separation = '';
            if (uploadedFiles.length > 1) {
                separation = "\n";
            }

            for (var i = 0; i < uploadedFiles.length; i++) {
                snippetManager.insertSnippet(editor, '![](' + uploadedFiles[i] + ')' + separation);
            }

        }).always(function () {
            loading.hide();
        });
    }

    function adjustFullscreenLayout (mdPanel) {
        var hWindow = $(window).height(),
            tEditor = mdPanel.offset().top,
            hEditor;

        if(hWindow > tEditor) {
            hEditor = hWindow - tEditor;
            mdPanel.css('height', hEditor + 'px');
        }
    }

    function setShortcuts (editor, snippetManager) {
        editor.commands.addCommand({
            name: 'bold',
            bindKey: {win: 'Ctrl-B',  mac: 'Command-B'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '**${1:text}**');
                } else {
                    snippetManager.insertSnippet(editor, '**' + selectedText + '**');
                }
            },
            readOnly: false
        });

        editor.commands.addCommand({
            name: 'italic',
            bindKey: {win: 'Ctrl-I',  mac: 'Command-I'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '*${1:text}*');
                } else {
                    snippetManager.insertSnippet(editor, '*' + selectedText + '*');
                }
            },
            readOnly: false
        });

        editor.commands.addCommand({
            name: 'link',
            bindKey: {win: 'Ctrl-K',  mac: 'Command-K'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '[${1:text}](http://$2)');
                } else {
                    snippetManager.insertSnippet(editor, '[' + selectedText + '](http://$1)');
                }
            },
            readOnly: false
        });
    }

    function insertBeforeText (editor, string) {

        if (editor.getCursorPosition().column === 0) {
            editor.navigateLineStart();
            editor.insert(string + ' ');
        } else {
            editor.navigateLineStart();
            editor.insert(string + ' ');
            editor.navigateLineEnd();
        }
    }

    function editorHtml (content, options) {
        var html = '';

        html += '

';
        html += '
';
            html += '
';

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader1 + '" class="md-btn btn btn-sm btn-default" data-btn="h1">H1</button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader2 + '" class="md-btn btn btn-sm btn-default" data-btn="h2">H2</button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader3 + '" class="md-btn btn btn-sm btn-default" data-btn="h3">H3</button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnBold + '" class="md-btn btn btn-sm btn-default" data-btn="bold"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnItalic + '" class="md-btn btn btn-sm btn-default" data-btn="italic"></button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnList + '" class="md-btn btn btn-sm btn-default" data-btn="ul"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnOrderedList + '" class="md-btn btn btn-sm btn-default" data-btn="ol"></button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnLink + '" class="md-btn btn btn-sm btn-default" data-btn="link"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnImage + '" class="md-btn btn btn-sm btn-default" data-btn="image"></button>';
                    if (options.imageUpload === true) {
                        html += '
<input class="md-input-upload" type="file" multiple accept=".jpg,.jpeg,.png,.gif">
';
                    }
                html += '
'; // .btn-group

                if (options.fullscreen === true) {
                    html += '
';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default" data-btn="fullscreen"> ' + options.label.btnFullscreen + '</button>';
                    html += '
'; // .btn-group
                }

                if (options.preview === true) {
                    html += '
';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default btn-edit active" data-btn="edit"> ' + options.label.btnEdit + '</button>';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default btn-preview" data-btn="preview"> ' + options.label.btnPreview + '</button>';
                    html += '
'; // .btn-group
                }

            html += '
'; // .btn-toolbar
        html += '
'; // .md-toolbar

        html += '
' + $('
').text($.trim(content)).html() + '
';
        html += '

';

        return html;
    }

    $.fn.markdownEditor.defaults = {
        width: '100%',
        height: '400px',
        fontSize: '14px',
        theme: 'tomorrow',
        fullscreen: true,
        imageUpload: false,
        uploadPath: '',
        preview: false,
        onPreview: function (content, callback) {
            callback(content);
        },
        label: {
            btnHeader1: 'Header 1',
            btnHeader2: 'Header 2',
            btnHeader3: 'Header 3',
            btnBold: 'Bold',
            btnItalic: 'Italic',
            btnList: 'Unordered list',
            btnOrderedList: 'Ordered list',
            btnLink: 'Link',
            btnImage: 'Insert image',
            btnUpload: 'Upload image',
            btnEdit: 'Edit',
            btnPreview: 'Preview',
            btnFullscreen: 'Fullscreen',
            loading: 'Loading'
        }
    };

}(jQuery));
<commit_msg>#10 #11<commit_after>
(function ($) {

    "use strict";

    var methods = {
        init: function (options) {

            var defaults = $.extend(true, {}, $.fn.markdownEditor.defaults, options),
                plugin = this,
                preview = false,
                fullscreen = false;

            // Replace the content of the div with our html
            plugin.addClass('md-container').html(editorHtml(this.text(), defaults));

            // If the Bootstrap tooltip library is loaded, initialize the tooltips of the toolbar
            if (typeof $().tooltip === 'function') {
                plugin.find('[data-mdtooltip="tooltip"]').tooltip({
                    container: 'body'
                });
            }

            var mdEditor = plugin.find('.md-editor'),
                mdPreview = plugin.find('.md-preview'),
                mdLoading = plugin.find('.md-loading');

            plugin.css({
                width: defaults.width
            });

            mdEditor.css({
                width: defaults.width,
                height: defaults.height,
                fontSize: defaults.fontSize
            });

            mdPreview.css({
                width: defaults.width,
                height: defaults.height
            });

            // Initialize Ace
            var editor = ace.edit(mdEditor[0]),
                snippetManager;

            editor.setTheme('ace/theme/' + defaults.theme);
            editor.getSession().setMode('ace/mode/markdown');
            editor.getSession().setUseWrapMode(true);

            editor.setHighlightActiveLine(false);
            editor.setShowPrintMargin(false);
            editor.renderer.setShowGutter(false);

            ace.config.loadModule('ace/ext/language_tools', function () {
                snippetManager = ace.require('ace/snippets').snippetManager;
                setShortcuts(editor, snippetManager);
            });

            // Image drag and drop and upload events
            if (defaults.imageUpload) {

                plugin.find('.md-input-upload').on('change', function() {
                    var files = $(this).get(0).files;

                    if (files.length) {
                        uploadFiles(defaults.uploadPath, $(this).get(0).files, editor, snippetManager, mdLoading);
                    }
                });

                plugin.on('dragenter', function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                });

                plugin.on('dragover', function (e) {
                    e.stopPropagation();
                    e.preventDefault();
                });

                plugin.on('drop', function (e) {
                    e.preventDefault();
                    var files = e.originalEvent.dataTransfer.files;

                    uploadFiles(defaults.uploadPath, files, editor, snippetManager, mdLoading);
                });
            }

            // Window resize event
            if (defaults.fullscreen === true) {
                $(window).resize(function () {
                    if (fullscreen === true) {
                        if (preview === false) {
                            adjustFullscreenLayout(mdEditor);
                        } else {
                            adjustFullscreenLayout(mdPreview);
                        }
                    }
                });
            }

            // Toolbar events
            plugin.find('.md-btn').click(function () {
                var btnType = $(this).data('btn'),
                    selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (btnType === 'h1') {
                    insertBeforeText(editor, '#');

                } else if (btnType === 'h2') {
                    insertBeforeText(editor, '##');

                } else if (btnType === 'h3') {
                    insertBeforeText(editor, '###');

                } else if (btnType === 'ul') {
                    insertBeforeText(editor, '*');

                } else if (btnType === 'ol') {
                    insertBeforeText(editor, '1.');

                } else if (btnType === 'bold') {
                    editor.execCommand('bold');

                } else if (btnType === 'italic') {
                    editor.execCommand('italic');

                } else if (btnType === 'link') {
                    editor.execCommand('link');

                } else if (btnType === 'image') {
                    if (selectedText === '') {
                        snippetManager.insertSnippet(editor, '![${1:text}](http://$2)');
                    } else {
                        snippetManager.insertSnippet(editor, '![' + selectedText + '](http://$1)');
                    }

                } else if (btnType === 'edit') {
                    preview = false;

                    mdPreview.hide();
                    mdEditor.show();
                    plugin.find('.btn-edit').addClass('active');
                    plugin.find('.btn-preview').removeClass('active');

                    if (fullscreen === true) {
                        adjustFullscreenLayout(mdEditor);
                    }

                } else if (btnType === 'preview') {
                    preview = true;

                    mdPreview.html('
' + defaults.label.loading + '...
');

                    defaults.onPreview(editor.getSession().getValue(), function (content) {
                        mdPreview.html(content);
                    });

                    mdEditor.hide();
                    mdPreview.show();
                    plugin.find('.btn-preview').addClass('active');
                    plugin.find('.btn-edit').removeClass('active');

                    if (fullscreen === true) {
                        adjustFullscreenLayout(mdPreview);
                    }

                } else if (btnType === 'fullscreen') {

                    if (fullscreen === true) {
                        fullscreen = false;

                        $('body, html').removeClass('md-body-fullscreen');
                        plugin.removeClass('md-fullscreen');

                        mdEditor.css('height', defaults.height);
                        mdPreview.css('height', defaults.height);

                    } else {
                        fullscreen = true;

                        $('body, html').addClass('md-body-fullscreen');
                        plugin.addClass('md-fullscreen');

                        if (preview === false) {
                            adjustFullscreenLayout(mdEditor);
                        } else {
                            adjustFullscreenLayout(mdPreview);
                        }
                    }

                    editor.resize();
                }

                editor.focus();
            });

            this.editor = editor;
            return this;
        },
        content: function () {
            var editor = ace.edit(this.find('.md-editor')[0]);
            return editor.getSession().getValue();
        },
        setContent: function(str) {
          var editor = ace.edit(this.find('.md-editor')[0]);
          editor.setValue(str);
        }
    };

    $.fn.markdownEditor = function (options) {

        if (methods[options]) {
            return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));

        } else if (typeof options === 'object' || ! options) {
            return methods.init.apply(this, arguments);

        } else {
            $.error('Method ' +  options + ' does not exist on jQuery.markdownEditor');
        }
    };

    function uploadFiles (url, files, editor, snippetManager, loading) {

        loading.show();

        var data = new FormData(),
            i = 0;

        for (i = 0; i < files.length; i++) {
            data.append('file' + i, files[i]);
        }

        $.ajax({
            url: url,
            type: 'POST',
            contentType: false,
            data: data,
            processData: false,
            cache: false,
            dataType: 'json'
        }).done (function (uploadedFiles) {

            var separation = '';
            if (uploadedFiles.length > 1) {
                separation = "\n";
            }

            for (var i = 0; i < uploadedFiles.length; i++) {
                snippetManager.insertSnippet(editor, '![](' + uploadedFiles[i] + ')' + separation);
            }

        }).always(function () {
            loading.hide();
        });
    }

    function adjustFullscreenLayout (mdPanel) {
        var hWindow = $(window).height(),
            tEditor = mdPanel.offset().top,
            hEditor;

        if(hWindow > tEditor) {
            hEditor = hWindow - tEditor;
            mdPanel.css('height', hEditor + 'px');
        }
    }

    function setShortcuts (editor, snippetManager) {
        editor.commands.addCommand({
            name: 'bold',
            bindKey: {win: 'Ctrl-B',  mac: 'Command-B'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '**${1:text}**');
                } else {
                    snippetManager.insertSnippet(editor, '**' + selectedText + '**');
                }
            },
            readOnly: false
        });

        editor.commands.addCommand({
            name: 'italic',
            bindKey: {win: 'Ctrl-I',  mac: 'Command-I'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '*${1:text}*');
                } else {
                    snippetManager.insertSnippet(editor, '*' + selectedText + '*');
                }
            },
            readOnly: false
        });

        editor.commands.addCommand({
            name: 'link',
            bindKey: {win: 'Ctrl-K',  mac: 'Command-K'},
            exec: function (editor) {
                var selectedText = editor.session.getTextRange(editor.getSelectionRange());

                if (selectedText === '') {
                    snippetManager.insertSnippet(editor, '[${1:text}](http://$2)');
                } else {
                    snippetManager.insertSnippet(editor, '[' + selectedText + '](http://$1)');
                }
            },
            readOnly: false
        });
    }

    function insertBeforeText (editor, string) {

        if (editor.getCursorPosition().column === 0) {
            editor.navigateLineStart();
            editor.insert(string + ' ');
        } else {
            editor.navigateLineStart();
            editor.insert(string + ' ');
            editor.navigateLineEnd();
        }
    }

    function editorHtml (content, options) {
        var html = '';

        html += '

';
        html += '
';
            html += '
';

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader1 + '" class="md-btn btn btn-sm btn-default" data-btn="h1">H1</button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader2 + '" class="md-btn btn btn-sm btn-default" data-btn="h2">H2</button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnHeader3 + '" class="md-btn btn btn-sm btn-default" data-btn="h3">H3</button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnBold + '" class="md-btn btn btn-sm btn-default" data-btn="bold"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnItalic + '" class="md-btn btn btn-sm btn-default" data-btn="italic"></button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnList + '" class="md-btn btn btn-sm btn-default" data-btn="ul"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnOrderedList + '" class="md-btn btn btn-sm btn-default" data-btn="ol"></button>';
                html += '
'; // .btn-group

                html += '
';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnLink + '" class="md-btn btn btn-sm btn-default" data-btn="link"></button>';
                    html += '<button type="button" data-mdtooltip="tooltip" title="' + options.label.btnImage + '" class="md-btn btn btn-sm btn-default" data-btn="image"></button>';
                    if (options.imageUpload === true) {
                        html += '
<input class="md-input-upload" type="file" multiple accept=".jpg,.jpeg,.png,.gif">
';
                    }
                html += '
'; // .btn-group

                if (options.fullscreen === true) {
                    html += '
';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default" data-btn="fullscreen"> ' + options.label.btnFullscreen + '</button>';
                    html += '
'; // .btn-group
                }

                if (options.preview === true) {
                    html += '
';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default btn-edit active" data-btn="edit"> ' + options.label.btnEdit + '</button>';
                        html += '<button type="button" class="md-btn btn btn-sm btn-default btn-preview" data-btn="preview"> ' + options.label.btnPreview + '</button>';
                    html += '
'; // .btn-group
                }

            html += '
'; // .btn-toolbar
        html += '
'; // .md-toolbar

        html += '
' + $('
').text(content).html() + '
';
        html += '

';

        return html;
    }

    $.fn.markdownEditor.defaults = {
        width: '100%',
        height: '400px',
        fontSize: '14px',
        theme: 'tomorrow',
        fullscreen: true,
        imageUpload: false,
        uploadPath: '',
        preview: false,
        onPreview: function (content, callback) {
            callback(content);
        },
        label: {
            btnHeader1: 'Header 1',
            btnHeader2: 'Header 2',
            btnHeader3: 'Header 3',
            btnBold: 'Bold',
            btnItalic: 'Italic',
            btnList: 'Unordered list',
            btnOrderedList: 'Ordered list',
            btnLink: 'Link',
            btnImage: 'Insert image',
            btnUpload: 'Upload image',
            btnEdit: 'Edit',
            btnPreview: 'Preview',
            btnFullscreen: 'Fullscreen',
            loading: 'Loading'
        }
    };

}(jQuery));
<|endoftext|>


<commit_before>const HIGHEST_POSSIBLE_Z_INDEX = 2147483647;

var library = [];
var counter = 0;

function checkSupported() {
  // Check for the various File API support.
  if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
    throw ('The File APIs are not fully supported in this browser.');
  }
}

function createFilesElement() {
  var filesElement = document.createElement('input');
  filesElement.type = 'file';
  filesElement.name = 'files[]';
  filesElement.multiple = true;
  filesElement.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
  filesElement.style.position = 'relative';
  filesElement.className = 'cordova-photo-library-select';
  document.body.appendChild(filesElement);
  return filesElement;
}

function removeFilesElement(filesElement) {
  filesElement.parentNode.removeChild(filesElement);
}

function getFiles(filesElement) {
  //convert from array-like to real array
  let files = Array.from(filesElement.files); // FileList object
  return files.filter(f => f.type.match('image.*'));
}

function readFileAsDataURL(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.onload = (e) => {
      resolve({ file: file, dataURL: e.target.result });
    };
    reader.readAsDataURL(file);
  });
}

function files2Library(files) {
  return new Promise((resolve, reject) => {

    let fileURLPromises = files.map(f => readFileAsDataURL(f));

    Promise.all(fileURLPromises)
      .then(filesWithDataURL => {
        let result = filesWithDataURL.map(fileWithURL => {

          let {file} = fileWithURL;
          let {dataURL} = fileWithURL;

          let libraryItem = {
            id: `${counter}#${file.name}`,
            filename: file.name,
            nativeURL: dataURL,
            width: '',
            height: '',
            creationDate: file.lastModifiedDate, // file contains only lastModifiedDate
          };
          counter += 1;
          return libraryItem;

        });

        resolve(result);

      });

  });
}

module.exports = {
  getLibrary: function (success, error) {

    checkSupported();

    let filesElement = createFilesElement();
    filesElement.addEventListener('change', (evt) => {

      let files = getFiles(evt.target);
      library = files2Library(files);
      removeFilesElement(filesElement);
      success(library);

    }, false);

  },
  getThumbnail: function (success, error) {

  },
  getPhoto: function (success, error) {

  },
  stopCaching: function (success, error) {

  },
  echo: function (success, error) {

  },
};

require('cordova/exec/proxy').add('PhotoLibrary', module.exports);
<commit_msg>getLibrary works for browser<commit_after>const HIGHEST_POSSIBLE_Z_INDEX = 2147483647;

var library = [];
var counter = 0;

function checkSupported() {
  // Check for the various File API support.
  if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
    throw ('The File APIs are not fully supported in this browser.');
  }
}

function createFilesElement() {
  var filesElement = document.createElement('input');
  filesElement.type = 'file';
  filesElement.name = 'files[]';
  filesElement.multiple = true;
  filesElement.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
  filesElement.style.position = 'relative';
  filesElement.className = 'cordova-photo-library-select';
  document.body.appendChild(filesElement);
  return filesElement;
}

function removeFilesElement(filesElement) {
  filesElement.parentNode.removeChild(filesElement);
}

function getFiles(filesElement) {
  //convert from array-like to real array
  let files = Array.from(filesElement.files); // FileList object
  return files.filter(f => f.type.match('image.*'));
}

function readFileAsDataURL(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.onload = (e) => {
      resolve(e.target.result);
    };
    reader.readAsDataURL(file);
  });
}

function readDataUrlAsImage(dataURL) {
  return new Promise((resolve, reject) => {
    var imageObj = new Image();
    imageObj.onload = () => {
      resolve(imageObj);
    };
    imageObj.src = dataURL;
  });
}

function files2Library(files) {
  return new Promise((resolve, reject) => {

    let filesWithDataPromises = files.map(f => {
      return new Promise((resolve, reject) => {
        readFileAsDataURL(f)
          .then(dataURL => {
            return readDataUrlAsImage(dataURL).then(image => {
              return { dataURL, image };
            });
          })
          .then(dataURLwithImage => {
            let {image} = dataURLwithImage;
            resolve({
              file: f,
              dataURL: dataURLwithImage.dataURL,
              width: image.width,
              height: image.height
            });
          });
      });
    });

    Promise.all(filesWithDataPromises)
      .then(filesWithData => {
        let result = filesWithData.map(fileWithData => {

          let {file} = fileWithData;
          let {dataURL} = fileWithData;

          let libraryItem = {
            id: `${counter}#${file.name}`,
            filename: file.name,
            nativeURL: dataURL,
            width: fileWithData.width,
            height: fileWithData.height,
            creationDate: file.lastModifiedDate, // file contains only lastModifiedDate
          };
          counter += 1;
          return libraryItem;

        });

        resolve(result);

      });

  });
}

module.exports = {
  getLibrary: function (success, error) {

    checkSupported();

    let filesElement = createFilesElement();
    filesElement.addEventListener('change', (evt) => {

      let files = getFiles(evt.target);
      library = files2Library(files);
      removeFilesElement(filesElement);
      success(library);

    }, false);

  },
  getThumbnail: function (success, error) {

  },
  getPhoto: function (success, error) {

  },
  stopCaching: function (success, error) {

  },
  echo: function (success, error) {

  },
};

require('cordova/exec/proxy').add('PhotoLibrary', module.exports);
<|endoftext|>


<commit_before>"use strict";

var CityTour = CityTour || {};

CityTour.VehicleController = function(terrain, roadNetwork, initial, target) {
  var HALF_PI = Math.PI / 2.0;
  var TWO_PI = Math.PI * 2.0;

  var DRIVING_MODE = 'driving';
  var HOVERING_MODE = 'hovering';
  var BIRDSEYE_MODE = 'birdseye';

  var HORIZONTAL_MOTION_DELTA = 0.2;
  var Y_ROTATION_DELTA = 0.03;
  var BIRDSEYE_X_ROTATION_DELTA = 0.0155140377955;
  var BIRDSEYE_Y = 150;
  var HOVERING_Y = 15;

  var MINIMUM_HEIGHT_OFF_GROUND = 0.5;

  var xPosition = initial.positionX;
  var yPosition = initial.positionY;
  var zPosition = initial.positionZ;
  var xRotation = initial.rotationX;
  var yRotation = initial.rotationY;

  var targetSceneX = target.positionX;
  var targetYPosition = target.positionY;
  var targetSceneZ = target.positionZ;
  var targetXRotation = target.rotationX;
  var targetYRotation = target.rotationY;

  var terrainHeightAtTouchdown = terrain.heightAtCoordinates(CityTour.Coordinates.sceneXToMapX(targetSceneX),
                                                             CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
  var distanceToTarget = CityTour.Math.distanceBetweenPoints3D(xPosition, yPosition, zPosition, targetSceneX, terrainHeightAtTouchdown + MINIMUM_HEIGHT_OFF_GROUND, targetSceneZ);
  var framesUntilCityEdge = Math.abs(distanceToTarget / HORIZONTAL_MOTION_DELTA);

  var xPositionDelta = Math.abs(targetSceneX - xPosition) / framesUntilCityEdge;
  var zPositionDelta = Math.abs(zPosition - targetSceneZ) / framesUntilCityEdge;
  var yPositionDelta = (yPosition - terrainHeightAtTouchdown) / framesUntilCityEdge;
  var xRotationDelta = Math.abs(initial.rotationX - target.rotationX) / framesUntilCityEdge;

  var framesInCurrentVerticalMode = 0;
  var VERTICAL_MODE_DURATION_IN_FRAMES = 2000;
  var verticalMode = DRIVING_MODE;

  var pathFinder = new CityTour.PathFinder(roadNetwork);
  var navigator = new CityTour.RoadNavigator(roadNetwork, pathFinder, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));

  var determineNextTargetPoint = function() {
    var oldTargetSceneX = targetSceneX;
    var oldTargetSceneZ = targetSceneZ;

    if (verticalMode === BIRDSEYE_MODE) {
      targetYPosition = BIRDSEYE_Y;
      yPositionDelta = 2;
      targetXRotation = -(Math.PI / 3);
      navigator = new CityTour.AerialNavigator(roadNetwork, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
    }
    else if (verticalMode === DRIVING_MODE) {
      targetYPosition = Number.NEGATIVE_INFINITY;
      yPositionDelta = 0.05;
      targetXRotation = 0.0;
      navigator = new CityTour.RoadNavigator(roadNetwork, pathFinder, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
    }
    else if (verticalMode === HOVERING_MODE) {
      targetYPosition = HOVERING_Y;
      yPositionDelta = 2;
      targetXRotation = 0.0;
    }

    navigator.nextTarget();
    targetSceneX = CityTour.Coordinates.mapXToSceneX(navigator.targetMapX());
    targetSceneZ = CityTour.Coordinates.mapZToSceneZ(navigator.targetMapZ());

    determinePositionDelta(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ);
    determineRotationAngle(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ);
  };

  var determinePositionDelta = function(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ) {
    var angleBetweenStartAndTarget = Math.atan2(oldTargetSceneZ - targetSceneZ, targetSceneX - oldTargetSceneX);

    xPositionDelta = Math.abs(HORIZONTAL_MOTION_DELTA * Math.cos(angleBetweenStartAndTarget));
    zPositionDelta = Math.abs(HORIZONTAL_MOTION_DELTA * Math.sin(angleBetweenStartAndTarget));
  };

  var determineRotationAngle = function(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ) {
    var oldTargetYRotation = targetYRotation;

    var x = targetSceneX - oldTargetSceneX;
    var z = -(targetSceneZ - oldTargetSceneZ);
    var angle = Math.atan2(z, x);
    if (angle < HALF_PI) {
      angle += TWO_PI;
    }
    var rightHandedAngle = angle - HALF_PI;

    targetYRotation = rightHandedAngle;

    // Prevent turns wider than 180 degrees
    if ((oldTargetYRotation - targetYRotation) > Math.PI) {
      yRotation -= TWO_PI;
    }
    else if ((oldTargetYRotation - targetYRotation) < -Math.PI) {
      yRotation += TWO_PI;
    }
  };

  var isAtTargetPoint = function() {
    return yRotation === targetYRotation &&
           xPosition === targetSceneX &&
           zPosition === targetSceneZ;
  };

  var calculateRoadHeight = function() {
    var mapX = CityTour.Coordinates.sceneXToMapX(xPosition);
    var mapZ = CityTour.Coordinates.sceneZToMapZ(zPosition);
    var roadHeight = roadNetwork.getRoadHeight(mapX, mapZ);

    if (roadHeight === undefined) {
      roadHeight = terrain.heightAtCoordinates(mapX, mapZ) || 0.0;
    }

    return roadHeight;
  };

  determineRotationAngle(xPosition, zPosition, targetSceneX, targetSceneZ);

  var xMotionGenerator = new CityTour.ClampedLinearMotionGenerator(xPosition, targetSceneX, xPositionDelta);
  var yMotionGenerator = new CityTour.ClampedLinearMotionGenerator(yPosition, targetYPosition, yPositionDelta);
  var zMotionGenerator = new CityTour.ClampedLinearMotionGenerator(zPosition, targetSceneZ, zPositionDelta);
  var xRotationGenerator = new CityTour.ClampedLinearMotionGenerator(xRotation, targetXRotation, xRotationDelta);
  var yRotationGenerator = new CityTour.ClampedLinearMotionGenerator(yRotation, targetYRotation, Y_ROTATION_DELTA);

  var tick = function() {
    if (isAtTargetPoint()) {
      if (framesInCurrentVerticalMode >= VERTICAL_MODE_DURATION_IN_FRAMES) {
        if (verticalMode === DRIVING_MODE) {
          verticalMode = BIRDSEYE_MODE;
        }
        else if (verticalMode === HOVERING_MODE) {
          verticalMode = DRIVING_MODE;
        }
        else if (verticalMode === BIRDSEYE_MODE) {
          verticalMode = HOVERING_MODE;
        }

        framesInCurrentVerticalMode = 0;
      }

      determineNextTargetPoint();

      xRotationGenerator = new CityTour.ClampedLinearMotionGenerator(xRotation, targetXRotation, BIRDSEYE_X_ROTATION_DELTA);
      yRotationGenerator = new CityTour.ClampedLinearMotionGenerator(yRotation, targetYRotation, Y_ROTATION_DELTA);
      xMotionGenerator = new CityTour.ClampedLinearMotionGenerator(xPosition, targetSceneX, xPositionDelta);
      yMotionGenerator = new CityTour.ClampedLinearMotionGenerator(yPosition, targetYPosition, yPositionDelta);
      zMotionGenerator = new CityTour.ClampedLinearMotionGenerator(zPosition, targetSceneZ, zPositionDelta);
    }

    if (yRotation != targetYRotation) {
      yRotation = yRotationGenerator.next();
    }
    else {
      xPosition = xMotionGenerator.next();
      zPosition = zMotionGenerator.next();
    }

    yPosition = Math.max(yMotionGenerator.next(), calculateRoadHeight() + MINIMUM_HEIGHT_OFF_GROUND);
    xRotation = xRotationGenerator.next();

    framesInCurrentVerticalMode += 1;
  };

  return {
    xPosition: function() { return xPosition; },
    yPosition: function() { return yPosition; },
    zPosition: function() { return zPosition; },
    yRotation: function() { return yRotation; },
    xRotation: function() { return xRotation; },
    tick: tick,
  };
};
<commit_msg>Better variable name<commit_after>"use strict";

var CityTour = CityTour || {};

CityTour.VehicleController = function(terrain, roadNetwork, initial, target) {
  var HALF_PI = Math.PI / 2.0;
  var TWO_PI = Math.PI * 2.0;

  var DRIVING_MODE = 'driving';
  var HOVERING_MODE = 'hovering';
  var BIRDSEYE_MODE = 'birdseye';

  var HORIZONTAL_MOTION_DELTA = 0.2;
  var Y_ROTATION_DELTA = 0.03;
  var BIRDSEYE_X_ROTATION_DELTA = 0.0155140377955;
  var BIRDSEYE_Y = 150;
  var HOVERING_Y = 15;

  var MINIMUM_HEIGHT_OFF_GROUND = 0.5;

  var xPosition = initial.positionX;
  var yPosition = initial.positionY;
  var zPosition = initial.positionZ;
  var xRotation = initial.rotationX;
  var yRotation = initial.rotationY;

  var targetSceneX = target.positionX;
  var targetYPosition = target.positionY;
  var targetSceneZ = target.positionZ;
  var targetXRotation = target.rotationX;
  var targetYRotation = target.rotationY;

  var terrainHeightAtTouchdown = terrain.heightAtCoordinates(CityTour.Coordinates.sceneXToMapX(targetSceneX),
                                                             CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
  var distanceToTarget = CityTour.Math.distanceBetweenPoints3D(xPosition, yPosition, zPosition, targetSceneX, terrainHeightAtTouchdown + MINIMUM_HEIGHT_OFF_GROUND, targetSceneZ);
  var framesUntilTarget = Math.abs(distanceToTarget / HORIZONTAL_MOTION_DELTA);

  var xPositionDelta = Math.abs(targetSceneX - xPosition) / framesUntilTarget;
  var zPositionDelta = Math.abs(zPosition - targetSceneZ) / framesUntilTarget;
  var yPositionDelta = (yPosition - terrainHeightAtTouchdown) / framesUntilTarget;
  var xRotationDelta = Math.abs(initial.rotationX - target.rotationX) / framesUntilTarget;

  var framesInCurrentVerticalMode = 0;
  var VERTICAL_MODE_DURATION_IN_FRAMES = 2000;
  var verticalMode = DRIVING_MODE;

  var pathFinder = new CityTour.PathFinder(roadNetwork);
  var navigator = new CityTour.RoadNavigator(roadNetwork, pathFinder, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));

  var determineNextTargetPoint = function() {
    var oldTargetSceneX = targetSceneX;
    var oldTargetSceneZ = targetSceneZ;

    if (verticalMode === BIRDSEYE_MODE) {
      targetYPosition = BIRDSEYE_Y;
      yPositionDelta = 2;
      targetXRotation = -(Math.PI / 3);
      navigator = new CityTour.AerialNavigator(roadNetwork, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
    }
    else if (verticalMode === DRIVING_MODE) {
      targetYPosition = Number.NEGATIVE_INFINITY;
      yPositionDelta = 0.05;
      targetXRotation = 0.0;
      navigator = new CityTour.RoadNavigator(roadNetwork, pathFinder, CityTour.Coordinates.sceneXToMapX(targetSceneX), CityTour.Coordinates.sceneZToMapZ(targetSceneZ));
    }
    else if (verticalMode === HOVERING_MODE) {
      targetYPosition = HOVERING_Y;
      yPositionDelta = 2;
      targetXRotation = 0.0;
    }

    navigator.nextTarget();
    targetSceneX = CityTour.Coordinates.mapXToSceneX(navigator.targetMapX());
    targetSceneZ = CityTour.Coordinates.mapZToSceneZ(navigator.targetMapZ());

    determinePositionDelta(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ);
    determineRotationAngle(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ);
  };

  var determinePositionDelta = function(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ) {
    var angleBetweenStartAndTarget = Math.atan2(oldTargetSceneZ - targetSceneZ, targetSceneX - oldTargetSceneX);

    xPositionDelta = Math.abs(HORIZONTAL_MOTION_DELTA * Math.cos(angleBetweenStartAndTarget));
    zPositionDelta = Math.abs(HORIZONTAL_MOTION_DELTA * Math.sin(angleBetweenStartAndTarget));
  };

  var determineRotationAngle = function(oldTargetSceneX, oldTargetSceneZ, targetSceneX, targetSceneZ) {
    var oldTargetYRotation = targetYRotation;

    var x = targetSceneX - oldTargetSceneX;
    var z = -(targetSceneZ - oldTargetSceneZ);
    var angle = Math.atan2(z, x);
    if (angle < HALF_PI) {
      angle += TWO_PI;
    }
    var rightHandedAngle = angle - HALF_PI;

    targetYRotation = rightHandedAngle;

    // Prevent turns wider than 180 degrees
    if ((oldTargetYRotation - targetYRotation) > Math.PI) {
      yRotation -= TWO_PI;
    }
    else if ((oldTargetYRotation - targetYRotation) < -Math.PI) {
      yRotation += TWO_PI;
    }
  };

  var isAtTargetPoint = function() {
    return yRotation === targetYRotation &&
           xPosition === targetSceneX &&
           zPosition === targetSceneZ;
  };

  var calculateRoadHeight = function() {
    var mapX = CityTour.Coordinates.sceneXToMapX(xPosition);
    var mapZ = CityTour.Coordinates.sceneZToMapZ(zPosition);
    var roadHeight = roadNetwork.getRoadHeight(mapX, mapZ);

    if (roadHeight === undefined) {
      roadHeight = terrain.heightAtCoordinates(mapX, mapZ) || 0.0;
    }

    return roadHeight;
  };

  determineRotationAngle(xPosition, zPosition, targetSceneX, targetSceneZ);

  var xMotionGenerator = new CityTour.ClampedLinearMotionGenerator(xPosition, targetSceneX, xPositionDelta);
  var yMotionGenerator = new CityTour.ClampedLinearMotionGenerator(yPosition, targetYPosition, yPositionDelta);
  var zMotionGenerator = new CityTour.ClampedLinearMotionGenerator(zPosition, targetSceneZ, zPositionDelta);
  var xRotationGenerator = new CityTour.ClampedLinearMotionGenerator(xRotation, targetXRotation, xRotationDelta);
  var yRotationGenerator = new CityTour.ClampedLinearMotionGenerator(yRotation, targetYRotation, Y_ROTATION_DELTA);

  var tick = function() {
    if (isAtTargetPoint()) {
      if (framesInCurrentVerticalMode >= VERTICAL_MODE_DURATION_IN_FRAMES) {
        if (verticalMode === DRIVING_MODE) {
          verticalMode = BIRDSEYE_MODE;
        }
        else if (verticalMode === HOVERING_MODE) {
          verticalMode = DRIVING_MODE;
        }
        else if (verticalMode === BIRDSEYE_MODE) {
          verticalMode = HOVERING_MODE;
        }

        framesInCurrentVerticalMode = 0;
      }

      determineNextTargetPoint();

      xRotationGenerator = new CityTour.ClampedLinearMotionGenerator(xRotation, targetXRotation, BIRDSEYE_X_ROTATION_DELTA);
      yRotationGenerator = new CityTour.ClampedLinearMotionGenerator(yRotation, targetYRotation, Y_ROTATION_DELTA);
      xMotionGenerator = new CityTour.ClampedLinearMotionGenerator(xPosition, targetSceneX, xPositionDelta);
      yMotionGenerator = new CityTour.ClampedLinearMotionGenerator(yPosition, targetYPosition, yPositionDelta);
      zMotionGenerator = new CityTour.ClampedLinearMotionGenerator(zPosition, targetSceneZ, zPositionDelta);
    }

    if (yRotation != targetYRotation) {
      yRotation = yRotationGenerator.next();
    }
    else {
      xPosition = xMotionGenerator.next();
      zPosition = zMotionGenerator.next();
    }

    yPosition = Math.max(yMotionGenerator.next(), calculateRoadHeight() + MINIMUM_HEIGHT_OFF_GROUND);
    xRotation = xRotationGenerator.next();

    framesInCurrentVerticalMode += 1;
  };

  return {
    xPosition: function() { return xPosition; },
    yPosition: function() { return yPosition; },
    zPosition: function() { return zPosition; },
    yRotation: function() { return yRotation; },
    xRotation: function() { return xRotation; },
    tick: tick,
  };
};
<|endoftext|>


<commit_before>(function() {

var _ = Mavo.Performance = {
	timed: function(id, callback) {
		return function() {
			console.time(id);
			callback.apply(this, arguments);
			console.timeEnd(id);
		};
	},

	time: function callee(ref) {
		var name = Mavo.match(ref, /[^.]+$/);
		var objName = Mavo.match(ref, /^.+(?=\.)/);
		var obj = eval(objName);
		console.log(`Benchmarking ${ref}(). Run console.table(${ref}.stats) at any time to see stats.`);
		var callback = obj[name];

		obj[name] = function callee() {
			var before = performance.now();
			var ret = callback.apply(this, arguments);
			var timeTaken = performance.now() - before;
			callee.stats.timeTaken += timeTaken;
			callee.stats.calls++;
			callee.stats.timings.push(timeTaken);
			callee.stats.arguments.push(Array.from(arguments));
			return ret;
		};

		obj[name].stats = {
			timeTaken: 0,
			calls: 0,
			timings: [],
			arguments: []
		};

		callee.all = callee.all || [];
		callee.all.push({obj, objName, name});

		return obj[name];
	},

	times: function() {
		if (!_.time.all) {
			return;
		}

		var results = {};

		_.time.all.forEach(o => {
			var stats = o.obj[o.name].stats;
			results[`${o.objName}.${o.name}`] = {
				"Time (ms)": stats.timeTaken,
				"Calls": stats.calls,
				"Time / Call": stats.timeTaken / stats.calls
			};
		});

		console.table(results);
	},

	count: function(...key) {
		key = key.join(" ");
		var obj = _.counts = _.counts || {};
		obj[key] = obj[key] || 0;
		obj[key]++;
	}
};

})();

// Mavo.Performance.time("Mavo.Data.resolve");
// Mavo.Performance.time("Mavo.Data.find");
<commit_msg>[performance] Easier benchmarking of prototype functions<commit_after>(function() {

var _ = Mavo.Performance = {
	timed: function(id, callback) {
		return function() {
			console.time(id);
			callback.apply(this, arguments);
			console.timeEnd(id);
		};
	},

	time: function callee(ref) {
		var name = Mavo.match(ref, /[^.#]+$/);
		var objName = Mavo.match(ref, /^.+(?=[.#])/);

		if (ref.indexOf("#") > -1) {
			objName += ".prototype"
		}

		var obj = eval(objName);
		console.log(`Benchmarking ${ref}(). Run console.table(${objName}.${name}.stats) to see stats or Mavo.Performance.times() to see a summary of all benchmarked functions.`);
		var callback = obj[name];

		obj[name] = function callee() {
			var before = performance.now();
			var ret = callback.apply(this, arguments);
			var timeTaken = performance.now() - before;
			callee.stats.timeTaken += timeTaken;
			callee.stats.calls++;
			callee.stats.timings.push(timeTaken);
			callee.stats.arguments.push(Array.from(arguments));
			return ret;
		};

		obj[name].stats = {
			timeTaken: 0,
			calls: 0,
			timings: [],
			arguments: []
		};

		callee.all = callee.all || [];
		callee.all.push({obj, objName, name});

		return obj[name];
	},

	times: function() {
		if (!_.time.all) {
			return;
		}

		var results = {};

		_.time.all.forEach(o => {
			var stats = o.obj[o.name].stats;
			results[`${o.objName}.${o.name}`] = {
				"Time (ms)": stats.timeTaken,
				"Calls": stats.calls,
				"Time / Call": stats.timeTaken / stats.calls
			};
		});

		console.table(results);
	},

	count: function(...key) {
		key = key.join(" ");
		var obj = _.counts = _.counts || {};
		obj[key] = obj[key] || 0;
		obj[key]++;
	}
};

})();

// Mavo.Performance.time("Mavo.Data.resolve");
// Mavo.Performance.time("Mavo.Data.find");
<|endoftext|>


<commit_before>/* eslint-disable */
import assert from 'assert'
import { transform } from 'babel-standalone'

// SET TO TRUE WHEN QA IS COMPLETE:
export const QA = true;

// ---------------------------- define challenge title ----------------------------
export const challengeTitle = `<span class = 'default'>Challenge: </span>Send Action Data to the Store`

// ---------------------------- challenge text ----------------------------
export const challengeText = `Intro: By now you've learned how to dispatch actions to the Redux store, but so far these actions have not contained any information other than a type. You can also send specific data along with your actions. In fact, this is very common because actions usually originate from some user interaction and tend to carry some data with them. The Redux store often needs to know about this data.`

// ---------------------------- challenge instructions ----------------------------
export const challengeInstructions = `Instructions: There's a basic notesReducer() and an addNoteText() action creator defined in the code editor. Finish the body of the addNoteText() function so that it returns an action object. The object should include a type property with a value of ADD_NOTE, and also a text property set to the note data that's passed into the action creator. When you call the action creator, you'll pass in specific note information that you can access for the object.

Next, finish writing the switch statement in the notesReducer(). You need to add a case that handles the addNoteText() actions. This case should be triggered whenever there is an action of type ADD_NOTE and it should return the text property on the incoming action as the new state.

The action are dispatched at the bottom of the code. Once you're finished, run the code and watch the console. That's all it takes to send action-specific data to the store and use it when you update store state.`

// ---------------------------- define challenge seed code ----------------------------
export const seedCode =
`const ADD_NOTE = 'ADD_NOTE';

const notesReducer = (state = 'Initial State', action) => {
	switch(action.type) {
		// change code below this line

		// change code above this line
		default:
			return state;
	}
};

const addNoteText = (note) => {
	// change code below this line

	// change code above this line
};

const store = Redux.createStore(notesReducer);

console.log(store.getState());
store.dispatch(addNoteText('Hello!'));
console.log(store.getState());`

// ---------------------------- define challenge solution code ----------------------------
export const solutionCode =
`const ADD_NOTE = 'ADD_NOTE';

const notesReducer = (state = 'Initial State', action) => {
	switch(action.type) {
		// change code below this line
		case ADD_NOTE:
			return action.text;
		// change code above this line
		default:
			return state;
	}
};

const addNoteText = (note) => {
	// change code below this line
	return {
		type: ADD_NOTE,
		text: note
	}
	// change code above this line
};

const store = Redux.createStore(notesReducer);

console.log(store.getState());
store.dispatch(addNoteText('Hello Redux!'));
console.log(store.getState());`

// ---------------------------- define challenge tests ----------------------------

export const executeTests = (code) => {

	const error_0 = 'Your code should transpile successfully.';
	const error_1 = 'The action creator addNoteText should return an object with keys \'type\' and \'text\'.';
	const error_2 = 'Dispatching an action of type \'ADD_NOTE\' with the addNoteText action creator should update the state to the string passed to the action creator.';

	let testResults = [
		{
			test: 0,
			status: false,
			condition: error_0
		},
		{
			test: 1,
			status: false,
			condition: error_1
		},
		{
			test: 2,
			status: false,
			condition: error_2
		}
	];

	let es5, reduxCode, passed = true;
	let store, notesReducer, addNoteText, ADD_NOTE;

	// this code hijacks the user input to create an IIFE
	// which returns the store from Redux as an object
	// or whatever you need from the client code
	const prepend = `(function() {`
	const append = `;\n return { store, notesReducer, addNoteText, ADD_NOTE } })()`
	const modifiedCode = prepend.concat(code).concat(append);

	// test 0: try to transpile JSX, ES6 code to ES5 in browser
	try {
		es5 = transform(modifiedCode, { presets: [ 'es2015', 'react' ] }).code;
		testResults[0].status = true;
	} catch (err) {
		passed = false;
		testResults[0].status = false;
	}

	// save the store from redux to test here
	// now you can access the redux store methods
	try {
		reduxCode = eval(es5);

		store = reduxCode.store;
		notesReducer = reduxCode.notesReducer;
		addNoteText = reduxCode.addNoteText;
		ADD_NOTE = reduxCode.ADD_NOTE;

	} catch (err) {
		passed = false;
	}

	// test 1:
	try {

		const addNoteFn = addNoteText('__TEST__NOTE');

		assert(
			addNoteFn.type === ADD_NOTE &&
			addNoteFn.text === '__TEST__NOTE',
			error_1
		);

		testResults[1].status = true;
	} catch (err) {
		passed = false;
		testResults[1].status = false;
	}

	// test 2:
	try {
		const initialState = store.getState();
		store.dispatch(addNoteText('__TEST__NOTE'));
		const newState = store.getState();

		assert(
			initialState !== newState &&
			newState === '__TEST__NOTE',
			error_2
		);

		testResults[2].status = true;
	} catch (err) {
		passed = false;
		testResults[2].status = false;
	}

	return {
		passed,
		testResults
	}

}

// liveRender modifies console.log in user input and returns message data -----------------------
export const liveRender = (code) => {

	// this code modifies the user input to return all
	// console.log statements as a message array to be
	// displayed on the client UI
	const prepend = `
	(function() {
		let __Custom__Log = []
		const message = (msg) => __Custom__Log.push(msg);
	`
	const append = `;\n return __Custom__Log })();`
	const consoleReplaced = code.replace(/console.log/g, 'message');
	const hijackedCode = prepend.concat(consoleReplaced).concat(append);

	let evaluatedCode;
	try {
		evaluatedCode = eval(hijackedCode);
	} catch (err) {
		console.log(err);
	}

	return evaluatedCode;

}
<commit_msg>Update Redux_11.js<commit_after>/* eslint-disable */
import assert from 'assert'
import { transform } from 'babel-standalone'

// SET TO TRUE WHEN QA IS COMPLETE:
export const QA = true;

// ---------------------------- define challenge title ----------------------------
export const challengeTitle = `<span class = 'default'>Challenge: </span>Send Action Data to the Store`

// ---------------------------- challenge text ----------------------------
export const challengeText = `Intro: By now you've learned how to dispatch actions to the Redux store, but so far these actions have not contained any information other than a type. You can also send specific data along with your actions. In fact, this is very common because actions usually originate from some user interaction and tend to carry some data with them. The Redux store often needs to know about this data.`

// ---------------------------- challenge instructions ----------------------------
export const challengeInstructions = `Instructions: There's a basic notesReducer() and an addNoteText() action creator defined in the code editor. Finish the body of the addNoteText() function so that it returns an action object. The object should include a type property with a value of ADD_NOTE, and also a text property set to the note data that's passed into the action creator. When you call the action creator, you'll pass in specific note information that you can access for the object.

Next, finish writing the switch statement in the notesReducer(). You need to add a case that handles the addNoteText() actions. This case should be triggered whenever there is an action of type ADD_NOTE and it should return the text property on the incoming action as the new state.

The action is dispatched at the bottom of the code. Once you're finished, run the code and watch the console. That's all it takes to send action-specific data to the store and use it when you update store state.`

// ---------------------------- define challenge seed code ----------------------------
export const seedCode =
`const ADD_NOTE = 'ADD_NOTE';

const notesReducer = (state = 'Initial State', action) => {
	switch(action.type) {
		// change code below this line

		// change code above this line
		default:
			return state;
	}
};

const addNoteText = (note) => {
	// change code below this line

	// change code above this line
};

const store = Redux.createStore(notesReducer);

console.log(store.getState());
store.dispatch(addNoteText('Hello!'));
console.log(store.getState());`

// ---------------------------- define challenge solution code ----------------------------
export const solutionCode =
`const ADD_NOTE = 'ADD_NOTE';

const notesReducer = (state = 'Initial State', action) => {
	switch(action.type) {
		// change code below this line
		case ADD_NOTE:
			return action.text;
		// change code above this line
		default:
			return state;
	}
};

const addNoteText = (note) => {
	// change code below this line
	return {
		type: ADD_NOTE,
		text: note
	}
	// change code above this line
};

const store = Redux.createStore(notesReducer);

console.log(store.getState());
store.dispatch(addNoteText('Hello Redux!'));
console.log(store.getState());`

// ---------------------------- define challenge tests ----------------------------

export const executeTests = (code) => {

	const error_0 = 'Your code should transpile successfully.';
	const error_1 = 'The action creator addNoteText should return an object with keys \'type\' and \'text\'.';
	const error_2 = 'Dispatching an action of type \'ADD_NOTE\' with the addNoteText action creator should update the state to the string passed to the action creator.';

	let testResults = [
		{
			test: 0,
			status: false,
			condition: error_0
		},
		{
			test: 1,
			status: false,
			condition: error_1
		},
		{
			test: 2,
			status: false,
			condition: error_2
		}
	];

	let es5, reduxCode, passed = true;
	let store, notesReducer, addNoteText, ADD_NOTE;

	// this code hijacks the user input to create an IIFE
	// which returns the store from Redux as an object
	// or whatever you need from the client code
	const prepend = `(function() {`
	const append = `;\n return { store, notesReducer, addNoteText, ADD_NOTE } })()`
	const modifiedCode = prepend.concat(code).concat(append);

	// test 0: try to transpile JSX, ES6 code to ES5 in browser
	try {
		es5 = transform(modifiedCode, { presets: [ 'es2015', 'react' ] }).code;
		testResults[0].status = true;
	} catch (err) {
		passed = false;
		testResults[0].status = false;
	}

	// save the store from redux to test here
	// now you can access the redux store methods
	try {
		reduxCode = eval(es5);

		store = reduxCode.store;
		notesReducer = reduxCode.notesReducer;
		addNoteText = reduxCode.addNoteText;
		ADD_NOTE = reduxCode.ADD_NOTE;

	} catch (err) {
		passed = false;
	}

	// test 1:
	try {

		const addNoteFn = addNoteText('__TEST__NOTE');

		assert(
			addNoteFn.type === ADD_NOTE &&
			addNoteFn.text === '__TEST__NOTE',
			error_1
		);

		testResults[1].status = true;
	} catch (err) {
		passed = false;
		testResults[1].status = false;
	}

	// test 2:
	try {
		const initialState = store.getState();
		store.dispatch(addNoteText('__TEST__NOTE'));
		const newState = store.getState();

		assert(
			initialState !== newState &&
			newState === '__TEST__NOTE',
			error_2
		);

		testResults[2].status = true;
	} catch (err) {
		passed = false;
		testResults[2].status = false;
	}

	return {
		passed,
		testResults
	}

}

// liveRender modifies console.log in user input and returns message data -----------------------
export const liveRender = (code) => {

	// this code modifies the user input to return all
	// console.log statements as a message array to be
	// displayed on the client UI
	const prepend = `
	(function() {
		let __Custom__Log = []
		const message = (msg) => __Custom__Log.push(msg);
	`
	const append = `;\n return __Custom__Log })();`
	const consoleReplaced = code.replace(/console.log/g, 'message');
	const hijackedCode = prepend.concat(consoleReplaced).concat(append);

	let evaluatedCode;
	try {
		evaluatedCode = eval(hijackedCode);
	} catch (err) {
		console.log(err);
	}

	return evaluatedCode;

}
<|endoftext|>


<commit_before>var Chart = require('chart.js');
Chart = typeof(Chart) === 'function' ? Chart : window.Chart;

var helpers = Chart.helpers;

var defaultOptions = {
    enabled: false,

    // max number of points to display per dataset
    threshold: 1000,

    // if true, downsamples data automatically every update
    auto: true,
    // if true, downsamples data when the chart is initialized
    onInit: true,

    // if true, replaces the downsampled data with the original data after each update
    restoreOriginalData: true,
    // if true, downsamples original data instead of data
    preferOriginalData: false,

};

var floor = Math.floor,
    abs = Math.abs;

function downsample(data, threshold) {
    // this function is from flot-downsample (MIT), with modifications

    var dataLength = data.length;
    if (threshold >= dataLength || threshold <= 0) {
        return data; // nothing to do
    }

    var sampled = [],
        sampledIndex = 0;

    // bucket size, leave room for start and end data points
    var every = (dataLength - 2) / (threshold - 2);

    var a = 0,  // initially a is the first point in the triangle
        maxAreaPoint,
        maxArea,
        area,
        nextA;

    // always add the first point
    sampled[sampledIndex++] = data[a];

    for (var i = 0; i < threshold - 2; i++) {
        // Calculate point average for next bucket (containing c)
        var avgX = 0,
            avgY = 0,
            avgRangeStart = floor(( i + 1 ) * every) + 1,
            avgRangeEnd = floor(( i + 2 ) * every) + 1;
        avgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;

        var avgRangeLength = avgRangeEnd - avgRangeStart;

        for (; avgRangeStart < avgRangeEnd; avgRangeStart++) {
            avgX += data[avgRangeStart].x * 1; // * 1 enforces Number (value may be Date)
            avgY += data[avgRangeStart].y * 1;
        }
        avgX /= avgRangeLength;
        avgY /= avgRangeLength;

        // Get the range for this bucket
        var rangeOffs = floor((i + 0) * every) + 1,
            rangeTo = floor((i + 1) * every) + 1;

        // Point a
        var pointAX = data[a].x * 1, // enforce Number (value may be Date)
            pointAY = data[a].y * 1;

        maxArea = area = -1;

        for (; rangeOffs < rangeTo; rangeOffs++) {
            // Calculate triangle area over three buckets
            area = abs(( pointAX - avgX ) * ( data[rangeOffs].y - pointAY ) -
                    ( pointAX - data[rangeOffs].x ) * ( avgY - pointAY )
                ) * 0.5;
            if (area > maxArea) {
                maxArea = area;
                maxAreaPoint = data[rangeOffs];
                nextA = rangeOffs; // Next a is this b
            }
        }

        sampled[sampledIndex++] = maxAreaPoint; // Pick this point from the bucket
        a = nextA; // This a is the next a (chosen b)
    }

    sampled[sampledIndex] = data[dataLength - 1]; // Always add last

    return sampled;
}

function getOptions(chartInstance) {
    return chartInstance.options.downsample;
}

function downsampleChart(chartInstance) {
    var options = getOptions(chartInstance),
        threshold = options.threshold;
    if(!options.enabled) return;

    var datasets = chartInstance.data.datasets;
    for(var i = 0; i < datasets.length; i++) {
        var dataset = datasets[i];

        var dataToDownsample = null;
        if(options.preferOriginalData) {
            dataToDownsample = dataset.originalData;
        }
        dataToDownsample = dataToDownsample || dataset.data;

        dataset.originalData = dataToDownsample;
        dataset.data = downsample(dataToDownsample, threshold);
    }
}

var downsamplePlugin = {
    beforeInit: function (chartInstance) {
        var options = chartInstance.options.downsample = helpers.extend({}, defaultOptions, chartInstance.options.downsample || {});

        if(options.onInit) {
            downsampleChart(chartInstance);
        }

        // allow manual downsample-triggering with chartInstance.downsample();
        chartInstance.downsample = function(threshold) {
            if(typeof(threshold) !== 'undefined') {
                chartInstance.options.downsample.threshold = threshold;
            }

            downsampleChart(chartInstance);
        }
    },

    beforeDatasetsUpdate: function(chartInstance) {
        if(chartInstance.options.downsample.auto) {
            downsampleChart(chartInstance);
        }
    },

    afterDatasetsUpdate: function(chartInstance) {
        var options = getOptions(chartInstance);
        if(!options.enabled || !options.restoreOriginalData) return;

        var datasets = chartInstance.data.datasets;
        for(var i = 0; i < datasets.length; i++) {
            var dataset = datasets[i];

            dataset.data = dataset.originalData || dataset.data;
            dataset.originalData = null;
        }
    }
};

module.exports = downsamplePlugin;
Chart.pluginService.register(downsamplePlugin);<commit_msg>targetDatasets options added and used for filtering datasets to be downsampled<commit_after>var Chart = require('chart.js');
Chart = typeof(Chart) === 'function' ? Chart : window.Chart;

var helpers = Chart.helpers;

var defaultOptions = {
    enabled: false,

    // max number of points to display per dataset
    threshold: 1000,

    // if true, downsamples data automatically every update
    auto: true,
    // if true, downsamples data when the chart is initialized
    onInit: true,

    // if true, replaces the downsampled data with the original data after each update
    restoreOriginalData: true,
    // if true, downsamples original data instead of data
    preferOriginalData: false,

    //if not undefined and not empty, indicates the ids of the datasets to downsample
    targetDatasets : []

};

var floor = Math.floor,
    abs = Math.abs;

function downsample(data, threshold) {
    // this function is from flot-downsample (MIT), with modifications

    var dataLength = data.length;
    if (threshold >= dataLength || threshold <= 0) {
        return data; // nothing to do
    }

    var sampled = [],
        sampledIndex = 0;

    // bucket size, leave room for start and end data points
    var every = (dataLength - 2) / (threshold - 2);

    var a = 0,  // initially a is the first point in the triangle
        maxAreaPoint,
        maxArea,
        area,
        nextA;

    // always add the first point
    sampled[sampledIndex++] = data[a];

    for (var i = 0; i < threshold - 2; i++) {
        // Calculate point average for next bucket (containing c)
        var avgX = 0,
            avgY = 0,
            avgRangeStart = floor(( i + 1 ) * every) + 1,
            avgRangeEnd = floor(( i + 2 ) * every) + 1;
        avgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;

        var avgRangeLength = avgRangeEnd - avgRangeStart;

        for (; avgRangeStart < avgRangeEnd; avgRangeStart++) {
            avgX += data[avgRangeStart].x * 1; // * 1 enforces Number (value may be Date)
            avgY += data[avgRangeStart].y * 1;
        }
        avgX /= avgRangeLength;
        avgY /= avgRangeLength;

        // Get the range for this bucket
        var rangeOffs = floor((i + 0) * every) + 1,
            rangeTo = floor((i + 1) * every) + 1;

        // Point a
        var pointAX = data[a].x * 1, // enforce Number (value may be Date)
            pointAY = data[a].y * 1;

        maxArea = area = -1;

        for (; rangeOffs < rangeTo; rangeOffs++) {
            // Calculate triangle area over three buckets
            area = abs(( pointAX - avgX ) * ( data[rangeOffs].y - pointAY ) -
                    ( pointAX - data[rangeOffs].x ) * ( avgY - pointAY )
                ) * 0.5;
            if (area > maxArea) {
                maxArea = area;
                maxAreaPoint = data[rangeOffs];
                nextA = rangeOffs; // Next a is this b
            }
        }

        sampled[sampledIndex++] = maxAreaPoint; // Pick this point from the bucket
        a = nextA; // This a is the next a (chosen b)
    }

    sampled[sampledIndex] = data[dataLength - 1]; // Always add last

    return sampled;
}

function getOptions(chartInstance) {
    return chartInstance.options.downsample;
}

function getFilteredDatasets(chartInstance){
    var options = getOptions(chartInstance)
    var datasets = options.targetDatasets.length == 0 ? chartInstance.data.datasets :
        chartInstance.data.datasets.filter(d => options.targetDatasets.find(targetId => targetId == d.id));
    return datasets;
}

function downsampleChart(chartInstance) {
    var options = getOptions(chartInstance),
        threshold = options.threshold;
    if(!options.enabled) return;

    var datasets = getFilteredDatasets(chartInstance);
    for(var i = 0; i < datasets.length; i++) {
        var dataset = datasets[i];

        var dataToDownsample = null;
        if(options.preferOriginalData) {
            dataToDownsample = dataset.originalData;
        }
        dataToDownsample = dataToDownsample || dataset.data;

        dataset.originalData = dataToDownsample;
        dataset.data = downsample(dataToDownsample, threshold);
    }
}

var downsamplePlugin = {
    beforeInit: function (chartInstance) {
        var options = chartInstance.options.downsample = helpers.extend({}, defaultOptions, chartInstance.options.downsample || {});

        if(options.onInit) {
            downsampleChart(chartInstance);
        }

        // allow manual downsample-triggering with chartInstance.downsample();
        chartInstance.downsample = function(threshold) {
            if(typeof(threshold) !== 'undefined') {
                chartInstance.options.downsample.threshold = threshold;
            }

            downsampleChart(chartInstance);
        }
    },

    beforeDatasetsUpdate: function(chartInstance) {
        if(chartInstance.options.downsample.auto) {
            downsampleChart(chartInstance);
        }
    },

    afterDatasetsUpdate: function(chartInstance) {
        var options = getOptions(chartInstance);
        if(!options.enabled || !options.restoreOriginalData) return;

    var datasets = getFilteredDatasets(chartInstance);
        for(var i = 0; i < datasets.length; i++) {
            var dataset = datasets[i];

            dataset.data = dataset.originalData || dataset.data;
            dataset.originalData = null;
        }
    }
};

module.exports = downsamplePlugin;
Chart.pluginService.register(downsamplePlugin);<|endoftext|>


<commit_before>dominoes.plugin( "css" , function( options ) {

	return function( callback ) {

		var link = document.createElement("link");
			charset = options.charset;

		link.rel = "Stylesheet";
		link.type = "text/css";
		link.href = options.url;

		if ( charset ) {
			link.charset = charset;
		}

		// Watch the link
		cssWatch( link , callback , options.title );

		// Add it to the doc
		head.appendChild( link );

		// We handle the callback
		return true;
	};

} );

var	// Next css id
	cssPollingId = ( new Date() ).getTime(),

	// Number of css being polled
	cssPollingNb = 0,

	// Polled css
	cssObjects = {},

	// Main poller function
	cssGlobalPoller = function() {

		var object,
			callback,
			link,
			stylesheet,
			stylesheets = document.styleSheets,
			title,
			i,
			length,
			readyState,
			urlParts;

		if ( stylesheets ) { // Safeguard for IE

			for ( i = 0, length = stylesheets.length; i < length; i++ ) {

				if ( ( stylesheet = stylesheets[i] ) // Safeguard for IE
					&& ( title = stylesheet.title )
					&& ( object = cssObjects[title] ) ) {

					callback = object.callback;
					link = object.link;

					// IE: links have a readyState property, use it
					readyState = link.readyState;
					if ( readyState !== undefined) {

						if ( readyState=="loaded" || readyState=="complete" ) {
							callback( stylesheet );
						}

					} else {

						try {

							stylesheet.cssRules;

							// Webkit: stylesheet object is not created before the link has been loaded
							//  * same-domain: cssRules is returned (no exception thrown)
							//  * cross-domain: cssRules is empty (no exception thrown)

							// Gecko, Opera: an exception is thrown if the stylesheet hasn't been loaded
							//  * same-domain: if loaded, cssRules is returned, else exception
							//  * cross-domain: always throws an exception

							callback( stylesheet );

						} catch(e) {

							// Gecko: the engine throws NS_ERROR_DOM_* exceptions

							if ( /NS_ERR/.test(e) ) {

								// Once loaded, a more specific NS_ERROR_DOM_SECURITY_ERR is thrown

								if ( /SECURITY/.test(e) ) {

									callback( stylesheet );

								}

							} else {

								// Opera

								// Determine if the request is cross domain

								if ( object.x === undefined ) {

									// More jQuery pillage

									urlParts = /^(\w+:)?\/\/([^\/?#]+)/.exec( link.href );
									object.x = !! (
											parts // found parts?
										&&
											(
													parts[1] // found a protocol & host?
												&&
														parts[1] != location.protocol
													||
														parts[2] != location.host
											)
									);
								}

								// If cross domain

								if ( object.x ) {
									try {

										stylesheet.deleteRule(0);

										// If the link hasn't been loaded yet, deleteRule is ignored by Opera
										// but once loaded, it throws a security exception

									} catch(_) {

										callback( stylesheet );

									}
								}
							}
						}
					}
				}
			}
		}
	},

	// Watch stylesheet loading (based on a timer)
	cssTimerId,

	cssWatch = function ( link , callback , finalTitle ) {

		var title = link.title = "-dominoescss-" + cssPollingId++;

		cssObjects[title] = {

			link: link,

			callback: function( stylesheet ) {
				delete cssObjects[title];
				if ( ! --cssPollingNb ) {
					clearInterval( cssTimerId );
				}
				if ( finalTitle ) {
					link.title = stylesheet.title = finalTitle;
				}
				callback();
			}
		};

		if ( ! cssPollingNb++ ) {
			cssTimerId = setInterval( cssGlobalPoller , 13 );
		}

	};

<commit_msg>Using global TRUE alias and revamped some comments<commit_after>dominoes.plugin( "css" , function( options ) {

	return function( callback ) {

		var link = document.createElement("link");
			charset = options.charset;

		link.rel = "Stylesheet";
		link.type = "text/css";
		link.href = options.url;

		if ( charset ) {
			link.charset = charset;
		}

		// Watch the link
		cssWatch( link , callback , options.title );

		// Add it to the doc
		head.appendChild( link );

		// We handle the callback
		return TRUE;
	};

} );

var	// Next css id
	cssPollingId = ( new Date() ).getTime(),

	// Number of css being polled
	cssPollingNb = 0,

	// Polled css
	cssObjects = {},

	// Main poller function
	cssGlobalPoller = function() {

		var object,
			callback,
			link,
			stylesheet,
			stylesheets = document.styleSheets,
			title,
			i,
			length,
			readyState,
			urlParts;

		if ( stylesheets ) { // Safeguard for IE

			for ( i = 0, length = stylesheets.length; i < length; i++ ) {

				if ( ( stylesheet = stylesheets[i] ) // Safeguard for IE
					&& ( title = stylesheet.title )
					&& ( object = cssObjects[title] ) ) {

					callback = object.callback;
					link = object.link;

					// IE: links have a readyState property, use it
					readyState = link.readyState;
					if ( readyState !== undefined) {

						if ( readyState=="loaded" || readyState=="complete" ) {
							callback( stylesheet );
						}

					} else {

						try {

							stylesheet.cssRules;

							// Webkit: stylesheet object is not created before the link has been loaded
							//  * same-domain: cssRules is returned (no exception thrown)
							//  * cross-domain: cssRules is empty (no exception thrown)

							// Gecko, Opera: an exception is thrown if the stylesheet hasn't been loaded
							//  * same-domain: if loaded, cssRules is returned, else exception
							//  * cross-domain: always throws an exception

							callback( stylesheet );

						} catch(e) {

							// Gecko: the engine throws NS_ERROR_DOM_* exceptions

							if ( /NS_ERR/.test(e) ) {

								// Once loaded, a more specific NS_ERROR_DOM_SECURITY_ERR is thrown
								// for cross-domain links

								if ( /SECURITY/.test(e) ) {

									callback( stylesheet );

								}

							} else {

								// Opera

								// Determine if the request is cross domain

								if ( object.x === undefined ) {

									// More jQuery pillage

									urlParts = /^(\w+:)?\/\/([^\/?#]+)/.exec( link.href );
									object.x = !! (
											parts // found parts?
										&&
											(
													parts[1] // found a protocol & host?
												&&
														parts[1] != location.protocol
													||
														parts[2] != location.host
											)
									);
								}

								// If cross domain

								if ( object.x ) {
									try {

										stylesheet.deleteRule(0);

										// If the link hasn't been loaded yet, deleteRule is ignored by Opera
										// but once loaded, it throws a security exception

									} catch(_) {

										callback( stylesheet );

									}
								}
							}
						}
					}
				}
			}
		}
	},

	// Watch stylesheet loading (based on a timer)
	cssTimerId,

	cssWatch = function ( link , callback , finalTitle ) {

		var title = link.title = "-dominoescss-" + cssPollingId++;

		cssObjects[title] = {

			link: link,

			callback: function( stylesheet ) {
				delete cssObjects[title];
				if ( ! --cssPollingNb ) {
					clearInterval( cssTimerId );
				}
				if ( finalTitle ) {
					link.title = stylesheet.title = finalTitle;
				}
				callback();
			}
		};

		if ( ! cssPollingNb++ ) {
			cssTimerId = setInterval( cssGlobalPoller , 13 );
		}

	};

<|endoftext|>