Skip to content

Commit d373fe1

Browse files
committedJul 22, 2016
feat(textAngularManager): Added a function updateStyles() to force all the updateSelectedStyles() to be updated.
feat(textAngularManager): We now detect calls which register Editors and Toolbars or modify them and automatically initialize them. textAngularManager calls that trigger this initialization are: registerEditor(), unregisterEditor() registerToolbar(), unregisterToolbar(), resetToolsDisplay(), updateToolDisplay(), resetToolDisplay(), removeTool(), addTool(), addToolToToolbar(), refreshEditor() feat(textAngularManager.spec): Added test for updateSelectedStyles()
1 parent a0024a2 commit d373fe1

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed
 

‎src/main.js

+51-1
Original file line numberDiff line numberDiff line change
@@ -579,13 +579,44 @@ textAngular.directive("textAngular", [
579579
};
580580
}
581581
]);
582-
textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'taRegisterTool', function(taToolExecuteAction, taTools, taRegisterTool){
582+
textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'taRegisterTool', '$interval', '$rootScope', function(taToolExecuteAction, taTools, taRegisterTool, $interval, $rootScope){
583583
// this service is used to manage all textAngular editors and toolbars.
584584
// All publicly published functions that modify/need to access the toolbar or editor scopes should be in here
585585
// these contain references to all the editors and toolbars that have been initialised in this app
586586
var toolbars = {}, editors = {};
587587
// toolbarScopes is an ARRAY of toolbar scopes
588588
var toolbarScopes = [];
589+
// we touch the time any change occurs through register of an editor or tool so that we
590+
// in the future will fire and event to trigger an updateSelection
591+
var timeRecentModification = 0;
592+
var updateStyles = function(selectedElement){
593+
angular.forEach(editors, function(editor) {
594+
editor.editorFunctions.updateSelectedStyles(selectedElement);
595+
});
596+
};
597+
var triggerInterval = 50;
598+
var triggerIntervalTimer;
599+
var setupTriggerUpdateStyles = function() {
600+
timeRecentModification = Date.now();
601+
/* istanbul ignore next: setup a one time updateStyles() */
602+
triggerIntervalTimer = $interval(function() {
603+
updateStyles();
604+
triggerIntervalTimer = undefined;
605+
}, triggerInterval, 1, false); // only trigger once
606+
};
607+
/* istanbul ignore next: make sure clean up on destroy */
608+
$rootScope.$on('destroy', function() {
609+
if (triggerIntervalTimer) {
610+
$interval.cancel(triggerIntervalTimer);
611+
triggerIntervalTimer = undefined;
612+
}
613+
});
614+
var touchModification = function() {
615+
if (Math.abs(Date.now() - timeRecentModification) > triggerInterval) {
616+
// we have already triggered the updateStyles a long time back... so setup it again...
617+
setupTriggerUpdateStyles();
618+
}
619+
};
589620
// when we focus into a toolbar, we need to set the TOOLBAR's $parent to be the toolbars it's linked to.
590621
// We also need to set the tools to be updated to be the toolbars...
591622
return {
@@ -639,6 +670,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
639670
angular.forEach(toolbarScope.tools, function(toolScope){
640671
if(toolScope.activeState){
641672
toolbarScope._parent = scope;
673+
// selectedElement may be undefined if nothing selected
642674
toolScope.active = toolScope.activeState(selectedElement);
643675
}
644676
});
@@ -721,6 +753,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
721753
}
722754
}
723755
};
756+
touchModification();
724757
return editors[name].editorFunctions;
725758
},
726759
// retrieve editor by name, largely used by testing suites only
@@ -729,6 +762,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
729762
},
730763
unregisterEditor: function(name){
731764
delete editors[name];
765+
touchModification();
732766
},
733767
// registers a toolbar such that it can be linked to editors
734768
registerToolbar: function(scope){
@@ -739,6 +773,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
739773
angular.forEach(editors, function(_editor){
740774
_editor._registerToolbarScope(scope);
741775
});
776+
touchModification();
742777
},
743778
// retrieve toolbar by name, largely used by testing suites only
744779
retrieveToolbar: function(name){
@@ -762,6 +797,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
762797
}
763798
}
764799
toolbarScopes = tmp;
800+
touchModification();
765801
},
766802
// functions for updating the toolbar buttons display
767803
updateToolsDisplay: function(newTaTools){
@@ -777,20 +813,23 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
777813
angular.forEach(taTools, function(_newTool, key){
778814
_this.resetToolDisplay(key);
779815
});
816+
touchModification();
780817
},
781818
// update a tool on all toolbars
782819
updateToolDisplay: function(toolKey, _newTool){
783820
var _this = this;
784821
angular.forEach(toolbars, function(toolbarScope, toolbarKey){
785822
_this.updateToolbarToolDisplay(toolbarKey, toolKey, _newTool);
786823
});
824+
touchModification();
787825
},
788826
// resets a tool to the default/starting state on all toolbars
789827
resetToolDisplay: function(toolKey){
790828
var _this = this;
791829
angular.forEach(toolbars, function(toolbarScope, toolbarKey){
792830
_this.resetToolbarToolDisplay(toolbarKey, toolKey);
793831
});
832+
touchModification();
794833
},
795834
// update a tool on a specific toolbar
796835
updateToolbarToolDisplay: function(toolbarKey, toolKey, _newTool){
@@ -825,18 +864,21 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
825864
}
826865
}
827866
});
867+
touchModification();
828868
},
829869
// toolkey, toolDefinition are required. If group is not specified will pick the last group, if index isnt defined will append to group
830870
addTool: function(toolKey, toolDefinition, group, index){
831871
taRegisterTool(toolKey, toolDefinition);
832872
angular.forEach(toolbars, function(toolbarScope){
833873
toolbarScope.addTool(toolKey, toolDefinition, group, index);
834874
});
875+
touchModification();
835876
},
836877
// adds a Tool but only to one toolbar not all
837878
addToolToToolbar: function(toolKey, toolDefinition, toolbarKey, group, index){
838879
taRegisterTool(toolKey, toolDefinition);
839880
toolbars[toolbarKey].addTool(toolKey, toolDefinition, group, index);
881+
touchModification();
840882
},
841883
// this is used when externally the html of an editor has been changed and textAngular needs to be notified to update the model.
842884
// this will call a $digest if not already happening
@@ -846,6 +888,7 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
846888
/* istanbul ignore else: phase catch */
847889
if(!editors[name].scope.$$phase) editors[name].scope.$digest();
848890
}else throw('textAngular Error: No Editor with name "' + name + '" exists');
891+
touchModification();
849892
},
850893
// this is used by taBind to send a key command in response to a special key event
851894
sendKeyCommand: function(scope, event){
@@ -860,6 +903,13 @@ textAngular.service('textAngularManager', ['taToolExecuteAction', 'taTools', 'ta
860903
return false;
861904
}
862905
},
906+
//
907+
// When a toolbar and tools are created, it isn't until there is a key event or mouse event
908+
// that the updateSelectedStyles() is called behind the scenes.
909+
// This function forces an update through the existing editors to help the application make sure
910+
// the inital state is correct.
911+
//
912+
updateStyles: updateStyles,
863913
// for testing
864914
getToolbarScopes: function () { return toolbarScopes; }
865915
};

‎test/textAngularManager.spec.js

+16
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ describe('textAngularManager', function(){
383383
$rootScope.$digest();
384384
editorScope = textAngularManager.retrieveEditor('test');
385385
}));
386+
386387
describe('updateSelectedStyles', function(){
387388
describe('should activate buttons correctly', function(){
388389
it('without rangyrange passed through', function(){
@@ -398,6 +399,21 @@ describe('textAngularManager', function(){
398399
});
399400
});
400401

402+
describe('updateSelectedStyles through textAngularMananger', function(){
403+
describe('should activate buttons correctly', function(){
404+
it('without rangyrange passed through', function(){
405+
textAngularManager.updateStyles();
406+
$rootScope.$digest();
407+
expect(element.find('.ta-toolbar button.active').length).toBe(1);
408+
});
409+
it('with rangyrange passed through', function(){
410+
textAngularManager.updateStyles({});
411+
$rootScope.$digest();
412+
expect(element.find('.ta-toolbar button.active').length).toBe(1);
413+
});
414+
});
415+
});
416+
401417
describe('sendKeyCommand', function(){
402418
it('should return true if there is a relevantCommandKeyCode on a tool', function(){
403419
expect(editorScope.editorFunctions.sendKeyCommand({metaKey: true, which: 21})).toBe(true);

0 commit comments

Comments
 (0)