Permalink
Browse files

added clone(), fixed up some ender bridge derps

  • Loading branch information...
1 parent 01f5401 commit 211f2cd763b9a0a25ed2c00c0f70b26ec14c5707 @rvagg rvagg committed Dec 20, 2012
Showing with 129 additions and 47 deletions.
  1. +13 −3 src/bonzo.js
  2. +8 −0 src/ender.js
  3. +25 −0 tests/dommanip-test.js
  4. +1 −0 tests/dommanip_insertions-test.js
  5. +5 −4 tests/emptycollection-test.js
  6. +75 −40 tests/ender-js.js
  7. +2 −0 tests/tests.html
View
16 src/bonzo.js
@@ -86,7 +86,6 @@
return node
}
-
/**
* @param {string} c a class name to test
* @return {boolean}
@@ -553,6 +552,17 @@
return this.remove()
}
+ /**
+ * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
+ * @return {Bonzo}
+ */
+ , clone: function (opt_host) {
+ var ret = [] // don't change original array
+ , l, i
+ for (i = 0, l = this.length; i < l; i++) ret[i] = cloneNode(opt_host || this, this[i])
+ return bonzo(ret)
+ }
+
// class management
/**
@@ -705,7 +715,7 @@
* @return {Element|Node}
*/
, related: function (method) {
- return this.map(
+ return bonzo(this.map(
function (el) {
el = el[method]
while (el && el.nodeType !== 1) {
@@ -716,7 +726,7 @@
function (el) {
return el
}
- )
+ ))
}
View
8 src/ender.js
@@ -74,6 +74,10 @@
return $(b(this).previous())
}
+ , related: function (t) {
+ return $(b(this).related(t))
+ }
+
, appendTo: function (t) {
return b(this.selector).appendTo(t, this)
}
@@ -90,6 +94,10 @@
return b(this.selector).insertBefore(t, this)
}
+ , clone: function () {
+ return $(b(this).clone(this))
+ }
+
, siblings: function () {
var i, l, p, r = []
for (i = 0, l = this.length; i < l; i++) {
View
25 tests/dommanip-test.js
@@ -214,4 +214,29 @@ sink('DOM Manipulation', function(test, ok, before, after, assert) {
ok($(document.createElement('div')).detach(), 'can call detach on already detached elements')
} catch (e) { ok(false, 'error detaching detached element: ' + e); console && console.log(e,e.stack) }
})
+
+ test('should clone() detached node list', 8, function () {
+ var orig = $.create('<div><a href="http://foo/">foo</a></div><p id="paragraphtastic"><span>spantastic</span></p>')
+ , clone = $(orig).clone()
+
+ ok(orig.length == 2, 'sanity check, original fixture has 2 parent elements')
+ ok(orig.length == clone.length, 'clone has 2 parent elements')
+ ok(orig[0] !== clone[0], 'clone element !== original element')
+ ok(orig[1] !== clone[1], 'clone element !== original element')
+ ok(orig[0].childNodes[0] !== clone[0].childNodes[0], 'clone element !== original element (child node)')
+ ok(orig[1].childNodes[0] !== clone[1].childNodes[0], 'clone element !== original element (child node)')
+ ok(clone[0].childNodes[0].href == 'http://foo/', 'cloned attributes')
+ ok(clone[1].id == 'paragraphtastic', 'cloned attributes')
+ })
+
+ test('should clone() attached node list', 2, function () {
+ var html = Q('#clonesrc')[0].innerHTML.toLowerCase().replace(/\s/g, '')
+ var src = $(Q('#clonesrc > *'))
+ src.clone().appendTo('#clonedst')
+ var newhtml = Q('#clonedst')[0].innerHTML.toLowerCase().replace(/\s/g, '')
+ ok(html == newhtml, 'cloning attached node duplicates HTML')
+ src.clone().appendTo('#clonedst') // do it again!
+ newhtml = Q('#clonedst')[0].innerHTML.toLowerCase().replace(/\s/g, '')
+ ok(html + html == newhtml, 'cloning attached node duplicates HTML (again!)')
+ })
})
View
1 tests/dommanip_insertions-test.js
@@ -2271,6 +2271,7 @@ sink('DOM Manipulation - insertions', function(test, ok, before, after, assert)
*/
test('nodes with text nodes being appended with $.create', function (complete) {
var tree = $.create('<span>hey</span> there')
+ console.log(tree)
ok(tree.length == 2, 'created two nodes')
ok(tree[0] && tree[0].nodeType == 1, 'first node is an element')
ok(tree[1] && tree[1].nodeType == 3, 'second node is a text node')
View
9 tests/emptycollection-test.js
@@ -44,9 +44,9 @@ sink('Empty-collection safety', function (test, ok) {
// FUNCTION NAME ARGUMENT SIGNATURE ARGUMENTS ARRAY EXPECTED RESULT MATCHER
first: { str: '', args: [], expect: isEmptyContainer }
, last: { str: '', args: [], expect: isEmptyContainer }
- , parent: { str: '', args: [], expect: isEmptyArray }
- , next: { str: '', args: [], expect: isEmptyArray }
- , previous: { str: '', args: [], expect: isEmptyArray }
+ , parent: { str: '', args: [], expect: isEmptyContainer }
+ , next: { str: '', args: [], expect: isEmptyContainer }
+ , previous: { str: '', args: [], expect: isEmptyContainer }
, dim: { str: '', args: [], expect: function(r) { return r.height === 0 && r.width === 0 } }
, get: { str: 'index', args: [0], expect: isNull }
, detach: { str: '', args: [], expect: isSameContainer }
@@ -74,12 +74,13 @@ sink('Empty-collection safety', function (test, ok) {
, prepend: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, appendTo: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, prependTo: { str: 'html', args: ['<a/>'], expect: isSameContainer }
- , related: { str: 'method', args: ['parentNode'], expect: isEmptyArray }
+ , related: { str: 'method', args: ['parentNode'], expect: isEmptyContainer }
, before: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, after: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, insertBefore: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, insertAfter: { str: 'html', args: ['<a/>'], expect: isSameContainer }
, replaceWith: { str: 'html', args: ['<a/>'], expect: isEmptyContainer }
+ , clone: { str: '', args: [], expect: isEmptyContainer }
, 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
, { str: 'prop, val', args: ['color', 'red'], expect: isSameContainer }
, { str: '{prop: val}', args: [{color: 'red'}], expect: isSameContainer }
View
115 tests/ender-js.js
@@ -1,10 +1,10 @@
/*!
* Ender: open module JavaScript framework (client-lib)
- * copyright Dustin Diaz & Jacob Thornton 2011 (@ded @fat)
- * http://ender.no.de
+ * copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
+ * http://ender.jit.su
* License MIT
*/
-!function (context) {
+(function (context) {
// a global object for node.js module compatiblity
// ============================================
@@ -16,17 +16,20 @@
// ============================================
var modules = {}
- , old = context.$
+ , old = context['$']
+ , oldEnder = context['ender']
+ , oldRequire = context['require']
+ , oldProvide = context['provide']
function require (identifier) {
// modules can be required from ender's build system, or found on the window
- var module = modules[identifier] || window[identifier]
- if (!module) throw new Error("Requested module '" + identifier + "' has not been defined.")
+ var module = modules['$' + identifier] || window[identifier]
+ if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
return module
}
function provide (name, what) {
- return (modules[name] = what)
+ return (modules['$' + name] = what)
}
context['provide'] = provide
@@ -37,48 +40,80 @@
return o
}
- function boosh(s, r, els) {
+ /**
+ * main Ender return object
+ * @constructor
+ * @param {Array|Node|string} s a CSS selector or DOM node(s)
+ * @param {Array.|Node} r a root node(s)
+ */
+ function Ender(s, r) {
+ var elements
+ , i
+
+ this.selector = s
// string || node || nodelist || window
- if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
- els = ender._select(s, r)
- els.selector = s
- } else els = isFinite(s.length) ? s : [s]
- return aug(els, boosh)
+ if (typeof s == 'undefined') {
+ elements = []
+ this.selector = ''
+ } else if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
+ elements = ender._select(s, r)
+ } else {
+ elements = isFinite(s.length) ? s : [s]
+ }
+ this.length = elements.length
+ for (i = this.length; i--;) this[i] = elements[i]
+ }
+
+ /**
+ * @param {function(el, i, inst)} fn
+ * @param {Object} opt_scope
+ * @returns {Ender}
+ */
+ Ender.prototype['forEach'] = function (fn, opt_scope) {
+ var i, l
+ // opt out of native forEach so we can intentionally call our own scope
+ // defaulting to the current item and be able to return self
+ for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(opt_scope || this[i], this[i], i, this)
+ // return self for chaining
+ return this
}
+ Ender.prototype.$ = ender // handy reference to self
+
+
function ender(s, r) {
- return boosh(s, r)
+ return new Ender(s, r)
}
- aug(ender, {
- _VERSION: '0.3.6'
- , fn: boosh // for easy compat to jQuery plugins
- , ender: function (o, chain) {
- aug(chain ? boosh : ender, o)
- }
- , _select: function (s, r) {
- return (r || document).querySelectorAll(s)
- }
- })
-
- aug(boosh, {
- forEach: function (fn, scope, i) {
- // opt out of native forEach so we can intentionally call our own scope
- // defaulting to the current item and be able to return self
- for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(scope || this[i], this[i], i, this)
- // return self for chaining
- return this
- },
- $: ender // handy reference to self
- })
-
- ender.noConflict = function () {
- context.$ = old
+ ender['_VERSION'] = '0.4.3-dev'
+
+ ender.fn = Ender.prototype // for easy compat to jQuery plugins
+
+ ender.ender = function (o, chain) {
+ aug(chain ? Ender.prototype : ender, o)
+ }
+
+ ender._select = function (s, r) {
+ if (typeof s == 'string') return (r || document).querySelectorAll(s)
+ if (s.nodeName) return [s]
+ return s
+ }
+
+
+ // use callback to receive Ender's require & provide and remove them from global
+ ender.noConflict = function (callback) {
+ context['$'] = old
+ if (callback) {
+ context['provide'] = oldProvide
+ context['require'] = oldRequire
+ context['ender'] = oldEnder
+ if (typeof callback == 'function') callback(require, provide, this)
+ }
return this
}
if (typeof module !== 'undefined' && module.exports) module.exports = ender
// use subscript notation as extern for Closure compilation
- context['ender'] = context['$'] = context['ender'] || ender
+ context['ender'] = context['$'] = ender
-}(this);
+}(this));
View
2 tests/tests.html
@@ -120,6 +120,8 @@
<div id="data-temp"></div>
<div id="insertiontasticSource"></div>
<div id="insertiontastic"></div>
+ <div id="clonesrc"><div><p>TEXT</p><span><b>foo</b></span></div><div>second child</div></div>
+ <div id="clonedst"></div>
</div>
<!-- special fixtures -->

0 comments on commit 211f2cd

Please sign in to comment.