<commit_before>(function(window, document, undefined) {
    "use strict";

	angular.module('angularWidgets').factory('widgetBase', ['$parse', '$interpolate', '$animate', '$q', '$http', WidgetBaseFactory]);

	function WidgetBaseFactory($parse, $interpolate, $animate, $q, $http) {

		AngularWidgets.$q = $q;
		AngularWidgets.$http = $http;

    	var widgetBase = {};

    	widgetBase.handleOnEnterKey = function(scope, element, onEnterKeyHandle) {

			if (onEnterKeyHandle !== undefined) {
				element.bind('keyup', function(e) {

					var keyCode = widgetBase.keyCode,
						key = e.which;

					if (key === keyCode.ENTER) {
						scope.safeApply(function() {
							onEnterKeyHandle();
						});
						e.preventDefault();
					}
				});
			}
    	}

    	widgetBase.getModelValue = function(scope, model) {
			var parseValue = $parse(model);
			return parseValue(scope);
    	}

		widgetBase.setModelValue = function(scope, model, value) {
            scope.safeApply(function() {
            	var parseValue = $parse(model);
            	parseValue.assign(scope, value);
           	});
		};

    	widgetBase.verifyRequiredOptions = function(widget, requiredOptions) {

    		requiredOptions = angular.isArray(requiredOptions) ? requiredOptions : [requiredOptions];

    		angular.forEach(requiredOptions, function(requiredOption) {
    			if (!widget.element.attr(requiredOption)) {
    				throw new Error('The attribute ' + requiredOption + ' is required!');
    			}
    		});
    	};

    	widgetBase.createWidget = function (widgetChild) {

 			var baseWidget = function(scope, element, options) {
 				this.scope = scope;
 				this.element = element;
 				this.init(options);
 				this.element.data('$widget', this);
 			};

 			baseWidget.prototype = widgetChild;

 			return baseWidget;
     	};

    	widgetBase.createBindAndAssignIfNecessary = function(widget, properties) {

    		var arrayProperties = properties.split(",");
    		widget.bindInstance = {};

    		for (var i=0, t=arrayProperties.length; i<t; i++) {
    			widget.bindInstance[arrayProperties[i]] = widget[arrayProperties[i]].bind(widget);
    		}

    		if (widget.options.binding) {
    			var parseValue = $parse(widget.options.binding);
                parseValue.assign(widget.scope.$parent, widget.bindInstance);
                widget.scope.safeApply();
    		}

    		var id = widget.element.attr('id');

			if (id) {
				AngularWidgets.putWidget(id, widget.bindInstance);
			}
    	};

    	widgetBase.determineOptions = function(scope, optionsDefault, optionsInline, fctOptions, expressions) {

			expressions = expressions !== undefined ? expressions : [];

        	var dynamicOptions = optionsInline.options ? scope.$eval(optionsInline.options) : {};

        	var options = angular.extend({}, optionsInline, dynamicOptions);

        	// Equalize options names and types
    		for (var optName in optionsDefault) {

    			// Equalize options names
    			var optNameLc = optName.toLowerCase();

    			if (optNameLc != optName && options[optNameLc]) {
    				options[optName] = options[optNameLc];
    				delete(options[optNameLc]);
    			}

				// Eval expressions
    			if (expressions.indexOf(optName) !== -1) {
					options[optName] = scope.$eval(options[optName]);
    			}

				// Equarlize options types
				if (options[optName] !== undefined) {

					var tod = typeof optionsDefault[optName];
					var toi = typeof options[optName];

					if (angular.isNumber(optionsDefault[optName])) {
						options[optName] = parseFloat(options[optName]);
					}
					else if (tod === 'boolean' && toi !== 'boolean') {
						options[optName] = (/^(true|1|yes)$/i).test(options[optName]);
					}
				}
    		}

			options = angular.extend({}, optionsDefault, options);

    		if (fctOptions) {
	    		for (var i=0, t=fctOptions.length; i<t; i++) {
	    			var fctOption = fctOptions[i];
	    			if (options[fctOption] && angular.isString(options[fctOption])) {
    					options[fctOption] =  scope.$eval(options[fctOption]);
	    			}
	    		}
    		}

    		return options;
    	};

    	widgetBase.determineDataSource = function(value) {

			var dataLoader;

    		if (angular.isString(value)) {
				dataLoader = new AngularWidgets.HttpDataSource({url: value});
			}
			else if (angular.isFunction(value)) {
				dataLoader = new AngularWidgets.FunctionDataSource(value);
			}
			else if (value instanceof AngularWidgets.HttpDataSource || value instanceof AngularWidgets.ArrayDataSource) {
				dataLoader = value;
			}
			else if (angular.isArray(value)) {
				dataLoader = new AngularWidgets.ArrayDataSource(value);
			}
			else {
				dataLoader = new AngularWidgets.ArrayDataSource([value]);
			}

			return dataLoader;
    	};

    	widgetBase.extend = function(target, source) {

    		target = target || {};

    		for (var prop in source) {
   				target[prop] = source[prop];
    		}

    		return target;
    	};

    	widgetBase.isWindow = function (obj) {
    		  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
    	};

    	widgetBase.isArrayLike = function (obj) {

    	  if (obj === null || widgetBase.isWindow(obj)) {
    	    return false;
    	  }

    	  var length = obj.length;

    	  if (obj.nodeType === 1 && length) {
    	    return true;
    	  }

    	  return angular.isString(obj) || angular.isArray(obj) || length === 0 ||
    	         typeof length === 'number' && length > 0 && (length - 1) in obj;
    	};

        widgetBase.hoverAndFocus = function (element) {

        	var items = angular.isArray(element) || widgetBase.isArrayLike(element) ? element : [].concat(element);

        	angular.forEach(items, function (item) {

				var elem = angular.element(item);

        		elem.hover(function () {
                    var element = angular.element(this);
                    if (!element.hasClass('ui-state-active') && !element.hasClass('ui-state-disabled')) {
                        element.addClass('ui-state-hover');
                    }
                },
                function () {
                    var element = angular.element(this);
					element.removeClass('ui-state-hover');
                });

        		elem.focus(function () {
        			var element = angular.element(this);
        			if (!element.hasClass('ui-state-disabled')) {
                        element.addClass('ui-state-focus');
                    }
                });

        		elem.blur(function () {
        			var element = angular.element(this);
        			element.removeClass('ui-state-focus');
                });
            });
        };

        widgetBase.mouseDownAndUp = function (element, onMouseupCallback) {

        	var items = angular.isArray(element) ? element : [].concat(element);

            angular.forEach(items, function (item) {

            	item.mousedown(function() {
            		if(!element.hasClass('ui-state-disabled')) {
            			element.removeClass('ui-state-hover').addClass('ui-state-active');
            		}
            	});

            	item.mouseup(function(e) {

            		element.removeClass('ui-state-active').addClass('ui-state-hover');

            		if (onMouseupCallback) {
            			onMouseupCallback(e);
            		}
            	});
            });
        };

        widgetBase.onKeydownEnterOrSpace = function(element, onKeydownCallback) {

        	var items = angular.isArray(element) ? element : [].concat(element);

            angular.forEach(items, function (item) {

            	item.bind('keydown', function(e) {
            		if(e.keyCode == widgetBase.keyCode.SPACE || e.keyCode == widgetBase.keyCode.ENTER || e.keyCode == widgetBase.keyCode.NUMPAD_ENTER) {
            			onKeydownCallback(e);
            		}
            	});
            });
        };

        widgetBase.supportHighlight = function (element) {
            var items = angular.isArray(element) ? element : [].concat(element);
            angular.forEach(items, function (item) {

                item.hover(function () {
                    var $this = angular.element(this);
                    $this.toggleClass('ui-state-highlight');
                });

            });

        };

        widgetBase.resetHoverAndFocus = function (element) {
        	element = angular.element(element);
            element.unbind("mouseenter");
            element.unbind("mouseleave");
            element.unbind("focus");
            element.unbind("blur");
        };

        widgetBase.hideWithAnimation = function(element, doneCallback) {
            $animate.addClass(element, 'pui-hide', doneCallback);
        };

        widgetBase.showWithAnimation = function(element, doneCallback) {
            $animate.removeClass(element, 'pui-hide', doneCallback);
        };

        widgetBase.slideUp = function(element, duration, doneCallback) {
        	element.hide();
        	if (doneCallback) doneCallback();
        };

        widgetBase.slideDown = function(element, duration, doneCallback) {
        	element.show();
        	if (doneCallback) doneCallback();
        };

        widgetBase.fadeOut = function (element, duration, doneCallback) {
        	element.hide();
        	if (doneCallback) doneCallback();
        };

        widgetBase.fadeIn = function (element, duration, doneCallback) {
        	element.show();
        	if (doneCallback) doneCallback();
        };

        widgetBase.isVisible = function (element) {
        	return AngularWidgets.isVisible(element);
		};

    	widgetBase.watchExpression = function(scope, expression, watchFunction) {

			var parsedExpression = $interpolate(expression),
				watches = [];

			angular.forEach(parsedExpression.expressions, function (part) {
				watches.push(part);
			}, watches);

			angular.forEach(watches, function(watchValue) {
				scope.$watch(watchValue, function (value) {
					watchFunction(parsedExpression(scope));
				});
			});

    		watchFunction(parsedExpression(scope));
       	};

        widgetBase.getExpression = function(element, property) {
           return element[0].attributes[property].value;
        };

        widgetBase.keyCode = {
            BACKSPACE: 8,
            TAB: 9,
            SHIFT: 16,
            CTRL: 17,
            PLUS: 171,
            COMMA: 188,
            DASH: 189,
            DOT: 190,
            DELETE: 46,
            ENTER: 13,
            ESCAPE: 27,
            HOME: 36,
            END: 35,
            NUMPAD_MULTIPLY: 106,
            NUMPAD_ADD: 107,
            NUMPAD_ENTER: 108,
            NUMPAD_SUBTRACT: 109,
            NUMPAD_DECIMAL: 110,
            NUMPAD_DIVIDE: 111,
            PAGE_DOWN: 34,
            PAGE_UP: 33,
            PERIOD: 190,
            SPACE: 32,
            ARROWS: [37,38,39,40],
			LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            NUMERICS: [48,49,50,51,52,53,54,55,56,57, 96,97,98,99,100,101,102,103,104,105]
        };

    	return widgetBase;
	}

}(window, document));<commit_msg>Correções do jslint<commit_after>(function(window, document, undefined) {
    "use strict";

	angular.module('angularWidgets').factory('widgetBase', ['$parse', '$interpolate', '$animate', '$q', '$http', WidgetBaseFactory]);

	function WidgetBaseFactory($parse, $interpolate, $animate, $q, $http) {

		AngularWidgets.$q = $q;
		AngularWidgets.$http = $http;

    	var widgetBase = {};

    	widgetBase.handleOnEnterKey = function(scope, element, onEnterKeyHandle) {

			if (onEnterKeyHandle !== undefined) {
				element.bind('keyup', function(e) {

					var keyCode = widgetBase.keyCode,
						key = e.which;

					if (key === keyCode.ENTER) {
						scope.safeApply(function() {
							onEnterKeyHandle();
						});
						e.preventDefault();
					}
				});
			}
    	};

    	widgetBase.getModelValue = function(scope, model) {
			var parseValue = $parse(model);
			return parseValue(scope);
    	};

		widgetBase.setModelValue = function(scope, model, value) {
            scope.safeApply(function() {
            	var parseValue = $parse(model);
            	parseValue.assign(scope, value);
           	});
		};

    	widgetBase.verifyRequiredOptions = function(widget, requiredOptions) {

    		requiredOptions = angular.isArray(requiredOptions) ? requiredOptions : [requiredOptions];

    		angular.forEach(requiredOptions, function(requiredOption) {
    			if (!widget.element.attr(requiredOption)) {
    				throw new Error('The attribute ' + requiredOption + ' is required!');
    			}
    		});
    	};

    	widgetBase.createWidget = function (widgetChild) {

 			var baseWidget = function(scope, element, options) {
 				this.scope = scope;
 				this.element = element;
 				this.init(options);
 				this.element.data('$widget', this);
 			};

 			baseWidget.prototype = widgetChild;

 			return baseWidget;
     	};

    	widgetBase.createBindAndAssignIfNecessary = function(widget, properties) {

    		var arrayProperties = properties.split(",");
    		widget.bindInstance = {};

    		for (var i=0, t=arrayProperties.length; i<t; i++) {
    			widget.bindInstance[arrayProperties[i]] = widget[arrayProperties[i]].bind(widget);
    		}

    		if (widget.options.binding) {
    			var parseValue = $parse(widget.options.binding);
                parseValue.assign(widget.scope.$parent, widget.bindInstance);
                widget.scope.safeApply();
    		}

    		var id = widget.element.attr('id');

			if (id) {
				AngularWidgets.putWidget(id, widget.bindInstance);
			}
    	};

    	widgetBase.determineOptions = function(scope, optionsDefault, optionsInline, fctOptions, expressions) {

			expressions = expressions !== undefined ? expressions : [];

        	var dynamicOptions = optionsInline.options ? scope.$eval(optionsInline.options) : {};

        	var options = angular.extend({}, optionsInline, dynamicOptions);

        	// Equalize options names and types
    		for (var optName in optionsDefault) {

    			// Equalize options names
    			var optNameLc = optName.toLowerCase();

    			if (optNameLc != optName && options[optNameLc]) {
    				options[optName] = options[optNameLc];
    				delete(options[optNameLc]);
    			}

				// Eval expressions
    			if (expressions.indexOf(optName) !== -1) {
					options[optName] = scope.$eval(options[optName]);
    			}

				// Equarlize options types
				if (options[optName] !== undefined) {

					var tod = typeof optionsDefault[optName];
					var toi = typeof options[optName];

					if (angular.isNumber(optionsDefault[optName])) {
						options[optName] = parseFloat(options[optName]);
					}
					else if (tod === 'boolean' && toi !== 'boolean') {
						options[optName] = (/^(true|1|yes)$/i).test(options[optName]);
					}
				}
    		}

			options = angular.extend({}, optionsDefault, options);

    		if (fctOptions) {
	    		for (var i=0, t=fctOptions.length; i<t; i++) {
	    			var fctOption = fctOptions[i];
	    			if (options[fctOption] && angular.isString(options[fctOption])) {
    					options[fctOption] =  scope.$eval(options[fctOption]);
	    			}
	    		}
    		}

    		return options;
    	};

    	widgetBase.determineDataSource = function(value) {

			var dataLoader;

    		if (angular.isString(value)) {
				dataLoader = new AngularWidgets.HttpDataSource({url: value});
			}
			else if (angular.isFunction(value)) {
				dataLoader = new AngularWidgets.FunctionDataSource(value);
			}
			else if (value instanceof AngularWidgets.HttpDataSource || value instanceof AngularWidgets.ArrayDataSource) {
				dataLoader = value;
			}
			else if (angular.isArray(value)) {
				dataLoader = new AngularWidgets.ArrayDataSource(value);
			}
			else {
				dataLoader = new AngularWidgets.ArrayDataSource([value]);
			}

			return dataLoader;
    	};

    	widgetBase.extend = function(target, source) {

    		target = target || {};

    		for (var prop in source) {
   				target[prop] = source[prop];
    		}

    		return target;
    	};

    	widgetBase.isWindow = function (obj) {
    		  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
    	};

    	widgetBase.isArrayLike = function (obj) {

    	  if (obj === null || widgetBase.isWindow(obj)) {
    	    return false;
    	  }

    	  var length = obj.length;

    	  if (obj.nodeType === 1 && length) {
    	    return true;
    	  }

    	  return angular.isString(obj) || angular.isArray(obj) || length === 0 ||
    	         typeof length === 'number' && length > 0 && (length - 1) in obj;
    	};

        widgetBase.hoverAndFocus = function (element) {

        	var items = angular.isArray(element) || widgetBase.isArrayLike(element) ? element : [].concat(element);

        	angular.forEach(items, function (item) {

				var elem = angular.element(item);

        		elem.hover(function () {
                    var element = angular.element(this);
                    if (!element.hasClass('ui-state-active') && !element.hasClass('ui-state-disabled')) {
                        element.addClass('ui-state-hover');
                    }
                },
                function () {
                    var element = angular.element(this);
					element.removeClass('ui-state-hover');
                });

        		elem.focus(function () {
        			var element = angular.element(this);
        			if (!element.hasClass('ui-state-disabled')) {
                        element.addClass('ui-state-focus');
                    }
                });

        		elem.blur(function () {
        			var element = angular.element(this);
        			element.removeClass('ui-state-focus');
                });
            });
        };

        widgetBase.mouseDownAndUp = function (element, onMouseupCallback) {

        	var items = angular.isArray(element) ? element : [].concat(element);

            angular.forEach(items, function (item) {

            	item.mousedown(function() {
            		if(!element.hasClass('ui-state-disabled')) {
            			element.removeClass('ui-state-hover').addClass('ui-state-active');
            		}
            	});

            	item.mouseup(function(e) {

            		element.removeClass('ui-state-active').addClass('ui-state-hover');

            		if (onMouseupCallback) {
            			onMouseupCallback(e);
            		}
            	});
            });
        };

        widgetBase.onKeydownEnterOrSpace = function(element, onKeydownCallback) {

        	var items = angular.isArray(element) ? element : [].concat(element);

            angular.forEach(items, function (item) {

            	item.bind('keydown', function(e) {
            		if(e.keyCode == widgetBase.keyCode.SPACE || e.keyCode == widgetBase.keyCode.ENTER || e.keyCode == widgetBase.keyCode.NUMPAD_ENTER) {
            			onKeydownCallback(e);
            		}
            	});
            });
        };

        widgetBase.supportHighlight = function (element) {
            var items = angular.isArray(element) ? element : [].concat(element);
            angular.forEach(items, function (item) {

                item.hover(function () {
                    var $this = angular.element(this);
                    $this.toggleClass('ui-state-highlight');
                });

            });

        };

        widgetBase.resetHoverAndFocus = function (element) {
        	element = angular.element(element);
            element.unbind("mouseenter");
            element.unbind("mouseleave");
            element.unbind("focus");
            element.unbind("blur");
        };

        widgetBase.hideWithAnimation = function(element, doneCallback) {
            $animate.addClass(element, 'pui-hide', doneCallback);
        };

        widgetBase.showWithAnimation = function(element, doneCallback) {
            $animate.removeClass(element, 'pui-hide', doneCallback);
        };

        widgetBase.slideUp = function(element, duration, doneCallback) {
        	element.hide();
        	if (doneCallback) doneCallback();
        };

        widgetBase.slideDown = function(element, duration, doneCallback) {
        	element.show();
        	if (doneCallback) doneCallback();
        };

        widgetBase.fadeOut = function (element, duration, doneCallback) {
        	element.hide();
        	if (doneCallback) doneCallback();
        };

        widgetBase.fadeIn = function (element, duration, doneCallback) {
        	element.show();
        	if (doneCallback) doneCallback();
        };

        widgetBase.isVisible = function (element) {
        	return AngularWidgets.isVisible(element);
		};

    	widgetBase.watchExpression = function(scope, expression, watchFunction) {

			var parsedExpression = $interpolate(expression),
				watches = [];

			angular.forEach(parsedExpression.expressions, function (part) {
				watches.push(part);
			}, watches);

			angular.forEach(watches, function(watchValue) {
				scope.$watch(watchValue, function (value) {
					watchFunction(parsedExpression(scope));
				});
			});

    		watchFunction(parsedExpression(scope));
       	};

        widgetBase.getExpression = function(element, property) {
           return element[0].attributes[property].value;
        };

        widgetBase.keyCode = {
            BACKSPACE: 8,
            TAB: 9,
            SHIFT: 16,
            CTRL: 17,
            PLUS: 171,
            COMMA: 188,
            DASH: 189,
            DOT: 190,
            DELETE: 46,
            ENTER: 13,
            ESCAPE: 27,
            HOME: 36,
            END: 35,
            NUMPAD_MULTIPLY: 106,
            NUMPAD_ADD: 107,
            NUMPAD_ENTER: 108,
            NUMPAD_SUBTRACT: 109,
            NUMPAD_DECIMAL: 110,
            NUMPAD_DIVIDE: 111,
            PAGE_DOWN: 34,
            PAGE_UP: 33,
            PERIOD: 190,
            SPACE: 32,
            ARROWS: [37,38,39,40],
			LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            NUMERICS: [48,49,50,51,52,53,54,55,56,57, 96,97,98,99,100,101,102,103,104,105]
        };

    	return widgetBase;
	}

}(window, document));<|endoftext|>


<commit_before>///import core
///commands 当输入内容超过编辑器高度时，编辑器自动增高
///commandsName  AutoHeight,autoHeightEnabled
///commandsTitle  自动增高
/**
 * @description 自动伸展
 * @author zhanyi
 */
UE.plugins['autoheight'] = function () {
    var me = this;
    //提供开关，就算加载也可以关闭
    me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
    if (!me.autoHeightEnabled) {
        return;
    }

    var bakOverflow,
        lastHeight = 0,
        options = me.options,
        currentHeight,
        timer;

    function adjustHeight() {
        var me = this;
        clearTimeout(timer);
        if(isFullscreen)return;
        if (!me.queryCommandState || me.queryCommandState && me.queryCommandState('source') != 1) {
            timer = setTimeout(function(){

                var node = me.body.lastChild;
                while(node && node.nodeType != 1){
                    node = node.previousSibling;
                }
                if(node && node.nodeType == 1){
                    node.style.clear = 'both';
                    currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25 ,Math.max(options.minFrameHeight, options.initialFrameHeight)) ;
                    if (currentHeight != lastHeight) {
                        if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
                            me.iframe.parentNode.style.height = currentHeight + 'px';
                        }
                        me.body.style.height = currentHeight + 'px';
                        lastHeight = currentHeight;
                    }
                    domUtils.removeStyle(node,'clear');
                }

            },50)
        }
    }
    var isFullscreen;
    me.addListener('fullscreenchanged',function(cmd,f){
        isFullscreen = f
    });
    me.addListener('destroy', function () {
        me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight)
    });
    me.enableAutoHeight = function () {
        var me = this;
        if (!me.autoHeightEnabled) {
            return;
        }
        var doc = me.document;
        me.autoHeightEnabled = true;
        bakOverflow = doc.body.style.overflowY;
        doc.body.style.overflowY = 'hidden';
        me.addListener('contentchange afterinserthtml keyup mouseup',adjustHeight);
        //ff不给事件算得不对

        setTimeout(function () {
            adjustHeight.call(me);
        }, browser.gecko ? 100 : 0);
        me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };
    me.disableAutoHeight = function () {

        me.body.style.overflowY = bakOverflow || '';

        me.removeListener('contentchange', adjustHeight);
        me.removeListener('keyup', adjustHeight);
        me.removeListener('mouseup', adjustHeight);
        me.autoHeightEnabled = false;
        me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };

    me.on('setHeight',function(){
        me.disableAutoHeight()
    });
    me.addListener('ready', function () {
        me.enableAutoHeight();
        //trace:1764
        var timer;
        domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () {
            clearTimeout(timer);
            timer = setTimeout(function () {
                //trace:3681
                adjustHeight.call(me);
            }, 100);

        });
        //修复内容过多时，回到顶部，顶部内容被工具栏遮挡问题
        var lastScrollY;
        window.onscroll = function(){
            if(lastScrollY === null){
                lastScrollY = this.scrollY
            }else if(this.scrollY == 0 && lastScrollY != 0){
                me.window.scrollTo(0,0);
                lastScrollY = null;
            }
        }
    });

};

<commit_msg>fix(ueditor): fix ueditor exception<commit_after>///import core
///commands 当输入内容超过编辑器高度时，编辑器自动增高
///commandsName  AutoHeight,autoHeightEnabled
///commandsTitle  自动增高
/**
 * @description 自动伸展
 * @author zhanyi
 */
UE.plugins['autoheight'] = function () {
    var me = this;
    //提供开关，就算加载也可以关闭
    me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
    if (!me.autoHeightEnabled) {
        return;
    }

    var bakOverflow,
        lastHeight = 0,
        options = me.options,
        currentHeight,
        timer;

    function adjustHeight() {
        var me = this;
        clearTimeout(timer);
        if(isFullscreen)return;
        if (!me.queryCommandState || me.queryCommandState && me.queryCommandState('source') != 1) {
            timer = setTimeout(function(){

                var node = me.body.lastChild;
                while(node && node.nodeType != 1){
                    node = node.previousSibling;
                }
                if(node && node.nodeType == 1){
                    node.style.clear = 'both';
                    currentHeight = Math.max(domUtils.getXY(node).y + node.offsetHeight + 25 ,Math.max(options.minFrameHeight, options.initialFrameHeight)) ;
                    if (currentHeight != lastHeight) {
                        if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
                            me.iframe.parentNode.style.height = currentHeight + 'px';
                        }
                        me.body.style.height = currentHeight + 'px';
                        lastHeight = currentHeight;
                    }
                    domUtils.removeStyle(node,'clear');
                }

            },50)
        }
    }
    var isFullscreen;
    me.addListener('fullscreenchanged',function(cmd,f){
        isFullscreen = f
    });
    me.addListener('destroy', function () {
        me.removeListener('contentchange afterinserthtml keyup mouseup',adjustHeight)
    });
    me.enableAutoHeight = function () {
        var me = this;
        if (!me.autoHeightEnabled) {
            return;
        }
        var doc = me.document;
        me.autoHeightEnabled = true;
        bakOverflow = doc.body.style.overflowY;
        doc.body.style.overflowY = 'hidden';
        me.addListener('contentchange afterinserthtml keyup mouseup',adjustHeight);
        //ff不给事件算得不对

        setTimeout(function () {
            adjustHeight.call(me);
        }, browser.gecko ? 100 : 0);
        me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };
    me.disableAutoHeight = function () {

        me.body.style.overflowY = bakOverflow || '';

        me.removeListener('contentchange', adjustHeight);
        me.removeListener('keyup', adjustHeight);
        me.removeListener('mouseup', adjustHeight);
        me.autoHeightEnabled = false;
        me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };

    me.on('setHeight',function(){
        me.disableAutoHeight()
    });
    me.addListener('ready', function () {
        me.enableAutoHeight();
        //trace:1764
        var timer;
        domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () {
            clearTimeout(timer);
            timer = setTimeout(function () {
                //trace:3681
                adjustHeight.call(me);
            }, 100);

        });
        //修复内容过多时，回到顶部，顶部内容被工具栏遮挡问题
        var lastScrollY;
        window.onscroll = function(){
          if (me.window === undefined) return;
            if(lastScrollY === null){
                lastScrollY = this.scrollY
            }else if(this.scrollY == 0 && lastScrollY != 0){
                me.window.scrollTo(0,0);
                lastScrollY = null;
            }
        }
    });

};
<|endoftext|>


<commit_before>'use strict';

angular.module('Teem')
  .directive('join', function() {
    return {
      controller: [
      '$scope', '$element', 'SessionSvc', '$timeout', '$analytics', 'SharedState',
      function($scope, $element, SessionSvc, $timeout, $analytics, SharedState) {

        $element.on('click', function() {

          if (!$scope.project.isParticipant()){
            if ($scope.joinModal) {
              SharedState.set('modal.join', { name: 'join' });
            } else {
              SessionSvc.loginRequired($scope, function() {
                $scope.project.addParticipant();
              }, undefined, $scope.project.synchPromise());
            }

            $timeout();
            $analytics.eventTrack('Join project', {});
          } else {

            SessionSvc.loginRequired($scope, function() {
              $scope.project.removeParticipant();
            }, undefined, $scope.project.synchPromise());
          }
        });
      }],
      scope: {
        joinIcon: '@',
        joinCopyOn: '@',
        joinCopyOff: '@',
        joinModal: '=',
        project: '=joinModel'
      },
      templateUrl: 'join.html'
    };
  });
<commit_msg>check origin url param to skip join modal if needed<commit_after>'use strict';

angular.module('Teem')
  .directive('join', function() {
    return {
      controller: [
      '$scope', '$element', 'SessionSvc', '$timeout', '$analytics', 'SharedState', '$routeParams',
      function($scope, $element, SessionSvc, $timeout, $analytics, SharedState, $routeParams) {

        $element.on('click', function() {

          if (!$scope.project.isParticipant()){

            var origin = $routeParams.origin;
            console.log($routeParams);

            if ($scope.joinModal && typeof origin === 'undefined') {
              SharedState.set('modal.join', { name: 'join' });
            } else {
              SessionSvc.loginRequired($scope, function() {
                $scope.project.addParticipant();
              }, undefined, $scope.project.synchPromise());
            }

            $timeout();
            $analytics.eventTrack('Join project', {});
          } else {

            SessionSvc.loginRequired($scope, function() {
              $scope.project.removeParticipant();
            }, undefined, $scope.project.synchPromise());
          }
        });
      }],
      scope: {
        joinIcon: '@',
        joinCopyOn: '@',
        joinCopyOff: '@',
        joinModal: '=',
        project: '=joinModel'
      },
      templateUrl: 'join.html'
    };
  });
<|endoftext|>


<commit_before>/**
 * Infinite Scroll
 * https://github.com/OpenBuildings/infinite
 *
 * Author Haralan Dobrev <hkdobrev@gmail.com>
 * Copyright (c) 2013 OpenBuildings, Inc.
 * Licensed under the BSD 2-clause license.
 */

(function( window, $, undefined ) {

var
	// Constants
	PLUGIN = 'infinite',
	NAMESPACE = '.' + PLUGIN,
	LOADING_CLASS = 'inf-anchor-loading',
	EVENTS = {
		click: 'click' + NAMESPACE,
		start: 'start' + NAMESPACE
	},
	DIRECTIONS = {
		up: 'up',
		down: 'down',
		both: 'both'
	},

	// Default options.
	// They could be overriden for all instances by setting
	// $.infinite.defaultOptions
	defaultOptions = {

		// Interval in milliseconds to check if scrolled
		scrollTimeInterval: 256,

		// Direction for the infinite scroll. "down", "up" or "both"
		direction: DIRECTIONS.down,

		// Number of buffer pixels before the next anchor is reached.
		// If loading of items is slow or you want to achieve seamless UX,
		// increase this value. Common for both directions.
		buffer: 100,

		upSelector: '.inf-anchor-up',

		downSelector: '.inf-anchor-down',

		itemSelector: '.inf-item'

	},
	$window = $(window),
	coreSlice = Array.prototype.slice;

function Infinite( options, element ) {
	this.element = element;
	this.options = $.extend(
		{},
		$.infinite.defaultOptions,
		$( element ).data(),
		options
	);
	this.deferred = new $.Deferred();

	this._init();
}

// Instance methods
$.extend(true, Infinite.prototype, {

	// Private methods

	// Initialization
	_init: function() {
		var
			direction = this.options.direction,
			self,
			upAnchor, downAnchor,
			scrolledPx, previousScrolledPx;

		this.retrieving = {
			up: false,
			down: false
		};

		if ( direction === 'both' ) {
			this.upDirection = true;
			this.downDirection = true;
		} else if ( direction === 'up' ) {
			this.upDirection = true;
		} else if ( direction === 'down' ) {
			this.downDirection = true;
		}

		upAnchor = $(this.options.upSelector);
		downAnchor = $(this.options.downSelector);

		if ( !upAnchor.length && !downAnchor.length ) {
			// No next anchor on page.
			// Probably the infinite scroll plugin was enabled in vain.
			// Further resistance is futile.
			return;
		}

		downAnchor.add(upAnchor).on(EVENTS.click, function() {
			return false;
		});

		if ( upAnchor.isScrolledTo( this.options.buffer ) ) {
			this.retrieve( 'up' );
		}

		if ( downAnchor.isScrolledTo( this.options.buffer ) ) {
			this.retrieve( 'down' );
		}

		scrolledPx = previousScrolledPx = $window.scrollTop();

		this._clearTimeout();

		self = this;

		(function hasScrolled() {
			scrolledPx = $window.scrollTop();

			self.scrolledDistancePx = scrolledPx - previousScrolledPx;

			if ( self.scrolledDistancePx !== 0 ) {
				self.scrolled();
			}

			previousScrolledPx = scrolledPx;

			self.timeoutID = window.setTimeout(
				hasScrolled,
				self.options.scrollTimeInterval
			);
		}());
	},

	// Retrieving is finished, successfully or not
	_done: function( success, direction ) {

		// If fetching items failed (or finished) in both directions,
		// destroy instance to free up resources
		if ( !success ) {

			this[ direction + 'Direction' ] = false;

			$( this.options[ direction + 'Selector' ] ).remove();

			if ( !this.upDirection && !this.downDirection ) {
				this.destroy();
			}
		}
	},

	// used in destroy
	_clearTimeout: function() {
		if ( this.timeoutID ) {
			window.clearTimeout(this.timeoutID);
		}
	},

	// Public methods

	promise: function() {
		return this.deferred.promise();
	},

	// Document is scrolled
	scrolled: function() {

		var
			direction = this.scrolledDistancePx > 0 ? 'down' : 'up',
			nextAnchor;

		// Currently retrieving items in this direction. Stop further checks.
		if ( this.retrieving[ direction ] ) {
			return;
		}

		// Infinite scroll in this direction is not enabled.
		if ( !this[ direction + 'Direction' ] ) {
			return;
		}

		nextAnchor = $( this.options[ direction + 'Selector' ] );

		// Anchor for this direction is no longer visible. Stop further checks.
		if ( !nextAnchor.is( ':visible' ) ) {
			return;
		}

		// Check if we have reached next anchor in this direction
		if ( nextAnchor.isScrolledTo( this.options.buffer, direction ) ) {

			// Retrieve items in this direction
			this.retrieve( direction );
		}
	},

	// Retrieve more elements to append in a given direction
	retrieve: function( direction ) {
		var
			self = this,
			nextAnchor = $( this.options[ direction + 'Selector' ] );

		// Set retrieving flag for the current direction
		this.retrieving[ direction ] = true;

		$( this.element ).trigger( EVENTS.start, direction );

		nextAnchor.addClass( LOADING_CLASS );

		$.get( nextAnchor.prop( 'href' ) )
			.done(function( data ) {
				self.loaded( data, direction );
			})
			.fail(function() {
				this.deferred.reject( direction );
				self._done( false, direction );
			})
			.always(function() {
				// Always unset the retrieving flag for this direction
				self.retrieving[ direction ] = false;

				nextAnchor.removeClass( LOADING_CLASS );
			});
	},

	// Response from the server is loaded
	loaded: function( data, direction ) {
		var
			nextAnchorSelector = this.options[ direction + 'Selector' ],
			nextAnchor, container, children, oldDocumentHeight;

		if ( !data || !data.length ) {
			this.deferred.resolve( direction, data );
			this._done( false, direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		// Support for infinite scroll in tables
		// You cannot append <tr> inside a <div> on some browsers
		container = $( this.element.nodeName === 'TABLE' ?
			'<tbody>' :
			'<div>' ).append( data );

		children = container.find( this.options.itemSelector );

		if ( !children.length ) {
			this.deferred.resolve( direction, data );
			this._done( false, direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		oldDocumentHeight = $( document ).height();

		$( this.element )[ direction === 'up' ?
			'prepend' :
			'append' ]( children );

		if ( direction === DIRECTIONS.up ) {
			$( window ).scrollTop(
				$( window ).scrollTop() +
				$( document ).height() -
				oldDocumentHeight
			);
		}

		this.deferred.notify( direction, children );

		nextAnchor = container.find( nextAnchorSelector );

		if ( !nextAnchor.length ) {
			this.deferred.resolve( direction, data );
			this._done( false, direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		$( nextAnchorSelector ).replaceWith( nextAnchor );
		this._done( true, direction );
	},

	// Destroy the instance
	destroy: function() {
		$.removeData( this.element, PLUGIN );
		this._clearTimeout();
	}
});

$.fn.infinite = function( options ) {
	var
		isMethodCall = typeof options === "string",
		args = coreSlice.call( arguments, 1 ),
		domElement = this.get( 0 ),
		instance, methodResult;

	if ( !domElement ) {
		return this;
	}

	instance = $.data( domElement, PLUGIN );

	if ( isMethodCall ) {

		if ( options === "instance" ) {
			return instance;
		}

		// If there is no instance, throw an error
		if ( !instance ) {
			return $.error( "cannot call methods on " +
				PLUGIN +
				" prior to initialization; " +
				"attempted to call method '" +
				options +
				"'" );
		}

		// If there is no such public method, throw an error
		if ( !$.isFunction( instance[ options ] ) ||
			options.charAt( 0 ) === "_" ) {
			return $.error( "no such method '" +
				options +
				"' for "+
				PLUGIN +
				" instance" );
		}

		methodResult = instance[ options ].apply( instance, args );

		if ( methodResult !== instance && methodResult !== undefined ) {
			return methodResult;
		}

		return this;
	}

	if ( instance ) {
		$.extend( instance.options, options || {} );
		if ( instance._init ) {
			instance._init();
		}
	} else {
		instance = new Infinite( options, domElement );
		$.data( domElement, PLUGIN, instance );
	}

	return instance.deferred.promise();
};

// Expose Infinite constructor
$.infinite = Infinite;

// Expose static properties
$.extend( $.infinite, {
	namespace: NAMESPACE,
	events: EVENTS,
	directions: DIRECTIONS,
	defaultOptions: defaultOptions
});

}( window, window.jQuery ));
<commit_msg>Resolve promise when finished in both directions<commit_after>/**
 * Infinite Scroll
 * https://github.com/OpenBuildings/infinite
 *
 * Author Haralan Dobrev <hkdobrev@gmail.com>
 * Copyright (c) 2013 OpenBuildings, Inc.
 * Licensed under the BSD 2-clause license.
 */

(function( window, $, undefined ) {

var
	// Constants
	PLUGIN = 'infinite',
	NAMESPACE = '.' + PLUGIN,
	LOADING_CLASS = 'inf-anchor-loading',
	EVENTS = {
		click: 'click' + NAMESPACE,
		start: 'start' + NAMESPACE
	},
	DIRECTIONS = {
		up: 'up',
		down: 'down',
		both: 'both'
	},

	// Default options.
	// They could be overriden for all instances by setting
	// $.infinite.defaultOptions
	defaultOptions = {

		// Interval in milliseconds to check if scrolled
		scrollTimeInterval: 256,

		// Direction for the infinite scroll. "down", "up" or "both"
		direction: DIRECTIONS.down,

		// Number of buffer pixels before the next anchor is reached.
		// If loading of items is slow or you want to achieve seamless UX,
		// increase this value. Common for both directions.
		buffer: 100,

		upSelector: '.inf-anchor-up',

		downSelector: '.inf-anchor-down',

		itemSelector: '.inf-item'

	},
	$window = $(window),
	coreSlice = Array.prototype.slice;

function Infinite( options, element ) {
	this.element = element;
	this.options = $.extend(
		{},
		$.infinite.defaultOptions,
		$( element ).data(),
		options
	);
	this.deferred = new $.Deferred();

	this._init();
}

// Instance methods
$.extend(true, Infinite.prototype, {

	// Private methods

	// Initialization
	_init: function() {
		var
			direction = this.options.direction,
			self,
			upAnchor, downAnchor,
			scrolledPx, previousScrolledPx;

		this.retrieving = {
			up: false,
			down: false
		};

		if ( direction === 'both' ) {
			this.upDirection = true;
			this.downDirection = true;
		} else if ( direction === 'up' ) {
			this.upDirection = true;
		} else if ( direction === 'down' ) {
			this.downDirection = true;
		}

		upAnchor = $(this.options.upSelector);
		downAnchor = $(this.options.downSelector);

		if ( !upAnchor.length && !downAnchor.length ) {
			// No next anchor on page.
			// Probably the infinite scroll plugin was enabled in vain.
			// Further resistance is futile.
			return;
		}

		downAnchor.add(upAnchor).on(EVENTS.click, function() {
			return false;
		});

		if ( upAnchor.isScrolledTo( this.options.buffer ) ) {
			this.retrieve( 'up' );
		}

		if ( downAnchor.isScrolledTo( this.options.buffer ) ) {
			this.retrieve( 'down' );
		}

		scrolledPx = previousScrolledPx = $window.scrollTop();

		this._clearTimeout();

		self = this;

		(function hasScrolled() {
			scrolledPx = $window.scrollTop();

			self.scrolledDistancePx = scrolledPx - previousScrolledPx;

			if ( self.scrolledDistancePx !== 0 ) {
				self.scrolled();
			}

			previousScrolledPx = scrolledPx;

			self.timeoutID = window.setTimeout(
				hasScrolled,
				self.options.scrollTimeInterval
			);
		}());
	},

	// No more items in this direction
	_done: function( direction ) {

		// If fetching items failed (or finished) in both directions,
		// destroy instance to free up resources

		this[ direction + 'Direction' ] = false;

		$( this.options[ direction + 'Selector' ] ).remove();

		if ( !this.upDirection && !this.downDirection ) {
			this.destroy();
		}
	},

	// used in destroy
	_clearTimeout: function() {
		if ( this.timeoutID ) {
			window.clearTimeout(this.timeoutID);
		}
	},

	// Public methods

	promise: function() {
		return this.deferred.promise();
	},

	// Document is scrolled
	scrolled: function() {

		var
			direction = this.scrolledDistancePx > 0 ? 'down' : 'up',
			nextAnchor;

		// Currently retrieving items in this direction. Stop further checks.
		if ( this.retrieving[ direction ] ) {
			return;
		}

		// Infinite scroll in this direction is not enabled.
		if ( !this[ direction + 'Direction' ] ) {
			return;
		}

		nextAnchor = $( this.options[ direction + 'Selector' ] );

		// Anchor for this direction is no longer visible. Stop further checks.
		if ( !nextAnchor.is( ':visible' ) ) {
			return;
		}

		// Check if we have reached next anchor in this direction
		if ( nextAnchor.isScrolledTo( this.options.buffer, direction ) ) {

			// Retrieve items in this direction
			this.retrieve( direction );
		}
	},

	// Retrieve more elements to append in a given direction
	retrieve: function( direction ) {
		var
			self = this,
			nextAnchor = $( this.options[ direction + 'Selector' ] );

		// Set retrieving flag for the current direction
		this.retrieving[ direction ] = true;

		$( this.element ).trigger( EVENTS.start, direction );

		nextAnchor.addClass( LOADING_CLASS );

		$.get( nextAnchor.prop( 'href' ) )
			.done(function( data ) {
				self.loaded( data, direction );
			})
			.fail(function() {
				self._done( direction );
			})
			.always(function() {
				// Always unset the retrieving flag for this direction
				self.retrieving[ direction ] = false;

				nextAnchor.removeClass( LOADING_CLASS );
			});
	},

	// Response from the server is loaded
	loaded: function( data, direction ) {
		var
			nextAnchorSelector = this.options[ direction + 'Selector' ],
			nextAnchor, container, children, oldDocumentHeight;

		if ( !data || !data.length ) {
			this._done( direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		// Support for infinite scroll in tables
		// You cannot append <tr> inside a <div> on some browsers
		container = $( this.element.nodeName === 'TABLE' ?
			'<tbody>' :
			'<div>' ).append( data );

		children = container.find( this.options.itemSelector );

		if ( !children.length ) {
			this._done( direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		oldDocumentHeight = $( document ).height();

		$( this.element )[ direction === 'up' ?
			'prepend' :
			'append' ]( children );

		if ( direction === DIRECTIONS.up ) {
			$( window ).scrollTop(
				$( window ).scrollTop() +
				$( document ).height() -
				oldDocumentHeight
			);
		}

		this.deferred.notify( direction, children );

		nextAnchor = container.find( nextAnchorSelector );

		if ( !nextAnchor.length ) {
			this._done( direction );
			$( nextAnchorSelector ).remove();

			return;
		}

		$( nextAnchorSelector ).replaceWith( nextAnchor );
	},

	// Destroy the instance
	destroy: function() {
		this.deferred.resolve();
		$.removeData( this.element, PLUGIN );
		this._clearTimeout();
	}
});

$.fn.infinite = function( options ) {
	var
		isMethodCall = typeof options === "string",
		args = coreSlice.call( arguments, 1 ),
		domElement = this.get( 0 ),
		instance, methodResult;

	if ( !domElement ) {
		return this;
	}

	instance = $.data( domElement, PLUGIN );

	if ( isMethodCall ) {

		if ( options === "instance" ) {
			return instance;
		}

		// If there is no instance, throw an error
		if ( !instance ) {
			return $.error( "cannot call methods on " +
				PLUGIN +
				" prior to initialization; " +
				"attempted to call method '" +
				options +
				"'" );
		}

		// If there is no such public method, throw an error
		if ( !$.isFunction( instance[ options ] ) ||
			options.charAt( 0 ) === "_" ) {
			return $.error( "no such method '" +
				options +
				"' for "+
				PLUGIN +
				" instance" );
		}

		methodResult = instance[ options ].apply( instance, args );

		if ( methodResult !== instance && methodResult !== undefined ) {
			return methodResult;
		}

		return this;
	}

	if ( instance ) {
		$.extend( instance.options, options || {} );
		if ( instance._init ) {
			instance._init();
		}
	} else {
		instance = new Infinite( options, domElement );
		$.data( domElement, PLUGIN, instance );
	}

	return instance.deferred.promise();
};

// Expose Infinite constructor
$.infinite = Infinite;

// Expose static properties
$.extend( $.infinite, {
	namespace: NAMESPACE,
	events: EVENTS,
	directions: DIRECTIONS,
	defaultOptions: defaultOptions
});

}( window, window.jQuery ));
<|endoftext|>


<commit_before>module( "plugins.basestyle" );

test( 'sub--table', function () {
        var editor = te.obj[0];
        editor.setContent( '

hello1	hello2

hello3	hello4

' );
    setTimeout(function(){
        var range = te.obj[1];
        var body = editor.document.body;
        //1.2的版本中，table标签套了div标签，原来的var tbody = body.firstChild.firstChild；改为如下
        var tbody = editor.document.getElementsByTagName( 'table' )[0].firstChild;
        range.selectNode( body.firstChild ).select();
        var tds = body.firstChild.getElementsByTagName( 'td' );
        var td;
//        for ( var index = 0; td = tds[index++]; ) {
//
//                editor.currentSelectedArr.push( td );
//        }
        editor.execCommand( 'subscript' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild ), 'hello1', '检查第1个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild.nextSibling ), 'hello2', '检查第2个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild ), 'hello3', '检查第3个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild.nextSibling ), 'hello4', '检查第4个单元格中文本是否是下标' );
        equal( editor.queryCommandState( 'superscript' ), 0, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 1, 'check sub state' );
        /**trace 943，为表格去上下标**/
        editor.execCommand( 'subscript' );
        equal( tbody.firstChild.firstChild.innerHTML, 'hello1', '检查第1个单元格中文本是否不是下标' );
        equal( tbody.firstChild.firstChild.nextSibling.innerHTML, 'hello2', '检查第2个单元格中文本是否不是下标' );
        equal( tbody.lastChild.firstChild.innerHTML, 'hello3', '检查第3个单元格中文本是否不是下标' );
        equal( tbody.lastChild.firstChild.nextSibling.innerHTML, 'hello4', '检查第4个单元格中文本是否你是下标' );
        equal( editor.queryCommandState( 'superscript' ), 0, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 0, 'check sub state' );
        /*上下标互斥*/
        editor.execCommand( 'superscript' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild ), 'hello1', '检查第1个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild.nextSibling ), 'hello2', '检查第2个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild ), 'hello3', '检查第3个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild.nextSibling ), 'hello4', '检查第4个单元格中文本是否是上标' );
        equal( editor.queryCommandState( 'superscript' ), 1, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 0, 'check sub state' );
        start();
    },50);
    stop();
} );
//如果没有setTimeout在FF（3.6和9都是）中range会出错，其他浏览器没问题
test( '闭合插入上下标', function () {
        var editor = te.obj[0];
        var range = te.obj[1];
        editor.setContent( '
你好
' );
        var body = editor.body;
        stop()
        setTimeout( function () {
                range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select( true );

                editor.execCommand( 'superscript' );
                equal( ua.getChildHTML( body.firstChild ), '你好', '查看执行上标后的结果' );
                range = editor.selection.getRange();
                range.insertNode( editor.document.createTextNode( 'hello' ) );
                equal( ua.getChildHTML( body.firstChild ), '你hello好', '上标标签中插入文本' );
                start()
        }, 100 )

} );
//如果没有setTimeout在FF（3.6和9都是）中range会出错，其他浏览器没问题
test( '不闭合插入上下标', function () {
        var editor = te.obj[0];
        var range = te.obj[1];
        editor.setContent( 'hello1hello2baidu_linkhello3' );
        var body = editor.document.body;
        stop();
        setTimeout( function () {
                range.setStart( body.firstChild.firstChild, 0 ).setEnd( body.firstChild.lastChild, 3 ).select();
                editor.execCommand( 'superscript' );
                ua.manualDeleteFillData( body );
                equal( ua.getChildHTML( body.firstChild ), 'hello1hello2baidu_linkhello3', '普通文本添加上标' );
                start();
        }, 100 )
} );

/*trace 870*/
//无法模拟光标自动移到的场景，因此模拟输入文本通过插入文本节点实现的方法，在插入文本后光标仍然在原来的位置
// 我们不确定光标实际在哪
test( 'trace 870:加粗文本前面去加粗', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( '

' );
        range.setStart( body.firstChild, 0 ).collapse( true ).select();
        editor.execCommand( 'bold' );
        range = editor.selection.getRange();
        range.insertNode( editor.document.createTextNode( 'hello' ) );
        equal( editor.queryCommandState( 'bold' ), 1, '加粗' );
        editor.execCommand( 'bold' );
        range = editor.selection.getRange();
        equal( editor.queryCommandState( 'bold' ), 0, '不加粗' );
        /*插入一个文本节点*/
        range.insertNode( editor.document.createTextNode( 'hello2' ) );
        ua.manualDeleteFillData( editor.body );
        /*ie下插入节点后会自动移动光标到节点后面，而其他浏览器不会*/
        if ( baidu.editor.browser.ie || baidu.editor.browser.opera)
                equal( editor.getContent(), '
hellohello2

' );
        else
                equal( editor.getContent(), '
hello2hello

' )
} );

/*trace 1043*/
test( 'bold-在已加粗文本中间去除加粗', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( 'hellossss' );
        range.setStart( body.firstChild.firstChild, 0 ).collapse( true ).select();
        editor.execCommand( 'bold' );
        range = editor.selection.getRange();
        equal( editor.queryCommandState( 'bold' ), 0, " 被去掉" );

        /*在当前的range选区插入文本节点*/
        range.insertNode( range.document.createTextNode( 'aa' ) );
        ua.manualDeleteFillData( editor.body );

        equal( ua.getChildHTML( body.firstChild ), "aahellossss", "新文本节点没有加粗" );
} );

/*trace 958*/
test( 'bold-在已加粗文本中间去除加粗', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( '' );
        editor.execCommand( 'bold' );
        ok( ua.getChildHTML( body ), "<stong></stong>", "editor不focus时点加粗，不会多一个空行" );
} );

/*trace 958*/
//如果没有setTimeout在FF（3.6和9都是）中range会出错，其他浏览器没问题
test( 'bold-加粗状态反射', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( 'this is a dog' );
        stop();
        setTimeout( function () {
                range.selectNode( body.firstChild ).select();
                editor.execCommand( 'bold' );
                range.setStart( body.firstChild.firstChild.firstChild, 2 ).collapse( true ).select();
                equal( editor.queryCommandState( 'bold' ), 1, '闭合选择，加粗高亮' );
                ua.manualDeleteFillData( editor.body );

                range.setStart( body.firstChild.firstChild.firstChild, 0 ).setEnd( body.firstChild.firstChild.lastChild, 4 ).select();
                equal( editor.queryCommandState( 'bold' ), 1, '不闭合选择，加粗高亮' );
                start();
        }, 100 )
} );

/*trace 580*/
test( 'bold-连续加粗2次', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( 'this is a dog' );
        var text = body.firstChild.firstChild;
        range.setStart( text, 0 ).setEnd( text, 3 ).select();
        /*第一次加粗*/
        editor.execCommand( 'bold' );
        equal( editor.queryCommandState( 'bold' ), 1, '加粗按钮高亮' );
        text = body.firstChild.lastChild;
        range.setStart( text, 1 ).setEnd( text, 3 ).select();
        /*不闭合选区文本*/
        equal( editor.queryCommandState( 'bold' ), 0, '不闭合选择，加粗不高亮' );
        /*第二次加粗*/
        ua.manualDeleteFillData( editor.body );
        editor.execCommand( 'bold' );
        equal( editor.queryCommandState( 'bold' ), 1, '加粗高亮' );
} );
/*trace 1983*/
test( 'bold-2个单词，中间有空格第一个单词加粗，第二个单词加粗再去加粗', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
//    editor.setContent( '
hello world
' );
        body.innerHTML =    '
hello world
';//用setContent复现不了这个问题
        var text = body.firstChild.firstChild;
        range.setStart( text, 0 ).setEnd( text, 5 ).select();
        editor.execCommand( 'bold' );
        text = body.firstChild.lastChild;
        range.setStart( text, 1 ).setEnd( text, 6 ).select();
        editor.execCommand( 'bold' );
        editor.execCommand( 'bold' );
        ok( body.firstChild.childNodes.length==3&&body.firstChild.childNodes[1].length ==1, '空格保留');

} );
test( '测试 userAction.manualdeleteFilldata', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( '

' );

//    var fillData = document.createTextNode(domUtils.fillChar);
        //  在ie 6,7下，使用appendChild时，需要body先加载，必须将上句document前加editor,否则出错
        var fillData = editor.document.createTextNode( domUtils.fillChar );
        body.appendChild( fillData );
        var space = ua.browser.ie ? ' ' : '
';//getContent（）结果：‘
’,innerHTML结果：

        notEqual( body.innerHTML.toLowerCase(), '
' + space + '
', '清除不可见字符前不相等' );
        ua.manualDeleteFillData( body );
        equal( body.innerHTML.toLowerCase(), '
' + space + '
', '清除不可见字符后相等' );
} );

test( 'trace 1884:单击B再单击I ', function () {
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( '' );
        range.setStart( body.firstChild, 0 ).collapse( 1 ).select();
        editor.execCommand( 'bold' );
        equal( editor.queryCommandState( 'bold' ), 1, 'b高亮' );
        editor.execCommand( 'italic' );
        equal( editor.queryCommandState( 'italic' ), 1, 'b高亮' );
} );

test( '单击B再在其他地方单击I，空的strong标签被删除 ', function () {
        //ie下有问题不能修，屏蔽ie
        var editor = te.obj[0];
        var body = editor.body;
        var range = te.obj[1];
        editor.setContent( '
hello
' );
        range.setStart( body.firstChild, 0 ).collapse( 1 ).select();
        editor.execCommand( 'bold' );
        equal( editor.queryCommandState( 'bold' ), 1, 'b高亮' );
        range.setStart( body.firstChild, 1 ).collapse( 1 ).select();
        editor.execCommand( 'italic' );
        equal( editor.queryCommandState( 'italic' ), 1, 'b高亮' );
        ua.manualDeleteFillData( body );
        if(!ua.browser.ie){
                equal( body.innerHTML.toLowerCase(), '
hello
', '空strong标签被删除' )
        }

} );<commit_msg>【test】整理用例plugins/basestyle<commit_after>module( "plugins.basestyle" );

test( 'sub--table', function () {
    var editor = te.obj[0];
    editor.setContent( '

hello1	hello2

hello3	hello4

' );
    setTimeout(function(){
        var range = te.obj[1];
        var body = editor.document.body;
        //1.2的版本中，table标签套了div标签，原来的var tbody = body.firstChild.firstChild；改为如下
        var tbody = editor.document.getElementsByTagName( 'table' )[0].firstChild;
        range.selectNode( body.firstChild ).select();
        var tds = body.firstChild.getElementsByTagName( 'td' );
        var td;
//        for ( var index = 0; td = tds[index++]; ) {
//                editor.currentSelectedArr.push( td );
//        }
        editor.execCommand( 'subscript' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild ), 'hello1', '检查第1个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild.nextSibling ), 'hello2', '检查第2个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild ), 'hello3', '检查第3个单元格中文本是否是下标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild.nextSibling ), 'hello4', '检查第4个单元格中文本是否是下标' );
        equal( editor.queryCommandState( 'superscript' ), 0, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 1, 'check sub state' );

        editor.execCommand( 'subscript' );      /**trace 943，为表格去上下标**/
        equal( tbody.firstChild.firstChild.innerHTML, 'hello1', '检查第1个单元格中文本是否不是下标' );
        equal( tbody.firstChild.firstChild.nextSibling.innerHTML, 'hello2', '检查第2个单元格中文本是否不是下标' );
        equal( tbody.lastChild.firstChild.innerHTML, 'hello3', '检查第3个单元格中文本是否不是下标' );
        equal( tbody.lastChild.firstChild.nextSibling.innerHTML, 'hello4', '检查第4个单元格中文本是否你是下标' );
        equal( editor.queryCommandState( 'superscript' ), 0, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 0, 'check sub state' );

        editor.execCommand( 'superscript' );        /*上下标互斥*/
        equal( ua.getChildHTML( tbody.firstChild.firstChild ), 'hello1', '检查第1个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.firstChild.firstChild.nextSibling ), 'hello2', '检查第2个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild ), 'hello3', '检查第3个单元格中文本是否是上标' );
        equal( ua.getChildHTML( tbody.lastChild.firstChild.nextSibling ), 'hello4', '检查第4个单元格中文本是否是上标' );
        equal( editor.queryCommandState( 'superscript' ), 1, 'check sup state' );
        equal( editor.queryCommandState( 'subscript' ), 0, 'check sub state' );
        start();
    },50);
    stop();
} );

//如果没有setTimeout在FF（3.6和9都是）中range会出错，其他浏览器没问题
test( '闭合插入上下标', function () {
    var editor = te.obj[0];
    var range = te.obj[1];
    editor.setContent( '
你好
' );
    var body = editor.body;
    stop();
    setTimeout( function () {
        range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select( true );
        editor.execCommand( 'superscript' );
        equal( ua.getChildHTML( body.firstChild ), '你好', '查看执行上标后的结果' );
        range = editor.selection.getRange();
        range.insertNode( editor.document.createTextNode( 'hello' ) );
        equal( ua.getChildHTML( body.firstChild ), '你hello好', '上标标签中插入文本' );
        start();
    }, 100 )
} );

test( '不闭合插入上下标', function () {
    var editor = te.obj[0];
    var range = te.obj[1];
    editor.setContent( 'hello1hello2baidu_linkhello3' );
    var body = editor.document.body;
    stop();
    setTimeout( function () {
        range.setStart( body.firstChild.firstChild, 0 ).setEnd( body.firstChild.lastChild, 3 ).select();
        editor.execCommand( 'superscript' );
            ua.manualDeleteFillData( body );
            equal( ua.getChildHTML( body.firstChild ), 'hello1hello2baidu_linkhello3', '普通文本添加上标' );
            start();
    }, 100 );
} );

/*trace 870*/
//无法模拟光标自动移到的场景，因此模拟输入文本通过插入文本节点实现的方法，在插入文本后光标仍然在原来的位置
// 我们不确定光标实际在哪
test( 'trace 870:加粗文本前面去加粗', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '

' );
    range.setStart( body.firstChild, 0 ).collapse( true ).select();
    editor.execCommand( 'bold' );
    range = editor.selection.getRange();
    range.insertNode( editor.document.createTextNode( 'hello' ) );
    equal( editor.queryCommandState( 'bold' ), 1, '加粗' );
    editor.execCommand( 'bold' );
    range = editor.selection.getRange();
    equal( editor.queryCommandState( 'bold' ), 0, '不加粗' );
    range.insertNode( editor.document.createTextNode( 'hello2' ) );     /*插入一个文本节点*/
    ua.manualDeleteFillData( editor.body );
    if ( baidu.editor.browser.ie || baidu.editor.browser.opera)     /*ie下插入节点后会自动移动光标到节点后面，而其他浏览器不会*/
        equal( editor.getContent(), '
hellohello2

' );
    else
        equal( editor.getContent(), '
hello2hello

' );
} );

/*trace 1043*/
test( 'bold-在已加粗文本中间去除加粗', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( 'hellossss' );
    range.setStart( body.firstChild.firstChild, 0 ).collapse( true ).select();
    editor.execCommand( 'bold' );
    range = editor.selection.getRange();
    equal( editor.queryCommandState( 'bold' ), 0, " 被去掉" );
    range.insertNode( range.document.createTextNode( 'aa' ) );       /*在当前的range选区插入文本节点*/
    ua.manualDeleteFillData( editor.body );
    equal( ua.getChildHTML( body.firstChild ), "aahellossss", "新文本节点没有加粗" );
} );

/*trace 958*/
test( 'bold-在已加粗文本中间去除加粗', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '' );
    editor.execCommand( 'bold' );
    ok( ua.getChildHTML( body ), "<stong></stong>", "editor不focus时点加粗，不会多一个空行" );
} );

/*trace 958*/
test( 'bold-加粗状态反射', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '
this is a dog
' );
    stop();
    setTimeout( function () {
        range.selectNode( body.firstChild ).select();
        editor.execCommand( 'bold' );
        range.setStart( body.firstChild.firstChild.firstChild, 2 ).collapse( true ).select();
        equal( editor.queryCommandState( 'bold' ), 1, '闭合选择，加粗高亮' );
        ua.manualDeleteFillData( editor.body );
        range.setStart( body.firstChild.firstChild.firstChild, 0 ).setEnd( body.firstChild.firstChild.lastChild, 4 ).select();
        equal( editor.queryCommandState( 'bold' ), 1, '不闭合选择，加粗高亮' );
        start();
    }, 100 )
} );

/*trace 580*/
test( 'bold-连续加粗2次', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '
this is a dog
' );
    var text = body.firstChild.firstChild;
    range.setStart( text, 0 ).setEnd( text, 3 ).select();
    editor.execCommand( 'bold' );        /*第一次加粗*/
    equal( editor.queryCommandState( 'bold' ), 1, '加粗按钮高亮' );
    text = body.firstChild.lastChild;
    range.setStart( text, 1 ).setEnd( text, 3 ).select();       /*不闭合选区文本*/
    equal( editor.queryCommandState( 'bold' ), 0, '不闭合选择，加粗不高亮' );
    ua.manualDeleteFillData( editor.body );
    editor.execCommand( 'bold' );       /*第二次加粗*/
    equal( editor.queryCommandState( 'bold' ), 1, '加粗高亮' );
} );

/*trace 1983*/
test( 'bold-2个单词，中间有空格第一个单词加粗，第二个单词加粗再去加粗', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    body.innerHTML =    '
hello world
';   //用setContent复现不了这个问题
    var text = body.firstChild.firstChild;
    range.setStart( text, 0 ).setEnd( text, 5 ).select();
    editor.execCommand( 'bold' );
    text = body.firstChild.lastChild;
    range.setStart( text, 1 ).setEnd( text, 6 ).select();
    editor.execCommand( 'bold' );
    editor.execCommand( 'bold' );
    ok( body.firstChild.childNodes.length==3&&body.firstChild.childNodes[1].length ==1, '空格保留');
} );

test( '测试 userAction.manualdeleteFilldata', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '

' );
    var fillData = editor.document.createTextNode( domUtils.fillChar );     //  在ie 6,7下，使用appendChild时，需要body先加载，必须将上句document前加editor,否则出错
    body.appendChild( fillData );
    var space = ua.browser.ie ? ' ' : '
';//getContent（）结果：‘
’,innerHTML结果：

    notEqual( body.innerHTML.toLowerCase(), '
' + space + '
', '清除不可见字符前不相等' );
    ua.manualDeleteFillData( body );
    equal( body.innerHTML.toLowerCase(), '
' + space + '
', '清除不可见字符后相等' );
} );

test( 'trace 1884:单击B再单击I ', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '' );
    range.setStart( body.firstChild, 0 ).collapse( 1 ).select();
    editor.execCommand( 'bold' );
    equal( editor.queryCommandState( 'bold' ), 1, 'b高亮' );
    editor.execCommand( 'italic' );
    equal( editor.queryCommandState( 'italic' ), 1, 'b高亮' );
} );

test( '单击B再在其他地方单击I，空的strong标签被删除 ', function () {
    var editor = te.obj[0];
    var body = editor.body;
    var range = te.obj[1];
    editor.setContent( '
hello
' );
    range.setStart( body.firstChild, 0 ).collapse( 1 ).select();
    editor.execCommand( 'bold' );
    equal( editor.queryCommandState( 'bold' ), 1, 'b高亮' );
    range.setStart( body.firstChild, 1 ).collapse( 1 ).select();
    editor.execCommand( 'italic' );
    equal( editor.queryCommandState( 'italic' ), 1, 'b高亮' );
    ua.manualDeleteFillData( body );
    if(!ua.browser.ie){     //ie下有问题不能修，屏蔽ie
            equal( body.innerHTML.toLowerCase(), '
hello
', '空strong标签被删除' )
    }
} );<|endoftext|>


<commit_before>(function(angular) {
	'use strict';

	angular.module('ngWYSIWYG').service('ngpImageResizer', ['NGP_EVENTS', function(NGP_EVENTS) {
		var service = this;
		var iframeDoc, iframeWindow, iframeBody, resizerContainer,
			iframeScope, keepRatioButton, resizerOptionsContainer, resizing, elementBeingResized;

		service.setup = function(scope, document) {
			iframeWindow = document.defaultView;
			iframeDoc = document;
			iframeBody = iframeDoc.querySelector('body');
			iframeScope = scope;

			// creating resizer container
			resizerContainer = iframeDoc.createElement('div');
			resizerContainer.className = 'ngp-image-resizer';
			resizerContainer.style.position = 'absolute';
			resizerContainer.style.border = '1px dashed black';
			resizerContainer.style.display = 'none';
			resizerContainer.setAttribute('contenteditable', false);

			// creating bottom-right resizer button
			keepRatioButton = iframeDoc.createElement('div');
			keepRatioButton.style.position = 'absolute';
			keepRatioButton.style.height = '10px';
			keepRatioButton.style.width = '10px';
			keepRatioButton.style.bottom = '-5px';
			keepRatioButton.style.right = '-5px';
			keepRatioButton.style.border = '1px solid black';
			keepRatioButton.style.backgroundColor = '#fff';
			keepRatioButton.style.cursor = 'se-resize';
			keepRatioButton.setAttribute('contenteditable', false);
			resizerContainer.appendChild(keepRatioButton);

			// resizer options container
			resizerOptionsContainer = iframeDoc.createElement('div');
			resizerOptionsContainer.style.position = 'absolute';
			resizerOptionsContainer.style.height = '30px';
			resizerOptionsContainer.style.width = '100px';
			resizerOptionsContainer.style.bottom = '-30px';
			resizerOptionsContainer.style.left = '0';
			resizerContainer.appendChild(resizerOptionsContainer);

			// resizer options
			var resizerReset = iframeDoc.createElement('button');
			resizerReset.addEventListener('click', resetImageSize);
			resizerReset.innerHTML = 'Auto';
			resizerOptionsContainer.appendChild(resizerReset);

			var resizer100 = iframeDoc.createElement('button');
			resizer100.addEventListener('click', size100);
			resizer100.innerHTML = '100%';
			resizerOptionsContainer.appendChild(resizer100);

			// resizer listener
			iframeDoc.addEventListener('mousedown', startResizing);
			iframeDoc.addEventListener('mouseup', startResizing);

			iframeBody.addEventListener('mscontrolselect', disableIESelect);

			// listening to events
			iframeScope.$on(NGP_EVENTS.ELEMENT_CLICKED, createResizer);
			iframeScope.$on(NGP_EVENTS.CLICK_AWAY, removeResizer);
		};

		function disableIESelect(event) {
			event.preventDefault();
		}

		function resetImageSize(event) {
			event.preventDefault();
			event.stopPropagation();
			elementBeingResized.style.height = '';
			elementBeingResized.style.width = '';
			updateResizer();
		}

		function size100(event) {
			event.preventDefault();
			event.stopPropagation();
			elementBeingResized.style.width = '100%';
			elementBeingResized.style.height = '';
			updateResizer();
		}

		function startResizing(event) {
			if (event.target != keepRatioButton) {
				iframeDoc.removeEventListener('mousemove', updateImageSize);
				resizing = false;
				return;
			}
			event.stopPropagation();
			event.preventDefault();
			iframeDoc.addEventListener('mousemove', updateImageSize);
			resizing = true;
		}

		function updateImageSize(event) {
			event.stopPropagation();
			event.preventDefault();

			var cursorVerticalPosition = event.pageY;
			var newHeight = cursorVerticalPosition -
							(elementBeingResized.getBoundingClientRect().top + iframeWindow.pageYOffset);
			elementBeingResized.style.height = newHeight + 'px';
			elementBeingResized.style.width = '';
			updateResizer();
		}

		function createResizer(event, element) {
			if (element == resizerContainer || resizing) {
				iframeDoc.removeEventListener('mousemove', updateImageSize);
				return;
			}
			if (element.tagName !== 'IMG') {
				return removeResizer();
			}
			if (!resizerContainer.parentNode) {
				iframeBody.appendChild(resizerContainer);
			}
			elementBeingResized = element;
			updateResizer();
		}

		function updateResizer() {
			var elementStyle = iframeWindow.getComputedStyle(elementBeingResized);
			resizerContainer.style.height = elementStyle.getPropertyValue('height');
			resizerContainer.style.width = elementStyle.getPropertyValue('width');
			resizerContainer.style.top = (elementBeingResized.getBoundingClientRect().top + iframeWindow.pageYOffset) + 'px';
			resizerContainer.style.left = (elementBeingResized.getBoundingClientRect().left + iframeWindow.pageXOffset) + 'px';
			resizerContainer.style.display = 'block';
		}

		function removeResizer(event) {
			if (!resizerContainer.parentNode) {
				return;
			}
			if (event && event.target.tagName === 'IMG') {
				return;
			}
		}
	}]);
}(window.angular));<commit_msg>handling image resize<commit_after>(function(angular) {
	'use strict';

	angular.module('ngWYSIWYG').service('ngpImageResizer', ['NGP_EVENTS', function(NGP_EVENTS) {
		var service = this;
		var iframeDoc, iframeWindow, iframeBody, resizerContainer,
			iframeScope, keepRatioButton, resizerOptionsContainer, resizing, elementBeingResized;

		service.setup = function(scope, document) {
			iframeWindow = document.defaultView;
			iframeDoc = document;
			iframeBody = iframeDoc.querySelector('body');
			iframeScope = scope;

			// creating resizer container
			resizerContainer = iframeDoc.createElement('div');
			resizerContainer.className = 'ngp-image-resizer';
			resizerContainer.style.position = 'absolute';
			resizerContainer.style.border = '1px dashed black';
			resizerContainer.style.display = 'none';
			resizerContainer.setAttribute('contenteditable', false);

			// creating bottom-right resizer button
			keepRatioButton = iframeDoc.createElement('div');
			keepRatioButton.style.position = 'absolute';
			keepRatioButton.style.height = '10px';
			keepRatioButton.style.width = '10px';
			keepRatioButton.style.bottom = '-5px';
			keepRatioButton.style.right = '-5px';
			keepRatioButton.style.border = '1px solid black';
			keepRatioButton.style.backgroundColor = '#fff';
			keepRatioButton.style.cursor = 'se-resize';
			keepRatioButton.setAttribute('contenteditable', false);
			resizerContainer.appendChild(keepRatioButton);

			// resizer options container
			resizerOptionsContainer = iframeDoc.createElement('div');
			resizerOptionsContainer.style.position = 'absolute';
			resizerOptionsContainer.style.height = '30px';
			resizerOptionsContainer.style.width = '150px';
			resizerOptionsContainer.style.bottom = '-30px';
			resizerOptionsContainer.style.left = '0';
			resizerContainer.appendChild(resizerOptionsContainer);

			// resizer options
			var resizerReset = iframeDoc.createElement('button');
			resizerReset.addEventListener('click', resetImageSize);
			resizerReset.innerHTML = 'Auto';
			resizerOptionsContainer.appendChild(resizerReset);

			var resizer100 = iframeDoc.createElement('button');
			resizer100.addEventListener('click', size100);
			resizer100.innerHTML = '100%';
			resizerOptionsContainer.appendChild(resizer100);

			// resizer listener
			iframeDoc.addEventListener('mousedown', startResizing);
			iframeDoc.addEventListener('mouseup', startResizing);

			iframeBody.addEventListener('mscontrolselect', disableIESelect);

			// listening to events
			iframeScope.$on(NGP_EVENTS.ELEMENT_CLICKED, createResizer);
			iframeScope.$on(NGP_EVENTS.CLICK_AWAY, removeResizer);
		};

		function disableIESelect(event) {
			event.preventDefault();
		}

		function resetImageSize(event) {
			event.preventDefault();
			event.stopPropagation();
			elementBeingResized.style.height = '';
			elementBeingResized.style.width = '';
			updateResizer();
		}

		function size100(event) {
			event.preventDefault();
			event.stopPropagation();
			elementBeingResized.style.width = '100%';
			elementBeingResized.style.height = '';
			updateResizer();
		}

		function startResizing(event) {
			if (event.target != keepRatioButton) {
				iframeDoc.removeEventListener('mousemove', updateImageSize);
				resizing = false;
				return;
			}
			event.stopPropagation();
			event.preventDefault();
			iframeDoc.addEventListener('mousemove', updateImageSize);
			resizing = true;
		}

		function updateImageSize(event) {
			event.stopPropagation();
			event.preventDefault();

			var cursorVerticalPosition = event.pageY;
			var newHeight = cursorVerticalPosition -
							(elementBeingResized.getBoundingClientRect().top + iframeWindow.pageYOffset);
			elementBeingResized.style.height = newHeight + 'px';
			elementBeingResized.style.width = '';
			updateResizer();
		}

		function createResizer(event, element) {
			if (element == resizerContainer || resizing) {
				iframeDoc.removeEventListener('mousemove', updateImageSize);
				return;
			}
			if (element.tagName !== 'IMG') {
				return removeResizer();
			}
			if (!resizerContainer.parentNode) {
				iframeBody.appendChild(resizerContainer);
			}
			elementBeingResized = element;
			updateResizer();
		}

		function updateResizer() {
			var elementStyle = iframeWindow.getComputedStyle(elementBeingResized);
			resizerContainer.style.height = elementStyle.getPropertyValue('height');
			resizerContainer.style.width = elementStyle.getPropertyValue('width');
			resizerContainer.style.top = (elementBeingResized.getBoundingClientRect().top + iframeWindow.pageYOffset) + 'px';
			resizerContainer.style.left = (elementBeingResized.getBoundingClientRect().left + iframeWindow.pageXOffset) + 'px';
			resizerContainer.style.display = 'block';
		}

		function removeResizer(event) {
			if (!resizerContainer.parentNode) {
				return;
			}
			if (event && event.target.tagName === 'IMG') {
				return;
			}
			resizerContainer.style.display = 'none';
		}
	}]);
}(window.angular));<|endoftext|>


<commit_before>function Handle(parameters) {

	this.el = document.getElementsByTagName('handle')[0];
	this.title = undefined;
	this.htmlData = undefined;

	if(ipcRenderer.sendSync('get-preference', 'show_title_bar')) {
		this.show();
	}
	else {
		this.hide();
	}
	this.build();
}

Handle.prototype.build = function() {

	this.htmlData = fs.readFileSync(path.join(__dirname, '..', '..', 'src', 'html', 'handle.html'), 'utf8');
	this.el.innerHTML = this.htmlData;
	this.title = this.el.querySelectorAll('.title')[0];
	this.closeBtn = this.el.querySelectorAll('.button.close')[0];
	this.minimizeBtn = this.el.querySelectorAll('.button.minimize')[0];
	this.fullscreenBtn = this.el.querySelectorAll('.button.fullscreen')[0];
	this.attachEvents();

}

Handle.prototype.attachEvents = function() {

	this.closeBtn.addEventListener('click', function() {
		ipcRenderer.send('closeWindow');
	});
	this.minimizeBtn.addEventListener('click', function() {
		ipcRenderer.send('minimizeWindow');
	});
	this.fullscreenBtn.addEventListener('click', function() {
		ipcRenderer.send('fullscreenWindow');
	});
	this.title.addEventListener('mousedown', this.openMenu.bind(this));

	console.log('[Handle] ☑');

}

Handle.prototype.hide = function() {

	this.el.className = 'hide';

}

Handle.prototype.show = function() {

	this.el.className = 'show';

}

Handle.prototype.disable = function() {

	this.el.classList.add('disabled');

}

Handle.prototype.enable = function() {

	this.el.classList.remove('disabled');

}

Handle.prototype.changeTitle = function(newTitle) {

	this.el.setAttribute('title', newTitle);
	if(newTitle.length > 60) {
		newTitle = newTitle.substring(0, 60) + '...';
	}
	this.title.innerText = newTitle;

	ipcRenderer.send('updateMenuTitle', Browser.id, newTitle);

}

Handle.prototype.getTitle = function() {

	return this.title.innerText;

}

Handle.prototype.openMenu = function(e) {

	e.preventDefault();

	var menu = new Menu();
	menu.append(
		new MenuItem(
			{
				label: 'Copy URL',
				enabled: !Browser.isFirstLoad,
				click: function() {
					clipboard.writeText(Browser.view.webview.getAttribute('src'));
				}
			}
		)
	);
	menu.append(
		new MenuItem(
			{
				label: 'Copy Screenshot',
				accelerator: 'Cmd+Shift+C',
				click: function() {
					ipcRenderer.send('copy-screenshot', Browser.id);
				}
			}
		)
	);
	menu.append(
		new MenuItem(
			{
				type: 'separator'
			}
		)
	);
	if(Browser.view.isFirstLoad) {
		menu.append(
			new MenuItem(
				{
					label: 'Back',
					enabled: false
				}
			)
		);
		menu.append(
			new MenuItem(
				{
					label: 'Forward',
					enabled: false
				}
			)
		);
	}
	else {
		menu.append(
			new MenuItem(
				{
					label: 'Back',
					accelerator: 'Cmd+Left',
					enabled: Browser.view.webview.canGoBack(),
					click: () => {
						Browser.view.webview.goBack();
					}
				}
			)
		);
		menu.append(
			new MenuItem(
				{
					label: 'Forward',
					accelerator: 'Cmd+Right',
					enabled: Browser.view.webview.canGoForward(),
					click: () => {
						Browser.view.webview.goForward();
					}
				}
			)
		);
	}
	menu.append(
		new MenuItem(
			{
				label: 'Reload',
				accelerator: 'Cmd+R',
				enabled: !Browser.view.isFirstLoad,
				click: () => {
					Browser.view.webview.reload();
				}
			}
		)
	);

	// Weird calc to get menu position right
	var x = this.el.offsetWidth / 2 - 46;
	var y = this.el.offsetHeight + 4;

	menu.popup(remote.getCurrentWindow(), x, y);

}<commit_msg>Align nav shortcut for handle menu<commit_after>function Handle(parameters) {

	this.el = document.getElementsByTagName('handle')[0];
	this.title = undefined;
	this.htmlData = undefined;

	if(ipcRenderer.sendSync('get-preference', 'show_title_bar')) {
		this.show();
	}
	else {
		this.hide();
	}
	this.build();
}

Handle.prototype.build = function() {

	this.htmlData = fs.readFileSync(path.join(__dirname, '..', '..', 'src', 'html', 'handle.html'), 'utf8');
	this.el.innerHTML = this.htmlData;
	this.title = this.el.querySelectorAll('.title')[0];
	this.closeBtn = this.el.querySelectorAll('.button.close')[0];
	this.minimizeBtn = this.el.querySelectorAll('.button.minimize')[0];
	this.fullscreenBtn = this.el.querySelectorAll('.button.fullscreen')[0];
	this.attachEvents();

}

Handle.prototype.attachEvents = function() {

	this.closeBtn.addEventListener('click', function() {
		ipcRenderer.send('closeWindow');
	});
	this.minimizeBtn.addEventListener('click', function() {
		ipcRenderer.send('minimizeWindow');
	});
	this.fullscreenBtn.addEventListener('click', function() {
		ipcRenderer.send('fullscreenWindow');
	});
	this.title.addEventListener('mousedown', this.openMenu.bind(this));

	console.log('[Handle] ☑');

}

Handle.prototype.hide = function() {

	this.el.className = 'hide';

}

Handle.prototype.show = function() {

	this.el.className = 'show';

}

Handle.prototype.disable = function() {

	this.el.classList.add('disabled');

}

Handle.prototype.enable = function() {

	this.el.classList.remove('disabled');

}

Handle.prototype.changeTitle = function(newTitle) {

	this.el.setAttribute('title', newTitle);
	if(newTitle.length > 60) {
		newTitle = newTitle.substring(0, 60) + '...';
	}
	this.title.innerText = newTitle;

	ipcRenderer.send('updateMenuTitle', Browser.id, newTitle);

}

Handle.prototype.getTitle = function() {

	return this.title.innerText;

}

Handle.prototype.openMenu = function(e) {

	e.preventDefault();

	var menu = new Menu();
	menu.append(
		new MenuItem(
			{
				label: 'Copy URL',
				enabled: !Browser.isFirstLoad,
				click: function() {
					clipboard.writeText(Browser.view.webview.getAttribute('src'));
				}
			}
		)
	);
	menu.append(
		new MenuItem(
			{
				label: 'Copy Screenshot',
				accelerator: 'Cmd+Shift+C',
				click: function() {
					ipcRenderer.send('copy-screenshot', Browser.id);
				}
			}
		)
	);
	menu.append(
		new MenuItem(
			{
				type: 'separator'
			}
		)
	);
	if(Browser.view.isFirstLoad) {
		menu.append(
			new MenuItem(
				{
					label: 'Back',
					enabled: false
				}
			)
		);
		menu.append(
			new MenuItem(
				{
					label: 'Forward',
					enabled: false
				}
			)
		);
	}
	else {
		menu.append(
			new MenuItem(
				{
					label: 'Back',
					accelerator: 'Cmd+[',
					enabled: Browser.view.webview.canGoBack(),
					click: () => {
						Browser.view.webview.goBack();
					}
				}
			)
		);
		menu.append(
			new MenuItem(
				{
					label: 'Forward',
					accelerator: 'Cmd+]',
					enabled: Browser.view.webview.canGoForward(),
					click: () => {
						Browser.view.webview.goForward();
					}
				}
			)
		);
	}
	menu.append(
		new MenuItem(
			{
				label: 'Reload',
				accelerator: 'Cmd+R',
				enabled: !Browser.view.isFirstLoad,
				click: () => {
					Browser.view.webview.reload();
				}
			}
		)
	);

	// Weird calc to get menu position right
	var x = this.el.offsetWidth / 2 - 46;
	var y = this.el.offsetHeight + 4;

	menu.popup(remote.getCurrentWindow(), x, y);

}<|endoftext|>