├── README.markdown ├── plugins ├── delegate.js └── once.js ├── test └── delegate.htm ├── vine.js └── vine.min.js /README.markdown: -------------------------------------------------------------------------------- 1 | # Vine.js 2 | * 1.6KB (about .9k gzipped) 3 | * Can be used with or without the DOM 4 | 5 | ## Goal 6 | * <2KB 7 | * Cross-browser 8 | * Easily embedded and used in libraries 9 | * usable stand-alone 10 | 11 | ## Tested in: 12 | * Chrome 11 13 | * IE 8 14 | * FF 4 15 | * Opera 11 16 | 17 | ## API: 18 | 19 | * vine.bind(target, type, handler \[, data\]\) 20 | * binds a handler to the element 21 | * target:Object/Element -- object event is bound to 22 | * type:String -- type, or space seperated list of types, of event(s) to bind 23 | * handler:Function(event:vine.Event) -- handler to bind 24 | * data:Object -- optional data to be set as the event's .data field 25 | * vine.unbind(target[, type\]\[, handler\) 26 | * unbinds a handler based on criteria (unbinds all events if only a target is passed) 27 | * target:Object/Element -- object event is unbound from 28 | * type:String -- type of event to unbind 29 | * handler:Function -- handler to unbind 30 | * vine.trigger(target\[, type\]\[, event\]\) 31 | * triggers an event and returns event object after handler execution 32 | * target:Object/Element -- object event is triggered on 33 | * type:String -- type of event to trigger 34 | * event:Object/Event -- event to use as the base event 35 | * new vine.Event(event:Object/Event) 36 | * normalizes an event (internal) 37 | 38 | ## Examples: 39 | 40 | 41 | ````js 42 | //if passed a string it looks for an element with that id 43 | vine.bind("ch", "click", function(e){ 44 | e.preventDefault(); 45 | }); 46 | ```` 47 | 48 | 49 | ````js 50 | //This will simulate a mouse click and check a checkbox if no events are bound that prevent it 51 | vine.trigger("ch", "click"); 52 | ```` 53 | 54 | 55 | ````js 56 | //Focus a textbox 57 | vine.trigger("text", "focus"); 58 | ```` 59 | 60 | 61 | 62 | 63 | 64 | ## Plugins: 65 | * delegate 66 | * vine.delegate(context:DOMElement,target:String,type:String,handler:Function[,data:Object]) 67 | * vine.undelegate(context:DOMElement,target:String,type:String[,handler:Function]) 68 | * once 69 | * vine.once(target:Object/DOMElement,type:String,handler:Function[,data:Object]) -------------------------------------------------------------------------------- /plugins/delegate.js: -------------------------------------------------------------------------------- 1 | vine._c={}; 2 | 3 | vine.re=function(str){ 4 | return this._c[str]=this._c[str]||new RegExp(str); 5 | } 6 | 7 | vine.is=function(re,r_id,r_tag,r_attrs,r_attr,r_stripQuot){ 8 | 9 | function attr(elem,attr,val,op,eq,ret){ 10 | attr=r_attr.exec(attr) 11 | 12 | val=elem.getAttribute(attr[1]) 13 | eq=r_stripQuot.exec(attr[3]) 14 | op=attr[2] 15 | 16 | eq=eq[1]||eq[2]||eq[3] 17 | 18 | switch(op){ 19 | case '=': 20 | ret=val==eq; 21 | break; 22 | case "~": 23 | ret=pavo.re(eq).test(val) 24 | break; 25 | case "^": 26 | ret=pavo.re("^"+eq).test(val) 27 | break; 28 | case "$": 29 | ret=pavo.re(eq+"$").test(val) 30 | break; 31 | 32 | } 33 | 34 | return ret; 35 | } 36 | 37 | function cName(elems,cls,y,ret,i,e){ 38 | ret=[]; 39 | i=0 40 | 41 | 42 | for(y=0;e=elems[y];y++){ 43 | 44 | (function(x,l,c){ 45 | 46 | for(;x 2 | 3 | 4 | 5 |
la
6 |
7 | -------------------------------------------------------------------------------- /vine.js: -------------------------------------------------------------------------------- 1 | vine = (function( 2 | expando, //The amount of milliseconds right now, unique identifier shorter than Math.random() 3 | uid, //A unique identifier, attached with expando to link to stored data 4 | data, //An object storing data(stored in central store for simplicity and to prevent leakage) 5 | defaultPrevented, //Shortening of .defaultPrevented 6 | addEventListener, //Shortening of .addEventListener 7 | attachEvent, //Shortening of .attachEvent 8 | document, //Reference to document 9 | vine, //Placeholder for vine object 10 | Event //Placeholder for vine.Event 11 | ){ 12 | 13 | //Initialize and fetch the data on an object 14 | function _data ( 15 | object, //Object to get data from 16 | id //Placeholder for unique id 17 | ) { 18 | id = object[expando] = object[expando] || uid++ 19 | return data[id] || (data[id] = {b: {}, e: {}}) 20 | } 21 | 22 | //If an object is a string, get the element with that ID 23 | function id ( 24 | object //Object to test 25 | ) { 26 | return object.charAt ? document.getElementById(object) : object 27 | } 28 | 29 | //Create vine object 30 | vine = { 31 | 32 | //Expose data function for plugins 33 | d: _data, 34 | id: id, 35 | 36 | //A constructor to build a normalized event 37 | Event: Event = function ( 38 | e, //Objects to mix in properties of 39 | x, //Placeholder for iteration 40 | t //Placeholder for 'this' to shorten code 41 | ) { 42 | t = this 43 | for (x in e) t[x] = t[x] || e[x] 44 | t.timestamp = +new Date 45 | t.target || (t.target = t.srcElement) 46 | }, 47 | 48 | //Bind a function to an element 49 | bind: function ( 50 | object, //Object to attach event to 51 | type, //Type of event (optinally prefixed with a namespace) 52 | fn, //Handler to bind 53 | evt_dat,//Data to bind with 54 | dat, //Placeholder for element's data 55 | ns, //Placeholder for namespace 56 | arr, //Placeholder for an array 57 | l //Placeholder for length 58 | ) { 59 | 60 | //If multiple types are provided, bind for each 61 | if ((l = (arr = type.split(" ")).length) > 1) { 62 | while (l--) vine.bind(object, arr[l], fn) 63 | 64 | //otherwise... 65 | } else { 66 | //Get the element if object is a string 67 | object = id(object) 68 | 69 | //Get data 70 | dat = _data(object) 71 | 72 | //Check for a namespace, if one is present assign to namespace variable 73 | if (ns = /^(.+)\.([^\.]+)$/.exec(type)) { 74 | type = ns[2] 75 | ns = ns[1] 76 | } 77 | 78 | //Initialize the array of functions, then push the handler and other data to it 79 | (dat.e[type] || (dat.e[type] = [])).push({ 80 | n: ns, 81 | f: fn, 82 | d: evt_dat || {} 83 | }) 84 | 85 | //Bind if the object is an element 86 | !dat.b[type] && (dat.b[type] = 1, object[addEventListener] 87 | ? object[addEventListener](type, function(e){ 88 | vine.trigger(object, type, e)[defaultPrevented] && e.preventDefault() 89 | },null) 90 | : object[attachEvent]("on" + type, function(){ 91 | return !vine.trigger(object, type, window.event)[defaultPrevented] 92 | })); 93 | } 94 | }, 95 | trigger: function ( 96 | object, //Object to trigger event on 97 | type, //Type of event to trigger 98 | evt, //Optional object to mix in to the event passed 99 | handlers, //Placeholder for an array of handlers 100 | x, len, //Placeholders for iteration 101 | event, //Placeholder for genereated event 102 | prev, //Placeholder for determining if default is prevented 103 | handler //Placeholder for specific handler 104 | ) { 105 | object = id(object) 106 | 107 | 108 | if (!evt && object.nodeType) { 109 | if (object.fireEvent) { 110 | try{ 111 | return new Event({defaultPrevented:object[type === "click" ? type : fireEvent]("on" + type)}) 112 | }catch(e){} 113 | } else { 114 | //make the event, init it, execute it, then return 115 | event = document.createEvent(( 116 | 117 | //if it's a mouse event, use mouse event init 118 | init=/click|mousedown|mouseup|mousemove/.test(type) 119 | 120 | ) ? "MouseEvents" : "HTMLEvents") 121 | event[init ? "initMouseEvent" : "initEvent"](type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) 122 | object.dispatchEvent(event) 123 | return event 124 | } 125 | } 126 | event = new Event(evt || {}) 127 | 128 | if (handlers = _data(object).e[type]) { 129 | for (x = 0, len = handlers.length; x < len; x++) { 130 | if (handler = handlers[x]) { 131 | event.namespace = handler.n 132 | event.data = handler.d 133 | prev = prev || handler.f.call(object, event) === false 134 | } 135 | } 136 | 137 | event[defaultPrevented] = event[defaultPrevented] || prev 138 | } 139 | return event 140 | }, 141 | unbind:function ( 142 | object, //Object to detach event from 143 | type, //Type of event to unbind 144 | dat, //Placeholder for data attached to object 145 | x, y, len, a//Placeholders for iteration 146 | ) { 147 | object = id(object) 148 | 149 | //If only an object is given, remove data 150 | if (!type) { 151 | //remove both the id on the object and the object from data object to reduce memory usage 152 | return data[object[expando]] = object[expando] = null 153 | } 154 | dat = _data(object) 155 | 156 | //If type is a string 157 | if (type.charAt) { 158 | //if it is a namespace 159 | if (type.charAt(0) === ".") { 160 | //go through all handlers and test for the namespace 161 | type = type.substring(1) 162 | for (y in dat.e) { 163 | a = dat.e[y] 164 | len = a.length 165 | for (x = 0; x < len;x++) { 166 | a[x].n === type && (a[x] = null) 167 | } 168 | } 169 | //Otherwise just reset the entire type 170 | } else { 171 | dat.e[type] = [] 172 | } 173 | //If type is instead a function, remove all instances of that function 174 | } else { 175 | for (y in dat.e) { 176 | a = dat.e[y] 177 | len = a.length 178 | for (x = 0; x < len; x++) { 179 | a[x].f === type && (a[x] = null) 180 | } 181 | } 182 | } 183 | } 184 | } 185 | 186 | //Functions on the event's prototype 187 | Event.prototype = { 188 | defaultPrevented: false, 189 | preventDefault: function () { 190 | this[defaultPrevented] = true 191 | } 192 | } 193 | 194 | return vine 195 | 196 | })(+(new Date), 1, {}, "defaultPrevented", "addEventListener", "attachEvent", document); -------------------------------------------------------------------------------- /vine.min.js: -------------------------------------------------------------------------------- 1 | vine=function(a,b,c,d,e,f,g,h,i){function j(d,e){return e=d[a]=d[a]||b++,c[e]||(c[e]={b:{},e:{}})}function k(a){return a.charAt?g.getElementById(a):a}return h={d:j,id:k,Event:i=function(a,b,c){c=this;for(b in a)c[b]=c[b]||a[b];c.timestamp=+(new Date),c.target||(c.target=c.srcElement)},bind:function(a,b,c,g,i,l,m,n){if((n=(m=b.split(" ")).length)>1)while(n--)h.bind(a,m[n],c);else{a=k(a),i=j(a);if(l=/^(.+)\.([^\.]+)$/.exec(b))b=l[2],l=l[1];(i.e[b]||(i.e[b]=[])).push({n:l,f:c,d:g||{}}),!i.b[b]&&(i.b[b]=1,a[e]?a[e](b,function(c){h.trigger(a,b,c)[d]&&c.preventDefault()},null):a[f]("on"+b,function(){return!h.trigger(a,b,window.event)[d]}))}},trigger:function(a,b,c,e,f,h,l,m,n){a=k(a);if(!c&&a.nodeType){if(!a.fireEvent)return l=g.createEvent((init=/click|mousedown|mouseup|mousemove/.test(b))?"MouseEvents":"HTMLEvents"),l[init?"initMouseEvent":"initEvent"](b,!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),a.dispatchEvent(l),l;try{return new i({defaultPrevented:a[b==="click"?b:fireEvent]("on"+b)})}catch(o){}}l=new i(c||{});if(e=j(a).e[b]){for(f=0,h=e.length;f