<commit_before>
define(['js/core/DomElement', 'underscore'], function (DomElement, _) {

    var HTML_Namespace = "http://www.w3.org/1999/xhtml",
        POLICY_OUT = 'out',
        POLICY_IN = 'in',
        POLICY_BOTH = 'both',
        attributeMap = {
            height: 'offsetHeight',
            width: 'offsetWidth'
        };

    /***
     * Sets the size of an element, if the policy requires it
     * @param element
     * @param policy
     * @param attribute
     */
    var checkSizePolicy = function (element, policy, attribute) {
        if (policy === POLICY_IN || policy === POLICY_BOTH) {
            element.set(attribute, element.$el[attributeMap[attribute]]);
        }
    };

    /***
     * Binds the window resize event and sets the size on resize if the policy requires it
     * @param element
     * @param policy
     * @param attribute
     */
    var bindSizePolicy = function (element, policy, attribute) {

        if (policy === POLICY_IN || policy === POLICY_BOTH) {
            if (!element["__update" + attribute]) {
                var self = element;
                element["__update" + attribute] = function () {
                    // setTimeout fix because of safari iOS bug: height and width are set after event is triggered
                    setTimeout(function () {
                        self.set(attribute, self.$el[attributeMap[attribute]]);
                    }, 1);
                };
                element.dom(element.$stage.$window).bindDomEvent('resize', element["__update" + attribute]);
            }
        } else {
            if (element["__update" + attribute]) {
                element.dom(element.$stage.$window).unbindDomEvent('resize', element["__update" + attribute]);
                delete element["__update" + attribute];
            }
        }

    };

    /**
     * Represents a HTML Element in the DOM
     */
    var HtmlElement = DomElement.inherit("js.html.HtmlElement", {

        defaults: {
            /**
             * If not null, false or undefined the "active" CSS class is added
             *
             * @type Boolean
             */
            selected: null,

            /**
             * If not null, false or undefined a click will set the element to selected
             * @type Boolean
             */
            selectable: null,

            /***
             * the target namespace for the HTMLElement
             * @type String
             */
            namespace: HTML_Namespace,

            /**
             * Possible values: "absolute", "relative"
             * @type String
             */
            position: null,

            /**
             *
             * The heightUpdatePolicy configures whether the height of the component is
             * updated when the DOM node height changes or if the DOM node height is updated
             * when the component height changes.
             *
             *  **Possible values:**
             *
             *   +  **in** - "height" attribute is determined by DOM nodes offsetHeight
             *   +  **out** - DOM node height is determined by the "height" attribute
             *   +  **both** - both directions
             *
             * @type String
             */
            heightUpdatePolicy: "out",

            /**
             *
             * The widthUpdatePolicy configures whether the width of the component is
             * updated when the DOM node width changes or if the DOM node width is updated
             * when the component width changes.
             *
             *  **Possible values:**
             *
             *   +  **in** - "width" attribute is determined by DOM nodes offsetWidth
             *   +  **out** - DOM node width is determined by the "width" attribute
             *   +  **both** - both directions
             *
             * @type String
             */
            widthUpdatePolicy: "out"
        },

        /**
         * @type Array
         */
        $classAttributes: ['heightUpdatePolicy', 'widthUpdatePolicy', 'content'],

        /**
         * @type Array
         */
        $excludedStyleAttributes: ['src', 'content', 'item'],

        /***
         * @type Array
         */
        $renderAsStyleWithPx: ['left', 'top', 'maxWidth', 'maxHeight'],

        /**
         *
         * @private
         */
        _onDomAdded: function () {
            this.callBase();

            this.checkSizePolicies();
        },
        /**
         * Checks if the element has the correct width and height according to the width and height update policy
         */
        checkSizePolicies: function(){
            checkSizePolicy(this, this.$.widthUpdatePolicy, 'width');
            checkSizePolicy(this, this.$.heightUpdatePolicy, 'height');
        },

        /**
         *
         * @param policy
         * @private
         */
        _renderHeightUpdatePolicy: function (policy) {
            bindSizePolicy(this, policy, "height");
        },

        /**
         *
         * @param policy
         * @private
         */
        _renderWidthUpdatePolicy: function (policy) {
            bindSizePolicy(this, policy, "width");
        },

        /**
         *
         * @param key
         * @param value
         * @private
         */
        _setAttribute: function (key, value) {

            if (_.indexOf(this.$renderAsStyleWithPx, key) !== -1) {
                if (value != null && !_.isString(value)) {
                    value += "px";
                }
            }

            this.callBase(key, value);
        },

        /**
         *
         * @param selectable
         * @private
         */
        _renderSelectable: function (selectable) {
            if (selectable) {
                if (!this._onSelect) {
                    var self = this;
                    this._onSelect = function () {
                        if (self.$.enabled) {
                            self.set({selected: !self.$.selected});
                        }
                    };
                }
                this.bindDomEvent('click', this._onSelect);
            } else {
                if (this._onSelect) {
                    this.unbindDomEvent('click', this._onSelect);
                }
            }
        },

        /***
         * renders the width of the element if the update-policy allows out-going
         * @param width - the width in pixel if not a string
         * @private
         */
        _renderWidth: function (width) {

            if (width !== undefined && width !== null && typeof(width) !== "string") {
                width += "px";
            }

            this._renderPolicyValue('width', width);
        },

        /***
         * renders the height of the element if the update-policy allows out-going
         * @param height - the width in pixel if not a string
         * @private
         */
        _renderHeight: function (height) {

            if (height !== undefined && height !== null && typeof(height) !== "string") {
                // TODO: check browser
                height = Math.min(17895697, height); // max height in firefox
                height += "px";
            }

            this._renderPolicyValue('height', height);
        },

        /***
         *
         * @param name
         * @param value
         * @private
         */
        _renderPolicyValue: function (name, value) {
            var policy = this.$[name + 'UpdatePolicy'];

            if (policy === POLICY_OUT || policy === POLICY_BOTH) {
                if (value != null && value !== undefined) {
                    this.$el.style[name] = value;
                }
            }

        },

        _renderAttributeInternal: function (key, value) {
            if (this._isStyleAttribute(key)) {
                if (_.indexOf(this.$renderAsStyleWithPx, key) !== -1) {
                    if (value != null && !_.isString(value)) {
                        value += "px";
                    }
                }

                var dashKey,
                    camelCaseKey,
                    transformedKey,
                    i;

                if (/-/.test(key)) {
                    // has dash
                    dashKey = key;

                    transformedKey = HtmlElement.dashFormatTransformCache[key];

                    if (!transformedKey) {

                        var parts = key.split("-");
                        // transform key
                        transformedKey = parts[0];
                        for (i = 1; i < parts.length; i++) {
                            transformedKey += parts[i].charAt(0).toUpperCase() + parts[i].substr(1);
                        }

                        HtmlElement.dashFormatTransformCache[key] = transformedKey;
                    }

                    camelCaseKey = transformedKey;

                } else {

                    camelCaseKey = key;

                    transformedKey = HtmlElement.camelCaseFormatTransformCache[key];

                    if (!transformedKey) {
                        // transform key
                        var split = key.split(/(?=[A-Z])/);
                        transformedKey = split[0];
                        for (i = 1; i < split.length; i++) {
                            transformedKey += "-" + split[i].charAt(0).toLowerCase() + split[i].substr(1);
                        }

                        HtmlElement.camelCaseFormatTransformCache[key] = transformedKey;
                    }

                    dashKey = transformedKey;
                }

                if (camelCaseKey in this.$el.style) {
                    if (value != null) {
                        if (this.$stage.$browser.isIE) {
                            // IE doesn't update style immediately with setProperty(), so we use style[key] = value
                            this.$el.style[dashKey] = value;
                        } else {
                            this.$el.style.setProperty(dashKey, value, null);
                        }
                    } else {
                        if(this.$el.style.setProperty){
                            this.$el.style.removeProperty(dashKey);
                        } else {
                            this.$el.style.removeAttribute(dashKey);
                        }
                    }
                }

            } else {
                // HACK FOR FF AND IE TO CLEAR THE IMAGE BEFORE SETTING A NEW ONE
                if (key === "src" && (this.$stage.$browser.isFF || this.$stage.$browser.isIE)) {
                    this.$el.removeAttribute(key);
                }
                this.callBase();
            }
        },

        _isStyleAttribute: function (key) {

            var supportedCssProperties = this.$stage.$supportedCssProperties;

            if (!supportedCssProperties && this.runsInBrowser()) {

                var window = this.$stage.$window,
                    document = this.$stage.$document;

                supportedCssProperties = this.$stage.$supportedCssProperties = [];

                if (document && window) {
                    var body = document.body || document.getElementsByName("body")[0] || document.getElementsByName("html")[0];
                    if (body) {
                        var styles = window.getComputedStyle(body, null);
                        for (var i = 0; i < styles.length; i++) {
                            supportedCssProperties.push(styles[i]);
                        }
                    }
                }
            }

            return _.indexOf(this.$excludedStyleAttributes, key) === -1 && this.$el && (key in this.$el.style || (supportedCssProperties && _.indexOf(supportedCssProperties, key) !== -1));

        }
    });

    HtmlElement.camelCaseFormatTransformCache = {};
    HtmlElement.dashFormatTransformCache = {};

    HtmlElement.HTML_Namespace = HTML_Namespace;

    return HtmlElement;
});<commit_msg>removed blank line<commit_after>define(['js/core/DomElement', 'underscore'], function (DomElement, _) {

    var HTML_Namespace = "http://www.w3.org/1999/xhtml",
        POLICY_OUT = 'out',
        POLICY_IN = 'in',
        POLICY_BOTH = 'both',
        attributeMap = {
            height: 'offsetHeight',
            width: 'offsetWidth'
        };

    /***
     * Sets the size of an element, if the policy requires it
     * @param element
     * @param policy
     * @param attribute
     */
    var checkSizePolicy = function (element, policy, attribute) {
        if (policy === POLICY_IN || policy === POLICY_BOTH) {
            element.set(attribute, element.$el[attributeMap[attribute]]);
        }
    };

    /***
     * Binds the window resize event and sets the size on resize if the policy requires it
     * @param element
     * @param policy
     * @param attribute
     */
    var bindSizePolicy = function (element, policy, attribute) {

        if (policy === POLICY_IN || policy === POLICY_BOTH) {
            if (!element["__update" + attribute]) {
                var self = element;
                element["__update" + attribute] = function () {
                    // setTimeout fix because of safari iOS bug: height and width are set after event is triggered
                    setTimeout(function () {
                        self.set(attribute, self.$el[attributeMap[attribute]]);
                    }, 1);
                };
                element.dom(element.$stage.$window).bindDomEvent('resize', element["__update" + attribute]);
            }
        } else {
            if (element["__update" + attribute]) {
                element.dom(element.$stage.$window).unbindDomEvent('resize', element["__update" + attribute]);
                delete element["__update" + attribute];
            }
        }

    };

    /**
     * Represents a HTML Element in the DOM
     */
    var HtmlElement = DomElement.inherit("js.html.HtmlElement", {

        defaults: {
            /**
             * If not null, false or undefined the "active" CSS class is added
             *
             * @type Boolean
             */
            selected: null,

            /**
             * If not null, false or undefined a click will set the element to selected
             * @type Boolean
             */
            selectable: null,

            /***
             * the target namespace for the HTMLElement
             * @type String
             */
            namespace: HTML_Namespace,

            /**
             * Possible values: "absolute", "relative"
             * @type String
             */
            position: null,

            /**
             *
             * The heightUpdatePolicy configures whether the height of the component is
             * updated when the DOM node height changes or if the DOM node height is updated
             * when the component height changes.
             *
             *  **Possible values:**
             *
             *   +  **in** - "height" attribute is determined by DOM nodes offsetHeight
             *   +  **out** - DOM node height is determined by the "height" attribute
             *   +  **both** - both directions
             *
             * @type String
             */
            heightUpdatePolicy: "out",

            /**
             *
             * The widthUpdatePolicy configures whether the width of the component is
             * updated when the DOM node width changes or if the DOM node width is updated
             * when the component width changes.
             *
             *  **Possible values:**
             *
             *   +  **in** - "width" attribute is determined by DOM nodes offsetWidth
             *   +  **out** - DOM node width is determined by the "width" attribute
             *   +  **both** - both directions
             *
             * @type String
             */
            widthUpdatePolicy: "out"
        },

        /**
         * @type Array
         */
        $classAttributes: ['heightUpdatePolicy', 'widthUpdatePolicy', 'content'],

        /**
         * @type Array
         */
        $excludedStyleAttributes: ['src', 'content', 'item'],

        /***
         * @type Array
         */
        $renderAsStyleWithPx: ['left', 'top', 'maxWidth', 'maxHeight'],

        /**
         *
         * @private
         */
        _onDomAdded: function () {
            this.callBase();

            this.checkSizePolicies();
        },
        /**
         * Checks if the element has the correct width and height according to the width and height update policy
         */
        checkSizePolicies: function(){
            checkSizePolicy(this, this.$.widthUpdatePolicy, 'width');
            checkSizePolicy(this, this.$.heightUpdatePolicy, 'height');
        },

        /**
         *
         * @param policy
         * @private
         */
        _renderHeightUpdatePolicy: function (policy) {
            bindSizePolicy(this, policy, "height");
        },

        /**
         *
         * @param policy
         * @private
         */
        _renderWidthUpdatePolicy: function (policy) {
            bindSizePolicy(this, policy, "width");
        },

        /**
         *
         * @param key
         * @param value
         * @private
         */
        _setAttribute: function (key, value) {

            if (_.indexOf(this.$renderAsStyleWithPx, key) !== -1) {
                if (value != null && !_.isString(value)) {
                    value += "px";
                }
            }

            this.callBase(key, value);
        },

        /**
         *
         * @param selectable
         * @private
         */
        _renderSelectable: function (selectable) {
            if (selectable) {
                if (!this._onSelect) {
                    var self = this;
                    this._onSelect = function () {
                        if (self.$.enabled) {
                            self.set({selected: !self.$.selected});
                        }
                    };
                }
                this.bindDomEvent('click', this._onSelect);
            } else {
                if (this._onSelect) {
                    this.unbindDomEvent('click', this._onSelect);
                }
            }
        },

        /***
         * renders the width of the element if the update-policy allows out-going
         * @param width - the width in pixel if not a string
         * @private
         */
        _renderWidth: function (width) {

            if (width !== undefined && width !== null && typeof(width) !== "string") {
                width += "px";
            }

            this._renderPolicyValue('width', width);
        },

        /***
         * renders the height of the element if the update-policy allows out-going
         * @param height - the width in pixel if not a string
         * @private
         */
        _renderHeight: function (height) {

            if (height !== undefined && height !== null && typeof(height) !== "string") {
                // TODO: check browser
                height = Math.min(17895697, height); // max height in firefox
                height += "px";
            }

            this._renderPolicyValue('height', height);
        },

        /***
         *
         * @param name
         * @param value
         * @private
         */
        _renderPolicyValue: function (name, value) {
            var policy = this.$[name + 'UpdatePolicy'];

            if (policy === POLICY_OUT || policy === POLICY_BOTH) {
                if (value != null && value !== undefined) {
                    this.$el.style[name] = value;
                }
            }

        },

        _renderAttributeInternal: function (key, value) {
            if (this._isStyleAttribute(key)) {
                if (_.indexOf(this.$renderAsStyleWithPx, key) !== -1) {
                    if (value != null && !_.isString(value)) {
                        value += "px";
                    }
                }

                var dashKey,
                    camelCaseKey,
                    transformedKey,
                    i;

                if (/-/.test(key)) {
                    // has dash
                    dashKey = key;

                    transformedKey = HtmlElement.dashFormatTransformCache[key];

                    if (!transformedKey) {

                        var parts = key.split("-");
                        // transform key
                        transformedKey = parts[0];
                        for (i = 1; i < parts.length; i++) {
                            transformedKey += parts[i].charAt(0).toUpperCase() + parts[i].substr(1);
                        }

                        HtmlElement.dashFormatTransformCache[key] = transformedKey;
                    }

                    camelCaseKey = transformedKey;

                } else {

                    camelCaseKey = key;

                    transformedKey = HtmlElement.camelCaseFormatTransformCache[key];

                    if (!transformedKey) {
                        // transform key
                        var split = key.split(/(?=[A-Z])/);
                        transformedKey = split[0];
                        for (i = 1; i < split.length; i++) {
                            transformedKey += "-" + split[i].charAt(0).toLowerCase() + split[i].substr(1);
                        }

                        HtmlElement.camelCaseFormatTransformCache[key] = transformedKey;
                    }

                    dashKey = transformedKey;
                }

                if (this.$el.style && camelCaseKey in this.$el.style) {
                    if (value != null) {
                        if (this.$stage.$browser.isIE) {
                            // IE doesn't update style immediately with setProperty(), so we use style[key] = value
                            this.$el.style[dashKey] = value;
                        } else {
                            this.$el.style.setProperty(dashKey, value, null);
                        }
                    } else {
                        if(this.$el.style.setProperty){
                            this.$el.style.removeProperty(dashKey);
                        } else {
                            this.$el.style.removeAttribute(dashKey);
                        }
                    }
                }

            } else {
                // HACK FOR FF AND IE TO CLEAR THE IMAGE BEFORE SETTING A NEW ONE
                if (key === "src" && (this.$stage.$browser.isFF || this.$stage.$browser.isIE)) {
                    this.$el.removeAttribute(key);
                }
                this.callBase();
            }
        },

        _isStyleAttribute: function (key) {

            var supportedCssProperties = this.$stage.$supportedCssProperties;

            if (!supportedCssProperties && this.runsInBrowser()) {

                var window = this.$stage.$window,
                    document = this.$stage.$document;

                supportedCssProperties = this.$stage.$supportedCssProperties = [];

                if (document && window) {
                    var body = document.body || document.getElementsByName("body")[0] || document.getElementsByName("html")[0];
                    if (body) {
                        var styles = window.getComputedStyle(body, null);
                        for (var i = 0; i < styles.length; i++) {
                            supportedCssProperties.push(styles[i]);
                        }
                    }
                }
            }

            return _.indexOf(this.$excludedStyleAttributes, key) === -1 && this.$el && ((this.$el.style && key in this.$el.style) || (supportedCssProperties && _.indexOf(supportedCssProperties, key) !== -1));

        }
    });

    HtmlElement.camelCaseFormatTransformCache = {};
    HtmlElement.dashFormatTransformCache = {};

    HtmlElement.HTML_Namespace = HTML_Namespace;

    return HtmlElement;
});<|endoftext|>


<commit_before>var Vesrion="0.1";

var app = angular.module('WebFormApp', ['pascalprecht.translate']);
app.controller('WebFormAppCtrl', WebFormAppCtrl);

/**
* WebFormAppCtrl: Main controller
*/
function WebFormAppCtrl($scope, $http, $timeout, $window,  $translate, $compile) {

	$scope.field = {};
	$scope.multipleIndex = 1;
	$scope.ValidationDisabled = false;
	$scope.selectedLanguage = "en";
	$scope.groups =  groups;

	$scope.submit = function(frm) {
		$scope.field[frm.$name].AEAPrice = 11;
		console.log(frm);
		return false;
	};

	$scope.addRow = function(frm, group) {
		$scope.multipleIndex = $scope.groups[frm][group].length;
		$scope.groups[frm][group].push(++$scope.multipleIndex);
		var tmi = $scope.multipleIndex;
		$timeout ( () => {
			$(`#group-area-${$scope.multipleIndex}-${group}`).prepend( $compile(`<div class="row"><button type="button"  title="{{'deleterow' | translate}}"class="deleterowbutton" ng-click="deleteRow('${frm}', '${group}', '${tmi}')"></button></div>`)($scope));
		}, 10);
	};

	$scope.deleteRow = function(frm, group, index) {
		$scope.groups[frm][group].splice($scope.groups[frm][group].indexOf(index), 1);
	};

}

$(document).on("scroll", function() {
	if ($(document).scrollTop() > 40) {
		$("#head").removeClass("tplarge").addClass("tpsmall");
	} else {
		$("#head").removeClass("tpsmall").addClass("tplarge");
	}
});<commit_msg>Delete Form row bug fixed<commit_after>var Vesrion="0.1";

var app = angular.module('WebFormApp', ['pascalprecht.translate']);
app.controller('WebFormAppCtrl', WebFormAppCtrl);

/**
* WebFormAppCtrl: Main controller
*/
function WebFormAppCtrl($scope, $http, $timeout, $window,  $translate, $compile) {

	$scope.field = {};
	$scope.multipleIndex = 1;
	$scope.ValidationDisabled = false;
	$scope.selectedLanguage = "en";
	$scope.groups =  groups;

	$scope.submit = function(frm) {
		$scope.field[frm.$name].AEAPrice = 11;
		console.log(frm);
		return false;
	};

	$scope.addRow = function(frm, group) {
		$scope.multipleIndex = $scope.groups[frm][group].length;
		var tmi = $scope.multipleIndex++;
		$scope.groups[frm][group].push(frm + '-' + tmi + '-' + group);
		$timeout ( () => {
			$(`#group-area-${$scope.multipleIndex}-${group}`).prepend( $compile(`<div class="row"><button type="button"  title="{{'deleterow' | translate}}"class="deleterowbutton" ng-click="deleteRow('${frm}', '${group}', ${tmi})"></button></div>`)($scope));
		}, 10);
	};

	$scope.deleteRow = function(frm, group, index) {
		$scope.groups[frm][group].splice($scope.groups[frm][group].indexOf(frm + '-' + index + '-' + group), 1);
	};

}

$(document).on("scroll", function() {
	if ($(document).scrollTop() > 40) {
		$("#head").removeClass("tplarge").addClass("tpsmall");
	} else {
		$("#head").removeClass("tpsmall").addClass("tplarge");
	}
});<|endoftext|>


<commit_before>"use strict";

(function ($) {

    $.fn.circliful = function (options, callback) {

        var settings = $.extend({
            // These are the defaults.
            //startDegree: 0,
            foregroundColor: "#3498DB",
            backgroundColor: "#ccc",
            pointColor: "none",
            fillColor: 'none',
            foregroundBorderWidth: 15,
            backgroundBorderWidth: 15,
            pointSize: 28.5,
            fontColor: '#aaa',
            percent: 75,
            animation: 1,
            animationStep: 5,
            icon: 'none',
            iconSize: '30',
            iconColor: '#ccc',
            iconPosition: 'top',
            target: 0,
            start: 0,
            showPercent: 1,
            percentageTextSize: 22,
            textAdditionalCss: '',
            targetPercent: 0,
            targetTextSize: 17,
            targetColor: '#2980B9',
            text: null,
            textStyle: null,
            textColor: '#666',
            multiPercentage: 0,
            percentages: null,
            textBelow: false,
            noPercentageSign: false
        }, options);

        return this.each(function () {
            var circleContainer = $(this);
            var percent = settings.percent;
            var iconY = 83;
            var iconX = 100;
            var textY = 110;
            var textX = 100;
            var additionalCss;
            var elements;
            var icon;
            var backgroundBorderWidth = settings.backgroundBorderWidth;

            if(settings.iconPosition == 'bottom') {
                iconY = 124;
                textY = 95;
            } else if(settings.iconPosition == 'left') {
                iconX = 80;
                iconY = 110;
                textX = 117;
            } else if(settings.iconPosition == 'middle') {
                if(settings.multiPercentage == 1) {
                    if(typeof settings.percentages == "object") {
                        backgroundBorderWidth = 30;
                    } else {
                        iconY = 110;
                        elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="133" y1="50" x2="140" y2="40" stroke-width="2"  /></g>';
                        elements += '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="140" y1="40" x2="200" y2="40" stroke-width="2"  /></g>';
                        textX = 228;
                        textY = 47;
                    }
                } else {
                    iconY = 110;
                    elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="133" y1="50" x2="140" y2="40" stroke-width="2"  /></g>';
                    elements += '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="140" y1="40" x2="200" y2="40" stroke-width="2"  /></g>';
                    textX = 175;
                    textY = 35;
                }
            } else if(settings.iconPosition == 'right') {
                iconX = 120;
                iconY = 110;
                textX = 80;
            }

            if(settings.targetPercent > 0) {
                textY = 95;
                elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="75" y1="101" x2="125" y2="101" stroke-width="1"  /></g>';
                elements += '<text text-anchor="middle" x="' + textX + '" y="120" style="font-size: ' + settings.targetTextSize + 'px;" fill="' + settings.targetColor + '">' + settings.targetPercent + (settings.noPercentageSign ? '' : '%') + '</text>';
                elements += '<circle cx="100" cy="100" r="69" fill="none" stroke="' + settings.backgroundColor + '" stroke-width="3" stroke-dasharray="450" transform="rotate(-90,100,100)" />';
                elements += '<circle cx="100" cy="100" r="69" fill="none" stroke="' + settings.targetColor + '" stroke-width="3" stroke-dasharray="' + (360 / 100 * settings.targetPercent) + ', 20000" transform="rotate(-90,100,100)" />';

            }

            if (settings.text != null){
                if (settings.textBelow){
                    elements += '<text text-anchor="middle" x="100" y="190" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
                else if (settings.multiPercentage == 0){
                    elements += '<text text-anchor="middle" x="100" y="125" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
                else if(settings.multiPercentage == 1) {
                    elements += '<text text-anchor="middle" x="228" y="65" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
            }

            if (settings.icon != 'none') {
                icon = '<text text-anchor="middle" x="' + iconX + '" y="' + iconY + '" class="icon" style="font-size: ' + settings.iconSize + 'px" fill="' + settings.iconColor + '">&#x' + settings.icon + '</text>';
            }

            circleContainer
                .addClass('svg-container')
                .append(
                    $('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">' +
                        elements +
                        '<circle cx="100" cy="100" r="57" class="border" fill="' + settings.fillColor + '" stroke="' + settings.backgroundColor + '" stroke-width="' + backgroundBorderWidth + '" stroke-dasharray="360" transform="rotate(-90,100,100)" />' +
                        '<circle class="circle" cx="100" cy="100" r="57" class="border" fill="none" stroke="' + settings.foregroundColor + '" stroke-width="' + settings.foregroundBorderWidth + '" stroke-dasharray="0,20000" transform="rotate(-90,100,100)" />' +
                        '<circle cx="100" cy="100" r="' + settings.pointSize + '" fill="' + settings.pointColor + '" />' +
                        icon +
                        '<text class="timer" text-anchor="middle" x="' + textX + '" y="' + textY + '" style="font-size: ' + settings.percentageTextSize + 'px; ' + additionalCss + ';' + settings.textAdditionalCss + '" fill="' + settings.fontColor + '">0' + (settings.noPercentageSign ? '' : '%') + '</text>')
                );

            var circle = circleContainer.find('.circle');
            var myTimer = circleContainer.find('.timer');
            var interval = 30;
            var angle = 0;
            var angleIncrement = settings.animationStep;
            var last = 0;
            var summary = 0;
            var oneStep = 0;

            if (settings.start > 0 && settings.target > 0) {
                percent = settings.start / (settings.target / 100);
                oneStep = settings.target / 100;
            }

            if (settings.animation == 1) {
                var timer = window.setInterval(function () {
                    if ((angle) >= (360 / 100 * percent)) {
                        window.clearInterval(timer);
                        last = 1;
                        if(typeof callback == 'function')
                        {
                            callback.call(this);
                        }
                    } else {
                        angle += angleIncrement;
                        summary += oneStep;
                    }

                    if (angle / 3.6 >= percent && last == 1) {
                        angle = 3.6 * percent;
                    }

                    if (summary > settings.target && last == 1) {
                        summary = settings.target;
                    }

                    circle
                        .attr("stroke-dasharray", angle + ", 20000");

                    if (settings.showPercent == 1) {
                        myTimer
                            .text(parseInt(angle / 360 * 100) + (settings.noPercentageSign ? '' : '%'));
                    } else {
                        myTimer
                            .text(summary);
                    }

                }.bind(circle), interval);
            } else {
                circle
                    .attr("stroke-dasharray", (360 / 100 * percent) + ", 20000");

                if (settings.showPercent == 1) {
                    myTimer
                        .text(percent + (settings.noPercentageSign ? '' : '%'));
                } else {
                    myTimer
                        .text(settings.target);
                }
            }
        });
    }

}(jQuery));
<commit_msg>Different text #84<commit_after>"use strict";

(function ($) {

    $.fn.circliful = function (options, callback) {

        var settings = $.extend({
            // These are the defaults.
            //startDegree: 0,
            foregroundColor: "#3498DB",
            backgroundColor: "#ccc",
            pointColor: "none",
            fillColor: 'none',
            foregroundBorderWidth: 15,
            backgroundBorderWidth: 15,
            pointSize: 28.5,
            fontColor: '#aaa',
            percent: 75,
            animation: 1,
            animationStep: 5,
            icon: 'none',
            iconSize: '30',
            iconColor: '#ccc',
            iconPosition: 'top',
            target: 0,
            start: 0,
            showPercent: 1,
            percentageTextSize: 22,
            textAdditionalCss: '',
            targetPercent: 0,
            targetTextSize: 17,
            targetColor: '#2980B9',
            text: null,
            textStyle: null,
            textColor: '#666',
            multiPercentage: 0,
            percentages: null,
            textBelow: false,
            noPercentageSign: false,
            replacePercentageByText: null
        }, options);

        return this.each(function () {
            var circleContainer = $(this);
            var percent = settings.percent;
            var iconY = 83;
            var iconX = 100;
            var textY = 110;
            var textX = 100;
            var additionalCss;
            var elements;
            var icon;
            var backgroundBorderWidth = settings.backgroundBorderWidth;

            if(settings.iconPosition == 'bottom') {
                iconY = 124;
                textY = 95;
            } else if(settings.iconPosition == 'left') {
                iconX = 80;
                iconY = 110;
                textX = 117;
            } else if(settings.iconPosition == 'middle') {
                if(settings.multiPercentage == 1) {
                    if(typeof settings.percentages == "object") {
                        backgroundBorderWidth = 30;
                    } else {
                        iconY = 110;
                        elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="133" y1="50" x2="140" y2="40" stroke-width="2"  /></g>';
                        elements += '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="140" y1="40" x2="200" y2="40" stroke-width="2"  /></g>';
                        textX = 228;
                        textY = 47;
                    }
                } else {
                    iconY = 110;
                    elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="133" y1="50" x2="140" y2="40" stroke-width="2"  /></g>';
                    elements += '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="140" y1="40" x2="200" y2="40" stroke-width="2"  /></g>';
                    textX = 175;
                    textY = 35;
                }
            } else if(settings.iconPosition == 'right') {
                iconX = 120;
                iconY = 110;
                textX = 80;
            }

            if(settings.targetPercent > 0) {
                textY = 95;
                elements = '<g stroke="' + (settings.backgroundColor != 'none' ? settings.backgroundColor : '#ccc') + '" ><line x1="75" y1="101" x2="125" y2="101" stroke-width="1"  /></g>';
                elements += '<text text-anchor="middle" x="' + textX + '" y="120" style="font-size: ' + settings.targetTextSize + 'px;" fill="' + settings.targetColor + '">' + settings.targetPercent + (settings.noPercentageSign ? '' : '%') + '</text>';
                elements += '<circle cx="100" cy="100" r="69" fill="none" stroke="' + settings.backgroundColor + '" stroke-width="3" stroke-dasharray="450" transform="rotate(-90,100,100)" />';
                elements += '<circle cx="100" cy="100" r="69" fill="none" stroke="' + settings.targetColor + '" stroke-width="3" stroke-dasharray="' + (360 / 100 * settings.targetPercent) + ', 20000" transform="rotate(-90,100,100)" />';

            }

            if (settings.text != null){
                if (settings.textBelow){
                    elements += '<text text-anchor="middle" x="100" y="190" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
                else if (settings.multiPercentage == 0){
                    elements += '<text text-anchor="middle" x="100" y="125" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
                else if(settings.multiPercentage == 1) {
                    elements += '<text text-anchor="middle" x="228" y="65" style="' + settings.textStyle + '" fill="' + settings.textColor + '">' + settings.text + '</text>';
                }
            }

            if (settings.icon != 'none') {
                icon = '<text text-anchor="middle" x="' + iconX + '" y="' + iconY + '" class="icon" style="font-size: ' + settings.iconSize + 'px" fill="' + settings.iconColor + '">&#x' + settings.icon + '</text>';
            }

            circleContainer
                .addClass('svg-container')
                .append(
                    $('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">' +
                        elements +
                        '<circle cx="100" cy="100" r="57" class="border" fill="' + settings.fillColor + '" stroke="' + settings.backgroundColor + '" stroke-width="' + backgroundBorderWidth + '" stroke-dasharray="360" transform="rotate(-90,100,100)" />' +
                        '<circle class="circle" cx="100" cy="100" r="57" class="border" fill="none" stroke="' + settings.foregroundColor + '" stroke-width="' + settings.foregroundBorderWidth + '" stroke-dasharray="0,20000" transform="rotate(-90,100,100)" />' +
                        '<circle cx="100" cy="100" r="' + settings.pointSize + '" fill="' + settings.pointColor + '" />' +
                        icon +
                        '<text class="timer" text-anchor="middle" x="' + textX + '" y="' + textY + '" style="font-size: ' + settings.percentageTextSize + 'px; ' + additionalCss + ';' + settings.textAdditionalCss + '" fill="' + settings.fontColor + '">'+ (settings.replacePercentageByText == null ? 0 : settings.replacePercentageByText) + (settings.noPercentageSign ? '' : '%') + '</text>')
                );

            var circle = circleContainer.find('.circle');
            var myTimer = circleContainer.find('.timer');
            var interval = 30;
            var angle = 0;
            var angleIncrement = settings.animationStep;
            var last = 0;
            var summary = 0;
            var oneStep = 0;
            var text = percent;

            if(settings.replacePercentageByText != null) {
                text = settings.replacePercentageByText;
            }

            if (settings.start > 0 && settings.target > 0) {
                percent = settings.start / (settings.target / 100);
                oneStep = settings.target / 100;
            }

            if (settings.animation == 1) {
                var timer = window.setInterval(function () {
                    if ((angle) >= (360 / 100 * percent)) {
                        window.clearInterval(timer);
                        last = 1;
                        if(typeof callback == 'function')
                        {
                            callback.call(this);
                        }
                    } else {
                        angle += angleIncrement;
                        summary += oneStep;
                    }

                    if (angle / 3.6 >= percent && last == 1) {
                        angle = 3.6 * percent;
                    }

                    if (summary > settings.target && last == 1) {
                        summary = settings.target;
                    }

                    if(settings.replacePercentageByText == null) {
                        text = parseInt(angle / 360 * 100);
                    }

                    circle
                        .attr("stroke-dasharray", angle + ", 20000");

                    if (settings.showPercent == 1) {
                        myTimer
                            .text(text + (settings.noPercentageSign ? '' : '%'));
                    } else {
                        myTimer
                            .text(summary);
                    }

                }.bind(circle), interval);
            } else {
                circle
                    .attr("stroke-dasharray", (360 / 100 * percent) + ", 20000");

                if (settings.showPercent == 1) {
                    myTimer
                        .text(text + (settings.noPercentageSign ? '' : '%'));
                } else {
                    myTimer
                        .text(settings.target);
                }
            }
        });
    }
}(jQuery));
<|endoftext|>


<commit_before>import { utils } from './utils';

/**
 * Represents a single point in a Wheel3D.
 * @ignore
 */
class VectorPoint {
    /**
     * @ignore
     * @param {number} x - The point's virtual x location.
     * @param {number} y - The point's virtual y location.
     * @param {number} z - The point's virtual z location.
     * @param {Object} sprite - The sprite associated with this point.
     * @param {number} position - The point's position on the Wheel3D.
     */
    constructor(x = 0, y = 0, z = 0, sprite = null, position = 0) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.sprite = sprite;
        this.position = position;
    }
    getSinCosOfAngle(angle) { // eslint-disable-line class-methods-use-this
        const rad = (angle * Math.PI) / 180;
        const cosAngle = Math.cos(rad);
        const sinAngle = Math.sin(rad);

        return { cosine: cosAngle, sine: sinAngle };
    }
    rotateY(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const z = (this.z * angles.cosine) - (this.x * angles.sine);
        const x = (this.z * angles.sine) + (this.x * angles.cosine);

        return new VectorPoint(x, this.y, z);
    }
    rotateX(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const y = (this.y * angles.cosine) - (this.z * angles.sine);
        const z = (this.y * angles.sine) + (this.z * angles.cosine);

        return new VectorPoint(this.x, y, z);
    }
    rotateZ(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const x = (this.x * angles.cosine) - (this.y * angles.sine);
        const y = (this.x * angles.sine) + (this.y * angles.cosine);

        return new VectorPoint(x, y, this.z);
    }
    /** Rotate the point along the given axis by the given angle.
    * @param {string} axis - The axis to rotate.
    * @param {number} angle - The angle to rotate by.
    */
    rotate(axis, angle) {
        if (axis === 'x') {
            return this.rotateX(angle);
        } else if (axis === 'y') {
            return this.rotateY(angle);
        } else if (axis === 'z') {
            return this.rotateZ(angle);
        }

        return null;
    }
    /** Project the point to the correct physical location on screen.
     * z axis is not projected, because screens are 2D.
     */
    project(width, height, factor) {
        const x = (this.x * factor) + width;
        const y = (-this.y * factor) + height;

        return new VectorPoint(x, y, this.z);
    }
}

/**
 * A Wheel of sprites where each item's position is projected in 3D space.
 * The number of points is automatically determined by the number of items.
 */
export class Wheel3D {
    /**
     * @param {Object} game - Reference to current game instance.
     * @param {array} sprites - List of sprites to use in the wheel.
     * @param {Number} firstPlace - Determines which position on the wheel is the active one.
     * @param {Number} zoom - Determines how far to project the points.
     * @param {String} axis - The axis the wheel3D places items around.
     * @param {Object} rotations - Axis and angle to rotate the entire wheel after the initial projection.
     * @param {Object} visibleRange - Determines which items on the wheel should be visible. If none provided, assumes all items should be visible.
     * @param {Object} tweenParams - Array with the duration and easing function for the movement tween.
     */
    constructor(game, xy, sprites, firstPlace, zoom, axis, rotations, visibleRange, tweenParams) {
        this.game = game;
        this.xy = xy;
        this.sprites = sprites;
        this.firstPlace = firstPlace;
        this.zoom = zoom;
        this.axis = axis;
        this.rotationAxis = rotations;
        this.visibleRange = visibleRange || null;
        this.tweenParams = tweenParams || { duration: 300, ease: Phaser.Easing.Quadratic.Out };

        // Signals
        this.onStart = new Phaser.Signal();
        this.onComplete = new Phaser.Signal();
        this.onBackComplete = new Phaser.Signal();
        this.onForwardComplete = new Phaser.Signal();

        // Group to store wheel sprites in, used for zindex sorting.
        this.group = this.game.add.group();
    }
    activate() {
        let angle;
        let radCos;
        let radSin;
        let nx;
        let ny;
        let nz;

        this.pointsAmount = this.sprites.length;
        this.totalPositions = this.pointsAmount - 1;
        this.rotationAmount = 360 / this.pointsAmount;

        // Determines which items in the wheel should be visible.
        if (this.visibleRange !== null) {
            const allPositions = [];
            for (let i = 0; i <= this.totalPositions; i++) {
                allPositions.push(i);
            }

            const maxV = allPositions.slice(0, this.visibleRange.max);
            const minV = allPositions.slice(this.visibleRange.min);

            this.visiblePositions = maxV.concat(minV);
        }

        // Prevents slamming down the move keys.
        this.moving = false;

        // Stores the direction the wheel is moving in.
        this.direction = null;

        // Set point positions on logical circle.
        this.wheelItems = [];
        const radius = 1;
        const slice = (2 * Math.PI) / this.pointsAmount;

        // For a vertical wheel, the X axis is -1. Points are laid out on the Y axis (height) and Z axis (depth). The wheel rotates around the X axis.
        // For a horizontal wheel, the Y Axis is -1. Points are laid out on the X axis (width) and Z axis (depth). The wheel rotates around the Y axis.
        // For flat circular wheel, the Z Axis is -1. Points are laid out on the X axis (width) and Y axis (height). The wheel rotates around the Z axis.
        for (let i = 0; i < this.pointsAmount; i++) {
            // Add sprite to group.
            this.sprites[i].wheelPosition = i;
            this.group.add(this.sprites[i]);

            angle = slice * i;
            radCos = radius * Math.cos(angle);
            radSin = radius * Math.sin(angle);

            if (this.axis === 'x') {
                nx = -1;
                ny = radCos;
                nz = radSin;
            } else if (this.axis === 'y') {
                nx = radCos;
                ny = -1;
                nz = radSin;
            } else if (this.axis === 'z') {
                nx = radCos;
                ny = radSin;
                nz = -1;
            }

            this.wheelItems.push(new VectorPoint(nx, ny, nz, this.sprites[i], i));
        }

        // Active Point
        this.active = this.wheelItems[this.firstPlace].sprite;

        this.project();
    }
    /** Move the wheel backwards. */
    moveBack() {
        if (this.moving === false) {
            this.moving = true;
            this.direction = 0;

            if (this.axis === 'x' || this.axis === 'z') {
                this.rotationAxis[this.axis] += this.rotationAmount;
            } else { // y axis needs to go in the opposite direction.
                this.rotationAxis[this.axis] -= this.rotationAmount;
            }

            this.updatePosition('+');

            this.project();
            this.resetAngle();
        }
    }
    /** Move the wheel forward. */
    moveForward() {
        if (this.moving === false) {
            this.moving = true;
            this.direction = 1;

            if (this.axis === 'x' || this.axis === 'z') {
                this.rotationAxis[this.axis] -= this.rotationAmount;
            } else { // y axis needs to go in the opposite direction.
                this.rotationAxis[this.axis] += this.rotationAmount;
            }

            this.updatePosition('-');

            this.project();
            this.resetAngle();
        }
    }
    /** Project every item in the wheel to it's physical location. */
    project() {
        let newTween;

        // Create a list with the axes, then remove the projected axis.
        const arr = ['x', 'y', 'z'];
        const idx = arr.indexOf(this.axis);
        arr.splice(idx, 1);

        // We only need to call all this when moving. It doesn't need to be done
        // every update
        for (let i = 0; i < this.wheelItems.length; i++) {
            // Rotate along the projected axis
            const rotationOne = this.wheelItems[i].rotate(
                this.axis,
                this.rotationAxis[this.axis],
            );

            // Rotate the other 2 axes
            const rotationTwo = rotationOne.rotate(arr[0], this.rotationAxis[arr[0]]);
            const rotationThree = rotationTwo.rotate(arr[1], this.rotationAxis[arr[1]]);

            const p = rotationThree.project(
                this.xy.x,
                this.xy.y,
                this.zoom,
            );

            const transformed = this.wheelItems[i].sprite;
            transformed.lz = p.z;

            // Ensure active sprite has no scale/alpha changes.
            if (this.wheelItems[i].position === this.firstPlace) {
                transformed.alpha = 1.0;
                this.active = this.wheelItems[i].sprite;
            } else {
                if (this.visibleRange !== null) {
                    const includes = this.visiblePosition.includes(this.wheelItems[i].position);
                    // const includes = _.includes(
                    //    this.visiblePositions,
                    //    this.wheelItems[i].position,
                    // );

                    if (includes) {
                        transformed.alpha = 1.0;
                    } else {
                        transformed.alpha = 0.0;
                    }
                }
            }

            // Tween to new position
            newTween = this.game.add.tween(transformed).to(
                { x: p.x, y: p.y },
                this.tweenParams.duration,
                this.tweenParams.ease,
                true,
            );

            newTween.onComplete.add(this.enableMoving, this);
        }

        // Sort wheelItems by the projection's z axis for correct z-order when drawing.
        this.group.sort('lz', Phaser.Group.SORT_ASCENDING);

        // Wheel's signals are dispatched by the tween's.
        newTween.onStart.add(this.dispatchOnStart, this);
        newTween.onComplete.add(this.dispatchOnComplete, this);
    }
    /** Called after movement starts. */
    dispatchOnStart() {
        this.onStart.dispatch(this);
    }
    /** Called after movement is finished. */
    dispatchOnComplete() {
        if (this.direction === 0) {
            this.onBackComplete.dispatch(this);
        } else if (this.direction === 1) {
            this.onForwardComplete.dispatch(this);
        }

        this.onComplete.dispatch(this);
    }
    /** Once the buttons have finished their move animation, allow them to move again. */
    enableMoving() {
        this.moving = false;
    }
    /** Move all the WheelItem's position by 1. */
    updatePosition(operator) {
        for (let i = 0; i < this.wheelItems.length; i++) {
            const { position } = this.wheelItems[i];
            this.wheelItems[i].position = utils.operators[operator](position, 1);

            const m = utils.modulo(this.wheelItems[i].position, this.pointsAmount);
            this.wheelItems[i].position = m;
            this.wheelItems[i].sprite.wheelPosition = m;
        }
    }
    /** Make sure rotation can't go past 360 in either direction. */
    resetAngle() {
        const angle = this.rotationAxis[this.axis];

        if (angle === 360 || angle === -360) {
            this.rotationAxis[this.axis] = 0;
        }
    }
}
<commit_msg>Wheel3D: Fix typo in var name from ES6 conversion<commit_after>import { utils } from './utils';

/**
 * Represents a single point in a Wheel3D.
 * @ignore
 */
class VectorPoint {
    /**
     * @ignore
     * @param {number} x - The point's virtual x location.
     * @param {number} y - The point's virtual y location.
     * @param {number} z - The point's virtual z location.
     * @param {Object} sprite - The sprite associated with this point.
     * @param {number} position - The point's position on the Wheel3D.
     */
    constructor(x = 0, y = 0, z = 0, sprite = null, position = 0) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.sprite = sprite;
        this.position = position;
    }
    getSinCosOfAngle(angle) { // eslint-disable-line class-methods-use-this
        const rad = (angle * Math.PI) / 180;
        const cosAngle = Math.cos(rad);
        const sinAngle = Math.sin(rad);

        return { cosine: cosAngle, sine: sinAngle };
    }
    rotateY(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const z = (this.z * angles.cosine) - (this.x * angles.sine);
        const x = (this.z * angles.sine) + (this.x * angles.cosine);

        return new VectorPoint(x, this.y, z);
    }
    rotateX(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const y = (this.y * angles.cosine) - (this.z * angles.sine);
        const z = (this.y * angles.sine) + (this.z * angles.cosine);

        return new VectorPoint(this.x, y, z);
    }
    rotateZ(angle) {
        const angles = this.getSinCosOfAngle(angle);
        const x = (this.x * angles.cosine) - (this.y * angles.sine);
        const y = (this.x * angles.sine) + (this.y * angles.cosine);

        return new VectorPoint(x, y, this.z);
    }
    /** Rotate the point along the given axis by the given angle.
    * @param {string} axis - The axis to rotate.
    * @param {number} angle - The angle to rotate by.
    */
    rotate(axis, angle) {
        if (axis === 'x') {
            return this.rotateX(angle);
        } else if (axis === 'y') {
            return this.rotateY(angle);
        } else if (axis === 'z') {
            return this.rotateZ(angle);
        }

        return null;
    }
    /** Project the point to the correct physical location on screen.
     * z axis is not projected, because screens are 2D.
     */
    project(width, height, factor) {
        const x = (this.x * factor) + width;
        const y = (-this.y * factor) + height;

        return new VectorPoint(x, y, this.z);
    }
}

/**
 * A Wheel of sprites where each item's position is projected in 3D space.
 * The number of points is automatically determined by the number of items.
 */
export class Wheel3D {
    /**
     * @param {Object} game - Reference to current game instance.
     * @param {array} sprites - List of sprites to use in the wheel.
     * @param {Number} firstPlace - Determines which position on the wheel is the active one.
     * @param {Number} zoom - Determines how far to project the points.
     * @param {String} axis - The axis the wheel3D places items around.
     * @param {Object} rotations - Axis and angle to rotate the entire wheel after the initial projection.
     * @param {Object} visibleRange - Determines which items on the wheel should be visible. If none provided, assumes all items should be visible.
     * @param {Object} tweenParams - Array with the duration and easing function for the movement tween.
     */
    constructor(game, xy, sprites, firstPlace, zoom, axis, rotations, visibleRange, tweenParams) {
        this.game = game;
        this.xy = xy;
        this.sprites = sprites;
        this.firstPlace = firstPlace;
        this.zoom = zoom;
        this.axis = axis;
        this.rotationAxis = rotations;
        this.visibleRange = visibleRange || null;
        this.tweenParams = tweenParams || { duration: 300, ease: Phaser.Easing.Quadratic.Out };

        // Signals
        this.onStart = new Phaser.Signal();
        this.onComplete = new Phaser.Signal();
        this.onBackComplete = new Phaser.Signal();
        this.onForwardComplete = new Phaser.Signal();

        // Group to store wheel sprites in, used for zindex sorting.
        this.group = this.game.add.group();
    }
    activate() {
        let angle;
        let radCos;
        let radSin;
        let nx;
        let ny;
        let nz;

        this.pointsAmount = this.sprites.length;
        this.totalPositions = this.pointsAmount - 1;
        this.rotationAmount = 360 / this.pointsAmount;

        // Determines which items in the wheel should be visible.
        if (this.visibleRange !== null) {
            const allPositions = [];
            for (let i = 0; i <= this.totalPositions; i++) {
                allPositions.push(i);
            }

            const maxV = allPositions.slice(0, this.visibleRange.max);
            const minV = allPositions.slice(this.visibleRange.min);

            this.visiblePositions = maxV.concat(minV);
        }

        // Prevents slamming down the move keys.
        this.moving = false;

        // Stores the direction the wheel is moving in.
        this.direction = null;

        // Set point positions on logical circle.
        this.wheelItems = [];
        const radius = 1;
        const slice = (2 * Math.PI) / this.pointsAmount;

        // For a vertical wheel, the X axis is -1. Points are laid out on the Y axis (height) and Z axis (depth). The wheel rotates around the X axis.
        // For a horizontal wheel, the Y Axis is -1. Points are laid out on the X axis (width) and Z axis (depth). The wheel rotates around the Y axis.
        // For flat circular wheel, the Z Axis is -1. Points are laid out on the X axis (width) and Y axis (height). The wheel rotates around the Z axis.
        for (let i = 0; i < this.pointsAmount; i++) {
            // Add sprite to group.
            this.sprites[i].wheelPosition = i;
            this.group.add(this.sprites[i]);

            angle = slice * i;
            radCos = radius * Math.cos(angle);
            radSin = radius * Math.sin(angle);

            if (this.axis === 'x') {
                nx = -1;
                ny = radCos;
                nz = radSin;
            } else if (this.axis === 'y') {
                nx = radCos;
                ny = -1;
                nz = radSin;
            } else if (this.axis === 'z') {
                nx = radCos;
                ny = radSin;
                nz = -1;
            }

            this.wheelItems.push(new VectorPoint(nx, ny, nz, this.sprites[i], i));
        }

        // Active Point
        this.active = this.wheelItems[this.firstPlace].sprite;

        this.project();
    }
    /** Move the wheel backwards. */
    moveBack() {
        if (this.moving === false) {
            this.moving = true;
            this.direction = 0;

            if (this.axis === 'x' || this.axis === 'z') {
                this.rotationAxis[this.axis] += this.rotationAmount;
            } else { // y axis needs to go in the opposite direction.
                this.rotationAxis[this.axis] -= this.rotationAmount;
            }

            this.updatePosition('+');

            this.project();
            this.resetAngle();
        }
    }
    /** Move the wheel forward. */
    moveForward() {
        if (this.moving === false) {
            this.moving = true;
            this.direction = 1;

            if (this.axis === 'x' || this.axis === 'z') {
                this.rotationAxis[this.axis] -= this.rotationAmount;
            } else { // y axis needs to go in the opposite direction.
                this.rotationAxis[this.axis] += this.rotationAmount;
            }

            this.updatePosition('-');

            this.project();
            this.resetAngle();
        }
    }
    /** Project every item in the wheel to it's physical location. */
    project() {
        let newTween;

        // Create a list with the axes, then remove the projected axis.
        const arr = ['x', 'y', 'z'];
        const idx = arr.indexOf(this.axis);
        arr.splice(idx, 1);

        // We only need to call all this when moving. It doesn't need to be done
        // every update
        for (let i = 0; i < this.wheelItems.length; i++) {
            // Rotate along the projected axis
            const rotationOne = this.wheelItems[i].rotate(
                this.axis,
                this.rotationAxis[this.axis],
            );

            // Rotate the other 2 axes
            const rotationTwo = rotationOne.rotate(arr[0], this.rotationAxis[arr[0]]);
            const rotationThree = rotationTwo.rotate(arr[1], this.rotationAxis[arr[1]]);

            const p = rotationThree.project(
                this.xy.x,
                this.xy.y,
                this.zoom,
            );

            const transformed = this.wheelItems[i].sprite;
            transformed.lz = p.z;

            // Ensure active sprite has no scale/alpha changes.
            if (this.wheelItems[i].position === this.firstPlace) {
                transformed.alpha = 1.0;
                this.active = this.wheelItems[i].sprite;
            } else {
                if (this.visibleRange !== null) {
                    const includes = this.visiblePositions.includes(this.wheelItems[i].position);
                    // const includes = _.includes(
                    //    this.visiblePositions,
                    //    this.wheelItems[i].position,
                    // );

                    if (includes) {
                        transformed.alpha = 1.0;
                    } else {
                        transformed.alpha = 0.0;
                    }
                }
            }

            // Tween to new position
            newTween = this.game.add.tween(transformed).to(
                { x: p.x, y: p.y },
                this.tweenParams.duration,
                this.tweenParams.ease,
                true,
            );

            newTween.onComplete.add(this.enableMoving, this);
        }

        // Sort wheelItems by the projection's z axis for correct z-order when drawing.
        this.group.sort('lz', Phaser.Group.SORT_ASCENDING);

        // Wheel's signals are dispatched by the tween's.
        newTween.onStart.add(this.dispatchOnStart, this);
        newTween.onComplete.add(this.dispatchOnComplete, this);
    }
    /** Called after movement starts. */
    dispatchOnStart() {
        this.onStart.dispatch(this);
    }
    /** Called after movement is finished. */
    dispatchOnComplete() {
        if (this.direction === 0) {
            this.onBackComplete.dispatch(this);
        } else if (this.direction === 1) {
            this.onForwardComplete.dispatch(this);
        }

        this.onComplete.dispatch(this);
    }
    /** Once the buttons have finished their move animation, allow them to move again. */
    enableMoving() {
        this.moving = false;
    }
    /** Move all the WheelItem's position by 1. */
    updatePosition(operator) {
        for (let i = 0; i < this.wheelItems.length; i++) {
            const { position } = this.wheelItems[i];
            this.wheelItems[i].position = utils.operators[operator](position, 1);

            const m = utils.modulo(this.wheelItems[i].position, this.pointsAmount);
            this.wheelItems[i].position = m;
            this.wheelItems[i].sprite.wheelPosition = m;
        }
    }
    /** Make sure rotation can't go past 360 in either direction. */
    resetAngle() {
        const angle = this.rotationAxis[this.axis];

        if (angle === 360 || angle === -360) {
            this.rotationAxis[this.axis] = 0;
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Released under BSD License
 * Copyright (c) 2014-2015 hizzgdev@163.com
 *
 * Project Home:
 *   https://github.com/hizzgdev/jsmind/
 */

(function($w){
    "use strict";
    var $d = $w.document;
    var __name__ = 'jsMind';
    var jsMind = $w[__name__];
    if(!!jsMind){return;}

    var jdom = jsMind.util.dom;
    var jcanvas = jsMind.util.canvas;

    var clear_selection = "getSelection" in $w ? function(){
         $w.getSelection().removeAllRanges();
    } : function(){
         $d.selection.empty();
    };

    var option = {
        line_width : 5
    };

    jsMind.draggable = function(jm){
        this.jm = jm;
        this.e_canvas = null;
        this.canvas_ctx = null;
        this.shadow = null;
        this.shadow_w = 0;
        this.shadow_h = 0;
        this.active_node = null;
        this.target_node = null;
        this.target_direct = null;
        this.client_w = 0;
        this.client_h = 0;
        this.offset_x = 0;
        this.offset_y = 0;
        this.hlookup = 0;
        this.capture = false;
        this.moved = false;
    };

    jsMind.draggable.prototype = {
        init:function(){
            this._create_canvas();
            this._create_shadow();
            this._event_bind();
        },

        reset:function(){
            this.jm.view.e_nodes.appendChild(this.shadow);
            this.e_canvas.width=this.jm.view.size.w;
            this.e_canvas.height=this.jm.view.size.h;
        },

        _create_canvas:function(){
            var c = $d.createElement('canvas');
            this.jm.view.e_panel.appendChild(c);
            var ctx = c.getContext('2d');
            this.e_canvas = c;
            this.canvas_ctx = ctx;
        },

        _create_shadow:function(){
            var s = $d.createElement('jmnode');
            s.style.visibility = 'hidden';
            s.style.zIndex = '3';
            s.style.cursor = 'move';
            s.style.opacity= '0.7';
            this.shadow = s;
        },

        reset_shadow:function(el){
            var s = this.shadow.style;
            this.shadow.innerHTML = el.innerHTML;
            s.left = el.style.left;
            s.top = el.style.top;
            this.shadow_w = this.shadow.clientWidth;
            this.shadow_h = this.shadow.clientHeight;
        },

        show_shadow:function(){
            if(!this.moved){
                this.shadow.style.visibility = 'visible';
            }
        },

        hide_shadow:function(){
            this.shadow.style.visibility = 'hidden';
        },

        clear_lines:function(){
            jcanvas.clear(this.canvas_ctx, 0, 0, this.jm.view.size.w, this.jm.view.size.h);
        },

        _magnet_shadow:function(node){
            if(!!node){
                this.canvas_ctx.lineWidth = option.line_width;
                this.canvas_ctx.strokeStyle = 'rgba(0,0,0,0.3)';
                this.canvas_ctx.lineCap = 'round';
                this.clear_lines();
                jcanvas.lineto(this.canvas_ctx,
                    node.sp.x,
                    node.sp.y,
                    node.np.x,
                    node.np.y);
            }
        },

        _lookup_close_node:function(){
            var root = this.jm.get_root();
            var root_view_data = root._data.view;
            var root_x = root_view_data.abs_x + root_view_data.width/2;

            var sw = this.shadow_w;
            var sh = this.shadow_h;
            var sx = this.shadow.offsetLeft;
            var sy = this.shadow.offsetTop;

            var nw,nh,nx,ny;

            var direct = (sx + sw/2)>=root_x ?
                            jsMind.direction.right : jsMind.direction.left;
            var nodes = this.jm.mind.nodes;
            var node = null;
            var view_data = null;
            var min_distance = Number.MAX_VALUE;
            var distance = 0;
            var closest_node = null;
            var closest_p = null;
            var shadow_p = null;
            for(var nodeid in nodes){
                var np,sp;
                node = nodes[nodeid];
                if(node.isroot || node.direction == direct){
                    if(node.id == this.active_node.id){
                        continue;
                    }
                    view_data = node._data.view;
                    nw = view_data.width;
                    nh = view_data.height;
                    nx = view_data.abs_x;
                    ny = view_data.abs_y;
                    if(direct == jsMind.direction.right){
                        if(sx-nx-nw<=0){continue;}
                        distance = Math.abs(sx-nx-nw) + Math.abs(sy+sh/2-ny-nh/2);
                        np = {x:nx+nw-option.line_width,y:ny+nh/2};
                        sp = {x:sx+option.line_width,y:sy+sh/2};
                    }else{
                        if(nx-sx-sw<=0){continue;}
                        distance = Math.abs(sx+sw-nx) + Math.abs(sy+sh/2-ny-nh/2);
                        np = {x:nx+option.line_width,y:ny+nh/2};
                        sp = {x:sx+sw-option.line_width,y:sy+sh/2};
                    }
                    if(distance < min_distance){
                        closest_node = node;
                        closest_p = np;
                        shadow_p = sp;
                        min_distance = distance;
                    }
                }
            }
            var result_node = null;
            if(!!closest_node){
                result_node = {
                    node:closest_node,
                    direction:direct,
                    sp:shadow_p,
                    np:closest_p
                };
            }
            return result_node;
        },

        lookup_close_node:function(){
            var node_data = this._lookup_close_node();
            if(!!node_data){
                this._magnet_shadow(node_data);
                this.target_node = node_data.node;
                this.target_direct = node_data.direction;
            }
        },

        _event_bind:function(){
            var jd = this;
            var container = this.jm.view.container;
            jdom.add_event(container,'mousedown',function(e){jd.dragstart.call(jd,e);});
            jdom.add_event(container,'mousemove',function(e){jd.drag.call(jd,e);});
            jdom.add_event(container,'mouseup',function(e){jd.dragend.call(jd,e);});
        },

        dragstart:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){return;}
            this.active_node = null;

            var jview = this.jm.view;
            var el = e.target || event.srcElement;
            var isnode = jview.is_node(el);
            if(isnode){
                var nodeid = jview.get_nodeid(el);
                var node = this.jm.get_node(nodeid);
                if(!node.isroot){
                    this.reset_shadow(el);
                    this.active_node = node;
                    this.offset_x = e.clientX - el.offsetLeft;
                    this.offset_y = e.clientY - el.offsetTop;
                    this.client_hw = Math.floor(el.clientWidth/2);
                    this.client_hh = Math.floor(el.clientHeight/2);
                    if(this.hlookup != 0){
                        $w.clearInterval(this.hlookup);
                    }
                    var jd = this;
                    this.hlookup = $w.setInterval(function(){
                        jd.lookup_close_node.call(jd);
                    },400);
                    this.capture = true;
                }
            }
        },

        drag:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){
                this.show_shadow();
                this.moved = true;
                clear_selection();
                var px = e.clientX - this.offset_x;
                var py = e.clientY - this.offset_y;
                var cx = px + this.client_hw;
                var cy = py + this.client_hh;
                this.shadow.style.left = px + 'px';
                this.shadow.style.top = py + 'px';
                clear_selection();
            }
        },

        dragend:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){
                if(this.hlookup != 0){
                    $w.clearInterval(this.hlookup);
                    this.hlookup = 0;
                    this.clear_lines();
                }
                if(this.moved){
                    var src_node = this.active_node;
                    var target_node = this.target_node;
                    var target_direct = this.target_direct;
                    this.move_node(src_node,target_node,target_direct);
                }
                this.hide_shadow();
            }
            this.moved = false;
            this.capture = false;
        },

        move_node:function(src_node,target_node,target_direct){
            var shadow_h = this.shadow.offsetTop;
            if(!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)){
                // lookup before_node
                var sibling_nodes = target_node.children;
                var sc = sibling_nodes.length;
                var node = null;
                var node_h = null;
                var delta_y = Number.MAX_VALUE;
                var node_before = null;
                var beforeid = '_last_';
                while(sc--){
                    node = sibling_nodes[sc];
                    if(node.direction == target_direct && node.id != src_node.id){
                        node_h = node._data.view.abs_y;
                        var dy = node_h - shadow_h;
                        if(dy > 0 && dy < delta_y){
                            delta_y = dy;
                            node_before = node;
                            beforeid = '_first_';
                        }
                    }
                }
                if(!!node_before){beforeid = node_before.id;}
                this.jm.move_node(src_node, beforeid, target_node.id, target_direct);
            }
            this.active_node = null;
            this.target_node = null;
            this.target_direct = null;
        }
    };

    var jm_event_handle = function(jm, type, data){
        if(type === 'init'){
            var jd = new jsMind.draggable(jm);
            jd.init();
            jm.draggable = jd;
        }
        if(type === 'show'){//reset
            var jd = jm.draggable;
            if(!!jd){
                jd.reset();
            }
        }
    };

    jsMind.add_event_handle(jm_event_handle);
})(window);
<commit_msg>fix bug<commit_after>/*
 * Released under BSD License
 * Copyright (c) 2014-2015 hizzgdev@163.com
 *
 * Project Home:
 *   https://github.com/hizzgdev/jsmind/
 */

(function($w){
    "use strict";
    var $d = $w.document;
    var __name__ = 'jsMind';
    var jsMind = $w[__name__];
    if(!jsMind){return;}

    var jdom = jsMind.util.dom;
    var jcanvas = jsMind.util.canvas;

    var clear_selection = "getSelection" in $w ? function(){
         $w.getSelection().removeAllRanges();
    } : function(){
         $d.selection.empty();
    };

    var options = {
        line_width : 5,
        lookup_interval : 30
    };

    jsMind.draggable = function(jm){
        this.jm = jm;
        this.e_canvas = null;
        this.canvas_ctx = null;
        this.shadow = null;
        this.shadow_w = 0;
        this.shadow_h = 0;
        this.active_node = null;
        this.target_node = null;
        this.target_direct = null;
        this.client_w = 0;
        this.client_h = 0;
        this.offset_x = 0;
        this.offset_y = 0;
        this.hlookup = 0;
        this.capture = false;
        this.moved = false;
    };

    jsMind.draggable.prototype = {
        init:function(){
            this._create_canvas();
            this._create_shadow();
            this._event_bind();
        },

        reset:function(){
            this.jm.view.e_nodes.appendChild(this.shadow);
            this.e_canvas.width=this.jm.view.size.w;
            this.e_canvas.height=this.jm.view.size.h;
        },

        _create_canvas:function(){
            var c = $d.createElement('canvas');
            this.jm.view.e_panel.appendChild(c);
            var ctx = c.getContext('2d');
            this.e_canvas = c;
            this.canvas_ctx = ctx;
        },

        _create_shadow:function(){
            var s = $d.createElement('jmnode');
            s.style.visibility = 'hidden';
            s.style.zIndex = '3';
            s.style.cursor = 'move';
            s.style.opacity= '0.7';
            this.shadow = s;
        },

        reset_shadow:function(el){
            var s = this.shadow.style;
            this.shadow.innerHTML = el.innerHTML;
            s.left = el.style.left;
            s.top = el.style.top;
            this.shadow_w = this.shadow.clientWidth;
            this.shadow_h = this.shadow.clientHeight;
        },

        show_shadow:function(){
            if(!this.moved){
                this.shadow.style.visibility = 'visible';
            }
        },

        hide_shadow:function(){
            this.shadow.style.visibility = 'hidden';
        },

        clear_lines:function(){
            jcanvas.clear(this.canvas_ctx, 0, 0, this.jm.view.size.w, this.jm.view.size.h);
        },

        _magnet_shadow:function(node){
            if(!!node){
                this.canvas_ctx.lineWidth = options.line_width;
                this.canvas_ctx.strokeStyle = 'rgba(0,0,0,0.3)';
                this.canvas_ctx.lineCap = 'round';
                this.clear_lines();
                jcanvas.lineto(this.canvas_ctx,
                    node.sp.x,
                    node.sp.y,
                    node.np.x,
                    node.np.y);
            }
        },

        _lookup_close_node:function(){
            var root = this.jm.get_root();
            var root_view_data = root._data.view;
            var root_x = root_view_data.abs_x + root_view_data.width/2;

            var sw = this.shadow_w;
            var sh = this.shadow_h;
            var sx = this.shadow.offsetLeft;
            var sy = this.shadow.offsetTop;

            var nw,nh,nx,ny;

            var direct = (sx + sw/2)>=root_x ?
                            jsMind.direction.right : jsMind.direction.left;
            var nodes = this.jm.mind.nodes;
            var node = null;
            var view_data = null;
            var min_distance = Number.MAX_VALUE;
            var distance = 0;
            var closest_node = null;
            var closest_p = null;
            var shadow_p = null;
            for(var nodeid in nodes){
                var np,sp;
                node = nodes[nodeid];
                if(node.isroot || node.direction == direct){
                    if(node.id == this.active_node.id){
                        continue;
                    }
                    view_data = node._data.view;
                    nw = view_data.width;
                    nh = view_data.height;
                    nx = view_data.abs_x;
                    ny = view_data.abs_y;
                    if(direct == jsMind.direction.right){
                        if(sx-nx-nw<=0){continue;}
                        distance = Math.abs(sx-nx-nw) + Math.abs(sy+sh/2-ny-nh/2);
                        np = {x:nx+nw-options.line_width,y:ny+nh/2};
                        sp = {x:sx+options.line_width,y:sy+sh/2};
                    }else{
                        if(nx-sx-sw<=0){continue;}
                        distance = Math.abs(sx+sw-nx) + Math.abs(sy+sh/2-ny-nh/2);
                        np = {x:nx+options.line_width,y:ny+nh/2};
                        sp = {x:sx+sw-options.line_width,y:sy+sh/2};
                    }
                    if(distance < min_distance){
                        closest_node = node;
                        closest_p = np;
                        shadow_p = sp;
                        min_distance = distance;
                    }
                }
            }
            var result_node = null;
            if(!!closest_node){
                result_node = {
                    node:closest_node,
                    direction:direct,
                    sp:shadow_p,
                    np:closest_p
                };
            }
            return result_node;
        },

        lookup_close_node:function(){
            var node_data = this._lookup_close_node();
            if(!!node_data){
                this._magnet_shadow(node_data);
                this.target_node = node_data.node;
                this.target_direct = node_data.direction;
            }
        },

        _event_bind:function(){
            var jd = this;
            var container = this.jm.view.container;
            jdom.add_event(container,'mousedown',function(e){jd.dragstart.call(jd,e);});
            jdom.add_event(container,'mousemove',function(e){jd.drag.call(jd,e);});
            jdom.add_event(container,'mouseup',function(e){jd.dragend.call(jd,e);});
        },

        dragstart:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){return;}
            this.active_node = null;

            var jview = this.jm.view;
            var el = e.target || event.srcElement;
            var isnode = jview.is_node(el);
            if(isnode){
                var nodeid = jview.get_nodeid(el);
                var node = this.jm.get_node(nodeid);
                if(!node.isroot){
                    this.reset_shadow(el);
                    this.active_node = node;
                    this.offset_x = e.clientX - el.offsetLeft;
                    this.offset_y = e.clientY - el.offsetTop;
                    this.client_hw = Math.floor(el.clientWidth/2);
                    this.client_hh = Math.floor(el.clientHeight/2);
                    if(this.hlookup != 0){
                        $w.clearInterval(this.hlookup);
                    }
                    var jd = this;
                    this.hlookup = $w.setInterval(function(){
                        jd.lookup_close_node.call(jd);
                    },options.lookup_interval);
                    this.capture = true;
                }
            }
        },

        drag:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){
                this.show_shadow();
                this.moved = true;
                clear_selection();
                var px = e.clientX - this.offset_x;
                var py = e.clientY - this.offset_y;
                var cx = px + this.client_hw;
                var cy = py + this.client_hh;
                this.shadow.style.left = px + 'px';
                this.shadow.style.top = py + 'px';
                clear_selection();
            }
        },

        dragend:function(e){
            if(!this.jm.get_editable()){return;}
            if(this.capture){
                if(this.hlookup != 0){
                    $w.clearInterval(this.hlookup);
                    this.hlookup = 0;
                    this.clear_lines();
                }
                if(this.moved){
                    var src_node = this.active_node;
                    var target_node = this.target_node;
                    var target_direct = this.target_direct;
                    this.move_node(src_node,target_node,target_direct);
                }
                this.hide_shadow();
            }
            this.moved = false;
            this.capture = false;
        },

        move_node:function(src_node,target_node,target_direct){
            var shadow_h = this.shadow.offsetTop;
            if(!!target_node && !!src_node && !jsMind.node.inherited(src_node, target_node)){
                // lookup before_node
                var sibling_nodes = target_node.children;
                var sc = sibling_nodes.length;
                var node = null;
                var node_h = null;
                var delta_y = Number.MAX_VALUE;
                var node_before = null;
                var beforeid = '_last_';
                while(sc--){
                    node = sibling_nodes[sc];
                    if(node.direction == target_direct && node.id != src_node.id){
                        node_h = node._data.view.abs_y;
                        var dy = node_h - shadow_h;
                        if(dy > 0 && dy < delta_y){
                            delta_y = dy;
                            node_before = node;
                            beforeid = '_first_';
                        }
                    }
                }
                if(!!node_before){beforeid = node_before.id;}
                this.jm.move_node(src_node, beforeid, target_node.id, target_direct);
            }
            this.active_node = null;
            this.target_node = null;
            this.target_direct = null;
        }
    };

    var jm_event_handle = function(jm, type, data){
        if(type === 'init'){
            var jd = new jsMind.draggable(jm);
            jd.init();
            jm.draggable = jd;
        }
        if(type === 'show'){//reset
            var jd = jm.draggable;
            if(!!jd){
                jd.reset();
            }
        }
    };

    jsMind.add_event_handle(jm_event_handle);
})(window);
<|endoftext|>