Skip to content

Commit 0187345

Browse files
SimeonCSimeonC
SimeonC
authored and
SimeonC
committed
fix(taBind): Ensure onSelectHandlers are allways applied with DOM changes
Fixes #446
1 parent 58f7537 commit 0187345

File tree

5 files changed

+38
-66
lines changed

5 files changed

+38
-66
lines changed

dist/textAngular.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/main.js

+13-27
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ textAngular.directive("textAngular", [
100100
// shim the .one till fixed
101101
var _func = function(){
102102
_element.off(event, _func);
103-
action();
103+
action.apply(this, arguments);
104104
};
105105
_element.on(event, _func);
106106
}, 100);
@@ -186,7 +186,7 @@ textAngular.directive("textAngular", [
186186
scope.displayElements.popover.css('display', 'block');
187187
scope.reflowPopover(_el);
188188
$animate.addClass(scope.displayElements.popover, 'in');
189-
oneEvent(element, 'click keyup', function(){scope.hidePopover();});
189+
oneEvent($document.find('body'), 'click keyup', function(){scope.hidePopover();});
190190
};
191191
scope.reflowPopover = function(_el){
192192
/* istanbul ignore if: catches only if near bottom of editor */
@@ -249,38 +249,24 @@ textAngular.directive("textAngular", [
249249
x: Math.max(0, startPosition.width + (event.clientX - startPosition.x)),
250250
y: Math.max(0, startPosition.height + (event.clientY - startPosition.y))
251251
};
252-
var applyImageSafeCSS = function(_el, css){
253-
_el = angular.element(_el);
254-
if(_el[0].tagName.toLowerCase() === 'img'){
255-
if(css.height){
256-
_el.attr('height', css.height);
257-
delete css.height;
258-
}
259-
if(css.width){
260-
_el.attr('width', css.width);
261-
delete css.width;
262-
}
263-
}
264-
_el.css(css);
265-
};
252+
266253
if(event.shiftKey){
267254
// keep ratio
268255
var newRatio = pos.y / pos.x;
269-
applyImageSafeCSS(_el, {
270-
width: ratio > newRatio ? pos.x : pos.y / ratio,
271-
height: ratio > newRatio ? pos.x * ratio : pos.y
272-
});
273-
}else{
274-
applyImageSafeCSS(_el, {
275-
width: pos.x,
276-
height: pos.y
277-
});
256+
pos.x = ratio > newRatio ? pos.x : pos.y / ratio;
257+
pos.y = ratio > newRatio ? pos.x * ratio : pos.y;
278258
}
259+
el = angular.element(_el);
260+
el.attr('height', Math.max(0, pos.y));
261+
el.attr('width', Math.max(0, pos.x));
262+
279263
// reflow the popover tooltip
280264
scope.reflowResizeOverlay(_el);
281265
};
282266
$document.find('body').on('mousemove', mousemove);
283-
oneEvent(scope.displayElements.resize.overlay, 'mouseup', function(){
267+
oneEvent($document.find('body'), 'mouseup', function(event){
268+
event.preventDefault();
269+
event.stopPropagation();
284270
$document.find('body').off('mousemove', mousemove);
285271
scope.showPopover(_el);
286272
});
@@ -291,7 +277,7 @@ textAngular.directive("textAngular", [
291277
scope.displayElements.resize.anchors[3].on('mousedown', resizeMouseDown);
292278

293279
scope.reflowResizeOverlay(_el);
294-
oneEvent(element, 'click', function(){scope.hideResizeOverlay();});
280+
oneEvent($document.find('body'), 'click', function(){scope.hideResizeOverlay();});
295281
};
296282
/* istanbul ignore next: pretty sure phantomjs won't test this */
297283
scope.hideResizeOverlay = function(){

lib/taBind.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
9393
if(!_isReadonly && _isContentEditable){
9494
var content = ngModel.$undoManager.undo();
9595
if(typeof content !== "undefined" && content !== null){
96-
element[0].innerHTML = content;
96+
_setInnerHTML(content);
9797
_setViewValue(content, false);
9898
/* istanbul ignore else: browser catch */
9999
if(element[0].childNodes.length) taSelection.setSelectionToElementEnd(element[0].childNodes[element[0].childNodes.length-1]);
@@ -107,7 +107,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
107107
if(!_isReadonly && _isContentEditable){
108108
var content = ngModel.$undoManager.redo();
109109
if(typeof content !== "undefined" && content !== null){
110-
element[0].innerHTML = content;
110+
_setInnerHTML(content);
111111
_setViewValue(content, false);
112112
/* istanbul ignore else: browser catch */
113113
if(element[0].childNodes.length) taSelection.setSelectionToElementEnd(element[0].childNodes[element[0].childNodes.length-1]);
@@ -131,6 +131,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
131131
if(ngModel.$viewValue !== '') ngModel.$setViewValue('');
132132
if(triggerUndo && ngModel.$undoManager.current() !== '') ngModel.$undoManager.push('');
133133
}else{
134+
_reApplyOnSelectorHandlers();
134135
if(ngModel.$viewValue !== _val){
135136
ngModel.$setViewValue(_val);
136137
if(triggerUndo) ngModel.$undoManager.push(_val);
@@ -416,7 +417,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
416417
}
417418
var val = _compileHtml();
418419
if(_defaultVal !== '' && val.trim() === ''){
419-
element[0].innerHTML = _defaultVal;
420+
_setInnerHTML(_defaultVal);
420421
taSelection.setSelectionToElementStart(element.children()[0]);
421422
}
422423
var triggerUndo = _lastKey !== event.keyCode && UNDO_TRIGGER_KEYS.test(event.keyCode);
@@ -513,7 +514,6 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
513514
$timeout(function(){
514515
dropFired = false;
515516
_setViewValue();
516-
_reApplyOnSelectorHandlers();
517517
}, 100);
518518
}
519519
};

src/textAngular.js

+17-31
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
886886
if(!_isReadonly && _isContentEditable){
887887
var content = ngModel.$undoManager.undo();
888888
if(typeof content !== "undefined" && content !== null){
889-
element[0].innerHTML = content;
889+
_setInnerHTML(content);
890890
_setViewValue(content, false);
891891
/* istanbul ignore else: browser catch */
892892
if(element[0].childNodes.length) taSelection.setSelectionToElementEnd(element[0].childNodes[element[0].childNodes.length-1]);
@@ -900,7 +900,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
900900
if(!_isReadonly && _isContentEditable){
901901
var content = ngModel.$undoManager.redo();
902902
if(typeof content !== "undefined" && content !== null){
903-
element[0].innerHTML = content;
903+
_setInnerHTML(content);
904904
_setViewValue(content, false);
905905
/* istanbul ignore else: browser catch */
906906
if(element[0].childNodes.length) taSelection.setSelectionToElementEnd(element[0].childNodes[element[0].childNodes.length-1]);
@@ -924,6 +924,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
924924
if(ngModel.$viewValue !== '') ngModel.$setViewValue('');
925925
if(triggerUndo && ngModel.$undoManager.current() !== '') ngModel.$undoManager.push('');
926926
}else{
927+
_reApplyOnSelectorHandlers();
927928
if(ngModel.$viewValue !== _val){
928929
ngModel.$setViewValue(_val);
929930
if(triggerUndo) ngModel.$undoManager.push(_val);
@@ -1209,7 +1210,7 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
12091210
}
12101211
var val = _compileHtml();
12111212
if(_defaultVal !== '' && val.trim() === ''){
1212-
element[0].innerHTML = _defaultVal;
1213+
_setInnerHTML(_defaultVal);
12131214
taSelection.setSelectionToElementStart(element.children()[0]);
12141215
}
12151216
var triggerUndo = _lastKey !== event.keyCode && UNDO_TRIGGER_KEYS.test(event.keyCode);
@@ -1306,7 +1307,6 @@ angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'
13061307
$timeout(function(){
13071308
dropFired = false;
13081309
_setViewValue();
1309-
_reApplyOnSelectorHandlers();
13101310
}, 100);
13111311
}
13121312
};
@@ -1548,7 +1548,7 @@ textAngular.directive("textAngular", [
15481548
// shim the .one till fixed
15491549
var _func = function(){
15501550
_element.off(event, _func);
1551-
action();
1551+
action.apply(this, arguments);
15521552
};
15531553
_element.on(event, _func);
15541554
}, 100);
@@ -1634,7 +1634,7 @@ textAngular.directive("textAngular", [
16341634
scope.displayElements.popover.css('display', 'block');
16351635
scope.reflowPopover(_el);
16361636
$animate.addClass(scope.displayElements.popover, 'in');
1637-
oneEvent(element, 'click keyup', function(){scope.hidePopover();});
1637+
oneEvent($document.find('body'), 'click keyup', function(){scope.hidePopover();});
16381638
};
16391639
scope.reflowPopover = function(_el){
16401640
/* istanbul ignore if: catches only if near bottom of editor */
@@ -1697,38 +1697,24 @@ textAngular.directive("textAngular", [
16971697
x: Math.max(0, startPosition.width + (event.clientX - startPosition.x)),
16981698
y: Math.max(0, startPosition.height + (event.clientY - startPosition.y))
16991699
};
1700-
var applyImageSafeCSS = function(_el, css){
1701-
_el = angular.element(_el);
1702-
if(_el[0].tagName.toLowerCase() === 'img'){
1703-
if(css.height){
1704-
_el.attr('height', css.height);
1705-
delete css.height;
1706-
}
1707-
if(css.width){
1708-
_el.attr('width', css.width);
1709-
delete css.width;
1710-
}
1711-
}
1712-
_el.css(css);
1713-
};
1700+
17141701
if(event.shiftKey){
17151702
// keep ratio
17161703
var newRatio = pos.y / pos.x;
1717-
applyImageSafeCSS(_el, {
1718-
width: ratio > newRatio ? pos.x : pos.y / ratio,
1719-
height: ratio > newRatio ? pos.x * ratio : pos.y
1720-
});
1721-
}else{
1722-
applyImageSafeCSS(_el, {
1723-
width: pos.x,
1724-
height: pos.y
1725-
});
1704+
pos.x = ratio > newRatio ? pos.x : pos.y / ratio;
1705+
pos.y = ratio > newRatio ? pos.x * ratio : pos.y;
17261706
}
1707+
el = angular.element(_el);
1708+
el.attr('height', Math.max(0, pos.y));
1709+
el.attr('width', Math.max(0, pos.x));
1710+
17271711
// reflow the popover tooltip
17281712
scope.reflowResizeOverlay(_el);
17291713
};
17301714
$document.find('body').on('mousemove', mousemove);
1731-
oneEvent(scope.displayElements.resize.overlay, 'mouseup', function(){
1715+
oneEvent($document.find('body'), 'mouseup', function(event){
1716+
event.preventDefault();
1717+
event.stopPropagation();
17321718
$document.find('body').off('mousemove', mousemove);
17331719
scope.showPopover(_el);
17341720
});
@@ -1739,7 +1725,7 @@ textAngular.directive("textAngular", [
17391725
scope.displayElements.resize.anchors[3].on('mousedown', resizeMouseDown);
17401726

17411727
scope.reflowResizeOverlay(_el);
1742-
oneEvent(element, 'click', function(){scope.hideResizeOverlay();});
1728+
oneEvent($document.find('body'), 'click', function(){scope.hideResizeOverlay();});
17431729
};
17441730
/* istanbul ignore next: pretty sure phantomjs won't test this */
17451731
scope.hideResizeOverlay = function(){

test/textAngular.spec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -975,11 +975,11 @@ describe('textAngular', function(){
975975
editorScope.hidePopover();
976976
expect(editorScope.displayElements.popover.hasClass('in')).toBe(false);
977977
});
978-
it('on click in editor', function(){
979-
element.triggerHandler('click');
978+
it('on click in editor', inject(function($document){
979+
$document.find('body').triggerHandler('click');
980980
editorScope.$parent.$digest();
981981
expect(editorScope.displayElements.popover.hasClass('in')).toBe(false);
982-
});
982+
}));
983983
it('should prevent mousedown from propagating up from popover', function(){
984984
var event;
985985
if(angular.element === jQuery){

0 commit comments

Comments
 (0)