attribute-getset-source.mustache revision e808b8824ca1091c8efb5669db9129e68e5e1c14
<div id="attrs" class="attrs">
<div class="header">Enter new values and click the "Set" buttons</div>
<div class="body">
<ul class="hints">
<li>Try entering valid and invalid values for x, y; or values which attempt to position the box outside it's parent (parent box co-ordinates are displayed next to the text box).</li>
<li>Try entering rgb, hex or keyword color values [ <code>rgb(255,0,0)</code>, <code>#ff0000</code>, <code>red</code> ].</li>
</ul>
<div class="fields">
<p>
<label for="x">x:</label>
<input type="text" name="x" id="x" />
<button type="button" class="action" id="setX">Set</button>
<span id="xhint" class="hint"></span>
</p>
<p>
<label for="y">y:</label>
<input type="text" name="y" id="y" />
<button type="button" class="action" id="setY">Set</button>
<span id="yhint" class="hint"></span>
</p>
<p>
<label for="color">color:</label>
<input type="text" name="color" id="color" />
<button type="button" class="action" id="setColor">Set</button>
</p>
</div>
</div>
<div class="footer">
<button type="button" class="action" id="setXY">Set XY</button>
<button type="button" class="action" id="setAll">Set All</button>
<button type="button" class="action" id="getAll">Get All</button>
</div>
</div>
<div id="boxParent"></div>
<script type="text/javascript">
// Get a new YUI instance
YUI().use("node", "attribute", function(Y) {
var boxParent = Y.one("#boxParent");
// Setup a custom class with attribute support
function Box(cfg) {
this._createNode(cfg);
// Attribute configuration
var attrs = {
"parent" : {
value: null
},
"x" : {
setter: function(val, name) {
// Pass through x value to xy
},
getter: function(val, name) {
// Get x value from xy
return this.get("xy")[0];
}
},
"y" : {
setter: function(val, name) {
// Pass through y value to xy
},
getter: function() {
// Get y value from xy
return this.get("xy")[1];
}
},
"xy" : {
// Actual stored xy co-ordinates
value: [0, 0],
setter: function(val, name) {
// Constrain XY value to the parent element.
// Returns the constrained xy value, which will
// be the final value stored.
return this.constrain(val);
},
validator: function(val, name) {
// Ensure we only store a valid data value
return (Y.Lang.isArray(val) && val.length == 2 && Y.Lang.isNumber(val[0]) && Y.Lang.isNumber(val[1]));
}
},
"color" : {
value: "olive",
getter: function(val, name) {
// Always normalize the returned value to
// a hex color value, even if the stored
// value is a keyword, or an rgb value.
if (val) {
return Y.Color.toHex(val);
} else {
return null;
}
},
validator: function(val, name) {
// Ensure we only store rgb, hex or keyword values.
}
}
};
this.addAttrs(attrs, cfg);
this._sync();
this._bind();
}
Box.BUFFER = 5;
// Create the box node
Box.prototype._createNode = function() {
this._node = Y.Node.create('<div class="yui3-box"><p>Positioned Box</p><p class="coord"></p><p class="color">None</p></div>');
};
// Update rendered state to match the attribute state
Box.prototype._sync = function() {
this._syncParent();
this._syncXY();
this._syncColor();
};
Box.prototype._syncParent = function() {
this.get("parent").appendChild(this._node);
};
Box.prototype._syncXY = function() {
this._node.setXY(this.get("xy"));
};
Box.prototype._syncColor = function() {
this._node.setStyle("backgroundColor", this.get("color"));
};
// Bind listeners for attribute change events
Box.prototype._bind = function() {
// Reflect any changes in xy, to the rendered Node
this.after("xyChange", this._syncXY);
// Reflect any changes in color, to the rendered Node
// and output the color value received from get
this.after("colorChange", this._syncColor);
// Append the rendered node to the parent provided
this.after("parentChange", this._syncParent);
};
// Get min, max unconstrained values for X. Using Math.round to handle FF3's sub-pixel region values
Box.prototype.getXConstraints = function() {
var parentRegion = this.get("parent").get("region");
return [Math.round(parentRegion.left + Box.BUFFER), Math.round(parentRegion.right - this._node.get("offsetWidth") - Box.BUFFER)];
};
// Get min, max unconstrained values for Y. Using Math.round to handle FF3's sub-pixel region values
Box.prototype.getYConstraints = function() {
var parentRegion = this.get("parent").get("region");
return [Math.round(parentRegion.top + Box.BUFFER), Math.round(parentRegion.bottom - this._node.get("offsetHeight") - Box.BUFFER)];
};
// Constrain the x,y value provided
Box.prototype.constrain = function(val) {
// If the X value places the box outside it's parent,
// modify it's value to place the box inside it's parent.
var xConstraints = this.getXConstraints();
if (val[0] < xConstraints[0]) {
val[0] = xConstraints[0];
} else {
if (val[0] > xConstraints[1]) {
val[0] = xConstraints[1];
}
}
// If the Y value places the box outside it's parent,
// modify it's value to place the box inside it's parent.
var yConstraints = this.getYConstraints();
if (val[1] < yConstraints[0]) {
val[1] = yConstraints[0];
} else {
if (val[1] > yConstraints[1]) {
val[1] = yConstraints[1];
}
}
return val;
};
Y.augment(Box, Y.Attribute);
// ------
// Create a new instance of Box
var box = new Box({
parent : boxParent
});
// Set references to form controls
var xTxt = Y.one("#x");
var yTxt = Y.one("#y");
var colorTxt = Y.one("#color");
var xHint = Y.one("#xhint");
var yHint = Y.one("#yhint");
function getAll() {
colorTxt.set("value", box.get("color"));
}
// Bind DOM events for Form Controls
// Use event delegation for the action button clicks
Y.delegate("click", function(e) {
// Get Node target from the event object
// We already know it's a button which has an action because
// of our selector (button.action), so all we need to do is
// route it based on the id.
var id = e.currentTarget.get("id");
switch (id) {
case "setXY":
break;
case "setX":
break;
case "setY":
break;
case "setColor":
break;
case "setAll":
break;
case "getAll":
getAll();
break;
default:
break;
}
}, "#attrs", "button.action");
// Bind listeners to provide min, max unconstrained value hints for x, y
// (focus/blur doesn't bubble, so bind individual listeners)
Y.on("focus", function() {
var minmax = box.getXConstraints();
xHint.set("innerHTML", "Valid values: " + minmax[0] + " to " + minmax[1]);
}, xTxt);
Y.on("focus", function() {
var minmax = box.getYConstraints();
yHint.set("innerHTML", "Valid values: " + minmax[0] + " to " + minmax[1]);
}, yTxt);
Y.on("blur", function() {
xHint.set("innerHTML", "");
}, xTxt);
Y.on("blur", function() {
yHint.set("innerHTML", "");
}, yTxt);
getAll();
});
</script>