From 8bea1e0807f36595d762592c030d4810396ada85 Mon Sep 17 00:00:00 2001
From: Eric Guzman
Date: Wed, 2 May 2012 15:30:27 -0700
Subject: CSS Panel - Add focus management to styles view delegate
---
.../css-panel/declaration.reel/declaration.js | 32 ++-
.../css-style-rule.reel/css-style-rule.js | 2 +-
js/panels/css-panel/style.reel/style.css | 2 +-
js/panels/css-panel/style.reel/style.html | 8 +
js/panels/css-panel/style.reel/style.js | 83 ++++++--
.../styles-view-container.html | 2 +-
js/panels/css-panel/styles-view-delegate.js | 233 +++++++++++++++++++++
js/panels/css-panel/styles-view-mediator.js | 190 -----------------
8 files changed, 333 insertions(+), 219 deletions(-)
create mode 100644 js/panels/css-panel/styles-view-delegate.js
delete mode 100644 js/panels/css-panel/styles-view-mediator.js
(limited to 'js/panels')
diff --git a/js/panels/css-panel/declaration.reel/declaration.js b/js/panels/css-panel/declaration.reel/declaration.js
index 873d2ce4..8ab19ad6 100644
--- a/js/panels/css-panel/declaration.reel/declaration.js
+++ b/js/panels/css-panel/declaration.reel/declaration.js
@@ -9,6 +9,9 @@ var Montage = require("montage/core/core").Montage,
ShorthandProps = require("js/panels/CSSPanel/css-shorthand-map");
exports.Declaration = Montage.create(Component, {
+ cssText : {
+ value: null
+ },
focusDelegate : {
value: null
},
@@ -42,6 +45,8 @@ exports.Declaration = Montage.create(Component, {
set: function(dec) {
this._declaration = dec;
+ this.cssText = dec.cssText;
+
///// creates data structure to use with tree component
this.buildStyleTree();
@@ -52,11 +57,34 @@ exports.Declaration = Montage.create(Component, {
"isEmpty": true
});
}
-//debugger;
+
this.needsDraw = true;
}
},
+ update : {
+ value: function() {
+ if(this.declaration.cssText !== this.cssText) {
+ ///// Needs update
+ this.treeController.branchControllers[0].content.forEach(function(obj) {
+ this.treeController.branchControllers[0].removeObjects(obj);
+ }, this );
+
+ this.buildStyleTree();
+
+ if(this.includeEmptyStyle) {
+ this.styleTree.properties.push({
+ "name": "property",
+ "value" : "value",
+ "isEmpty": true
+ });
+ }
+//debugger;
+ this.needsDraw = true;
+ }
+ }
+ },
+
buildStyleTree : {
value: function() {
var styles = Array.prototype.slice.call(this._declaration).sort();
@@ -124,8 +152,6 @@ exports.Declaration = Montage.create(Component, {
addNewStyleAfter : {
value: function(style) {
- //this.treeController.branchControllers[0].addObjects({
- foo1 = style.parentComponent.parentComponent;
style.parentComponent.parentComponent.contentController.addObjects({
name: 'property',
value: 'value',
diff --git a/js/panels/css-panel/rule-components/css-style-rule.reel/css-style-rule.js b/js/panels/css-panel/rule-components/css-style-rule.reel/css-style-rule.js
index 7b5a736f..cfa3e605 100644
--- a/js/panels/css-panel/rule-components/css-style-rule.reel/css-style-rule.js
+++ b/js/panels/css-panel/rule-components/css-style-rule.reel/css-style-rule.js
@@ -90,7 +90,7 @@ exports.CssStyleRule = Montage.create(Component, {
value: function() {
if(this.cssText !== this.rule.cssText) {
// TODO: add update for selector and stylesheet name
- this.declarationComponent.update();
+ //this.declarationComponent.update();
}
}
},
diff --git a/js/panels/css-panel/style.reel/style.css b/js/panels/css-panel/style.reel/style.css
index c6bb070c..6864e245 100644
--- a/js/panels/css-panel/style.reel/style.css
+++ b/js/panels/css-panel/style.reel/style.css
@@ -111,7 +111,7 @@
right: -1px;
}
.style-item .hintable-hint {
- color: #CCC;
+ color: #bdbdbd;
}
/* ------------------------
diff --git a/js/panels/css-panel/style.reel/style.html b/js/panels/css-panel/style.reel/style.html
index acc169be..9830a21e 100644
--- a/js/panels/css-panel/style.reel/style.html
+++ b/js/panels/css-panel/style.reel/style.html
@@ -58,6 +58,10 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
{
"type": "change",
"listener": {"@": "owner"}
+ },
+ {
+ "type": "stop",
+ "listener": {"@": "owner"}
}
]
},
@@ -80,6 +84,10 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
{
"type": "change",
"listener": {"@": "owner"}
+ },
+ {
+ "type": "stop",
+ "listener": {"@": "owner"}
}
]
}
diff --git a/js/panels/css-panel/style.reel/style.js b/js/panels/css-panel/style.reel/style.js
index c73da6e5..1d5a11a5 100644
--- a/js/panels/css-panel/style.reel/style.js
+++ b/js/panels/css-panel/style.reel/style.js
@@ -8,27 +8,14 @@ var Montage = require("montage/core/core").Montage,
TreeNode = require("js/components/treeview/tree-node").TreeNode;
exports.Style = Montage.create(TreeNode, {
- delegate : {
- value: null
- },
- disabledClass : {
- value: 'style-item-disabled'
- },
- editingStyleClass : {
- value: 'edit-style-item'
- },
- editNewEmptyClass : {
- value: 'edit-empty-style'
- },
- invalidStyleClass : {
- value: "style-item-invalid"
- },
- propertyText : {
- value: "property"
- },
- _valueText : {
- value: "value"
- },
+ delegate : { value: null },
+ disabledClass : { value: 'style-item-disabled' },
+ editingStyleClass : { value: 'edit-style-item' },
+ editNewEmptyClass : { value: 'edit-empty-style' },
+ invalidStyleClass : { value: "style-item-invalid" },
+
+ propertyText : { value: "property" },
+ _valueText : { value: "value" },
valueText : {
get: function() {
return this._valueText;
@@ -158,6 +145,27 @@ exports.Style = Montage.create(TreeNode, {
}
},
+ getSiblingStyle : {
+ value: function(which) {
+ var styles = this.parentComponent.parentComponent.childComponents.map(function(sub){
+ return sub.childComponents[0];
+ }),
+ index = styles.indexOf(this);
+
+ switch (which) {
+ case "first":
+ return styles[0];
+ case "last":
+ return styles[styles.length-1];
+ case "next":
+ return (index+1 < styles.length) ? styles[index+1] : null;
+ case "prev":
+ return (index-1 >= 0) ? styles[index-1] : null;
+ }
+ }
+ },
+
+
handleEvent : {
value: function(e) {
console.log(e);
@@ -206,11 +214,40 @@ exports.Style = Montage.create(TreeNode, {
handleStart : {
value: function(e) {
this.editing = true;
+
+ if(this.empty) {
+ this.editingNewStyle = true;
+ }
}
},
//// Handler for both hintable components
- handleStop : {
+ handlePropertyStop : {
+ value: function(e) {
+ var event = e;
+ ///// Function to determine if an empty (new) style should return
+ ///// to showing the add button, i.e. the fields were not clicked
+ function fieldsClicked() {
+ var clicked;
+ if(e._event.detail.originalEventType === 'mousedown') {
+ clicked = e._event.detail.originalEvent.target;
+ return clicked === this.propertyField.element || clicked === this.valueField.element;
+ }
+ return false;
+ }
+
+ this.editing = false;
+
+ if(this.sourceObject.isEmpty && !this.dirty && !fieldsClicked.bind(this)()) {
+ ///// Show add button
+ this.editingNewStyle = false;
+ }
+
+ this.delegate.handlePropertyStop(e, this);
+ }
+ },
+ //// Handler for both hintable components
+ handleValueStop : {
value: function(e) {
var event = e;
///// Function to determine if an empty (new) style should return
@@ -231,7 +268,7 @@ exports.Style = Montage.create(TreeNode, {
this.editingNewStyle = false;
}
- this.delegate.handleStyleStop(e);
+ this.delegate.handleValueStop(e, this);
}
},
diff --git a/js/panels/css-panel/styles-view-container.reel/styles-view-container.html b/js/panels/css-panel/styles-view-container.reel/styles-view-container.html
index 10b63087..658a8bac 100644
--- a/js/panels/css-panel/styles-view-container.reel/styles-view-container.html
+++ b/js/panels/css-panel/styles-view-container.reel/styles-view-container.html
@@ -38,7 +38,7 @@ No rights, expressed or implied, whatsoever to this software are provided by Mot
}
},
"stylesViewDelegate" : {
- "module": "js/panels/css-panel/styles-view-mediator",
+ "module": "js/panels/css-panel/styles-view-delegate",
"name": "StylesViewMediator",
"properties": {
"ruleListContainer": {"@": "ruleListContainer"}
diff --git a/js/panels/css-panel/styles-view-delegate.js b/js/panels/css-panel/styles-view-delegate.js
new file mode 100644
index 00000000..a76d25ad
--- /dev/null
+++ b/js/panels/css-panel/styles-view-delegate.js
@@ -0,0 +1,233 @@
+/*
+ This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
+ */
+
+var Montage = require("montage/core/core").Montage,
+ Component = require("montage/ui/component").Component,
+ Keyboard = require("js/mediators/keyboard-mediator").Keyboard;
+
+exports.StylesViewMediator = Montage.create(Component, {
+ newClassPrefix : {
+ value: "new-class"
+ },
+ stylesController : {
+ get: function() {
+ return this.application.ninja.stylesController;
+ },
+ set: function(){
+ return;
+ }
+ },
+
+ handleSelectorChange : {
+ value: function(rule, newSelector, ruleComponent) {
+ if(newSelector === "") {
+ //debugger;
+ ruleComponent.parentComponent.removeRule(ruleComponent);
+ return false;
+ }
+
+ rule.selectorText = newSelector;
+
+ ruleComponent.applied = this.ruleListContainer.displayedList.selection.every(function(el) {
+ return this._doesSelectorTargetElement(newSelector, el);
+ }, this);
+
+ }
+ },
+
+ ///// 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;
+
+ }
+ },
+
+ _doesSelectorTargetElement : {
+ value: function doesSelectorTargetElement(selector, element) {
+ var doc = element.ownerDocument,
+ matchingEls = Array.prototype.slice.call(doc.querySelectorAll(selector));
+ return matchingEls.indexOf(element) !== -1;
+ }
+ },
+
+ ///// Enable/Disable Style when checkbox is clicked
+ handleStyleToggle : {
+ value: function(rule, enable, style) {
+ if(enable) {
+ this.stylesController.setStyle(rule, style.propertyText, style.valueText, style.priority);
+ } else {
+ this.stylesController.deleteStyle(rule, style.propertyText);
+ }
+
+ this._dispatchChange();
+ }
+ },
+
+ handlePropertyStop: {
+ value: function(e, style) {
+ var key, nextFocus;
+
+ console.log("Handle Style Stop");
+
+ if(e._event.detail.type === 'keydown') {
+ key = e._event.detail.keyCode;
+
+ if(key === Keyboard.ENTER || key === Keyboard.TAB) {
+ e._event.detail.preventDefault();
+
+ if(e._event.detail.shiftKey) {
+ nextFocus = style.getSiblingStyle('prev') || style.getSiblingStyle('last');
+ nextFocus.valueField.start();
+ } else {
+ style.valueField.start();
+ }
+ }
+ }
+ }
+ },
+ handleValueStop: {
+ value: function(e, style) {
+ var key, nextFocus
+ console.log("Handle Value Stop");
+ console.log("Editing new style: ", style.editingNewStyle);
+
+ if(e._event.detail.type === 'keydown') {
+ key = e._event.detail.keyCode;
+
+ if(key === Keyboard.ENTER || key === Keyboard.TAB) {
+ e._event.detail.preventDefault();
+
+ if(e._event.detail.shiftKey) {
+ style.propertyField.start();
+ } else {
+ nextFocus = style.getSiblingStyle('next');
+ if(nextFocus) {
+ nextFocus.propertyField.start();
+ } else {
+ style.treeView.parentComponent.addNewStyleAfter(style);
+ style.editingNewStyle = false;
+ setTimeout(function() {
+ style.getSiblingStyle('next').propertyField.start();
+ }, 50);
+ }
+ }
+ }
+ }
+ }
+ },
+ handlePropertyChange : {
+ value: function(rule, property, value, oldProperty, style) {
+ var browserValue;
+
+ if(style.editingNewStyle) {
+ return false;
+ }
+
+ if(property === '') {
+ style.remove();
+ this._dispatchChange(oldProperty, browserValue);
+ return false;
+ }
+
+ ///// Remove old property and add new one
+ this.stylesController.deleteStyle(rule, oldProperty);
+ browserValue = this.stylesController.setStyle(rule, property, value);
+
+ ///// Mark style as invalid if the browser doesn't accept it
+ style.invalid = (browserValue === null);
+
+ console.log("BrowserValue: ", browserValue, rule);
+
+ this._dispatchChange(property, browserValue);
+ }
+ },
+ handleValueChange : {
+ value: function(rule, property, value, style) {
+ var browserValue, units;
+
+ if(value === '') {
+ style.remove();
+ this._dispatchChange(property, browserValue);
+ return false;
+ }
+
+ ///// Auto-fill units if not provided and units
+ ///// not previously stored
+ units = style.getUnits(value);
+ if(style.units && units === null && parseInt(value)) {
+ value += style.units;
+ style.valueField.value = value;
+ } else if (value !== '0') {
+ style.units = units;
+ }
+
+ ///// update value
+ browserValue = this.stylesController.setStyle(rule, property, value);
+
+ ///// Mark style as invalid if the browser doesn't accept it
+ style.invalid = (browserValue === null);
+
+ console.log("BrowserValue: ", browserValue, rule);
+
+ this._dispatchChange(property, browserValue);
+
+ if(style.editingNewStyle) {
+ style.treeView.parentComponent.addNewStyleAfter(style);
+ style.editingNewStyle = false;
+ }
+ }
+ },
+
+ handlePaste : {
+ value: function(e) {
+ var text = document.execCommand('insertHTML', null, e._event.clipboardData.getData("Text")).trim();
+
+ if(text.matches(/([a-zA-Z-]+:[a-zA-Z-]+){,1}/)) {
+
+ }
+ }
+ },
+
+ _dispatchChange : {
+ value: function(property, value) {
+ this.application.ninja.stage.updatedStage = true;
+ NJevent('elementChange', {
+ type : 'cssChange',
+ data: {
+ "prop": property,
+ "value": value
+ },
+ redraw: null
+ });
+ }
+ }
+});
\ No newline at end of file
diff --git a/js/panels/css-panel/styles-view-mediator.js b/js/panels/css-panel/styles-view-mediator.js
deleted file mode 100644
index c3154db0..00000000
--- a/js/panels/css-panel/styles-view-mediator.js
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- This file contains proprietary software owned by Motorola Mobility, Inc.
- No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
- (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
- */
-
-var Montage = require("montage/core/core").Montage,
- Component = require("montage/ui/component").Component,
- Keyboard = require("js/mediators/keyboard-mediator").Keyboard;
-
-exports.StylesViewMediator = Montage.create(Component, {
- newClassPrefix : {
- value: "new-class"
- },
- stylesController : {
- get: function() {
- return this.application.ninja.stylesController;
- },
- set: function(){
- return;
- }
- },
-
- handleSelectorChange : {
- value: function(rule, newSelector, ruleComponent) {
- if(newSelector === "") {
- debugger;
- ruleComponent.parentComponent.removeRule(ruleComponent);
- return false;
- }
-
- rule.selectorText = newSelector;
-
- ruleComponent.applied = this.ruleListContainer.displayedList.selection.every(function(el) {
- return this._doesSelectorTargetElement(newSelector, el);
- }, this);
-
- }
- },
-
- ///// 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;
-
- }
- },
-
- _doesSelectorTargetElement : {
- value: function doesSelectorTargetElement(selector, element) {
- var doc = element.ownerDocument,
- matchingEls = Array.prototype.slice.call(doc.querySelectorAll(selector));
- return matchingEls.indexOf(element) !== -1;
- }
- },
-
- ///// Enable/Disable Style when checkbox is clicked
- handleStyleToggle : {
- value: function(rule, enable, style) {
- if(enable) {
- this.stylesController.setStyle(rule, style.propertyText, style.valueText, style.priority);
- } else {
- this.stylesController.deleteStyle(rule, style.propertyText);
- }
-
- this._dispatchChange();
- }
- },
-
- handleStyleStop: {
- value: function(e) {
- console.log("Handle Style Stop");
- //debugger;
- if(e._event.detail.type === 'keydown') {
-
- }
- }
- },
- handlePropertyChange : {
- value: function(rule, property, value, oldProperty, style) {
- var browserValue;
-
- if(style.editingNewStyle) {
- return false;
- }
-
- if(property === '') {
- style.remove();
- this._dispatchChange(oldProperty, browserValue);
- return false;
- }
-
- ///// Remove old property and add new one
- this.stylesController.deleteStyle(rule, oldProperty);
- browserValue = this.stylesController.setStyle(rule, property, value);
-
- ///// Mark style as invalid if the browser doesn't accept it
- style.invalid = (browserValue === null);
-
- console.log("BrowserValue: ", browserValue, rule);
-
- this._dispatchChange(property, browserValue);
- }
- },
- handleValueChange : {
- value: function(rule, property, value, style) {
- var browserValue, units;
-
- if(value === '') {
- style.remove();
- this._dispatchChange(property, browserValue);
- return false;
- }
-
- ///// Auto-fill units if not provided and units
- ///// not previously stored
- units = style.getUnits(value);
- if(style.units && units === null && parseInt(value)) {
- value += style.units;
- style.valueField.value = value;
- } else if (value !== '0') {
- style.units = units;
- }
-
- ///// update value
- browserValue = this.stylesController.setStyle(rule, property, value);
-
- ///// Mark style as invalid if the browser doesn't accept it
- style.invalid = (browserValue === null);
-
- console.log("BrowserValue: ", browserValue, rule);
-
- this._dispatchChange(property, browserValue);
-
- if(style.editingNewStyle) {
- style.treeView.parentComponent.addNewStyleAfter(style);
- style.editingNewStyle = false;
- }
- }
- },
-
- handlePaste : {
- value: function(e) {
- var text = document.execCommand('insertHTML', null, e._event.clipboardData.getData("Text")).trim();
-
- if(text.matches(/([a-zA-Z-]+:[a-zA-Z-]+){,1}/)) {
-
- }
- }
- },
-
- _dispatchChange : {
- value: function(property, value) {
- this.application.ninja.stage.updatedStage = true;
- NJevent('elementChange', {
- type : 'cssChange',
- data: {
- "prop": property,
- "value": value
- },
- redraw: null
- });
- }
- }
-});
\ No newline at end of file
--
cgit v1.2.3