<commit_before>/* This module defines and exposes JS pseudo-classes to support a complex view
 * model for editing illustrations.
 */
var TreeIllustrator = function(window, document, $, ko) {

    // Explicitly check for dependencies by passing them as args to the module
    if (typeof($) !== 'function') {
        alert("TreeIllustrator module cancelled, needs jQuery (as '$')");
        return null;
    }
    if (!ko || typeof(ko) !== 'object') {
        alert("TreeIllustrator module cancelled, needs KnockoutJS (as 'ko')");
        return null;
    }

    /* Here we can share information among all classes and instances */
    //var shared = {};

    /* Return the values for a new illustration (outlines our JSON representation) */
    var getNewIllustrationObject = function(options) {
        if (!options) options = {};
        var obj = {
            'metadata': {
                'name': "Untitled",
                'description': "",
                'authors': [ ],   // assign immediately to this user?
                'tags': [ ],
                'dois': [ ]
            },
            'template': {
                // maybe the defaults here are "anything goes" (all options enabled)?
                // TODO: Explicitly list all options somewhere else? Filter template styles if they fall out of conformance?
                'name': "Default template",
                'description': "You can replace this with a shared template in the Style Switcher above", // captured when assigned
                'source': {'type': "builtin", 'value': "DEFAULT"},  // URL, builtin
                'version': {'type': "version number", 'value': "0.1"},  // git SHA, mod date, version number
                'constraints': {
                    // list constrained labels and values, if any (items not listed are unconstrained)
                    'units': {
                        "Inches": "inches",
                        "Centimeters": "centimeters"
                    },
                    'printSizes': {
                    }
                },
                'placeholderElements': [
                    // dummy tree(s) or data to show, eg, "two mirrored trees"
                    {
                        'id': "tree1",
                        'type': "tree",
                        'layout': "blah",
                        'source': { 'type': "URL", 'value': "blah" },
                        'styleOverrides': {
                            // 'edgeThickness': {'value': '4pt', 'edges': 'ALL'} // or ['edge23', 'edge948']
                        }
                    }
                ]
            },
            'style': {
                // choices and overrides from the template defaults above
                'units': "inches",  // OR "centimeters"
                'printWidth': 3.5,  // in physical units
                'printHeight': 5.0,   // in physical units
                'backgroundColor': "#fdd",
                'border': "none",
                'fontFamily': "Times New Roman, Times, serif",
                'fontSize': "12pt",  // use same physical units as above?
                'fontWeight': "normal"
                // TODO: add default line color, thickness, node shape/size, etc.
            },
            'elements': {
            }
        };
        /* TODO: Apply optional modifications?
        if (options.BLAH) {
            obj.metadata.FOO = 'BAR';
        }
        */
        return obj;
    };

    /* Our principle view model [1] is a single illustration. This uses basic
     * Knockout observables as members, but adds custom behavior. We'll use a
     * family of pseudo-classes to define the main illustration and selected parts.
     *
     * [1] http://knockoutjs.com/documentation/observables.html
     */
    var Illustration = function(data) {
        if ( !(this instanceof Illustration) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new Illustration(data);
        }

        if (!data || typeof(data) !== 'object') {
            // load the "empty" illustration object above
            data = getNewIllustrationObject();
        }

        // safely refer to this instance
        var self = this;

        /* define PRIVATE members (variables and methods)functions and with 'var' */
        var secretSauce = function() {
            alert("TOP SECRET!");
        }

        /* define PUBLIC variables (and privileged methods) with 'self' */
        //self.myVariable = ko.observable();
        //self.myComputed = ko.computed(function () { return "hello" + self.myVariable() });

/*
        self.metadata = {
            name: ko.observable(data.metadata.name),
            description: ko.observable(data.metadata.description)
        };
        self.styles = ko.observable();
        self.sceneGraph = ko.observable();
        self.vegaSpec = ko.observable();

        // two initial test properties for tree placement
        self.treeX = ko.observable( 'treeX' in data ? data.treeX : physicalWidth / 2.0 );
        self.treeY = ko.observable( 'treeY' in data ? data.treeY : physicalHeight / 2.0 );
*/

        /* Instead of explicitly defining all possible members, let's
         * trust the ko.mapping plugin to handle loading and saving
         * illustration data from JS(ON), with mapping options to handle
         * any exceptional stuff.
         */
        var mappingOptions = {
            /* Use to handle special cases:
             *  'ignore' to keep some clutter out of the saved model
             *  'include' to force view-model properties to be saved
             *  'copy' to keep simple values simple (vs. observable)
             *  'observe' ONLY if it's easier to whitelist the observables
             *  'create' map some elements to object classes
             *  'update'? convert Dates to ISO date-strings, ints to floats
             *  'key': pin elements to specified keys
             * See http://knockoutjs.com/documentation/plugins-mapping.html
             */
            'ignore': [ 'constructor' ],
            'include': [ ],
            'copy': [ ],
            // 'observe': [ ], // WARNING: using this flips default mapping!
            'elements': {
                'create': function(options) {
                    // create these as object instances
                    var data = options.data;
                    var dataParent = options.parent;
                    switch(data.type) {
                        case 'tree':
                            //TODO: return new Tree(data);
                            break;
                        case 'supporting data':
                            //TODO: return new SupportingData(data);
                            break;
                    }
                    // keep it simple by default
                    return ko.observable(data);
                },
                'key': function(data) {
                    // use 'id' attribute to pin these
                    return ko.utils.unwrapObservable(data.id);
                }
            }
        };
        /* Map incoming data from a JS object. NOTE that we can also do
         * this piecemeal to (for example) apply new styles to an illustration.
         *
         * TODO: Add some valication or other sanity checks after mapping, to
         * make sure we're not getting nonsense from the saved model?
         */
        ko.mapping.fromJS(data, mappingOptions, self);

        // Add validation for fields that need it
        self.metadata.name.extend({required: true});

        self.exportModelAsObject = function() {
            var obj = ko.mapping.toJS(self);
            // TODO: any cleanup here?
            return obj;
        };

        self.exportModelAsJSON = function() {
            var json = ko.mapping.toJSON(self);
            // TODO: any cleanup here?
            return json;
        };

    }
    /* define PUBLIC methods (that don't need private data) in its prototype */
    Illustration.prototype = {
        constructor: Illustration,
        greet: function () {
            var self = this;
            alert(self.name() + ' says hi!');
        }
    };

    /* We need to be able to define custom styles for many different elements of
     * the scene graph, e.g., a tree, node, or caption.
     */
    var SceneGraph = function(data) {
        if ( !(this instanceof SceneGraph) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new SceneGraph(data);
        }
        // safely refer to this instance
        var self = this;

        // TODO: Based on the element type, offer appropriate styles and constraints
        // TODO: Include options to map selected data to visual style
        return self;
    }

    /* We need to be able to define custom styles for many different elements of
     * the scene graph, e.g., a tree, node, or caption.
     */
    var StyleOverrides = function(data) {
        if ( !(this instanceof StyleOverrides) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new StyleOverrides(data);
        }
        // safely refer to this instance
        var self = this;

        // TODO: Based on the element type, offer appropriate styles and constraints
        // TODO: Include options to map selected data to visual style
        return self;
    }

    /* expose class constructors (and static methods) for instantiation */
    return {
        //Tree: Tree,
        SceneGraph: SceneGraph,
        StyleOverrides: StyleOverrides,
        Illustration: Illustration
    };
}(window, document, $, ko);
<commit_msg>Add enumerations, control over print size & units<commit_after>/* This module defines and exposes JS pseudo-classes to support a complex view
 * model for editing illustrations.
 */
var TreeIllustrator = function(window, document, $, ko) {

    // Explicitly check for dependencies by passing them as args to the module
    if (typeof($) !== 'function') {
        alert("TreeIllustrator module cancelled, needs jQuery (as '$')");
        return null;
    }
    if (!ko || typeof(ko) !== 'object') {
        alert("TreeIllustrator module cancelled, needs KnockoutJS (as 'ko')");
        return null;
    }

    /* Here we can share information among all classes and instances */
    //var shared = {};

    // define some simple enumerations (for legibility, and to avoid typos)
    var units = {
        INCHES: 'inches',
        CENTIMETERS: 'centimeters'
    };

    /* Return the values for a new illustration (outlines our JSON representation) */
    var getNewIllustrationObject = function(options) {
        if (!options) options = {};
        var obj = {
            'metadata': {
                'name': "Untitled",
                'description': "",
                'authors': [ ],   // assign immediately to this user?
                'tags': [ ],
                'dois': [ ]
            },
            'template': {
                // maybe the defaults here are "anything goes" (all options enabled)?
                // TODO: Explicitly list all options somewhere else? Filter template styles if they fall out of conformance?
                'name': "Default template",
                'description': "You can replace this with a shared template in the Style Switcher above", // captured when assigned
                'source': {'type': "builtin", 'value': "DEFAULT"},  // URL, builtin
                'version': {'type': "version number", 'value': "0.1"},  // git SHA, mod date, version number
                'constraints': {
                    // list constrained labels and values, if any (items not listed are unconstrained)
                    'printSizes': [
                        {
                            'name': "Letter size (portrait)",
                            'width': 8.5,
                            'height': 11,
                            'units': units.INCHES
                        },
                        {
                            'name': "Letter size (landscape)",
                            'width': 11,
                            'height': 8.5,
                            'units': units.INCHES
                        },
                        {
                            'name': "Quarter-page (portrait)",
                            'width': 4.25,
                            'height': 5.5,
                            'units': units.INCHES
                        },
                        {
                            'name': "Quarter-page (landscape)",
                            'width': 5.5,
                            'height': 4.25,
                            'units': units.INCHES
                        },
                        {
                            'name': "Custom size"
                        }
                    ]
                },
                'placeholderElements': [
                    // dummy tree(s) or data to show, eg, "two mirrored trees"
                    {
                        'id': "tree1",
                        'type': "tree",
                        'layout': "blah",
                        'source': { 'type': "URL", 'value': "blah" },
                        'styleOverrides': {
                            // 'edgeThickness': {'value': '4pt', 'edges': 'ALL'} // or ['edge23', 'edge948']
                        }
                    }
                ]
            },
            'style': {
                // choices and overrides from the template defaults above
                'printSize': {
                    'units': units.INCHES,  // OR units.CENTIMETERS
                    'width': 3.5,  // in physical units
                    'height': 5.0,   // in physical units
                },
                'backgroundColor': "#fdd",
                'border': "none",
                'fontFamily': "Times New Roman, Times, serif",
                'fontSize': "12pt",  // use same physical units as above?
                'fontWeight': "normal"
                // TODO: add default line color, thickness, node shape/size, etc.
            },
            'elements': {
            }
        };
        /* TODO: Apply optional modifications?
        if (options.BLAH) {
            obj.metadata.FOO = 'BAR';
        }
        */
        return obj;
    };

    /* Our principle view model [1] is a single illustration. This uses basic
     * Knockout observables as members, but adds custom behavior. We'll use a
     * family of pseudo-classes to define the main illustration and selected parts.
     *
     * [1] http://knockoutjs.com/documentation/observables.html
     */
    var Illustration = function(data) {
        if ( !(this instanceof Illustration) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new Illustration(data);
        }

        if (!data || typeof(data) !== 'object') {
            // load the "empty" illustration object above
            data = getNewIllustrationObject();
        }

        // safely refer to this instance
        var self = this;

        /* define PRIVATE members (variables and methods)functions and with 'var' */
        var secretSauce = function() {
            alert("TOP SECRET!");
        }

        /* define PUBLIC variables (and privileged methods) with 'self' */

        // REMINDER: computed observables should use 'deferEvaluation' in
        // case their dependencies will appear during ko.mapping
        self.templateSourceHTML = ko.computed(function () {
            switch(self.template.source.type()) {
                case 'URL':
                    var itsURL = self.template.source.value();
                    return ''+ itsURL +'';
                case 'builtin':
                    return "Built-in";
            }
            return "Undefined";
        }, self, {deferEvaluation:true});

        self.useChosenPrintSize = function() {
            var sizeName = $('#template-docsize-chooser').val();
            var selectedSize = getPrintSizeByName( sizeName );
            if (!selectedSize) {
                console.warn('useChosenPrintSize(): no matching size found!');
                return;
            }
            if (selectedSize.units) {
                // Custom size should retain current settings
                self.style.printSize.width( selectedSize.width() );
                self.style.printSize.height( selectedSize.height() );
                self.style.printSize.units( selectedSize.units() );
            }
        };
        self.updatePrintSizeChooser = function() {
            // (de)select matching size after manual adjustments
            var matchingSize = $.grep(
                self.template.constraints.printSizes(),
                function(o) {
                    if (!('units' in o)) return false; // 'Custom size' never matches
                    // NOTE use of != instead of !== below, because "11" == 11
                    if (o.units() != self.style.printSize.units()) return false;
                    if (o.width() != self.style.printSize.width()) return false;
                    if (o.height() != self.style.printSize.height()) return false;
                    return true;
                }
            )[0];
            var matchingSizeName = 'Custom size';
            if (matchingSize) {
                matchingSizeName = matchingSize.name();
            }
            $('#template-docsize-chooser').val(matchingSizeName);
        };

        var getPrintSizeByName = function( name ) {
            var matchingSize = $.grep(
                self.template.constraints.printSizes(), function(o) {
                    return o.name() === name;
                }
            )[0];
            if (typeof matchingSize === 'undefined') {
                console.warn('getPrintSizeByname(): no such size as "'+ name +'"!');
            }
            return matchingSize;
        }
/*
        self.metadata = {
            name: ko.observable(data.metadata.name),
            description: ko.observable(data.metadata.description)
        };
        self.styles = ko.observable();
        self.sceneGraph = ko.observable();
        self.vegaSpec = ko.observable();

        // two initial test properties for tree placement
        self.treeX = ko.observable( 'treeX' in data ? data.treeX : physicalWidth / 2.0 );
        self.treeY = ko.observable( 'treeY' in data ? data.treeY : physicalHeight / 2.0 );
*/

        /* Instead of explicitly defining all possible members, let's
         * trust the ko.mapping plugin to handle loading and saving
         * illustration data from JS(ON), with mapping options to handle
         * any exceptional stuff.
         */
        var mappingOptions = {
            /* Use to handle special cases:
             *  'ignore' to keep some clutter out of the saved model
             *  'include' to force view-model properties to be saved
             *  'copy' to keep simple values simple (vs. observable)
             *  'observe' ONLY if it's easier to whitelist the observables
             *  'create' map some elements to object classes
             *  'update'? convert Dates to ISO date-strings, ints to floats
             *  'key': pin elements to specified keys
             * See http://knockoutjs.com/documentation/plugins-mapping.html
             */
            'ignore': [ 'constructor' ],
            'include': [ ],
            'copy': [ ],
            // 'observe': [ ], // WARNING: using this flips default mapping!
            'elements': {
                'create': function(options) {
                    // create these as object instances
                    var data = options.data;
                    var dataParent = options.parent;
                    switch(data.type) {
                        case 'tree':
                            //TODO: return new Tree(data);
                            break;
                        case 'supporting data':
                            //TODO: return new SupportingData(data);
                            break;
                    }
                    // keep it simple by default
                    return ko.observable(data);
                },
                'key': function(data) {
                    // use 'id' attribute to pin these
                    return ko.utils.unwrapObservable(data.id);
                }
            }
        };
        /* Map incoming data from a JS object. NOTE that we can also do
         * this piecemeal to (for example) apply new styles to an illustration.
         *
         * TODO: Add some valication or other sanity checks after mapping, to
         * make sure we're not getting nonsense from the saved model?
         */
        ko.mapping.fromJS(data, mappingOptions, self);

        // Add validation for fields that need it
        self.metadata.name.extend({required: true});

        self.exportModelAsObject = function() {
            var obj = ko.mapping.toJS(self);
            // TODO: any cleanup here?
            return obj;
        };

        self.exportModelAsJSON = function() {
            var json = ko.mapping.toJSON(self);
            // TODO: any cleanup here?
            return json;
        };

    }
    /* define PUBLIC methods (that don't need private data) in its prototype */
    Illustration.prototype = {
        constructor: Illustration,
        greet: function () {
            var self = this;
            alert(self.name() + ' says hi!');
        }
    };

    /* We need to be able to define custom styles for many different elements of
     * the scene graph, e.g., a tree, node, or caption.
     */
    var SceneGraph = function(data) {
        if ( !(this instanceof SceneGraph) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new SceneGraph(data);
        }
        // safely refer to this instance
        var self = this;

        // TODO: Based on the element type, offer appropriate styles and constraints
        // TODO: Include options to map selected data to visual style
        return self;
    }

    /* We need to be able to define custom styles for many different elements of
     * the scene graph, e.g., a tree, node, or caption.
     */
    var StyleOverrides = function(data) {
        if ( !(this instanceof StyleOverrides) ) {
            console.warn("MISSING 'new' keyword, patching this now");
            return new StyleOverrides(data);
        }
        // safely refer to this instance
        var self = this;

        // TODO: Based on the element type, offer appropriate styles and constraints
        // TODO: Include options to map selected data to visual style
        return self;
    }

    /* expose class constructors (and static methods) for instantiation */
    return {
        //Tree: Tree,
        SceneGraph: SceneGraph,
        StyleOverrides: StyleOverrides,
        Illustration: Illustration
    };
}(window, document, $, ko);
<|endoftext|>


<commit_before>/*
    genericadmin - Weston Nielson (wnielson@gmail.com)

    updated by Jan Schrewe (jschrewe@googlemail.com)

    updated by Troy Melhase (troy.melhase@gmail.com)

	updated by Jonathan Ellenberger (jon@respondcreate.com)

 */
 (function($) {
    var GenericAdmin = {
        url_array: null,
        obj_url: "../obj/",
        admin_media_url: window.__admin_media_prefix__,
        generics_list_url: '../get-generic-rel-list/',
        loadUrlArray: function() {
            var that = this;
            $.ajax({
                url: this.generics_list_url,
                dataType: 'json',
                success: function(data) {
                    that.url_array = data;
                },
                async: false
            });
        },
        prepareSelect: function(elem) {
            var that = this;
            var opt_keys = [];
            var opt_dict = {};
            var contentTypeSelect;
            var outstring = '';

            // should return 3 items: ["id_ingredientlist_set", "2",
            // "content_type"]
            // FIX:  a better way to specify this for generic inlines
            var context = $(elem).parents('fieldset');
            contentTypeSelect = $("[id$='content_type']", context).first();
            // contentTypeSelect = $('#id_content_type').first();
            var vars = $(this.object_input).attr("id").split('-');
            if (vars.length !== 1) {
                for (var x = 0; x < (vars.length-1); x++){
                    outstring+=vars[x];
                    if (x < (vars.length-2)){
                        outstring+='-';
                    }
                }
                contentTypeSelect = $('#' + outstring + '-content_type').first();
            }

            // polish the look of the select
            $(contentTypeSelect).find('option').each(function() {
                var key;

                if (this.value) {
                    if (that.url_array[this.value]) {
                        key = that.url_array[this.value][0].split('/')[0];
                        // create an array with unique elements
                        if ($.inArray(key, opt_keys) < 0) {
                            opt_keys.push(key);
                            // if it's the first time in array
                            // it's the first time in dict
                            opt_dict[key] = [$(this).clone()];
                        } else {
                            opt_dict[key].push($(this).clone());
                        }
                    }
                    $(this).remove();
                }
            });

            opt_keys = opt_keys.sort();

            var opt_group_css = 'style="font-style:normal; font-weight:bold; color:#999; padding-left: 2px;"';
            $.each(opt_keys, function(index, key) {
                var opt_group = $('<optgroup label="' + key + '" ' + opt_group_css + '></optgroup>');
                $.each(opt_dict[key], function(index, value) {
                    opt_group.append(value).css({
                        'color': '#000'
                    });
                });
                $(contentTypeSelect).append(opt_group);
            });

            return contentTypeSelect;
        },

        getLookupUrlParams: function(cID) {
            var q = this.url_array[cID][1] || {};
            var str = [];
            for(var p in q)
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(q[p]));
            x = str.join("&");
            url = x ? ("?" + x) : "";
            return url
        },
        getLookupUrl: function(cID) {
            return '../../../' + this.url_array[cID][0] + '/' + this.getLookupUrlParams(cID);
        },
        hideLookupLink: function() {
            var this_id = this.object_input.attr('id');
            $('#lookup_' + this_id).unbind().remove();
            $('#lookup_text_' + this_id).remove();
        },
        showLookupLink: function() {
            var that = this;
            var url = this.getLookupUrl(this.cID);
            var this_id = this.object_input.attr('id');
            var id = 'lookup_' + this_id;

            var link = '';
            link = link + '';
            link = link + '';

            // insert link html after input element
            $(this.object_input).after(link);

            return id;
        },
        pollInputChange: function(window) {
            var that = this;
            var interval_id = setInterval(function() {
                if (window.closed == true) {
                    clearInterval(interval_id);
                    that.updateObjectData()();
                    return true;
                }
            },
            150);
        },
        popRelatedObjectLookup: function(link) {
            var name = link.id.replace(/^lookup_/, '');
            var href;
            var win;

            name = id_to_windowname(name);

            if (link.href.search(/\?/) >= 0) {
                href = link.href + '&pop=1';
            } else {
                href = link.href + '?pop=1';
            }
            win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');

            // wait for popup to be closed and load object data
            this.pollInputChange(win);

            win.focus();
            return false;
        },
        updateObjectData: function() {
            var that = this;
            return function() {
                // if (!that.object_input.value) { return }
                // bail if no input
                var this_id = that.object_input.attr('id');
                $('#lookup_text_'+this_id).text('').text('loading...');
                $.ajax({
                    url: that.obj_url,
                    dataType: 'json',
                    data: {
                        object_id: that.object_input.attr('value'),
                        content_type: that.cID
                    },
                    success: function(data) {
                        var item = data[0];
                        if (item && item.content_type_text && item.object_text) {
                            $('#lookup_text_'+this_id).text(item.content_type_text + ': ' + item.object_text);
                            // run a callback to do other stuff like prepopulating url fields
                            // can't be done with normal django admin prepopulate
                            if (that.updateObjectDataCallback) {
                                that.updateObjectDataCallback(item);
                            }
                        }
                    }
                });
            };
        },

        installAdmin: function(elem) {
            var that = this;
            // initialize the url array
            that.loadUrlArray();
            // store the base element
            that.object_input = elem;

            // find the select we need to change
            that.object_select = that.prepareSelect(elem);

            // install event handler for select
            $(that.object_select).change(function() {
                // reset the object input to the associated select (this one)
                var id_split = this.id.split('-');
                if (id_split.length !== 1) {
                    that.object_input = $('#' + this.id.replace('-content_type', '-object_id'));
                } else {
                    that.object_input = $('#' + this.id.replace('content_type', 'object_id'));
                }

                //(this).css('color', 'red'); // uncomment for testing
                var link_id;
                that.hideLookupLink();
                // Set our objectId when the content_type is changed
                if (this.value) {
                    that.cID = this.value;
                    link_id = that.showLookupLink();
                    $('#' + link_id).click(function(e) {
                        that.popRelatedObjectLookup(this);
                        return false;
                    });
                }
            });

            // fire change event if something is already selected
            if ($(this.object_select).val()) {
                $(this.object_select).trigger('change');
            }

            // Bind to the onblur of the object_id input.
            $(this.object_input).blur(this.updateObjectData());
        },
    };

    $(document).ready(function() {
        $("[id$='object_id']").each(function(i, e) {
            $.extend({}, GenericAdmin).installAdmin(this);
        });
    });
} (django.jQuery));
<commit_msg>Fixed path to admin's selector search image<commit_after>/*
    genericadmin - Weston Nielson (wnielson@gmail.com)

    updated by Jan Schrewe (jschrewe@googlemail.com)

    updated by Troy Melhase (troy.melhase@gmail.com)

	updated by Jonathan Ellenberger (jon@respondcreate.com)

 */
 (function($) {
    var GenericAdmin = {
        url_array: null,
        obj_url: "../obj/",
        admin_media_url: window.__admin_media_prefix__,
        generics_list_url: '../get-generic-rel-list/',
        loadUrlArray: function() {
            var that = this;
            $.ajax({
                url: this.generics_list_url,
                dataType: 'json',
                success: function(data) {
                    that.url_array = data;
                },
                async: false
            });
        },
        prepareSelect: function(elem) {
            var that = this;
            var opt_keys = [];
            var opt_dict = {};
            var contentTypeSelect;
            var outstring = '';

            // should return 3 items: ["id_ingredientlist_set", "2",
            // "content_type"]
            // FIX:  a better way to specify this for generic inlines
            var context = $(elem).parents('fieldset');
            contentTypeSelect = $("[id$='content_type']", context).first();
            // contentTypeSelect = $('#id_content_type').first();
            var vars = $(this.object_input).attr("id").split('-');
            if (vars.length !== 1) {
                for (var x = 0; x < (vars.length-1); x++){
                    outstring+=vars[x];
                    if (x < (vars.length-2)){
                        outstring+='-';
                    }
                }
                contentTypeSelect = $('#' + outstring + '-content_type').first();
            }

            // polish the look of the select
            $(contentTypeSelect).find('option').each(function() {
                var key;

                if (this.value) {
                    if (that.url_array[this.value]) {
                        key = that.url_array[this.value][0].split('/')[0];
                        // create an array with unique elements
                        if ($.inArray(key, opt_keys) < 0) {
                            opt_keys.push(key);
                            // if it's the first time in array
                            // it's the first time in dict
                            opt_dict[key] = [$(this).clone()];
                        } else {
                            opt_dict[key].push($(this).clone());
                        }
                    }
                    $(this).remove();
                }
            });

            opt_keys = opt_keys.sort();

            var opt_group_css = 'style="font-style:normal; font-weight:bold; color:#999; padding-left: 2px;"';
            $.each(opt_keys, function(index, key) {
                var opt_group = $('<optgroup label="' + key + '" ' + opt_group_css + '></optgroup>');
                $.each(opt_dict[key], function(index, value) {
                    opt_group.append(value).css({
                        'color': '#000'
                    });
                });
                $(contentTypeSelect).append(opt_group);
            });

            return contentTypeSelect;
        },

        getLookupUrlParams: function(cID) {
            var q = this.url_array[cID][1] || {};
            var str = [];
            for(var p in q)
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(q[p]));
            x = str.join("&");
            url = x ? ("?" + x) : "";
            return url
        },
        getLookupUrl: function(cID) {
            return '../../../' + this.url_array[cID][0] + '/' + this.getLookupUrlParams(cID);
        },
        hideLookupLink: function() {
            var this_id = this.object_input.attr('id');
            $('#lookup_' + this_id).unbind().remove();
            $('#lookup_text_' + this_id).remove();
        },
        showLookupLink: function() {
            var that = this;
            var url = this.getLookupUrl(this.cID);
            var this_id = this.object_input.attr('id');
            var id = 'lookup_' + this_id;

            var link = '';
            link = link + '';
            link = link + '';

            // insert link html after input element
            $(this.object_input).after(link);

            return id;
        },
        pollInputChange: function(window) {
            var that = this;
            var interval_id = setInterval(function() {
                if (window.closed == true) {
                    clearInterval(interval_id);
                    that.updateObjectData()();
                    return true;
                }
            },
            150);
        },
        popRelatedObjectLookup: function(link) {
            var name = link.id.replace(/^lookup_/, '');
            var href;
            var win;

            name = id_to_windowname(name);

            if (link.href.search(/\?/) >= 0) {
                href = link.href + '&pop=1';
            } else {
                href = link.href + '?pop=1';
            }
            win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');

            // wait for popup to be closed and load object data
            this.pollInputChange(win);

            win.focus();
            return false;
        },
        updateObjectData: function() {
            var that = this;
            return function() {
                // if (!that.object_input.value) { return }
                // bail if no input
                var this_id = that.object_input.attr('id');
                $('#lookup_text_'+this_id).text('').text('loading...');
                $.ajax({
                    url: that.obj_url,
                    dataType: 'json',
                    data: {
                        object_id: that.object_input.attr('value'),
                        content_type: that.cID
                    },
                    success: function(data) {
                        var item = data[0];
                        if (item && item.content_type_text && item.object_text) {
                            $('#lookup_text_'+this_id).text(item.content_type_text + ': ' + item.object_text);
                            // run a callback to do other stuff like prepopulating url fields
                            // can't be done with normal django admin prepopulate
                            if (that.updateObjectDataCallback) {
                                that.updateObjectDataCallback(item);
                            }
                        }
                    }
                });
            };
        },

        installAdmin: function(elem) {
            var that = this;
            // initialize the url array
            that.loadUrlArray();
            // store the base element
            that.object_input = elem;

            // find the select we need to change
            that.object_select = that.prepareSelect(elem);

            // install event handler for select
            $(that.object_select).change(function() {
                // reset the object input to the associated select (this one)
                var id_split = this.id.split('-');
                if (id_split.length !== 1) {
                    that.object_input = $('#' + this.id.replace('-content_type', '-object_id'));
                } else {
                    that.object_input = $('#' + this.id.replace('content_type', 'object_id'));
                }

                //(this).css('color', 'red'); // uncomment for testing
                var link_id;
                that.hideLookupLink();
                // Set our objectId when the content_type is changed
                if (this.value) {
                    that.cID = this.value;
                    link_id = that.showLookupLink();
                    $('#' + link_id).click(function(e) {
                        that.popRelatedObjectLookup(this);
                        return false;
                    });
                }
            });

            // fire change event if something is already selected
            if ($(this.object_select).val()) {
                $(this.object_select).trigger('change');
            }

            // Bind to the onblur of the object_id input.
            $(this.object_input).blur(this.updateObjectData());
        },
    };

    $(document).ready(function() {
        $("[id$='object_id']").each(function(i, e) {
            $.extend({}, GenericAdmin).installAdmin(this);
        });
    });
} (django.jQuery));
<|endoftext|>


<commit_before>import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import memoize from 'memoizerific';

import { Global } from '@storybook/theming';

import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
import { SET_STORIES } from '@storybook/core-events';

import { PARAM_KEY } from './constants';

const toList = memoize(50)(items =>
  items ? Object.entries(items).map(([id, value]) => ({ ...value, id })) : []
);
const iframeId = 'storybook-preview-iframe';

const createItem = memoize(1000)((id, name, value, change) => ({
  id: id || name,
  title: name,
  onClick: () => {
    change({ selected: id, expanded: false });
  },
  right: `${value.width}-${value.height}`,
  value,
}));

const flip = ({ width, height }) => ({ height: width, width: height });

const getState = memoize(10)((props, state, change) => {
  const data = props.api.getCurrentStoryData();
  const list = toList(data && data.parameters && data.parameters[PARAM_KEY]);

  const selected =
    state.selected === 'responsive' || list.find(i => i.id === state.selected)
      ? state.selected
      : list.find(i => i.default) || 'responsive';

  const resets =
    selected !== 'responsive'
      ? [
          {
            id: 'reset',
            title: 'Reset viewport',
            onClick: () => {
              change({ selected: undefined, expanded: false });
            },
          },
          {
            id: 'rotate',
            title: 'Rotate viewport',
            onClick: () => {
              change({ isRotated: !state.isRotated, expanded: false });
            },
          },
        ]
      : [];
  const items = list.length
    ? resets.concat(list.map(({ id, name, styles: value }) => createItem(id, name, value, change)))
    : list;

  return {
    isRotated: state.isRotated,
    items,
    selected,
  };
});

export default class ViewportTool extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isRotated: false,
      items: [],
      selected: 'responsive',
      expanded: false,
    };

    this.listener = () => {
      this.setState({
        selected: null,
      });
    };
  }

  componentDidMount() {
    const { api } = this.props;
    api.on(SET_STORIES, this.listener);
  }

  componentWillUnmount() {
    const { api } = this.props;
    api.off(SET_STORIES, this.listener);
  }

  change = (...args) => this.setState(...args);

  render() {
    const { expanded } = this.state;
    const { items, selected, isRotated } = getState(this.props, this.state, this.change);
    const item = items.find(i => i.id === selected);

    return items.length ? (
      <Fragment>
        {item ? (
          <Global
            styles={{
              [`#${iframeId}`]: {
                border: '10px solid black',
                borderRadius: 4,
                margin: 10,

                ...(isRotated ? flip(item.value || {}) : item.value || {}),
              },
            }}
          />
        ) : null}
        <WithTooltip
          placement="top"
          trigger="click"
          tooltipShown={expanded}
          onVisibilityChange={s => this.setState({ expanded: s })}
          tooltip={<TooltipLinkList links={items} />}
          closeOnClick
        >
          <IconButton key="viewport" title="Change Viewport">
            <Icons icon="grow" />
          </IconButton>
        </WithTooltip>
      </Fragment>
    ) : null;
  }
}

ViewportTool.propTypes = {
  api: PropTypes.shape({
    on: PropTypes.func,
  }).isRequired,
};
<commit_msg>Improve readability of Viewports addons list items<commit_after>import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import memoize from 'memoizerific';

import { Global } from '@storybook/theming';

import { Icons, IconButton, WithTooltip, TooltipLinkList } from '@storybook/components';
import { SET_STORIES } from '@storybook/core-events';

import { PARAM_KEY } from './constants';

const toList = memoize(50)(items =>
  items ? Object.entries(items).map(([id, value]) => ({ ...value, id })) : []
);
const iframeId = 'storybook-preview-iframe';

const createItem = memoize(1000)((id, name, value, change) => ({
  id: id || name,
  title: name,
  onClick: () => {
    change({ selected: id, expanded: false });
  },
  right: `${value.width.replace('px', '')}x${value.height.replace('px', '')}`,
  value,
}));

const flip = ({ width, height }) => ({ height: width, width: height });

const getState = memoize(10)((props, state, change) => {
  const data = props.api.getCurrentStoryData();
  const list = toList(data && data.parameters && data.parameters[PARAM_KEY]);

  const selected =
    state.selected === 'responsive' || list.find(i => i.id === state.selected)
      ? state.selected
      : list.find(i => i.default) || 'responsive';

  const resets =
    selected !== 'responsive'
      ? [
          {
            id: 'reset',
            title: 'Reset viewport',
            onClick: () => {
              change({ selected: undefined, expanded: false });
            },
          },
          {
            id: 'rotate',
            title: 'Rotate viewport',
            onClick: () => {
              change({ isRotated: !state.isRotated, expanded: false });
            },
          },
        ]
      : [];
  const items = list.length
    ? resets.concat(list.map(({ id, name, styles: value }) => createItem(id, name, value, change)))
    : list;

  return {
    isRotated: state.isRotated,
    items,
    selected,
  };
});

export default class ViewportTool extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isRotated: false,
      items: [],
      selected: 'responsive',
      expanded: false,
    };

    this.listener = () => {
      this.setState({
        selected: null,
      });
    };
  }

  componentDidMount() {
    const { api } = this.props;
    api.on(SET_STORIES, this.listener);
  }

  componentWillUnmount() {
    const { api } = this.props;
    api.off(SET_STORIES, this.listener);
  }

  change = (...args) => this.setState(...args);

  render() {
    const { expanded } = this.state;
    const { items, selected, isRotated } = getState(this.props, this.state, this.change);
    const item = items.find(i => i.id === selected);

    return items.length ? (
      <Fragment>
        {item ? (
          <Global
            styles={{
              [`#${iframeId}`]: {
                border: '10px solid black',
                borderRadius: 4,
                margin: 10,

                ...(isRotated ? flip(item.value || {}) : item.value || {}),
              },
            }}
          />
        ) : null}
        <WithTooltip
          placement="top"
          trigger="click"
          tooltipShown={expanded}
          onVisibilityChange={s => this.setState({ expanded: s })}
          tooltip={<TooltipLinkList links={items} />}
          closeOnClick
        >
          <IconButton key="viewport" title="Change Viewport">
            <Icons icon="grow" />
          </IconButton>
        </WithTooltip>
      </Fragment>
    ) : null;
  }
}

ViewportTool.propTypes = {
  api: PropTypes.shape({
    on: PropTypes.func,
  }).isRequired,
};
<|endoftext|>


<commit_before>(function(win){
	var ns = FL.ns("billd");
	eval(FL.import("FL", "Utils, MovieClip, Keyboard, Mouse"));

	var speed1 = 2;
	var speed2 = 3.5;
	var jumpSpeed = -6;
	var maxSpeed = 7;
	var g = .2;

	var idleActions = ["play1", "play2", "play3", "stand1", "attack", "stand3"];
	var IDLE_TIME = 300;

	var SHOOT_TIME = 40;

	var Player = ns.Player = function()
	{
		MovieClip.apply(this, arguments);

		this.action = "stand2";
		this.time = 0;

		this.pos = new Vector();
		this.v = new Vector();
		this.a = new Vector(0, g);
		this.alive = true;
		this.idle = false;
		this.idleTime = 0;
		this.idleAction = idleActions[0];
		this.floorV = 0;

		this.shootTime = SHOOT_TIME;
	};
	Utils.extends(Player, MovieClip);

	Player.prototype.init = function()
	{
		this.addAnimation("stand3", "0-5", true, 6);
		this.addAnimation("stand2", "6-11", true, 6);
		this.addAnimation("stand1", "12-19", true, 6);
		this.addAnimation("run2", "20-23", true, 4);
		this.addAnimation("run1", "24-29", true, 6);
		this.addAnimation("swim", "30-35 ", true, 6);
		this.addAnimation("play1", "40-54", true, 6);
		this.addAnimation("play2", "55-59", true, 6);
		this.addAnimation("play3", "88-93", true, 6);
		this.addAnimation("jump2", "60-70", false, 8);
		this.addAnimation("jump1", "71-77", false, 6);
		this.addAnimation("attack", "80-87", true, 6);
		this.addAnimation("climb", "88-89", true, 6);

		this.setImg(R.images["billd_mc"], 22, 22);
		this.originX = this.width>>1;
		this.originY = this.height;
		this.bounds = this.getBounds();
	};

	Player.prototype.keyAction = function(){
		if(Math.abs(this.a.x) < .001 && (Keyboard.getIsDown("LEFT") || oState["l"]))
		{
			if(Keyboard.getKeyDelay("LEFT") < 300 || oState["l"] > 1)
			{
				this.v.x = -1*speed2;
			}
			else
			{
				this.v.x = -1*speed1;
			}
			this.scaleX = -1;
		}
		else if(Math.abs(this.a.x) < .001 && (Keyboard.getIsDown("RIGHT") || oState["r"]))
		{
			if(Keyboard.getKeyDelay("RIGHT") < 300 || oState["r"] > 1)
			{
				this.v.x = speed2;
			}
			else
			{
				this.v.x = speed1;
			}
			this.scaleX = 1;
		}
		else
		{
			this.v.x *= .9;
		}

		if(this.v.y == 0 && (Keyboard.getIsDown("UP") || Mouse.isDown))
		{
			this.v.y = jumpSpeed;
			this.angle = 0;
		}

		if(this.v.y == 0 && Keyboard.getIsDown("SPACE") && this.shootTime >= SHOOT_TIME)
		{
			this.playAction("attack");
			this.idleTime = 0;
			this.shootTime = 0;
		}
		else if(this.v.y != 0)
		{
			this.playAction("jump2");
			this.idleTime = 0;
		}
		else if(this.shootTime < 36) {
			this.playAction("attack");
			if(this.shootTime == 30){
				var v = new Vector(5, 0);
				var shootAngle = 0.7;
				var angle = this.scaleX==1?this.angle-shootAngle:this.angle+Math.PI+shootAngle;
				v.rotate(angle);
				var pos = new Vector(this.scaleX*12, -16);
				pos.rotate(this.angle);
				pos.plus(this.pos);
				var ball = ns.InstanceFactory.create("yellow_ball", {x:pos.x, y:pos.y, v:v});
				ns.stage.addChild(ball);
				ns.yellowBalls.push(ball);
			}
		}
		else if(Math.abs(this.v.x) == speed1) this.playAction("run1");
		else if(Math.abs(this.v.x) == speed2) this.playAction("run2");
		else if(this.v.x < speed1)
		{
			this.playAction("idle");
		}
	};

	Player.prototype.playAction = function(name){
		if(name == "idle")
		{
			this.idleTime ++;
			if(this.idleTime > IDLE_TIME)
			{
				if(this.idleTime > IDLE_TIME+100)
				{
					this.idleAction = idleActions[Math.floor(Math.random()*idleActions.length)];
					this.idleTime = IDLE_TIME+1;
				}
				this.play(this.idleAction);
			}
			else
			{
				this.play("stand2");
			}
		}
		else
		{
			this.idleTime = 0;
			this.play(name);
		}
	};

	Player.prototype.checkMap = function(map)
	{
		//脚碰地
		if(map && this.v.y >= 0)
		{
			this.angle = 0;
			var dataArr = map.mapData[this.pos.x>>0];
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var data = dataArr[i];
					if(data.y <= this.pos.y + 2 && data.y >= this.pos.y - 5)
					{
						this.pos.y = data.y;
						this.v.y = 0;
						this.angle = data.ang;
						break;
					}
				}
			}
		}

		var padding = 3;
		//头碰墙
		var dataArr = map.wallData[(this.pos.y-this.height+padding)>>0];
		if(map && this.v.x > 0)//碰右边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x + this.width*.5 && x >= this.pos.x + this.width*.5 - 5)
					{
						this.pos.x = x - this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		else if(map && this.v.x < 0)//碰左边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x - this.width*.5 + 5&& x >= this.pos.x - this.width*.5)
					{
						this.pos.x = x + this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		//脚碰墙
		var dataArr = map.wallData[(this.pos.y-padding)>>0];
		if(map && this.v.x > 0)//碰右边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x + this.width*.5 && x >= this.pos.x + this.width*.5 - 5)
					{
						this.pos.x = x - this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		else if(map && this.v.x < 0)//碰左边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x - this.width*.5 + 5&& x >= this.pos.x - this.width*.5)
					{
						this.pos.x = x + this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
	};

	Player.prototype.die  =function()
	{
		this.alive = false;
		var that = this;
		setTimeout(function(){
			that.alive = true;
			that.alpha = 1;
		}, 2000);
	}

	Player.prototype.checkFloors = function(floors){
		if(this.v.y>=0)
		{
			for(var i = 0, l = floors.length;i < l;i ++)
			{
				var floor = floors[i];
				if(this.bounds.left < floor.x + floor.width && this.bounds.right > floor.x)
				{
					if(floor.pos.y <= this.pos.y + 2 && floor.pos.y >= this.pos.y - 5)
					{
						this.pos.y = floor.pos.y;
						this.v.y = 0;
						this.floorV = floor.v.x;
						return;
					}
				}
			}
		}
		this.floorV = 0;
	}

	Player.prototype.checkSprings = function(springs){
		if(this.v.y>0)
		{
			for(var i = 0, l = springs.length;i < l;i ++)
			{
				var spring = springs[i];
				if(!spring.isJump && this.bounds.left < spring.x + spring.width && this.bounds.right > spring.x)
				{
					if(spring.pos.y - spring.height <= this.pos.y + 2 && spring.pos.y - spring.height >= this.pos.y - 5)
					{
						spring.jump(this);
						this.spring = spring;
						return;
					}
				}
			}
		}
	}

	Player.prototype.update = function()
	{
		this.shootTime ++;
		this.bounds = this.getBounds();
		this.v.plus(this.a);
		if(this.v.y > maxSpeed) this.v.y = maxSpeed;
		if(this.v.x > speed2) this.v.x = speed2;
		if(this.v.x < -1*speed2) this.v.x = -1*speed2;

		this.pos.plus(this.v);
		this.pos.x += this.floorV;
		this.a.x *= .9;

		this.checkMap(ns.map);
		this.checkFloors(ns.floors);
		this.checkSprings(ns.springs);

		this.x = this.pos.x + ns.map.x;
		this.y = this.pos.y + ns.map.y;

		this.keyAction();

		if( !this.alive)
		{
			this.time++;
			if(this.time%10>5)
			{
				this.alpha = 1;
			}
			else
			{
				this.alpha = 0;
			}
		}
	};

	Player.create = function(x, y)
	{
		var player = new Player();
		player.init();
		player.play("play1");
		player.pos.set(x, y);
		return player;
	}

	var oState = {};
	window.ondeviceorientation =  function(e)
	{
		var ang;
		var o = window.orientation;
		if(o == 90){
			ang = e.beta;
		}
		else if(o == -90){
			ang = -e.beta;
		}
		else if(o == 0){
			ang = e.gamma;
		}

		if(ang > 15)
		{
			oState["r"] = 2;
		}
		else if(ang > 5)
		{
			oState["r"] = 1;
		}
		else if(ang < -15)
		{
			oState["l"] = 2;
		}
		else if(ang < -5)
		{
			oState["l"] = 1;
		}
		else
		{
			oState["l"] = oState["r"] = false;
		}
	}
})(window);

<commit_msg>add bullet<commit_after>(function(win){
	var ns = FL.ns("billd");
	eval(FL.import("FL", "Utils, MovieClip, Keyboard, Mouse"));

	var speed1 = 2;
	var speed2 = 3.5;
	var jumpSpeed = -6;
	var maxSpeed = 7;
	var g = .2;

	var idleActions = ["play1", "play2", "play3", "stand1", "attack", "stand3"];
	var IDLE_TIME = 300;

	var SHOOT_TIME = 14;

	var Player = ns.Player = function()
	{
		MovieClip.apply(this, arguments);

		this.action = "stand2";
		this.time = 0;

		this.pos = new Vector();
		this.v = new Vector();
		this.a = new Vector(0, g);
		this.alive = true;
		this.idle = false;
		this.idleTime = 0;
		this.idleAction = idleActions[0];
		this.floorV = 0;

		this.shootTime = SHOOT_TIME;
	};
	Utils.extends(Player, MovieClip);

	Player.prototype.init = function()
	{
		this.addAnimation("stand3", "0-5", true, 6);
		this.addAnimation("stand2", "6-11", true, 6);
		this.addAnimation("stand1", "12-19", true, 6);
		this.addAnimation("run2", "20-23", true, 4);
		this.addAnimation("run1", "24-29", true, 6);
		this.addAnimation("swim", "30-35 ", true, 6);
		this.addAnimation("play1", "40-54", true, 6);
		this.addAnimation("play2", "55-59", true, 6);
		this.addAnimation("play3", "88-93", true, 6);
		this.addAnimation("jump2", "60-70", false, 8);
		this.addAnimation("jump1", "71-77", false, 6);
		this.addAnimation("attack", "80-87", true, 6);
		this.addAnimation("climb", "88-89", true, 6);

		this.setImg(R.images["billd_mc"], 22, 22);
		this.originX = this.width>>1;
		this.originY = this.height;
		this.bounds = this.getBounds();
	};

	Player.prototype.keyAction = function(){
		if(Math.abs(this.a.x) < .001 && (Keyboard.getIsDown("LEFT") || oState["l"]))
		{
			if(Keyboard.getKeyDelay("LEFT") < 300 || oState["l"] > 1)
			{
				this.v.x = -1*speed2;
			}
			else
			{
				this.v.x = -1*speed1;
			}
			this.scaleX = -1;
		}
		else if(Math.abs(this.a.x) < .001 && (Keyboard.getIsDown("RIGHT") || oState["r"]))
		{
			if(Keyboard.getKeyDelay("RIGHT") < 300 || oState["r"] > 1)
			{
				this.v.x = speed2;
			}
			else
			{
				this.v.x = speed1;
			}
			this.scaleX = 1;
		}
		else
		{
			this.v.x *= .9;
		}

		if(this.v.y == 0 && (Keyboard.getIsDown("UP") || Mouse.isDown))
		{
			this.v.y = jumpSpeed;
			this.angle = 0;
		}

		if(this.v.y == 0 && Keyboard.getIsDown("SPACE") && this.shootTime >= SHOOT_TIME)
		{
			this.playAction("play2");
			this.idleTime = 0;
			this.shootTime = 0;
		}
		else if(this.v.y != 0)
		{
			this.playAction("jump2");
			this.idleTime = 0;
		}
		else if(this.shootTime < 12) {
			this.playAction("play2");
			if(this.shootTime == 10){
				var v = new Vector(5, 0);
				var shootAngle = 0.7;
				var angle = this.scaleX==1?this.angle-shootAngle:this.angle+Math.PI+shootAngle;
				v.rotate(angle);
				var pos = new Vector(this.scaleX*12, -16);
				pos.rotate(this.angle);
				pos.plus(this.pos);
				var ball = ns.InstanceFactory.create("yellow_ball", {x:pos.x, y:pos.y, v:v});
				ns.stage.addChild(ball);
				ns.yellowBalls.push(ball);
			}
		}
		else if(Math.abs(this.v.x) == speed1) this.playAction("run1");
		else if(Math.abs(this.v.x) == speed2) this.playAction("run2");
		else if(this.v.x < speed1)
		{
			this.playAction("idle");
		}
	};

	Player.prototype.playAction = function(name){
		if(name == "idle")
		{
			this.idleTime ++;
			if(this.idleTime > IDLE_TIME)
			{
				if(this.idleTime > IDLE_TIME+100)
				{
					this.idleAction = idleActions[Math.floor(Math.random()*idleActions.length)];
					this.idleTime = IDLE_TIME+1;
				}
				this.play(this.idleAction);
			}
			else
			{
				this.play("stand2");
			}
		}
		else
		{
			this.idleTime = 0;
			this.play(name);
		}
	};

	Player.prototype.checkMap = function(map)
	{
		//脚碰地
		if(map && this.v.y >= 0)
		{
			this.angle = 0;
			var dataArr = map.mapData[this.pos.x>>0];
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var data = dataArr[i];
					if(data.y <= this.pos.y + 2 && data.y >= this.pos.y - 5)
					{
						this.pos.y = data.y;
						this.v.y = 0;
						this.angle = data.ang;
						break;
					}
				}
			}
		}

		var padding = 3;
		//头碰墙
		var dataArr = map.wallData[(this.pos.y-this.height+padding)>>0];
		if(map && this.v.x > 0)//碰右边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x + this.width*.5 && x >= this.pos.x + this.width*.5 - 5)
					{
						this.pos.x = x - this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		else if(map && this.v.x < 0)//碰左边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x - this.width*.5 + 5&& x >= this.pos.x - this.width*.5)
					{
						this.pos.x = x + this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		//脚碰墙
		var dataArr = map.wallData[(this.pos.y-padding)>>0];
		if(map && this.v.x > 0)//碰右边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x + this.width*.5 && x >= this.pos.x + this.width*.5 - 5)
					{
						this.pos.x = x - this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
		else if(map && this.v.x < 0)//碰左边墙
		{
			if(dataArr){
				for(var i = 0, l = dataArr.length;i < l;i ++)
				{
					var x = dataArr[i];
					if(x <= this.pos.x - this.width*.5 + 5&& x >= this.pos.x - this.width*.5)
					{
						this.pos.x = x + this.width*.5;
						this.v.x = 0;
						return;
					}
				}
			}
		}
	};

	Player.prototype.die  =function()
	{
		this.alive = false;
		var that = this;
		setTimeout(function(){
			that.alive = true;
			that.alpha = 1;
		}, 2000);
	}

	Player.prototype.checkFloors = function(floors){
		if(this.v.y>=0)
		{
			for(var i = 0, l = floors.length;i < l;i ++)
			{
				var floor = floors[i];
				if(this.bounds.left < floor.x + floor.width && this.bounds.right > floor.x)
				{
					if(floor.pos.y <= this.pos.y + 2 && floor.pos.y >= this.pos.y - 5)
					{
						this.pos.y = floor.pos.y;
						this.v.y = 0;
						this.floorV = floor.v.x;
						return;
					}
				}
			}
		}
		this.floorV = 0;
	}

	Player.prototype.checkSprings = function(springs){
		if(this.v.y>0)
		{
			for(var i = 0, l = springs.length;i < l;i ++)
			{
				var spring = springs[i];
				if(!spring.isJump && this.bounds.left < spring.x + spring.width && this.bounds.right > spring.x)
				{
					if(spring.pos.y - spring.height <= this.pos.y + 2 && spring.pos.y - spring.height >= this.pos.y - 5)
					{
						spring.jump(this);
						this.spring = spring;
						return;
					}
				}
			}
		}
	}

	Player.prototype.update = function()
	{
		this.shootTime ++;
		this.bounds = this.getBounds();
		this.v.plus(this.a);
		if(this.v.y > maxSpeed) this.v.y = maxSpeed;
		if(this.v.x > speed2) this.v.x = speed2;
		if(this.v.x < -1*speed2) this.v.x = -1*speed2;

		this.pos.plus(this.v);
		this.pos.x += this.floorV;
		this.a.x *= .9;

		this.checkMap(ns.map);
		this.checkFloors(ns.floors);
		this.checkSprings(ns.springs);

		this.x = this.pos.x + ns.map.x;
		this.y = this.pos.y + ns.map.y;

		this.keyAction();

		if( !this.alive)
		{
			this.time++;
			if(this.time%10>5)
			{
				this.alpha = 1;
			}
			else
			{
				this.alpha = 0;
			}
		}
	};

	Player.create = function(x, y)
	{
		var player = new Player();
		player.init();
		player.play("play1");
		player.pos.set(x, y);
		return player;
	}

	var oState = {};
	window.ondeviceorientation =  function(e)
	{
		var ang;
		var o = window.orientation;
		if(o == 90){
			ang = e.beta;
		}
		else if(o == -90){
			ang = -e.beta;
		}
		else if(o == 0){
			ang = e.gamma;
		}

		if(ang > 15)
		{
			oState["r"] = 2;
		}
		else if(ang > 5)
		{
			oState["r"] = 1;
		}
		else if(ang < -15)
		{
			oState["l"] = 2;
		}
		else if(ang < -5)
		{
			oState["l"] = 1;
		}
		else
		{
			oState["l"] = oState["r"] = false;
		}
	}
})(window);

<|endoftext|>


<commit_before><commit_msg>Update cartModelBuilder.js<commit_after><|endoftext|>


<commit_before>/*
 * @license Hyphenopoly_Loader 2.0.0-devel - client side hyphenation
 *  ©2018  Mathias Nater, Zürich (mathiasnater at gmail dot com)
 *  https://github.com/mnater/Hyphenopoly
 *
 *  Released under the MIT license
 *  http://mnater.github.io/Hyphenopoly/LICENSE
 */

(function H9YL() {
    "use strict";
    const d = document;
    const H = Hyphenopoly;

    /**
     * Create Object without standard Object-prototype
     * @returns {Object} empty object
     */
    function empty() {
        return Object.create(null);
    }

    if (H.cacheFeatureTests && sessionStorage.getItem("Hyphenopoly_Loader")) {
        H.clientFeat = JSON.parse(sessionStorage.getItem("Hyphenopoly_Loader"));
    } else {
        H.clientFeat = {
            "wasm": null,
            "langs": empty(),
            "polyfill": false
        };
    }

    const t = H.clientFeat;

    (function setupEvents() {
        // Events known to the system
        const definedEvents = empty();
        // Default events, execution deferred to Hyphenopoly.js
        const deferred = [];

        /*
         * Eegister for custom event handlers, where event is not yet defined
         * these events will be correctly registered in Hyphenopoly.js
         */
        const tempRegister = [];

        /**
         * Create Event Object
         * @param {string} name The Name of the event
         * @param {function} defFunc The default method of the event
         * @param {boolean} cancellable Is the default cancellable
         * @returns {undefined}
         */
        function define(name, defFunc, cancellable) {
            definedEvents[name] = {
                "cancellable": cancellable,
                "default": defFunc,
                "register": []
            };
        }

        define(
            "timeout",
            function def(e) {
                d.documentElement.style.visibility = "visible";
                window.console.info(
                    "Hyphenopolys 'FOUHC'-prevention timed out after %dms",
                    e.delay
                );
            },
            false
        );

        define(
            "error",
            function def(e) {
                window.console.error(e.msg);
            },
            true
        );

        define(
            "contentLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "contentLoaded"
                });
            },
            false
        );

        define(
            "engineLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "engineLoaded"
                });
            },
            false
        );

        define(
            "hpbLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "hpbLoaded"
                });
            },
            false
        );

        /**
         * Dispatch error <name> with arguments <data>
         * @param {string} name The name of the event
         * @param {Object|undefined} data Data of the event
         * @returns {undefined}
         */
        function dispatch(name, data) {
            if (!data) {
                data = empty();
            }
            data.defaultPrevented = false;
            data.preventDefault = function preventDefault() {
                if (definedEvents[name].cancellable) {
                    data.defaultPrevented = true;
                }
            };
            definedEvents[name].register.forEach(function call(currentHandler) {
                currentHandler(data);
            });
            if (!data.defaultPrevented && definedEvents[name].default) {
                definedEvents[name].default(data);
            }
        }

        /**
         * Add EventListender <handler> to event <name>
         * @param {string} name The name of the event
         * @param {function} handler Function to register
         * @param {boolean} defer If the registration is deferred
         * @returns {undefined}
         */
        function addListener(name, handler, defer) {
            if (definedEvents[name]) {
                definedEvents[name].register.push(handler);
            } else if (defer) {
                tempRegister.push({
                    "handler": handler,
                    "name": name
                });
            } else {
                H.events.dispatch(
                    "error",
                    {"msg": `unknown Event "${name}" discarded`}
                );
            }
        }

        if (H.handleEvent) {
            Object.keys(H.handleEvent).forEach(function add(name) {
                addListener(name, H.handleEvent[name], true);
            });
        }

        H.events = empty();
        H.events.deferred = deferred;
        H.events.tempRegister = tempRegister;
        H.events.dispatch = dispatch;
        H.events.define = define;
        H.events.addListener = addListener;
    }());

    (function featureTestWasm() {
        /* eslint-disable max-len, no-magic-numbers, no-prototype-builtins */
        /**
         * Feature test for wasm
         * @returns {boolean} support
         */
        function runWasmTest() {
            /*
             * This is the original test, without webkit workaround
             * if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
             *     const module = new WebAssembly.Module(Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0]));
             *     if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
             *         return WebAssembly.Instance.prototype.isPrototypeOf(new WebAssembly.Instance(module));
             *     }
             * }
             * return false;
             */

            // Wasm feature test with iOS bug detection (https://bugs.webkit.org/show_bug.cgi?id=181781)
            if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
                const module = new WebAssembly.Module(Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127, 3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 8, 1, 4, 116, 101, 115, 116, 0, 0, 10, 16, 1, 14, 0, 32, 0, 65, 1, 54, 2, 0, 32, 0, 40, 2, 0, 11]));
                if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
                    const inst = new WebAssembly.Instance(module);
                    return WebAssembly.Instance.prototype.isPrototypeOf(inst) && (inst.exports.test(4) !== 0);
                }
            }
            return false;
        }
        /* eslint-enable max-len, no-magic-numbers, no-prototype-builtins */
        if (t.wasm === null) {
            t.wasm = runWasmTest();
        }
    }());

    const scriptLoader = (function scriptLoader() {
        const loadedScripts = empty();

        /**
         * Load script by adding <script>-tag
         * @param {string} path Where the script is stored
         * @param {string} filename Filename of the script
         * @returns {undefined}
         */
        function loadScript(path, filename) {
            if (!loadedScripts[filename]) {
                const script = d.createElement("script");
                loadedScripts[filename] = true;
                script.src = path + filename;
                if (filename === "hyphenEngine.asm.js") {
                    script.addEventListener("load", function listener() {
                        H.events.dispatch("engineLoaded", {"msg": "asm"});
                    });
                }
                d.head.appendChild(script);
            }
        }
        return loadScript;
    }());

    const binLoader = (function binLoader() {
        const loadedBins = empty();

        /**
         * Get bin file using fetch
         * @param {string} path Where the script is stored
         * @param {string} fne Filename of the script with extension
         * @param {Object} msg Message
         * @returns {undefined}
         */
        function fetchBinary(path, fne, msg) {
            if (!loadedBins[fne]) {
                loadedBins[fne] = true;
                fetch(path + fne).then(
                    function then(response) {
                        if (response.ok) {
                            const name = fne.slice(0, fne.lastIndexOf("."));
                            if (name === "hyphenEngine") {
                                H.binaries[name] = response.arrayBuffer().then(
                                    function getModule(buf) {
                                        return new WebAssembly.Module(buf);
                                    }
                                );
                            } else {
                                H.binaries[name] = response.arrayBuffer();
                            }
                            H.events.dispatch(msg[0], {"msg": msg[1]});
                        }
                    }
                );
            }
        }

        /**
         * Get bin file using XHR
         * @param {string} path Where the script is stored
         * @param {string} fne Filename of the script with extension
         * @param {Object} msg Message
         * @returns {undefined}
         */
        function requestBinary(path, fne, msg) {
            if (!loadedBins[fne]) {
                loadedBins[fne] = true;
                const xhr = new XMLHttpRequest();
                xhr.open("GET", path + fne);
                xhr.onload = function onload() {
                    const name = fne.slice(0, fne.lastIndexOf("."));
                    H.binaries[name] = xhr.response;
                    H.events.dispatch(msg[0], {"msg": msg[1]});
                };
                xhr.responseType = "arraybuffer";
                xhr.send();
            }
        }

        return (t.wasm)
            ? fetchBinary
            : requestBinary;
    }());

    /**
     * Allocate memory for (w)asm
     * @param {string} lang Language
     * @returns {undefined}
     */
    function allocateMemory(lang) {
        let wasmPages = 0;
        switch (lang) {
        case "nl":
            wasmPages = 41;
            break;
        case "de":
            wasmPages = 75;
            break;
        case "nb-no":
            wasmPages = 92;
            break;
        case "hu":
            wasmPages = 207;
            break;
        default:
            wasmPages = 32;
        }
        if (!H.specMems) {
            H.specMems = empty();
        }
        if (t.wasm) {
            H.specMems[lang] = new WebAssembly.Memory({
                "initial": wasmPages,
                "maximum": 256
            });
        } else {
            /* eslint-disable no-bitwise */
            /**
             * Polyfill Math.log2
             * @param {number} x argument
             * @return {number} Log2(x)
             */
            Math.log2 = Math.log2 || function polyfillLog2(x) {
                return Math.log(x) * Math.LOG2E;
            };

            const asmPages = (2 << Math.floor(Math.log2(wasmPages))) * 65536;
            /* eslint-enable no-bitwise */
            H.specMems[lang] = new ArrayBuffer(asmPages);
        }
    }

    /**
     * Load all ressources for a required <lang>
     * @param {string} lang The language
     * @returns {undefined}
     */
    function loadRessources(lang) {
        if (!H.binaries) {
            H.binaries = empty();
        }
        scriptLoader(H.paths.maindir, "Hyphenopoly.js");
        if (t.wasm) {
            binLoader(
                H.paths.maindir,
                "hyphenEngine.wasm",
                ["engineLoaded", "wasm"]
            );
        } else {
            scriptLoader(H.paths.maindir, "hyphenEngine.asm.js");
        }
        binLoader(H.paths.patterndir, `${lang}.hpb`, ["hpbLoaded", lang]);
        allocateMemory(lang);
    }

    (function featureTestCSSHHyphenation() {
        const tester = (function tester() {
            let fakeBody = null;

            /**
             * Create and append div with CSS-hyphenated word
             * @param {string} lang Language
             * @returns {undefined}
             */
            function createTest(lang) {
                if (t.langs[lang]) {
                    return;
                }
                if (!fakeBody) {
                    fakeBody = d.createElement("body");
                }
                const testDiv = d.createElement("div");
                testDiv.lang = lang;
                testDiv.id = lang;
                testDiv.style.cssText = "visibility:hidden;-moz-hyphens:auto;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;width:48px;font-size:12px;line-height:12px;border:none;padding:0;word-wrap:normal";
                testDiv.appendChild(d.createTextNode(H.require[lang]));
                fakeBody.appendChild(testDiv);
            }

            /**
             * Append fakeBody with tests to target (document)
             * @param {Object} target Where to append fakeBody
             * @returns {Object|null} The body element or null, if no tests
             */
            function appendTests(target) {
                if (fakeBody) {
                    target.appendChild(fakeBody);
                    return fakeBody;
                }
                return null;
            }

            /**
             * Remove fakeBody
             * @returns {undefined}
             */
            function clearTests() {
                if (fakeBody) {
                    fakeBody.parentNode.removeChild(fakeBody);
                }
            }
            return {
                "appendTests": appendTests,
                "clearTests": clearTests,
                "createTest": createTest
            };
        }());

        Object.keys(H.require).forEach(function doReqLangs(lang) {
            if (H.require[lang] === "FORCEHYPHENOPOLY") {
                t.polyfill = true;
                t.langs[lang] = "H9Y";
                loadRessources(lang);
            } else if (
                t.langs[lang] &&
                t.langs[lang] === "H9Y"
            ) {
                loadRessources(lang);
            } else {
                tester.createTest(lang);
            }
        });
        const testContainer = tester.appendTests(d.documentElement);
        if (testContainer !== null) {
            Object.keys(H.require).forEach(function checkReqLangs(lang) {
                if (H.require[lang] !== "FORCEHYPHENOPOLY") {
                    const el = d.getElementById(lang);
                    if (window.getComputedStyle(el).hyphens === "auto" &&
                        el.offsetHeight > 12) {
                        t.polyfill = t.polyfill || false;
                        t.langs[lang] = "CSS";
                    } else {
                        t.polyfill = true;
                        t.langs[lang] = "H9Y";
                        loadRessources(lang);
                    }
                }
            });
            tester.clearTests();
        }
    }());

    (function run() {
        // Set defaults for paths and setup
        if (H.paths) {
            if (!H.paths.patterndir) {
                H.paths.patterndir = "../Hyphenopoly/patterns/";
            }
            if (!H.paths.maindir) {
                H.paths.maindir = "../Hyphenopoly/";
            }
        } else {
            H.paths = {
                "maindir": "../Hyphenopoly/",
                "patterndir": "../Hyphenopoly/patterns/"
            };
        }
        if (H.setup) {
            if (!H.setup.classnames) {
                H.setup.classnames = {"hyphenate": {}};
            }
            if (!H.setup.timeout) {
                H.setup.timeout = 1000;
            }
        } else {
            H.setup = {
                "classnames": {"hyphenate": {}},
                "timeout": 1000
            };
        }

        if (t.polyfill) {
            d.documentElement.style.visibility = "hidden";

            H.setup.timeOutHandler = window.setTimeout(function timedOut() {
                d.documentElement.style.visibility = "visible";
                H.events.dispatch("timeout", {"delay": H.setup.timeout});
            }, H.setup.timeout);
            d.addEventListener(
                "DOMContentLoaded",
                function DCL() {
                    H.events.dispatch("contentLoaded", {"msg": ["contentLoaded"]});
                },
                {
                    "once": true,
                    "passive": true
                }
            );
        } else {
            window.Hyphenopoly = null;
        }
    }());

    if (H.cacheFeatureTests) {
        sessionStorage.setItem("Hyphenopoly_Loader", JSON.stringify(t));
    }
}());
<commit_msg>Make e.preventDefault behave correctly<commit_after>/*
 * @license Hyphenopoly_Loader 2.0.0-devel - client side hyphenation
 *  ©2018  Mathias Nater, Zürich (mathiasnater at gmail dot com)
 *  https://github.com/mnater/Hyphenopoly
 *
 *  Released under the MIT license
 *  http://mnater.github.io/Hyphenopoly/LICENSE
 */

(function H9YL() {
    "use strict";
    const d = document;
    const H = Hyphenopoly;

    /**
     * Create Object without standard Object-prototype
     * @returns {Object} empty object
     */
    function empty() {
        return Object.create(null);
    }

    if (H.cacheFeatureTests && sessionStorage.getItem("Hyphenopoly_Loader")) {
        H.clientFeat = JSON.parse(sessionStorage.getItem("Hyphenopoly_Loader"));
    } else {
        H.clientFeat = {
            "wasm": null,
            "langs": empty(),
            "polyfill": false
        };
    }

    const t = H.clientFeat;

    (function setupEvents() {
        // Events known to the system
        const definedEvents = empty();
        // Default events, execution deferred to Hyphenopoly.js
        const deferred = [];

        /*
         * Eegister for custom event handlers, where event is not yet defined
         * these events will be correctly registered in Hyphenopoly.js
         */
        const tempRegister = [];

        /**
         * Create Event Object
         * @param {string} name The Name of the event
         * @param {function} defFunc The default method of the event
         * @param {boolean} cancellable Is the default cancellable
         * @returns {undefined}
         */
        function define(name, defFunc, cancellable) {
            definedEvents[name] = {
                "cancellable": cancellable,
                "default": defFunc,
                "register": []
            };
        }

        define(
            "timeout",
            function def(e) {
                d.documentElement.style.visibility = "visible";
                window.console.info(
                    "Hyphenopolys 'FOUHC'-prevention timed out after %dms",
                    e.delay
                );
            },
            false
        );

        define(
            "error",
            function def(e) {
                window.console.error(e.msg);
            },
            true
        );

        define(
            "contentLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "contentLoaded"
                });
            },
            false
        );

        define(
            "engineLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "engineLoaded"
                });
            },
            false
        );

        define(
            "hpbLoaded",
            function def(e) {
                deferred.push({
                    "data": e,
                    "name": "hpbLoaded"
                });
            },
            false
        );

        /**
         * Dispatch error <name> with arguments <data>
         * @param {string} name The name of the event
         * @param {Object|undefined} data Data of the event
         * @returns {undefined}
         */
        function dispatch(name, data) {
            if (!data) {
                data = empty();
            }
            definedEvents[name].register.forEach(function call(currentHandler) {
                let defaultPrevented = false;
                data.preventDefault = function preventDefault() {
                    if (definedEvents[name].cancellable) {
                        defaultPrevented = true;
                    }
                };
                currentHandler(data);
                if (!defaultPrevented && definedEvents[name].default) {
                    definedEvents[name].default(data);
                }
            });
        }

        /**
         * Add EventListender <handler> to event <name>
         * @param {string} name The name of the event
         * @param {function} handler Function to register
         * @param {boolean} defer If the registration is deferred
         * @returns {undefined}
         */
        function addListener(name, handler, defer) {
            if (definedEvents[name]) {
                definedEvents[name].register.push(handler);
            } else if (defer) {
                tempRegister.push({
                    "handler": handler,
                    "name": name
                });
            } else {
                H.events.dispatch(
                    "error",
                    {"msg": `unknown Event "${name}" discarded`}
                );
            }
        }

        if (H.handleEvent) {
            Object.keys(H.handleEvent).forEach(function add(name) {
                addListener(name, H.handleEvent[name], true);
            });
        }

        H.events = empty();
        H.events.deferred = deferred;
        H.events.tempRegister = tempRegister;
        H.events.dispatch = dispatch;
        H.events.define = define;
        H.events.addListener = addListener;
    }());

    (function featureTestWasm() {
        /* eslint-disable max-len, no-magic-numbers, no-prototype-builtins */
        /**
         * Feature test for wasm
         * @returns {boolean} support
         */
        function runWasmTest() {
            /*
             * This is the original test, without webkit workaround
             * if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
             *     const module = new WebAssembly.Module(Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0]));
             *     if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
             *         return WebAssembly.Instance.prototype.isPrototypeOf(new WebAssembly.Instance(module));
             *     }
             * }
             * return false;
             */

            // Wasm feature test with iOS bug detection (https://bugs.webkit.org/show_bug.cgi?id=181781)
            if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
                const module = new WebAssembly.Module(Uint8Array.from([0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127, 3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 8, 1, 4, 116, 101, 115, 116, 0, 0, 10, 16, 1, 14, 0, 32, 0, 65, 1, 54, 2, 0, 32, 0, 40, 2, 0, 11]));
                if (WebAssembly.Module.prototype.isPrototypeOf(module)) {
                    const inst = new WebAssembly.Instance(module);
                    return WebAssembly.Instance.prototype.isPrototypeOf(inst) && (inst.exports.test(4) !== 0);
                }
            }
            return false;
        }
        /* eslint-enable max-len, no-magic-numbers, no-prototype-builtins */
        if (t.wasm === null) {
            t.wasm = runWasmTest();
        }
    }());

    const scriptLoader = (function scriptLoader() {
        const loadedScripts = empty();

        /**
         * Load script by adding <script>-tag
         * @param {string} path Where the script is stored
         * @param {string} filename Filename of the script
         * @returns {undefined}
         */
        function loadScript(path, filename) {
            if (!loadedScripts[filename]) {
                const script = d.createElement("script");
                loadedScripts[filename] = true;
                script.src = path + filename;
                if (filename === "hyphenEngine.asm.js") {
                    script.addEventListener("load", function listener() {
                        H.events.dispatch("engineLoaded", {"msg": "asm"});
                    });
                }
                d.head.appendChild(script);
            }
        }
        return loadScript;
    }());

    const binLoader = (function binLoader() {
        const loadedBins = empty();

        /**
         * Get bin file using fetch
         * @param {string} path Where the script is stored
         * @param {string} fne Filename of the script with extension
         * @param {Object} msg Message
         * @returns {undefined}
         */
        function fetchBinary(path, fne, msg) {
            if (!loadedBins[fne]) {
                loadedBins[fne] = true;
                fetch(path + fne).then(
                    function then(response) {
                        if (response.ok) {
                            const name = fne.slice(0, fne.lastIndexOf("."));
                            if (name === "hyphenEngine") {
                                H.binaries[name] = response.arrayBuffer().then(
                                    function getModule(buf) {
                                        return new WebAssembly.Module(buf);
                                    }
                                );
                            } else {
                                H.binaries[name] = response.arrayBuffer();
                            }
                            H.events.dispatch(msg[0], {"msg": msg[1]});
                        }
                    }
                );
            }
        }

        /**
         * Get bin file using XHR
         * @param {string} path Where the script is stored
         * @param {string} fne Filename of the script with extension
         * @param {Object} msg Message
         * @returns {undefined}
         */
        function requestBinary(path, fne, msg) {
            if (!loadedBins[fne]) {
                loadedBins[fne] = true;
                const xhr = new XMLHttpRequest();
                xhr.open("GET", path + fne);
                xhr.onload = function onload() {
                    const name = fne.slice(0, fne.lastIndexOf("."));
                    H.binaries[name] = xhr.response;
                    H.events.dispatch(msg[0], {"msg": msg[1]});
                };
                xhr.responseType = "arraybuffer";
                xhr.send();
            }
        }

        return (t.wasm)
            ? fetchBinary
            : requestBinary;
    }());

    /**
     * Allocate memory for (w)asm
     * @param {string} lang Language
     * @returns {undefined}
     */
    function allocateMemory(lang) {
        let wasmPages = 0;
        switch (lang) {
        case "nl":
            wasmPages = 41;
            break;
        case "de":
            wasmPages = 75;
            break;
        case "nb-no":
            wasmPages = 92;
            break;
        case "hu":
            wasmPages = 207;
            break;
        default:
            wasmPages = 32;
        }
        if (!H.specMems) {
            H.specMems = empty();
        }
        if (t.wasm) {
            H.specMems[lang] = new WebAssembly.Memory({
                "initial": wasmPages,
                "maximum": 256
            });
        } else {
            /* eslint-disable no-bitwise */
            /**
             * Polyfill Math.log2
             * @param {number} x argument
             * @return {number} Log2(x)
             */
            Math.log2 = Math.log2 || function polyfillLog2(x) {
                return Math.log(x) * Math.LOG2E;
            };

            const asmPages = (2 << Math.floor(Math.log2(wasmPages))) * 65536;
            /* eslint-enable no-bitwise */
            H.specMems[lang] = new ArrayBuffer(asmPages);
        }
    }

    /**
     * Load all ressources for a required <lang>
     * @param {string} lang The language
     * @returns {undefined}
     */
    function loadRessources(lang) {
        if (!H.binaries) {
            H.binaries = empty();
        }
        scriptLoader(H.paths.maindir, "Hyphenopoly.js");
        if (t.wasm) {
            binLoader(
                H.paths.maindir,
                "hyphenEngine.wasm",
                ["engineLoaded", "wasm"]
            );
        } else {
            scriptLoader(H.paths.maindir, "hyphenEngine.asm.js");
        }
        binLoader(H.paths.patterndir, `${lang}.hpb`, ["hpbLoaded", lang]);
        allocateMemory(lang);
    }

    (function featureTestCSSHHyphenation() {
        const tester = (function tester() {
            let fakeBody = null;

            /**
             * Create and append div with CSS-hyphenated word
             * @param {string} lang Language
             * @returns {undefined}
             */
            function createTest(lang) {
                if (t.langs[lang]) {
                    return;
                }
                if (!fakeBody) {
                    fakeBody = d.createElement("body");
                }
                const testDiv = d.createElement("div");
                testDiv.lang = lang;
                testDiv.id = lang;
                testDiv.style.cssText = "visibility:hidden;-moz-hyphens:auto;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;width:48px;font-size:12px;line-height:12px;border:none;padding:0;word-wrap:normal";
                testDiv.appendChild(d.createTextNode(H.require[lang]));
                fakeBody.appendChild(testDiv);
            }

            /**
             * Append fakeBody with tests to target (document)
             * @param {Object} target Where to append fakeBody
             * @returns {Object|null} The body element or null, if no tests
             */
            function appendTests(target) {
                if (fakeBody) {
                    target.appendChild(fakeBody);
                    return fakeBody;
                }
                return null;
            }

            /**
             * Remove fakeBody
             * @returns {undefined}
             */
            function clearTests() {
                if (fakeBody) {
                    fakeBody.parentNode.removeChild(fakeBody);
                }
            }
            return {
                "appendTests": appendTests,
                "clearTests": clearTests,
                "createTest": createTest
            };
        }());

        Object.keys(H.require).forEach(function doReqLangs(lang) {
            if (H.require[lang] === "FORCEHYPHENOPOLY") {
                t.polyfill = true;
                t.langs[lang] = "H9Y";
                loadRessources(lang);
            } else if (
                t.langs[lang] &&
                t.langs[lang] === "H9Y"
            ) {
                loadRessources(lang);
            } else {
                tester.createTest(lang);
            }
        });
        const testContainer = tester.appendTests(d.documentElement);
        if (testContainer !== null) {
            Object.keys(H.require).forEach(function checkReqLangs(lang) {
                if (H.require[lang] !== "FORCEHYPHENOPOLY") {
                    const el = d.getElementById(lang);
                    if (window.getComputedStyle(el).hyphens === "auto" &&
                        el.offsetHeight > 12) {
                        t.polyfill = t.polyfill || false;
                        t.langs[lang] = "CSS";
                    } else {
                        t.polyfill = true;
                        t.langs[lang] = "H9Y";
                        loadRessources(lang);
                    }
                }
            });
            tester.clearTests();
        }
    }());

    (function run() {
        // Set defaults for paths and setup
        if (H.paths) {
            if (!H.paths.patterndir) {
                H.paths.patterndir = "../Hyphenopoly/patterns/";
            }
            if (!H.paths.maindir) {
                H.paths.maindir = "../Hyphenopoly/";
            }
        } else {
            H.paths = {
                "maindir": "../Hyphenopoly/",
                "patterndir": "../Hyphenopoly/patterns/"
            };
        }
        if (H.setup) {
            if (!H.setup.classnames) {
                H.setup.classnames = {"hyphenate": {}};
            }
            if (!H.setup.timeout) {
                H.setup.timeout = 1000;
            }
        } else {
            H.setup = {
                "classnames": {"hyphenate": {}},
                "timeout": 1000
            };
        }

        if (t.polyfill) {
            d.documentElement.style.visibility = "hidden";

            H.setup.timeOutHandler = window.setTimeout(function timedOut() {
                d.documentElement.style.visibility = "visible";
                H.events.dispatch("timeout", {"delay": H.setup.timeout});
            }, H.setup.timeout);
            d.addEventListener(
                "DOMContentLoaded",
                function DCL() {
                    H.events.dispatch("contentLoaded", {"msg": ["contentLoaded"]});
                },
                {
                    "once": true,
                    "passive": true
                }
            );
        } else {
            window.Hyphenopoly = null;
        }
    }());

    if (H.cacheFeatureTests) {
        sessionStorage.setItem("Hyphenopoly_Loader", JSON.stringify(t));
    }
}());
<|endoftext|>