Blame view

framework/thirdparty/jquery-entwine/README.textile 12 KB
0084d336   Administrator   Importers CRUD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  h1. Entwine - Support for Concrete UI style programming in jQuery
  
  By Hamish Friedlander, with thanks to "SilverStripe":http://www.silverstripe.com/
  
  Entwine tries to provide a new model of code organisation - a replacement for Object Oriented programming that is
  focused on adding functions to groups of DOM elements based on the structure and contents of those DOM elements. It's a
  merging of the model and view layer that initially seems weird, but can give very powerful results.
  
  We're standing on the shoulders of giants here - combining ideas from Prototype's behaviour & lowpro and jQuery's effen
  & livequery (who themselves stole ideals from Self's Morphic UI and others), but extending & combining the concepts
  presented in those tools to provide a complete alternative to traditional OO concepts - self-aware methods, inheritance,
  polymorphisim and namespacing without a single class definition.
  
  h2. Requirements
  
  Currently Entwine layers itself on top of jQuery. Any patch level of jQuery from 1.7 through 1.10 or 2.0 should work.
  Because we patch some internal jQuery APIs there can be a delay between a new version of jQuery being released
  and Entwine providing support.
  
  h2. Getting Started
  
  * Walk through the "Tutorial":http://hafriedlander.github.com/jquery.entwine/tutorial/
  * Watch the "Screencast":http://www.vimeo.com/6353390 (shot during a introductory developer meeting at SilverStripe)
  * Join the "Google Group":http://groups.google.com/group/jquery-entwine and let us know what you think, or what other features you'd like to see
  
  h2. Name change
  
  jQuery Entwine used to be called jQuery Concrete. The name was changed to avoid confusion with another product. The concrete function remains as an alias, but all new code should use entwine
  
  h2. Basic use
  
  h4. First intro
  
  To attach methods to DOM nodes, call the `entwine` function on a jQuery selector object, passing a hash listing the method names and bodys
  
  <pre><code>
    $('div').entwine({
      foo: function(..){..},
      bar: function(..){..}
    });
  </code></pre>
  
  You can then call those methods on any jQuery object.
  
  <pre><code>
    $('#a').foo();
  </code></pre>
  
  Any elements in the jQuery selection that match the selector used during definition ('div' in this example) will have foo called with that element
  set as this. Any other objects are skipped. The return value will be the return value of foo() for the last matched DOM object in the set
  
  h4. A proper example
  
  Given this DOM structure:
  
  <pre><code>
    <body>
      <div class="internal_text">Internal text</div>
      <div class="attribute_text" rel="Attribute text"></div>
      <div>Nonsense</div>
    </body>
  </code></pre>
  
  And this entwine definition
  
  <pre><code>
    $('.internal_text').entwine({
      foo: function(){ console.log(this.text()); }
    });
    $('.attribute_text').entwine({
      foo: function(){ console.log(this.attr('rel')); }
    });
  </code></pre>
    
  Then this call
  
  <pre><code>
    $('div').foo();
  </code></pre>
  
  Will log this to the console
  
  <pre><code>
    Internal text
    Attribute text  
  </code></pre>
  
  h4. Limitations
  
  When defining methods, the jQuery object that entwine is called on must be a plain selector, without context. These examples will not work
  
  <pre><code>
    $('div', el).entwine(...)
    $([ela, elb, elc]).entwine(...)
    $('<div id="a"></div>').entwine(...)
  </code></pre>
  
  h2. Live
  
  The definitions you provide are not bound to the elements that match at definition time. You can declare behaviour prior to the DOM existing in any
  form (i.e. prior to DOMReady) and later calls will function correctly.
  
  h2. Selector specifity
  
  When there are two definitions for a particular method on a particular DOM node, the function with the most _specific_ selector is used. 
  _Specifity_ is calculated as defined by the CSS 2/3 spec. This can be seen as _subclassing_ applied to behaviour.
  
  Another example. Given this DOM structure
  
  <pre><code>
    <body>
      <div>Internal text</div>
      <div class="attribute_text" rel="Attribute text"></div>
      <div>Nonsense</div>
    </body>
  </code></pre>
  
  And this entwine definition
  
  <pre><code>
    $('div').entwine({
      foo: function(){ console.log(this.text()); }
    });
    $('.attribute_text').entwine({
      foo: function(){ console.log(this.attr('rel')); }
    });
  </code></pre>
  
  Then this call
  
  <pre><code>
    $('div').foo();
  </code></pre>
  
  Will log this to the console
  
  <pre><code>
    Internal text
    Attribute text
    Nonsense
  </code></pre>
  
  h2. Events
   
  If you declare a function with a name starting with 'on', then instead of defining that function, it will be bound to an event of that
  name. Just like other functions this binding will be live, and only the most specific definition will be used
  
  <pre><code>
    <head>
      <script type='text/javascript'>
        /* No need for onready wrapper. Events are bound as needed */
        $('div').entwine({
          onclick: function(){ this.css({backgroundColor: 'blue'}); }
        });
        $('.green').entwine({
          onclick: function(){ this.css({color: 'green'}); }
        });
      </script>
    <body>
      <div>Background will turn blue when clicked on</div>
      <div>Will also have blue background when clicked on</div>
      <div class='green'>Will have green text when clicked on. Background color will not change</div>
    </body>
  </code></pre>
    
  h2. Constructors / Destructors
  
  Declaring a function with the name `onmatch` will create a behavior that is called on each object when it matches. Likewise, `onunmatch` will
  be called when an object that did match this selector stops matching it (because it is removed, or because you've changed its properties).
  
  Note that an onunmatch block must be paired with an onmatch block - an onunmatch without an onmatch _in the same entwine definition block_ is illegal
  
  Like other functions, only the most specific definition will be used. However, because property changes are not atomic, this may not work as you
  expect.
  
  h2. Namespaces
  
  To avoid name clashes, to allow multiple bindings to the same event, and to generally seperate a set of functions from other code you can use namespaces
  
  <pre><code>
    $.entwine('foo.bar', function($){
      $('div').entwine({
        baz: function(){}
      });
    });
  </code></pre>
  
  You can then call these functions like this:
  
  <pre><code>
    $('div').entwine('foo.bar').baz()
  </code></pre>
    
  Namespaced functions work just like regular functions (`this` is still set to a matching DOM Node). However, specifity is calculated per namespace.
  This is particularly useful for events, because given this:
  
  <pre><code>
    $('div').entwine({
      onclick: function(){ this.css({backgroundColor: 'blue'}); }
    });
    
    $.entwine('foo', function($){
      $('div').entwine({
        onclick: function(){ this.css({color: 'green'}); }
      });
    });
  </code></pre>
    
  Clicking on a div will change the background **and** foreground color.
  
  This is particularly important when writing reusable code, since otherwise you can't know before hand whether your event handler will be called or not
  
  Although a namespace can be any string, best practise is to name them with dotted-identifier notation.
  
  h4. Namespaces and scope (or What the hell's up with that ugly function closure)
  
  Inside a namespace definition, functions remember the namespace they are in, and calls to other functions will be looked up inside that namespace first. 
  Where they don't exist, they will be looked up in the base namespace
  
  <pre><code>
    $.entwine('foo', function($){
      $('div').entwine({
        bar: function() { this.baz(); this.qux(); }
        baz: function() { console.log('baz'); }
      })
    })
    
    $('div').entwine({
      qux: function() { console.log('qux'); }
    })
  </code></pre>
    
  Will print baz, qux to the console
  
  Note that 'exists' means that a function is declared in this namespace for _any_ selector, not just a matching one. Given the dom
  
  <pre><code>
    <div>Internal text</div>
  </code></pre>
  
  And the entwine definitions
  
  <pre><code>
    $.entwine('foo', function($){
      $('div').entwine({
        bar: function() { this.baz(); }
      });
      $('span').entwine({
        baz: function() { console.log('a'); }
      });
    })
    
    
    $('div').entwine({
      baz: function() { console.log('b'); }
    })
  </code></pre>
  
  Then doing $('div').bar(); will _not_ display b. Even though the span rule could never match a div, because baz is defined for some rule in the foo namespace, the base namespace will never be checked
  
  h4. Nesting namespace blocks
  
  You can also nest declarations. In this next example, we're defining the functions $().entwine('zap').bar() and $().entwine('zap.pow').baz()
  
  <pre><code>
    $.entwine('zap', function($){
      $('div').entwine({
        bar: function() { .. }
      })
      $.entwine('pow', function($){
        $('div').entwine({
          baz: function() { .. }
        })
      })
    })
  </code></pre>
  
  h4. Calling to another namespace (and forcing base)
  
  Inside a namespace, namespace lookups are by default relative to the current namespace.
  
  In some situations (such as the last example) you may want to force using the base namespace. In this case you can call entwine with the first argument being the base namespace code '.'. For example, if the first definition in the previous example was
  
  <pre><code>
    $.entwine('foo', function($){
      $('div').entwine({
        bar: function() { this.entwine('.').baz(); }
      })
    })
  </code></pre>
  
  Then b _would_ be output to the console.
  
  h4. Using
  
  Sometimes a block outside of a namespace will need to refer to that namespace repeatedly. By passing a function to the entwine function, you can change the looked-up namespace
  
  <pre><code>
    $.entwine('foo', function($){
      $('div').entwine({
        bar: function() { console.log('a'); }
      })
    })
    
    $('div').entwine('foo', function(){
      this.bar();
      this.bar();
      this.bar();
    });
  </code></pre>
    
  This equivalent to /with/ in javascript, and just like /with/, care should be taken to only use this construct in situations that merit it.
  
  h2. Tests
  
  Specs are written using the awesome "JSpec":http://github.com/visionmedia/jspec library.  You can run them in two ways
  
  h4. Ad-hoc
  
  Open the file `spec/spec.html` in any modern browser
  
  h4. Continuous testing 
  
  JSpec has a command line client which can be used for continuous testing. Make sure ruby is installed and enabled the "Gemcutter":http://gemcutter.org/ gem hosting service, like so: 
  
  <pre><code>
  	sudo gem install gemcutter
      sudo gem tumble
  </code></pre>
  
  Then install the jspec binary:
  
  <pre><code>
      sudo gem install jspec
  </code></pre>
  
  The JSpec command line tool should now be installed. This command will re-run the specs whenever you edit a file:
  
  <pre><code>
      jspec spec/spec.html -p src,spec
  </code></pre>
  
  
  h2. License
  
  Copyright (C) 2009 Hamish Friedlander (hamish@silverstripe.com) and SilverStripe Limited (www.silverstripe.com). All rights reserved.
  
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  
      * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
      * Neither the name of Hamish Friedlander nor SilverStripe nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
  
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.