Skip to content
This repository
Browse code

added clone(), fixed up some ender bridge derps

  • Loading branch information...
commit 71310c3c584e775f01c4e88d17d50a97b28ab963 1 parent 5e991c8
Rod Vagg authored
16  src/bonzo.js
@@ -86,7 +86,6 @@
86 86
     return node
87 87
   }
88 88
 
89  
-
90 89
   /**
91 90
    * @param {string} c a class name to test
92 91
    * @return {boolean}
@@ -553,6 +552,17 @@
553 552
         return this.remove()
554 553
       }
555 554
 
  555
+      /**
  556
+       * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
  557
+       * @return {Bonzo}
  558
+       */
  559
+    , clone: function (opt_host) {
  560
+        var ret = [] // don't change original array
  561
+          , l, i
  562
+        for (i = 0, l = this.length; i < l; i++) ret[i] = cloneNode(opt_host || this, this[i])
  563
+        return bonzo(ret)
  564
+      }
  565
+
556 566
       // class management
557 567
 
558 568
       /**
@@ -705,7 +715,7 @@
705 715
        * @return {Element|Node}
706 716
        */
707 717
     , related: function (method) {
708  
-        return this.map(
  718
+        return bonzo(this.map(
709 719
           function (el) {
710 720
             el = el[method]
711 721
             while (el && el.nodeType !== 1) {
@@ -716,7 +726,7 @@
716 726
           function (el) {
717 727
             return el
718 728
           }
719  
-        )
  729
+        ))
720 730
       }
721 731
 
722 732
 
8  src/ender.js
@@ -74,6 +74,10 @@
74 74
       return $(b(this).previous())
75 75
     }
76 76
 
  77
+  , related: function (t) {
  78
+      return $(b(this).related(t))
  79
+    }
  80
+
77 81
   , appendTo: function (t) {
78 82
       return b(this.selector).appendTo(t, this)
79 83
     }
@@ -90,6 +94,10 @@
90 94
       return b(this.selector).insertBefore(t, this)
91 95
     }
92 96
 
  97
+  , clone: function () {
  98
+      return $(b(this).clone(this))
  99
+    }
  100
+
93 101
   , siblings: function () {
94 102
       var i, l, p, r = []
95 103
       for (i = 0, l = this.length; i < l; i++) {
25  tests/dommanip-test.js
@@ -214,4 +214,29 @@ sink('DOM Manipulation', function(test, ok, before, after, assert) {
214 214
       ok($(document.createElement('div')).detach(), 'can call detach on already detached elements')
215 215
     } catch (e) { ok(false, 'error detaching detached element: ' + e); console && console.log(e,e.stack) }
216 216
   })
  217
+
  218
+  test('should clone() detached node list', 8, function () {
  219
+    var orig = $.create('<div><a href="http://foo/">foo</a></div><p id="paragraphtastic"><span>spantastic</span></p>')
  220
+      , clone = $(orig).clone()
  221
+
  222
+    ok(orig.length == 2, 'sanity check, original fixture has 2 parent elements')
  223
+    ok(orig.length == clone.length, 'clone has 2 parent elements')
  224
+    ok(orig[0] !== clone[0], 'clone element !== original element')
  225
+    ok(orig[1] !== clone[1], 'clone element !== original element')
  226
+    ok(orig[0].childNodes[0] !== clone[0].childNodes[0], 'clone element !== original element (child node)')
  227
+    ok(orig[1].childNodes[0] !== clone[1].childNodes[0], 'clone element !== original element (child node)')
  228
+    ok(clone[0].childNodes[0].href == 'http://foo/', 'cloned attributes')
  229
+    ok(clone[1].id == 'paragraphtastic', 'cloned attributes')
  230
+  })
  231
+
  232
+  test('should clone() attached node list', 2, function () {
  233
+    var html = Q('#clonesrc')[0].innerHTML.toLowerCase().replace(/\s/g, '')
  234
+    var src = $(Q('#clonesrc > *'))
  235
+    src.clone().appendTo('#clonedst')
  236
+    var newhtml = Q('#clonedst')[0].innerHTML.toLowerCase().replace(/\s/g, '')
  237
+    ok(html == newhtml, 'cloning attached node duplicates HTML')
  238
+    src.clone().appendTo('#clonedst') // do it again!
  239
+    newhtml = Q('#clonedst')[0].innerHTML.toLowerCase().replace(/\s/g, '')
  240
+    ok(html + html == newhtml, 'cloning attached node duplicates HTML (again!)')
  241
+  })
217 242
 })
1  tests/dommanip_insertions-test.js
@@ -2271,6 +2271,7 @@ sink('DOM Manipulation - insertions', function(test, ok, before, after, assert)
2271 2271
    */
2272 2272
   test('nodes with text nodes being appended with $.create', function (complete) {
2273 2273
     var tree = $.create('<span>hey</span> there')
  2274
+    console.log(tree)
2274 2275
     ok(tree.length == 2, 'created two nodes')
2275 2276
     ok(tree[0] && tree[0].nodeType == 1, 'first node is an element')
2276 2277
     ok(tree[1] && tree[1].nodeType == 3, 'second node is a text node')
9  tests/emptycollection-test.js
@@ -44,9 +44,9 @@ sink('Empty-collection safety', function (test, ok) {
44 44
     //  FUNCTION NAME         ARGUMENT SIGNATURE        ARGUMENTS ARRAY            EXPECTED RESULT MATCHER
45 45
         first:         { str: '',                 args: [],                expect: isEmptyContainer }
46 46
       , last:          { str: '',                 args: [],                expect: isEmptyContainer }
47  
-      , parent:        { str: '',                 args: [],                expect: isEmptyArray }
48  
-      , next:          { str: '',                 args: [],                expect: isEmptyArray }
49  
-      , previous:      { str: '',                 args: [],                expect: isEmptyArray }
  47
+      , parent:        { str: '',                 args: [],                expect: isEmptyContainer }
  48
+      , next:          { str: '',                 args: [],                expect: isEmptyContainer }
  49
+      , previous:      { str: '',                 args: [],                expect: isEmptyContainer }
50 50
       , dim:           { str: '',                 args: [],                expect: function(r) { return r.height === 0 && r.width === 0 } }
51 51
       , get:           { str: 'index',            args: [0],               expect: isNull }
52 52
       , detach:        { str: '',                 args: [],                expect: isSameContainer }
@@ -74,12 +74,13 @@ sink('Empty-collection safety', function (test, ok) {
74 74
       , prepend:       { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
75 75
       , appendTo:      { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
76 76
       , prependTo:     { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
77  
-      , related:       { str: 'method',            args: ['parentNode'],   expect: isEmptyArray }
  77
+      , related:       { str: 'method',            args: ['parentNode'],   expect: isEmptyContainer }
78 78
       , before:        { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
79 79
       , after:         { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
80 80
       , insertBefore:  { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
81 81
       , insertAfter:   { str: 'html',              args: ['<a/>'],         expect: isSameContainer }
82 82
       , replaceWith:   { str: 'html',              args: ['<a/>'],         expect: isEmptyContainer }
  83
+      , clone:         { str: '',                  args: [],               expect: isEmptyContainer }
83 84
       , css: [         { str: 'prop',              args: ['color'],        expect: isNull } // not sure about this one, depending on the browser you might get "" for an empty property on a real element and undefined for an unknown property on a real element
84 85
                      , { str: 'prop, val',         args: ['color', 'red'], expect: isSameContainer }
85 86
                      , { str: '{prop: val}',       args: [{color: 'red'}], expect: isSameContainer }
115  tests/ender-js.js
... ...
@@ -1,10 +1,10 @@
1 1
 /*!
2 2
   * Ender: open module JavaScript framework (client-lib)
3  
-  * copyright Dustin Diaz & Jacob Thornton 2011 (@ded @fat)
4  
-  * http://ender.no.de
  3
+  * copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
  4
+  * http://ender.jit.su
5 5
   * License MIT
6 6
   */
7  
-!function (context) {
  7
+(function (context) {
8 8
 
9 9
   // a global object for node.js module compatiblity
10 10
   // ============================================
@@ -16,17 +16,20 @@
16 16
   // ============================================
17 17
 
18 18
   var modules = {}
19  
-    , old = context.$
  19
+    , old = context['$']
  20
+    , oldEnder = context['ender']
  21
+    , oldRequire = context['require']
  22
+    , oldProvide = context['provide']
20 23
 
21 24
   function require (identifier) {
22 25
     // modules can be required from ender's build system, or found on the window
23  
-    var module = modules[identifier] || window[identifier]
24  
-    if (!module) throw new Error("Requested module '" + identifier + "' has not been defined.")
  26
+    var module = modules['$' + identifier] || window[identifier]
  27
+    if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
25 28
     return module
26 29
   }
27 30
 
28 31
   function provide (name, what) {
29  
-    return (modules[name] = what)
  32
+    return (modules['$' + name] = what)
30 33
   }
31 34
 
32 35
   context['provide'] = provide
@@ -37,48 +40,80 @@
37 40
     return o
38 41
   }
39 42
 
40  
-  function boosh(s, r, els) {
  43
+  /**
  44
+   * main Ender return object
  45
+   * @constructor
  46
+   * @param {Array|Node|string} s a CSS selector or DOM node(s)
  47
+   * @param {Array.|Node} r a root node(s)
  48
+   */
  49
+  function Ender(s, r) {
  50
+    var elements
  51
+      , i
  52
+
  53
+    this.selector = s
41 54
     // string || node || nodelist || window
42  
-    if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
43  
-      els = ender._select(s, r)
44  
-      els.selector = s
45  
-    } else els = isFinite(s.length) ? s : [s]
46  
-    return aug(els, boosh)
  55
+    if (typeof s == 'undefined') {
  56
+      elements = []
  57
+      this.selector = ''
  58
+    } else if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
  59
+      elements = ender._select(s, r)
  60
+    } else {
  61
+      elements = isFinite(s.length) ? s : [s]
  62
+    }
  63
+    this.length = elements.length
  64
+    for (i = this.length; i--;) this[i] = elements[i]
  65
+  }
  66
+
  67
+  /**
  68
+   * @param {function(el, i, inst)} fn
  69
+   * @param {Object} opt_scope
  70
+   * @returns {Ender}
  71
+   */
  72
+  Ender.prototype['forEach'] = function (fn, opt_scope) {
  73
+    var i, l
  74
+    // opt out of native forEach so we can intentionally call our own scope
  75
+    // defaulting to the current item and be able to return self
  76
+    for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(opt_scope || this[i], this[i], i, this)
  77
+    // return self for chaining
  78
+    return this
47 79
   }
48 80
 
  81
+  Ender.prototype.$ = ender // handy reference to self
  82
+
  83
+
49 84
   function ender(s, r) {
50  
-    return boosh(s, r)
  85
+    return new Ender(s, r)
51 86
   }
52 87
 
53  
-  aug(ender, {
54  
-      _VERSION: '0.3.6'
55  
-    , fn: boosh // for easy compat to jQuery plugins
56  
-    , ender: function (o, chain) {
57  
-        aug(chain ? boosh : ender, o)
58  
-      }
59  
-    , _select: function (s, r) {
60  
-        return (r || document).querySelectorAll(s)
61  
-      }
62  
-  })
63  
-
64  
-  aug(boosh, {
65  
-    forEach: function (fn, scope, i) {
66  
-      // opt out of native forEach so we can intentionally call our own scope
67  
-      // defaulting to the current item and be able to return self
68  
-      for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(scope || this[i], this[i], i, this)
69  
-      // return self for chaining
70  
-      return this
71  
-    },
72  
-    $: ender // handy reference to self
73  
-  })
74  
-
75  
-  ender.noConflict = function () {
76  
-    context.$ = old
  88
+  ender['_VERSION'] = '0.4.3-dev'
  89
+
  90
+  ender.fn = Ender.prototype // for easy compat to jQuery plugins
  91
+
  92
+  ender.ender = function (o, chain) {
  93
+    aug(chain ? Ender.prototype : ender, o)
  94
+  }
  95
+
  96
+  ender._select = function (s, r) {
  97
+    if (typeof s == 'string') return (r || document).querySelectorAll(s)
  98
+    if (s.nodeName) return [s]
  99
+    return s
  100
+  }
  101
+
  102
+
  103
+  // use callback to receive Ender's require & provide and remove them from global
  104
+  ender.noConflict = function (callback) {
  105
+    context['$'] = old
  106
+    if (callback) {
  107
+      context['provide'] = oldProvide
  108
+      context['require'] = oldRequire
  109
+      context['ender'] = oldEnder
  110
+      if (typeof callback == 'function') callback(require, provide, this)
  111
+    }
77 112
     return this
78 113
   }
79 114
 
80 115
   if (typeof module !== 'undefined' && module.exports) module.exports = ender
81 116
   // use subscript notation as extern for Closure compilation
82  
-  context['ender'] = context['$'] = context['ender'] || ender
  117
+  context['ender'] = context['$'] = ender
83 118
 
84  
-}(this);
  119
+}(this));
2  tests/tests.html
@@ -120,6 +120,8 @@
120 120
       <div id="data-temp"></div>
121 121
       <div id="insertiontasticSource"></div>
122 122
       <div id="insertiontastic"></div>
  123
+      <div id="clonesrc"><div><p>TEXT</p><span><b>foo</b></span></div><div>second child</div></div>
  124
+      <div id="clonedst"></div>
123 125
     </div>
124 126
 
125 127
     <!-- special fixtures -->

0 notes on commit 71310c3

Please sign in to comment.
Something went wrong with that request. Please try again.