<commit_before>/**
 * `modules/analytics-4` data store: properties.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME, PROPERTY_CREATE } from './constants';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertySelection } from '../utils/validation';

const fetchGetPropertiesStore = createFetchStore( {
	baseName: 'getProperties',
	controlCallback( { accountID } ) {
		return API.get( 'modules', 'analytics-4', 'properties', { accountID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, properties, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: properties,
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const fetchCreatePropertyStore = createFetchStore( {
	baseName: 'createProperty',
	controlCallback( { accountID } ) {
		return API.set( 'modules', 'analytics-4', 'create-property', { accountID } );
	},
	reducerCallback( state, property, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: [
					...( state.properties[ accountID ] || [] ),
					property,
				],
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const baseInitialState = {
	properties: {},
};

const baseActions = {
	/**
	 * Creates a new GA4 property.
	 *
	 * @since n.e.x.t
	 *
	 * @param {string} accountID Analytics account ID.
	 * @return {Object} Object with `response` and `error`.
	 */
	createProperty( accountID ) {
		invariant( accountID, 'accountID is required.' );

		return ( function*() {
			const { response, error } = yield fetchCreatePropertyStore.actions.fetchCreateProperty( accountID );
			return { response, error };
		}() );
	},

	/**
	 * Sets the given property and related fields in the store.
	 *
	 * @since n.e.x.t
	 *
	 * @param {string} propertyID GA4 property ID.
	 * @return {Object} A Generator function.
	 */
	selectProperty( propertyID ) {
		invariant( isValidPropertySelection( propertyID ), 'A valid propertyID selection is required.' );

		return ( function* () {
			const registry = yield Data.commonActions.getRegistry();

			registry.dispatch( STORE_NAME ).setPropertyID( propertyID );
			registry.dispatch( STORE_NAME ).setWebDataStreamID( '' );
			registry.dispatch( STORE_NAME ).setMeasurementID( '' );

			if ( PROPERTY_CREATE === propertyID ) {
				return;
			}

			yield registry.dispatch( STORE_NAME ).waitForWebDataStreams( propertyID );

			const webdatastream = registry.select( STORE_NAME ).getMatchingWebDataStream( propertyID );
			if ( webdatastream ) {
				registry.dispatch( STORE_NAME ).setWebDataStreamID( webdatastream.name.split( '/' ).pop() );
				registry.dispatch( STORE_NAME ).setMeasurementID( webdatastream.measurementId ); // eslint-disable-line sitekit/acronym-case
			}
		}() );
	},
};

const baseControls = {
};

const baseReducer = ( state, { type } ) => {
	switch ( type ) {
		default: {
			return state;
		}
	}
};

const baseResolvers = {
	*getProperties( accountID ) {
		const registry = yield Data.commonActions.getRegistry();
		// Only fetch properties if there are none in the store for the given account.
		const properties = registry.select( STORE_NAME ).getProperties( accountID );
		if ( properties === undefined ) {
			yield fetchGetPropertiesStore.actions.fetchGetProperties( accountID );
		}
	},
};

const baseSelectors = {
	/**
	 * Gets all GA4 properties this account can access.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} state     Data store's state.
	 * @param {string} accountID The GA4 Account ID to fetch properties for.
	 * @return {(Array.<Object>|undefined)} An array of GA4 properties; `undefined` if not loaded.
	 */
	getProperties( state, accountID ) {
		return state.properties[ accountID ];
	},
};

const store = Data.combineStores(
	fetchGetPropertiesStore,
	fetchCreatePropertyStore,
	{
		initialState: baseInitialState,
		actions: baseActions,
		controls: baseControls,
		reducer: baseReducer,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<commit_msg>Yield raw action instead of dispatch.<commit_after>/**
 * `modules/analytics-4` data store: properties.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME, PROPERTY_CREATE } from './constants';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertySelection } from '../utils/validation';
import { actions as webDataStreamActions } from './webdatastreams';

const fetchGetPropertiesStore = createFetchStore( {
	baseName: 'getProperties',
	controlCallback( { accountID } ) {
		return API.get( 'modules', 'analytics-4', 'properties', { accountID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, properties, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: properties,
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const fetchCreatePropertyStore = createFetchStore( {
	baseName: 'createProperty',
	controlCallback( { accountID } ) {
		return API.set( 'modules', 'analytics-4', 'create-property', { accountID } );
	},
	reducerCallback( state, property, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: [
					...( state.properties[ accountID ] || [] ),
					property,
				],
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const baseInitialState = {
	properties: {},
};

const baseActions = {
	/**
	 * Creates a new GA4 property.
	 *
	 * @since n.e.x.t
	 *
	 * @param {string} accountID Analytics account ID.
	 * @return {Object} Object with `response` and `error`.
	 */
	createProperty( accountID ) {
		invariant( accountID, 'accountID is required.' );

		return ( function*() {
			const { response, error } = yield fetchCreatePropertyStore.actions.fetchCreateProperty( accountID );
			return { response, error };
		}() );
	},

	/**
	 * Sets the given property and related fields in the store.
	 *
	 * @since n.e.x.t
	 *
	 * @param {string} propertyID GA4 property ID.
	 * @return {Object} A Generator function.
	 */
	selectProperty( propertyID ) {
		invariant( isValidPropertySelection( propertyID ), 'A valid propertyID selection is required.' );

		return ( function* () {
			const registry = yield Data.commonActions.getRegistry();

			registry.dispatch( STORE_NAME ).setPropertyID( propertyID );
			registry.dispatch( STORE_NAME ).setWebDataStreamID( '' );
			registry.dispatch( STORE_NAME ).setMeasurementID( '' );

			if ( PROPERTY_CREATE === propertyID ) {
				return;
			}

			yield webDataStreamActions.waitForWebDataStreams( propertyID );

			const webdatastream = registry.select( STORE_NAME ).getMatchingWebDataStream( propertyID );
			if ( webdatastream ) {
				registry.dispatch( STORE_NAME ).setWebDataStreamID( webdatastream.name.split( '/' ).pop() );
				registry.dispatch( STORE_NAME ).setMeasurementID( webdatastream.measurementId ); // eslint-disable-line sitekit/acronym-case
			}
		}() );
	},
};

const baseControls = {
};

const baseReducer = ( state, { type } ) => {
	switch ( type ) {
		default: {
			return state;
		}
	}
};

const baseResolvers = {
	*getProperties( accountID ) {
		const registry = yield Data.commonActions.getRegistry();
		// Only fetch properties if there are none in the store for the given account.
		const properties = registry.select( STORE_NAME ).getProperties( accountID );
		if ( properties === undefined ) {
			yield fetchGetPropertiesStore.actions.fetchGetProperties( accountID );
		}
	},
};

const baseSelectors = {
	/**
	 * Gets all GA4 properties this account can access.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} state     Data store's state.
	 * @param {string} accountID The GA4 Account ID to fetch properties for.
	 * @return {(Array.<Object>|undefined)} An array of GA4 properties; `undefined` if not loaded.
	 */
	getProperties( state, accountID ) {
		return state.properties[ accountID ];
	},
};

const store = Data.combineStores(
	fetchGetPropertiesStore,
	fetchCreatePropertyStore,
	{
		initialState: baseInitialState,
		actions: baseActions,
		controls: baseControls,
		reducer: baseReducer,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<|endoftext|>


<commit_before>/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2016 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function() {

"use strict";

var ui = angular.module('axelor.ui');

function getStylePopup(element, styles) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(styles, function(format, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                                $(element).wysiwyg('shell').format(format).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getFontNamePopup(element, fonts) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(fonts, function(font, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                                $(element).wysiwyg('shell').fontName(font).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getFontSizePopup(element, sizes) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(sizes, function(size, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                            	$(element).focus();
	                            	$(element).wysiwyg('shell').fontSize(size).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getButtons(scope, element) {

	var lite = scope.field.lite;

	return {
		style: lite ? false : {
			title: _t('Style'),
			image: '\uf1dd',
			popup: getStylePopup(element, {
				'
' 			: _t('Normal'),
				'
' 		: '
' + _t('Formatted') + '
',
				'
'	: '
' + _t('Blockquote') + '
',
				'
': '
' + _t('Header 1') + '
',
				'
': '
' + _t('Header 2') + '
',
				'
': '
' + _t('Header 3') + '
',
				'
': '
' + _t('Header 4') + '
',
				'
': '
' + _t('Header 5') + '
',
				'
': '
' + _t('Header 6') + '
'
		    })
		},
		fontName: (lite || !$.browser.chrome) ? false : {
			title: _t('Font'),
			image: '\uf031',
			popup: getFontNamePopup(element, {
				'"Times New Roman", Times, serif': 'Times New Roman',
				'Arial, Helvetica, sans-serif': 'Arial',
				'"Courier New", Courier, monospace': 'Courier New',
				'Comic Sans, Comic Sans MS, cursive': 'Comic Sans',
				'Impact, fantasy': 'Impact',
		    })
		},
		fontSize: (lite || !$.browser.chrome) ? false : {
			title: _t('Font size'),
			image: '\uf035',
			popup: getFontSizePopup(element, {
				'1': '' + _t('Smaller') + '',
				'2': '' + _t('Small') + '',
				'3': '' + _t('Medium') + '',
				'4': '' + _t('Large') + '',
				'5': '' + _t('Larger') + ''
		    })
		},
		d1: lite ? false : {
			html: $('')
		},
		bold: {
	        title: _t('Bold (Ctrl+B)'),
	        image: '\uf032'
	    },
	    italic: {
	        title: _t('Italic (Ctrl+I)'),
	        image: '\uf033'
	    },
	    underline: {
	        title: _t('Underline (Ctrl+U)'),
	        image: '\uf0cd'
	    },
	    strikethrough: {
	        title: _t('Strikethrough (Ctrl+S)'),
	        image: '\uf0cc'
	    },
	    removeformat: {
	        title: _t('Remove format'),
	        image: '\uf12d'
	    },
	    d2: {
			html: $('')
		},
	    forecolor: lite ? false : {
	        title: _t('Text color'),
	        image: '\uf1fc'
	    },
	    highlight: lite ? false : {
	        title: _t('Background color'),
	        image: '\uf043'
	    },
	    d3: lite ? false : {
			html: $('')
		},
	    alignleft: {
	        title: _t('Left'),
	        image: '\uf036'
	    },
	    aligncenter: {
	        title: _t('Center'),
	        image: '\uf037'
	    },
	    alignright: {
	        title: _t('Right'),
	        image: '\uf038'
	    },
	    alignjustify: {
	        title: _t('Justify'),
	        image: '\uf039'
	    },
	    d4: {
			html: $('')
		},
	    orderedList: {
	        title: _t('Ordered list'),
	        image: '\uf0cb'
	    },
	    unorderedList: {
	        title: _t('Unordered list'),
	        image: '\uf0ca'
	    },
	    d6: lite ? false : {
			html: $('')
		},
	    indent: lite ? false : {
	        title: _t('Indent'),
	        image: '\uf03c'
	    },
	    outdent: lite ? false : {
	        title: _t('Outdent'),
	        image: '\uf03b'
	    },
	    d7: lite ? false : {
			html: $('')
		},
		insertimage: lite ? false : {
            title: _t('Insert image'),
            image: '\uf030'
		},
		insertlink: lite ? false : {
            title: _t('Insert link'),
            image: '\uf08e'
		},
		d8: lite ? false : {
			html: $('')
		},
		normalize: lite ? false : {
	    	title: _t('Normalize'),
	    	image: '\uf0d0',
	    	click: function () {
	    		scope.normalize();
	    	}
	    },
		showCode: lite ? false : {
			title: _t('Code'),
			image: '\uf121',
			click: function () {
				scope.toggleCode();
			}
		}
	};
}

ui.formInput('Html', {

	css: "html-item",

	init: function(scope) {

		scope.parse = function(value) {
			return value ? value : null;
		};
	},

	link_editable: function(scope, element, attrs, model) {
		this._super(scope, element, attrs, model);
		var textElement = element.find('textarea');
		var buttons = getButtons(scope, textElement);

		var height = +(scope.field.height) || null;
		if (height) {
			height = Math.max(100, height);
		}

		function isParagraph(node) {
			return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
		}

		function findParagraph(node) {
			if (!node) return null;
			if (node.classList && node.classList.contains('wysiwyg-editor')) return null;
			if (isParagraph(node)) return node;
			return findParagraph(node.parentNode);
		}

		textElement.height(height).wysiwyg({
			toolbar: 'top',
			buttons: buttons,
			submit: {
                title: _t('Submit'),
                image: '\uf00c'
            },
            selectImage: _t('Click or drop image'),
            placeholderUrl: 'www.example.com',
            maxImageSize: [600, 200],
			hijackContextmenu: false,
			onKeyPress: function(key, character, shiftKey, altKey, ctrlKey, metaKey) {
				if (key !== 13 || shiftKey) {
					return;
				}
		    	var parent = findParagraph(document.getSelection().anchorNode);
			    if (!parent) {
			    	document.execCommand('formatBlock', false, '
');
			    }
			}
		});

		var shell = textElement.wysiwyg('shell');
		var shellElement = $(shell.getElement());
		var shellActive = true;

		shellElement.addClass('html-content');

		function onChange(e) {

			var value = shellActive ? shell.getHTML() : textElement.val();

			var old = scope.getValue();
			var txt = scope.parse(value);

			if (old === txt) {
				return;
			}

			scope.setValue(value, true);
			scope.applyLater();
		}

		scope.$render_editable = function () {
			var value = scope.getValue() || "";
			scope.text = scope.format(value);

			var current = shellActive ? shell : textElement;
			var getter = shellActive ? 'getHTML' : 'val';
			var setter = shellActive ? 'setHTML' : 'val';

			var html = current[getter]();
			if (value !== html) {
				current[setter](value);
			}
		};

		textElement.on('input paste change blur', _.debounce(onChange, 100));

		textElement.on("focus", function (e) {

		    // Chrome and Edge supports this
			document.execCommand('defaultParagraphSeparator', false, 'p');

			// firefox uses attributes for some commands
			document.execCommand('styleWithCSS', false, true);
			document.execCommand('insertBrOnReturn', false, false);
		});

		scope.toggleCode = function () {

			shellActive = !shellActive;

			element.parent().find('.wysiwyg-toolbar-icon')
				.toggleClass('disabled', !shellActive)
				.last().removeClass('disabled');

			if (shellActive) {
				textElement.hide();
				shellElement.show();
				shell.setHTML(textElement.val());
			} else {
				var height = Math.max(100, shellElement.outerHeight());
				shellElement.hide();
				textElement.show().height(height);
			}
		};

		scope.normalize = function () {

    		var html = shell.getHTML();
    		var div = $('
').html(html);

    		div.find('p').css({
    			'margin-top': 0,
    			'margin-bottom': '1em'});

    		div.find('ol,ul').each(function() {
    			var el = $(this);
    			if (el.parents('ol,ul').size()) return;
    			el.css({
	    			'margin-top': 0,
	    			'margin-bottom': '1em'});
    		});

    		div.find('blockquote').each(function() {
    			var el = $(this);
    			el.css({
	    			'margin': el.parents('blockquote').size() ? '0 0 0 2em' : '0 0 1em 2em',
	    			'border': 'none',
	    			'padding': 0
	    		});
    		});

    		shellElement.focus();
    		shell.setHTML(div[0].innerHTML);

    		div.remove();
		};

	},

	template_readonly:
	'
'+
		'

'+
	'
',
	template_editable:
	'
'+
		'<textarea class="html-editor html-content"></textarea>'+
	'
'

});

ui.directive('uiBindTemplate', ['$interpolate', function($interpolate){

	function expand(scope, template) {
		if (!template || !template.match(/{{.*?}}/)) {
			return template;
		}
		return $interpolate(template)(scope.locals());
	}

	return {
		terminal: true,
		scope: {
			locals: "&",
			text: "=text",
			live: "&"
		},
		link: function(scope, element, attrs) {

			var template = null;

			function update() {
				var output = expand(scope, template) || "";
				element.html(output);
			}

			scope.$watch("text", function(text, old) {

				if (text === template) {
					return;
				}
				template = text;
				update();
			});

			var live = false;
			scope.$watch("live()", function(value) {
				if (live || !value) {
					return;
				}
				live = true;
				scope.$watch("locals()", function(value) {
					update();
				}, true);
			});
		}
	};
}]);

})();

<commit_msg>Fix html widget execCommand warning<commit_after>/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2005-2016 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function() {

"use strict";

var ui = angular.module('axelor.ui');

function getStylePopup(element, styles) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(styles, function(format, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                                $(element).wysiwyg('shell').format(format).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getFontNamePopup(element, fonts) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(fonts, function(font, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                                $(element).wysiwyg('shell').fontName(font).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getFontSizePopup(element, sizes) {

	return function ($popup, $button) {

		var $list = $('
').addClass('wysiwyg-plugin-list')
	                           .attr('unselectable', 'on');

		$.each(sizes, function(size, name) {
	        var $link = $('').attr('href','#')
	                             .html(name)
	                             .click(function(event) {
	                            	$(element).focus();
	                            	$(element).wysiwyg('shell').fontSize(size).closePopup();
	                                event.stopPropagation();
	                                event.preventDefault();
	                                return false;
	                            });
	        $list.append($link);
	    });

		$popup.append($list);
	};
}

function getButtons(scope, element) {

	var lite = scope.field.lite;

	return {
		style: lite ? false : {
			title: _t('Style'),
			image: '\uf1dd',
			popup: getStylePopup(element, {
				'
' 			: _t('Normal'),
				'
' 		: '
' + _t('Formatted') + '
',
				'
'	: '
' + _t('Blockquote') + '
',
				'
': '
' + _t('Header 1') + '
',
				'
': '
' + _t('Header 2') + '
',
				'
': '
' + _t('Header 3') + '
',
				'
': '
' + _t('Header 4') + '
',
				'
': '
' + _t('Header 5') + '
',
				'
': '
' + _t('Header 6') + '
'
		    })
		},
		fontName: (lite || !$.browser.chrome) ? false : {
			title: _t('Font'),
			image: '\uf031',
			popup: getFontNamePopup(element, {
				'"Times New Roman", Times, serif': 'Times New Roman',
				'Arial, Helvetica, sans-serif': 'Arial',
				'"Courier New", Courier, monospace': 'Courier New',
				'Comic Sans, Comic Sans MS, cursive': 'Comic Sans',
				'Impact, fantasy': 'Impact',
		    })
		},
		fontSize: (lite || !$.browser.chrome) ? false : {
			title: _t('Font size'),
			image: '\uf035',
			popup: getFontSizePopup(element, {
				'1': '' + _t('Smaller') + '',
				'2': '' + _t('Small') + '',
				'3': '' + _t('Medium') + '',
				'4': '' + _t('Large') + '',
				'5': '' + _t('Larger') + ''
		    })
		},
		d1: lite ? false : {
			html: $('')
		},
		bold: {
	        title: _t('Bold (Ctrl+B)'),
	        image: '\uf032'
	    },
	    italic: {
	        title: _t('Italic (Ctrl+I)'),
	        image: '\uf033'
	    },
	    underline: {
	        title: _t('Underline (Ctrl+U)'),
	        image: '\uf0cd'
	    },
	    strikethrough: {
	        title: _t('Strikethrough (Ctrl+S)'),
	        image: '\uf0cc'
	    },
	    removeformat: {
	        title: _t('Remove format'),
	        image: '\uf12d'
	    },
	    d2: {
			html: $('')
		},
	    forecolor: lite ? false : {
	        title: _t('Text color'),
	        image: '\uf1fc'
	    },
	    highlight: lite ? false : {
	        title: _t('Background color'),
	        image: '\uf043'
	    },
	    d3: lite ? false : {
			html: $('')
		},
	    alignleft: {
	        title: _t('Left'),
	        image: '\uf036'
	    },
	    aligncenter: {
	        title: _t('Center'),
	        image: '\uf037'
	    },
	    alignright: {
	        title: _t('Right'),
	        image: '\uf038'
	    },
	    alignjustify: {
	        title: _t('Justify'),
	        image: '\uf039'
	    },
	    d4: {
			html: $('')
		},
	    orderedList: {
	        title: _t('Ordered list'),
	        image: '\uf0cb'
	    },
	    unorderedList: {
	        title: _t('Unordered list'),
	        image: '\uf0ca'
	    },
	    d6: lite ? false : {
			html: $('')
		},
	    indent: lite ? false : {
	        title: _t('Indent'),
	        image: '\uf03c'
	    },
	    outdent: lite ? false : {
	        title: _t('Outdent'),
	        image: '\uf03b'
	    },
	    d7: lite ? false : {
			html: $('')
		},
		insertimage: lite ? false : {
            title: _t('Insert image'),
            image: '\uf030'
		},
		insertlink: lite ? false : {
            title: _t('Insert link'),
            image: '\uf08e'
		},
		d8: lite ? false : {
			html: $('')
		},
		normalize: lite ? false : {
	    	title: _t('Normalize'),
	    	image: '\uf0d0',
	    	click: function () {
	    		scope.normalize();
	    	}
	    },
		showCode: lite ? false : {
			title: _t('Code'),
			image: '\uf121',
			click: function () {
				scope.toggleCode();
			}
		}
	};
}

ui.formInput('Html', {

	css: "html-item",

	init: function(scope) {

		scope.parse = function(value) {
			return value ? value : null;
		};
	},

	link_editable: function(scope, element, attrs, model) {
		this._super(scope, element, attrs, model);
		var textElement = element.find('textarea');
		var buttons = getButtons(scope, textElement);

		var height = +(scope.field.height) || null;
		if (height) {
			height = Math.max(100, height);
		}

		function isParagraph(node) {
			return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase());
		}

		function findParagraph(node) {
			if (!node) return null;
			if (node.classList && node.classList.contains('wysiwyg-editor')) return null;
			if (isParagraph(node)) return node;
			return findParagraph(node.parentNode);
		}

		textElement.height(height).wysiwyg({
			toolbar: 'top',
			buttons: buttons,
			submit: {
                title: _t('Submit'),
                image: '\uf00c'
            },
            selectImage: _t('Click or drop image'),
            placeholderUrl: 'www.example.com',
            maxImageSize: [600, 200],
			hijackContextmenu: false,
			onKeyPress: function(key, character, shiftKey, altKey, ctrlKey, metaKey) {
				if (key !== 13 || shiftKey) {
					return;
				}
		    	var parent = findParagraph(document.getSelection().anchorNode);
			    if (!parent) {
			    	document.execCommand('formatBlock', false, '
');
			    }
			}
		});

		var shell = textElement.wysiwyg('shell');
		var shellElement = $(shell.getElement());
		var shellActive = true;

		shellElement.addClass('html-content');

		function onChange(e) {

			var value = shellActive ? shell.getHTML() : textElement.val();

			var old = scope.getValue();
			var txt = scope.parse(value);

			if (old === txt) {
				return;
			}

			scope.setValue(value, true);
			scope.applyLater();
		}

		scope.$render_editable = function () {
			var value = scope.getValue() || "";
			scope.text = scope.format(value);

			var current = shellActive ? shell : textElement;
			var getter = shellActive ? 'getHTML' : 'val';
			var setter = shellActive ? 'setHTML' : 'val';

			var html = current[getter]();
			if (value !== html) {
				current[setter](value);
			}
		};

		textElement.on('input paste change blur', _.debounce(onChange, 100));

		textElement.on("focus", _.once(function (e) {

		    // Chrome and Edge supports this
			document.execCommand('defaultParagraphSeparator', false, 'p');

			// firefox uses attributes for some commands
			document.execCommand('styleWithCSS', false, true);
			document.execCommand('insertBrOnReturn', false, false);
		}));

		scope.toggleCode = function () {

			shellActive = !shellActive;

			element.parent().find('.wysiwyg-toolbar-icon')
				.toggleClass('disabled', !shellActive)
				.last().removeClass('disabled');

			if (shellActive) {
				textElement.hide();
				shellElement.show();
				shell.setHTML(textElement.val());
			} else {
				var height = Math.max(100, shellElement.outerHeight());
				shellElement.hide();
				textElement.show().height(height);
			}
		};

		scope.normalize = function () {

    		var html = shell.getHTML();
    		var div = $('
').html(html);

    		div.find('p').css({
    			'margin-top': 0,
    			'margin-bottom': '1em'});

    		div.find('ol,ul').each(function() {
    			var el = $(this);
    			if (el.parents('ol,ul').size()) return;
    			el.css({
	    			'margin-top': 0,
	    			'margin-bottom': '1em'});
    		});

    		div.find('blockquote').each(function() {
    			var el = $(this);
    			el.css({
	    			'margin': el.parents('blockquote').size() ? '0 0 0 2em' : '0 0 1em 2em',
	    			'border': 'none',
	    			'padding': 0
	    		});
    		});

    		shellElement.focus();
    		shell.setHTML(div[0].innerHTML);

    		div.remove();
		};

	},

	template_readonly:
	'
'+
		'

'+
	'
',
	template_editable:
	'
'+
		'<textarea class="html-editor html-content"></textarea>'+
	'
'

});

ui.directive('uiBindTemplate', ['$interpolate', function($interpolate){

	function expand(scope, template) {
		if (!template || !template.match(/{{.*?}}/)) {
			return template;
		}
		return $interpolate(template)(scope.locals());
	}

	return {
		terminal: true,
		scope: {
			locals: "&",
			text: "=text",
			live: "&"
		},
		link: function(scope, element, attrs) {

			var template = null;

			function update() {
				var output = expand(scope, template) || "";
				element.html(output);
			}

			scope.$watch("text", function(text, old) {

				if (text === template) {
					return;
				}
				template = text;
				update();
			});

			var live = false;
			scope.$watch("live()", function(value) {
				if (live || !value) {
					return;
				}
				live = true;
				scope.$watch("locals()", function(value) {
					update();
				}, true);
			});
		}
	};
}]);

})();

<|endoftext|>


<commit_before>var jsondb = require('com.irlgaming.jsondb');
jsondb.debug(true);
var localCollection = jsondb.factory('localJSONDB', 'blogDB');
var exports = {
  load:function(/* string */ blogger, /* function */callback){
    initJSONDB();
    var self = this;
    var count = localCollection.count({blogger:{$eq:blogger}});
    if(count >= 1){
      var entries = localCollection.find({
        blogger:{$eq:blogger}
      },{
        $limit:5,
        $sort:{post_date:-1}
      });
      callback(entries);
    }else{
      self.loadLatest(blogger,callback);
    }
  },
  loadLatest:function(/* string */ blogger, /* function */callback){
    alert('start'+ blogger + 'さんのエントリ読み込み開始');
    // 2033-05-18 12:33:20 +0900(unixitmeだと2000000000 ) よりも最新エントリは存在しないので
    // 決め打ち
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/older/2000000000";
    httpClient(url,callback);

  },
  loadLastUpdateEntry:function(/* string */ blogger,/* date */ lastupdate, /* function */callback){
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/newer/" + lastupdate;
    httpClient(url,callback);

  },
  loadOldEntry:function(/* string */ blogger,/* date */ baseDate, /* function */callback){
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/older/" + baseDate;
    httpClient(url,callback);

  },
  findLocalJSONDB:function(blogger,callback){
    myApps.ui.actInd.setMessage('Load data from local....');
    myApps.ui.actInd.show();
    var localCollection = jsondb.factory('localJSONDB', 'asunaroblog');
    var entries = localCollection.find({
      blogger:{$eq:blogger}
    },{
      // $limit:5,
      $sort:{
        post_date:1
      }
    });
    for(var i=0;i<entries.length;i++){
      Ti.API.info(entries[i].title);
    }
    callback(sorted(entries));

  }
};
// private method

function initJSONDB(){
  Ti.API.info(Titanium.Utils.sha1("obj"));
  Ti.API.info(Ti.Filesystem.applicationDataDirectory);

};
function isConnected(){
  if(Titanium.Network.online===true){
    return true;
  }
};
function sorted(entries){
  var _ = require('lib/underscore')._;
  var value = _.chain(entries)
      .sortBy(function(item) {return item.post_date; })
      .reverse()
      .value();
  return value;
}

function httpClient(url,callback){
  if(Titanium.Network.online===true){
    var xhr = Ti.Network.createHTTPClient();
    xhr.open('GET',url);
    xhr.onload = function(){
      var res = JSON.parse(this.responseText);
      var result = sorted(res);

      for(var i=0;i<result.length;i++){
        localCollection.save({
          permalink:result[i].permalink,
          html_body:result[i].html_body,
          blogger:result[i].blogger,
          post_date:result[i].post_date,
          title:result[i].title
        });
        localCollection.ensureIndex({'post_date':1});
        localCollection.commit();
        Ti.API.info('stored cache!! entry title is:'+result[i].title);
      }
      callback(result);
    };
    xhr.error = function(){
      var dialog = Ti.UI.createAlertDialog({
        title: "ネットワーク接続エラー",
        message: "ネットワーク接続が確立されていません。再度お試しください"
      });
      dialog.show();
      myApps.ui.actInd.hide();
    };
    xhr.send();
  }else{
    var dialog = Ti.UI.createAlertDialog({
      title: "ネットワーク接続できていません"
    });
    dialog.show();
    myApps.ui.actInd.hide();
  }
}<commit_msg>alert文を入れていたのを忘れていたので除去<commit_after>var jsondb = require('com.irlgaming.jsondb');
jsondb.debug(true);
var localCollection = jsondb.factory('localJSONDB', 'blogDB');
var exports = {
  load:function(/* string */ blogger, /* function */callback){
    initJSONDB();
    var self = this;
    var count = localCollection.count({blogger:{$eq:blogger}});
    if(count >= 1){
      var entries = localCollection.find({
        blogger:{$eq:blogger}
      },{
        $limit:5,
        $sort:{post_date:-1}
      });
      callback(entries);
    }else{
      self.loadLatest(blogger,callback);
    }
  },
  loadLatest:function(/* string */ blogger, /* function */callback){

    // 2033-05-18 12:33:20 +0900(unixitmeだと2000000000 ) よりも最新エントリは存在しないので
    // 決め打ち
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/older/2000000000";
    httpClient(url,callback);

  },
  loadLastUpdateEntry:function(/* string */ blogger,/* date */ lastupdate, /* function */callback){
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/newer/" + lastupdate;
    httpClient(url,callback);

  },
  loadOldEntry:function(/* string */ blogger,/* date */ baseDate, /* function */callback){
    var url = "http://h5y1m141.info/entry/" + blogger + "/date/older/" + baseDate;
    httpClient(url,callback);

  },
  findLocalJSONDB:function(blogger,callback){
    myApps.ui.actInd.setMessage('Load data from local....');
    myApps.ui.actInd.show();
    var localCollection = jsondb.factory('localJSONDB', 'asunaroblog');
    var entries = localCollection.find({
      blogger:{$eq:blogger}
    },{
      // $limit:5,
      $sort:{
        post_date:1
      }
    });
    for(var i=0;i<entries.length;i++){
      Ti.API.info(entries[i].title);
    }
    callback(sorted(entries));

  }
};
// private method

function initJSONDB(){
  Ti.API.info(Titanium.Utils.sha1("obj"));
  Ti.API.info(Ti.Filesystem.applicationDataDirectory);

};
function isConnected(){
  if(Titanium.Network.online===true){
    return true;
  }
};
function sorted(entries){
  var _ = require('lib/underscore')._;
  var value = _.chain(entries)
      .sortBy(function(item) {return item.post_date; })
      .reverse()
      .value();
  return value;
}

function httpClient(url,callback){
  if(Titanium.Network.online===true){
    var xhr = Ti.Network.createHTTPClient();
    xhr.open('GET',url);
    xhr.onload = function(){
      var res = JSON.parse(this.responseText);
      var result = sorted(res);

      for(var i=0;i<result.length;i++){
        localCollection.save({
          permalink:result[i].permalink,
          html_body:result[i].html_body,
          blogger:result[i].blogger,
          post_date:result[i].post_date,
          title:result[i].title
        });
        localCollection.ensureIndex({'post_date':1});
        localCollection.commit();
        Ti.API.info('stored cache!! entry title is:'+result[i].title);
      }
      callback(result);
    };
    xhr.error = function(){
      var dialog = Ti.UI.createAlertDialog({
        title: "ネットワーク接続エラー",
        message: "ネットワーク接続が確立されていません。再度お試しください"
      });
      dialog.show();
      myApps.ui.actInd.hide();
    };
    xhr.send();
  }else{
    var dialog = Ti.UI.createAlertDialog({
      title: "ネットワーク接続できていません"
    });
    dialog.show();
    myApps.ui.actInd.hide();
  }
}<|endoftext|>


<commit_before>var _ = require('lib/underscore')._;
var Question = require('models/question');
var Response = require('models/response')

var Survey = new Ti.App.joli.model({
	table : 'survey',
	columns : {
		id : 'INTEGER PRIMARY KEY',
		name : 'TEXT',
		description : 'TEXT',
		expiry_date : 'TEXT'
	},

	methods : {
		fetchSurveys : function() {
			var url = Ti.App.Properties.getString('server_url') + '/api/surveys';
			var that = this;
			var client = Ti.Network.createHTTPClient({
				// function called when the response data is available
				onload : function(e) {
					Ti.API.info("Received text: " + this.responseText);
					var data = JSON.parse(this.responseText);
					// Emptying the table for now (until we get all the survey info from the server)
					that.truncate();
					Question.truncate();
					_(data).each(function(surveyData) {
						var survey = that.createRecord(surveyData);
						survey.fetchQuestions();
					});
					Ti.App.fireEvent('surveys.fetch.success');
				},
				// function called when an error occurs, including a timeout
				onerror : function(e) {
					Ti.API.debug(e.error);
					Ti.App.fireEvent('surveys.fetch.error', {
						status : this.status
					});
				},
				timeout : 5000 // in milliseconds
			});
			// Prepare the connection.
			client.open("GET", url);
			// Send the request.
			client.send();
		},

		createRecord : function(surveyData) {
			var record = this.newRecord({
				id : surveyData.id,
				name : surveyData.name,
				description : surveyData.description,
				expiry_date : surveyData.expiry_date
			});
			record.save();
			return record;
		},

		isEmpty : function() {
			return this.count() == 0;
		},
	},
	objectMethods : {
		syncResponses : function() {
			var success_count = 0;
			var self = this;

			var syncHandler = function(data) {
				Ti.API.info("All RESPONSES SYNCED: " + self.allResponsesSynced().toString())
				if (data.survey_id == self.id) {
					if (self.allResponsesSynced()) {
						Ti.App.fireEvent("survey.responses.sync", self.syncSummary());
						Ti.API.info("SUMMARY: " + self.syncSummary());
						Ti.App.removeEventListener("response.sync", syncHandler);
					};
				}
			};

			Ti.App.addEventListener("response.sync", syncHandler);

			_(this.responses()).each(function(response) {
				response.sync();
			});
		},

		responses : function() {
			this.response_objects = this.response_objects || Response.findBy('survey_id', this.id);
			return this.response_objects
		},

		allResponsesSynced : function() {
			return _(this.responses()).all(function(response) {
				return response.synced === true;
			});
		},

		syncSummary : function() {
			return _(this.responses()).countBy(function(response){
				return response.has_error ? 'errors' : 'successes'
			});
		},

		fetchQuestions : function() {
			var self = this;
			var url = Ti.App.Properties.getString('server_url') + '/api/questions';
			var client = Ti.Network.createHTTPClient({
				// function called when the response data is available
				onload : function(e) {
					Ti.API.info("Received text for questions: " + this.responseText);
					var data = JSON.parse(this.responseText);
					Question.createRecords(data, self.id);
				},
				// function called when an error occurs, including a timeout
				onerror : function(e) {
					Ti.API.info("Error");
				},
				timeout : 5000 // in milliseconds
			});
			// Prepare the connection.
			client.open("GET", url);
			// Send the request.
			client.send({ survey_id: self.id});
		},
	}
});

Ti.App.joli.models.initialize();
module.exports = Survey;

<commit_msg>Pass params as a part of URL<commit_after>var _ = require('lib/underscore')._;
var Question = require('models/question');
var Response = require('models/response')

var Survey = new Ti.App.joli.model({
	table : 'survey',
	columns : {
		id : 'INTEGER PRIMARY KEY',
		name : 'TEXT',
		description : 'TEXT',
		expiry_date : 'TEXT'
	},

	methods : {
		fetchSurveys : function() {
			var url = Ti.App.Properties.getString('server_url') + '/api/surveys';
			var that = this;
			var client = Ti.Network.createHTTPClient({
				// function called when the response data is available
				onload : function(e) {
					Ti.API.info("Received text: " + this.responseText);
					var data = JSON.parse(this.responseText);
					// Emptying the table for now (until we get all the survey info from the server)
					that.truncate();
					Question.truncate();
					_(data).each(function(surveyData) {
						var survey = that.createRecord(surveyData);
						survey.fetchQuestions();
					});
					Ti.App.fireEvent('surveys.fetch.success');
				},
				// function called when an error occurs, including a timeout
				onerror : function(e) {
					Ti.API.debug(e.error);
					Ti.App.fireEvent('surveys.fetch.error', {
						status : this.status
					});
				},
				timeout : 5000 // in milliseconds
			});
			// Prepare the connection.
			client.open("GET", url);
			// Send the request.
			client.send();
		},

		createRecord : function(surveyData) {
			var record = this.newRecord({
				id : surveyData.id,
				name : surveyData.name,
				description : surveyData.description,
				expiry_date : surveyData.expiry_date
			});
			record.save();
			return record;
		},

		isEmpty : function() {
			return this.count() == 0;
		},
	},
	objectMethods : {
		syncResponses : function() {
			var success_count = 0;
			var self = this;

			var syncHandler = function(data) {
				Ti.API.info("All RESPONSES SYNCED: " + self.allResponsesSynced().toString())
				if (data.survey_id == self.id) {
					if (self.allResponsesSynced()) {
						Ti.App.fireEvent("survey.responses.sync", self.syncSummary());
						Ti.API.info("SUMMARY: " + self.syncSummary());
						Ti.App.removeEventListener("response.sync", syncHandler);
					};
				}
			};

			Ti.App.addEventListener("response.sync", syncHandler);

			_(this.responses()).each(function(response) {
				response.sync();
			});
		},

		responses : function() {
			this.response_objects = this.response_objects || Response.findBy('survey_id', this.id);
			return this.response_objects
		},

		allResponsesSynced : function() {
			return _(this.responses()).all(function(response) {
				return response.synced === true;
			});
		},

		syncSummary : function() {
			return _(this.responses()).countBy(function(response){
				return response.has_error ? 'errors' : 'successes'
			});
		},

		fetchQuestions : function() {
			var self = this;
			var url = Ti.App.Properties.getString('server_url') + '/api/questions?survey_id=' + self.id;
			var client = Ti.Network.createHTTPClient({
				// function called when the response data is available
				onload : function(e) {
					Ti.API.info("Received text for questions: " + this.responseText);
					var data = JSON.parse(this.responseText);
					Question.createRecords(data, self.id);
				},
				// function called when an error occurs, including a timeout
				onerror : function(e) {
					Ti.API.info("Error");
				},
				timeout : 5000 // in milliseconds
			});
			// Prepare the connection.
			client.open("GET", url);
			// Send the request.
			client.send();
		},
	}
});

Ti.App.joli.models.initialize();
module.exports = Survey;

<|endoftext|>


<commit_before>$(document).ready(function() {
    $('.tree > ul').attr('role', 'tree').find('ul').attr('role', 'group');
    $('.tree').find('li:has(ul)').addClass('parent_li').attr('role', 'treeitem').find(' > span.expand').on('click', function (e) {
        var children = $(this).parent('li.parent_li').find(' > ul > li');
        if (children.is(':visible')) {
            children.hide('fast');
            $(this).removeClass('expanded');
        }
        else {
            children.show('fast');
            $(this).addClass('expanded');
        }
        e.stopPropagation();
    });

    $('.tree').find('span.checkmark').on('click', function(e) {
        var inputId = $(this).closest('.tree').data('input-id');

        $('#'+inputId).val($(this).parent('li').data('id'));
        $(this).closest('.tree').find('li.selected').removeClass('selected');
        $(this).parent('li').addClass('selected');
    });
});
<commit_msg>Fixed tree view<commit_after>$(document).ready(function() {
    $('.tree > ul').attr('role', 'tree').find('ul').attr('role', 'group');
    $('.tree').find('li:has(ul)').addClass('parent_li').attr('role', 'treeitem').find(' > span.expand').on('click', function (e) {
        var children = $(this).parent('li.parent_li').find(' > ul > li');
        if (children.is(':visible')) {
            $(this).parent('li.parent_li').removeClass('expanded');
        }
        else {
            $(this).parent('li.parent_li').addClass('expanded');
        }
        e.stopPropagation();
    });

    $('.tree').find('span.checkmark').on('click', function(e) {
        var inputId = $(this).closest('.tree').data('input-id');

        $('#'+inputId).val($(this).parent('li').data('id'));
        $(this).closest('.tree').find('li.selected').removeClass('selected');
        $(this).parent('li').addClass('selected');
    });
});
<|endoftext|>


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

    // @todo: Move config and merging with defaults back to PHP Element (Scheme class is now a pure data object)
    /**
     *
     * @param {Object} options
     * @param widget
     * @constructor
     */

    Mapbender.Digitizer.Scheme = function (options, widget) {
        var schema = this;

        schema.widget = widget;

        schema.featureType = options.featureType || {
            uniqueId: null,
            geomField: null,
            styleField: null,
            srid: 4326
        };

        schema.schemaName = options.schemaName;

        schema.label = options.label;
        schema.popup = options.popup || {title: schema.schemaName, width: '500px'};
        schema.tableFields = options.tableFields;
        schema.formItems = options.formItems || {};
        schema.allowEditData = options.allowEditData || (typeof options.allowEditData === 'undefined');  //default true
        schema.allowSave = options.allowSave || false;
        schema.allowOpenEditDialog = options.allowOpenEditDialog || false;
        schema.allowDelete = options.allowDelete || (typeof options.allowDelete === 'undefined');  //default true;
        schema.inlineSearch = options.inlineSearch || true;
        schema.pageLength = options.pageLength || 10;
        schema.inlineSearch = options.inlineSearch || false;
        schema.tableTranslation = options.tableTranslation || undefined;

        // alias different config keys "allowEditData", "allowOpenEditDialog" to upstream-compatible "allowEdit"
        schema.allowEdit = schema.allowEditData || options.allowOpenEditDialog || options.allowEdit || false;

        schema.toolset = options.toolset;

        schema.allowCustomStyle = options.allowCustomStyle || false;

        schema.allowDigitize = options.allowDigitize || (typeof options.allowEditData === 'undefined');  // default true

        schema.allowSaveInResultTable = options.allowSaveInResultTable || false;

        schema.copy = options.copy || {
            enable: false,
            overwriteValuesWithDefault: false,
            moveCopy: {x: 10, y: 10}
        };

        schema.printable = options.printable || false;

        schema.allowChangeVisibility = options.allowChangeVisibility || false;

        schema.minScale = options.minScale || undefined;

        schema.maxScale = options.maxScale || undefined;

        schema.currentExtentSearch = options.currentExtentSearch || false;

        schema.displayPermanent = options.displayPermanent || false;

        schema.refreshFeaturesAfterSave = options.refreshFeaturesAfterSave || false;

        schema.refreshLayersAfterFeatureSave = options.refreshLayersAfterFeatureSave || false;

        /** New properties **/
        schema.revertChangedGeometryOnCancel = options.revertChangedGeometryOnCancel || false;

        schema.allowSaveAll = options.allowSaveAll || false;

        schema.allowOpenEditDialog = options.allowOpenEditDialog || false;
    };

    Mapbender.Digitizer.FeatureRenderer = function FeatureRenderer(olMap, schema) {
        this.schema = schema;
        this.olMap = olMap;
        /** @todo: should go PHP, in getSchemaConfig; less runtime merging of stuff */
        this.basicStyles = Object.assign({}, this.getDefaultStyles(), schema.styles || {});

        this.styles = this.initializeStyles_(this.basicStyles); // NOTE: accessed only in event handlers currently inlined here

        this.layer = this.createSchemaFeatureLayer_(schema);
        this.olMap.addLayer(this.layer);

        this.addSelectControl_();

        var renderer = this;
        this.layer.getSource().on(ol.source.VectorEventType.ADDFEATURE, function (event) {
            var feature = event.feature;
            renderer.initializeFeature(schema, feature);
            renderer.registerFeatureEvents(schema, feature);
        });
        this.layer.getSource().on('controlFactory.FeatureAdded', function (event) {
            // @todo: this is no longer rendering specific and this class should not listen to this event at all
            // @todo: Renderer should know about the widget
            schema.widget._openEditDialog(schema, event.feature);
        });

        $(olMap).on('Digitizer.FeatureUpdatedOnServer', function (event) {
            renderer.onFeatureUpdatedOnServer(renderer.schema);
        });
    }
    Object.assign(Mapbender.Digitizer.FeatureRenderer.prototype, {
        initializeFeature: function(schema, feature) {
            feature.set("mbOrigin", "digitizer");
            feature.setStyle = feature.setStyleWithLabel;
            feature.setStyle(this.styles.default);
            // @todo: don't do this if style cannot be saved (no style field)
            if (schema.allowCustomStyle) {
                this.customStyleFeature_(feature);
            }

            feature.set("oldGeometry", feature.getGeometry().clone());
        },
        registerFeatureEvents: function(schema, feature) {
            feature.on('Digitizer.HoverFeature', function (event) {
                var hover = !!event.hover || (typeof (event.hover) === 'undefined');
                feature.set('selected', hover && !feature.get('hidden'));
            });

            var renderer = this;
            feature.on(ol.ObjectEventType.PROPERTYCHANGE, function (event) {
                if (event.key == "selected" || event.key == "modificationState" || event.key == "hidden") {
                    renderer.updateFeatureStyle(schema, feature);
                }
            });
        },
        setRenderIntent: function(feature, intent) {
            // @todo: drop monkey-patching of setStyle = setStyleWithLabel
            feature.setStyle(this.getStyleForIntent_(feature, intent));
        },
        getStyleForIntent_: function(feature, intent) {
            // @todo: turn this into a style function on the layer, so it will work without events
            var intent_ = intent;
            if (!this.styles[intent]) {
                console.warn("Unknown render intent " + intent + ", using default");
                intent_ = 'default';
            }
            var style;
            if (intent_ === 'default') {
                // NOTE: "style" value only set by feature style editor (disabled?; see customStyleFeature_)
                style = feature.get('style');
            }
            return style || this.styles[intent_];
        },
        updateFeatureStyle: function(schema, feature) {
            // See selectableModify interaction (ol4 extensions)
            // @todo: selectableModify should deal with pausing style updates itself
            if (feature.get("featureStyleDisabled")) {
                return;
            }
            if (feature.get("hidden")) {
                this.setRenderIntent(feature, 'invisible');
            } else if (feature.get("selected")) {
                this.setRenderIntent(feature, 'select');
            } else if (feature.get("modificationState")) {
                this.setRenderIntent(feature, 'unsaved');
            } else {
                this.setRenderIntent(feature, 'default');
            }
        }
    });

    Object.assign(Mapbender.Digitizer.FeatureRenderer.prototype, {
        onFeatureUpdatedOnServer: function(schema) {
            if (schema.refreshLayersAfterFeatureSave) {
                $.each(schema.refreshLayersAfterFeatureSave, function (k1, layerInstanceId) {
                    var layers = Mapbender.layerManager.getLayersByInstanceId(layerInstanceId);
                    $.each(layers, function (k2, layer) {
                        Mapbender.layerManager.refreshLayer(layer);
                    });
                });
            }

            if(schema.refreshFeaturesAfterSave){
                $.each(schema.refreshFeaturesAfterSave, function(key,schemaName){
                    schema.widget.refreshConnectedDigitizerFeatures(schemaName);
                })
            }
        }
    });

    /** @todo: should go PHP, in getSchemaConfigDefaults; less runtime merging of stuff */
    Mapbender.Digitizer.FeatureRenderer.prototype.getDefaultStyles = function () {
        return {
            default: {
                strokeWidth: 1,
                strokeColor: '#6fb536',
                fillColor: '#6fb536',
                fillOpacity: 0.3
            },
            select: {
                strokeWidth: 3,
                fillColor: '#F7F79A',
                strokeColor: '#6fb536',
                fillOpacity: 0.5,
                graphicZIndex: 15
            },
            unsaved: {
                strokeWidth: 3,
                fillColor: '#FFD14F',
                strokeColor: '#F5663C',
                fillOpacity: 0.5
            }
        };
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.getLayer = function() {
        return this.layer;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.initializeStyles_ = function (styleConfigs) {
        var styles = {};
        var keys = Object.keys(styleConfigs);
        for (var i = 0; i < keys.length; ++ i) {
            var key = keys[i];
            var styleConfig = styleConfigs[key];
            styles[key] = ol.style.StyleConverter.convertToOL4Style(styleConfig);
        }
        Object.freeze(styles.default.getFill().getColor()); // Freeze Color to prevent unpredictable behaviour
        styles.invisible = new ol.style.Style();
        return styles;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.createSchemaFeatureLayer_ = function (schema) {
        var layer = new ol.layer.Vector({
            source: new ol.source.Vector(),
            visible: true
            // HACK: disable min / max resolution and initial visibility while testing
            // @todo: reenable minScale / maxScale config evaluation
//            minResolution: Mapbender.Model.scaleToResolution(schema.maxScale || 0),
//            maxResolution: Mapbender.Model.scaleToResolution(schema.minScale || Infinity),
//            visible: false
        });
        return layer;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.customStyleFeature_ = function (feature) {
        var schema = this;

        console.assert(!!schema.featureType.styleField, "Style Field in Feature Type is not specified");

        var jsonStyle = feature.get("data") && feature.get("data").get(schema.featureType.styleField);

        if (jsonStyle) {
            var basicStyle = JSON.parse(jsonStyle);
            var style = ol.style.StyleConverter.convertToOL4Style(basicStyle);
            feature.set("basicStyle", basicStyle);
            feature.set("style", style);
            feature.setStyle(style);
        }
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.addSelectControl_ = function () {
        this.highlightControl = this.initializeHighlightControl_();
        this.selectControl = this.initializeSelectControl_();
        this.olMap.addInteraction(this.selectControl);
        this.olMap.addInteraction(this.highlightControl);
    };
    Mapbender.Digitizer.FeatureRenderer.prototype.initializeHighlightControl_ = function () {
        var highlightControl = new ol.interaction.Select({
            condition: ol.events.condition.pointerMove,
            layers: [this.layer]
        });
        highlightControl.on('select', function (e) {
            e.selected.forEach(function (feature) {
                feature.dispatchEvent({type: 'Digitizer.HoverFeature', hover: true});
            });

            e.deselected.forEach(function (feature) {
                feature.dispatchEvent({type: 'Digitizer.HoverFeature', hover: false});
            });
        });

        highlightControl.setActive(false);
        return highlightControl;
    };
    Mapbender.Digitizer.FeatureRenderer.prototype.initializeSelectControl_ = function () {
        var selectControl = new ol.interaction.Select({
            condition: ol.events.condition.singleClick,
            layers: [this.layer],
            style: function () {
                return null;
            }
        });

        var schema = this.schema;
        if (schema.allowEditData || this.schema.allowOpenEditDialog) {
            selectControl.on('select', function (event) {
                // @todo: Renderer should know about the widget
                schema.widget._openEditDialog(schema, event.selected[0]);
                selectControl.getFeatures().clear();
            });
        }
        selectControl.setActive(false);
        return selectControl;
    };
})();
<commit_msg>Remove default for "featureType" schema config. Missing "featureType" is an error<commit_after>(function () {
    "use strict";

    // @todo: Move config and merging with defaults back to PHP Element (Scheme class is now a pure data object)
    /**
     *
     * @param {Object} options
     * @param widget
     * @constructor
     */

    Mapbender.Digitizer.Scheme = function (options, widget) {
        var schema = this;

        schema.widget = widget;

        schema.featureType = options.featureType;

        schema.schemaName = options.schemaName;

        schema.label = options.label;
        schema.popup = options.popup || {title: schema.schemaName, width: '500px'};
        schema.tableFields = options.tableFields;
        schema.formItems = options.formItems || {};
        schema.allowEditData = options.allowEditData || (typeof options.allowEditData === 'undefined');  //default true
        schema.allowSave = options.allowSave || false;
        schema.allowOpenEditDialog = options.allowOpenEditDialog || false;
        schema.allowDelete = options.allowDelete || (typeof options.allowDelete === 'undefined');  //default true;
        schema.inlineSearch = options.inlineSearch || true;
        schema.pageLength = options.pageLength || 10;
        schema.inlineSearch = options.inlineSearch || false;
        schema.tableTranslation = options.tableTranslation || undefined;

        // alias different config keys "allowEditData", "allowOpenEditDialog" to upstream-compatible "allowEdit"
        schema.allowEdit = schema.allowEditData || options.allowOpenEditDialog || options.allowEdit || false;

        schema.toolset = options.toolset;

        schema.allowCustomStyle = options.allowCustomStyle || false;

        schema.allowDigitize = options.allowDigitize || (typeof options.allowEditData === 'undefined');  // default true

        schema.allowSaveInResultTable = options.allowSaveInResultTable || false;

        schema.copy = options.copy || {
            enable: false,
            overwriteValuesWithDefault: false,
            moveCopy: {x: 10, y: 10}
        };

        schema.printable = options.printable || false;

        schema.allowChangeVisibility = options.allowChangeVisibility || false;

        schema.minScale = options.minScale || undefined;

        schema.maxScale = options.maxScale || undefined;

        schema.currentExtentSearch = options.currentExtentSearch || false;

        schema.displayPermanent = options.displayPermanent || false;

        schema.refreshFeaturesAfterSave = options.refreshFeaturesAfterSave || false;

        schema.refreshLayersAfterFeatureSave = options.refreshLayersAfterFeatureSave || false;

        /** New properties **/
        schema.revertChangedGeometryOnCancel = options.revertChangedGeometryOnCancel || false;

        schema.allowSaveAll = options.allowSaveAll || false;

        schema.allowOpenEditDialog = options.allowOpenEditDialog || false;
    };

    Mapbender.Digitizer.FeatureRenderer = function FeatureRenderer(olMap, schema) {
        this.schema = schema;
        this.olMap = olMap;
        /** @todo: should go PHP, in getSchemaConfig; less runtime merging of stuff */
        this.basicStyles = Object.assign({}, this.getDefaultStyles(), schema.styles || {});

        this.styles = this.initializeStyles_(this.basicStyles); // NOTE: accessed only in event handlers currently inlined here

        this.layer = this.createSchemaFeatureLayer_(schema);
        this.olMap.addLayer(this.layer);

        this.addSelectControl_();

        var renderer = this;
        this.layer.getSource().on(ol.source.VectorEventType.ADDFEATURE, function (event) {
            var feature = event.feature;
            renderer.initializeFeature(schema, feature);
            renderer.registerFeatureEvents(schema, feature);
        });
        this.layer.getSource().on('controlFactory.FeatureAdded', function (event) {
            // @todo: this is no longer rendering specific and this class should not listen to this event at all
            // @todo: Renderer should know about the widget
            schema.widget._openEditDialog(schema, event.feature);
        });

        $(olMap).on('Digitizer.FeatureUpdatedOnServer', function (event) {
            renderer.onFeatureUpdatedOnServer(renderer.schema);
        });
    }
    Object.assign(Mapbender.Digitizer.FeatureRenderer.prototype, {
        initializeFeature: function(schema, feature) {
            feature.set("mbOrigin", "digitizer");
            feature.setStyle = feature.setStyleWithLabel;
            feature.setStyle(this.styles.default);
            // @todo: don't do this if style cannot be saved (no style field)
            if (schema.allowCustomStyle) {
                this.customStyleFeature_(feature);
            }

            feature.set("oldGeometry", feature.getGeometry().clone());
        },
        registerFeatureEvents: function(schema, feature) {
            feature.on('Digitizer.HoverFeature', function (event) {
                var hover = !!event.hover || (typeof (event.hover) === 'undefined');
                feature.set('selected', hover && !feature.get('hidden'));
            });

            var renderer = this;
            feature.on(ol.ObjectEventType.PROPERTYCHANGE, function (event) {
                if (event.key == "selected" || event.key == "modificationState" || event.key == "hidden") {
                    renderer.updateFeatureStyle(schema, feature);
                }
            });
        },
        setRenderIntent: function(feature, intent) {
            // @todo: drop monkey-patching of setStyle = setStyleWithLabel
            feature.setStyle(this.getStyleForIntent_(feature, intent));
        },
        getStyleForIntent_: function(feature, intent) {
            // @todo: turn this into a style function on the layer, so it will work without events
            var intent_ = intent;
            if (!this.styles[intent]) {
                console.warn("Unknown render intent " + intent + ", using default");
                intent_ = 'default';
            }
            var style;
            if (intent_ === 'default') {
                // NOTE: "style" value only set by feature style editor (disabled?; see customStyleFeature_)
                style = feature.get('style');
            }
            return style || this.styles[intent_];
        },
        updateFeatureStyle: function(schema, feature) {
            // See selectableModify interaction (ol4 extensions)
            // @todo: selectableModify should deal with pausing style updates itself
            if (feature.get("featureStyleDisabled")) {
                return;
            }
            if (feature.get("hidden")) {
                this.setRenderIntent(feature, 'invisible');
            } else if (feature.get("selected")) {
                this.setRenderIntent(feature, 'select');
            } else if (feature.get("modificationState")) {
                this.setRenderIntent(feature, 'unsaved');
            } else {
                this.setRenderIntent(feature, 'default');
            }
        }
    });

    Object.assign(Mapbender.Digitizer.FeatureRenderer.prototype, {
        onFeatureUpdatedOnServer: function(schema) {
            if (schema.refreshLayersAfterFeatureSave) {
                $.each(schema.refreshLayersAfterFeatureSave, function (k1, layerInstanceId) {
                    var layers = Mapbender.layerManager.getLayersByInstanceId(layerInstanceId);
                    $.each(layers, function (k2, layer) {
                        Mapbender.layerManager.refreshLayer(layer);
                    });
                });
            }

            if(schema.refreshFeaturesAfterSave){
                $.each(schema.refreshFeaturesAfterSave, function(key,schemaName){
                    schema.widget.refreshConnectedDigitizerFeatures(schemaName);
                })
            }
        }
    });

    /** @todo: should go PHP, in getSchemaConfigDefaults; less runtime merging of stuff */
    Mapbender.Digitizer.FeatureRenderer.prototype.getDefaultStyles = function () {
        return {
            default: {
                strokeWidth: 1,
                strokeColor: '#6fb536',
                fillColor: '#6fb536',
                fillOpacity: 0.3
            },
            select: {
                strokeWidth: 3,
                fillColor: '#F7F79A',
                strokeColor: '#6fb536',
                fillOpacity: 0.5,
                graphicZIndex: 15
            },
            unsaved: {
                strokeWidth: 3,
                fillColor: '#FFD14F',
                strokeColor: '#F5663C',
                fillOpacity: 0.5
            }
        };
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.getLayer = function() {
        return this.layer;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.initializeStyles_ = function (styleConfigs) {
        var styles = {};
        var keys = Object.keys(styleConfigs);
        for (var i = 0; i < keys.length; ++ i) {
            var key = keys[i];
            var styleConfig = styleConfigs[key];
            styles[key] = ol.style.StyleConverter.convertToOL4Style(styleConfig);
        }
        Object.freeze(styles.default.getFill().getColor()); // Freeze Color to prevent unpredictable behaviour
        styles.invisible = new ol.style.Style();
        return styles;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.createSchemaFeatureLayer_ = function (schema) {
        var layer = new ol.layer.Vector({
            source: new ol.source.Vector(),
            visible: true
            // HACK: disable min / max resolution and initial visibility while testing
            // @todo: reenable minScale / maxScale config evaluation
//            minResolution: Mapbender.Model.scaleToResolution(schema.maxScale || 0),
//            maxResolution: Mapbender.Model.scaleToResolution(schema.minScale || Infinity),
//            visible: false
        });
        return layer;
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.customStyleFeature_ = function (feature) {
        var schema = this;

        console.assert(!!schema.featureType.styleField, "Style Field in Feature Type is not specified");

        var jsonStyle = feature.get("data") && feature.get("data").get(schema.featureType.styleField);

        if (jsonStyle) {
            var basicStyle = JSON.parse(jsonStyle);
            var style = ol.style.StyleConverter.convertToOL4Style(basicStyle);
            feature.set("basicStyle", basicStyle);
            feature.set("style", style);
            feature.setStyle(style);
        }
    };

    Mapbender.Digitizer.FeatureRenderer.prototype.addSelectControl_ = function () {
        this.highlightControl = this.initializeHighlightControl_();
        this.selectControl = this.initializeSelectControl_();
        this.olMap.addInteraction(this.selectControl);
        this.olMap.addInteraction(this.highlightControl);
    };
    Mapbender.Digitizer.FeatureRenderer.prototype.initializeHighlightControl_ = function () {
        var highlightControl = new ol.interaction.Select({
            condition: ol.events.condition.pointerMove,
            layers: [this.layer]
        });
        highlightControl.on('select', function (e) {
            e.selected.forEach(function (feature) {
                feature.dispatchEvent({type: 'Digitizer.HoverFeature', hover: true});
            });

            e.deselected.forEach(function (feature) {
                feature.dispatchEvent({type: 'Digitizer.HoverFeature', hover: false});
            });
        });

        highlightControl.setActive(false);
        return highlightControl;
    };
    Mapbender.Digitizer.FeatureRenderer.prototype.initializeSelectControl_ = function () {
        var selectControl = new ol.interaction.Select({
            condition: ol.events.condition.singleClick,
            layers: [this.layer],
            style: function () {
                return null;
            }
        });

        var schema = this.schema;
        if (schema.allowEditData || this.schema.allowOpenEditDialog) {
            selectControl.on('select', function (event) {
                // @todo: Renderer should know about the widget
                schema.widget._openEditDialog(schema, event.selected[0]);
                selectControl.getFeatures().clear();
            });
        }
        selectControl.setActive(false);
        return selectControl;
    };
})();
<|endoftext|>


<commit_before>Ti.include('/util.js');
Ti.include('/data.js');
Ti.include('/club_data.js');

var table;

table = Util.createSimpleDataTable(clubData, {
  'table': {
    style: Ti.UI.iPhone.TableViewStyle.GROUPED
  },
  'row': { }
});

table.addEventListener('click', function (e) {
  e.rowData.backgroundColor = '#0f0';
  Data.subscribeToClub(e.rowData.title);
});

Ti.UI.currentWindow.add(table);
<commit_msg>Corrected file/variable naming.<commit_after>Ti.include('/util.js');
Ti.include('/data.js');
Ti.include('/clubs_data.js');

var table;

table = Util.createSimpleDataTable(clubsData, {
  'table': {
    style: Ti.UI.iPhone.TableViewStyle.GROUPED
  },
  'row': { }
});

table.addEventListener('click', function (e) {
  e.rowData.backgroundColor = '#0f0';
  Data.subscribeToClub(e.rowData.title);
});

Ti.UI.currentWindow.add(table);
<|endoftext|>


<commit_before>/*global module*/
module.controller('PanelCtrl', ['$scope', '$filter', '$window', 'ProxyService', 'MimeTypesService', 'focus',
	function ($scope, $filter, $window, ProxyService, MimeTypesService, focus) {

	$scope.proxyStates = {
		PROXY_NOT_CONNECTED: 'not connected',
		PROXY_COULD_NOT_START_PORT_ERROR: 'could not start port error',
		PROXY_COULD_NOT_START_LIBS_ERROR: 'could not start libs error',
		PROXY_STARTED: 'proxy started',
		PROXY_CONNECTED: 'proxy connected',
		PROXY_DISCONNECTED: 'proxy disconnected'
	};

	function onBgMessage(message) {
		switch (message.method) {
			case 'proxy-state-update':
				$scope.isProxyEnabled = message.isProxyEnabled;
				$scope.proxyState = message.proxyState;
				$scope.$digest();
				break;
			case 'update-rules':
				$scope.proxyRules = JSON.parse(localStorage.getItem('rules'));
				$scope.$digest();
				break;
		}
	}

	ProxyService.bgPort.onMessage.addListener(onBgMessage);

	/****************************/
	/********* TOOLBAR **********/
	/****************************/

	$scope.onToggleProxy = function(e) {
		$scope.isProxyEnabled = !$scope.isProxyEnabled;
		chrome.runtime.sendMessage(chrome.runtime.id, {'method': 'toggle-proxy', 'isEnabled': $scope.isProxyEnabled});
	};

	/****************************/
	/******** RULES LIST ********/
	/****************************/

	$scope.onDeleteRuleClick = function(rule) {
		$scope.proxyRules.splice($scope.proxyRules.indexOf(rule), 1);
		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
	};

	$scope.onToggleRuleEnabled = function(rule) {
		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
	};

	/****************************/
	/****** NETWORK PANEL *******/
	/****************************/

	$scope.onQuickEditClick = function(request, e) {
		if (request.error) { return; }
		// var target = e.currentTarget.parentNode;
		// if (!Utils.hasClassName(target, 'request-item')) {
		// 	target = target.parentNode;
		// }
		// var request = requests[target.id.substr(4)].request;
		// var url = target.querySelector('.request-item-url').innerText;
		var url = request.url;

		if (e.metaKey) {
			if (e.altKey) {
				window.open(url);
			} else {
				window.open('view-source:' + url);
			}
			return;
		}

		var ruleExists = false;
		var rule;
		for (var i = 0; i < $scope.proxyRules.length; i++) {
			if ($scope.proxyRules[i].url === url) {
				ruleExists = true;
				rule = $scope.proxyRules[i];
				break;
			}
		}

		if (ruleExists) {
			ProxyService.openFile(rule.cachedFilename);
		} else {
			request.status = 'loading';
			request.requestEvent.getContent(function (content, encoding) {
				request.status = 'loaded';

				if (content === null) { return; }

				var filename = $filter('getFilename')(url).replace(/\//g, '');
				if (filename.indexOf('?') > -1) {
					filename = filename.substr(0, filename.indexOf('?'));
				}

				var fileExtension;
				for (var i = 0; i < request.requestEvent.response.headers.length; i++) {
					var currentHeader = request.requestEvent.response.headers[i];
					if (currentHeader.name.toLowerCase() === 'content-type') {
						var mimeType = currentHeader.value;
						if (mimeType.indexOf(';') > -1) {
							mimeType = mimeType.substr(0, mimeType.indexOf(';'));
						}
						fileExtension = MimeTypesService.getFileExtension(mimeType);
						break;
					}
				}
				if (fileExtension) {
					if (filename.indexOf(fileExtension) !== filename.length - fileExtension.length) {
						filename += '.' + fileExtension;
					}
				} else {
					filename += '.tamper';
				}

				ProxyService.cacheResponse(filename, content).then(function (response) {
					ProxyService.openFile(response.cachedFilename);
					$scope.proxyRules.push({
						url: url,
						responseHeaders: request.requestEvent.response.headers,
						cachedFilename: response.cachedFilename,
						isEnabled: true
					});
					localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
					ProxyService.updateRules($scope.proxyRules);
					// updateRulesListView();
				});
			});
		}
	};

	$scope.onDiscardChangesClick = function(request, e) {
		// Utils.addClassName(target, 'request-item-removed');
		// var url = target.querySelector('.request-item-url').innerText;
		var url = request.url;

		for (var i = 0; i < $scope.proxyRules.length; i++) {
			if ($scope.proxyRules[i].url === url) {
				$scope.proxyRules.splice(i, 1);
				break;
			}
		}

		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
		// updateRulesListView();
	};

	function onRequestFinished(e) {
		var request = {
			url: e.request.url,
			requestEvent: e
		};

		if (e.response._error) {
			request.error = e.response._error;
		} else {
		}

		for (var i = 0; i < e.response.headers.length; i++) {
			if (e.response.headers[i].name.toLowerCase() === 'via' && e.response.headers[i].value.indexOf('tamper') > -1) {
				request.isModified = true;
				break;
			}
		}

		$scope.requests.push(request);
		console.log(request);
		$scope.$digest();
	}

	function onNavigated(e) {
		$scope.requests = [];
	}

	chrome.devtools.network.onRequestFinished.addListener(onRequestFinished);
	chrome.devtools.network.onNavigated.addListener(onNavigated);

	/****************************/
	/******** SPLIT VIEW ********/
	/****************************/

	var initX;

	$scope.onResizeMouseMove = function (e) {
		$scope.sidebarWidth = Math.min(Math.max(e.pageX - initX, 20), $window.innerWidth - 20);
		$scope.$digest();
	};

	$scope.onResizeMouseUp = function (e) {
		$scope.isResizing = false;
		$window.removeEventListener('mousemove', $scope.onResizeMouseMove);
		$window.removeEventListener('mouseup', $scope.onResizeMouseUp);
		localStorage.setItem('sidebarWidth', $scope.sidebarWidth);
		$scope.$digest();
	};

	$scope.onResizeMouseDown = function (e) {
		initX = e.offsetX;
		$scope.isResizing = true;
		$window.addEventListener('mousemove', $scope.onResizeMouseMove);
		$window.addEventListener('mouseup', $scope.onResizeMouseUp);
	};

	if (localStorage.getItem('sidebarWidth')) {
		$scope.sidebarWidth = localStorage.getItem('sidebarWidth');
	} else {
		$scope.sidebarWidth = 170;
	}

	/****************************/
	/********* SETTINGS *********/
	/****************************/

	$scope.onRestoreDefaults = function () {
		$scope.settings.editorCommandLine = localStorage.getItem('default.editorCommandLine');
		$scope.settings.pacScript = localStorage.getItem('default.pacScript');
		$scope.settings.proxyPort = localStorage.getItem('default.proxyPort');
		$scope.saveSettings();
	};

	$scope.loadSettings = function () {
		$scope.settings = {
			editorCommandLine: localStorage.getItem('editorCommandLine'),
			pacScript: localStorage.getItem('pacScript'),
			proxyPort: localStorage.getItem('proxyPort'),
			hasProxyRestarted: false
		};
	};

	$scope.saveSettings = function () {
		localStorage.setItem('editorCommandLine', $scope.settings.editorCommandLine);
		localStorage.setItem('pacScript', $scope.settings.pacScript);
		localStorage.setItem('proxyPort', $scope.settings.proxyPort);
	};

	$scope.showSettings = function () {
		$scope.isShowingSettings = true;

		$scope.loadSettings();
		$scope.$watch('settings', function() {
			$scope.saveSettings();
			ProxyService.bgPort.postMessage({
				method: 'update-settings'
			});
		}, true);
	};

	$scope.closeSettings = function () {
		$scope.isShowingSettings = false;
		$scope.saveSettings();
	};

	$scope.onRestartProxy = function () {
		ProxyService.restartProxy().then(function () {
			$scope.settings.hasProxyRestarted = true;
		});
	};

	/****************************/
	/***** KEYBOARD CONTROL *****/
	/****************************/

	$scope.onBodyKeyDown = function(e) {
		if (e.shiftKey && e.keyCode === 191) {
			if (document.activeElement.tagName !== 'input' && document.activeElement.tagName !== 'textarea') {
				$scope.showSettings();
			}
		} else if ((e.metaKey || e.ctrlKey) && e.keyCode === 70) {
			focus('focusFilter');
			e.stopPropagation();
			e.preventDefault();
		} else if (e.keyCode === 27) {
			$scope.requestFilter = null;
			$scope.closeSettings();
			e.preventDefault();
			e.stopPropagation();
		}
	};

	/****************************/
	/*********** INIT ***********/
	/****************************/

	$scope.proxyRules = localStorage.getItem('rules');
	if (!$scope.proxyRules) {
		$scope.proxyRules = [];
	} else {
		$scope.proxyRules = JSON.parse($scope.proxyRules);
	}

	$scope.requests = [];

	var mitmproxyExtensionVersion = localStorage.getItem('mitmproxyExtensionVersion');
	if (mitmproxyExtensionVersion) {
		mitmproxyExtensionVersion = mitmproxyExtensionVersion.split('.');
		var chromeExtensionVersion = chrome.runtime.getManifest().version.split('.');

		if (mitmproxyExtensionVersion[0] !== chromeExtensionVersion[0] ||
			mitmproxyExtensionVersion[1] !== chromeExtensionVersion[1]) {
			$scope.updateAvailable = true;
		}
	}

	if ($window.navigator.appVersion.match(/OS X/)) {
		$scope.isOSX = true;
	} else if ($window.navigator.appVersion.match(/win/i)) {
		$scope.isWindows = true;
	}
}]);
<commit_msg>Cleaned up code<commit_after>/*global module*/
module.controller('PanelCtrl', ['$scope', '$filter', '$window', 'ProxyService', 'MimeTypesService', 'focus',
	function ($scope, $filter, $window, ProxyService, MimeTypesService, focus) {

	$scope.proxyStates = {
		PROXY_NOT_CONNECTED: 'not connected',
		PROXY_COULD_NOT_START_PORT_ERROR: 'could not start port error',
		PROXY_COULD_NOT_START_LIBS_ERROR: 'could not start libs error',
		PROXY_STARTED: 'proxy started',
		PROXY_CONNECTED: 'proxy connected',
		PROXY_DISCONNECTED: 'proxy disconnected'
	};

	function onBgMessage(message) {
		switch (message.method) {
			case 'proxy-state-update':
				$scope.isProxyEnabled = message.isProxyEnabled;
				$scope.proxyState = message.proxyState;
				$scope.$digest();
				break;
			case 'update-rules':
				$scope.proxyRules = JSON.parse(localStorage.getItem('rules'));
				$scope.$digest();
				break;
		}
	}

	ProxyService.bgPort.onMessage.addListener(onBgMessage);

	/****************************/
	/********* TOOLBAR **********/
	/****************************/

	$scope.onToggleProxy = function(e) {
		$scope.isProxyEnabled = !$scope.isProxyEnabled;
		chrome.runtime.sendMessage(chrome.runtime.id, {'method': 'toggle-proxy', 'isEnabled': $scope.isProxyEnabled});
	};

	/****************************/
	/******** RULES LIST ********/
	/****************************/

	$scope.onDeleteRuleClick = function(rule) {
		$scope.proxyRules.splice($scope.proxyRules.indexOf(rule), 1);
		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
	};

	$scope.onToggleRuleEnabled = function(rule) {
		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
	};

	/****************************/
	/****** NETWORK PANEL *******/
	/****************************/

	$scope.onQuickEditClick = function(request, e) {
		if (request.error) { return; }

		var url = request.url;

		if (e.metaKey) {
			if (e.altKey) {
				window.open(url);
			} else {
				window.open('view-source:' + url);
			}
			return;
		}

		var ruleExists = false;
		var rule;
		for (var i = 0; i < $scope.proxyRules.length; i++) {
			if ($scope.proxyRules[i].url === url) {
				ruleExists = true;
				rule = $scope.proxyRules[i];
				break;
			}
		}

		if (ruleExists) {
			ProxyService.openFile(rule.cachedFilename);
		} else {
			request.status = 'loading';
			request.requestEvent.getContent(function (content, encoding) {
				request.status = 'loaded';

				if (content === null) { return; }

				var filename = $filter('getFilename')(url).replace(/\//g, '');
				if (filename.indexOf('?') > -1) {
					filename = filename.substr(0, filename.indexOf('?'));
				}

				var fileExtension;
				for (var i = 0; i < request.requestEvent.response.headers.length; i++) {
					var currentHeader = request.requestEvent.response.headers[i];
					if (currentHeader.name.toLowerCase() === 'content-type') {
						var mimeType = currentHeader.value;
						if (mimeType.indexOf(';') > -1) {
							mimeType = mimeType.substr(0, mimeType.indexOf(';'));
						}
						fileExtension = MimeTypesService.getFileExtension(mimeType);
						break;
					}
				}
				if (fileExtension) {
					if (filename.indexOf(fileExtension) !== filename.length - fileExtension.length) {
						filename += '.' + fileExtension;
					}
				} else {
					filename += '.tamper';
				}

				ProxyService.cacheResponse(filename, content).then(function (response) {
					ProxyService.openFile(response.cachedFilename);
					$scope.proxyRules.push({
						url: url,
						responseHeaders: request.requestEvent.response.headers,
						cachedFilename: response.cachedFilename,
						isEnabled: true
					});
					localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
					ProxyService.updateRules($scope.proxyRules);
					// updateRulesListView();
				});
			});
		}
	};

	$scope.onDiscardChangesClick = function(request, e) {
		var url = request.url;

		for (var i = 0; i < $scope.proxyRules.length; i++) {
			if ($scope.proxyRules[i].url === url) {
				$scope.proxyRules.splice(i, 1);
				break;
			}
		}

		localStorage.setItem('rules', JSON.stringify($scope.proxyRules));
		ProxyService.updateRules($scope.proxyRules);
	};

	function onRequestFinished(e) {
		var request = {
			url: e.request.url,
			requestEvent: e
		};

		if (e.response._error) {
			request.error = e.response._error;
		} else {
		}

		for (var i = 0; i < e.response.headers.length; i++) {
			if (e.response.headers[i].name.toLowerCase() === 'via' && e.response.headers[i].value.indexOf('tamper') > -1) {
				request.isModified = true;
				break;
			}
		}

		$scope.requests.push(request);
		console.log(request);
		$scope.$digest();
	}

	function onNavigated(e) {
		$scope.requests = [];
	}

	chrome.devtools.network.onRequestFinished.addListener(onRequestFinished);
	chrome.devtools.network.onNavigated.addListener(onNavigated);

	/****************************/
	/******** SPLIT VIEW ********/
	/****************************/

	var initX;

	$scope.onResizeMouseMove = function (e) {
		$scope.sidebarWidth = Math.min(Math.max(e.pageX - initX, 20), $window.innerWidth - 20);
		$scope.$digest();
	};

	$scope.onResizeMouseUp = function (e) {
		$scope.isResizing = false;
		$window.removeEventListener('mousemove', $scope.onResizeMouseMove);
		$window.removeEventListener('mouseup', $scope.onResizeMouseUp);
		localStorage.setItem('sidebarWidth', $scope.sidebarWidth);
		$scope.$digest();
	};

	$scope.onResizeMouseDown = function (e) {
		initX = e.offsetX;
		$scope.isResizing = true;
		$window.addEventListener('mousemove', $scope.onResizeMouseMove);
		$window.addEventListener('mouseup', $scope.onResizeMouseUp);
	};

	if (localStorage.getItem('sidebarWidth')) {
		$scope.sidebarWidth = localStorage.getItem('sidebarWidth');
	} else {
		$scope.sidebarWidth = 170;
	}

	/****************************/
	/********* SETTINGS *********/
	/****************************/

	$scope.onRestoreDefaults = function () {
		$scope.settings.editorCommandLine = localStorage.getItem('default.editorCommandLine');
		$scope.settings.pacScript = localStorage.getItem('default.pacScript');
		$scope.settings.proxyPort = localStorage.getItem('default.proxyPort');
		$scope.saveSettings();
	};

	$scope.loadSettings = function () {
		$scope.settings = {
			editorCommandLine: localStorage.getItem('editorCommandLine'),
			pacScript: localStorage.getItem('pacScript'),
			proxyPort: localStorage.getItem('proxyPort'),
			hasProxyRestarted: false
		};
	};

	$scope.saveSettings = function () {
		localStorage.setItem('editorCommandLine', $scope.settings.editorCommandLine);
		localStorage.setItem('pacScript', $scope.settings.pacScript);
		localStorage.setItem('proxyPort', $scope.settings.proxyPort);
	};

	$scope.showSettings = function () {
		$scope.isShowingSettings = true;

		$scope.loadSettings();
		$scope.$watch('settings', function() {
			$scope.saveSettings();
			ProxyService.bgPort.postMessage({
				method: 'update-settings'
			});
		}, true);
	};

	$scope.closeSettings = function () {
		$scope.isShowingSettings = false;
		$scope.saveSettings();
	};

	$scope.onRestartProxy = function () {
		ProxyService.restartProxy().then(function () {
			$scope.settings.hasProxyRestarted = true;
		});
	};

	/****************************/
	/***** KEYBOARD CONTROL *****/
	/****************************/

	$scope.onBodyKeyDown = function(e) {
		if (e.shiftKey && e.keyCode === 191) {
			if (document.activeElement.tagName !== 'input' && document.activeElement.tagName !== 'textarea') {
				$scope.showSettings();
			}
		} else if ((e.metaKey || e.ctrlKey) && e.keyCode === 70) {
			focus('focusFilter');
			e.stopPropagation();
			e.preventDefault();
		} else if (e.keyCode === 27) {
			$scope.requestFilter = null;
			$scope.closeSettings();
			e.preventDefault();
			e.stopPropagation();
		}
	};

	/****************************/
	/*********** INIT ***********/
	/****************************/

	$scope.proxyRules = localStorage.getItem('rules');
	if (!$scope.proxyRules) {
		$scope.proxyRules = [];
	} else {
		$scope.proxyRules = JSON.parse($scope.proxyRules);
	}

	$scope.requests = [];

	var mitmproxyExtensionVersion = localStorage.getItem('mitmproxyExtensionVersion');
	if (mitmproxyExtensionVersion) {
		mitmproxyExtensionVersion = mitmproxyExtensionVersion.split('.');
		var chromeExtensionVersion = chrome.runtime.getManifest().version.split('.');

		if (mitmproxyExtensionVersion[0] !== chromeExtensionVersion[0] ||
			mitmproxyExtensionVersion[1] !== chromeExtensionVersion[1]) {
			$scope.updateAvailable = true;
		}
	}

	if ($window.navigator.appVersion.match(/OS X/)) {
		$scope.isOSX = true;
	} else if ($window.navigator.appVersion.match(/win/i)) {
		$scope.isWindows = true;
	}
}]);
<|endoftext|>