<commit_before>/**
 * Creates a selectionTree object that represents a
 * selectable taxonomy tree using nested unordered lists
 *
 * @param <Array> args.data is an array of around 2500 objects with this format:
 *          {"bioproject_id":57587,"class_id":29547,"genus_id":194,
 *          "name":"Campylobacter jejuni","order_id":213849,"species_id":197}
 * @param <Hash> args.taxa is a list of key-value pairs mapping
 *          taxon id's to taxon names
 * @return <SelectionTree> that The constructed selectionTree object
 */
var constructSelectionTree = function constructSelectionTree(args) {
    /*************** Private variables ***************/

    var that = {},
        data = args.data,
        taxa = args.taxa,
        titles = ["Class", "Order", "Genus", "Species"];

    // Status vars used while dragging to determine if the
    // droptarget needs to be recalculated
    var moving = false,
        moving2 = false;

    /*************** Private methods ***************/

    /**
     * Initializes the data variables and calculates the children property
     * of all nodes in the data
     */
    function init() {
        // Uses a "group by" operator on the data array to create a nested array
        data = d3.nest()
            .key(function (d) { return d.class_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.order_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.genus_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.species_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .entries(data);
        calculateNumOfChildren(data);
        delete data.children;
    }

    /**
     * Calculates the number of leafs under every node in the given list by
     * calling the method recursively.
     *
     * The children property gets set for every node and cointains the
     * calculated number of children.
     *
     * @param <Array> list A list of nodes which all potentially have children
     *          stored in de values param.
     * @return <Hash> return The sum of the number of leafs for all nodes in
     *          given list.
     */
    function calculateNumOfChildren(list) {
        var result = 0,
            node,
            i;

        // Iterate over all nodes
        for (i = 0; i < list.length; i++) {
            node = list[i];

            // If the node has children, call recursively, else 1
            if (node.values !== undefined) {
                node.children = calculateNumOfChildren(node.values);
            } else {
                node.children = 1;
            }
            result += node.children;
        }
        list.children = result;
        return result;
    }

    /**
     * Filters the tree for a given search string if this method isn't call
     * for a second time in the next 500ms
     *
     * @param <String> searchString The string we want to search for
     * @param <jQuery> $tree jQuery object of the tree we want to filter
     */
    function search(searchString, $tree) {
        var text = searchString.toLowerCase();
        delay(function doSearch() {
            $tree.find("li").removeClass("match unmatch");
            if (text !== "") {
                $tree.find("li[data-search*='" + text + "']").addClass("match");
                $tree.find("li.match").parents("li")
                    .addClass("match")
                    .addClass("collapsibleListOpen")
                    .removeClass("collapsibleListClosed");
                $tree.find("li:not(.match):not(.root)").addClass("unmatch");
            }
        }, 500);
    }

    /**
     * Drag helper. Constructs html-code that gets added to the page and
     * 'follows' the cursor while dragging. Mimics the design of the table.
     *
     * @param <jQuery> $node jQuery object of the dom element were dragging
     */
    function help($node) {
        var returnString = "
";
        if ($node.hasClass("leaf")) {
            returnString += "
	"
                + $node.text()
                + "
";
        } else {
            $node.find(".leaf").each(function () {
                returnString += "
	"
                    + $(this).text()
                    + "
";
            });
        }
        returnString += "
";
        return $(returnString);
    }

    /*************** Public methods ***************/

    /**
     * Adds the collapsible selection tree to the page at the given selector
     * and adds the dragging behaviour.
     *
     * @param <String> selectors.tree Selector of div where we want
     *          to add the tree
     * @param <String> selectors.tableDiv Selector of the div containing
     *          the genomes table
     * @param <String> selectors.treeSearch Selector of the div containing
     *          the tree search field
     */
    that.drawTree = function drawTree(selectors) {
        var treeSelector = selectors.tree,
            tableDivSelector = selectors.tableDiv,
            treeSearchSelector = selectors.treeSearch,
            $tree = $(treeSelector),
            $tableDiv = $(tableDivSelector),
            tree,
            items,
            i;

        // Add the root
        tree = d3.select(treeSelector)
            .append("ul")
            .append("li")
                .attr("class", "root not")
            .append("ul");

        // Add the lower nodes
        items = tree.selectAll("li").data(data)
            .enter()
            .append("li")
                .html(function (d) { return "" + taxa[d.key] + " (" + d.children + ")"; })
                .attr("title", "Class")
                .attr("class", "collapsibleListOpen")
                .attr("data-search", function (d) { return taxa[d.key]; })
            .append("ul");
        for (i = 1; i < 4; i++) {
            items = items.selectAll("li").data(function (d) { return d.values; })
                .enter()
                .append("li")
                    .html(function (d) { return "" + taxa[d.key] + " (" + d.children + ")"; })
                    .attr("title", titles[i])
                    .attr("class", "collapsibleListOpen")
                    .attr("data-search", function (d) { return taxa[d.key]; })
                .append("ul");
        }
        items = items.selectAll("li").data(function (d) { return d.values; })
            .enter()
            .append("li")
                .attr("class", "not leaf")
                .attr("title", function (d) { return "bioproject id: " + d.bioproject_id; })
                .attr("data-search", function (d) { return d.name.toLowerCase() + " " + d.bioproject_id; })
                .attr("data-bioproject_id", function (d) { return d.bioproject_id; })
                .html(function (d) { return "" + d.name + ""; });

        // Prevent accidental text selection
        $tree.find("li.root ul").disableSelection();

        // Add the search div as root
        $tree.find("li.root").prepend($(treeSearchSelector));

        // Expand or collapse a node when clicked
        $tree.find("li").click(function toggleExpand() {
            if (!$(this).hasClass("not")) {
                $(this).toggleClass("collapsibleListOpen collapsibleListClosed");
            }
            return false;
        });

        // Filter the tree 500ms after the last key press
        $(treeSearchSelector + " input").keyup(function keyUpped() {
            search($(this).val(), $tree);
        });

        // Make the nodes draggable using JQuery UI
        $tree.find("li").draggable({
            appendTo: tableDivSelector + " table",
            addClasses: false,
            refreshPositions: true,
            // Mimic the style of the table on the right
            helper: function startHelping(event) {
                return help($(this));
            },
            // Table on the right slides into view on drag start
            start: function startDragging(event, ui) {
                var pos = Math.max(0, window.pageYOffset - $tableDiv.offset().top + 16);
                $tableDiv.css("margin-top", pos + "px");
                $(event.target).draggable('option', 'refreshPositions', true);
                moving = true;
                moving2 = true;
                setTimeout(function () {moving = false; }, 800);
            },
            // Table on the right slides back to original position 1s after
            // drag stop
            stop: function stopDragging(event, ui) {
                setTimeout(function () {$tableDiv.css("margin-top", "0px"); }, 1000);
            },
            // Because the drop target slides in, we have to recalculate the
            // position of the target while dragging. This is computationally
            // expensive, so we stop recalculating once we know the target
            // stays in place
            drag: function whileDragging(event, ui) {
                if (!moving2) {
                    $(event.target).draggable('option', 'refreshPositions', false);
                }
                if (!moving) {
                    moving2 = false;
                }
            }
        });
    };

    // initialize the object
    init();

    return that;
};
<commit_msg>fix case sensitiveness of the search in the inner nodes of the selection tree. Closes #377<commit_after>/**
 * Creates a selectionTree object that represents a
 * selectable taxonomy tree using nested unordered lists
 *
 * @param <Array> args.data is an array of around 2500 objects with this format:
 *          {"bioproject_id":57587,"class_id":29547,"genus_id":194,
 *          "name":"Campylobacter jejuni","order_id":213849,"species_id":197}
 * @param <Hash> args.taxa is a list of key-value pairs mapping
 *          taxon id's to taxon names
 * @return <SelectionTree> that The constructed selectionTree object
 */
var constructSelectionTree = function constructSelectionTree(args) {
    /*************** Private variables ***************/

    var that = {},
        data = args.data,
        taxa = args.taxa,
        titles = ["Class", "Order", "Genus", "Species"];

    // Status vars used while dragging to determine if the
    // droptarget needs to be recalculated
    var moving = false,
        moving2 = false;

    /*************** Private methods ***************/

    /**
     * Initializes the data variables and calculates the children property
     * of all nodes in the data
     */
    function init() {
        // Uses a "group by" operator on the data array to create a nested array
        data = d3.nest()
            .key(function (d) { return d.class_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.order_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.genus_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .key(function (d) { return d.species_id; })
                .sortKeys(function (a, b) { return d3.ascending(taxa[a], taxa[b]); })
            .entries(data);
        calculateNumOfChildren(data);
        delete data.children;
    }

    /**
     * Calculates the number of leafs under every node in the given list by
     * calling the method recursively.
     *
     * The children property gets set for every node and cointains the
     * calculated number of children.
     *
     * @param <Array> list A list of nodes which all potentially have children
     *          stored in de values param.
     * @return <Hash> return The sum of the number of leafs for all nodes in
     *          given list.
     */
    function calculateNumOfChildren(list) {
        var result = 0,
            node,
            i;

        // Iterate over all nodes
        for (i = 0; i < list.length; i++) {
            node = list[i];

            // If the node has children, call recursively, else 1
            if (node.values !== undefined) {
                node.children = calculateNumOfChildren(node.values);
            } else {
                node.children = 1;
            }
            result += node.children;
        }
        list.children = result;
        return result;
    }

    /**
     * Filters the tree for a given search string if this method isn't call
     * for a second time in the next 500ms
     *
     * @param <String> searchString The string we want to search for
     * @param <jQuery> $tree jQuery object of the tree we want to filter
     */
    function search(searchString, $tree) {
        var text = searchString.toLowerCase();
        delay(function doSearch() {
            $tree.find("li").removeClass("match unmatch");
            if (text !== "") {
                $tree.find("li[data-search*='" + text + "']").addClass("match");
                $tree.find("li.match").parents("li")
                    .addClass("match")
                    .addClass("collapsibleListOpen")
                    .removeClass("collapsibleListClosed");
                $tree.find("li:not(.match):not(.root)").addClass("unmatch");
            }
        }, 500);
    }

    /**
     * Drag helper. Constructs html-code that gets added to the page and
     * 'follows' the cursor while dragging. Mimics the design of the table.
     *
     * @param <jQuery> $node jQuery object of the dom element were dragging
     */
    function help($node) {
        var returnString = "
";
        if ($node.hasClass("leaf")) {
            returnString += "
	"
                + $node.text()
                + "
";
        } else {
            $node.find(".leaf").each(function () {
                returnString += "
	"
                    + $(this).text()
                    + "
";
            });
        }
        returnString += "
";
        return $(returnString);
    }

    /*************** Public methods ***************/

    /**
     * Adds the collapsible selection tree to the page at the given selector
     * and adds the dragging behaviour.
     *
     * @param <String> selectors.tree Selector of div where we want
     *          to add the tree
     * @param <String> selectors.tableDiv Selector of the div containing
     *          the genomes table
     * @param <String> selectors.treeSearch Selector of the div containing
     *          the tree search field
     */
    that.drawTree = function drawTree(selectors) {
        var treeSelector = selectors.tree,
            tableDivSelector = selectors.tableDiv,
            treeSearchSelector = selectors.treeSearch,
            $tree = $(treeSelector),
            $tableDiv = $(tableDivSelector),
            tree,
            items,
            i;

        // Add the root
        tree = d3.select(treeSelector)
            .append("ul")
            .append("li")
                .attr("class", "root not")
            .append("ul");

        // Add the lower nodes
        items = tree.selectAll("li").data(data)
            .enter()
            .append("li")
                .html(function (d) { return "" + taxa[d.key] + " (" + d.children + ")"; })
                .attr("title", "Class")
                .attr("class", "collapsibleListOpen")
                .attr("data-search", function (d) { return taxa[d.key] ? taxa[d.key].toLowerCase() : "undefined"; })
            .append("ul");
        for (i = 1; i < 4; i++) {
            items = items.selectAll("li").data(function (d) { return d.values; })
                .enter()
                .append("li")
                    .html(function (d) { return "" + taxa[d.key] + " (" + d.children + ")"; })
                    .attr("title", titles[i])
                    .attr("class", "collapsibleListOpen")
                    .attr("data-search", function (d) { return taxa[d.key] ? taxa[d.key].toLowerCase() : "undefined"; })
                .append("ul");
        }
        items = items.selectAll("li").data(function (d) { return d.values; })
            .enter()
            .append("li")
                .attr("class", "not leaf")
                .attr("title", function (d) { return "bioproject id: " + d.bioproject_id; })
                .attr("data-search", function (d) { return d.name.toLowerCase() + " " + d.bioproject_id; })
                .attr("data-bioproject_id", function (d) { return d.bioproject_id; })
                .html(function (d) { return "" + d.name + ""; });

        // Prevent accidental text selection
        $tree.find("li.root ul").disableSelection();

        // Add the search div as root
        $tree.find("li.root").prepend($(treeSearchSelector));

        // Expand or collapse a node when clicked
        $tree.find("li").click(function toggleExpand() {
            if (!$(this).hasClass("not")) {
                $(this).toggleClass("collapsibleListOpen collapsibleListClosed");
            }
            return false;
        });

        // Filter the tree 500ms after the last key press
        $(treeSearchSelector + " input").keyup(function keyUpped() {
            search($(this).val(), $tree);
        });

        // Make the nodes draggable using JQuery UI
        $tree.find("li").draggable({
            appendTo: tableDivSelector + " table",
            addClasses: false,
            refreshPositions: true,
            // Mimic the style of the table on the right
            helper: function startHelping(event) {
                return help($(this));
            },
            // Table on the right slides into view on drag start
            start: function startDragging(event, ui) {
                var pos = Math.max(0, window.pageYOffset - $tableDiv.offset().top + 16);
                $tableDiv.css("margin-top", pos + "px");
                $(event.target).draggable('option', 'refreshPositions', true);
                moving = true;
                moving2 = true;
                setTimeout(function () {moving = false; }, 800);
            },
            // Table on the right slides back to original position 1s after
            // drag stop
            stop: function stopDragging(event, ui) {
                setTimeout(function () {$tableDiv.css("margin-top", "0px"); }, 1000);
            },
            // Because the drop target slides in, we have to recalculate the
            // position of the target while dragging. This is computationally
            // expensive, so we stop recalculating once we know the target
            // stays in place
            drag: function whileDragging(event, ui) {
                if (!moving2) {
                    $(event.target).draggable('option', 'refreshPositions', false);
                }
                if (!moving) {
                    moving2 = false;
                }
            }
        });
    };

    // initialize the object
    init();

    return that;
};
<|endoftext|>


<commit_before>const fs = require("fs");
const path = require("path");

var oldFile = "pso2Tools.db";
var newFile = "pso2db.db";

function upgradeDatabase(dbFile){
    var db = require("sqlite-sync");
    db.connect(dbFile)
    var commands = [
        "CREATE TABLE temp_table AS SELECT * FROM characters",
        "DROP TABLE characters",
        "CREATE TABLE IF NOT EXISTS `characters`(\
            `cid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\
            `CName` TEXT,\
            `lastTATime` TIMESTAMP,\
            `classLv` TEXT,\
            `memo` TEXT\
        );",
        `INSERT INTO characters(CName, lastTATime, classLv, memo) SELECT CName, strftime('%s',lastTATime), classLv, memo FROM temp_table`,
        `DROP TABLE temp_table`,
        "CREATE TABLE IF NOT EXISTS `installed_modules`(`module_name` TEXT PRIMARY KEY);",
        "INSERT INTO installed_modules(module_name) VALUES ('ClassLevel')",
        "INSERT INTO installed_modules(module_name) VALUES ('Memo')",
        "INSERT INTO installed_modules(module_name) VALUES ('TaCounter')",
    ]
    for(var cmd in commands){
        console.log(db.run(commands[cmd]));
    }
}

if(!path.isAbsolute(oldFile)){
    oldFile = path.join(__dirname,oldFile);
}

if(!path.isAbsolute(newFile)){
    newFile = path.join(__dirname,newFile);
}

if(fs.existsSync(oldFile)){
    fs.rename(oldFile, newFile, ()=>{upgradeDatabase(newFile);})
}else{
    upgradeDatabase(newFile);
}<commit_msg>Fixed timezone problem for timestamp type<commit_after>const fs = require("fs");
const path = require("path");

var oldFile = "pso2Tools.db";
var newFile = "pso2db.db";

function upgradeDatabase(dbFile){
    var db = require("sqlite-sync");
    var offset = (new Date().getTimezoneOffset())*60;
    var timeahead = offset<0;
    offset = Math.abs(offset);
    db.connect(dbFile)
    var commands = [
        "CREATE TABLE temp_table AS SELECT * FROM characters",
        "DROP TABLE characters",
        "CREATE TABLE IF NOT EXISTS `characters`(\
            `cid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\
            `CName` TEXT,\
            `lastTATime` TIMESTAMP,\
            `classLv` TEXT,\
            `memo` TEXT\
        );",
        "INSERT INTO characters(CName, lastTATime, classLv, memo) SELECT CName, strftime('%s',lastTATime)"+ (timeahead?"-":"+") + offset.toString() +", classLv, memo FROM temp_table",
        "DROP TABLE temp_table",
        "CREATE TABLE IF NOT EXISTS `installed_modules`(`module_name` TEXT PRIMARY KEY);",
        "INSERT INTO installed_modules(module_name) VALUES ('ClassLevel')",
        "INSERT INTO installed_modules(module_name) VALUES ('Memo')",
        "INSERT INTO installed_modules(module_name) VALUES ('TaCounter')",
    ]
    for(var cmd in commands){
        console.log(db.run(commands[cmd]));
    }
}

if(!path.isAbsolute(oldFile)){
    oldFile = path.join(__dirname,oldFile);
}

if(!path.isAbsolute(newFile)){
    newFile = path.join(__dirname,newFile);
}

if(fs.existsSync(oldFile)){
    fs.rename(oldFile, newFile, ()=>{upgradeDatabase(newFile);})
}else{
    upgradeDatabase(newFile);
}<|endoftext|>


<commit_before>if (!cbus.hasOwnProperty("server")) { cbus.server = {} }

(function() {
  const request = require("request");
  const x2j = require("xml2js");
  const path = require("path");

  cbus.server.getPodcastInfo = function(podcastUrl, callback) {
    var podcastData = {};

    request({
      url: podcastUrl,
      headers: require(path.join(__dirname, "../../request-headers.js")).REQUEST_HEADERS
    }, function(err, result, body) {
      x2j.parseString(body, function(err, result) {
        if (err) {
          console.log("error parsing xml", err);
          callback(null)
        } else {
          var channel = result.rss.channel[0];
          // console.log(channel);

          // title
          if (channel.title && channel.title[0]) {
            podcastData.title = channel.title[0];
          }
          // publisher
          if (channel["itunes:author"] && channel["itunes:author"][0]) {
            podcastData.publisher = channel["itunes:author"][0];
          }
          // description
          if (channel.description && channel.description[0]) {
            podcastData.description = channel.description[0];
          }
          // image
          if (channel["itunes:image"] && channel["itunes:image"][0]) {
            podcastData.image = channel["itunes:image"][0].$.href;
          }
          if (channel["image"] && channel["image"][0] &&
            channel["image"][0]["url"] && channel["image"][0]["url"][0]) {
            podcastData.image = channel["image"][0]["url"][0];
          }

          callback(podcastData);
        }
      });
    });
  }
}());
<commit_msg>Change order of xml elems checked for podcast image<commit_after>if (!cbus.hasOwnProperty("server")) { cbus.server = {} }

(function() {
  const request = require("request");
  const x2j = require("xml2js");
  const path = require("path");

  cbus.server.getPodcastInfo = function(podcastUrl, callback) {
    var podcastData = {};

    request({
      url: podcastUrl,
      headers: require(path.join(__dirname, "../../request-headers.js")).REQUEST_HEADERS
    }, function(err, result, body) {
      x2j.parseString(body, function(err, result) {
        if (err) {
          console.log("error parsing xml", err);
          callback(null)
        } else {
          var channel = result.rss.channel[0];
          // console.log(channel);

          // title
          if (channel.title && channel.title[0]) {
            podcastData.title = channel.title[0];
          }
          // publisher
          if (channel["itunes:author"] && channel["itunes:author"][0]) {
            podcastData.publisher = channel["itunes:author"][0];
          }
          // description
          if (channel.description && channel.description[0]) {
            podcastData.description = channel.description[0];
          }
          // image
          if (channel["image"] && channel["image"][0] &&
            channel["image"][0]["url"] && channel["image"][0]["url"][0]) {
            podcastData.image = channel["image"][0]["url"][0];
          } else if (channel["itunes:image"] && channel["itunes:image"][0]) {
            podcastData.image = channel["itunes:image"][0].$.href;
          }

          callback(podcastData);
        }
      });
    });
  }
}());
<|endoftext|>


<commit_before>/*
 *  jQuery prioritize events
 *
 *  A jQuery plugin that adds controls to the selected jQuery
 *  elements with a simple call.
 *
 *  Example:
 *
 *      $("img").imageUpload();
 *
 *  Copyright (c) jillix GmbH
 *  License: MIT License
 *
 * */
(function ($) {

   /*
    * $("[jQuery selector]").imageUpload({...});
    * */
    $.fn.imageUpload = function(options) {

        // defaults
        var settings = $.extend( {

            wrapContent: "
",

            inputFileName: "inputFile",
            inputFileClass: "inputFile",

            uploadButtonValue: "Upload",
            uploadButtonClass: "uploadButton",

            browseButtonClass: "browseButton",
            browseButtonValue: "Browse",

            formClass: "controlForm",

            hideFileInput: true,

            uploadIframe: ".uploadIframe",

            hover: true,

            addClass: "jQuery-image-upload"
        }, options);

        // selected jQuery objects
        var $self = this;

        // call image upload for each element
        if ($self.length > 1) {
            $self.each(function () {
                $(this).imageUpload(settings);
            });
            return $self;
        }

        $self.addClass(settings.addClass);

        // form action not provided
        if (!settings.formAction) {
            throw new Error ("Form action was not provided. Please provide it: $(...).imageUpload({formAction: '...'})");
        }

        // wrap
        if (!settings.hover) {
            $self.wrap(settings.wrapContent)
        }

        // create the controls div
        var $controls       = $("
").addClass("controls")
          , $fileInput      = $("<input>")
                                .attr("type", "file")
                                .addClass(settings.inputFileClass)
                                .attr("name", settings.inputFileName)

          , $uploadButton   = $("<input>")
                                .attr("type", "submit")
                                .addClass()
                                .attr("value", settings.uploadButtonValue)

          , $browseButton   = $("<input>")
                                .attr("type", "button")
                                .addClass(settings.browseButtonClass)
                                .attr("value", settings.browseButtonValue)
                                .on("click", function () { $fileInput.click(); })

          , $uploadIframe   = $("")
                                .attr("id", "uploadIframe-" + Math.random().toString(36).substring(5, 20).toUpperCase())
                                .hide()

          , $uploadForm     = $("<form>")
                                .addClass(settings.formClass)
                                .attr("target", $uploadIframe.attr("id"))
                                .attr("enctype", "multipart/form-data")
                                .attr("method", "post")
                                .attr("action", settings.formAction);

        // append controls to form
        $uploadForm.append([$browseButton, $fileInput, $uploadButton, $uploadIframe]);

        // hide file input
        if (settings.hideFileInput) {
            $fileInput.hide();
        } else {
            // hide browse button
            $browseButton.hide();
        }

        // append $form to $controls
        $controls.append($uploadForm);

        // form on submit
        $uploadForm.on("submit", function () {

            // get submiited form
            var $form = $(this);

            // unset the load handler
            $uploadIframe.off("load");

            // set it again
            $uploadIframe.on("load", function () {

                // get text from the page
                var result = $(this.contentWindow.document).text();

                // if no result, return
                if (!result) { return; }

                // verify file input value
                if (!$fileInput.val()) {
                    return;
                }

                // try to parse result
                try {
                    result = JSON.parse(result);
                } catch (e) {
                    // nothing to do
                }

                // set src of iframe
                $uploadIframe.attr("src", "");

                // upadte the image source
                $self.attr("src", result);

                // trigger image changed event
                $self.trigger("imageChanged");

                // replace the file input
                $fileInput.replaceWith($fileInput.clone(true));
            });
        });

        // no hover
        if (!settings.hover) {

            // append controls to image wrapper
            $self.parent().append($controls);
        } else {

            // get the self offset
            var offset = $self.offset();

            // set absolute position to controls and set the offset
            $controls.css({
                position: "absolute",
                top: offset.top,
                left: offset.left
            // add class to controls
            }).addClass("jQuery-image-upload-controls");

            // append controls to body
            $("body").append($controls.hide());

            // self on mouse enter
            $self.on("mouseenter", function () {

                // show controls
                $controls.show();
            });

            // on mouse leave
            $("body").on("mouseleave", "." + settings.addClass, function (e) {

                // get position
                var o = $self.offset()

                    // width
                  , w = $self.width()

                    // and the hegiht
                  , h = $self.height();

                // hide controls
                if ((e.pageX < o.left || e.pageX > o.left + w) ||
                    (e.pageY < o.top || e.pageY > o.top + h)) {
                    $controls.hide();
                }
            });
        }

        // return selected element
        return $self;
    };
})($);
<commit_msg>Set offset every time before show. The position of the element may be changed.<commit_after>/*
 *  jQuery prioritize events
 *
 *  A jQuery plugin that adds controls to the selected jQuery
 *  elements with a simple call.
 *
 *  Example:
 *
 *      $("img").imageUpload();
 *
 *  Copyright (c) jillix GmbH
 *  License: MIT License
 *
 * */
(function ($) {

   /*
    * $("[jQuery selector]").imageUpload({...});
    * */
    $.fn.imageUpload = function(options) {

        // defaults
        var settings = $.extend( {

            wrapContent: "
",

            inputFileName: "inputFile",
            inputFileClass: "inputFile",

            uploadButtonValue: "Upload",
            uploadButtonClass: "uploadButton",

            browseButtonClass: "browseButton",
            browseButtonValue: "Browse",

            formClass: "controlForm",

            hideFileInput: true,

            uploadIframe: ".uploadIframe",

            hover: true,

            addClass: "jQuery-image-upload"
        }, options);

        // selected jQuery objects
        var $self = this;

        // call image upload for each element
        if ($self.length > 1) {
            $self.each(function () {
                $(this).imageUpload(settings);
            });
            return $self;
        }

        $self.addClass(settings.addClass);

        // form action not provided
        if (!settings.formAction) {
            throw new Error ("Form action was not provided. Please provide it: $(...).imageUpload({formAction: '...'})");
        }

        // wrap
        if (!settings.hover) {
            $self.wrap(settings.wrapContent)
        }

        // create the controls div
        var $controls       = $("
").addClass("controls")
          , $fileInput      = $("<input>")
                                .attr("type", "file")
                                .addClass(settings.inputFileClass)
                                .attr("name", settings.inputFileName)

          , $uploadButton   = $("<input>")
                                .attr("type", "submit")
                                .addClass()
                                .attr("value", settings.uploadButtonValue)

          , $browseButton   = $("<input>")
                                .attr("type", "button")
                                .addClass(settings.browseButtonClass)
                                .attr("value", settings.browseButtonValue)
                                .on("click", function () { $fileInput.click(); })

          , $uploadIframe   = $("")
                                .attr("id", "uploadIframe-" + Math.random().toString(36).substring(5, 20).toUpperCase())
                                .hide()

          , $uploadForm     = $("<form>")
                                .addClass(settings.formClass)
                                .attr("target", $uploadIframe.attr("id"))
                                .attr("enctype", "multipart/form-data")
                                .attr("method", "post")
                                .attr("action", settings.formAction);

        // append controls to form
        $uploadForm.append([$browseButton, $fileInput, $uploadButton, $uploadIframe]);

        // hide file input
        if (settings.hideFileInput) {
            $fileInput.hide();
        } else {
            // hide browse button
            $browseButton.hide();
        }

        // append $form to $controls
        $controls.append($uploadForm);

        // form on submit
        $uploadForm.on("submit", function () {

            // get submiited form
            var $form = $(this);

            // unset the load handler
            $uploadIframe.off("load");

            // set it again
            $uploadIframe.on("load", function () {

                // get text from the page
                var result = $(this.contentWindow.document).text();

                // if no result, return
                if (!result) { return; }

                // verify file input value
                if (!$fileInput.val()) {
                    return;
                }

                // try to parse result
                try {
                    result = JSON.parse(result);
                } catch (e) {
                    // nothing to do
                }

                // set src of iframe
                $uploadIframe.attr("src", "");

                // upadte the image source
                $self.attr("src", result);

                // trigger image changed event
                $self.trigger("imageChanged");

                // replace the file input
                $fileInput.replaceWith($fileInput.clone(true));
            });
        });

        // no hover
        if (!settings.hover) {

            // append controls to image wrapper
            $self.parent().append($controls);
        } else {

            // set absolute position to controls and set the offset
            $controls.css({ position: "absolute" });

            // add class to controls
            $controls.addClass("jQuery-image-upload-controls");

            // append controls to body
            $("body").append($controls.hide());

            // self on mouse enter
            $self.on("mouseenter", function () {

                // get the self offset
                var offset = $self.offset();

                // set control possition
                $controls.css({
                    top: offset.top,
                    left: offset.left
                });

                // show controls
                $controls.show();
            });

            // on mouse leave
            $("body").on("mouseleave", "." + settings.addClass, function (e) {

                // get position
                var o = $self.offset()

                    // width
                  , w = $self.width()

                    // and the hegiht
                  , h = $self.height();

                // hide controls
                if ((e.pageX < o.left || e.pageX > o.left + w) ||
                    (e.pageY < o.top || e.pageY > o.top + h)) {
                    $controls.hide();
                }
            });
        }

        // return selected element
        return $self;
    };
})($);
<|endoftext|>


<commit_before>(function (exports) {

  // -- Group selectors
  var ps = function(selector){
    selector = selector || ''
    var cn = selector.split('.');
    var tag = false;
    if(selector[0] != '.') tag = cn[0];
    cn.splice(0, 1);
    var id = false;
    if(tag && tag[0] == '#') id = tag.split('#')[1];
    if(tag && id == '' && tag.indexOf('#') != -1){
      _tag = tag.split('#')
      tag = _tag[0]
      id = _tag[1]
    }
    if(id == '')
      for(var i = 0; i<cn.length;i++){
        var _id = cn[i].split('#')
        if(_id[1]){
          id = _id[1]
          cn[i] = _id[0]
          break;
        }
      }
    if(tag == '#'+id) tag = '';
    return {
      tag: tag,
      id: id,
      classList: cn
    }
  }

  // -- Query functions
  var qq = function(qs, root){
    if(root instanceof Array || root instanceof NodeList){
      var s = ps(qs);
      var arr = [].slice.call(root);
      var ret = [];
      for (var i = 0; i < arr.length; i++){
        is = true;
        if(arr[i] instanceof Element){
          if(s.tag && arr[i].tagName.toLowerCase()!=s.tag.toLowerCase()) is = false;
          if(s.id && arr[i].id != s.id) is = false;
          for (var j = 0; j < s.classList.length; j++)
            if(!arr[i].classList.contains(s.classList[j])) is = false;
          if(is) ret.push(arr[i]);
        }
      }
      return ret;
    }
    root = root instanceof Element ? root : document;
    if(qs instanceof Element) return [qs];
    if(qs instanceof NodeList || qs instanceof Array){
      var arr = [].slice.call(qs);
      var ret = [];
      for (var i = 0; i < arr.length; i++)
        if(arr[i] instanceof Element) ret.push(arr[i]);
      return ret;
    }
    var arr = [].slice.call(root.querySelectorAll(qs));
    var ret = [];
    for (var i = 0; i < arr.length; i++)
      if(arr[i] instanceof Element) ret.push(arr[i]);
    return ret;
  }
  var q = function(qs, root){
    return qq(qs, root)[0]||null;
  }
  Element.prototype.qq = function(qs){
    return qq(qs, this);
  }
  Element.prototype.q = function(qs){
    return q(qs, this);
  }

  //-- Create elements
  var e = function(selector){
    var s = ps(selector);
    var el = document.createElement(s.tag||'div');
    if(s.id) el.id = s.id;
    for (var i = 0; i < s.classList.length; i++)
      el.classList.add(s.classList[i]);
    return el;
  }
  var t = function(text){
    var e = document.createTextNode(text);
    return e;
  }
  Text.prototype.set = function (text) {
    this.nodeValue = text;
  }
  Text.prototype.get = function () {
    return this.nodeValue;
  }

  // -- Element actions
  Element.prototype.append = function (element) {
    this.appendChild(element);
  }
  Element.prototype.text = function (text) {
    if(!text) return this.textContent;
    if(text instanceof NodeList || text instanceof Array){
      var arr = [].slice.call(text);
      var _text = '';
      for (var i = 0; i < arr.length; i++){
        if(arr[i] instanceof Text) _text+= arr[i].get();
        else _text += arr[i].toString();
      }
      var e = t(_text);
      this.append(e);
      return e;
    }
    var nodes = this.childNodes;
    for (var i = 0; i < nodes.length; i++)
      nodes[i].remove();
    var e = t(text);
    this.append(e);
    return e;
  }
  Element.prototype.html = function (html) {
    if(!html) return this.innerHTML;
    var nodes = this.childNodes;
    for (var i = 0; i < nodes.length; i++)
      nodes[i].remove();
    if(html instanceof Element){
      this.append(html);
      return this.innerHTML;
    }
    if(html instanceof NodeList || html instanceof Array){
      var arr = [].slice.call(html);
      for (var i = 0; i < arr.length; i++)
        if(arr[i] instanceof Element || arr[i] instanceof Text)
          this.append(arr[i]);
      return this.innerHTML;
    }
    this.innerHTML = html;
    return this.innerHTML;
  }

  // -- Observe elements
  Element.prototype.observe = function () {
    var self = this;
    if(!this._observer){
      this._observerHandlers = []
      this._observer = new MutationObserver(function(mutations) {
        for (var i = 0; i < self._observerHandlers.length; i++) {
          for (var j = 0; j < mutations.length; j++) {
            var mutation = mutations[j];
            self._observerHandlers[i].call(self, mutation);
          }
        }
      });
      var config = {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true,
        attributeOldValue: true,
        characterDataOldValue: true
      }
      this._observer.observe(this, config);
    }
  }
  Element.prototype.stopObserving = function () {
    if(this._observer){
      this._observer.disconnect();
      delete this._observer;
    }
  }

  // -- Path
  Element.prototype.path = function (){
    var root = this;
    var path = [];
    while (root.parentNode){
      if (root.id != ''){
        path.unshift('#' + root.id);
        break;
      }
      if (root==root.ownerDocument.documentElement) path.unshift(root.tagName.toLowerCase());
      else{
        for (var i = 1, e = root; e.previousElementSibling; e = e.previousElementSibling, i++);
        path.unshift(root.tagName.toLowerCase() + ':nth-child(' + i + ')');
      }
      root=root.parentNode;
    }
    return path.join(' > ');
  }

  // -- Event
  var _ev = function(event, next){
    var self = this;
    this.addEventListener(event, function(ev){next.call(self,ev)});
  }
  Text.prototype.on = _ev;
  Window.prototype.on = _ev;
  Document.prototype.on = _ev;
  FormData.prototype.on = _ev;
  FileReader.prototype.on = _ev;
  XMLHttpRequest.prototype.on = _ev;
  AudioNode.prototype.on = _ev;
  AudioContext.prototype.on = _ev;

  // -- Element events
  Element.prototype.on = function(event, next){
      switch (event) {
        case 'mutation':
          this._observerHandlers.push(next);
          break;
        default:
          _ev.apply(this, arguments);
      }
  }

  // -- Changing css
  Element.prototype.css = function(css, ignoreDefaults){
    if(typeof css === 'boolean') return this.css(null, css);
    if(typeof css === 'string') return this.css(null, ignoreDefaults)[css];
    if(!css){
      css = getComputedStyle(this);
      var ret = {};
      if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
        if(ignoreDefaults){
          var defaults = getComputedStyle(e(this.tagName));
          for (var k in css) {
            if (!css.hasOwnProperty(k) && isNaN(+k) && css[k] != '' && css[k] != defaults[k]) {
               ret[k] = css[k];
            }
          }
          return ret;
        }
        for (var k in css) {
          if (!css.hasOwnProperty(k) && isNaN(+k) && css[k] != '') {
             ret[k] = css[k];
          }
        }
      } else {
        if(ignoreDefaults){
          var defaults = getComputedStyle(e(this.tagName));
          for (var k in css) {
            if (css.hasOwnProperty(k) && isNaN(+k) && css[k] != '' && css[k] != defaults[k]) {
               ret[k] = css[k];
            }
          }
          return ret;
        }
        for (var k in css) {
          if (css.hasOwnProperty(k) && isNaN(+k) && css[k] != '') {
             ret[k] = css[k];
          }
        }
      }
      return ret;
    };
    var self = this;
    for (var _k in css) {
      if (css.hasOwnProperty(_k)) {
        self.style[_k] = css[_k]
      }
    }
  }

  exports.q = q;
  exports.qq = qq;
  exports.ps = ps;
  exports.e = e;
  exports.t = t;

})(window);
<commit_msg>Added longer full function names<commit_after>(function (exports) {

  // -- Parse selectors
  var ps = function(selector){
    selector = selector || ''
    var cn = selector.split('.');
    var tag = false;
    if(selector[0] != '.') tag = cn[0];
    cn.splice(0, 1);
    var id = false;
    if(tag && tag[0] == '#') id = tag.split('#')[1];
    if(tag && id == '' && tag.indexOf('#') != -1){
      _tag = tag.split('#')
      tag = _tag[0]
      id = _tag[1]
    }
    if(id == '')
      for(var i = 0; i<cn.length;i++){
        var _id = cn[i].split('#')
        if(_id[1]){
          id = _id[1]
          cn[i] = _id[0]
          break;
        }
      }
    if(tag == '#'+id) tag = '';
    return {
      tag: tag,
      id: id,
      classList: cn
    }
  }

  // -- Query functions
  var qq = function(qs, root){
    if(root instanceof Array || root instanceof NodeList){
      var s = ps(qs);
      var arr = [].slice.call(root);
      var ret = [];
      for (var i = 0; i < arr.length; i++){
        is = true;
        if(arr[i] instanceof Element){
          if(s.tag && arr[i].tagName.toLowerCase()!=s.tag.toLowerCase()) is = false;
          if(s.id && arr[i].id != s.id) is = false;
          for (var j = 0; j < s.classList.length; j++)
            if(!arr[i].classList.contains(s.classList[j])) is = false;
          if(is) ret.push(arr[i]);
        }
      }
      return ret;
    }
    root = root instanceof Element ? root : document;
    if(qs instanceof Element) return [qs];
    if(qs instanceof NodeList || qs instanceof Array){
      var arr = [].slice.call(qs);
      var ret = [];
      for (var i = 0; i < arr.length; i++)
        if(arr[i] instanceof Element) ret.push(arr[i]);
      return ret;
    }
    var arr = [].slice.call(root.querySelectorAll(qs));
    var ret = [];
    for (var i = 0; i < arr.length; i++)
      if(arr[i] instanceof Element) ret.push(arr[i]);
    return ret;
  }
  var q = function(qs, root){
    return qq(qs, root)[0]||null;
  }
  Element.prototype.qq = function(qs){
    return qq(qs, this);
  }
  Element.prototype.q = function(qs){
    return q(qs, this);
  }

  //-- Create elements
  var e = function(selector){
    var s = ps(selector);
    var el = document.createElement(s.tag||'div');
    if(s.id) el.id = s.id;
    for (var i = 0; i < s.classList.length; i++)
      el.classList.add(s.classList[i]);
    return el;
  }
  var t = function(text){
    var e = document.createTextNode(text);
    return e;
  }
  Text.prototype.set = function (text) {
    this.nodeValue = text;
  }
  Text.prototype.get = function () {
    return this.nodeValue;
  }

  // -- Element actions
  Element.prototype.append = function (element) {
    this.appendChild(element);
  }
  Element.prototype.text = function (text) {
    if(!text) return this.textContent;
    if(text instanceof NodeList || text instanceof Array){
      var arr = [].slice.call(text);
      var _text = '';
      for (var i = 0; i < arr.length; i++){
        if(arr[i] instanceof Text) _text+= arr[i].get();
        else _text += arr[i].toString();
      }
      var e = t(_text);
      this.append(e);
      return e;
    }
    var nodes = this.childNodes;
    for (var i = 0; i < nodes.length; i++)
      nodes[i].remove();
    var e = t(text);
    this.append(e);
    return e;
  }
  Element.prototype.html = function (html) {
    if(!html) return this.innerHTML;
    var nodes = this.childNodes;
    for (var i = 0; i < nodes.length; i++)
      nodes[i].remove();
    if(html instanceof Element){
      this.append(html);
      return this.innerHTML;
    }
    if(html instanceof NodeList || html instanceof Array){
      var arr = [].slice.call(html);
      for (var i = 0; i < arr.length; i++)
        if(arr[i] instanceof Element || arr[i] instanceof Text)
          this.append(arr[i]);
      return this.innerHTML;
    }
    this.innerHTML = html;
    return this.innerHTML;
  }

  // -- Observe elements
  Element.prototype.observe = function () {
    var self = this;
    if(!this._observer){
      this._observerHandlers = []
      this._observer = new MutationObserver(function(mutations) {
        for (var i = 0; i < self._observerHandlers.length; i++) {
          for (var j = 0; j < mutations.length; j++) {
            var mutation = mutations[j];
            self._observerHandlers[i].call(self, mutation);
          }
        }
      });
      var config = {
        attributes: true,
        childList: true,
        characterData: true,
        subtree: true,
        attributeOldValue: true,
        characterDataOldValue: true
      }
      this._observer.observe(this, config);
    }
  }
  Element.prototype.stopObserving = function () {
    if(this._observer){
      this._observer.disconnect();
      delete this._observer;
    }
  }

  // -- Path
  Element.prototype.path = function (){
    var root = this;
    var path = [];
    while (root.parentNode){
      if (root.id != ''){
        path.unshift('#' + root.id);
        break;
      }
      if (root==root.ownerDocument.documentElement) path.unshift(root.tagName.toLowerCase());
      else{
        for (var i = 1, e = root; e.previousElementSibling; e = e.previousElementSibling, i++);
        path.unshift(root.tagName.toLowerCase() + ':nth-child(' + i + ')');
      }
      root=root.parentNode;
    }
    return path.join(' > ');
  }

  // -- Event
  var _ev = function(event, next){
    var self = this;
    this.addEventListener(event, function(ev){next.call(self,ev)});
  }
  Text.prototype.on = _ev;
  Window.prototype.on = _ev;
  Document.prototype.on = _ev;
  FormData.prototype.on = _ev;
  FileReader.prototype.on = _ev;
  XMLHttpRequest.prototype.on = _ev;
  AudioNode.prototype.on = _ev;
  AudioContext.prototype.on = _ev;

  // -- Element events
  Element.prototype.on = function(event, next){
      switch (event) {
        case 'mutation':
          this._observerHandlers.push(next);
          break;
        default:
          _ev.apply(this, arguments);
      }
  }

  // -- Changing css
  Element.prototype.css = function(css, ignoreDefaults){
    if(typeof css === 'boolean') return this.css(null, css);
    if(typeof css === 'string') return this.css(null, ignoreDefaults)[css];
    if(!css){
      css = getComputedStyle(this);
      var ret = {};
      if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){
        if(ignoreDefaults){
          var defaults = getComputedStyle(e(this.tagName));
          for (var k in css) {
            if (!css.hasOwnProperty(k) && isNaN(+k) && css[k] != '' && css[k] != defaults[k]) {
               ret[k] = css[k];
            }
          }
          return ret;
        }
        for (var k in css) {
          if (!css.hasOwnProperty(k) && isNaN(+k) && css[k] != '') {
             ret[k] = css[k];
          }
        }
      } else {
        if(ignoreDefaults){
          var defaults = getComputedStyle(e(this.tagName));
          for (var k in css) {
            if (css.hasOwnProperty(k) && isNaN(+k) && css[k] != '' && css[k] != defaults[k]) {
               ret[k] = css[k];
            }
          }
          return ret;
        }
        for (var k in css) {
          if (css.hasOwnProperty(k) && isNaN(+k) && css[k] != '') {
             ret[k] = css[k];
          }
        }
      }
      return ret;
    };
    var self = this;
    for (var _k in css) {
      if (css.hasOwnProperty(_k)) {
        self.style[_k] = css[_k]
      }
    }
  }

  exports.q = exports.query = q;
  exports.qq = exports.queryAll = qq;
  exports.ps = exports.parseSelectors = ps;
  exports.e = exports.element = e;
  exports.t = exports.text = t;

})(window);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Ericsson AB. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

var domObject = (function () {

    function createAttributeDescriptor(name, attributes) {
        return {
            "get": function () {
                var attribute = attributes[name];
                return typeof attribute == "function" ? attribute() : attribute;
            },
            "enumerable": true
        };
    }

    return {
        "addReadOnlyAttributes": function (target, attributes) {
            for (var name in attributes)
                Object.defineProperty(target, name, createAttributeDescriptor(name, attributes));
        },

        "addConstants": function (target, constants) {
            for (var name in constants)
                Object.defineProperty(target, name, {
                    "value": constants[name],
                    "enumerable": true
                });
        }
    };
})();

function EventTarget(attributes) {
    var _this = this;
    var listenersMap = {};

    if (attributes)
        addEventListenerAttributes(this, attributes);

    this.addEventListener = function (type, listener, useCapture) {
        if (typeof(listener) != "function")
            throw new TypeError("listener argument (" + listener + ") is not a function");
        var listeners = listenersMap[type];
        if (!listeners)
            listeners = listenersMap[type] = [];

        if (listeners.indexOf(listener) < 0)
            listeners.push(listener);
    };

    this.removeEventListener = function (type, listener, useCapture) {
        var listeners = listenersMap[type];
        if (!listeners)
            return;

        var i = listeners.indexOf(listener);
        if (i >= 0)
            listeners.splice(i, 1);
    };

    this.dispatchEvent = function (evt) {
        var listeners = [];

        var attributeListener = _this["on" + evt.type];
        if (attributeListener)
            listeners.push(attributeListener);

        if (listenersMap[evt.type])
            Array.prototype.push.apply(listeners, listenersMap[evt.type]);

        var errors = [];
        var result = true;
        listeners.forEach(function (listener) {
            try {
                result = !(listener(evt) === false) && result;
            } catch (e) {
                errors.push(e);
            }
        });

        errors.forEach(function (e) {
            setTimeout(function () {
                throw e;
            });
        });

        return result;
    };

    function addEventListenerAttributes(target, attributes) {
        for (var name in attributes)
            Object.defineProperty(target, name, createEventListenerDescriptor(name, attributes));
    }

    function createEventListenerDescriptor(name, attributes) {
        return {
            "get": function () { return attributes[name]; },
            "set": function (cb) { attributes[name] = (typeof(cb) == "function") ? cb : null; },
            "enumerable": true
        };
    }
}

function checkDictionary(name, dict, typeMap) {
    for (var memberName in dict) {
        if (!dict.hasOwnProperty(memberName) || !typeMap.hasOwnProperty(memberName))
            continue;

        var message = name + ": Dictionary member " + memberName;
        checkType(message, dict[memberName], typeMap[memberName]);
    }
}

function checkArguments(name, argsTypeTemplate, numRequired, args) {
    if (args.length < numRequired) {
        throw new TypeError(name + ": Too few arguments (got " + args.length + " expected " +
            numRequired + ")");
    }

    var typeTemplates = argsTypeTemplate.split(/\s*,\s*/);

    for (var i = 0; i < args.length && i < typeTemplates.length; i++) {
        var message = name + ": Argument " + (i + 1);
        checkType(message, args[i], typeTemplates[i]);
    }
}

function checkType(name, value, typeTemplate) {
    var expectedTypes = typeTemplate.split(/\s*\|\s*/);
    if (!canConvert(value, expectedTypes)) {
        throw new TypeError(name + " is of wrong type (expected " +
            expectedTypes.join(" or ") + ")");
    }
}

function canConvert(value, expectedTypes) {
    var type = typeof value;
    for (var i = 0; i < expectedTypes.length; i++) {
        var expectedType = expectedTypes[i];
        if (expectedType == "string" || expectedType == "boolean")
            return true; // type conversion will never throw
        if (expectedType == "number") {
            var asNumber = +value;
            if (!isNaN(asNumber) && asNumber != -Infinity && asNumber != Infinity)
                return true;
        }
        if (type == "object") {
            if (expectedType == "object")
                return true;
            // could be a specific object type or host object (e.g. Array)
            var constructor = self[expectedType];
            if (constructor && value instanceof constructor)
                return true;
        }
        if (type == expectedType && expectedType == "function")
            return true;
    }
    return false;
}

function randomString() {
    var randomValues = new Uint8Array(27);
    crypto.getRandomValues(randomValues);
    return btoa(String.fromCharCode.apply(null, randomValues));
}

function createError(name, message) {
    var constructor = self[name] || self.Error;
    var error = new constructor(message);
    error.name = name;
    return error;
}

function entityReplace(str) {
    return escape(str).replace(/%([0-9A-F]{2})/g, function (match) {
        return "&#" + parseInt(match.substr(1), 16) + ";"
    });
}
<commit_msg>domutils.js: Expose functions that return type check error strings<commit_after>/*
 * Copyright (C) 2014 Ericsson AB. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

"use strict";

var domObject = (function () {

    function createAttributeDescriptor(name, attributes) {
        return {
            "get": function () {
                var attribute = attributes[name];
                return typeof attribute == "function" ? attribute() : attribute;
            },
            "enumerable": true
        };
    }

    return {
        "addReadOnlyAttributes": function (target, attributes) {
            for (var name in attributes)
                Object.defineProperty(target, name, createAttributeDescriptor(name, attributes));
        },

        "addConstants": function (target, constants) {
            for (var name in constants)
                Object.defineProperty(target, name, {
                    "value": constants[name],
                    "enumerable": true
                });
        }
    };
})();

function EventTarget(attributes) {
    var _this = this;
    var listenersMap = {};

    if (attributes)
        addEventListenerAttributes(this, attributes);

    this.addEventListener = function (type, listener, useCapture) {
        if (typeof(listener) != "function")
            throw new TypeError("listener argument (" + listener + ") is not a function");
        var listeners = listenersMap[type];
        if (!listeners)
            listeners = listenersMap[type] = [];

        if (listeners.indexOf(listener) < 0)
            listeners.push(listener);
    };

    this.removeEventListener = function (type, listener, useCapture) {
        var listeners = listenersMap[type];
        if (!listeners)
            return;

        var i = listeners.indexOf(listener);
        if (i >= 0)
            listeners.splice(i, 1);
    };

    this.dispatchEvent = function (evt) {
        var listeners = [];

        var attributeListener = _this["on" + evt.type];
        if (attributeListener)
            listeners.push(attributeListener);

        if (listenersMap[evt.type])
            Array.prototype.push.apply(listeners, listenersMap[evt.type]);

        var errors = [];
        var result = true;
        listeners.forEach(function (listener) {
            try {
                result = !(listener(evt) === false) && result;
            } catch (e) {
                errors.push(e);
            }
        });

        errors.forEach(function (e) {
            setTimeout(function () {
                throw e;
            });
        });

        return result;
    };

    function addEventListenerAttributes(target, attributes) {
        for (var name in attributes)
            Object.defineProperty(target, name, createEventListenerDescriptor(name, attributes));
    }

    function createEventListenerDescriptor(name, attributes) {
        return {
            "get": function () { return attributes[name]; },
            "set": function (cb) { attributes[name] = (typeof(cb) == "function") ? cb : null; },
            "enumerable": true
        };
    }
}

function checkDictionary(name, dict, typeMap) {
    for (var memberName in dict) {
        if (!dict.hasOwnProperty(memberName) || !typeMap.hasOwnProperty(memberName))
            continue;

        var message = name + ": Dictionary member " + memberName;
        checkType(message, dict[memberName], typeMap[memberName]);
    }
}

function checkArguments(name, argsTypeTemplate, numRequired, args) {
    var error = getArgumentsError(argsTypeTemplate, numRequired, args);
    if (error)
        throw createError("TypeError", name + ": " + error);
}

function checkType(name, value, typeTemplate) {
    var error = getTypeError(name, value, typeTemplate);
    if (error)
        throw createError("TypeError", name + ": " + error);
}

function getArgumentsError(argsTypeTemplate, numRequired, args) {
    if (args.length < numRequired)
        return "Too few arguments (got " + args.length + " expected " + numRequired + ")";

    var typeTemplates = argsTypeTemplate.split(/\s*,\s*/);

    for (var i = 0; i < args.length && i < typeTemplates.length; i++) {
        var prefix = "Argument " + (i + 1);
        var error = getTypeError(prefix, args[i], typeTemplates[i]);
        if (error)
            return error;
    }
    return null;
}

function getTypeError(prefix, value, typeTemplate) {
    var expectedTypes = typeTemplate.split(/\s*\|\s*/);
    if (!canConvert(value, expectedTypes))
        return prefix + " is of wrong type (expected " + expectedTypes.join(" or ") + ")";
    return null;
}

function canConvert(value, expectedTypes) {
    var type = typeof value;
    for (var i = 0; i < expectedTypes.length; i++) {
        var expectedType = expectedTypes[i];
        if (expectedType == "string" || expectedType == "boolean")
            return true; // type conversion will never throw
        if (expectedType == "number") {
            var asNumber = +value;
            if (!isNaN(asNumber) && asNumber != -Infinity && asNumber != Infinity)
                return true;
        }
        if (type == "object") {
            if (expectedType == "object")
                return true;
            // could be a specific object type or host object (e.g. Array)
            var constructor = self[expectedType];
            if (constructor && value instanceof constructor)
                return true;
        }
        if (type == expectedType && expectedType == "function")
            return true;
    }
    return false;
}

function randomString() {
    var randomValues = new Uint8Array(27);
    crypto.getRandomValues(randomValues);
    return btoa(String.fromCharCode.apply(null, randomValues));
}

function createError(name, message) {
    var constructor = self[name] || self.Error;
    var error = new constructor(message);
    error.name = name;
    return error;
}

function entityReplace(str) {
    return escape(str).replace(/%([0-9A-F]{2})/g, function (match) {
        return "&#" + parseInt(match.substr(1), 16) + ";"
    });
}
<|endoftext|>


<commit_before>import CanvasControl from './jsiso/canvas/Control';
import CanvasInput from './jsiso/canvas/Input';
import imgLoader from './jsiso/img/load';
import jsonLoader from './jsiso/json/load';
import TileField from './jsiso/tile/Field';
import pathfind from './jsiso/pathfind/pathfind';

import Player from './player';
import ActionExecutor from './action';

let requestAnimFrame = (function() {
  return window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame  ||
  window.mozRequestAnimationFrame     ||
  window.oRequestAnimationFrame       ||
  window.msRequestAnimationFrame      ||
  function(callback, element) {
    window.setTimeout(callback, 1000 / 60);
  };
})();

const ELEMENT_NAMES = {
  containerName: 'container',
  frameName: 'text-frame',
  messageName: 'text-message',
  indicatorName: 'text-indicator'
};

let appendHtml = (el, str) => {
  let div = document.createElement('div');
  div.innerHTML = str;
  while (div.children.length > 0) {
    el.appendChild(div.children[0]);
  }
}

let createElements = (container, names, outputEnabled=false) => {
  let elements = '

';
  if (outputEnabled) {
    elements += '\

\
        \
        ▼\

';
  }
  appendHtml(container, elements);
}

export default function TileEngine (x, y, xrange, yrange, overrides) {
  let self = this;
  overrides = Object.assign({}, overrides);

  let parent = overrides.parent || document.body;
  let elementNames = Object.assign(ELEMENT_NAMES, overrides.customElementNames);
  if (!overrides.useCustomElements) {
    createElements(parent, elementNames, overrides.enableTextOutput);
  }
  const container = document.getElementById(elementNames.containerName);

  let textMessages = [];
  const textMessageFrame = document.getElementById(elementNames.frameName);
  const textMessage = document.getElementById(elementNames.messageName);
  const textIndicator = document.getElementById(elementNames.indicatorName)

  const controlWidth = container.clientWidth;
  const controlHeight = container.clientHeight;
  const context = CanvasControl.create("canvas", controlWidth, controlHeight, {}, elementNames.containerName, true);

  let backgroundLayers = [];
  let foregroundLayers = [];

  let paused = false;
  let mapLayers = [];
  let players = [];
  let playerMap = {};

  let actionExecutor = new ActionExecutor();
  actionExecutor.registerAction('toggleTile', (options, engine, player) => {
    let layers = mapLayers.filter((layer) => layer.zIndex === player.properties.zIndex);
    layers.forEach((layer) => {
      let currentTile = layer.getTile(options.target.x, options.target.y);
      let currentIndex = options.tiles.indexOf(currentTile);
      layer.setTile(options.target.x, options.target.y, options.tiles[(currentIndex + 1) % options.tiles.length]);
    })
  });

  let clearText = function () {};
  let displayText = function () {};
  let drawMessages = function () {};

  if (overrides.enableTextOutput) {
    textMessageFrame.onclick = () => {
      if (paused) {
        drawMessages();
      }
    };

    clearText = () => {
      textMessages = [];
      textMessageFrame.classList.remove("in");
      textMessage.innerHTML = "";
      textIndicator.classList.remove("in");
      if (paused) {
        unpause();
      }
    }

    displayText = (text) => {
      textMessages = textMessages.concat(text);
    }

    drawMessages = () => {
      if (textMessages.length > 0) {
        pause();
        let text = textMessages.splice(0, 1)[0];
        textMessage.innerHTML = text;
        if (!("in" in textMessageFrame.classList)) {
          textMessageFrame.classList.add("in");
        }
        if (textMessages.length >= 1) {
          textIndicator.classList.add("in");
        } else {
          textIndicator.classList.remove("in");
        }
      } else {
        clearText();
      }
    }
  }

  const input = new CanvasInput(document, CanvasControl());
  if (overrides.enableMouseInput) {
    input.mouse_action(function(coords) {
      if (paused) {
        drawMessages()
      } else {
        let player = getCharacter('player');
        let layer = player.properties.layer;
        let t = layer.applyMouseFocus(coords.x, coords.y);
        player.goTo(t.x, t.y);
        if (Math.abs(t.x - player.getTile().x) + Math.abs(t.y - player.getTile().y) === 1) {
          interact(player, t);
        }
      }
    });
  }

  if (overrides.enableKeyboardInput) {
    input.keyboard(function(pressed, status) {
      let player = getCharacter('player');
      if (status) {
        if (paused) {
          if ([13, 32].indexOf(pressed) >= 0) {
            drawMessages();
          }
        } else {
          switch (pressed) {
            case 37: player.moveTo(player.getTile().x - 1, player.getTile().y); break;
            case 38: player.moveTo(player.getTile().x, player.getTile().y - 1); break;
            case 39: player.moveTo(player.getTile().x + 1, player.getTile().y); break;
            case 40: player.moveTo(player.getTile().x, player.getTile().y + 1); break;
            case 13: case 32: interact(player, player.getLookedAtTile()); break;
          }
        }
      }
    });
  }

  let getActions = (player=null) => {
    let layers = mapLayers;
    if (player !== null) {
      layers = layers.filter((layer) => layer.zIndex === player.properties.zIndex);
    }
    let actions = [];
    layers.forEach((layer) => actions = actions.concat(layer.actions || []));
    return actions;
  }

  let interact = (player, tile) => {
    if (!player.isMoving()) {
      getActions(player)
        .filter((action) => action.type !== actionExecutor.TYPE_POSITIONAL)
        .filter((action) => action.x === tile.x && action.y == tile.y)
        .forEach((action) => actionExecutor.execute(action, self, player));
    }
  };

  let pause = () => {
    paused = true;
  }

  let unpause = () => {
    if (paused) {
      paused = false;
      draw();
    }
  }

  let getCharacter = (id) => playerMap[id];

  let setPlayerLighting = (tile) => {
    mapLayers.forEach((layer) => layer.setLight(tile.x, tile.y));
  }

  let drawLayer = (layer) => {
    for (let i = 0; i < (layer.width || xrange); i++) {
      for (let j = 0; j < (layer.height || yrange); j++) {
        layer.draw(i, j, void 0, (layer.x || x), (layer.y || y));
      }
    }
  }

  let previousTime = 0;
  let timeToDraw = (time) => !overrides.lockedFrameRate || (time - previousTime) >= 1000 / overrides.lockedFrameRate;

  let draw = (time) => {
    if (!timeToDraw(time)) {
      requestAnimationFrame(draw);
    } else {
      previousTime = time;
      context.clearRect(0, 0, controlWidth, controlHeight);
      let thingsToDraw = mapLayers.concat(players).sort((a, b) => a.zIndex > b.zIndex);
      for (let thing of thingsToDraw) {
        if (thing instanceof Player) {
          thing.draw();
          thing.move();
          if (thing.useLighting) {
            setPlayerLighting(thing.getTile());
          }
        } else {
          if (thing.visible) {
            drawLayer(thing);
          }
        }
      }
      drawMessages();
      if (!paused) {
        requestAnimationFrame(draw);
      }
    }
  }

  let initLayer = (layer) => {
    let mapLayer = new TileField(context, controlWidth, controlHeight);
    mapLayer.setup(layer);
    mapLayer.flip("horizontal");
    mapLayer.rotate("left");
    mapLayer.setLightmap(layer.lightmap);
    mapLayer = Object.assign(mapLayer, layer);
    return mapLayer;
  }

  let computeOnce = (fn) => {
    var instance = void 0;
    return function () {
      if (instance === void 0) {
        instance = fn.apply(this, arguments);
      }
      return instance;
    }
  }

  let createEmptyLayer = computeOnce((map) => {
    let layer = {
      width: map.width,
      height: map.height,
      layout: Array(map.width * map.height).fill(0)
    }
    return initLayer(layer);
  });

  let init = (map) => {
    mapLayers = map.layers.map(initLayer);
    draw();
    let promises = [];
    let characters = map.characters || {};
    for (let characterId of Object.keys(characters)) {
      let playerOptions = characters[characterId];
      if (playerOptions) {
        promises.push(imgLoader([{
          graphics: [playerOptions.sprites],
          spritesheet: {
            width: playerOptions.width,
            height: playerOptions.height
          }
        }]).then((playerImages) => {
          playerOptions.files = playerImages[0].files;
          playerOptions.layer = mapLayers[0];
          playerOptions.pathfindingLayer = mapLayers[playerOptions.pathfindingLayer] || createEmptyLayer(map);
          playerOptions.tileWidth = map.tileWidth;
          playerOptions.tileHeight = map.tileHeight;

          let player = new Player(context, playerOptions, playerOptions.x, playerOptions.y, pathfind);
          player.on("changeTile", (p, tile) => {
            getActions().filter((action) => action.type === actionExecutor.TYPE_POSITIONAL).forEach((action) => {
              if (action.x === tile.x && action.y === tile.y) {
                actionExecutor.execute(action, self, p);
              }
            })
          });
          players.push(player);
          playerMap[characterId] = player;
        }));
      }
    }
    return Promise.all(promises);
  }

  this.init = init;
  this.displayText = displayText;
  this.pause = pause;
  this.unpause = unpause;
  this.getCharacter = getCharacter;

  this.actionExecutor = actionExecutor;
}
<commit_msg>Don't restrict actions to layer<commit_after>import CanvasControl from './jsiso/canvas/Control';
import CanvasInput from './jsiso/canvas/Input';
import imgLoader from './jsiso/img/load';
import jsonLoader from './jsiso/json/load';
import TileField from './jsiso/tile/Field';
import pathfind from './jsiso/pathfind/pathfind';

import Player from './player';
import ActionExecutor from './action';

let requestAnimFrame = (function() {
  return window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame  ||
  window.mozRequestAnimationFrame     ||
  window.oRequestAnimationFrame       ||
  window.msRequestAnimationFrame      ||
  function(callback, element) {
    window.setTimeout(callback, 1000 / 60);
  };
})();

const ELEMENT_NAMES = {
  containerName: 'container',
  frameName: 'text-frame',
  messageName: 'text-message',
  indicatorName: 'text-indicator'
};

let appendHtml = (el, str) => {
  let div = document.createElement('div');
  div.innerHTML = str;
  while (div.children.length > 0) {
    el.appendChild(div.children[0]);
  }
}

let createElements = (container, names, outputEnabled=false) => {
  let elements = '

';
  if (outputEnabled) {
    elements += '\

\
        \
        ▼\

';
  }
  appendHtml(container, elements);
}

export default function TileEngine (x, y, xrange, yrange, overrides) {
  let self = this;
  overrides = Object.assign({}, overrides);

  let parent = overrides.parent || document.body;
  let elementNames = Object.assign(ELEMENT_NAMES, overrides.customElementNames);
  if (!overrides.useCustomElements) {
    createElements(parent, elementNames, overrides.enableTextOutput);
  }
  const container = document.getElementById(elementNames.containerName);

  let textMessages = [];
  const textMessageFrame = document.getElementById(elementNames.frameName);
  const textMessage = document.getElementById(elementNames.messageName);
  const textIndicator = document.getElementById(elementNames.indicatorName)

  const controlWidth = container.clientWidth;
  const controlHeight = container.clientHeight;
  const context = CanvasControl.create("canvas", controlWidth, controlHeight, {}, elementNames.containerName, true);

  let backgroundLayers = [];
  let foregroundLayers = [];

  let paused = false;
  let mapLayers = [];
  let players = [];
  let playerMap = {};

  let actionExecutor = new ActionExecutor();
  actionExecutor.registerAction('toggleTile', (options, engine, player) => {
    let layers = mapLayers.filter((layer) => layer.zIndex === player.properties.zIndex);
    layers.forEach((layer) => {
      let currentTile = layer.getTile(options.target.x, options.target.y);
      let currentIndex = options.tiles.indexOf(currentTile);
      layer.setTile(options.target.x, options.target.y, options.tiles[(currentIndex + 1) % options.tiles.length]);
    })
  });

  let clearText = function () {};
  let displayText = function () {};
  let drawMessages = function () {};

  if (overrides.enableTextOutput) {
    textMessageFrame.onclick = () => {
      if (paused) {
        drawMessages();
      }
    };

    clearText = () => {
      textMessages = [];
      textMessageFrame.classList.remove("in");
      textMessage.innerHTML = "";
      textIndicator.classList.remove("in");
      if (paused) {
        unpause();
      }
    }

    displayText = (text) => {
      textMessages = textMessages.concat(text);
    }

    drawMessages = () => {
      if (textMessages.length > 0) {
        pause();
        let text = textMessages.splice(0, 1)[0];
        textMessage.innerHTML = text;
        if (!("in" in textMessageFrame.classList)) {
          textMessageFrame.classList.add("in");
        }
        if (textMessages.length >= 1) {
          textIndicator.classList.add("in");
        } else {
          textIndicator.classList.remove("in");
        }
      } else {
        clearText();
      }
    }
  }

  const input = new CanvasInput(document, CanvasControl());
  if (overrides.enableMouseInput) {
    input.mouse_action(function(coords) {
      if (paused) {
        drawMessages()
      } else {
        let player = getCharacter('player');
        let layer = player.properties.layer;
        let t = layer.applyMouseFocus(coords.x, coords.y);
        player.goTo(t.x, t.y);
        if (Math.abs(t.x - player.getTile().x) + Math.abs(t.y - player.getTile().y) === 1) {
          interact(player, t);
        }
      }
    });
  }

  if (overrides.enableKeyboardInput) {
    input.keyboard(function(pressed, status) {
      let player = getCharacter('player');
      if (status) {
        if (paused) {
          if ([13, 32].indexOf(pressed) >= 0) {
            drawMessages();
          }
        } else {
          switch (pressed) {
            case 37: player.moveTo(player.getTile().x - 1, player.getTile().y); break;
            case 38: player.moveTo(player.getTile().x, player.getTile().y - 1); break;
            case 39: player.moveTo(player.getTile().x + 1, player.getTile().y); break;
            case 40: player.moveTo(player.getTile().x, player.getTile().y + 1); break;
            case 13: case 32: interact(player, player.getLookedAtTile()); break;
          }
        }
      }
    });
  }

  let getActions = () => {
    let layers = mapLayers;
    let actions = [];
    layers.forEach((layer) => actions = actions.concat(layer.actions || []));
    return actions;
  }

  let interact = (player, tile) => {
    if (!player.isMoving()) {
      getActions()
        .filter((action) => action.type !== actionExecutor.TYPE_POSITIONAL)
        .filter((action) => action.x === tile.x && action.y == tile.y)
        .forEach((action) => actionExecutor.execute(action, self, player));
    }
  };

  let pause = () => {
    paused = true;
  }

  let unpause = () => {
    if (paused) {
      paused = false;
      draw();
    }
  }

  let getCharacter = (id) => playerMap[id];

  let setPlayerLighting = (tile) => {
    mapLayers.forEach((layer) => layer.setLight(tile.x, tile.y));
  }

  let drawLayer = (layer) => {
    for (let i = 0; i < (layer.width || xrange); i++) {
      for (let j = 0; j < (layer.height || yrange); j++) {
        layer.draw(i, j, void 0, (layer.x || x), (layer.y || y));
      }
    }
  }

  let previousTime = 0;
  let timeToDraw = (time) => !overrides.lockedFrameRate || (time - previousTime) >= 1000 / overrides.lockedFrameRate;

  let draw = (time) => {
    if (!timeToDraw(time)) {
      requestAnimationFrame(draw);
    } else {
      previousTime = time;
      context.clearRect(0, 0, controlWidth, controlHeight);
      let thingsToDraw = mapLayers.concat(players).sort((a, b) => a.zIndex > b.zIndex);
      for (let thing of thingsToDraw) {
        if (thing instanceof Player) {
          thing.draw();
          thing.move();
          if (thing.useLighting) {
            setPlayerLighting(thing.getTile());
          }
        } else {
          if (thing.visible) {
            drawLayer(thing);
          }
        }
      }
      drawMessages();
      if (!paused) {
        requestAnimationFrame(draw);
      }
    }
  }

  let initLayer = (layer) => {
    let mapLayer = new TileField(context, controlWidth, controlHeight);
    mapLayer.setup(layer);
    mapLayer.flip("horizontal");
    mapLayer.rotate("left");
    mapLayer.setLightmap(layer.lightmap);
    mapLayer = Object.assign(mapLayer, layer);
    return mapLayer;
  }

  let computeOnce = (fn) => {
    var instance = void 0;
    return function () {
      if (instance === void 0) {
        instance = fn.apply(this, arguments);
      }
      return instance;
    }
  }

  let createEmptyLayer = computeOnce((map) => {
    let layer = {
      width: map.width,
      height: map.height,
      layout: Array(map.width * map.height).fill(0)
    }
    return initLayer(layer);
  });

  let init = (map) => {
    mapLayers = map.layers.map(initLayer);
    draw();
    let promises = [];
    let characters = map.characters || {};
    for (let characterId of Object.keys(characters)) {
      let playerOptions = characters[characterId];
      if (playerOptions) {
        promises.push(imgLoader([{
          graphics: [playerOptions.sprites],
          spritesheet: {
            width: playerOptions.width,
            height: playerOptions.height
          }
        }]).then((playerImages) => {
          playerOptions.files = playerImages[0].files;
          playerOptions.layer = mapLayers[0];
          playerOptions.pathfindingLayer = mapLayers[playerOptions.pathfindingLayer] || createEmptyLayer(map);
          playerOptions.tileWidth = map.tileWidth;
          playerOptions.tileHeight = map.tileHeight;

          let player = new Player(context, playerOptions, playerOptions.x, playerOptions.y, pathfind);
          player.on("changeTile", (p, tile) => {
            getActions().filter((action) => action.type === actionExecutor.TYPE_POSITIONAL).forEach((action) => {
              if (action.x === tile.x && action.y === tile.y) {
                actionExecutor.execute(action, self, p);
              }
            })
          });
          players.push(player);
          playerMap[characterId] = player;
        }));
      }
    }
    return Promise.all(promises);
  }

  this.init = init;
  this.displayText = displayText;
  this.pause = pause;
  this.unpause = unpause;
  this.getCharacter = getCharacter;

  this.actionExecutor = actionExecutor;
}
<|endoftext|>


<commit_before>import config from './../config.json';
import { decodeBase64Image } from './parsingHelpers';

export function getApiLists() {
  return fetch(`${config.api.domain}${config.api.endpoints.getLists}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching lists.');
    return {};
  });
};

// article object has to contain folder name (text) and filename (text, name + extension, .md mostly) property
export function getApiArticleContents(article) {
  return fetch(`${config.api.domain}${config.api.endpoints.getArticleContents}${article.folder}/${article.file}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching article contents.');
    return {};
  });
};

// article object has to contain content (text), url (text) and customFields property (object)
export function saveApiArticle(articleObj) {
  return fetch(`${config.api.domain}${config.api.endpoints.saveArticle}`, {
      headers: new Headers({
        'Content-Type': 'application/json',
      }),
      method: 'POST',
      dataType: 'json',
      body: JSON.stringify(articleObj),
    }).then(resp => {
    if (resp.ok) {
      return resp;
    }
    console.error('There was an error during saving file.');
    return {};
  });
};

export function getContentsRootUrl() {
  return fetch(`${config.api.domain}${config.api.endpoints.getRootUrl}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error when obtaining root contents folder path.');
    return {};
  });
};

// remove file (e.g. when title or date is updated so slug is now different and so file name should be)
export function removeApiFile(url) {
  return fetch(`${config.api.domain}${config.api.endpoints.removeFile}`, {
      headers: new Headers({
        'Content-Type': 'application/json',
      }),
      method: 'POST',
      dataType: 'json',
      body: JSON.stringify({
        url: url
      }),
    }).then(resp => {
    if (resp.ok) {
      return resp;
    }
    console.error('There was an error during removing file.');
    return {};
  });
};

const uploadApiImageHelper = function(fileObj) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    const filename = fileObj.name;
    reader.onload = function(e){
      let img = reader.result;
      return fetch(`${config.api.domain}${config.api.endpoints.saveImage}`, {
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
        method: 'POST',
        dataType: 'json',
        body: JSON.stringify({
          file: img,
          name: filename
        }),
      }).then(resp => {
        if (resp.ok) {
          resolve(resp);
          return;
        }
        console.error('There was an error during uploading image file.');
        reject();
      });
    }
    return reader.readAsDataURL(fileObj);
  });
}

export function uploadApiImage(fileObj) {
  return uploadApiImageHelper(fileObj).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during uploading image file.');
    return;
  });
}

export function parseApiMarkdownToHtml(content) {
  return fetch(`${config.api.domain}${config.api.endpoints.parse2html}`, {
    headers: new Headers({
      'Content-Type': 'application/json',
    }),
    method: 'POST',
    dataType: 'json',
    body: JSON.stringify({
      markdown: content
    }),
  }).then(resp => {
  if (resp.ok) {
    return resp.json();
  }
  console.error('There was an error during markdown parse.');
  return '';
});
}
<commit_msg>Added api helper methods for handling pages data.<commit_after>import config from './../config.json';
import { decodeBase64Image } from './parsingHelpers';

// function that fetches all available lists
export function getApiLists() {
  return fetch(`${config.api.domain}${config.api.endpoints.getLists}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching lists.');
    return {};
  });
};

// article object has to contain folder name (text) and file name (text, name + extension, .md mostly) property
export function getApiArticleContents(article) {
  return fetch(`${config.api.domain}${config.api.endpoints.getArticleContents}${article.folder}/${article.file}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching article contents.');
    return {};
  });
};

// article object has to contain content (text), url (text) and customFields property (object)
export function saveApiArticle(articleObj) {
  return fetch(`${config.api.domain}${config.api.endpoints.saveArticle}`, {
      headers: new Headers({
        'Content-Type': 'application/json',
      }),
      method: 'POST',
      dataType: 'json',
      body: JSON.stringify(articleObj),
    }).then(resp => {
    if (resp.ok) {
      return resp;
    }
    console.error('There was an error during saving file.');
    return {};
  });
};

export function getContentsRootUrl() {
  return fetch(`${config.api.domain}${config.api.endpoints.getRootUrl}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error when obtaining root contents folder path.');
    return {};
  });
};

// remove file (e.g. when title or date is updated so slug is now different and so file name should be)
export function removeApiFile(url) {
  return fetch(`${config.api.domain}${config.api.endpoints.removeFile}`, {
      headers: new Headers({
        'Content-Type': 'application/json',
      }),
      method: 'POST',
      dataType: 'json',
      body: JSON.stringify({
        url: url
      }),
    }).then(resp => {
    if (resp.ok) {
      return resp;
    }
    console.error('There was an error during removing file.');
    return {};
  });
};

const uploadApiImageHelper = function(fileObj) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    const filename = fileObj.name;
    reader.onload = function(e){
      let img = reader.result;
      return fetch(`${config.api.domain}${config.api.endpoints.saveImage}`, {
        headers: new Headers({
          'Content-Type': 'application/json',
        }),
        method: 'POST',
        dataType: 'json',
        body: JSON.stringify({
          file: img,
          name: filename
        }),
      }).then(resp => {
        if (resp.ok) {
          resolve(resp);
          return;
        }
        console.error('There was an error during uploading image file.');
        reject();
      });
    }
    return reader.readAsDataURL(fileObj);
  });
}

export function uploadApiImage(fileObj) {
  return uploadApiImageHelper(fileObj).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during uploading image file.');
    return;
  });
}

export function parseApiMarkdownToHtml(content) {
  return fetch(`${config.api.domain}${config.api.endpoints.parse2html}`, {
    headers: new Headers({
      'Content-Type': 'application/json',
    }),
    method: 'POST',
    dataType: 'json',
    body: JSON.stringify({
      markdown: content
    }),
  }).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during markdown parse.');
    return '';
  });
}

// fetches list of available pages
export function getApiPages() {
  return fetch(`${config.api.domain}${config.api.endpoints.getPages}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching lists.');
    return {};
  });
};

// page object has to contain file name (text, name + extension, .md mostly) property
export function getApiPageContents(page) {
  return fetch(`${config.api.domain}${config.api.endpoints.getPageContents}${page.file}`).then(resp => {
    if (resp.ok) {
      return resp.json();
    }
    console.error('There was an error during fetching page contents.');
    return {};
  });
};
<|endoftext|>


<commit_before>angular.module('starter', ['ionic', 'ngResource', 'starter.controllers', 'starter.directives', 'starter.services'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {

      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

      cordova.plugins.Keyboard.disableScroll(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

.config(function($ionicConfigProvider){
  $ionicConfigProvider.tabs.style('top');
})

.config(function($stateProvider, $urlRouterProvider) {
  $urlRouterProvider.otherwise("/menu/home");
  $stateProvider

  .state("menu", {
    url:"/menu",
    templateUrl: "templates/menu.html",
    controller: "menuCtrl",
    abstract: true
  })

  .state("menu.home", {
    url:"/home",
    views: {
      "menuContent": {
          templateUrl: "templates/home.html",
          controller: "loginCtrl"
      }
    }
  })

  .state("menu.profile", {
    url: "/profile",
    views: {
      "menuContent": {
        templateUrl: "templates/profile.html",
        controller: "profileCtrl"
      }
    }
  })

  .state("menu.rank", {
    url: "/rank",
    views: {
      "menuContent": {
        templateUrl: "templates/rank.html"
      }
    }
  })
/* Page relationed with login*/
  .state("menu.login", {
      url:"/login",
      views: {
        "menuContent": {
            templateUrl: "templates/login.html",
            controller: "loginCtrl"
        }
      }
  })

  .state("menu.rides", {
      url:"/rides",
      views: {
        "menuContent": {
          templateUrl: "templates/searchRide.html",
          controller: "rideCtrl"
        }
      }
  })

  .state("menu.rideForm", {
      url: "/ride/new",
      views: {
        "menuContent": {
          templateUrl: "templates/rideForm.html",
          controller: "rideCtrl"
        }
      }
  })

  .state("menu.configuration", {
    url: "/configuration",
    views: {
      "menuContent": {
        templateUrl: "templates/configuration.html"
      }
    }
  })

  .state("menu.about", {
    url: "/about",
    views: {
      "menuContent": {
        templateUrl: "templates/about.html",
        controller: "aboutCtrl"
      }
    }
  })
})
<commit_msg>Configuration on the view cache of the application<commit_after>angular.module('starter', ['ionic', 'ngResource', 'starter.controllers', 'starter.directives', 'starter.services'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {

      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

      cordova.plugins.Keyboard.disableScroll(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

.config(function($ionicConfigProvider){
  $ionicConfigProvider.tabs.style('top');
})

.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
  $urlRouterProvider.otherwise("/menu/home");
  $ionicConfigProvider.views.maxCache(0);
  $stateProvider

  .state("menu", {
    url:"/menu",
    templateUrl: "templates/menu.html",
    controller: "menuCtrl",
    abstract: true
  })

  .state("menu.home", {
    url:"/home",
    views: {
      "menuContent": {
          templateUrl: "templates/home.html",
          controller: "loginCtrl"
      }
    }
  })

  .state("menu.profile", {
    url: "/profile",
    views: {
      "menuContent": {
        templateUrl: "templates/profile.html",
        controller: "profileCtrl"
      }
    }
  })

  .state("menu.rank", {
    url: "/rank",
    views: {
      "menuContent": {
        templateUrl: "templates/rank.html"
      }
    }
  })
/* Page relationed with login*/
  .state("menu.login", {
      url:"/login",
      views: {
        "menuContent": {
            templateUrl: "templates/login.html",
            controller: "loginCtrl"
        }
      }
  })

  .state("menu.rides", {
      url:"/rides",
      views: {
        "menuContent": {
          templateUrl: "templates/searchRide.html",
          controller: "rideCtrl"
        }
      }
  })

  .state("menu.rideForm", {
      url: "/ride/new",
      views: {
        "menuContent": {
          templateUrl: "templates/rideForm.html",
          controller: "rideCtrl"
        }
      }
  })

  .state("menu.configuration", {
    url: "/configuration",
    views: {
      "menuContent": {
        templateUrl: "templates/configuration.html"
      }
    }
  })

  .state("menu.about", {
    url: "/about",
    views: {
      "menuContent": {
        templateUrl: "templates/about.html",
        controller: "aboutCtrl"
      }
    }
  })

  .state("menu.exit", {
    url: "/exit",
    views: {
      "menuContent": {
        templateUrl: "templates/exit.html"
      }
    }
  })
})
<|endoftext|>