The next step, part 2
-
Upload
pat-cavit -
Category
Technology
-
view
2.593 -
download
1
description
Transcript of The next step, part 2
The Next Step, Part 2
Where have we been?
SimpleYUI, inline JS
External JS file via <script>
Plugin for Node objects
Simple Widget
Why continue?
Then where are we going?
Widget provides some structure
initializer : function(config) { var node = this.get("node"); if(node) { if(!this.get("content")) { this.set("content", node.getAttribute("title")); } node.removeAttribute("title"); }},
destructor : function() { this._handlers.detach(); this._handlers = null;},
renderUI
bindUI
bindUI : function() { var node = this.get("node"); this._handlers = node.on({ mouseenter : { fn : function() { this.get('boundingBox').setStyles({
left : e.pageX + 5, top : e.pageY + 5 }); this.show(); }, context : this }, mouseleave: Y.bind(this.hide, this) });},
syncUI
syncUI : function() { this.publish("sync", { defaultFn : Y.bind(function() { this.get('contentBox') .setContent(this.get('content'));
}, this) }).fire();}
YUI().use("gallery-tooltip", function(Y) { var tooltip = new Y.Tooltip({ visible : false, render : true, node : Y.one("a") });});
Now what?
Plugins for new behaviors
new Y.Tooltip({ visible : false, render : true, node : Y.one("a"), plugins : [ Y.Plugin.TooltipSimpleDisplay ]});
//orvar tooltip = New Y.Tooltip({ visible : false, render : true, node : Y.one("a")});tooltip.plug(Y.Plugin.TooltipSimpleDisplay);
Simple Plugin
Y.Base.create("TooltipSimpleDisplay", Y.Plugin.Base, [], { initializer : function() { var host = this.get("host"); host.on("sync", function(e) { //prevent default sync method e.preventDefault();
var content = host.get('content') + " + plugin";
host.get("contentBox").setContent(content); }, this); }}, { NS : 'TooltipSimpleDisplay' });
Powered by Custom Events
That call to preventDefault is important
syncUI : function() { this.publish("sync", { //Now we see why this slightly //odd syntax was important //it lets this method be //overriden by plugins defaultFn : Y.bind(function() { this.get('contentBox')
.setContent(this.get('content')); }, this) }).fire();}
We can go further
http://www.flickr.com/photos/st3f4n/4501172754/
Transitions Module
Adding some flash
new Y.Tooltip({ visible : false, render : true, node : Y.one("a"), plugins : [ //from gallery Y.Plugin.TransitionOverlay ]});
Still, not really all that useful
http://www.flickr.com/photos/zen/1174874997/
WidgetIO
YQL
WidgetYQL
Y.Base.create("WidgetYQL", Y.Plugin.Base, [], { _yql : null, initializer : function() { this.after([
"queryChange", "formatterChange", "configChange" ], this._createYQL, this); },_ _createYQL : function() { attrs = this.getAttrs([ "query", "formatter", "config" ]); this._yql = new Y.YQLRequest( attrs.query, Y.bind(attrs.formatter, this), attrs.config ); }, sendQuery : function() { return this._yql.send(); }
tooltip.plug(Y.Plugin.WidgetYQL, { query : "SELECT * FROM ...", formatter : function(r) { host._yqlData = r.query.results.quote;
host.set("content", r.query...LastTradePriceOnly); host.fire("yqlResponse", r); }});
Repeating yourself sucks
Plugins are full JS objects
Plugins on top of plugins
http://idont/have/a/source/its/just/funny
initializer : function() { var host = this.get("host"); host.plug(Y.namespace("Plugin").WidgetYQL, { query : "SELECT * FROM ...", formatter : function(r) { host.set("content", r.query.res...); host.fire("yqlResponse"); } }
host.on(["visibleChange", "renderedChange"], function(e) { host.YQL.sendQuery(); }, this); host.on("yqlResponse", function() { host.syncUI(); });}
Multiple plugins
new Y.Tooltip({ visible : false, render : true, node : Y.one('a'), plugins : [ Y.Plugin.TransitionOverlay,
Y.Plugin.TooltipYQL, Y.Plugin.TooltipDisplay ]});
Done? Not so fast.
Prove it works, use tests
Widget & YUITest
var test = new Y.Test.Case({ name : "Simple Tooltip Test",
"tooltip should render without errors" : function() { var tooltip = new Y.Tooltip({ visible : false, render : true,
node : Y.one('a') }); }
});
//add & run testY.Test.Runner.add(test);Y.Test.Runner.run();
Didn’t do anything too dumb
(yet)
Not very useful though
http://www.flickr.com/photos/sewitsforyou/3466154372/
Event simulation adds utility
new Y.Test.Case({ name : "Tooltip Event Simulation Test", "tooltip should show on mouseenter" : function() { //create tooltip var tooltip = ... //simulate mousing over the link Y.one("a").simulate("mouseover"); //fail if the tooltip isn't visible Y.assert( tooltip.get("visible"), "Tooltip wasn't visible“ ); }});
Lots of JS is async though
Sync tests don’t solve everything
this.wait()
this.resume()
"tooltip should transition to visible" : function() { var tooltip = ... //resume the test once the transition has finished tooltip.transitionPlugin.on("end", function(visible) { this.resume(function() { Y.assert(visible && tooltip.get("visible"),
"Tooltip wasn't visible"); }); }, this); //show the overlay, triggering the transition tooltip.show(); //wait for a bit for the transition to end this.wait(1000);}
Inline JS, great for prototyping
Bad for more complicated testing
Scaling up the testing
new Y.Test.Case({ name : "Advanced Tests", //set up a tooltip before every test, clean it up setUp : function() { ... }, tearDown : function() { ... }, //multiple tests "tooltip should render without errors" : function() { ... },
"tooltip should show on mouseenter" : function() { ... },
"tooltip should transition to visible" : function() { ... },
"YQL plugin should get data from YQL" : function() { ... }
});
YUI Gallery
You’ve been meaning to share more anyways, right?
One way to flesh out your idea
Definitely not the only one
Patrick Cavit
@tivac on twitter
“tivac” in IRC
http://patcavit.com
http://lanyrd.com/people/tiva
c/