<commit_before>'use strict';

angular.module('JSONedit', ['ui.sortable'])
.directive('ngModelOnblur', function() {
    // override the default input to update on blur
    // from http://jsfiddle.net/cn8VF/
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });
            });
        }
    };
})
.directive('json', function($compile) {
  return {
    restrict: 'E',
    scope: {
      child: '=',
      type: '@',
      defaultCollapsed: '='
    },
    link: function(scope, element, attributes) {
        var stringName = "Text";
        var objectName = "Object";
        var arrayName = "Array";
        var refName = "Reference";

        scope.valueTypes = [stringName, objectName, arrayName, refName];
        scope.sortableOptions = {
            axis: 'y'
        };
        if (scope.$parent.defaultCollapsed === undefined) {
            scope.collapsed = false;
        } else {
            scope.collapsed = scope.defaultCollapsed;
        }
        if (scope.collapsed) {
            scope.chevron = "glyphicon-chevron-right";
        } else {
            scope.chevron = "glyphicon-chevron-down";
        }

        //////
        // Helper functions
        //////

        var getType = function(obj) {
            var type = Object.prototype.toString.call(obj);
            if (type === "[object Object]") {
                return "Object";
            } else if(type === "[object Array]"){
                return "Array";
            } else {
                return "Literal";
            }
        };
        var isNumber = function(n) {
          return !isNaN(parseFloat(n)) && isFinite(n);
        };
        scope.getType = function(obj) {
            return getType(obj);
        };
        scope.toggleCollapse = function() {
            if (scope.collapsed) {
                scope.collapsed = false;
                scope.chevron = "glyphicon-chevron-down";
            } else {
                scope.collapsed = true;
                scope.chevron = "glyphicon-chevron-right";
            }
        };
        scope.moveKey = function(obj, key, newkey) {
            //moves key to newkey in obj
            if (key !== newkey) {
                obj[newkey] = obj[key];
                delete obj[key];
            }
        };
        scope.deleteKey = function(obj, key) {
            if (getType(obj) == "Object") {
                if( confirm('Delete "'+key+'" and all it contains?') ) {
                    delete obj[key];
                }
            } else if (getType(obj) == "Array") {
                if( confirm('Delete "'+obj[key]+'"?') ) {
                    obj.splice(key, 1);
                }
            } else {
                console.error("object to delete from was " + obj);
            }
        };
        scope.addItem = function(obj) {
            if (getType(obj) == "Object") {
                // check input for key
                if (scope.keyName == undefined || scope.keyName.length == 0){
                    alert("Please fill in a name");
                } else if (scope.keyName.indexOf("$") == 0){
                    alert("The name may not start with $ (the dollar sign)");
                } else if (scope.keyName.indexOf("_") == 0){
                    alert("The name may not start with _ (the underscore)");
                } else {
                    if (obj[scope.keyName]) {
                        if( !confirm('An item with the name "'+scope.keyName
                            +'" exists already. Do you really want to replace it?') ) {
                            return;
                        }
                    }
                    // add item to object
                    switch(scope.valueType) {
                        case stringName: obj[scope.keyName] = scope.valueName ? scope.possibleNumber(scope.valueName) : "";
                                        break;
                        case objectName:  obj[scope.keyName] = {};
                                        break;
                        case arrayName:   obj[scope.keyName] = [];
                                        break;
                        case refName: obj[scope.keyName] = {"Reference!!!!": "todo"};
                                        break;
                    }
                    //clean-up
                    scope.keyName = "";
                    scope.valueName = "";
                    scope.showAddKey = false;
                }
            } else if (getType(obj) == "Array") {
                // add item to array
                switch(scope.valueType) {
                    case stringName: obj.push(scope.valueName ? scope.valueName : "");
                                    break;
                    case objectName:  obj.push({});
                                    break;
                    case arrayName:   obj.push([]);
                                    break;
                    case refName: obj.push({"Reference!!!!": "todo"});
                                    break;
                }
                scope.valueName = "";
                scope.showAddKey = false;
            } else {
                console.error("object to add to was " + obj);
            }
        };
        scope.possibleNumber = function(val) {
            return isNumber(val) ? parseFloat(val) : val;
        };

        //////
        // Template Generation
        //////

        // Note:
        // sometimes having a different ng-model and then saving it on ng-change
        // into the object or array is necesarry for all updates to work

        // recursion
        var switchTemplate =
            ''
                + '<json ng-switch-when="Object" child="val" type="object" default-collapsed="defaultCollapsed"></json>'
                + '<json ng-switch-when="Array" child="val" type="array" default-collapsed="defaultCollapsed"></json>'
                + '<input type="text" ng-model="val" '
                    + 'placeholder="Empty" ng-model-onblur ng-change="child[key] = possibleNumber(val)"/>'
                + ''
            + '';

        // display either "plus button" or "key-value inputs"
        var addItemTemplate =
        '
'
            + '';
                if (scope.type == "object"){
                   // input key
                    addItemTemplate += '<input placeholder="Name" type="text" ui-keyup="{\'enter\':\'addItem(child)\'}" '
                        + 'class="form-control input-sm addItemKeyInput" ng-model="$parent.keyName" /> ';
                }
                addItemTemplate +=
                // value type dropdown
                '<select ng-model="$parent.valueType" ng-options="option for option in valueTypes" class="form-control input-sm"'
                    + 'ng-init="$parent.valueType=\''+stringName+'\'" ui-keydown="{\'enter\':\'addItem(child)\'}"></select>'
                // input value
                + ' : <input type="text" placeholder="Value" '
                    + 'class="form-control input-sm addItemValueInput" ng-model="$parent.valueName" ui-keyup="{\'enter\':\'addItem(child)\'}"/> '
                // Add button
                + '<button class="btn btn-primary btn-sm" ng-click="addItem(child)">Add</button> '
                + '<button class="btn btn-default btn-sm" ng-click="$parent.showAddKey=false">Cancel</button>'
            + ''
            + ''
                // plus button
                + '<button class="addObjectItemBtn" ng-click="$parent.showAddKey = true"></button>'
            + ''
        + '
';

        // start template
        if (scope.type == "object"){
            var template = ''
            + ''+objectName+''
            + '
'
                // repeat
                + ''
                    // object key
                    + ''
                        + '<input class="keyinput" type="text" ng-model="newkey" ng-init="newkey=key" '
                            + 'ng-blur="moveKey(child, key, newkey)"/>'
                        // delete button
                        + ''
                    + ''
                    // object value
                    + '' + switchTemplate + ''
                + ''
                // repeat end
                + addItemTemplate
            + '
';
        } else if (scope.type == "array") {
            var template = ''
            + ''+arrayName+''
            + '
'
                + '
'
                    // repeat
                    + '
'
                        // delete button
                        + ''
                        + ''
                        + '' + switchTemplate + ''
                    + '
'
                    // repeat end
                + '
'
                + addItemTemplate
            + '
';
        } else {
            console.error("scope.type was "+ scope.type);
        }

        var newElement = angular.element(template);
        $compile(newElement)(scope);
        element.empty().html(newElement);
    }
  };
});

<commit_msg>changed element empty with replaceWith<commit_after>'use strict';

angular.module('JSONedit', ['ui.sortable'])
.directive('ngModelOnblur', function() {
    // override the default input to update on blur
    // from http://jsfiddle.net/cn8VF/
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });
            });
        }
    };
})
.directive('json', function($compile) {
  return {
    restrict: 'E',
    scope: {
      child: '=',
      type: '@',
      defaultCollapsed: '='
    },
    link: function(scope, element, attributes) {
        var stringName = "Text";
        var objectName = "Object";
        var arrayName = "Array";
        var refName = "Reference";

        scope.valueTypes = [stringName, objectName, arrayName, refName];
        scope.sortableOptions = {
            axis: 'y'
        };
        if (scope.$parent.defaultCollapsed === undefined) {
            scope.collapsed = false;
        } else {
            scope.collapsed = scope.defaultCollapsed;
        }
        if (scope.collapsed) {
            scope.chevron = "glyphicon-chevron-right";
        } else {
            scope.chevron = "glyphicon-chevron-down";
        }

        //////
        // Helper functions
        //////

        var getType = function(obj) {
            var type = Object.prototype.toString.call(obj);
            if (type === "[object Object]") {
                return "Object";
            } else if(type === "[object Array]"){
                return "Array";
            } else {
                return "Literal";
            }
        };
        var isNumber = function(n) {
          return !isNaN(parseFloat(n)) && isFinite(n);
        };
        scope.getType = function(obj) {
            return getType(obj);
        };
        scope.toggleCollapse = function() {
            if (scope.collapsed) {
                scope.collapsed = false;
                scope.chevron = "glyphicon-chevron-down";
            } else {
                scope.collapsed = true;
                scope.chevron = "glyphicon-chevron-right";
            }
        };
        scope.moveKey = function(obj, key, newkey) {
            //moves key to newkey in obj
            if (key !== newkey) {
                obj[newkey] = obj[key];
                delete obj[key];
            }
        };
        scope.deleteKey = function(obj, key) {
            if (getType(obj) == "Object") {
                if( confirm('Delete "'+key+'" and all it contains?') ) {
                    delete obj[key];
                }
            } else if (getType(obj) == "Array") {
                if( confirm('Delete "'+obj[key]+'"?') ) {
                    obj.splice(key, 1);
                }
            } else {
                console.error("object to delete from was " + obj);
            }
        };
        scope.addItem = function(obj) {
            if (getType(obj) == "Object") {
                // check input for key
                if (scope.keyName == undefined || scope.keyName.length == 0){
                    alert("Please fill in a name");
                } else if (scope.keyName.indexOf("$") == 0){
                    alert("The name may not start with $ (the dollar sign)");
                } else if (scope.keyName.indexOf("_") == 0){
                    alert("The name may not start with _ (the underscore)");
                } else {
                    if (obj[scope.keyName]) {
                        if( !confirm('An item with the name "'+scope.keyName
                            +'" exists already. Do you really want to replace it?') ) {
                            return;
                        }
                    }
                    // add item to object
                    switch(scope.valueType) {
                        case stringName: obj[scope.keyName] = scope.valueName ? scope.possibleNumber(scope.valueName) : "";
                                        break;
                        case objectName:  obj[scope.keyName] = {};
                                        break;
                        case arrayName:   obj[scope.keyName] = [];
                                        break;
                        case refName: obj[scope.keyName] = {"Reference!!!!": "todo"};
                                        break;
                    }
                    //clean-up
                    scope.keyName = "";
                    scope.valueName = "";
                    scope.showAddKey = false;
                }
            } else if (getType(obj) == "Array") {
                // add item to array
                switch(scope.valueType) {
                    case stringName: obj.push(scope.valueName ? scope.valueName : "");
                                    break;
                    case objectName:  obj.push({});
                                    break;
                    case arrayName:   obj.push([]);
                                    break;
                    case refName: obj.push({"Reference!!!!": "todo"});
                                    break;
                }
                scope.valueName = "";
                scope.showAddKey = false;
            } else {
                console.error("object to add to was " + obj);
            }
        };
        scope.possibleNumber = function(val) {
            return isNumber(val) ? parseFloat(val) : val;
        };

        //////
        // Template Generation
        //////

        // Note:
        // sometimes having a different ng-model and then saving it on ng-change
        // into the object or array is necesarry for all updates to work

        // recursion
        var switchTemplate =
            ''
                + '<json ng-switch-when="Object" child="val" type="object" default-collapsed="defaultCollapsed"></json>'
                + '<json ng-switch-when="Array" child="val" type="array" default-collapsed="defaultCollapsed"></json>'
                + '<input type="text" ng-model="val" '
                    + 'placeholder="Empty" ng-model-onblur ng-change="child[key] = possibleNumber(val)"/>'
                + ''
            + '';

        // display either "plus button" or "key-value inputs"
        var addItemTemplate =
        '
'
            + '';
                if (scope.type == "object"){
                   // input key
                    addItemTemplate += '<input placeholder="Name" type="text" ui-keyup="{\'enter\':\'addItem(child)\'}" '
                        + 'class="form-control input-sm addItemKeyInput" ng-model="$parent.keyName" /> ';
                }
                addItemTemplate +=
                // value type dropdown
                '<select ng-model="$parent.valueType" ng-options="option for option in valueTypes" class="form-control input-sm"'
                    + 'ng-init="$parent.valueType=\''+stringName+'\'" ui-keydown="{\'enter\':\'addItem(child)\'}"></select>'
                // input value
                + ' : <input type="text" placeholder="Value" '
                    + 'class="form-control input-sm addItemValueInput" ng-model="$parent.valueName" ui-keyup="{\'enter\':\'addItem(child)\'}"/> '
                // Add button
                + '<button class="btn btn-primary btn-sm" ng-click="addItem(child)">Add</button> '
                + '<button class="btn btn-default btn-sm" ng-click="$parent.showAddKey=false">Cancel</button>'
            + ''
            + ''
                // plus button
                + '<button class="addObjectItemBtn" ng-click="$parent.showAddKey = true"></button>'
            + ''
        + '
';

        // start template
        if (scope.type == "object"){
            var template = ''
            + ''+objectName+''
            + '
'
                // repeat
                + ''
                    // object key
                    + ''
                        + '<input class="keyinput" type="text" ng-model="newkey" ng-init="newkey=key" '
                            + 'ng-blur="moveKey(child, key, newkey)"/>'
                        // delete button
                        + ''
                    + ''
                    // object value
                    + '' + switchTemplate + ''
                + ''
                // repeat end
                + addItemTemplate
            + '
';
        } else if (scope.type == "array") {
            var template = ''
            + ''+arrayName+''
            + '
'
                + '
'
                    // repeat
                    + '
'
                        // delete button
                        + ''
                        + ''
                        + '' + switchTemplate + ''
                    + '
'
                    // repeat end
                + '
'
                + addItemTemplate
            + '
';
        } else {
            console.error("scope.type was "+ scope.type);
        }

        var newElement = angular.element(template);
        $compile(newElement)(scope);
        element.replaceWith ( newElement );
    }
  };
});
<|endoftext|>


<commit_before>var tliRegister = tliRegister || {};

tliRegister.discountCodes = function() {

	var init = function() {
		initCodeItemEnabling();
	},

	initCodeItemEnabling = function() {
		$('#discount-code-items input:checkbox')
			.change(handlePricingItemChange)
			.each(handlePricingItemChange);
	},

	handlePricingItemChange = function() {
		var row = $(this).closest('tr'),
			chekbox = this;

		$('input[type=number]', row)
			.prop('disabled', !$(chekbox).prop('checked'))
			.each(function() {
				if (!$(chekbox).prop('checked')) {
					$(this).val($(this).attr('data-value-original'));
				}
			});
	}

	return {
		init: init
	}

}();
<commit_msg>Reset validation status on unchecking item<commit_after>var tliRegister = tliRegister || {};

tliRegister.discountCodes = function() {

	var init = function() {
		initCodeItemEnabling();
	},

	initCodeItemEnabling = function() {
		$('#discount-code-items input:checkbox')
			.change(handlePricingItemChange)
			.each(handlePricingItemChange);
	},

	handlePricingItemChange = function() {
		var row = $(this).closest('tr'),
			chekbox = this;

		$('input[type=number]', row)
			.prop('disabled', !$(chekbox).prop('checked'))
			.each(function() {
				if (!$(chekbox).prop('checked')) {
					$(this).val($(this).attr('data-value-original'));
					$('.has-error', row).each(function() {
						$(this).children('.help-block').slideUp(function() {
							$(this).remove();
						});
						$(this).removeClass('has-error');
					});
				}
			});
	}

	return {
		init: init
	}

}();
<|endoftext|>


<commit_before>jQuery(function ($) {
    "use strict";

    var Promise = window.Promise;
    if (!Promise) {
        Promise = JSZip.external.Promise;
    }

    /**
     * Reset the message.
     */
    function resetMessage () {
        $("#result")
        .removeClass()
        .text("");
    }
    /**
     * show a successful message.
     * @param {String} text the text to show.
     */
    function showMessage(text) {
        resetMessage();
        $("#result")
        .addClass("alert alert-success")
        .text(text);
    }
    /**
     * show an error message.
     * @param {String} text the text to show.
     */
    function showError(text) {
        resetMessage();
        $("#result")
        .addClass("alert alert-danger")
        .text(text);
    }
    /**
     * Update the progress bar.
     * @param {Integer} percent the current percent
     */
    function updatePercent(percent) {
        $("#progress_bar").removeClass("hide")
        .find(".progress-bar")
        .attr("aria-valuenow", percent)
        .css({
            width : percent + "%"
        });
    }

    /**
     * Fetch the content and return the associated promise.
     * @param {String} url the url of the content to fetch.
     * @return {Promise} the promise containing the data.
     */
    function urlToPromise(url) {
        return new Promise(function(resolve, reject) {
            JSZipUtils.getBinaryContent(url, function (err, data) {
                if(err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }

    if(!JSZip.support.blob) {
        showError("This only works with a good browser!");
        return;
    }

    var $form = $("#download_form").on("submit", function () {

        resetMessage();

        var zip = new JSZip();

        // find every checked item
        $(this).find(":checked").each(function () {
			var customs = new Array("");
            var $this = $(this);
            var url = $this.data("url");
			var iswhat = $this.data("name");
            var filename = url.replace(/.*\//g, "");   //using static filenames for gfx cfg
			if(iswhat == "gfx") {
				zip.file("cfg/gfx.cfg", urlToPromise(url), {binary:true});
            }
			if(iswhat == "scripts") {
				zip.file("custom/runfasterpls/scripts/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "vpks") {
				zip.file("custom/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "configs") {
				zip.file("cfg/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "tweaks") {
				zip.file("cfg/tweaks/" + filename, urlToPromise(url), {binary:true});
				customs.push("exec " + filename);
            }
        });
		//building and downloading static configs
		zip.file("cfg/autoexec.cfg", "exec gfx\nexec binds\nexec custom"); 				//autoexec
		zip.file("cfg/binds.cfg", urlToPromise("/cfgen/cfg/binds.cfg"), {binary:true}); 	//binds
		var cexecs = "";																//writing custom execs to a single variable
 		customs.forEach(function(entry) {
			cexecs = entry + "\n";
			}
		zip.file('cfg/custom.cfg', cexecs + 'echo "------------- Thanks for using config generator by 200 -------------"\necho "------------- Create your own custom config at https://mkrl.github.io/cfgen/ -------------"\necho "------------- Type the following to run the scripts you installed: -------------"'); //load custom tweaks and config

        // when everything has been downloaded, we can trigger the dl
        zip.generateAsync({type:"blob"}, function updateCallback(metadata) {
            var msg = "Packing : " + metadata.percent.toFixed(2) + " %";
            if(metadata.currentFile) {
                msg += ", current file = " + metadata.currentFile;
            }
            showMessage(msg);
            updatePercent(metadata.percent|0);
        })
        .then(function callback(blob) {

            // see FileSaver.js
            saveAs(blob, "config.zip");

            showMessage("Enjoy your custom stuff!");
        }, function (e) {
            showError(e);
        });

        return false;
    });
});

// vim: set shiftwidth=4 softtabstop=4:
<commit_msg>More syntax error fixies<commit_after>jQuery(function ($) {
    "use strict";

    var Promise = window.Promise;
    if (!Promise) {
        Promise = JSZip.external.Promise;
    }

    /**
     * Reset the message.
     */
    function resetMessage () {
        $("#result")
        .removeClass()
        .text("");
    }
    /**
     * show a successful message.
     * @param {String} text the text to show.
     */
    function showMessage(text) {
        resetMessage();
        $("#result")
        .addClass("alert alert-success")
        .text(text);
    }
    /**
     * show an error message.
     * @param {String} text the text to show.
     */
    function showError(text) {
        resetMessage();
        $("#result")
        .addClass("alert alert-danger")
        .text(text);
    }
    /**
     * Update the progress bar.
     * @param {Integer} percent the current percent
     */
    function updatePercent(percent) {
        $("#progress_bar").removeClass("hide")
        .find(".progress-bar")
        .attr("aria-valuenow", percent)
        .css({
            width : percent + "%"
        });
    }

    /**
     * Fetch the content and return the associated promise.
     * @param {String} url the url of the content to fetch.
     * @return {Promise} the promise containing the data.
     */
    function urlToPromise(url) {
        return new Promise(function(resolve, reject) {
            JSZipUtils.getBinaryContent(url, function (err, data) {
                if(err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }

    if(!JSZip.support.blob) {
        showError("This only works with a good browser!");
        return;
    }

    var $form = $("#download_form").on("submit", function () {

        resetMessage();

        var zip = new JSZip();

        // find every checked item
        $(this).find(":checked").each(function () {
			var customs = new Array("");
            var $this = $(this);
            var url = $this.data("url");
			var iswhat = $this.data("name");
            var filename = url.replace(/.*\//g, "");   //using static filenames for gfx cfg
			if(iswhat == "gfx") {
				zip.file("cfg/gfx.cfg", urlToPromise(url), {binary:true});
            }
			if(iswhat == "scripts") {
				zip.file("custom/runfasterpls/scripts/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "vpks") {
				zip.file("custom/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "configs") {
				zip.file("cfg/" + filename, urlToPromise(url), {binary:true});
            }
			if(iswhat == "tweaks") {
				zip.file("cfg/tweaks/" + filename, urlToPromise(url), {binary:true});
				customs.push("exec " + filename);
            }
        });
		//building and downloading static configs
		zip.file("cfg/autoexec.cfg", "exec gfx\nexec binds\nexec custom"); 				//autoexec
		zip.file("cfg/binds.cfg", urlToPromise("/cfgen/cfg/binds.cfg"), {binary:true}); 	//binds
		var cexecs = "";																//writing custom execs to a single variable
 		customs.forEach(function(entry) {
			cexecs = entry + "\n";
			});
		zip.file('cfg/custom.cfg', cexecs + 'echo "------------- Thanks for using config generator by 200 -------------"\necho "------------- Create your own custom config at https://mkrl.github.io/cfgen/ -------------"\necho "------------- Type the following to run the scripts you installed: -------------"'); //load custom tweaks and config

        // when everything has been downloaded, we can trigger the dl
        zip.generateAsync({type:"blob"}, function updateCallback(metadata) {
            var msg = "Packing : " + metadata.percent.toFixed(2) + " %";
            if(metadata.currentFile) {
                msg += ", current file = " + metadata.currentFile;
            }
            showMessage(msg);
            updatePercent(metadata.percent|0);
        })
        .then(function callback(blob) {

            // see FileSaver.js
            saveAs(blob, "config.zip");

            showMessage("Enjoy your custom stuff!");
        }, function (e) {
            showError(e);
        });

        return false;
    });
});

// vim: set shiftwidth=4 softtabstop=4:
<|endoftext|>


<commit_before>/**
 * @class Garp.FormPanel
 * @extends Ext.FormPanel
 * @author Peter
 */

Garp.FormPanel = Ext.extend(Ext.FormPanel, {

	/**
	 * @cfg defaults:
	 */
	layout: 'fit',
	hideMode: 'offsets',
	monitorValid: true,
	trackResetOnLoad: false,
	clientValidation: true,

	/**
	 * private
	 */
	state: null,

	/**
	 * Sets the UI for all dirty / undirty / phantom combinations
	 * It enables / disabled buttons and such. It also fires 'dirty' & 'undirty' events
	 * It keeps track of the previous state for performance reasons
	 */
	updateUI: function(){
		if(!this.rec || !this.formcontent.rendered || this.hidden){
			return;
		}

		var
		PHANTOM_VALID = 1,
		PHANTOM_INVALID = 2,
		EXISTING_NON_DIRTY_VALID = 4,
		EXISTING_NON_DIRTY_INVALID = 8,
		EXISTING_DIRTY_VALID = 16,
		EXISTING_DIRTY_INVALID = 32;

		var valid = this.getForm().isValid();
		var dirty = this.getForm().isDirty();

		var prevState = this.state;
		if(this.rec.phantom){
			if(valid){
				this.state = PHANTOM_VALID;
			} else {
				this.state = PHANTOM_INVALID;
			}
		} else {
			if (dirty) {
				if (valid) {
					this.state = EXISTING_DIRTY_VALID;
				} else {
					this.state = EXISTING_DIRTY_INVALID;
				}
			} else {
				if (valid) {
					this.state = EXISTING_NON_DIRTY_VALID;
				} else {
					this.state = EXISTING_NON_DIRTY_INVALID;
				}
			}
		}

		if(this.state != prevState){
			var tb = this.formcontent.getTopToolbar();

			switch(this.state){

				case PHANTOM_VALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.enable();
					tb.saveButton.enable();
					tb.saveAsDraftButton.enable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				case PHANTOM_INVALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.disable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				case EXISTING_NON_DIRTY_VALID:
					this.fireEvent('undirty');
					this.enableTabs();
					this.metaPanel.enable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
					tb.previewButton.enable();
				break;

				case EXISTING_NON_DIRTY_INVALID:
				//.. SHOULD NOT OCCUR! (possible if model file is not valid)
					//this.fireEvent('dirty');
					//this.disableTabs();
					//tb.saveButton.disable();
					//tb.cancelButton.enable();
					//tb.previewButton.enable();

					this.fireEvent('undirty');
					this.enableTabs();
					this.metaPanel.enable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
					tb.previewButton.disable();

				break;

				case EXISTING_DIRTY_VALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.enable();
					tb.saveButton.enable();
					tb.saveAsDraftButton.enable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				//case EXISTING_DIRTY_INVALID:
				default:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.disable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;
			}
		}
	},

	/**
	 * Disables the other tabpanels (relatepanels)
	 */
	disableTabs: function(){
		//console.log('disableTabs');
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				i.disable();
			}
		}, this);
	},

	/**
	 * Enables the other tabpanels (relatepanels) (duh)
	 */
	enableTabs: function(){
		//console.log('enableTabs');
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				i.enable();
			}
		}, this);
	},

	/**
	 * Retrieves relationTabPanel based on modelName
	 * @param {Object} modelName
	 */
	getTab: function(modelName){
		return this.get(0).items.find(function(i){
			return (i.model == modelName);
		});
	},

	/**
	 * @function newItem
	 * Makes sure the panel is shown and focuses the first field.
	 */
	newItem: function(){
		this.form.reset();
		(function(){
			this.stopMonitoring();
			this.focusFirstField();
			this.getForm().items.each(function(i){
				if (typeof i.blur == 'function') {
					i.on('blur', this.startMonitoring.createDelegate(this), this, {
						single: true
					});
					i.on('keyup', this.startMonitoring.createDelegate(this), this, {
						single: true
					});
				}
			}, this);
			this.getForm().clearInvalid();
			this.updateUI();
			this.rec = Garp.gridPanel.getSelectionModel().getSelected();
			this.formcontent.fireEvent('loaddata', this.rec, this);
		}).defer(100,this);
		this.getForm().clearInvalid();
	},

	/**
	 * @returns {String} All errors from all fields in the form
	 */
	getErrors: function(){
		var str = '';
		this.getForm().items.each(function(i){
			if(i.getActiveError()){
				str += i.getActiveError() + ': ' + i.fieldLabel + '
';
			}
		});
		return str;
	},

	/**
	 * @function updateTitle
	 */
	updateTitle: function(){
		if (Garp.dataTypes[Garp.currentModel].displayFieldRenderer) {
			var panel = this.items.itemAt(0).items.itemAt(0);
			if (panel.xtype !== 'relationpanel') {
				panel.setTitle(Garp.dataTypes[Garp.currentModel].displayFieldRenderer(this.rec));
			}
		}
	},

	/**
	 * @function loadData
	 * loads Data in the form and makes sure the panel is visible
	 *
	 * @param {Object} sm selectionModel
	 */
	loadData: function(sm){
		var form = this.getForm();
		this.stopMonitoring();
		if(form.isDirty() || sm.getCount() != 1){
			return;
		}
		this.rec = sm.getSelected();
		if (!this.rec) {
			return;
		}

		this.state = null;
		form.loadRecord(this.rec);

		if (!this.ownerCt) {
			return;
		}
		this.updateTitle();

		this.fireEvent('defocus');

		function relayEvent(){
			if(this.formcontent.rendered){
				this.formcontent.fireEvent('loaddata', this.rec, this);
			}
			if(this.metaPanel.rendered){
				this.metaPanel.fireEvent('loaddata', this.rec, this);
			}
			this.state = null;
			this.startMonitoring();
			this.getForm().clearInvalid();
		}

		relayEvent.call(this);
		this.formcontent.on('activate', relayEvent, this, {
			single: true
		});
		this.metaPanel.on('activate', relayEvent, this, {
			single: true
		});
			var draftable = Garp.dataTypes[Garp.currentModel].getColumn('online_status') && Garp.dataTypes[Garp.currentModel].getColumn('published') ? true : false;
			this.formcontent.getTopToolbar().saveAsDraftButton.setVisible(draftable);

		form.unDirty();
	},

	/**
	 * @function focusFirstField
	 * Focuses the first editable & visible field
	 */
	focusFirstField: function(){
		var fp = this;
		this.getForm().items.each(function(item){

			// See Garp changelist 3.4 'compositefield' not supported anymore

			/*if(item.xtype == 'compositefield'){
				item.items.each(function(item){
					if (!item.hidden && !item.disabled && item.focus && Ext.isFunction(item.focus)) {
						item.focus(100);
						return false;
					} else {
						return true;
					}
				});
			}*/

			if (!item.hidden && !item.disabled && item.focus && Ext.isFunction(item.focus)) {
				item.focus(100);
				return false;
			} else {
				return true;
			}
		});
	},

	/**
	 * @function afterRender
	 * Sets up keyboard handlin & events for the tabs
	 */
	afterRender: function(){
		var keyMap = new Ext.KeyMap(this.getEl(), [{
			key: Ext.EventObject.ESC,
			scope: this,
			handler: function(){
				this.fireEvent('defocus');
			}
		}]);
		keyMap.stopEvent = true;
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				this.relayEvents(i, ['dirty', 'undirty']);
			}
		}, this);
		Garp.FormPanel.superclass.afterRender.call(this);
	},

	/*
	setLocked: function(lock){
		this.locked = lock;
		this.fireEvent(lock ? 'lock' : 'unlock', this);
		if(lock){
			this.getEl().addClass('locked');
		} else {
			this.getEl().removeClass('locked');
		}
	},

	lock: function(){
		this.setLocked(true);
	},

	unlock: function(){
		this.setLocked(false);
	},

	isLocked: function(){
		return this.locked;
	},
	*/

	/**
	 * init
	 */
	initComponent: function(){

		this.id = Ext.id();
		this.addEvents('save-all','cancel','preview','open-new-window','lock','unlock','dirty','undirty','delete');

		this.on({
			scope: this,
			'new': {
				buffer: 30,
				fn: this.newItem
			},
			'save-all': {
				fn: function(){
					var tb = this.formcontent.getTopToolbar();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
				}
			},
			'after-save': {
				fn: function(sm){
					this.state = null;
					this.form.unDirty();
					this.form.reset();
					this.loadData(sm);
					this.updateUI();
				}
			},
			'rowselect': {
				buffer: 100,
				fn: this.loadData
			},
			'clientvalidation': {
				fn: function(fp, valid){
					this.updateUI(valid);
				}
			}
		});

		var items = [];
		Ext.each(Garp.dataTypes[Garp.currentModel].formConfig, function(o){
			items.push(Ext.apply({}, o));
		});

		Ext.apply(items[0],{
			ref: '../formcontent',
			title: ' ', // misformed tab otherwise
			layout: 'border'
		});
		// fieldset properties override:
		Ext.apply(items[0].items[0], {
			region: 'center',
			autoScroll: true,
			margins: '0 0 0 10'
		});

		items[0].tbar = {
			cls: 'garp-formpanel-toolbar',
			items: [{
				text: __('Save'),
				iconCls: 'icon-save',
				ref: 'saveButton',
				disabled: true,
				handler: function(){
					this.dirtyState = null;
					this.fireEvent('save-all');
				},
				scope: this
			},{
				text: __('Save as draft'),
				hidden: !this.draftable,
				iconCls: 'icon-save-draft',
				ref: 'saveAsDraftButton',
				disabled: true,
				handler: function(){
					this.dirtyState = null;
					this.rec.set('online_status',0);
					this.fireEvent('save-all');
				},
				scope: this
			},{
				text: __('Cancel'),
				iconCls: 'icon-cancel',
				ref: 'cancelButton',
				disabled: true,
				handler: function(){
					function revertPhantom(){
						this.getForm().reset();
						this.updateUI();
						this.rec = null;
						this.fireEvent('delete');
					}
					if(this.getForm().isDirty()){
						Ext.Msg.confirm(__('Garp'), __('Are you sure you want to revert your changes?'), function(btn){
							if(btn == 'yes'){
								if (this.rec.phantom) {
									revertPhantom.call(this);
								} else {
									this.getForm().reset();
									this.updateUI();
									this.fireEvent('cancel', this);
								}
							}
						}, this);
						return;
					}
					if(!this.rec || this.rec.phantom){
						revertPhantom.call(this);
						return;
					}
				},
				scope: this
			},' ',{
				text: __('Open in new window'),
				iconCls: 'icon-open-new-window',
				handler: function(){
					this.fireEvent('open-new-window');
				},
				scope: this
			}, ' ', {
				text: __('Preview'),
				iconCls: 'icon-preview',
				ref: 'previewButton',
				disabled: true,
				hidden: Garp.currentModel && !Garp.dataTypes[Garp.currentModel].previewLink,
				scope: this,
				handler: function(){
					this.fireEvent('preview');
				},
				listeners: {
					'disable': function(){
						this.setTooltip(__('To preview, save this item first'));
					},
					'enable': function(){
						this.setTooltip(__('Preview this item'));
					}
				}
			}]
		};

		var cm = Garp.dataTypes[Garp.currentModel];
		var metaPanelCfg = Ext.apply({
			hidden: window.innerWidth <= Garp.SMALLSCREENWIDTH
		}, cm.metaPanelConfig ? cm.metaPanelConfig : {});
		items[0].items.push(this.metaPanel = new Garp.MetaPanel(metaPanelCfg));

		console.info(metaPanelCfg);

		this.items = {
			xtype:'tabpanel',
			deferredRender: false,
			activeTab: 0,
			resizeTabs: true,
			minTabWidth: 80,
			tabWidth: 150,
			tabMargin: 15,
			enableTabScroll: true,
			border: false,
			defaults: {
				border: false,
				deferredRender: false,
				bodyCssClass: 'garp-formpanel' // visual styling
			},
			items: items
		};

		this.relayEvents(this.metaPanel, ['save-all', 'dirty', 'undirty']);

		Garp.FormPanel.superclass.initComponent.call(this, arguments);
		this.stopMonitoring();
	}

});

Ext.reg('garpformpanel', Garp.FormPanel);<commit_msg>-- debug<commit_after>/**
 * @class Garp.FormPanel
 * @extends Ext.FormPanel
 * @author Peter
 */

Garp.FormPanel = Ext.extend(Ext.FormPanel, {

	/**
	 * @cfg defaults:
	 */
	layout: 'fit',
	hideMode: 'offsets',
	monitorValid: true,
	trackResetOnLoad: false,
	clientValidation: true,

	/**
	 * private
	 */
	state: null,

	/**
	 * Sets the UI for all dirty / undirty / phantom combinations
	 * It enables / disabled buttons and such. It also fires 'dirty' & 'undirty' events
	 * It keeps track of the previous state for performance reasons
	 */
	updateUI: function(){
		if(!this.rec || !this.formcontent.rendered || this.hidden){
			return;
		}

		var
		PHANTOM_VALID = 1,
		PHANTOM_INVALID = 2,
		EXISTING_NON_DIRTY_VALID = 4,
		EXISTING_NON_DIRTY_INVALID = 8,
		EXISTING_DIRTY_VALID = 16,
		EXISTING_DIRTY_INVALID = 32;

		var valid = this.getForm().isValid();
		var dirty = this.getForm().isDirty();

		var prevState = this.state;
		if(this.rec.phantom){
			if(valid){
				this.state = PHANTOM_VALID;
			} else {
				this.state = PHANTOM_INVALID;
			}
		} else {
			if (dirty) {
				if (valid) {
					this.state = EXISTING_DIRTY_VALID;
				} else {
					this.state = EXISTING_DIRTY_INVALID;
				}
			} else {
				if (valid) {
					this.state = EXISTING_NON_DIRTY_VALID;
				} else {
					this.state = EXISTING_NON_DIRTY_INVALID;
				}
			}
		}

		if(this.state != prevState){
			var tb = this.formcontent.getTopToolbar();

			switch(this.state){

				case PHANTOM_VALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.enable();
					tb.saveButton.enable();
					tb.saveAsDraftButton.enable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				case PHANTOM_INVALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.disable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				case EXISTING_NON_DIRTY_VALID:
					this.fireEvent('undirty');
					this.enableTabs();
					this.metaPanel.enable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
					tb.previewButton.enable();
				break;

				case EXISTING_NON_DIRTY_INVALID:
				//.. SHOULD NOT OCCUR! (possible if model file is not valid)
					//this.fireEvent('dirty');
					//this.disableTabs();
					//tb.saveButton.disable();
					//tb.cancelButton.enable();
					//tb.previewButton.enable();

					this.fireEvent('undirty');
					this.enableTabs();
					this.metaPanel.enable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
					tb.previewButton.disable();

				break;

				case EXISTING_DIRTY_VALID:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.enable();
					tb.saveButton.enable();
					tb.saveAsDraftButton.enable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;

				//case EXISTING_DIRTY_INVALID:
				default:
					this.fireEvent('dirty');
					this.disableTabs();
					this.metaPanel.disable();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.enable();
					tb.previewButton.disable();
				break;
			}
		}
	},

	/**
	 * Disables the other tabpanels (relatepanels)
	 */
	disableTabs: function(){
		//console.log('disableTabs');
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				i.disable();
			}
		}, this);
	},

	/**
	 * Enables the other tabpanels (relatepanels) (duh)
	 */
	enableTabs: function(){
		//console.log('enableTabs');
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				i.enable();
			}
		}, this);
	},

	/**
	 * Retrieves relationTabPanel based on modelName
	 * @param {Object} modelName
	 */
	getTab: function(modelName){
		return this.get(0).items.find(function(i){
			return (i.model == modelName);
		});
	},

	/**
	 * @function newItem
	 * Makes sure the panel is shown and focuses the first field.
	 */
	newItem: function(){
		this.form.reset();
		(function(){
			this.stopMonitoring();
			this.focusFirstField();
			this.getForm().items.each(function(i){
				if (typeof i.blur == 'function') {
					i.on('blur', this.startMonitoring.createDelegate(this), this, {
						single: true
					});
					i.on('keyup', this.startMonitoring.createDelegate(this), this, {
						single: true
					});
				}
			}, this);
			this.getForm().clearInvalid();
			this.updateUI();
			this.rec = Garp.gridPanel.getSelectionModel().getSelected();
			this.formcontent.fireEvent('loaddata', this.rec, this);
		}).defer(100,this);
		this.getForm().clearInvalid();
	},

	/**
	 * @returns {String} All errors from all fields in the form
	 */
	getErrors: function(){
		var str = '';
		this.getForm().items.each(function(i){
			if(i.getActiveError()){
				str += i.getActiveError() + ': ' + i.fieldLabel + '
';
			}
		});
		return str;
	},

	/**
	 * @function updateTitle
	 */
	updateTitle: function(){
		if (Garp.dataTypes[Garp.currentModel].displayFieldRenderer) {
			var panel = this.items.itemAt(0).items.itemAt(0);
			if (panel.xtype !== 'relationpanel') {
				panel.setTitle(Garp.dataTypes[Garp.currentModel].displayFieldRenderer(this.rec));
			}
		}
	},

	/**
	 * @function loadData
	 * loads Data in the form and makes sure the panel is visible
	 *
	 * @param {Object} sm selectionModel
	 */
	loadData: function(sm){
		var form = this.getForm();
		this.stopMonitoring();
		if(form.isDirty() || sm.getCount() != 1){
			return;
		}
		this.rec = sm.getSelected();
		if (!this.rec) {
			return;
		}

		this.state = null;
		form.loadRecord(this.rec);

		if (!this.ownerCt) {
			return;
		}
		this.updateTitle();

		this.fireEvent('defocus');

		function relayEvent(){
			if(this.formcontent.rendered){
				this.formcontent.fireEvent('loaddata', this.rec, this);
			}
			if(this.metaPanel.rendered){
				this.metaPanel.fireEvent('loaddata', this.rec, this);
			}
			this.state = null;
			this.startMonitoring();
			this.getForm().clearInvalid();
		}

		relayEvent.call(this);
		this.formcontent.on('activate', relayEvent, this, {
			single: true
		});
		this.metaPanel.on('activate', relayEvent, this, {
			single: true
		});
			var draftable = Garp.dataTypes[Garp.currentModel].getColumn('online_status') && Garp.dataTypes[Garp.currentModel].getColumn('published') ? true : false;
			this.formcontent.getTopToolbar().saveAsDraftButton.setVisible(draftable);

		form.unDirty();
	},

	/**
	 * @function focusFirstField
	 * Focuses the first editable & visible field
	 */
	focusFirstField: function(){
		var fp = this;
		this.getForm().items.each(function(item){

			// See Garp changelist 3.4 'compositefield' not supported anymore

			/*if(item.xtype == 'compositefield'){
				item.items.each(function(item){
					if (!item.hidden && !item.disabled && item.focus && Ext.isFunction(item.focus)) {
						item.focus(100);
						return false;
					} else {
						return true;
					}
				});
			}*/

			if (!item.hidden && !item.disabled && item.focus && Ext.isFunction(item.focus)) {
				item.focus(100);
				return false;
			} else {
				return true;
			}
		});
	},

	/**
	 * @function afterRender
	 * Sets up keyboard handlin & events for the tabs
	 */
	afterRender: function(){
		var keyMap = new Ext.KeyMap(this.getEl(), [{
			key: Ext.EventObject.ESC,
			scope: this,
			handler: function(){
				this.fireEvent('defocus');
			}
		}]);
		keyMap.stopEvent = true;
		this.get(0).items.each(function(i){
			if (i != this.formcontent) {
				this.relayEvents(i, ['dirty', 'undirty']);
			}
		}, this);
		Garp.FormPanel.superclass.afterRender.call(this);
	},

	/*
	setLocked: function(lock){
		this.locked = lock;
		this.fireEvent(lock ? 'lock' : 'unlock', this);
		if(lock){
			this.getEl().addClass('locked');
		} else {
			this.getEl().removeClass('locked');
		}
	},

	lock: function(){
		this.setLocked(true);
	},

	unlock: function(){
		this.setLocked(false);
	},

	isLocked: function(){
		return this.locked;
	},
	*/

	/**
	 * init
	 */
	initComponent: function(){

		this.id = Ext.id();
		this.addEvents('save-all','cancel','preview','open-new-window','lock','unlock','dirty','undirty','delete');

		this.on({
			scope: this,
			'new': {
				buffer: 30,
				fn: this.newItem
			},
			'save-all': {
				fn: function(){
					var tb = this.formcontent.getTopToolbar();
					tb.saveButton.disable();
					tb.saveAsDraftButton.disable();
					tb.cancelButton.disable();
				}
			},
			'after-save': {
				fn: function(sm){
					this.state = null;
					this.form.unDirty();
					this.form.reset();
					this.loadData(sm);
					this.updateUI();
				}
			},
			'rowselect': {
				buffer: 100,
				fn: this.loadData
			},
			'clientvalidation': {
				fn: function(fp, valid){
					this.updateUI(valid);
				}
			}
		});

		var items = [];
		Ext.each(Garp.dataTypes[Garp.currentModel].formConfig, function(o){
			items.push(Ext.apply({}, o));
		});

		Ext.apply(items[0],{
			ref: '../formcontent',
			title: ' ', // misformed tab otherwise
			layout: 'border'
		});
		// fieldset properties override:
		Ext.apply(items[0].items[0], {
			region: 'center',
			autoScroll: true,
			margins: '0 0 0 10'
		});

		items[0].tbar = {
			cls: 'garp-formpanel-toolbar',
			items: [{
				text: __('Save'),
				iconCls: 'icon-save',
				ref: 'saveButton',
				disabled: true,
				handler: function(){
					this.dirtyState = null;
					this.fireEvent('save-all');
				},
				scope: this
			},{
				text: __('Save as draft'),
				hidden: !this.draftable,
				iconCls: 'icon-save-draft',
				ref: 'saveAsDraftButton',
				disabled: true,
				handler: function(){
					this.dirtyState = null;
					this.rec.set('online_status',0);
					this.fireEvent('save-all');
				},
				scope: this
			},{
				text: __('Cancel'),
				iconCls: 'icon-cancel',
				ref: 'cancelButton',
				disabled: true,
				handler: function(){
					function revertPhantom(){
						this.getForm().reset();
						this.updateUI();
						this.rec = null;
						this.fireEvent('delete');
					}
					if(this.getForm().isDirty()){
						Ext.Msg.confirm(__('Garp'), __('Are you sure you want to revert your changes?'), function(btn){
							if(btn == 'yes'){
								if (this.rec.phantom) {
									revertPhantom.call(this);
								} else {
									this.getForm().reset();
									this.updateUI();
									this.fireEvent('cancel', this);
								}
							}
						}, this);
						return;
					}
					if(!this.rec || this.rec.phantom){
						revertPhantom.call(this);
						return;
					}
				},
				scope: this
			},' ',{
				text: __('Open in new window'),
				iconCls: 'icon-open-new-window',
				handler: function(){
					this.fireEvent('open-new-window');
				},
				scope: this
			}, ' ', {
				text: __('Preview'),
				iconCls: 'icon-preview',
				ref: 'previewButton',
				disabled: true,
				hidden: Garp.currentModel && !Garp.dataTypes[Garp.currentModel].previewLink,
				scope: this,
				handler: function(){
					this.fireEvent('preview');
				},
				listeners: {
					'disable': function(){
						this.setTooltip(__('To preview, save this item first'));
					},
					'enable': function(){
						this.setTooltip(__('Preview this item'));
					}
				}
			}]
		};

		var cm = Garp.dataTypes[Garp.currentModel];
		var metaPanelCfg = Ext.apply({
			hidden: window.innerWidth <= Garp.SMALLSCREENWIDTH
		}, cm.metaPanelConfig ? cm.metaPanelConfig : {});
		items[0].items.push(this.metaPanel = new Garp.MetaPanel(metaPanelCfg));

		this.items = {
			xtype:'tabpanel',
			deferredRender: false,
			activeTab: 0,
			resizeTabs: true,
			minTabWidth: 80,
			tabWidth: 150,
			tabMargin: 15,
			enableTabScroll: true,
			border: false,
			defaults: {
				border: false,
				deferredRender: false,
				bodyCssClass: 'garp-formpanel' // visual styling
			},
			items: items
		};

		this.relayEvents(this.metaPanel, ['save-all', 'dirty', 'undirty']);

		Garp.FormPanel.superclass.initComponent.call(this, arguments);
		this.stopMonitoring();
	}

});

Ext.reg('garpformpanel', Garp.FormPanel);<|endoftext|>


<commit_before>// Copyright 2013-2015, University of Colorado Boulder

/**
 * Escaping of HTML content that will be placed in the body, inside an element as a node.
 *
 * This is NOT for escaping something in other HTML contexts, for example as an attribute value
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( function( require ) {
  'use strict';

  var phetCore = require( 'PHET_CORE/phetCore' );

  function escapeHTML( str ) {
    // see https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
    // HTML Entity Encoding
    return str
      .replace( /&/g, '&' )
      .replace( /</g, '<' )
      .replace( />/g, '>' )
      .replace( /\"/g, '"' )
      .replace( /\'/g, ''' )
      .replace( /\//g, '/' );
  }

  phetCore.register( 'escapeHTML', escapeHTML );

  return escapeHTML;
} );<commit_msg>fix no-needless-escape eslint rule and turn it on, https://github.com/phetsims/chipper/issues/750<commit_after>// Copyright 2013-2015, University of Colorado Boulder

/**
 * Escaping of HTML content that will be placed in the body, inside an element as a node.
 *
 * This is NOT for escaping something in other HTML contexts, for example as an attribute value
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( function( require ) {
  'use strict';

  var phetCore = require( 'PHET_CORE/phetCore' );

  function escapeHTML( str ) {
    // see https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
    // HTML Entity Encoding
    return str
      .replace( /&/g, '&' )
      .replace( /</g, '<' )
      .replace( />/g, '>' )
      .replace( /"/g, '"' )
      .replace( /'/g, ''' )
      .replace( /\//g, '/' );
  }

  phetCore.register( 'escapeHTML', escapeHTML );

  return escapeHTML;
} );<|endoftext|>


<commit_before>define(function(require, exports, module) {
  'use strict';

  var Utils = require('utils'),
      Condition = require('condition'),
      Operator = require('operator'),
      EvalTree = require('evalTree');

  function Expression(text) {
    var self = this;
    self.operators = [/*Operator*/];
    self.conditions = [/*Condition*/];

    // trim surrounding space and parenthesis pairs
    var textToParse = Utils.trimParenthesisPairs(text);
    var topLevelParenthesis = Utils.findTopLevelParenthesis(textToParse);

    var textChunks = [],
        lastPosition = 0;

    // Break the text into sub-expressions and top-level expressions
    // TODO: Identify when a ! precedes an Expression, and pass that into the constructor
    if(topLevelParenthesis.length === 0) {
      // There are no sub-expressions to extract.  Store the entire string
      textChunks.push(textToParse);
    } else {

      topLevelParenthesis.forEach(function(e) {
        // Store the text between previous chunk and start of this Expression
        textChunks.push(textToParse.substring(lastPosition, e.start));
        // Store the sub-expression
        textChunks.push(new Expression(textToParse.substring(e.start, e.end + 1)));
        // Advance the pointer
        lastPosition = e.end + 1;
      });

      // Store any trailing text
      if(lastPosition < textToParse.length - 1) {
        textChunks.push(textToParse.substring(lastPosition));
      }

    }

    var conditionChunks = [],
        matchAndOrXor = new RegExp(
            '(\\s|\\b)(?=' + Utils.tokensAndOrXor.join('|') + ')'
        , 'ig'),
        captureLeadingAnd = new RegExp(
            '^(' + Utils.tokensAnd.join('|') + ')'
        , 'ig'),
        captureLeadingOr = new RegExp(
            '^(' + Utils.tokensOr.join('|') + ')'
        , 'ig'),
        captureLeadingXor = new RegExp(
            '^(' + Utils.tokensXor.join('|') + ')'
        , 'ig'),
        leadingAndMatch, leadingOrMatch, leadingXorMatch, retVal, ignoredText;

    // TODO: Identify when the condition is preceded by a ! or has a negative comparison
    textChunks.forEach(function(textChunk) {
      // If this chunk is a sub-expression, just store it without parsing
      if(textChunk instanceof Expression) {
        self.conditions.push(textChunk);
      } else {
        // Remove all the text that should be ignored: the contents of function calls and strings
        // Otherwise the split() could match operators in those strings
        retVal = Utils.removeIgnoredText(textChunk);
        textChunk = retVal[0];
        ignoredText = retVal[1];

        conditionChunks = textChunk.split(matchAndOrXor);

        conditionChunks.forEach(function(condition) {
          // Determine if an AND operator or an OR operator was found.
          // If so, store which was found and then remove it.
          if((leadingAndMatch = condition.match(captureLeadingAnd)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_AND));
            condition = condition.substring(leadingAndMatch[0].length);
          } else if((leadingOrMatch = condition.match(captureLeadingOr)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_OR));
            condition = condition.substring(leadingOrMatch[0].length);
          } else if((leadingXorMatch = condition.match(captureLeadingXor)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_XOR));
            condition = condition.substring(leadingXorMatch[0].length);
          }

          // Store anything that's not still empty.
          condition = condition.trim();
          if(condition !== '') {
            // Restore any text that was ignored above
            condition = Utils.restoreIgnoredText(condition, ignoredText);
            self.conditions.push(new Condition.Condition(condition));
          }
        });

      }
    });

    self.hasMixedOperators = Utils.hasMixedOperators(self.operators);

    self.truePaths = self.hasMixedOperators ? null : new EvalTree.EvalTree(self, true);
    self.falsePaths = self.hasMixedOperators ? null : new EvalTree.EvalTree(self, false);

    return this;
  }

  Expression.prototype.getEvalPaths = function(treeType) {
    return treeType ? this.truePaths : this.falsePaths;
  };

  Expression.prototype.hasMixedOperatorsDeep = function() {
    var self = this;
    return self.hasMixedOperators || self.conditions.some(function(c) {
      return (c instanceof Expression) && c.hasMixedOperatorsDeep();
    });
  };

  exports.Expression = Expression;

});<commit_msg>More code indentation fixes.<commit_after>define(function(require, exports, module) {
  'use strict';

  var Utils = require('utils'),
      Condition = require('condition'),
      Operator = require('operator'),
      EvalTree = require('evalTree');

  function Expression(text) {
    var self = this;
    self.operators = [/*Operator*/];
    self.conditions = [/*Condition*/];

    // trim surrounding space and parenthesis pairs
    var textToParse = Utils.trimParenthesisPairs(text);
    var topLevelParenthesis = Utils.findTopLevelParenthesis(textToParse);

    var textChunks = [],
        lastPosition = 0;

    // Break the text into sub-expressions and top-level expressions
    // TODO: Identify when a ! precedes an Expression, and pass that into the constructor
    if(topLevelParenthesis.length === 0) {
      // There are no sub-expressions to extract.  Store the entire string
      textChunks.push(textToParse);
    } else {

      topLevelParenthesis.forEach(function(e) {
        // Store the text between previous chunk and start of this Expression
        textChunks.push(textToParse.substring(lastPosition, e.start));
        // Store the sub-expression
        textChunks.push(new Expression(textToParse.substring(e.start, e.end + 1)));
        // Advance the pointer
        lastPosition = e.end + 1;
      });

      // Store any trailing text
      if(lastPosition < textToParse.length - 1) {
        textChunks.push(textToParse.substring(lastPosition));
      }

    }

    var conditionChunks = [],
        matchAndOrXor = new RegExp(
          '(\\s|\\b)(?=' + Utils.tokensAndOrXor.join('|') + ')'
        , 'ig'),
        captureLeadingAnd = new RegExp(
          '^(' + Utils.tokensAnd.join('|') + ')'
        , 'ig'),
        captureLeadingOr = new RegExp(
          '^(' + Utils.tokensOr.join('|') + ')'
        , 'ig'),
        captureLeadingXor = new RegExp(
          '^(' + Utils.tokensXor.join('|') + ')'
        , 'ig'),
        leadingAndMatch, leadingOrMatch, leadingXorMatch, retVal, ignoredText;

    // TODO: Identify when the condition is preceded by a ! or has a negative comparison
    textChunks.forEach(function(textChunk) {
      // If this chunk is a sub-expression, just store it without parsing
      if(textChunk instanceof Expression) {
        self.conditions.push(textChunk);
      } else {
        // Remove all the text that should be ignored: the contents of function calls and strings
        // Otherwise the split() could match operators in those strings
        retVal = Utils.removeIgnoredText(textChunk);
        textChunk = retVal[0];
        ignoredText = retVal[1];

        conditionChunks = textChunk.split(matchAndOrXor);

        conditionChunks.forEach(function(condition) {
          // Determine if an AND operator or an OR operator was found.
          // If so, store which was found and then remove it.
          if((leadingAndMatch = condition.match(captureLeadingAnd)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_AND));
            condition = condition.substring(leadingAndMatch[0].length);
          } else if((leadingOrMatch = condition.match(captureLeadingOr)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_OR));
            condition = condition.substring(leadingOrMatch[0].length);
          } else if((leadingXorMatch = condition.match(captureLeadingXor)) !== null) {
            self.operators.push(new Operator.Operator(Operator.Operator.TYPE_XOR));
            condition = condition.substring(leadingXorMatch[0].length);
          }

          // Store anything that's not still empty.
          condition = condition.trim();
          if(condition !== '') {
            // Restore any text that was ignored above
            condition = Utils.restoreIgnoredText(condition, ignoredText);
            self.conditions.push(new Condition.Condition(condition));
          }
        });

      }
    });

    self.hasMixedOperators = Utils.hasMixedOperators(self.operators);

    self.truePaths = self.hasMixedOperators ? null : new EvalTree.EvalTree(self, true);
    self.falsePaths = self.hasMixedOperators ? null : new EvalTree.EvalTree(self, false);

    return this;
  }

  Expression.prototype.getEvalPaths = function(treeType) {
    return treeType ? this.truePaths : this.falsePaths;
  };

  Expression.prototype.hasMixedOperatorsDeep = function() {
    var self = this;
    return self.hasMixedOperators || self.conditions.some(function(c) {
      return (c instanceof Expression) && c.hasMixedOperatorsDeep();
    });
  };

  exports.Expression = Expression;

});<|endoftext|>


<commit_before>function file_order_up(editor_sequence){
	jQuery('#uploaded_file_list_'+editor_sequence+' option:selected').each( function() {
    	var newPos = jQuery('#uploaded_file_list_'+editor_sequence+' option').index(this) - 1;

        if (newPos > -1) {

			//this는 현재 셀렉트된 값 jQuery(this).val()
			//this의 바로 위의 시퀀스 값
			var newVal = jQuery('#uploaded_file_list_'+editor_sequence+' option').eq(newPos).val();
			var formData = {editor_sequence:editor_sequence,file_srl:jQuery(this).val(),file_srl2:newVal};

		 	var request = jQuery.ajax({
				url: './addons/file_order/tpl/updown.php',type:'POST',dataType:'json',data:formData,
				success: function(result){
					if(result.ok == "ok"){
				 		removeUploadedFile_1sam(editor_sequence,newPos);
					}else if(result.ok == "bad"){
				}},
				global:false,cache:false,headers:{"cache-control":"no-cache","pragma":"no-cache"},	async:false,	error: function(){alert(result);}
			});
        }
    });

}

function file_order_down(editor_sequence){
	var	preview = jQuery('#preview_uploaded_'+editor_sequence);
	//preview.html('안녕');
	preview.removeAttr('id');
	preview.attr('id', '#preview_uploadedx_'+editor_sequence);

    var countOptions = jQuery('#uploaded_file_list_'+editor_sequence+' option').size();
    jQuery('#uploaded_file_list_'+editor_sequence+' option:selected').each( function() {
        var newPos = jQuery('#uploaded_file_list_'+editor_sequence+' option').index(this) + 1;

        if (newPos < countOptions) {
			var newVal = jQuery('#uploaded_file_list_'+editor_sequence+' option').eq(newPos).val();
			var formData = {editor_sequence:editor_sequence,file_srl:jQuery(this).val(),file_srl2:newVal};
		 	var request = jQuery.ajax({
				url: './addons/file_order/tpl/updown.php',type:'POST',dataType:'json',data:formData,
				success: function(result){
					if(result.ok == "ok"){
						removeUploadedFile_1sam(editor_sequence,newPos);
					}else if(result.ok == "bad"){
				}},
				global:false,cache:false,headers:{"cache-control":"no-cache","pragma":"no-cache"},	async:false,	error: function(){alert(result);}
			});
        }
    });
}

//파일정렬을 변경하였을 때
//구체적으로 수정은 하지 않았으나 나중에 해야함
//idx는 리로드 된 후에 셀렉트 되어야할 인덱스값임

function removeUploadedFile_1sam(editorSequence,idx) {
	var cfg = uploaderSettings[editorSequence];
	var fileListAreaID = cfg.fileListAreaID;
	var fileListObj = get_by_id(fileListAreaID);

	var params = {
		mid : current_mid,
		file_list_area_id : cfg.fileListAreaID,
		editor_sequence   : cfg.editorSequence,
		upload_target_srl : cfg.uploadTargetSrl
	};

	function on_completex(ret, response_tags) {
		(function($){
			var $list, seq, files, target_srl, up_status, remain, items, i, c, itm, file_srl;

			seq   = ret.editor_sequence;
			files = ret.files;
			up_status  = ret.upload_status;
			target_srl = ret.upload_target_srl;
			//remain     = Math.floor((parseInt(ret.left_size,10)||0)/1024);

			$list = jQuery('#'+cfg.fileListAreaID).empty();

			if(target_srl) {
				if(editorRelKeys[seq].primary.value != target_srl) {
					editorRelKeys[seq].primary.value = target_srl;
					//autosave();
				}

				editorRelKeys[seq].primary.value = target_srl;
				cfg.uploadTargetSrl = target_srl;
			}

			jQuery('#'+cfg.uploaderStatusID).html(up_status);
			jQuery('#'+cfg.previewAreaID).empty();

			if(files && files.item) {
				items = files.item;
				if(!$.isArray(items)) items = [items];
				for(i=0,c=items.length; i < c; i++) {
					itm = items[i];

					file_srl = itm.file_srl;
					uploadedFiles[file_srl] = itm;

					itm.previewAreaID = cfg.previewAreaID;

					/*if(/\.(jpe?g|png|gif)$/i.test(itm.download_url)) {
						loaded_images[file_srl] = jQuery('<img />').attr('src', itm.download_url).get(0);
					}*/
					jQuery('<option />')
						.text(itm.source_filename + ' ('+itm.disp_file_size+' )')
						.attr('value', file_srl)
						.appendTo($list);
					/*if(i+1 == idx) {
						jQuery('<option />')
							.attr("selected", "selected");
					}*/
				}
				//jQuery(this).attr("selected","selected");
				//jQuery('#uploaded_file_list_'+editorSequence+' option').eq(idx).attr("selected", "selected");
				$list.prop('selectedIndex', idx).click();
			}

		})(jQuery);
	}

	exec_xml(
		'file',         // module
		'getFileList',  // act
		params,         // parameters
		on_completex,    // callback
		'error,message,files,upload_status,upload_target_srl,editor_sequence,left_size'.split(',') // response_tags
	);

}

        function startProgress()
        {
            var iFrame = document.createElement('iframe');
            document.getElementsByTagName('body')[0].appendChild(iFrame);
            iFrame.src = 'JsPush.php?progress';
        }

        function Zend_ProgressBar_Update(data)
        {
            document.getElementById('pg-percent').style.width = data.percent + '%';

            document.getElementById('pg-text-1').innerHTML = data.text;
            document.getElementById('pg-text-2').innerHTML = data.text;
        }

        function Zend_ProgressBar_Finish()
        {
            document.getElementById('pg-percent').style.width = '100%';

            document.getElementById('pg-text-1').innerHTML = 'Demo done';
            document.getElementById('pg-text-2').innerHTML = 'Demo done';
        }

    jQuery('#btn-up').bind('click', function() {
        jQuery('#uploaded_file_list_{$editor_sequence} option:selected').each( function() {
            var newPos = jQuery('#uploaded_file_list_{$editor_sequence} option').index(this) - 1;

            if (newPos > -1) {
				var newVal1 = $("#uploaded_file_list_{$editor_sequence} option").eq(newPos).val();

                jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).before("<option value='"+newVal1+"'>"+jQuery(this).text()+"</option>");
				jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos + 1).val(jQuery(this).val());
                jQuery(this).remove();
				jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).attr("selected", "selected");
            }
        });
    });
    jQuery('#btn-down').bind('click', function() {
        var countOptions = jQuery('#uploaded_file_list_{$editor_sequence} option').size();
        jQuery('#uploaded_file_list_{$editor_sequence} option:selected').each( function() {
            var newPos = jQuery('#uploaded_file_list_{$editor_sequence} option').index(this) + 1;

            if (newPos < countOptions) {
				var newVal1 = $("#uploaded_file_list_{$editor_sequence} option").eq(newPos).val();

                jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).after("<option value='"+newVal1+"'>"+jQuery(this).text()+"</option>");
				jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).val(jQuery(this).val());

                jQuery(this).remove();
				jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).attr("selected", "selected");
            }
        });
    });
<commit_msg>Update file_order.js<commit_after>function file_order_up(editor_sequence){
	jQuery('#uploaded_file_list_'+editor_sequence+' option:selected').each( function() {
    	var newPos = jQuery('#uploaded_file_list_'+editor_sequence+' option').index(this) - 1;

        if (newPos > -1) {

			//this는 현재 셀렉트된 값 jQuery(this).val()
			//this의 바로 위의 시퀀스 값
			var newVal = jQuery('#uploaded_file_list_'+editor_sequence+' option').eq(newPos).val();
			var formData = {editor_sequence:editor_sequence,file_srl:jQuery(this).val(),file_srl2:newVal};

		 	var request = jQuery.ajax({
				url: './addons/file_order/tpl/updown.php',type:'POST',dataType:'json',data:formData,
				success: function(result){
					if(result.ok == "ok"){
				 		removeUploadedFile_1sam(editor_sequence,newPos);
					}else if(result.ok == "bad"){
				}},
				global:false,cache:false,headers:{"cache-control":"no-cache","pragma":"no-cache"},	async:false,	error: function(){alert(result);}
			});
        }
    });

}

function file_order_down(editor_sequence){
	var	preview = jQuery('#preview_uploaded_'+editor_sequence);
	//preview.html('안녕');
	preview.removeAttr('id');
	preview.attr('id', '#preview_uploadedx_'+editor_sequence);

    var countOptions = jQuery('#uploaded_file_list_'+editor_sequence+' option').size();
    jQuery('#uploaded_file_list_'+editor_sequence+' option:selected').each( function() {
        var newPos = jQuery('#uploaded_file_list_'+editor_sequence+' option').index(this) + 1;

        if (newPos < countOptions) {
			var newVal = jQuery('#uploaded_file_list_'+editor_sequence+' option').eq(newPos).val();
			var formData = {editor_sequence:editor_sequence,file_srl:jQuery(this).val(),file_srl2:newVal};
		 	var request = jQuery.ajax({
				url: './addons/file_order/tpl/updown.php',type:'POST',dataType:'json',data:formData,
				success: function(result){
					if(result.ok == "ok"){
						removeUploadedFile_1sam(editor_sequence,newPos);
					}else if(result.ok == "bad"){
				}},
				global:false,cache:false,headers:{"cache-control":"no-cache","pragma":"no-cache"},	async:false,	error: function(){alert(result);}
			});
        }
    });
}

//파일정렬을 변경하였을 때
//구체적으로 수정은 하지 않았으나 나중에 해야함
//idx는 리로드 된 후에 셀렉트 되어야할 인덱스값임

function removeUploadedFile_1sam(editorSequence,idx) {
	var cfg = uploaderSettings[editorSequence];
	var fileListAreaID = cfg.fileListAreaID;
	var fileListObj = get_by_id(fileListAreaID);

	var params = {
		mid : current_mid,
		file_list_area_id : cfg.fileListAreaID,
		editor_sequence   : cfg.editorSequence,
		upload_target_srl : cfg.uploadTargetSrl
	};

	function on_completex(ret, response_tags) {
		(function($){
			var $list, seq, files, target_srl, up_status, remain, items, i, c, itm, file_srl;

			seq   = ret.editor_sequence;
			files = ret.files;
			up_status  = ret.upload_status;
			target_srl = ret.upload_target_srl;
			//remain     = Math.floor((parseInt(ret.left_size,10)||0)/1024);

			$list = jQuery('#'+cfg.fileListAreaID).empty();

			if(target_srl) {
				if(editorRelKeys[seq].primary.value != target_srl) {
					editorRelKeys[seq].primary.value = target_srl;
					//autosave();
				}

				editorRelKeys[seq].primary.value = target_srl;
				cfg.uploadTargetSrl = target_srl;
			}

			jQuery('#'+cfg.uploaderStatusID).html(up_status);
			jQuery('#'+cfg.previewAreaID).empty();

			if(files && files.item) {
				items = files.item;
				if(!$.isArray(items)) items = [items];
				for(i=0,c=items.length; i < c; i++) {
					itm = items[i];

					file_srl = itm.file_srl;
					uploadedFiles[file_srl] = itm;

					itm.previewAreaID = cfg.previewAreaID;

					/*if(/\.(jpe?g|png|gif)$/i.test(itm.download_url)) {
						loaded_images[file_srl] = jQuery('<img />').attr('src', itm.download_url).get(0);
					}*/
					jQuery('<option />')
						.text(itm.source_filename + ' ('+itm.disp_file_size+' )')
						.attr('value', file_srl)
						.appendTo($list);
					/*if(i+1 == idx) {
						jQuery('<option />')
							.attr("selected", "selected");
					}*/
				}
				//jQuery(this).attr("selected","selected");
				//jQuery('#uploaded_file_list_'+editorSequence+' option').eq(idx).attr("selected", "selected");
				$list.prop('selectedIndex', idx).click();
			}

		})(jQuery);
	}

	exec_xml(
		'file',         // module
		'getFileList',  // act
		params,         // parameters
		on_completex,    // callback
		'error,message,files,upload_status,upload_target_srl,editor_sequence,left_size'.split(',') // response_tags
	);

}

function startProgress()
{
	var iFrame = document.createElement('iframe');
	document.getElementsByTagName('body')[0].appendChild(iFrame);
	iFrame.src = 'JsPush.php?progress';
}

function Zend_ProgressBar_Update(data)
{
	document.getElementById('pg-percent').style.width = data.percent + '%';

	document.getElementById('pg-text-1').innerHTML = data.text;
	document.getElementById('pg-text-2').innerHTML = data.text;
}

function Zend_ProgressBar_Finish()
{
	document.getElementById('pg-percent').style.width = '100%';

	document.getElementById('pg-text-1').innerHTML = 'Demo done';
	document.getElementById('pg-text-2').innerHTML = 'Demo done';
}

jQuery('#btn-up').bind('click', function() {
	jQuery('#uploaded_file_list_{$editor_sequence} option:selected').each( function() {
		var newPos = jQuery('#uploaded_file_list_{$editor_sequence} option').index(this) - 1;

		if (newPos > -1) {
			var newVal1 = $("#uploaded_file_list_{$editor_sequence} option").eq(newPos).val();

			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).before("<option value='"+newVal1+"'>"+jQuery(this).text()+"</option>");
			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos + 1).val(jQuery(this).val());
			jQuery(this).remove();
			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).attr("selected", "selected");
		}
	});
});

jQuery('#btn-down').bind('click', function() {
	var countOptions = jQuery('#uploaded_file_list_{$editor_sequence} option').size();
	jQuery('#uploaded_file_list_{$editor_sequence} option:selected').each( function() {
		var newPos = jQuery('#uploaded_file_list_{$editor_sequence} option').index(this) + 1;

		if (newPos < countOptions) {
			var newVal1 = $("#uploaded_file_list_{$editor_sequence} option").eq(newPos).val();

			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).after("<option value='"+newVal1+"'>"+jQuery(this).text()+"</option>");
			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).val(jQuery(this).val());

			jQuery(this).remove();
			jQuery('#uploaded_file_list_{$editor_sequence} option').eq(newPos).attr("selected", "selected");
		}
	});
});
<|endoftext|>


<commit_before>var width = 960,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(200)
    .size([width, height]);

var forceSvg = d3.select("div#chord_chart").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("newsGraph.json", function(error, graph) {
  console.log(graph);
  selectedList = [0,10,2,3,4,50,60,75,18];
  selectedData1 = $.map(graph.nodes, function(element){
      return ($.inArray(element.id,selectedList)>-1?element:null);
    });
  selectedData2 = $.map(graph.links, function(element){
      return ($.inArray(element.source,selectedList)>-1?element:null);
    });
  console.log(selectedData2);
  selectedData3 = $.map(selectedData2, function(element){
      return ($.inArray(element.target,selectedList)>-1?element:null);
    });
  new_graph = {};
  new_graph['nodes'] = selectedData1;
  new_graph['links'] = selectedData3;
  console.log(new_graph);
  graph = new_graph;
  console.log(graph);
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();

  var graphMin = d3.min(graph.links, function(d){ return d.size; });
  var graphMax = d3.max(graph.links, function(d){ return d.size; });

  var fill = d3.scale.ordinal()
      .domain([graphMin, graphMax])
      .range(["#DB704D", "#D2D0C6", "#ECD08D", "#F8EDD3"]);

  var link = forceSvg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style('stroke-width', 1)
      .style('stroke', function(d){ return fill(d.value); })
      //.style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = forceSvg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  node.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});<commit_msg>update data<commit_after>var width = 960,
    height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
    .charge(-120)
    .linkDistance(200)
    .size([width, height]);

var forceSvg = d3.select("div#chord_chart").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("newsGraph.json", function(error, graph) {
  console.log(graph);
  selectedList = [0,10,2,3,4,50,60,75,18];
  selectedData1 = $.map(graph.nodes, function(element){
      return ($.inArray(element.id,selectedList)>-1?element:null);
    });
  selectedData2 = $.map(graph.links, function(element){
      return ($.inArray(element.source,selectedList)>-1?element:null);
    });
  console.log(selectedData2);
  selectedData3 = $.map(selectedData2, function(element){
      return ($.inArray(element.target,selectedList)>-1?element:null);
    });
  new_graph = {};
  new_graph['nodes'] = selectedData1;
  new_graph['links'] = selectedData3;
  console.log(new_graph);
  graph = new_graph;
  console.log(graph);
  force
      .nodes(selectedData1)
      .links(selectedData2)
      .start();

  var graphMin = d3.min(selectedData2, function(d){ return d.size; });
  var graphMax = d3.max(selectedData2, function(d){ return d.size; });

  var fill = d3.scale.ordinal()
      .domain([graphMin, graphMax])
      .range(["#DB704D", "#D2D0C6", "#ECD08D", "#F8EDD3"]);

  var link = forceSvg.selectAll(".link")
      .data(selectedData2)
    .enter().append("line")
      .attr("class", "link")
      .style('stroke-width', 1)
      .style('stroke', function(d){ return fill(d.value); })
      //.style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var node = forceSvg.selectAll(".node")
      .data(selectedData1)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag);

  node.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});<|endoftext|>


<commit_before>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  The GamePiece class. The GamePiece class is mostly an abstract super-
 * class for all the in-game objects. A GamePiece provides a UUID for each instance.
 * At a minimum, subclasses should override these methods:
 *     GamePiece.prototype.getBodyDef = function() {}
 *     GamePiece.prototype.addFixturesToBody = function(simulation, body) {}
 *     GamePiece.prototype.loadView = function(simulation) {}
 */

/**
 * Constructor for the GamePiece.
 * @constructor
 */
GamePiece = function() {
  /**
   * The Box2D body that represents this game piece. Not valid until addToSimulation()
   * is called.
   * @type {Box2D.Dynamics.b2Body}
   * @private
   */
  this._body = null;

  /**
   * The view associated with this game piece. Set via the loadView() method.
   * @type {BodyView}
   * @public
   */
  this.view = null;

  /**
   * The UUID for this instance. Generated lazily.
   * @type {string}
   * @private
   */
  this._uuid = uuid();
}
GamePiece.prototype.constructor = GamePiece;

/**
 * Return the UUID for this instance.
 * @return {String} UUID
 */
GamePiece.prototype.uuid = function() {
  return this._uuid;
}

/**
 * Accessor for the Box2D body that represents this game piece. Not valid until after
 * addToSimulation() has returned.
 * @return {Box2D.Dynamics.b2Body} The Box2D body.
 */
GamePiece.prototype.body = function() {
  return this._body;
}

/**
 * Abstract method to process a "tick" in the game simulation. Subclasses should override
 * this to update any internal time-based state. Default implementation does nothing.
 * @param {number} gameTimeNow The wall-clock time when this function was called,
 *     measured in seconds since the "epoch" (Jan 1, 1970).
 * @param {number} gameTimeDelta The time since the last call to this method, measured in
 *     seconds.
 */
GamePiece.prototype.processGameTick = function(gameTimeNow, gameTimeDelta) {}

/**
 * Abstract method to create a Box2D body that represents this GamePiece. The returned
 * instance must have all the various dynamics attributes set. Subclasses should override
 * this method.
 * @return {Box2D.Dynamics.b2BodyDef} the Box2D body associated with this GamePiece.
 */
GamePiece.prototype.getBodyDef = function() { return null; }

/**
 * Abstract method to create and and add the Box2D fixtures used to represent the
 * geometry of this GamePiece.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 * @param {Box2D.Dynamics.b2Body} body The Box2D body. On return, this body will have
 *     all the GamePiece fixtures added to it.
 */
GamePiece.prototype.addFixturesToBody = function(simulation, body) {}

/**
 * Load the game piece's view and set the |view| object. On return, the |view| object
 * must point to a valid BodyView subclass. The default implementation sets the view
 * to a generic BodyView.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 * @return {BodyView} The BodyView subclass used to draw this GamePiece.
 */
GamePiece.prototype.loadView = function(simulation) {
  this.view = new BodyView();
}

/**
 * Draw the game piece geometry that is attached to it's Box2D body representation.
 * Game pieces that do not have a corresponding Box2D body representation can override
 * this method to do custom drawing.
 * @param {Context2D} ctx The 2D drawing context for the CANVAS.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 */
GamePiece.prototype.draw = function(ctx, simulation) {
  var b = this.body();
  if (b && b.IsActive()) {
    this.view.draw(ctx, b);
  }
}

/**
 * Method to add this game piece to the Box2D world. Calls abstract methods to create
 * the Box2D body and fixture(s) that represent this GamePiece. Also calls the method to
 * add the BodyView subclass that draws this GamePiece and attaches that to the Box2D
 * definition. Subclasses should override methods to create the Box2D fixtures and the
 * body instead of this method. Note that a GamePiece is represented by one body, but
 * each body can have many fixtures.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 */
GamePiece.prototype.addToSimulation = function(simulation) {
  var bodyDef = this.getBodyDef();
  if (bodyDef) {
    this._body = simulation.world().CreateBody(bodyDef);
    this.addFixturesToBody(simulation, this._body);
    this.loadView();
    this._body.SetUserData(this.uuid());
  } else {
    this._body = null;
  }
}
<commit_msg>Add GamePiece API to support stats.<commit_after>/* Copyright 2014 (c) SoFIE Studios.  All rights reserved.
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview  The GamePiece class. The GamePiece class is mostly an abstract super-
 * class for all the in-game objects. A GamePiece provides a UUID for each instance.
 * At a minimum, subclasses should override these methods:
 *     GamePiece.prototype.getBodyDef = function() {}
 *     GamePiece.prototype.addFixturesToBody = function(simulation, body) {}
 *     GamePiece.prototype.loadView = function(simulation) {}
 */

/**
 * Constructor for the GamePiece.
 * @constructor
 */
GamePiece = function() {
  /**
   * The Box2D body that represents this game piece. Not valid until addToSimulation()
   * is called.
   * @type {Box2D.Dynamics.b2Body}
   * @private
   */
  this._body = null;

  /**
   * The view associated with this game piece. Set via the loadView() method.
   * @type {BodyView}
   * @public
   */
  this.view = null;

  /**
   * The UUID for this instance. Generated lazily.
   * @type {string}
   * @private
   */
  this._uuid = uuid();
}
GamePiece.prototype.constructor = GamePiece;

/**
 * Return the UUID for this instance.
 * @return {String} UUID
 */
GamePiece.prototype.uuid = function() {
  return this._uuid;
}

/**
 * Accessor for the Box2D body that represents this game piece. Not valid until after
 * addToSimulation() has returned.
 * @return {Box2D.Dynamics.b2Body} The Box2D body.
 */
GamePiece.prototype.body = function() {
  return this._body;
}

/**
 * Abstract method to process a "tick" in the game simulation. Subclasses should override
 * this to update any internal time-based state. Default implementation does nothing.
 * @param {number} gameTimeNow The wall-clock time when this function was called,
 *     measured in seconds since the "epoch" (Jan 1, 1970).
 * @param {number} gameTimeDelta The time since the last call to this method, measured in
 *     seconds.
 */
GamePiece.prototype.processGameTick = function(gameTimeNow, gameTimeDelta) {}

/**
 * Abstract method to create a Box2D body that represents this GamePiece. The returned
 * instance must have all the various dynamics attributes set. Subclasses should override
 * this method.
 * @return {Box2D.Dynamics.b2BodyDef} the Box2D body associated with this GamePiece.
 */
GamePiece.prototype.getBodyDef = function() { return null; }

/**
 * Abstract method to create and and add the Box2D fixtures used to represent the
 * geometry of this GamePiece.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 * @param {Box2D.Dynamics.b2Body} body The Box2D body. On return, this body will have
 *     all the GamePiece fixtures added to it.
 */
GamePiece.prototype.addFixturesToBody = function(simulation, body) {}

/**
 * Load the game piece's view and set the |view| object. On return, the |view| object
 * must point to a valid BodyView subclass. The default implementation sets the view
 * to a generic BodyView.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 * @return {BodyView} The BodyView subclass used to draw this GamePiece.
 */
GamePiece.prototype.loadView = function(simulation) {
  this.view = new BodyView();
}

/**
 * Draw the game piece geometry that is attached to it's Box2D body representation.
 * Game pieces that do not have a corresponding Box2D body representation can override
 * this method to do custom drawing.
 * @param {Context2D} ctx The 2D drawing context for the CANVAS.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 */
GamePiece.prototype.draw = function(ctx, simulation) {
  var b = this.body();
  if (b && b.IsActive()) {
    this.view.draw(ctx, b);
  }
}

/**
 * Return whether this game piece reports stats for the stats panel. Default
 * implementation returns false.
 * @return {boolean} whether this game piece reports stats.
 */
GamePiece.prototype.hasStats = function() {
  return false;
}

/**
 * Return the display name of this game piece. This is used for things like the stats
 * panel. Default implementation returns "<unnamed>".
 * @return {string} the display name of this game pieces.
 */
GamePiece.prototype.displayName = function() {
  return "<unnamed>";  // TODO(daves): localize this?
}

/**
 * Return the stats for this game piece, formatted for display. Default implementation
 * returns "0".
 * @return {string} the stats formatted for display.
 */
GamePiece.prototype.statsDisplayString = function() {
  return "0";
}

/**
 * Method to add this game piece to the Box2D world. Calls abstract methods to create
 * the Box2D body and fixture(s) that represent this GamePiece. Also calls the method to
 * add the BodyView subclass that draws this GamePiece and attaches that to the Box2D
 * definition. Subclasses should override methods to create the Box2D fixtures and the
 * body instead of this method. Note that a GamePiece is represented by one body, but
 * each body can have many fixtures.
 * @param {Object} simulation The simulation. This object is expected to implement these
 *     methods:
 *       world() The Box2D world
 *       worldSize() The size of the game board in Box2D world coordinates
 *       scale() The scale factor from CANVAS to Box2D world
 */
GamePiece.prototype.addToSimulation = function(simulation) {
  var bodyDef = this.getBodyDef();
  if (bodyDef) {
    this._body = simulation.world().CreateBody(bodyDef);
    this.addFixturesToBody(simulation, this._body);
    this.loadView();
    this._body.SetUserData(this.uuid());
  } else {
    this._body = null;
  }
}
<|endoftext|>