From 830b6577ee25a6955bd4e275f216e1cadeff168c Mon Sep 17 00:00:00 2001 From: Eric Guzman Date: Thu, 10 May 2012 13:20:19 -0700 Subject: CSS Panel - Rule List refactor Improved adding, updating, and sorting of rules in rule list. --- .../rule-list-container.js | 33 ++-- js/panels/css-panel/rule-list.reel/rule-list.js | 168 +++++++++++++-------- js/panels/css-panel/styles-view-delegate.js | 109 +++++++------ 3 files changed, 175 insertions(+), 135 deletions(-) diff --git a/js/panels/css-panel/rule-list-container.reel/rule-list-container.js b/js/panels/css-panel/rule-list-container.reel/rule-list-container.js index 5371ec9a..d9aae867 100644 --- a/js/panels/css-panel/rule-list-container.reel/rule-list-container.js +++ b/js/panels/css-panel/rule-list-container.reel/rule-list-container.js @@ -11,8 +11,8 @@ exports.RuleListContainer = Montage.create(Component, { _instanceToAdd : { value: null }, _appendElement : { value: null }, _lastDisplayedList : { value: null }, - _displayedList : { value: null }, + _displayedList : { value: null }, displayedList : { get: function() { return this._displayedList; @@ -74,22 +74,21 @@ exports.RuleListContainer = Montage.create(Component, { add : { value: function(selection) { var stylesController = this.application.ninja.stylesController, - listInstance = Montage.create(this.ruleListComponent), + instance = Montage.create(this.ruleListComponent), container = document.createElement('div'), rules, ruleListLog; rules = this.getRulesForSelection(selection); - this._instanceToAdd = listInstance; - listInstance.rules = rules; + this._instanceToAdd = instance; + instance.rules = rules; ruleListLog = { selection: selection, - component : listInstance + component : instance }; this.ruleLists.push(ruleListLog); - this._appendElement = container; this.needsDraw = true; @@ -120,17 +119,21 @@ exports.RuleListContainer = Montage.create(Component, { update : { value: function() { - var stylesController = this.application.ninja.stylesController, - rules = this.getRulesForSelection(this.displayedList.selection), - newRules; + this.displayedList.component.rules = this.getRulesForSelection(this.displayedList.selection); + - newRules = rules.filter(function(rule) { - return rule.type !== 'inline' && this.displayedList.component.rules.indexOf(rule) === -1; - }, this); + ///// Update the currently displayed list + //this.displayedList.component.update(); - newRules.forEach(function(rule) { - this.displayedList.component.addRule(rule); - },this); + ///// Find the new rules which need to be added to the rule-list +// newRules = rules.filter(function(rule) { +// return rule.type !== 'inline' && this.displayedList.component.rules.indexOf(rule) === -1; +// }, this); +// +// ///// Add the new rules +// newRules.forEach(function(rule) { +// this.displayedList.component.addRule(rule); +// },this); } }, diff --git a/js/panels/css-panel/rule-list.reel/rule-list.js b/js/panels/css-panel/rule-list.reel/rule-list.js index c9eeb64b..5f6afee5 100644 --- a/js/panels/css-panel/rule-list.reel/rule-list.js +++ b/js/panels/css-panel/rule-list.reel/rule-list.js @@ -12,35 +12,6 @@ exports.RuleList = Montage.create(Component, { ruleNodeName : { value: 'li' }, _needsScrollToBottom: { value: null }, - _rules: { value: null }, - rules: { - get: function() { - return this._rules; - }, - set: function(list) { - if(!list) { - return null; - } - //debugger; - console.log('list: ', list); - this._rules = list; - - ///// remove previously added rules - if(this.childComponents){ - this.childComponents.forEach(function(ruleComponent) { - this.removeRule(ruleComponent); - }, this); - } - - this._rules.forEach(function(rule) { - this.addRule(rule); - }, this); - - this.needsDraw = true; - - } - }, - childComponents : { value: [], distinct: true @@ -54,51 +25,98 @@ exports.RuleList = Montage.create(Component, { value: [], distinct: true }, - addRule: { - value: function(rule) { - var componentBase = this.supportedRules[rule.type], - instance, el; - ///// Draw the rule if we have a template for the rule type - if(componentBase) { - instance = Montage.create(componentBase); - instance.rule = rule; + update : { + value: function(rules) { + this.childComponents.forEach(function(component) { + component.update(); + }, this); + } + }, - if(this.focusDelegate) { - instance.focusDelegate = this.focusDelegate; + _rules: { value: null }, + rules: { + get: function() { + return this._rules; + }, + set: function(list) { + if(!list) { + return null; + } + + var foundIndices = []; + + //// Iterate existing rules, update those which rule exists in new + //// rule list + this.childComponents.forEach(function(ruleComponent, i, drawnRules) { + //// If rule exists in new list, update it + var index = list.indexOf(ruleComponent.rule); + + if(ruleComponent.rule.type === 'inline') { + //// Let's emulate finding the line rule at the first index + index = 0; } - this.rulesToDraw.push(instance); - this.needsDraw = true; - } + if(index !== -1) { + // found rule in our component list, or it's the inline rule + ruleComponent.update(); + foundIndices.push(index); + } else { + this.rulesToRemove.push(ruleComponent); + } + }, this); - return instance; - } - }, + //// Find rules to add + list.forEach(function(rule, index) { + //// If we haven't updated the rule already, + //// we're dealing with a new rule to add + if(foundIndices.indexOf(index) === -1) { + this.addRule(rule, index); + } + }, this); + + this._rules = list; - removeRule : { - value: function(rule) { - this.childComponents.splice(this.childComponents.indexOf(rule), 1); - this.rulesToRemove.push(rule); this.needsDraw = true; + } }, - update : { - value: function(rules) { - this.childComponents.forEach(function(component) { - component.update(); - }, this); + addRule: { + value: function(rule, atIndex) { + var insertIndex = atIndex || this.childComponents.length; - //// TODO: find new styles based on selection + this.rulesToDraw.push({ + rule: rule, + index: insertIndex, + instance : null + }); + this.needsDraw = true; } }, willDraw : { value: function() { - this.rulesToDraw.forEach(function(component) { - component.element = document.createElement(this.ruleNodeName); + this.rulesToDraw.forEach(function(ruleObj) { + var el = document.createElement(this.ruleNodeName); + + var componentBase = this.supportedRules[ruleObj.rule.type], + instance; + + ///// Draw the rule if we have a template for the rule type + if(!componentBase) { return false; } + + instance = Montage.create(componentBase); + instance.element = document.createElement(this.ruleNodeName); + instance.rule = ruleObj.rule; + + if(this.focusDelegate) { + instance.focusDelegate = this.focusDelegate; + } + + ruleObj.instance = instance; + }, this); } @@ -114,21 +132,41 @@ exports.RuleList = Montage.create(Component, { this._needsScrollToBottom = false; } - //// Iterate through all rules that need draw and append them - this.rulesToDraw.forEach(function(component) { - this.element.appendChild(component.element); - this._needsScrollToBottom = this.needsDraw = true; - this.childComponents.push(component); - component.needsDraw = true; + //// Iterate through all rules needing removal + console.log("Rule List :: Rules to draw:,", this.rulesToDraw.length); + this.rulesToRemove.forEach(function(ruleComponent) { + var componentIndex = this.childComponents.indexOf(ruleComponent); + this.childComponents.splice(componentIndex, 1); + this.element.removeChild(ruleComponent.element); }, this); //// Iterate through all rules that need draw and append them - this.rulesToRemove.forEach(function(component) { - this.element.removeChild(component.element); + this.rulesToDraw.forEach(function(ruleObj) { + var ruleAtIndex = this.childComponents[ruleObj.index]; + + if(ruleAtIndex) { + //// Insert rule at appropriate index + this.element.insertBefore(ruleObj.instance.element, ruleAtIndex.element); + } else { + this.element.appendChild(ruleObj.instance.element); + } + + this._needsScrollToBottom = this.needsDraw = true; + this.childComponents.push(ruleObj.instance); + ruleObj.instance.needsDraw = true; }, this); ///// Null out any rules that were just drawn this.rulesToDraw.length = 0; + + } + }, + + didDraw : { + value: function() { + this.rulesToRemove.forEach(function(ruleObj) { + ruleObj.instance = null; + }, this); this.rulesToRemove.length = 0; } } diff --git a/js/panels/css-panel/styles-view-delegate.js b/js/panels/css-panel/styles-view-delegate.js index 71b4a8dd..3f29ba27 100644 --- a/js/panels/css-panel/styles-view-delegate.js +++ b/js/panels/css-panel/styles-view-delegate.js @@ -72,61 +72,6 @@ exports.StylesViewMediator = Montage.create(Component, { } }, - - /// Toolbar Button Actions - /// ----------------------- - - ///// Add rule button action - handleAddAction : { - value: function(e) { - var selector, - newRule, - applies = true; - - ///// Get selection prefix - if(this.ruleListContainer.displayedList.selection.length > 1) { - selector = this.stylesController.generateClassName(null, true); - } else { - selector = this.stylesController.generateClassName(this.newClassPrefix); - } - - ///// Create the rule with generated selector - newRule = this.application.ninja.stylesController.addRule('.'+selector, ' { }'); - - ///// Add the generated class to each element in selection - ///// and check whether it applies to the element - this.ruleListContainer.displayedList.selection.forEach(function(el) { - this.stylesController.addClass(el, selector); - - if(applies) { - applies = (this._doesSelectorTargetElement('.'+selector, el)); - } - },this); - - ///// Add rule directly to the rule list - this.ruleListContainer.displayedList.component.addRule(newRule).applied = applies; - - } - }, - - ///// Show/hide computed style sub panel - handleComputedAction : { - value: function(e) { - var container = this.ownerComponent, - panelToShow = (container.contentPanel === "computed") ? "rules" : "computed"; - - ///// Handle showing and hiding of the add button - if(panelToShow === "computed") { - container.toolbar.hideButton('add'); - } else { - container.toolbar.showButton('add'); - } - - container.contentPanel = panelToShow; - this.ownerComponent.handleSelectionChange(); - } - }, - ///// Style event handlers //// ------------------------------------- @@ -270,6 +215,60 @@ exports.StylesViewMediator = Montage.create(Component, { } }, + /// Toolbar Button Actions + /// ----------------------- + + ///// Add rule button action + handleAddAction : { + value: function(e) { + var selector, + newRule, + applies = true; + + ///// Get selection prefix + if(this.ruleListContainer.displayedList.selection.length > 1) { + selector = this.stylesController.generateClassName(null, true); + } else { + selector = this.stylesController.generateClassName(this.newClassPrefix); + } + + ///// Create the rule with generated selector + newRule = this.application.ninja.stylesController.addRule('.'+selector, ' { }'); + + ///// Add the generated class to each element in selection + ///// and check whether it applies to the element + this.ruleListContainer.displayedList.selection.forEach(function(el) { + this.stylesController.addClass(el, selector); + + if(applies) { + applies = (this._doesSelectorTargetElement('.'+selector, el)); + } + },this); + + ///// Add rule directly to the rule list + this.ruleListContainer.displayedList.component.addRule(newRule).applied = applies; + + } + }, + + ///// Show/hide computed style sub panel + handleComputedAction : { + value: function(e) { + var container = this.ownerComponent, + panelToShow = (container.contentPanel === "computed") ? "rules" : "computed"; + + ///// Handle showing and hiding of the add button + if(panelToShow === "computed") { + container.toolbar.hideButton('add'); + } else { + container.toolbar.showButton('add'); + } + + container.contentPanel = panelToShow; + this.ownerComponent.handleSelectionChange(); + } + }, + ///// Utilities //// ------------------------------------- -- cgit v1.2.3