<commit_before>// TODO in EditorGridPanel add clickToEdit option new EditorGridPanel(this).setClicksToEdit(2)
// TODO fieldLabel must have ":" have labelSeparator

var _classGen = {
    logId: true,
    elemCount: 0,

    getVarName: function(name){
        name = name ? name : 'item' + (_classGen.elemCount++);
        // remove spaces and capitalize each word
        var words = name.split(/\s/);
        Ext.each(words, function(w, i){
            words[i] = Ext.util.Format.capitalize(w);
        });
        name = words.join('');

        name = name.replace(/[\(\)/\\:;\<>=\-"]/gi, '');
        //name = Ext.util.Format.capitalize(name);
        return !name ? name : name.charAt(0).toLowerCase() + name.substr(1);
    },

    getPanelConfig: function (item){
        var code = '';
        if(item.title){
            code += '.setTitle("' + item.title + '")';
        } else if(item.fieldLabel){
            code += '.setLabel("' + item.fieldLabel + '")';
        }
        return code;
    },

    getItemCode: function (container, item){
        var name = '',
            code = '\tpublic ',
            xtype = item.getXType(),
            xtypes = item.getXTypes(),
            label = item.fieldLabel + (item.ownerCt.getLayout().labelSeparator || '');

        //console.debug('getItemCode', container, item);

        // all classes that are or extend panels
        if(xtype == 'panel' || xtypes.indexOf('/panel/') != -1 || item instanceof Ext.Panel){
            if(xtype == 'editorgrid' || xtypes.indexOf('/editorgrid/') != -1 || item instanceof Ext.grid.EditorGridPanel){
                name = _classGen.getVarName(item.title) + 'EditorGridPanel';
                code += 'EditorGridPanel ' + name + ' = new EditorGridPanel(' + container + ')';
            } else if(xtype == 'grid' || xtypes.indexOf('/grid/') != -1 || item instanceof Ext.grid.GridPanel){
                name = _classGen.getVarName(item.title) + 'GridPanel';
                code += 'GridPanel ' + name + ' = new GridPanel(' + container + ')';
            } else {
                name = _classGen.getVarName(item.title) + 'Panel';
                code += 'Panel ' + name + ' = new Panel(' + container + ')';
            }
            code += _classGen.getPanelConfig(item);
        }

        if(xtype == 'combo' || xtypes.indexOf('/combo/') != -1){
            name = _classGen.getVarName(label) + 'ComboBox';
            code += 'ComboBox ' + name + ' = new ComboBox(' + container + ', "' + label +  '")';
        } else if(xtype == 'textarea' || xtypes.indexOf('/textarea/') != -1){
            name = _classGen.getVarName(label) + 'TextArea';
            code += 'TextArea ' + name + ' = new TextArea(' + container + ', "'  + label +  '")';
        } else if(xtype == 'textfield' || xtypes.indexOf('/textfield/') != -1){
            name = _classGen.getVarName(label) + 'TextField';
            code += 'TextField ' + name + ' = new TextField(' + container + ', "'  + label +  '")';
        } else if(xtype == 'displayfield' || xtypes.indexOf('/displayfield/') != -1){
            name = _classGen.getVarName(label) + 'DisplayField';
            code += 'DisplayField ' + name + ' = new DisplayField(' + container + ', "'  + label +  '")';
        } else if(xtype == 'checkbox' || xtypes.indexOf('/checkbox/') != -1){
            name = _classGen.getVarName(label || item.boxLabel) + 'Checkbox';
            code += 'Checkbox ' + name + ' = new Checkbox(' + container + ', "'  + (label || item.boxLabel) +  '")';
        } else if(xtype == 'button' || xtypes.indexOf('/button/') != -1){
            name = _classGen.getVarName(item.text) + 'Button';
            code += 'Button ' + name + ' = new Button(' + container + ', "'  + item.text +  '")';
        } else if(!_classGen.isNecesaryType(xtype, xtypes)){
            code = '';
        } else {
            //code += 'XYZ xyz = new XYZ("' + xtype + '", "' + xtypes + '")';
            code = '';
            console.warn(container, item, xtype, xtypes, item.id);
        }
        if(code != ''){
            code += ';';
            if(_classGen.logId){
                code += '// ' + item.id;
            }
            code += '\n';
        }
        return {
            code: code,
            name: name
        };
    },

    isNecesaryType : function (xtype, xtypes){
        var necesary = true;
        if(xtype == 'hidden' || xtypes.indexOf('/hidden/') != -1){
            necesary = false;
        } else if(xtype == 'tbfill' || xtypes.indexOf('/tbfill/') != -1){
            necesary = false;
        } else if(xtype == 'tbtext' || xtypes.indexOf('/tbtext/') != -1){
            necesary = false;
        } else if(xtype == 'tbspacer' || xtypes.indexOf('/tbspacer/') != -1){
            necesary = false;
        } else if(xtype == 'tbseparator' || xtypes.indexOf('/tbseparator/') != -1){
            necesary = false;
        } else if(xtype == 'box' || xtypes.indexOf('/box/') != -1){
            necesary = false; // TODO this is temporary
        }
        return necesary;
    },

    isTabPanel : function (item){
        return item.getXType() == 'tabpanel' || item.getXTypes().indexOf('/tabpanel/') != -1;
    },

    getEachElementsCode : function (container, items, isTab){
        var code = '';
        if(items){
            if (Ext.isArray(items)){
                for(var i = 0, len = items.length; i < len; i++){
                    code += _classGen.getItemsCode(container, items[i]);
                }
            } else {
                items.each(function(it){
                    var c = container;
                    if(isTab){
                        c = _classGen.getVarName(it.title) + 'TabPanel';
                        code += '\tpublic TabPanel ' + c + ' = new TabPanel(' + container + ', "' + it.title +  '");\n';
                    }
                    code += _classGen.getItemsCode(c, it);
                });
            }
        }

        return code;
    },

    getItemsCode: function (container, item){
        //console.debug('getItemsCode', container, item);
        var elements,
            code = '';

        var isTab = _classGen.isTabPanel(item);
        if(!isTab){
            elements = _classGen.getItemCode(container, item);
            code += elements.code;
            container = elements.name || container;
        }

        code += _classGen.getInsideItems(container, item, isTab);

        return code;
    },

    getInsideItems: function(container, item, isTab){
        var code = '',
            tbar = item.getTopToolbar ? item.getTopToolbar() : false,
            bbar = item.getBottomToolbar ? item.getBottomToolbar(): false,
            fbar = item.getFooterToolbar ? item.getFooterToolbar(): false;

        code += _classGen.getEachElementsCode(container, item.items, isTab);
        if(tbar){
            code += _classGen.getEachElementsCode(container, tbar.items, false);
        }
        if(bbar){
            code += _classGen.getEachElementsCode(container, bbar.items, false);
        }
        if(fbar){
            code += _classGen.getEachElementsCode(container, fbar.items, false);
        }
        return code;
    },

    getActiveWinClassCode : function (){
        var w = Ext.WindowMgr.getActive(),
            name = _classGen.getVarName(w.title),
            code,
            container = 'this';
        console.debug('getActiveWinClassCode', name);
        code = 'public class ' + name + 'Window extends Window {\n';
        code += '\tpublic ' + name + 'Window(){\n';
        code += '\t\tsetTitle("' + w.title + '");\n';
        code += '\t}\n';

        code += _classGen.getInsideItems(container, w, false);

        code += '}\n';
        return code;
    }
};

console.info('\n'+ _classGen.getActiveWinClassCode());<commit_msg>add getFieldConfig improvement getItemCode<commit_after>// TODO in EditorGridPanel add clickToEdit option new EditorGridPanel(this).setClicksToEdit(2)
// TODO fieldLabel must have ":" have labelSeparator

var _classGen = {
    logId: true,
    elemCount: 0,

    getVarName: function(name){
        name = name ? name : 'item' + (_classGen.elemCount++);
        // remove spaces and capitalize each word
        var words = name.split(/\s/);
        Ext.each(words, function(w, i){
            words[i] = Ext.util.Format.capitalize(w);
        });
        name = words.join('');

        name = name.replace(/[\(\)/\\:;\<>=\-"]/gi, '');
        //name = Ext.util.Format.capitalize(name);
        return !name ? name : name.charAt(0).toLowerCase() + name.substr(1);
    },

    getPanelConfig: function (item){
        var code = '';
        if(item.title){
            code += '.setTitle("' + item.title + '")';
        } else if(item.fieldLabel){
            code += '.setLabel("' + item.fieldLabel + '")';
        }
        return code;
    },

    getFieldConfig: function (item){
        var code = '';
        if(item.fieldLabel){
            code += '.setLabel("' + item.fieldLabel + '")';
        } else if (item.name){
            code += '.setName("' + item.name + '")';
        }
        return code;
    },

    getItemCode: function (container, item){
        var name = '',
            className = '',
            code = '\tpublic ',
            xtype = item.getXType(),
            xtypes = item.getXTypes(),
            label = item.fieldLabel + (item.ownerCt.getLayout().labelSeparator || '');

        //console.debug('getItemCode', container, item);

        // all classes that are or extend panels
        if(xtype == 'panel' || xtypes.indexOf('/panel/') != -1 || item instanceof Ext.Panel){
            if(xtype == 'editorgrid' || xtypes.indexOf('/editorgrid/') != -1 || item instanceof Ext.grid.EditorGridPanel){
                className = 'EditorGridPanel';
            } else if(xtype == 'grid' || xtypes.indexOf('/grid/') != -1 || item instanceof Ext.grid.GridPanel){
                className = 'GridPanel';
            } else {
                className = 'Panel';
            }
            name = _classGen.getVarName(item.title) + className;
            code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
            code += _classGen.getPanelConfig(item);
        } else if(xtype == 'field' || xtypes.indexOf('/field/') != -1 || item instanceof Ext.form.Field){
            if(xtype == 'combo' || xtypes.indexOf('/combo/') != -1){
                className = 'ComboBox';
            } else if(xtype == 'textarea' || xtypes.indexOf('/textarea/') != -1){
                className = 'TextArea';
            } else if(xtype == 'textfield' || xtypes.indexOf('/textfield/') != -1){
                className = 'TextField';
            } else if(xtype == 'displayfield' || xtypes.indexOf('/displayfield/') != -1){
                className = 'DisplayField';
            } else if(xtype == 'checkbox' || xtypes.indexOf('/checkbox/') != -1){
                className = 'Checkbox';
                //TODO code += (label || item.boxLabel)
            }
            name = _classGen.getVarName(label) + className;
            code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
            code += _classGen.getFieldConfig(item);
        } else if(xtype == 'button' || xtypes.indexOf('/button/') != -1){
            name = _classGen.getVarName(item.text) + 'Button';
            code += 'Button ' + name + ' = new Button(' + container + ', "'  + item.text +  '")';
        } else if(!_classGen.isNecesaryType(xtype, xtypes)){
            code = '';
        } else {
            //code += 'XYZ xyz = new XYZ("' + xtype + '", "' + xtypes + '")';
            code = '';
            console.warn(container, item, xtype, xtypes, item.id);
        }
        if(code != ''){
            code += ';';
            if(_classGen.logId){
                code += '// ' + item.id;
            }
            code += '\n';
        }
        return {
            code: code,
            name: name
        };
    },

    isNecesaryType : function (xtype, xtypes){
        var necesary = true;
        if(xtype == 'hidden' || xtypes.indexOf('/hidden/') != -1){
            necesary = false;
        } else if(xtype == 'tbfill' || xtypes.indexOf('/tbfill/') != -1){
            necesary = false;
        } else if(xtype == 'tbtext' || xtypes.indexOf('/tbtext/') != -1){
            necesary = false;
        } else if(xtype == 'tbspacer' || xtypes.indexOf('/tbspacer/') != -1){
            necesary = false;
        } else if(xtype == 'tbseparator' || xtypes.indexOf('/tbseparator/') != -1){
            necesary = false;
        } else if(xtype == 'box' || xtypes.indexOf('/box/') != -1){
            necesary = false; // TODO this is temporary
        }
        return necesary;
    },

    isTabPanel : function (item){
        return item.getXType() == 'tabpanel' || item.getXTypes().indexOf('/tabpanel/') != -1;
    },

    getEachElementsCode : function (container, items, isTab){
        var code = '';
        if(items){
            if (Ext.isArray(items)){
                for(var i = 0, len = items.length; i < len; i++){
                    code += _classGen.getItemsCode(container, items[i]);
                }
            } else {
                items.each(function(it){
                    var c = container;
                    if(isTab){
                        c = _classGen.getVarName(it.title) + 'TabPanel';
                        code += '\tpublic TabPanel ' + c + ' = new TabPanel(' + container + ', "' + it.title +  '");\n';
                    }
                    code += _classGen.getItemsCode(c, it);
                });
            }
        }

        return code;
    },

    getItemsCode: function (container, item){
        //console.debug('getItemsCode', container, item);
        var elements,
            code = '';

        var isTab = _classGen.isTabPanel(item);
        if(!isTab){
            elements = _classGen.getItemCode(container, item);
            code += elements.code;
            container = elements.name || container;
        }

        code += _classGen.getInsideItems(container, item, isTab);

        return code;
    },

    getInsideItems: function(container, item, isTab){
        var code = '',
            tbar = item.getTopToolbar ? item.getTopToolbar() : false,
            bbar = item.getBottomToolbar ? item.getBottomToolbar(): false,
            fbar = item.getFooterToolbar ? item.getFooterToolbar(): false;

        code += _classGen.getEachElementsCode(container, item.items, isTab);
        if(tbar){
            code += _classGen.getEachElementsCode(container, tbar.items, false);
        }
        if(bbar){
            code += _classGen.getEachElementsCode(container, bbar.items, false);
        }
        if(fbar){
            code += _classGen.getEachElementsCode(container, fbar.items, false);
        }
        return code;
    },

    getActiveWinClassCode : function (){
        var w = Ext.WindowMgr.getActive(),
            name = _classGen.getVarName(w.title),
            code,
            container = 'this';
        console.debug('getActiveWinClassCode', name);
        code = 'public class ' + name + 'Window extends Window {\n';
        code += '\tpublic ' + name + 'Window(){\n';
        code += '\t\tsetTitle("' + w.title + '");\n';
        code += '\t}\n';

        code += _classGen.getInsideItems(container, w, false);

        code += '}\n';
        return code;
    }
};

console.info('\n'+ _classGen.getActiveWinClassCode());<|endoftext|>


<commit_before>import ns from 'imajs/client/core/namespace.js';

ns.namespace('Core.Page.Render');

/**
 * Server-side page renderer. The renderer renders the page into the HTML
 * markup and sends it to the client.
 *
 * @class Server
 * @extends Core.Abstract.PageRender
 * @namespace Core.Page.Render
 * @module Core
 * @submodule Core.Page
 */
export default class Server extends ns.Core.Abstract.PageRender {

	/**
	 * Initializes the server-side page renderer.
	 *
	 * @method contructor
	 * @constructor
	 * @param {Core.Page.Render.Factory} factory Factory for receive $Utils to view.
	 * @param {Vendor.Helper} Helper The IMA.js helper methods.
	 * @param {Vendor.React} React React framework instance to use to render the
	 *        page.
	 * @param {Object<string, *>} settings Application setting for the current
	 *        application environment.
	 * @param {Core.Router.Response} response Utility for sending the page markup
	 *        to the client as a response to the current HTTP request.
	 * @param {Core.Interface.Cache} cache Resource cache caching the results of
	 *        HTTP requests made by services used by the rendered page.
	 */
	constructor(factory, Helper, React, settings, response, cache) {
		super(factory, Helper, React, settings);

		/**
		 * Utility for sending the page markup to the client as a response to the
		 * current HTTP request.
		 *
		 * @private
		 * @property _response
		 * @type {Core.Router.Response}
		 */
		this._response = response;

		/**
		 * The resource cache, caching the results of all HTTP requests made by the
		 * services using by the rendered page. The state of the cache will then be
		 * serialized and sent to the client to re-initialize the page at the
		 * client side.
		 *
		 * @private
		 * @property _cache
		 * @type {Core.Interface.Cache}
		 */
		this._cache = cache;

	}

	/**
	 * Renders the page using the provided controller and view. The actual
	 * behavior of this method differs at the client and the at server in the
	 * following way:
	 *
	 * On server, the method renders the page to a string containing HTML markup
	 * to send to the client.
	 *
	 * On client, the method renders the page into DOM, re-using the DOM created
	 * from the HTML markup send by the server if possible.
	 *
	 * @inheritDoc
	 * @override
	 * @method mount
	 * @abstract
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @return {Promise}
	 */
	mount(controller, view) {
		var loadPromises = this._wrapEachKeyToPromise(controller.load());

		if (this._response.isResponseSent()) {
			return Promise.resolve(this._response.getResponseParams());
		}

		return (
			this._Helper
				.allPromiseHash(loadPromises)
				.then((fetchedResources) => {
					return this._renderPage(controller, view, fetchedResources);
				})
		);
	}

	/**
	 * Only update controller state and React view not call constructor.
	 *
	 * It is useful for same controller and view, where only change url params.
	 * Then it is possible to reuse same controller and view.
	 *
	 * @inheritDoc
	 * @override
	 * @method update
	 * @param {Core.Decorator.Controller} controller
	 * @param {Object<string, string>=} [params={}] Last route params.
	 * @return {Promise}
	 */
	update(controller, params = {}) {
		return this.mount(controller, params);
	}

	/**
	 * Unmount view from the DOM. Then React always call constructor
	 * for new mounting view.
	 *
	 * @inheritDoc
	 * @override
	 * @method unmount
	 */
	unmount() {
		if (this._reactiveView) {
			this._reactiveView = null;
		}
	}

	/**
	 * THe HTML code will include a script settings the "revival"
	 * data for the application at the client-side.
	 *
	 * @method _getRevivalSettings
	 * @private
	 * @return {string} HTML code containing script element to include into
	 *         the rendered page.
	 */
	_getRevivalSettings() {
		return (
			'<script>' +
			' window.$IMA = window.$IMA || {};' +
			' window.$IMA.Cache = ' + (this._cache.serialize()) + ';' +
			' window.$IMA.$Language = "' + (this._settings.$Language) + '";' +
			' window.$IMA.$Env = "' + (this._settings.$Env) + '";' +
			' window.$IMA.$Debug = "' + (this._settings.$Debug) + '";' +
			' window.$IMA.$Protocol = "' + (this._settings.$Protocol) + '";' +
			' window.$IMA.$Host = "' + (this._settings.$Host) + '";' +
			' window.$IMA.$Root = "' + (this._settings.$Root) + '";' +
			' window.$IMA.$LanguagePartPath = "' + (this._settings.$LanguagePartPath) + '";' +
			'</script>'
		);
	}

	/**
	 * Creates a copy of the provided data map object that has the values of its
	 * fields wrapped into Promises.
	 *
	 * The the values that are already Promises will referenced directly without
	 * wrapping then into another Promise.
	 *
	 * @method _wrapEachKeyToPromise
	 * @protected
	 * @param {Object<string, *>=} [dataMap={}] A map of data that should have its
	 *        values wrapped into Promises.
	 * @return {Object<string, Promise>} A copy of the provided data
	 *         map that has all its values wrapped into promises.
	 */
	_wrapEachKeyToPromise(dataMap = {}) {
		var copy = {};

		for (var field of Object.keys(dataMap)) {
			var value = dataMap[field];

			if (value instanceof Promise) {
				copy[field] = value;
			} else {
				copy[field] = Promise.resolve(value);
			}
		}

		return copy;
	}

	/**
	 * Render page after all promises from loaded resources is resolved.
	 *
	 * @private
	 * @method _renderPage
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @param {Object<string, *>} fetchedResource
	 * @return {{content: string, status: number}}
	 */
	_renderPage(controller, view, fetchedResources) {
		if (!this._response.isResponseSent()) {
			controller.setState(fetchedResources);
			controller.setMetaParams(fetchedResources);

			this._response
				.status(controller.getHttpStatus())
				.send(this._renderPageContentToString(controller, view));
		}

		return this._response.getResponseParams();
	}

	/**
	 * Render page content to a string containing HTML markup.
	 *
	 * @private
	 * @method _renderPageContentToString
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @return {string}
	 */
	_renderPageContentToString(controller, view) {
		var props = this._generateViewProps(controller.getState());
		var reactElementView = this._factory.wrapView(view, props);
		var pageMarkup = this._React.renderToString(reactElementView);

		var documentView = ns.get(this._settings.$Page.$Render.documentView);
		var documentViewFactory = this._React.createFactory(documentView);
		var appMarkup = this._React.renderToStaticMarkup(documentViewFactory({
			page: pageMarkup,
			revivalSettings: this._getRevivalSettings(),
			metaManager: controller.getMetaManager(),
			$Utils: this._factory.getUtils()
		}));

		return '<!doctype html>\n' + appMarkup;
	}
}

ns.Core.Page.Render.Server = Server;
<commit_msg>#! fix bug $Debug is boolean<commit_after>import ns from 'imajs/client/core/namespace.js';

ns.namespace('Core.Page.Render');

/**
 * Server-side page renderer. The renderer renders the page into the HTML
 * markup and sends it to the client.
 *
 * @class Server
 * @extends Core.Abstract.PageRender
 * @namespace Core.Page.Render
 * @module Core
 * @submodule Core.Page
 */
export default class Server extends ns.Core.Abstract.PageRender {

	/**
	 * Initializes the server-side page renderer.
	 *
	 * @method contructor
	 * @constructor
	 * @param {Core.Page.Render.Factory} factory Factory for receive $Utils to view.
	 * @param {Vendor.Helper} Helper The IMA.js helper methods.
	 * @param {Vendor.React} React React framework instance to use to render the
	 *        page.
	 * @param {Object<string, *>} settings Application setting for the current
	 *        application environment.
	 * @param {Core.Router.Response} response Utility for sending the page markup
	 *        to the client as a response to the current HTTP request.
	 * @param {Core.Interface.Cache} cache Resource cache caching the results of
	 *        HTTP requests made by services used by the rendered page.
	 */
	constructor(factory, Helper, React, settings, response, cache) {
		super(factory, Helper, React, settings);

		/**
		 * Utility for sending the page markup to the client as a response to the
		 * current HTTP request.
		 *
		 * @private
		 * @property _response
		 * @type {Core.Router.Response}
		 */
		this._response = response;

		/**
		 * The resource cache, caching the results of all HTTP requests made by the
		 * services using by the rendered page. The state of the cache will then be
		 * serialized and sent to the client to re-initialize the page at the
		 * client side.
		 *
		 * @private
		 * @property _cache
		 * @type {Core.Interface.Cache}
		 */
		this._cache = cache;

	}

	/**
	 * Renders the page using the provided controller and view. The actual
	 * behavior of this method differs at the client and the at server in the
	 * following way:
	 *
	 * On server, the method renders the page to a string containing HTML markup
	 * to send to the client.
	 *
	 * On client, the method renders the page into DOM, re-using the DOM created
	 * from the HTML markup send by the server if possible.
	 *
	 * @inheritDoc
	 * @override
	 * @method mount
	 * @abstract
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @return {Promise}
	 */
	mount(controller, view) {
		var loadPromises = this._wrapEachKeyToPromise(controller.load());

		if (this._response.isResponseSent()) {
			return Promise.resolve(this._response.getResponseParams());
		}

		return (
			this._Helper
				.allPromiseHash(loadPromises)
				.then((fetchedResources) => {
					return this._renderPage(controller, view, fetchedResources);
				})
		);
	}

	/**
	 * Only update controller state and React view not call constructor.
	 *
	 * It is useful for same controller and view, where only change url params.
	 * Then it is possible to reuse same controller and view.
	 *
	 * @inheritDoc
	 * @override
	 * @method update
	 * @param {Core.Decorator.Controller} controller
	 * @param {Object<string, string>=} [params={}] Last route params.
	 * @return {Promise}
	 */
	update(controller, params = {}) {
		return this.mount(controller, params);
	}

	/**
	 * Unmount view from the DOM. Then React always call constructor
	 * for new mounting view.
	 *
	 * @inheritDoc
	 * @override
	 * @method unmount
	 */
	unmount() {
		if (this._reactiveView) {
			this._reactiveView = null;
		}
	}

	/**
	 * THe HTML code will include a script settings the "revival"
	 * data for the application at the client-side.
	 *
	 * @method _getRevivalSettings
	 * @private
	 * @return {string} HTML code containing script element to include into
	 *         the rendered page.
	 */
	_getRevivalSettings() {
		return (
			'<script>' +
			' window.$IMA = window.$IMA || {};' +
			' window.$IMA.Cache = ' + (this._cache.serialize()) + ';' +
			' window.$IMA.$Language = "' + (this._settings.$Language) + '";' +
			' window.$IMA.$Env = "' + (this._settings.$Env) + '";' +
			' window.$IMA.$Debug = ' + (this._settings.$Debug) + ';' +
			' window.$IMA.$Protocol = "' + (this._settings.$Protocol) + '";' +
			' window.$IMA.$Host = "' + (this._settings.$Host) + '";' +
			' window.$IMA.$Root = "' + (this._settings.$Root) + '";' +
			' window.$IMA.$LanguagePartPath = "' + (this._settings.$LanguagePartPath) + '";' +
			'</script>'
		);
	}

	/**
	 * Creates a copy of the provided data map object that has the values of its
	 * fields wrapped into Promises.
	 *
	 * The the values that are already Promises will referenced directly without
	 * wrapping then into another Promise.
	 *
	 * @method _wrapEachKeyToPromise
	 * @protected
	 * @param {Object<string, *>=} [dataMap={}] A map of data that should have its
	 *        values wrapped into Promises.
	 * @return {Object<string, Promise>} A copy of the provided data
	 *         map that has all its values wrapped into promises.
	 */
	_wrapEachKeyToPromise(dataMap = {}) {
		var copy = {};

		for (var field of Object.keys(dataMap)) {
			var value = dataMap[field];

			if (value instanceof Promise) {
				copy[field] = value;
			} else {
				copy[field] = Promise.resolve(value);
			}
		}

		return copy;
	}

	/**
	 * Render page after all promises from loaded resources is resolved.
	 *
	 * @private
	 * @method _renderPage
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @param {Object<string, *>} fetchedResource
	 * @return {{content: string, status: number}}
	 */
	_renderPage(controller, view, fetchedResources) {
		if (!this._response.isResponseSent()) {
			controller.setState(fetchedResources);
			controller.setMetaParams(fetchedResources);

			this._response
				.status(controller.getHttpStatus())
				.send(this._renderPageContentToString(controller, view));
		}

		return this._response.getResponseParams();
	}

	/**
	 * Render page content to a string containing HTML markup.
	 *
	 * @private
	 * @method _renderPageContentToString
	 * @param {Core.Abstract.Controller} controller
	 * @param {Vendor.React.Component} view
	 * @return {string}
	 */
	_renderPageContentToString(controller, view) {
		var props = this._generateViewProps(controller.getState());
		var reactElementView = this._factory.wrapView(view, props);
		var pageMarkup = this._React.renderToString(reactElementView);

		var documentView = ns.get(this._settings.$Page.$Render.documentView);
		var documentViewFactory = this._React.createFactory(documentView);
		var appMarkup = this._React.renderToStaticMarkup(documentViewFactory({
			page: pageMarkup,
			revivalSettings: this._getRevivalSettings(),
			metaManager: controller.getMetaManager(),
			$Utils: this._factory.getUtils()
		}));

		return '<!doctype html>\n' + appMarkup;
	}
}

ns.Core.Page.Render.Server = Server;
<|endoftext|>


<commit_before>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');
var Plotly = require('../plotly');
var Registry = require('../registry');
var Plots = require('../plots/plots');
var Lib = require('../lib');

var Color = require('../components/color');
var Drawing = require('../components/drawing');
var Titles = require('../components/titles');
var ModeBar = require('../components/modebar');
var initInteractions = require('../plots/cartesian/graph_interact');

exports.layoutStyles = function(gd) {
    return Lib.syncOrAsync([Plots.doAutoMargin, exports.lsInner], gd);
};

function overlappingDomain(xDomain, yDomain, domains) {
    for(var i = 0; i < domains.length; i++) {
        var existingX = domains[i][0],
            existingY = domains[i][1];

        if(existingX[0] >= xDomain[1] || existingX[1] <= xDomain[0]) {
            continue;
        }
        if(existingY[0] < yDomain[1] && existingY[1] > yDomain[0]) {
            return true;
        }
    }
    return false;
}

exports.lsInner = function(gd) {
    var fullLayout = gd._fullLayout;
    var gs = fullLayout._size;
    var axList = Plotly.Axes.list(gd);
    var i;

    // clear axis line positions, to be set in the subplot loop below
    for(i = 0; i < axList.length; i++) axList[i]._linepositions = {};

    fullLayout._paperdiv
        .style({
            width: fullLayout.width + 'px',
            height: fullLayout.height + 'px'
        })
        .selectAll('.main-svg')
            .call(Drawing.setSize, fullLayout.width, fullLayout.height);

    gd._context.setBackground(gd, fullLayout.paper_bgcolor);

    var subplotSelection = fullLayout._paper.selectAll('g.subplot');

    // figure out which backgrounds we need to draw, and in which layers
    // to put them
    var lowerBackgroundIDs = [];
    var lowerDomains = [];
    subplotSelection.each(function(subplot) {
        var plotinfo = fullLayout._plots[subplot];

        if(plotinfo.mainplot) {
            // mainplot is a reference to the main plot this one is overlaid on
            // so if it exists, this is an overlaid plot and we don't need to
            // give it its own background
            if(plotinfo.bg) {
                plotinfo.bg.remove();
            }
            plotinfo.bg = undefined;
            return;
        }

        var xa = Plotly.Axes.getFromId(gd, subplot, 'x');
        var ya = Plotly.Axes.getFromId(gd, subplot, 'y');
        var xDomain = xa.domain;
        var yDomain = ya.domain;
        var plotgroupBgData = [];

        if(overlappingDomain(xDomain, yDomain, lowerDomains)) {
            plotgroupBgData = [0];
        }
        else {
            lowerBackgroundIDs.push(subplot);
            lowerDomains.push([xDomain, yDomain]);
        }

        // create the plot group backgrounds now, since
        // they're all independent selections
        var plotgroupBg = plotinfo.plotgroup.selectAll('.bg')
            .data(plotgroupBgData);

        plotgroupBg.enter().append('rect')
            .classed('bg', true);

        plotgroupBg.exit().remove();

        plotgroupBg.each(function() {
            plotinfo.bg = plotgroupBg;
            var pgNode = plotinfo.plotgroup.node();
            pgNode.insertBefore(this, pgNode.childNodes[0]);
        });
    });

    // now create all the lower-layer backgrounds at once now that
    // we have the list of subplots that need them
    var lowerBackgrounds = fullLayout._bgLayer.selectAll('.bg')
        .data(lowerBackgroundIDs);

    lowerBackgrounds.enter().append('rect')
        .classed('bg', true);

    lowerBackgrounds.exit().remove();

    lowerBackgrounds.each(function(subplot) {
        fullLayout._plots[subplot].bg = d3.select(this);
    });

    var freefinished = [];
    subplotSelection.each(function(subplot) {
        var plotinfo = fullLayout._plots[subplot];

        var xa = Plotly.Axes.getFromId(gd, subplot, 'x');
        var ya = Plotly.Axes.getFromId(gd, subplot, 'y');

        // reset scale in case the margins have changed
        xa.setScale();
        ya.setScale();

        if(plotinfo.bg && fullLayout._has('cartesian')) {
            plotinfo.bg
                .call(Drawing.setRect,
                    xa._offset - gs.p, ya._offset - gs.p,
                    xa._length + 2 * gs.p, ya._length + 2 * gs.p)
                .call(Color.fill, fullLayout.plot_bgcolor)
                .style('stroke-width', 0);
        }

        // Clip so that data only shows up on the plot area.
        plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot';

        var plotClip = fullLayout._defs.selectAll('g.clips')
            .selectAll('#' + plotinfo.clipId)
            .data([0]);

        plotClip.enter().append('clipPath')
            .attr({
                'class': 'plotclip',
                'id': plotinfo.clipId
            })
            .append('rect');

        plotClip.selectAll('rect')
            .attr({
                'width': xa._length,
                'height': ya._length
            });

        plotinfo.plot.call(Drawing.setTranslate, xa._offset, ya._offset);
        plotinfo.plot.call(Drawing.setClipUrl, plotinfo.clipId);

        var xlw = Drawing.crispRound(gd, xa.linewidth, 1);
        var ylw = Drawing.crispRound(gd, ya.linewidth, 1);
        var xp = gs.p + ylw;
        var xpathPrefix = 'M' + (-xp) + ',';
        var xpathSuffix = 'h' + (xa._length + 2 * xp);
        var showfreex = xa.anchor === 'free' &&
            freefinished.indexOf(xa._id) === -1;
        var freeposx = gs.h * (1 - (xa.position||0)) + ((xlw / 2) % 1);
        var showbottom =
            (xa.anchor === ya._id && (xa.mirror || xa.side !== 'top')) ||
            xa.mirror === 'all' || xa.mirror === 'allticks' ||
            (xa.mirrors && xa.mirrors[ya._id + 'bottom']);
        var bottompos = ya._length + gs.p + xlw / 2;
        var showtop =
            (xa.anchor === ya._id && (xa.mirror || xa.side === 'top')) ||
            xa.mirror === 'all' || xa.mirror === 'allticks' ||
            (xa.mirrors && xa.mirrors[ya._id + 'top']);
        var toppos = -gs.p - xlw / 2;

        // shorten y axis lines so they don't overlap x axis lines
        var yp = gs.p;
        // except where there's no x line
        // TODO: this gets more complicated with multiple x and y axes
        var ypbottom = showbottom ? 0 : xlw;
        var yptop = showtop ? 0 : xlw;
        var ypathSuffix = ',' + (-yp - yptop) +
            'v' + (ya._length + 2 * yp + yptop + ypbottom);
        var showfreey = ya.anchor === 'free' &&
            freefinished.indexOf(ya._id) === -1;
        var freeposy = gs.w * (ya.position||0) + ((ylw / 2) % 1);
        var showleft =
            (ya.anchor === xa._id && (ya.mirror || ya.side !== 'right')) ||
            ya.mirror === 'all' || ya.mirror === 'allticks' ||
            (ya.mirrors && ya.mirrors[xa._id + 'left']);
        var leftpos = -gs.p - ylw / 2;
        var showright =
            (ya.anchor === xa._id && (ya.mirror || ya.side === 'right')) ||
            ya.mirror === 'all' || ya.mirror === 'allticks' ||
            (ya.mirrors && ya.mirrors[xa._id + 'right']);
        var rightpos = xa._length + gs.p + ylw / 2;

        // save axis line positions for ticks, draggers, etc to reference
        // each subplot gets an entry:
        //    [left or bottom, right or top, free, main]
        // main is the position at which to draw labels and draggers, if any
        xa._linepositions[subplot] = [
            showbottom ? bottompos : undefined,
            showtop ? toppos : undefined,
            showfreex ? freeposx : undefined
        ];
        if(xa.anchor === ya._id) {
            xa._linepositions[subplot][3] = xa.side === 'top' ?
                toppos : bottompos;
        }
        else if(showfreex) {
            xa._linepositions[subplot][3] = freeposx;
        }

        ya._linepositions[subplot] = [
            showleft ? leftpos : undefined,
            showright ? rightpos : undefined,
            showfreey ? freeposy : undefined
        ];
        if(ya.anchor === xa._id) {
            ya._linepositions[subplot][3] = ya.side === 'right' ?
                rightpos : leftpos;
        }
        else if(showfreey) {
            ya._linepositions[subplot][3] = freeposy;
        }

        // translate all the extra stuff to have the
        // same origin as the plot area or axes
        var origin = 'translate(' + xa._offset + ',' + ya._offset + ')';
        var originx = origin;
        var originy = origin;
        if(showfreex) {
            originx = 'translate(' + xa._offset + ',' + gs.t + ')';
            toppos += ya._offset - gs.t;
            bottompos += ya._offset - gs.t;
        }
        if(showfreey) {
            originy = 'translate(' + gs.l + ',' + ya._offset + ')';
            leftpos += xa._offset - gs.l;
            rightpos += xa._offset - gs.l;
        }

        if(fullLayout._has('cartesian')) {
            plotinfo.xlines
                .attr('transform', originx)
                .attr('d', (
                    (showbottom ? (xpathPrefix + bottompos + xpathSuffix) : '') +
                    (showtop ? (xpathPrefix + toppos + xpathSuffix) : '') +
                    (showfreex ? (xpathPrefix + freeposx + xpathSuffix) : '')) ||
                    // so it doesn't barf with no lines shown
                    'M0,0')
                .style('stroke-width', xlw + 'px')
                .call(Color.stroke, xa.showline ?
                    xa.linecolor : 'rgba(0,0,0,0)');
            plotinfo.ylines
                .attr('transform', originy)
                .attr('d', (
                    (showleft ? ('M' + leftpos + ypathSuffix) : '') +
                    (showright ? ('M' + rightpos + ypathSuffix) : '') +
                    (showfreey ? ('M' + freeposy + ypathSuffix) : '')) ||
                    'M0,0')
                .attr('stroke-width', ylw + 'px')
                .call(Color.stroke, ya.showline ?
                    ya.linecolor : 'rgba(0,0,0,0)');
        }

        plotinfo.xaxislayer.attr('transform', originx);
        plotinfo.yaxislayer.attr('transform', originy);
        plotinfo.gridlayer.attr('transform', origin);
        plotinfo.zerolinelayer.attr('transform', origin);
        plotinfo.draglayer.attr('transform', origin);

        // mark free axes as displayed, so we don't draw them again
        if(showfreex) { freefinished.push(xa._id); }
        if(showfreey) { freefinished.push(ya._id); }
    });

    Plotly.Axes.makeClipPaths(gd);
    exports.drawMainTitle(gd);
    ModeBar.manage(gd);

    return gd._promises.length && Promise.all(gd._promises);
};

exports.drawMainTitle = function(gd) {
    var fullLayout = gd._fullLayout;

    Titles.draw(gd, 'gtitle', {
        propContainer: fullLayout,
        propName: 'title',
        dfltName: 'Plot',
        attributes: {
            x: fullLayout.width / 2,
            y: fullLayout._size.t / 2,
            'text-anchor': 'middle'
        }
    });
};

// First, see if we need to do arraysToCalcdata
// call it regardless of what change we made, in case
// supplyDefaults brought in an array that was already
// in gd.data but not in gd._fullData previously
exports.doTraceStyle = function(gd) {
    for(var i = 0; i < gd.calcdata.length; i++) {
        var cdi = gd.calcdata[i],
            _module = ((cdi[0] || {}).trace || {})._module || {},
            arraysToCalcdata = _module.arraysToCalcdata;

        if(arraysToCalcdata) arraysToCalcdata(cdi, cdi[0].trace);
    }

    Plots.style(gd);
    Registry.getComponentMethod('legend', 'draw')(gd);

    return Plots.previousPromises(gd);
};

exports.doColorBars = function(gd) {
    for(var i = 0; i < gd.calcdata.length; i++) {
        var cdi0 = gd.calcdata[i][0];

        if((cdi0.t || {}).cb) {
            var trace = cdi0.trace,
                cb = cdi0.t.cb;

            if(Registry.traceIs(trace, 'contour')) {
                cb.line({
                    width: trace.contours.showlines !== false ?
                        trace.line.width : 0,
                    dash: trace.line.dash,
                    color: trace.contours.coloring === 'line' ?
                        cb._opts.line.color : trace.line.color
                });
            }
            if(Registry.traceIs(trace, 'markerColorscale')) {
                cb.options(trace.marker.colorbar)();
            }
            else cb.options(trace.colorbar)();
        }
    }

    return Plots.previousPromises(gd);
};

// force plot() to redo the layout and replot with the modified layout
exports.layoutReplot = function(gd) {
    var layout = gd.layout;
    gd.layout = undefined;
    return Plotly.plot(gd, '', layout);
};

exports.doLegend = function(gd) {
    Registry.getComponentMethod('legend', 'draw')(gd);
    return Plots.previousPromises(gd);
};

exports.doTicksRelayout = function(gd) {
    Plotly.Axes.doTicks(gd, 'redraw');
    exports.drawMainTitle(gd);
    return Plots.previousPromises(gd);
};

exports.doModeBar = function(gd) {
    var fullLayout = gd._fullLayout;
    var subplotIds, subplotObj, i;

    ModeBar.manage(gd);
    initInteractions(gd);

    subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout[subplotIds[i]]._scene;
        subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode);
    }

    subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout._plots[subplotIds[i]]._scene2d;
        subplotObj.updateFx(fullLayout.dragmode);
    }

    subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout[subplotIds[i]]._subplot;
        subplotObj.updateFx(fullLayout);
    }

    return Plots.previousPromises(gd);
};

exports.doCamera = function(gd) {
    var fullLayout = gd._fullLayout,
        sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');

    for(var i = 0; i < sceneIds.length; i++) {
        var sceneLayout = fullLayout[sceneIds[i]],
            scene = sceneLayout._scene;

        scene.setCamera(sceneLayout.camera);
    }
};
<commit_msg>plotinfo already has xaxis/yaxis stashed<commit_after>/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var d3 = require('d3');
var Plotly = require('../plotly');
var Registry = require('../registry');
var Plots = require('../plots/plots');
var Lib = require('../lib');

var Color = require('../components/color');
var Drawing = require('../components/drawing');
var Titles = require('../components/titles');
var ModeBar = require('../components/modebar');
var initInteractions = require('../plots/cartesian/graph_interact');

exports.layoutStyles = function(gd) {
    return Lib.syncOrAsync([Plots.doAutoMargin, exports.lsInner], gd);
};

function overlappingDomain(xDomain, yDomain, domains) {
    for(var i = 0; i < domains.length; i++) {
        var existingX = domains[i][0],
            existingY = domains[i][1];

        if(existingX[0] >= xDomain[1] || existingX[1] <= xDomain[0]) {
            continue;
        }
        if(existingY[0] < yDomain[1] && existingY[1] > yDomain[0]) {
            return true;
        }
    }
    return false;
}

exports.lsInner = function(gd) {
    var fullLayout = gd._fullLayout;
    var gs = fullLayout._size;
    var axList = Plotly.Axes.list(gd);
    var i;

    // clear axis line positions, to be set in the subplot loop below
    for(i = 0; i < axList.length; i++) axList[i]._linepositions = {};

    fullLayout._paperdiv
        .style({
            width: fullLayout.width + 'px',
            height: fullLayout.height + 'px'
        })
        .selectAll('.main-svg')
            .call(Drawing.setSize, fullLayout.width, fullLayout.height);

    gd._context.setBackground(gd, fullLayout.paper_bgcolor);

    var subplotSelection = fullLayout._paper.selectAll('g.subplot');

    // figure out which backgrounds we need to draw, and in which layers
    // to put them
    var lowerBackgroundIDs = [];
    var lowerDomains = [];
    subplotSelection.each(function(subplot) {
        var plotinfo = fullLayout._plots[subplot];

        if(plotinfo.mainplot) {
            // mainplot is a reference to the main plot this one is overlaid on
            // so if it exists, this is an overlaid plot and we don't need to
            // give it its own background
            if(plotinfo.bg) {
                plotinfo.bg.remove();
            }
            plotinfo.bg = undefined;
            return;
        }

        var xDomain = plotinfo.xaxis.domain;
        var yDomain = plotinfo.yaxis.domain;
        var plotgroupBgData = [];

        if(overlappingDomain(xDomain, yDomain, lowerDomains)) {
            plotgroupBgData = [0];
        }
        else {
            lowerBackgroundIDs.push(subplot);
            lowerDomains.push([xDomain, yDomain]);
        }

        // create the plot group backgrounds now, since
        // they're all independent selections
        var plotgroupBg = plotinfo.plotgroup.selectAll('.bg')
            .data(plotgroupBgData);

        plotgroupBg.enter().append('rect')
            .classed('bg', true);

        plotgroupBg.exit().remove();

        plotgroupBg.each(function() {
            plotinfo.bg = plotgroupBg;
            var pgNode = plotinfo.plotgroup.node();
            pgNode.insertBefore(this, pgNode.childNodes[0]);
        });
    });

    // now create all the lower-layer backgrounds at once now that
    // we have the list of subplots that need them
    var lowerBackgrounds = fullLayout._bgLayer.selectAll('.bg')
        .data(lowerBackgroundIDs);

    lowerBackgrounds.enter().append('rect')
        .classed('bg', true);

    lowerBackgrounds.exit().remove();

    lowerBackgrounds.each(function(subplot) {
        fullLayout._plots[subplot].bg = d3.select(this);
    });

    var freefinished = [];
    subplotSelection.each(function(subplot) {
        var plotinfo = fullLayout._plots[subplot];
        var xa = plotinfo.xaxis;
        var ya = plotinfo.yaxis;

        // reset scale in case the margins have changed
        xa.setScale();
        ya.setScale();

        if(plotinfo.bg && fullLayout._has('cartesian')) {
            plotinfo.bg
                .call(Drawing.setRect,
                    xa._offset - gs.p, ya._offset - gs.p,
                    xa._length + 2 * gs.p, ya._length + 2 * gs.p)
                .call(Color.fill, fullLayout.plot_bgcolor)
                .style('stroke-width', 0);
        }

        // Clip so that data only shows up on the plot area.
        plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot';

        var plotClip = fullLayout._defs.selectAll('g.clips')
            .selectAll('#' + plotinfo.clipId)
            .data([0]);

        plotClip.enter().append('clipPath')
            .attr({
                'class': 'plotclip',
                'id': plotinfo.clipId
            })
            .append('rect');

        plotClip.selectAll('rect')
            .attr({
                'width': xa._length,
                'height': ya._length
            });

        plotinfo.plot.call(Drawing.setTranslate, xa._offset, ya._offset);
        plotinfo.plot.call(Drawing.setClipUrl, plotinfo.clipId);

        var xlw = Drawing.crispRound(gd, xa.linewidth, 1);
        var ylw = Drawing.crispRound(gd, ya.linewidth, 1);
        var xp = gs.p + ylw;
        var xpathPrefix = 'M' + (-xp) + ',';
        var xpathSuffix = 'h' + (xa._length + 2 * xp);
        var showfreex = xa.anchor === 'free' &&
            freefinished.indexOf(xa._id) === -1;
        var freeposx = gs.h * (1 - (xa.position||0)) + ((xlw / 2) % 1);
        var showbottom =
            (xa.anchor === ya._id && (xa.mirror || xa.side !== 'top')) ||
            xa.mirror === 'all' || xa.mirror === 'allticks' ||
            (xa.mirrors && xa.mirrors[ya._id + 'bottom']);
        var bottompos = ya._length + gs.p + xlw / 2;
        var showtop =
            (xa.anchor === ya._id && (xa.mirror || xa.side === 'top')) ||
            xa.mirror === 'all' || xa.mirror === 'allticks' ||
            (xa.mirrors && xa.mirrors[ya._id + 'top']);
        var toppos = -gs.p - xlw / 2;

        // shorten y axis lines so they don't overlap x axis lines
        var yp = gs.p;
        // except where there's no x line
        // TODO: this gets more complicated with multiple x and y axes
        var ypbottom = showbottom ? 0 : xlw;
        var yptop = showtop ? 0 : xlw;
        var ypathSuffix = ',' + (-yp - yptop) +
            'v' + (ya._length + 2 * yp + yptop + ypbottom);
        var showfreey = ya.anchor === 'free' &&
            freefinished.indexOf(ya._id) === -1;
        var freeposy = gs.w * (ya.position||0) + ((ylw / 2) % 1);
        var showleft =
            (ya.anchor === xa._id && (ya.mirror || ya.side !== 'right')) ||
            ya.mirror === 'all' || ya.mirror === 'allticks' ||
            (ya.mirrors && ya.mirrors[xa._id + 'left']);
        var leftpos = -gs.p - ylw / 2;
        var showright =
            (ya.anchor === xa._id && (ya.mirror || ya.side === 'right')) ||
            ya.mirror === 'all' || ya.mirror === 'allticks' ||
            (ya.mirrors && ya.mirrors[xa._id + 'right']);
        var rightpos = xa._length + gs.p + ylw / 2;

        // save axis line positions for ticks, draggers, etc to reference
        // each subplot gets an entry:
        //    [left or bottom, right or top, free, main]
        // main is the position at which to draw labels and draggers, if any
        xa._linepositions[subplot] = [
            showbottom ? bottompos : undefined,
            showtop ? toppos : undefined,
            showfreex ? freeposx : undefined
        ];
        if(xa.anchor === ya._id) {
            xa._linepositions[subplot][3] = xa.side === 'top' ?
                toppos : bottompos;
        }
        else if(showfreex) {
            xa._linepositions[subplot][3] = freeposx;
        }

        ya._linepositions[subplot] = [
            showleft ? leftpos : undefined,
            showright ? rightpos : undefined,
            showfreey ? freeposy : undefined
        ];
        if(ya.anchor === xa._id) {
            ya._linepositions[subplot][3] = ya.side === 'right' ?
                rightpos : leftpos;
        }
        else if(showfreey) {
            ya._linepositions[subplot][3] = freeposy;
        }

        // translate all the extra stuff to have the
        // same origin as the plot area or axes
        var origin = 'translate(' + xa._offset + ',' + ya._offset + ')';
        var originx = origin;
        var originy = origin;
        if(showfreex) {
            originx = 'translate(' + xa._offset + ',' + gs.t + ')';
            toppos += ya._offset - gs.t;
            bottompos += ya._offset - gs.t;
        }
        if(showfreey) {
            originy = 'translate(' + gs.l + ',' + ya._offset + ')';
            leftpos += xa._offset - gs.l;
            rightpos += xa._offset - gs.l;
        }

        if(fullLayout._has('cartesian')) {
            plotinfo.xlines
                .attr('transform', originx)
                .attr('d', (
                    (showbottom ? (xpathPrefix + bottompos + xpathSuffix) : '') +
                    (showtop ? (xpathPrefix + toppos + xpathSuffix) : '') +
                    (showfreex ? (xpathPrefix + freeposx + xpathSuffix) : '')) ||
                    // so it doesn't barf with no lines shown
                    'M0,0')
                .style('stroke-width', xlw + 'px')
                .call(Color.stroke, xa.showline ?
                    xa.linecolor : 'rgba(0,0,0,0)');
            plotinfo.ylines
                .attr('transform', originy)
                .attr('d', (
                    (showleft ? ('M' + leftpos + ypathSuffix) : '') +
                    (showright ? ('M' + rightpos + ypathSuffix) : '') +
                    (showfreey ? ('M' + freeposy + ypathSuffix) : '')) ||
                    'M0,0')
                .attr('stroke-width', ylw + 'px')
                .call(Color.stroke, ya.showline ?
                    ya.linecolor : 'rgba(0,0,0,0)');
        }

        plotinfo.xaxislayer.attr('transform', originx);
        plotinfo.yaxislayer.attr('transform', originy);
        plotinfo.gridlayer.attr('transform', origin);
        plotinfo.zerolinelayer.attr('transform', origin);
        plotinfo.draglayer.attr('transform', origin);

        // mark free axes as displayed, so we don't draw them again
        if(showfreex) { freefinished.push(xa._id); }
        if(showfreey) { freefinished.push(ya._id); }
    });

    Plotly.Axes.makeClipPaths(gd);
    exports.drawMainTitle(gd);
    ModeBar.manage(gd);

    return gd._promises.length && Promise.all(gd._promises);
};

exports.drawMainTitle = function(gd) {
    var fullLayout = gd._fullLayout;

    Titles.draw(gd, 'gtitle', {
        propContainer: fullLayout,
        propName: 'title',
        dfltName: 'Plot',
        attributes: {
            x: fullLayout.width / 2,
            y: fullLayout._size.t / 2,
            'text-anchor': 'middle'
        }
    });
};

// First, see if we need to do arraysToCalcdata
// call it regardless of what change we made, in case
// supplyDefaults brought in an array that was already
// in gd.data but not in gd._fullData previously
exports.doTraceStyle = function(gd) {
    for(var i = 0; i < gd.calcdata.length; i++) {
        var cdi = gd.calcdata[i],
            _module = ((cdi[0] || {}).trace || {})._module || {},
            arraysToCalcdata = _module.arraysToCalcdata;

        if(arraysToCalcdata) arraysToCalcdata(cdi, cdi[0].trace);
    }

    Plots.style(gd);
    Registry.getComponentMethod('legend', 'draw')(gd);

    return Plots.previousPromises(gd);
};

exports.doColorBars = function(gd) {
    for(var i = 0; i < gd.calcdata.length; i++) {
        var cdi0 = gd.calcdata[i][0];

        if((cdi0.t || {}).cb) {
            var trace = cdi0.trace,
                cb = cdi0.t.cb;

            if(Registry.traceIs(trace, 'contour')) {
                cb.line({
                    width: trace.contours.showlines !== false ?
                        trace.line.width : 0,
                    dash: trace.line.dash,
                    color: trace.contours.coloring === 'line' ?
                        cb._opts.line.color : trace.line.color
                });
            }
            if(Registry.traceIs(trace, 'markerColorscale')) {
                cb.options(trace.marker.colorbar)();
            }
            else cb.options(trace.colorbar)();
        }
    }

    return Plots.previousPromises(gd);
};

// force plot() to redo the layout and replot with the modified layout
exports.layoutReplot = function(gd) {
    var layout = gd.layout;
    gd.layout = undefined;
    return Plotly.plot(gd, '', layout);
};

exports.doLegend = function(gd) {
    Registry.getComponentMethod('legend', 'draw')(gd);
    return Plots.previousPromises(gd);
};

exports.doTicksRelayout = function(gd) {
    Plotly.Axes.doTicks(gd, 'redraw');
    exports.drawMainTitle(gd);
    return Plots.previousPromises(gd);
};

exports.doModeBar = function(gd) {
    var fullLayout = gd._fullLayout;
    var subplotIds, subplotObj, i;

    ModeBar.manage(gd);
    initInteractions(gd);

    subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout[subplotIds[i]]._scene;
        subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode);
    }

    subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout._plots[subplotIds[i]]._scene2d;
        subplotObj.updateFx(fullLayout.dragmode);
    }

    subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox');
    for(i = 0; i < subplotIds.length; i++) {
        subplotObj = fullLayout[subplotIds[i]]._subplot;
        subplotObj.updateFx(fullLayout);
    }

    return Plots.previousPromises(gd);
};

exports.doCamera = function(gd) {
    var fullLayout = gd._fullLayout,
        sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');

    for(var i = 0; i < sceneIds.length; i++) {
        var sceneLayout = fullLayout[sceneIds[i]],
            scene = sceneLayout._scene;

        scene.setCamera(sceneLayout.camera);
    }
};
<|endoftext|>


<commit_before>exports.run = async (client, msg) => {
  const information = [
    "Komada is a 'plug-and-play' framework built on top of the Discord.js library.",
    "Most of the code is modularized, which allows developers to edit Komada to suit their needs.",
    "",
    "Some features of Komada include:",
    "• 🐇💨 Fast loading times with ES8 support (`async`/`await`)",
    "• 🎚🎛 Per-server settings that can be extended with your own fields",
    "• 💬 Customizable command system with automated usage parsing and the ability to reload commands and download new modules on-the-fly",
    "• 👀 \"Monitors\", which can watch messages and act on them, like a normal message event (for swear filters, spam protection, etc.)",
    "• ⛔ \"Inhibitors\", which can prevent commands from running based on a set of parameters (for permissions, blacklists, etc.)",
    "• 🗄 \"Providers\", which standardize and simplify usage of outside databases of your choosing (not yet documented)",
    "• ✅ \"Finalizers\", which run on messages after a successful command",
    "• ➕ \"Extendables\", which passively add properties or methods to existing Discord.js or Komada classes",
    "• 🇫 Internal \"Functions\", which allow you to use functions anywhere you have access to a client variable",
    "",
    "We hope to be a 100% customizable framework that can cater to all audiences. We do frequent updates and bugfixes when available.",
    "If you're interested in us, check us out at https://komada.js.org",
  ];
  return msg.sendMessage(information);
};

exports.conf = {
  enabled: true,
  runIn: ["text", "dm", "group"],
  aliases: ["details", "what"],
  permLevel: 0,
  botPerms: ["SEND_MESSAGES"],
  requiredFuncs: [],
  requiredSettings: [],
};

exports.help = {
  name: "info",
  description: "Provides some information about this bot.",
  usage: "",
  usageDelim: "",
};
<commit_msg>Changes to be consistent with Klasa (#383)<commit_after>exports.run = async (client, msg) => {
  const information = [
    "Komada is a 'plug-and-play' framework built on top of the Discord.js library.",
    "Most of the code is modularized, which allows developers to edit Komada to suit their needs.",
    "",
    "Some features of Komada include:",
    "• 🐇💨 Fast loading times with ES2017 support (`async`/`await`)",
    "• 🎚🎛 Per-server settings that can be extended with your own fields",
    "• 💬 Customizable command system with automated parameter resolving and the ability to reload commands and download new modules on-the-fly",
    "• 👀 \"Monitors\", which can watch messages and edits (for swear filters, spam protection, etc.)",
    "• ⛔ \"Inhibitors\", which can prevent commands from running based on any condition you wish to apply (for permissions, blacklists, etc.)",
    "• 🗄 \"Providers\", which simplify usage of any database of your choosing",
    "• ✅ \"Finalizers\", which run after successful commands (for logging, collecting stats, cleaning up responses, etc.)",
    "• ➕ \"Extendables\", which passively add methods, getters/setters, or static properties to existing Discord.js or Komada classes",
    "• 🇫 Internal \"Functions\", which allow you to use functions anywhere you have access to a client variable",
    "",
    "We hope to be a 100% customizable framework that can cater to all audiences. We do frequent updates and bugfixes when available.",
    "If you're interested in us, check us out at https://komada.js.org",
  ];
  return msg.sendMessage(information);
};

exports.conf = {
  enabled: true,
  runIn: ["text", "dm", "group"],
  aliases: ["details", "what"],
  permLevel: 0,
  botPerms: ["SEND_MESSAGES"],
  requiredFuncs: [],
  requiredSettings: [],
};

exports.help = {
  name: "info",
  description: "Provides some information about this bot.",
  usage: "",
  usageDelim: "",
};
<|endoftext|>


<commit_before>// Controller for both server and client.

'use strict';

var assign = require('es5-ext/object/assign')
  , db     = require('mano').db;

// Common controller.
module.exports = assign(exports, require('../user'));

exports['business-process/[0-9][a-z0-9]+/delete'] = {
	match: function (businessProcessId) {
		var businessProcess = db.BusinessProcess.getById(businessProcessId);
		if (!businessProcess) return false;
		if (businessProcess.isSubmitted) return false;
		this.businessProcess = businessProcess;
		return true;
	},
	submit: function () {
		db.objects.delete(this.businessProcess);
	}
};

exports['business-process/[0-9][a-z0-9]+'] = {
	match: function (businessProcessId) {
		this.businessProcess = db.BusinessProcess.getById(businessProcessId);
		return Boolean(this.businessProcess);
	},
	submit: function () {
		this.user.currentBusinessProcess = this.businessProcess;
	}
};
<commit_msg>#931 added missing validation<commit_after>// Controller for both server and client.

'use strict';

var assign = require('es5-ext/object/assign')
  , db     = require('mano').db;

// Common controller.
module.exports = assign(exports, require('../user'));

exports['business-process/[0-9][a-z0-9]+/delete'] = {
	match: function (businessProcessId) {
		var businessProcess = db.BusinessProcess.getById(businessProcessId);
		if (!businessProcess) return false;
		if (businessProcess.isSubmitted) return false;
		this.businessProcess = businessProcess;
		return true;
	},
	submit: function () {
		db.objects.delete(this.businessProcess);
	}
};

exports['business-process/[0-9][a-z0-9]+'] = {
	match: function (businessProcessId) {
		this.businessProcess = db.BusinessProcess.getById(businessProcessId);
		if (!this.businessProcess) return false;
		if (!this.businessProcess.isFromEregistrations) return false;
		return this.user.businessProcesses.has(this.businessProcess);
	},
	submit: function () {
		this.user.currentBusinessProcess = this.businessProcess;
	}
};
<|endoftext|>


<commit_before>window.eg = window.eg || {};
(function(ns) {
    ns.Class = function(oDef) {
		var typeClass = function typeClass() {
			if (typeof oDef.construct == "function") {
				oDef.construct.apply(this, arguments);
			}
		};

		typeClass.prototype = oDef;
		typeClass.prototype.constructor = typeClass;
		return typeClass;
	};

	ns.Class.extend = function(oSuperClass, oDef) {
		var extendClass = function extendClass() {
			// Call a parent constructor
			oSuperClass.apply(this, arguments);

			// Call a child constructor
			if (typeof oDef.construct == "function") {
				oDef.construct.apply(this, arguments);
			}
		};

		var ExtProto = function() {};
		ExtProto.prototype = oSuperClass.prototype;
		//extendClass.$super = oSuperClass.prototype; //'super' is supported not yet.

		var oExtProto = new ExtProto();
		for (var i in oDef) {
			if (oDef.hasOwnProperty(i)) {
				oExtProto[i] = oDef[i];
			}
		}
		oExtProto.constructor = extendClass;
		extendClass.prototype = oExtProto;

		return extendClass;
	}
})(eg);<commit_msg>check js lint<commit_after>window.eg = window.eg || {};
(function(ns) {
    ns.Class = function(oDef) {
		var typeClass = function typeClass() {
			if (typeof oDef.construct === "function") {
				oDef.construct.apply(this, arguments);
			}
		};

		typeClass.prototype = oDef;
		typeClass.prototype.constructor = typeClass;
		return typeClass;
	};

	ns.Class.extend = function(oSuperClass, oDef) {
		var extendClass = function extendClass() {
			// Call a parent constructor
			oSuperClass.apply(this, arguments);

			// Call a child constructor
			if (typeof oDef.construct === "function") {
				oDef.construct.apply(this, arguments);
			}
		};

		var ExtProto = function() {};
		ExtProto.prototype = oSuperClass.prototype;
		//extendClass.$super = oSuperClass.prototype; //'super' is supported not yet.

		var oExtProto = new ExtProto();
		for (var i in oDef) {
			if (oDef.hasOwnProperty(i)) {
				oExtProto[i] = oDef[i];
			}
		}
		oExtProto.constructor = extendClass;
		extendClass.prototype = oExtProto;

		return extendClass;
	};
})(eg);<|endoftext|>


<commit_before>"use strict";

var ejs = require("ejs");

module.exports = function(options, imports, register) {

    imports["connect.render"].registerEngine("ejs", createView);

    ejs.filters.JSONToJS = function(obj, indent) {
        return JSON.stringify(obj, null, indent).replace(/<\/?script|[\u2028\u2029]/ig, function(a) {
            var h =  a.charCodeAt(0).toString(16);
            return (h.length == 2 ? "\\x" : "\\u") + h + a.substr(1);
        });
    };

    var helper = {
        timeSpan: function(ts) {
            var sec = 1000;
            var min = 60 * sec;
            var hour = 60 * min;

            return pad(~~(ts / hour)) + ":" + pad(~~((ts % hour) / min)) + ":" + pad(~~((ts % min) / sec));

            function pad(d) {
                if (d < 10)
                    return "0" + d;
                else
                    return d;
            }
        },
        timeSpanSince: function(ts) {
            return helper.timeSpan(Date.now() - ts);
        }
    };

    function createView(path, callback) {
        return callback(null, function(res, options, callback) {
            options.helper = helper;
            ejs.renderFile(path, options, function(err, template) {
                if (err) return callback(err);

                callback(null, {
                    headers: {"Content-Type": "text/html"},
                    body: template
                });
            });
        });
    }

    register(null, {
        "connect.render.ejs": {
            addHelper: function(name, helper) {
                helper[name] = helper;
            }
        }
    });
};<commit_msg>escape invalid unicode sequences in JSONToJs<commit_after>"use strict";

var ejs = require("ejs");

module.exports = function(options, imports, register) {

    imports["connect.render"].registerEngine("ejs", createView);

    ejs.filters.JSONToJS = function(obj, indent) {
        return JSON.stringify(obj, null, indent).replace(/<\/?script|[\u2028\u2029\ud800-\uDFFF\ufeff]/ig, function(a) {
            var h =  a.charCodeAt(0).toString(16);
            return (h.length == 2 ? "\\x" : "\\u") + h + a.substr(1);
        });
    };

    var helper = {
        timeSpan: function(ts) {
            var sec = 1000;
            var min = 60 * sec;
            var hour = 60 * min;

            return pad(~~(ts / hour)) + ":" + pad(~~((ts % hour) / min)) + ":" + pad(~~((ts % min) / sec));

            function pad(d) {
                if (d < 10)
                    return "0" + d;
                else
                    return d;
            }
        },
        timeSpanSince: function(ts) {
            return helper.timeSpan(Date.now() - ts);
        }
    };

    function createView(path, callback) {
        return callback(null, function(res, options, callback) {
            options.helper = helper;
            ejs.renderFile(path, options, function(err, template) {
                if (err) return callback(err);

                callback(null, {
                    headers: {"Content-Type": "text/html"},
                    body: template
                });
            });
        });
    }

    register(null, {
        "connect.render.ejs": {
            addHelper: function(name, helper) {
                helper[name] = helper;
            }
        }
    });
};<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options', function() {
  const OptionsPage = options.OptionsPage;
  const ArrayDataModel = cr.ui.ArrayDataModel;

  //
  // BrowserOptions class
  // Encapsulated handling of browser options page.
  //
  function BrowserOptions() {
    OptionsPage.call(this, 'browser',
                     templateData.browserPageTabTitle,
                     'browserPage');
  }

  cr.addSingletonGetter(BrowserOptions);

  BrowserOptions.prototype = {
    // Inherit BrowserOptions from OptionsPage.
    __proto__: options.OptionsPage.prototype,

    startup_pages_pref_: {
      'name': 'session.urls_to_restore_on_startup',
      'managed': false
    },

    /**
     * At autocomplete list that can be attached to a text field during editing.
     * @type {HTMLElement}
     * @private
     */
    autocompleteList_: null,

    // The cached value of the instant.confirm_dialog_shown preference.
    instantConfirmDialogShown_: false,

    /**
     * Initialize BrowserOptions page.
     */
    initializePage: function() {
      // Call base class implementation to start preference initialization.
      OptionsPage.prototype.initializePage.call(this);

      // Wire up controls.
      $('startupUseCurrentButton').onclick = function(event) {
        chrome.send('setStartupPagesToCurrentPages');
      };
      $('defaultSearchManageEnginesButton').onclick = function(event) {
        OptionsPage.navigateToPage('searchEngines');
        chrome.send('coreOptionsUserMetricsAction',
            ['Options_ManageSearchEngines']);
      };
      $('defaultSearchEngine').onchange = this.setDefaultSearchEngine_;

      var self = this;
      $('instantEnabledCheckbox').customChangeHandler = function(event) {
        if (this.checked) {
          if (self.instantConfirmDialogShown_)
            chrome.send('enableInstant');
          else
            OptionsPage.navigateToPage('instantConfirm');
        } else {
          chrome.send('disableInstant');
        }
        return true;
      };

      $('instantFieldTrialCheckbox').addEventListener('change',
          function(event) {
            this.checked = true;
            chrome.send('disableInstant');
          });

      Preferences.getInstance().addEventListener('instant.confirm_dialog_shown',
          this.onInstantConfirmDialogShownChanged_.bind(this));

      Preferences.getInstance().addEventListener('instant.enabled',
          this.onInstantEnabledChanged_.bind(this));

      Preferences.getInstance().addEventListener(
          $('homepageUseNTPButton').pref,
          this.onHomepageUseNTPChanged_);
      var homepageField = $('homepageURL');
      homepageField.addEventListener('focus', function(event) {
        self.autocompleteList_.attachToInput(homepageField);
      });
      homepageField.addEventListener('blur', function(event) {
        self.autocompleteList_.detach();
      });
      homepageField.addEventListener('keydown', function(event) {
        // Remove focus when the user hits enter since people expect feedback
        // indicating that they are done editing.
        if (event.keyIdentifier == 'Enter')
          homepageField.blur();
      });

      // Text fields may change widths when the window changes size, so make
      // sure the suggestion list stays in sync.
      window.addEventListener('resize', function() {
        self.autocompleteList_.syncWidthToInput();
      });

      // Ensure that changes are committed when closing the page.
      window.addEventListener('unload', function() {
        if (document.activeElement == homepageField)
          homepageField.blur();
      });

      if (!cr.isChromeOS) {
        $('defaultBrowserUseAsDefaultButton').onclick = function(event) {
          chrome.send('becomeDefaultBrowser');
        };
      }

      var startupPagesList = $('startupPagesList');
      options.browser_options.StartupPageList.decorate(startupPagesList);
      startupPagesList.autoExpands = true;

      // Check if we are in the guest mode.
      if (cr.commandLine.options['--bwsi']) {
        // Hide the startup section.
        $('startupSection').hidden = true;
      } else {
        // Initialize control enabled states.
        Preferences.getInstance().addEventListener('session.restore_on_startup',
            this.updateCustomStartupPageControlStates_.bind(this));
        Preferences.getInstance().addEventListener(
            this.startup_pages_pref_.name,
            this.handleStartupPageListChange_.bind(this));

        this.updateCustomStartupPageControlStates_();
      }

      var suggestionList = new options.AutocompleteList();
      suggestionList.autoExpands = true;
      suggestionList.suggestionUpdateRequestCallback =
          this.requestAutocompleteSuggestions_.bind(this);
      $('main-content').appendChild(suggestionList);
      this.autocompleteList_ = suggestionList;
      startupPagesList.autocompleteList = suggestionList;
    },

    /**
     * Called when the value of the instant.confirm_dialog_shown preference
     * changes. Cache this value.
     * @param {Event} event Change event.
     * @private
     */
    onInstantConfirmDialogShownChanged_: function(event) {
      this.instantConfirmDialogShown_ = event.value['value'];
    },

    /**
     * Called when the value of the instant.enabled preference changes. Request
     * the state of the Instant field trial experiment.
     * @param {Event} event Change event.
     * @private
     */
    onInstantEnabledChanged_: function(event) {
      chrome.send('getInstantFieldTrialStatus');
    },

    /**
     * Called to set the Instant field trial status.
     * @param {boolean} enabled If true, the experiment is enabled.
     * @private
     */
    setInstantFieldTrialStatus_: function(enabled) {
      $('instantEnabledCheckbox').hidden = enabled;
      $('instantFieldTrialCheckbox').hidden = !enabled;
      $('instantLabel').htmlFor = enabled ? 'instantFieldTrialCheckbox'
                                          : 'instantEnabledCheckbox';
    },

    /**
     * Called when the value of the homepage-use-NTP pref changes.
     * Updates the disabled state of the homepage text field.
     * Notice that the text field can be disabled for other reasons too
     * (it can be managed by policy, for instance).
     * @param {Event} event Change event.
     * @private
     */
    onHomepageUseNTPChanged_: function(event) {
      var homepageField = $('homepageURL');
      var homepageUseURLButton = $('homepageUseURLButton');
      homepageField.setDisabled('radioNotSelected',
                                !homepageUseURLButton.checked);
    },

    /**
     * Update the Default Browsers section based on the current state.
     * @param {string} statusString Description of the current default state.
     * @param {boolean} isDefault Whether or not the browser is currently
     *     default.
     * @param {boolean} canBeDefault Whether or not the browser can be default.
     * @private
     */
    updateDefaultBrowserState_: function(statusString, isDefault,
                                         canBeDefault) {
      var label = $('defaultBrowserState');
      label.textContent = statusString;

      $('defaultBrowserUseAsDefaultButton').disabled = !canBeDefault ||
                                                       isDefault;
    },

    /**
     * Clears the search engine popup.
     * @private
     */
    clearSearchEngines_: function() {
      $('defaultSearchEngine').textContent = '';
    },

    /**
     * Updates the search engine popup with the given entries.
     * @param {Array} engines List of available search engines.
     * @param {number} defaultValue The value of the current default engine.
     * @param {boolean} defaultManaged Whether the default search provider is
     *     managed. If true, the default search provider can't be changed.
     */
    updateSearchEngines_: function(engines, defaultValue, defaultManaged) {
      this.clearSearchEngines_();
      engineSelect = $('defaultSearchEngine');
      engineSelect.disabled = defaultManaged;
      engineCount = engines.length;
      var defaultIndex = -1;
      for (var i = 0; i < engineCount; i++) {
        var engine = engines[i];
        var option = new Option(engine['name'], engine['index']);
        if (defaultValue == option.value)
          defaultIndex = i;
        engineSelect.appendChild(option);
      }
      if (defaultIndex >= 0)
        engineSelect.selectedIndex = defaultIndex;
    },

    /**
     * Returns true if the custom startup page control block should
     * be enabled.
     * @returns {boolean} Whether the startup page controls should be
     *     enabled.
     */
    shouldEnableCustomStartupPageControls: function(pages) {
      return $('startupShowPagesButton').checked &&
          !this.startup_pages_pref_.controlledBy;
    },

    /**
     * Updates the startup pages list with the given entries.
     * @param {Array} pages List of startup pages.
     * @private
     */
    updateStartupPages_: function(pages) {
      var model = new ArrayDataModel(pages);
      // Add a "new page" row.
      model.push({
        'modelIndex': '-1'
      });
      $('startupPagesList').dataModel = model;
    },

    /**
     * Sets the enabled state of the custom startup page list controls
     * based on the current startup radio button selection.
     * @private
     */
    updateCustomStartupPageControlStates_: function() {
      var disable = !this.shouldEnableCustomStartupPageControls();
      var startupPagesList = $('startupPagesList');
      startupPagesList.disabled = disable;
      // Explicitly set disabled state for input text elements.
      var inputs = startupPagesList.querySelectorAll("input[type='text']");
      for (var i = 0; i < inputs.length; i++)
        inputs[i].disabled = disable;
      $('startupUseCurrentButton').disabled = disable;
    },

    /**
     * Handle change events of the preference
     * 'session.urls_to_restore_on_startup'.
     * @param {event} preference changed event.
     * @private
     */
    handleStartupPageListChange_: function(event) {
      this.startup_pages_pref_.controlledBy = event.value['controlledBy'];
      this.updateCustomStartupPageControlStates_();
    },

    /**
     * Set the default search engine based on the popup selection.
     */
    setDefaultSearchEngine_: function() {
      var engineSelect = $('defaultSearchEngine');
      var selectedIndex = engineSelect.selectedIndex;
      if (selectedIndex >= 0) {
        var selection = engineSelect.options[selectedIndex];
        chrome.send('setDefaultSearchEngine', [String(selection.value)]);
      }
    },

    /**
     * Sends an asynchronous request for new autocompletion suggestions for the
     * the given query. When new suggestions are available, the C++ handler will
     * call updateAutocompleteSuggestions_.
     * @param {string} query List of autocomplete suggestions.
     * @private
     */
    requestAutocompleteSuggestions_: function(query) {
      chrome.send('requestAutocompleteSuggestions', [query]);
    },

    /**
     * Updates the autocomplete suggestion list with the given entries.
     * @param {Array} pages List of autocomplete suggestions.
     * @private
     */
    updateAutocompleteSuggestions_: function(suggestions) {
      var list = this.autocompleteList_;
      // If the trigger for this update was a value being selected from the
      // current list, do nothing.
      if (list.targetInput && list.selectedItem &&
          list.selectedItem['url'] == list.targetInput.value)
        return;
      list.suggestions = suggestions;
    },
  };

  BrowserOptions.updateDefaultBrowserState = function(statusString, isDefault,
                                                      canBeDefault) {
    if (!cr.isChromeOS) {
      BrowserOptions.getInstance().updateDefaultBrowserState_(statusString,
                                                              isDefault,
                                                              canBeDefault);
    }
  };

  BrowserOptions.updateSearchEngines = function(engines, defaultValue,
                                                defaultManaged) {
    BrowserOptions.getInstance().updateSearchEngines_(engines, defaultValue,
                                                      defaultManaged);
  };

  BrowserOptions.updateStartupPages = function(pages) {
    BrowserOptions.getInstance().updateStartupPages_(pages);
  };

  BrowserOptions.updateAutocompleteSuggestions = function(suggestions) {
    BrowserOptions.getInstance().updateAutocompleteSuggestions_(suggestions);
  };

  BrowserOptions.setInstantFieldTrialStatus = function(enabled) {
    BrowserOptions.getInstance().setInstantFieldTrialStatus_(enabled);
  };

  // Export
  return {
    BrowserOptions: BrowserOptions
  };

});
<commit_msg>options: make default page list focusability match disable state<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

cr.define('options', function() {
  const OptionsPage = options.OptionsPage;
  const ArrayDataModel = cr.ui.ArrayDataModel;

  //
  // BrowserOptions class
  // Encapsulated handling of browser options page.
  //
  function BrowserOptions() {
    OptionsPage.call(this, 'browser',
                     templateData.browserPageTabTitle,
                     'browserPage');
  }

  cr.addSingletonGetter(BrowserOptions);

  BrowserOptions.prototype = {
    // Inherit BrowserOptions from OptionsPage.
    __proto__: options.OptionsPage.prototype,

    startup_pages_pref_: {
      'name': 'session.urls_to_restore_on_startup',
      'managed': false
    },

    /**
     * At autocomplete list that can be attached to a text field during editing.
     * @type {HTMLElement}
     * @private
     */
    autocompleteList_: null,

    // The cached value of the instant.confirm_dialog_shown preference.
    instantConfirmDialogShown_: false,

    /**
     * Initialize BrowserOptions page.
     */
    initializePage: function() {
      // Call base class implementation to start preference initialization.
      OptionsPage.prototype.initializePage.call(this);

      // Wire up controls.
      $('startupUseCurrentButton').onclick = function(event) {
        chrome.send('setStartupPagesToCurrentPages');
      };
      $('defaultSearchManageEnginesButton').onclick = function(event) {
        OptionsPage.navigateToPage('searchEngines');
        chrome.send('coreOptionsUserMetricsAction',
            ['Options_ManageSearchEngines']);
      };
      $('defaultSearchEngine').onchange = this.setDefaultSearchEngine_;

      var self = this;
      $('instantEnabledCheckbox').customChangeHandler = function(event) {
        if (this.checked) {
          if (self.instantConfirmDialogShown_)
            chrome.send('enableInstant');
          else
            OptionsPage.navigateToPage('instantConfirm');
        } else {
          chrome.send('disableInstant');
        }
        return true;
      };

      $('instantFieldTrialCheckbox').addEventListener('change',
          function(event) {
            this.checked = true;
            chrome.send('disableInstant');
          });

      Preferences.getInstance().addEventListener('instant.confirm_dialog_shown',
          this.onInstantConfirmDialogShownChanged_.bind(this));

      Preferences.getInstance().addEventListener('instant.enabled',
          this.onInstantEnabledChanged_.bind(this));

      Preferences.getInstance().addEventListener(
          $('homepageUseNTPButton').pref,
          this.onHomepageUseNTPChanged_);
      var homepageField = $('homepageURL');
      homepageField.addEventListener('focus', function(event) {
        self.autocompleteList_.attachToInput(homepageField);
      });
      homepageField.addEventListener('blur', function(event) {
        self.autocompleteList_.detach();
      });
      homepageField.addEventListener('keydown', function(event) {
        // Remove focus when the user hits enter since people expect feedback
        // indicating that they are done editing.
        if (event.keyIdentifier == 'Enter')
          homepageField.blur();
      });

      // Text fields may change widths when the window changes size, so make
      // sure the suggestion list stays in sync.
      window.addEventListener('resize', function() {
        self.autocompleteList_.syncWidthToInput();
      });

      // Ensure that changes are committed when closing the page.
      window.addEventListener('unload', function() {
        if (document.activeElement == homepageField)
          homepageField.blur();
      });

      if (!cr.isChromeOS) {
        $('defaultBrowserUseAsDefaultButton').onclick = function(event) {
          chrome.send('becomeDefaultBrowser');
        };
      }

      var startupPagesList = $('startupPagesList');
      options.browser_options.StartupPageList.decorate(startupPagesList);
      startupPagesList.autoExpands = true;

      // Check if we are in the guest mode.
      if (cr.commandLine.options['--bwsi']) {
        // Hide the startup section.
        $('startupSection').hidden = true;
      } else {
        // Initialize control enabled states.
        Preferences.getInstance().addEventListener('session.restore_on_startup',
            this.updateCustomStartupPageControlStates_.bind(this));
        Preferences.getInstance().addEventListener(
            this.startup_pages_pref_.name,
            this.handleStartupPageListChange_.bind(this));

        this.updateCustomStartupPageControlStates_();
      }

      var suggestionList = new options.AutocompleteList();
      suggestionList.autoExpands = true;
      suggestionList.suggestionUpdateRequestCallback =
          this.requestAutocompleteSuggestions_.bind(this);
      $('main-content').appendChild(suggestionList);
      this.autocompleteList_ = suggestionList;
      startupPagesList.autocompleteList = suggestionList;
    },

    /**
     * Called when the value of the instant.confirm_dialog_shown preference
     * changes. Cache this value.
     * @param {Event} event Change event.
     * @private
     */
    onInstantConfirmDialogShownChanged_: function(event) {
      this.instantConfirmDialogShown_ = event.value['value'];
    },

    /**
     * Called when the value of the instant.enabled preference changes. Request
     * the state of the Instant field trial experiment.
     * @param {Event} event Change event.
     * @private
     */
    onInstantEnabledChanged_: function(event) {
      chrome.send('getInstantFieldTrialStatus');
    },

    /**
     * Called to set the Instant field trial status.
     * @param {boolean} enabled If true, the experiment is enabled.
     * @private
     */
    setInstantFieldTrialStatus_: function(enabled) {
      $('instantEnabledCheckbox').hidden = enabled;
      $('instantFieldTrialCheckbox').hidden = !enabled;
      $('instantLabel').htmlFor = enabled ? 'instantFieldTrialCheckbox'
                                          : 'instantEnabledCheckbox';
    },

    /**
     * Called when the value of the homepage-use-NTP pref changes.
     * Updates the disabled state of the homepage text field.
     * Notice that the text field can be disabled for other reasons too
     * (it can be managed by policy, for instance).
     * @param {Event} event Change event.
     * @private
     */
    onHomepageUseNTPChanged_: function(event) {
      var homepageField = $('homepageURL');
      var homepageUseURLButton = $('homepageUseURLButton');
      homepageField.setDisabled('radioNotSelected',
                                !homepageUseURLButton.checked);
    },

    /**
     * Update the Default Browsers section based on the current state.
     * @param {string} statusString Description of the current default state.
     * @param {boolean} isDefault Whether or not the browser is currently
     *     default.
     * @param {boolean} canBeDefault Whether or not the browser can be default.
     * @private
     */
    updateDefaultBrowserState_: function(statusString, isDefault,
                                         canBeDefault) {
      var label = $('defaultBrowserState');
      label.textContent = statusString;

      $('defaultBrowserUseAsDefaultButton').disabled = !canBeDefault ||
                                                       isDefault;
    },

    /**
     * Clears the search engine popup.
     * @private
     */
    clearSearchEngines_: function() {
      $('defaultSearchEngine').textContent = '';
    },

    /**
     * Updates the search engine popup with the given entries.
     * @param {Array} engines List of available search engines.
     * @param {number} defaultValue The value of the current default engine.
     * @param {boolean} defaultManaged Whether the default search provider is
     *     managed. If true, the default search provider can't be changed.
     */
    updateSearchEngines_: function(engines, defaultValue, defaultManaged) {
      this.clearSearchEngines_();
      engineSelect = $('defaultSearchEngine');
      engineSelect.disabled = defaultManaged;
      engineCount = engines.length;
      var defaultIndex = -1;
      for (var i = 0; i < engineCount; i++) {
        var engine = engines[i];
        var option = new Option(engine['name'], engine['index']);
        if (defaultValue == option.value)
          defaultIndex = i;
        engineSelect.appendChild(option);
      }
      if (defaultIndex >= 0)
        engineSelect.selectedIndex = defaultIndex;
    },

    /**
     * Returns true if the custom startup page control block should
     * be enabled.
     * @returns {boolean} Whether the startup page controls should be
     *     enabled.
     */
    shouldEnableCustomStartupPageControls: function(pages) {
      return $('startupShowPagesButton').checked &&
          !this.startup_pages_pref_.controlledBy;
    },

    /**
     * Updates the startup pages list with the given entries.
     * @param {Array} pages List of startup pages.
     * @private
     */
    updateStartupPages_: function(pages) {
      var model = new ArrayDataModel(pages);
      // Add a "new page" row.
      model.push({
        'modelIndex': '-1'
      });
      $('startupPagesList').dataModel = model;
    },

    /**
     * Sets the enabled state of the custom startup page list controls
     * based on the current startup radio button selection.
     * @private
     */
    updateCustomStartupPageControlStates_: function() {
      var disable = !this.shouldEnableCustomStartupPageControls();
      var startupPagesList = $('startupPagesList');
      startupPagesList.disabled = disable;
      startupPagesList.setAttribute('tabindex', disable ? -1 : 0);
      // Explicitly set disabled state for input text elements.
      var inputs = startupPagesList.querySelectorAll("input[type='text']");
      for (var i = 0; i < inputs.length; i++)
        inputs[i].disabled = disable;
      $('startupUseCurrentButton').disabled = disable;
    },

    /**
     * Handle change events of the preference
     * 'session.urls_to_restore_on_startup'.
     * @param {event} preference changed event.
     * @private
     */
    handleStartupPageListChange_: function(event) {
      this.startup_pages_pref_.controlledBy = event.value['controlledBy'];
      this.updateCustomStartupPageControlStates_();
    },

    /**
     * Set the default search engine based on the popup selection.
     */
    setDefaultSearchEngine_: function() {
      var engineSelect = $('defaultSearchEngine');
      var selectedIndex = engineSelect.selectedIndex;
      if (selectedIndex >= 0) {
        var selection = engineSelect.options[selectedIndex];
        chrome.send('setDefaultSearchEngine', [String(selection.value)]);
      }
    },

    /**
     * Sends an asynchronous request for new autocompletion suggestions for the
     * the given query. When new suggestions are available, the C++ handler will
     * call updateAutocompleteSuggestions_.
     * @param {string} query List of autocomplete suggestions.
     * @private
     */
    requestAutocompleteSuggestions_: function(query) {
      chrome.send('requestAutocompleteSuggestions', [query]);
    },

    /**
     * Updates the autocomplete suggestion list with the given entries.
     * @param {Array} pages List of autocomplete suggestions.
     * @private
     */
    updateAutocompleteSuggestions_: function(suggestions) {
      var list = this.autocompleteList_;
      // If the trigger for this update was a value being selected from the
      // current list, do nothing.
      if (list.targetInput && list.selectedItem &&
          list.selectedItem['url'] == list.targetInput.value)
        return;
      list.suggestions = suggestions;
    },
  };

  BrowserOptions.updateDefaultBrowserState = function(statusString, isDefault,
                                                      canBeDefault) {
    if (!cr.isChromeOS) {
      BrowserOptions.getInstance().updateDefaultBrowserState_(statusString,
                                                              isDefault,
                                                              canBeDefault);
    }
  };

  BrowserOptions.updateSearchEngines = function(engines, defaultValue,
                                                defaultManaged) {
    BrowserOptions.getInstance().updateSearchEngines_(engines, defaultValue,
                                                      defaultManaged);
  };

  BrowserOptions.updateStartupPages = function(pages) {
    BrowserOptions.getInstance().updateStartupPages_(pages);
  };

  BrowserOptions.updateAutocompleteSuggestions = function(suggestions) {
    BrowserOptions.getInstance().updateAutocompleteSuggestions_(suggestions);
  };

  BrowserOptions.setInstantFieldTrialStatus = function(enabled) {
    BrowserOptions.getInstance().setInstantFieldTrialStatus_(enabled);
  };

  // Export
  return {
    BrowserOptions: BrowserOptions
  };

});
<|endoftext|>