Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first commit

Marrow.js
  • Loading branch information...
commit 387f5b32e77c4f61e1ffc6f97ef93b95e402af09 1 parent 0d338e6
@kentaromiura authored
View
4 .gitignore
@@ -0,0 +1,4 @@
+.idea/*
+Build/*
+*.iml
+node_modules/*
View
18 Makefile
@@ -0,0 +1,18 @@
+
+all: test build-src build
+
+build-src:
+ @if [ ! -d Build ]; then mkdir Build; fi
+ @npm install
+ @./node_modules/wrapup/bin/wrup.js -r ./Source/index.js > Build/Marrow.js
+ @echo "Browser version written to 'Build/Marrow.js'"
+
+
+test:
+# @make install
+# @./node_modules/mocha/bin/mocha Tests/index.js
+
+install: package.json
+ @npm prune
+ @npm install
+
View
37 README.md
@@ -1,2 +1,35 @@
-Marrow
-======
+Marrow.js
+========================
+
+because without it, backbone is useful as confetti to clean your ass.
+
+What's Marrow?
+------------------------
+
+Marrow objective is to provide a single drop-in dependency for backbone,
+using the latest MooTools technology, especially the new moofx effects library.
+
+In order to do this, it shim jQuery methods used by backbone, right now it still require underscore, but most of what underscore provide is already backed in the new mootools prime, so eventually it will be substituted with
+https://github.com/GCheung55/underprime, so that when built using MooTools wrapup, the size of the download will drastically be reduced.
+
+TL;DR: Marrow = Backbone + moofx
+
+In order to provide the best compatibility Marrow should pass the jQuery core test,
+in this first version it pass just few of them, but this is intended, it will eventually improve.
+
+What works right now?
+
+this fiddle work perfectly, without changing anything in the code.
+
+http://jsfiddle.net/tBS4X/1/
+
+TODO:
+* Add support for event namespacing, since BB use that, Add HTTP 1.1 emulation for webserver without the WebDav plugin
+* Moar tests need to pass, especially the jQ events tests
+* remove underscore in favor of underprime when it's ready.
+
+Inspiration:
+Marrow take inspiration from https://github.com/inkling/backbone-mootools,
+after removing Request in favor of agent I though it was better to start a new project to reduce the size of the dependency
+
+
View
232 Source/index.js
@@ -0,0 +1,232 @@
+var prime = require('prime'), $ = {}
+var array = require('prime/shell/array')
+var moofx = require('moofx')
+var type = require('prime/type')
+var ready = require('elements/domready')
+
+/* nodes */
+var $$ = require('elements')
+require('elements/traversal')
+require('elements/events')
+require('elements/attributes')
+
+// For JQ compat only, this breaks elements api coherency
+// TODO: externalize this and make a new prime so it will not ovveride elements methods.
+$$.implement({
+ val : function(value){
+ return this.value(value);
+ },
+ width: function(value){
+ if(value) {
+ moofx(this).style('width', value)
+ return this
+ }
+ return moofx(this).compute('width')
+ },
+ get: function(index){
+ if(!index) return this;
+ if(index < 0){
+ index = this.length + index;
+ }
+ return this[index];
+ },
+ parent: function(){
+ var results = [];
+ this.forEach(function(node){
+ results.push(node.parentNode);
+ })
+ return $.$$(results);
+ },
+ html: function(html){
+ if (html){
+ this.forEach(function(node){node.innerHTML = html})
+ } else {
+ return (this[0] || {innerHTML:''}).innerHTML
+ }
+
+ },
+ hide: function(){
+ moofx(this).style({'display':'none'});
+ },
+ /// other methods, not needed by bb.
+
+ offset: function(obj){
+ moofx(this).style(obj);
+ return this;
+ },
+ css: function(obj){
+ moofx(this).style(obj);
+ return this;
+ },
+ attr: function(obj){
+ if(type(obj) === 'string'){
+ return this[0].getAttribute(obj)
+ }
+ for(var attr in obj){
+ this.setAttribute(attr, obj[attr]);
+ }
+ return this;
+ },
+ "class": function(name){
+ this.addClass(name);
+ return this;
+ },
+ click: function(handler){
+ if(handler){
+ this.on('click', handler);
+ }else{
+ this.emit('click');
+ }
+ return this;
+ },
+ remove:function(){
+ this.forEach(function(node){
+ if(node.parentNode){
+ node.parentNode.removeChild(node);
+ }
+ })
+ return this;
+ }
+})
+
+var div = document.createElement('div');
+// nodes returns null, while jquery [];
+var empty = function(){
+ var empty = $$(div);
+ delete empty['0'];
+ empty.length = 0;
+ return empty;
+};
+
+$.$$ = function(selector, context){
+ var result = $$(selector, context);
+ if(result && type(selector) === 'string'){
+ result.selector = selector;
+
+// result.on = function(result, on){
+// return function ( event, selector, callback ){
+//
+// var els = this.find(selector)
+// if(els) els.on(event.split('.')[0], callback);
+// //on.call(result, event.split('.')[0], selector, callback);
+// }
+// }(result, result.on);
+
+ result.on = (function(result, on){
+ return function(event, selector, callback){
+ on.call( result.find(selector) || result, event.split('.')[0], callback )
+ }
+ })(result, result.on)
+ }
+ return result || empty();
+}
+
+/* agent */
+$.agent = require('agent');
+
+var sugar = prime({
+ constructor: function(a, options){
+
+ switch(type(a)){
+ case 'array':
+ var result = $.$$(a);
+ if(result.length) return result;
+ //not an element array :p
+
+ return array(a);
+
+ case 'string':
+ if(!a || a === '#') return empty();
+ if( a.charAt(0) == '<' && a.charAt(a.length-1) == '>' ){ //jQuery here also check if length >3 ???
+ //element creation via innerHTML
+ var element = document.createElement('div');
+ var results = [];
+
+ // fixes element autoclose.
+ element.innerHTML = a.replace(/<([^ /]+)[^>]*>/g,function(x, tagname){
+ div.innerHTML = x.replace('/>', '></' + tagname + '>');
+ var result = div.childNodes.length == 1 ? x.replace('/>', '></' + tagname + '>') : a;
+ div.innerHTML = '';
+ return result;
+ });
+
+ while(element.childNodes.length){
+ results.push(element.childNodes[0]);
+ element.removeChild(element.childNodes[0]);
+ }
+
+ results = $.$$(results)
+
+ for( var option in options){
+ var value = options[option];
+ if(type(value) == 'function'){
+ // it must be an event
+ results.on(option, value)
+ } else {
+ results[option](value)
+ }
+
+ }
+ return results;
+ }
+
+
+
+ return $.$$(a);
+ break;
+ case 'function':
+ var wrapper = function(){
+ a.apply($, arguments)
+ };
+ ready(wrapper)
+ break;
+ default :
+ return $.$$(a);
+ break;
+ }
+ }
+});
+
+// sugar.implement($)
+sugar.fn = sugar.prototype;
+
+/* export namespace */
+global.jQuery = sugar;
+
+window.jQuery.ajax = function(params){
+ var emulation = false;
+ var data = params.data;
+
+ /* agent doesn't support emulation (yet)
+ if (Backbone.emulateJSON){
+ emulation = true;
+ data = data ? { model: data } : {};
+ }
+ */
+
+
+ var req;
+ if (data){
+ req = new agent(params.type, params.url, data)
+ } else {
+ req = new agent(params.type, params.url)
+ }
+
+ req.header('Content-Type', params.contentType || 'application/json')
+
+
+ if('headers' in params){
+ for(var header in params.headers){
+ req.header(header, params.headers[header])
+ }
+ }
+
+ req.send(function(res){
+
+ if(res.ok){
+ (params.success || isNaN)(JSON.parse(res.text))
+ }else{
+ (params.failure || isNaN)(res)
+ }
+ })
+};
View
274 Test/core.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr" id="html">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+ <title>jQuery Test Suite</title>
+ <script src="../Build/Marrow.js"></script>
+ <link href="mocha.css" rel="stylesheet" type="text/css" media="screen"/>
+ <script src="mocha.js" type="text/javascript"></script>
+
+ <script>
+ mocha.globals(['create', '__utils__', 'ClientUtils'])
+ mocha.setup('bdd')
+ window.onload = function(){
+ mocha.run(function(){
+ // required so phantomjs can check if mocha is ready
+ document.body.setAttribute('data-ready', '1')
+ })
+ }
+ </script>
+
+ <script type="text/javascript" src="test.js?test/core"></script>
+</head>
+<body id="body">
+<div id="mocha"></div>
+<h1 id="qunit-header"><a href="/jquery/test/index.html">jQuery Test Suite</a></h1>
+<h2 id="qunit-banner"></h2>
+<div id="qunit-testrunner-toolbar"></div>
+<h2 id="qunit-userAgent"></h2>
+<ol id="qunit-tests"></ol>
+
+<!-- Test HTML -->
+<div id="nothiddendiv" style="height:1px;background:white;" class="nothiddendiv">
+ <div id="nothiddendivchild"></div>
+</div>
+<!-- this iframe is outside the #qunit-fixture so it won't reload constantly wasting time, but it means the tests must be "safe" and clean up after themselves -->
+<iframe id="loadediframe" name="loadediframe" style="display:none;" src="data/iframe.html"></iframe>
+<dl id="dl" style="position:absolute;top:-32767px;left:-32767px;width:1px">
+<div id="qunit-fixture">
+<p id="firstp">See <a id="simon1" href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a> for more information.</p>
+<p id="ap">
+ Here are some links in a normal paragraph: <a id="google" href="http://www.google.com/" title="Google!">Google</a>,
+ <a id="groups" href="http://groups.google.com/" class="GROUPS">Google Groups (Link)</a>.
+ This link has <code><a href="http://smin" id="anchor1">class="blog"</a></code>:
+ <a href="http://diveintomark.org/" class="blog" hreflang="en" id="mark">diveintomark</a>
+
+</p>
+<div id="foo">
+ <p id="sndp">Everything inside the red border is inside a div with <code>id="foo"</code>.</p>
+ <p lang="en" id="en">This is a normal link: <a id="yahoo" href="http://www.yahoo.com/" class="blogTest">Yahoo</a></p>
+ <p id="sap">This link has <code><a href="#2" id="anchor2">class="blog"</a></code>: <a href="http://simon.incutio.com/" class="blog link" id="simon">Simon Willison's Weblog</a></p>
+
+</div>
+<span id="name+value"></span>
+<p id="first">Try them out:</p>
+<ul id="firstUL"></ul>
+<ol id="empty"></ol>
+<form id="form" action="formaction">
+ <label for="action" id="label-for">Action:</label>
+ <input type="text" name="action" value="Test" id="text1" maxlength="30"/>
+ <input type="text" name="text2" value="Test" id="text2" disabled="disabled"/>
+ <input type="radio" name="radio1" id="radio1" value="on"/>
+
+ <input type="radio" name="radio2" id="radio2" checked="checked"/>
+ <input type="checkbox" name="check" id="check1" checked="checked"/>
+ <input type="checkbox" id="check2" value="on"/>
+
+ <input type="hidden" name="hidden" id="hidden1"/>
+ <input type="text" style="display:none;" name="foo[bar]" id="hidden2"/>
+
+ <input type="text" id="name" name="name" value="name" />
+ <input type="search" id="search" name="search" value="search" />
+
+ <button id="button" name="button" type="button">Button</button>
+
+ <textarea id="area1" maxlength="30">foobar</textarea>
+
+ <select name="select1" id="select1">
+ <option id="option1a" class="emptyopt" value="">Nothing</option>
+ <option id="option1b" value="1">1</option>
+ <option id="option1c" value="2">2</option>
+ <option id="option1d" value="3">3</option>
+ </select>
+ <select name="select2" id="select2">
+ <option id="option2a" class="emptyopt" value="">Nothing</option>
+ <option id="option2b" value="1">1</option>
+ <option id="option2c" value="2">2</option>
+ <option id="option2d" selected="selected" value="3">3</option>
+ </select>
+ <select name="select3" id="select3" multiple="multiple">
+ <option id="option3a" class="emptyopt" value="">Nothing</option>
+ <option id="option3b" selected="selected" value="1">1</option>
+ <option id="option3c" selected="selected" value="2">2</option>
+ <option id="option3d" value="3">3</option>
+ <option id="option3e">no value</option>
+ </select>
+ <select name="select4" id="select4" multiple="multiple">
+ <optgroup disabled="disabled">
+ <option id="option4a" class="emptyopt" value="">Nothing</option>
+ <option id="option4b" disabled="disabled" selected="selected" value="1">1</option>
+ <option id="option4c" selected="selected" value="2">2</option>
+ </optgroup>
+ <option selected="selected" disabled="disabled" id="option4d" value="3">3</option>
+ <option id="option4e">no value</option>
+ </select>
+ <select name="select5" id="select5">
+ <option id="option5a" value="3">1</option>
+ <option id="option5b" value="2">2</option>
+ <option id="option5c" value="1" data-attr="">3</option>
+ </select>
+
+ <object id="object1" codebase="stupid">
+ <param name="p1" value="x1" />
+ <param name="p2" value="x2" />
+ </object>
+
+ <span id="台北Táiběi"></span>
+ <span id="台北" lang="中文"></span>
+ <span id="utf8class1" class="台北Táiběi 台北"></span>
+ <span id="utf8class2" class="台北"></span>
+ <span id="foo:bar" class="foo:bar"></span>
+ <span id="test.foo[5]bar" class="test.foo[5]bar"></span>
+
+ <foo_bar id="foobar">test element</foo_bar>
+</form>
+<b id="floatTest">Float test.</b>
+<iframe id="iframe" name="iframe"></iframe>
+<form id="lengthtest">
+ <input type="text" id="length" name="test"/>
+ <input type="text" id="idTest" name="id"/>
+</form>
+<table id="table"></table>
+
+<form id="name-tests">
+ <!-- Inputs with a grouped name attribute. -->
+ <input name="types[]" id="types_all" type="checkbox" value="all" />
+ <input name="types[]" id="types_anime" type="checkbox" value="anime" />
+ <input name="types[]" id="types_movie" type="checkbox" value="movie" />
+</form>
+
+<form id="testForm" action="#" method="get">
+ <textarea name="T3" rows="2" cols="15">?
+ Z</textarea>
+ <input type="hidden" name="H1" value="x" />
+ <input type="hidden" name="H2" />
+ <input name="PWD" type="password" value="" />
+ <input name="T1" type="text" />
+ <input name="T2" type="text" value="YES" readonly="readonly" />
+ <input type="checkbox" name="C1" value="1" />
+ <input type="checkbox" name="C2" />
+ <input type="radio" name="R1" value="1" />
+ <input type="radio" name="R1" value="2" />
+ <input type="text" name="My Name" value="me" />
+ <input type="reset" name="reset" value="NO" />
+ <select name="S1">
+ <option value="abc">ABC</option>
+ <option value="abc">ABC</option>
+ <option value="abc">ABC</option>
+ </select>
+ <select name="S2" multiple="multiple" size="3">
+ <option value="abc">ABC</option>
+ <option value="abc">ABC</option>
+ <option value="abc">ABC</option>
+ </select>
+ <select name="S3">
+ <option selected="selected">YES</option>
+ </select>
+ <select name="S4">
+ <option value="" selected="selected">NO</option>
+ </select>
+ <input type="submit" name="sub1" value="NO" />
+ <input type="submit" name="sub2" value="NO" />
+ <input type="image" name="sub3" value="NO" />
+ <button name="sub4" type="submit" value="NO">NO</button>
+ <input name="D1" type="text" value="NO" disabled="disabled" />
+ <input type="checkbox" checked="checked" disabled="disabled" name="D2" value="NO" />
+ <input type="radio" name="D3" value="NO" checked="checked" disabled="disabled" />
+ <select name="D4" disabled="disabled">
+ <option selected="selected" value="NO">NO</option>
+ </select>
+ <input id="list-test" type="text" />
+ <datalist id="datalist">
+ <option value="option"></option>
+ </datalist>
+</form>
+<div id="moretests">
+ <form>
+ <div id="checkedtest" style="display:none;">
+ <input type="radio" name="checkedtestradios" checked="checked"/>
+ <input type="radio" name="checkedtestradios" value="on"/>
+ <input type="checkbox" name="checkedtestcheckboxes" checked="checked"/>
+ <input type="checkbox" name="checkedtestcheckboxes" />
+ </div>
+ </form>
+ <div id="nonnodes"><span>hi</span> there <!-- mon ami --></div>
+ <div id="t2037">
+ <div><div class="hidden">hidden</div></div>
+ </div>
+ <div id="t6652">
+ <div></div>
+ </div>
+ <div id="no-clone-exception"><object><embed></embed></object></div>
+</div>
+
+<div id="tabindex-tests">
+ <ol id="listWithTabIndex" tabindex="5">
+ <li id="foodWithNegativeTabIndex" tabindex="-1">Rice</li>
+ <li id="foodNoTabIndex">Beans</li>
+ <li>Blinis</li>
+ <li>Tofu</li>
+ </ol>
+
+ <div id="divWithNoTabIndex">I'm hungry. I should...</div>
+ <span>...</span><a href="#" id="linkWithNoTabIndex">Eat lots of food</a><span>...</span> |
+ <span>...</span><a href="#" id="linkWithTabIndex" tabindex="2">Eat a little food</a><span>...</span> |
+ <span>...</span><a href="#" id="linkWithNegativeTabIndex" tabindex="-1">Eat no food</a><span>...</span>
+ <span>...</span><a id="linkWithNoHrefWithNoTabIndex">Eat a burger</a><span>...</span>
+ <span>...</span><a id="linkWithNoHrefWithTabIndex" tabindex="1">Eat some funyuns</a><span>...</span>
+ <span>...</span><a id="linkWithNoHrefWithNegativeTabIndex" tabindex="-1">Eat some funyuns</a><span>...</span>
+</div>
+
+<div id="liveHandlerOrder">
+ <span id="liveSpan1"><a href="#" id="liveLink1"></a></span>
+ <span id="liveSpan2"><a href="#" id="liveLink2"></a></span>
+</div>
+
+<div id="siblingTest">
+ <em id="siblingfirst">1</em>
+ <em id="siblingnext">2</em>
+ <em id="siblingthird">
+ <em id="siblingchild">
+ <em id="siblinggrandchild">
+ <em id="siblinggreatgrandchild"></em>
+ </em>
+ </em>
+ </em>
+ <span id="siblingspan"></span>
+</div>
+<div id="fx-test-group" style="position: absolute; width: 1px; height: 1px; overflow: hidden;">
+ <div id="fx-queue" name="test">
+ <div id="fadein" class='chain-test' name='div'>fadeIn<div>fadeIn</div></div>
+ <div id="fadeout" class='chain-test chain-test-out'>fadeOut<div>fadeOut</div></div>
+
+ <div id="show" class='chain-test'>show<div>show</div></div>
+ <div id="hide" class='chain-test chain-test-out'>hide<div>hide</div></div>
+ <div id="easehide" class='chain-test chain-test-out'>hide<div>hide</div></div>
+
+ <div id="togglein" class='chain-test'>togglein<div>togglein</div></div>
+ <div id="toggleout" class='chain-test chain-test-out'>toggleout<div>toggleout</div></div>
+ <div id="easetoggleout" class='chain-test chain-test-out'>toggleout<div>toggleout</div></div>
+
+ <div id="slideup" class='chain-test'>slideUp<div>slideUp</div></div>
+ <div id="slidedown" class='chain-test chain-test-out'>slideDown<div>slideDown</div></div>
+ <div id="easeslideup" class='chain-test'>slideUp<div>slideUp</div></div>
+
+ <div id="slidetogglein" class='chain-test'>slideToggleIn<div>slideToggleIn</div></div>
+ <div id="slidetoggleout" class='chain-test chain-test-out'>slideToggleOut<div>slideToggleOut</div></div>
+
+ <div id="fadetogglein" class='chain-test'>fadeToggleIn<div>fadeToggleIn</div></div>
+ <div id="fadetoggleout" class='chain-test chain-test-out'>fadeToggleOut<div>fadeToggleOut</div></div>
+
+ <div id="fadeto" class='chain-test'>fadeTo<div>fadeTo</div></div>
+ </div>
+
+ <div id="fx-tests"></div>
+</div>
+</div>
+</dl>
+<map name="imgmap" id="imgmap">
+ <area shape="rect" coords="0,0,200,50">
+</map>
+
+</body>
+</html>
View
1,363 Test/core.js
@@ -0,0 +1,1363 @@
+/**
+ * Created with JetBrains WebStorm.
+ * User: cristian
+ * Date: 16/11/2012
+ * Time: 17:19
+ * To change this template use File | Settings | File Templates.
+ */
+var jQuery = global.jQuery, $ = jQuery
+
+"use strict";
+var ready = require('elements/domready')
+var expect = require('expect.js')
+describe('core.js', function(){
+ // prepare the environment
+ beforeEach(function(){
+
+ })
+
+ describe('Basic requirements', function(){
+
+ it('should have Array.push', function(){
+ expect(Array.prototype.push).to.be.ok()
+ })
+
+ it('should have Function.apply', function(){
+ expect(Function.prototype.apply).to.be.ok()
+ })
+
+ it('should have getElementById', function(){
+ expect(document.getElementById).to.be.ok()
+ })
+
+ it('should have getElementByTagName', function(){
+ expect(document.getElementsByTagName).to.be.ok()
+ })
+
+ it('should have the RegExp object', function(){
+ expect(RegExp).to.be.ok()
+ })
+
+ it('should have load jQuery (mtQuery)', function(){
+ expect(jQuery).to.be.ok()
+ })
+
+ it('should have aliased $ to jQuery (mtQuery)', function(){
+ expect($).to.be.ok()
+ })
+ })
+
+ describe("jQuery()", function() {
+ var elem, i, obj, main, code, img, div, exec, lng, expected, attrObj;
+ beforeEach(function(){
+
+
+ obj = jQuery("div");
+ main = jQuery("#qunit-fixture");
+ code = jQuery("<code/>");
+ img = jQuery("<img/>");
+ div = jQuery("<div/><hr/><code/><b/>");
+ exec = false;
+ lng = "";
+ expected = 26;
+ attrObj = {
+ "click": function() { exec = true; },
+ "text": "test",
+ "class": "test2",
+ "id": "test3"
+ };
+
+
+ attrObj["width"] = 10;
+
+ attrObj["offset"] = { "top": 1, "left": 1 };
+
+ attrObj["css"] = { "paddingLeft": 1, "paddingRight": 1 };
+
+ attrObj.attr = { "desired": "very" };
+
+ })
+ // Basic constructor's behavior
+ it('should return an empty array when called without parameters', function(){
+ expect(jQuery().length).to.be(0);
+ })
+
+ it('should return an empty array when undefined is passed', function(){
+ expect(jQuery(undefined).length).to.be(0);
+ })
+
+ it('should return an empty array when null is passed', function(){
+ expect(jQuery(null).length).to.be(0);
+ })
+
+ it('should return an empty array when "" is passed', function(){
+ expect(jQuery("").length).to.be(0);
+ })
+
+ it('should return an empty array when "#" is passed', function(){
+ expect(jQuery("#").length).to.be(0);
+ })
+
+ it('should return the same instance when a jQuery object is passed', function(){
+ expect(jQuery(obj).selector).to.be('div');
+ })
+
+ it('should found only one window when no iframe in the pages', function(){
+ expect(jQuery(window).length).to.be(1);
+ })
+
+ it('Basic selector with jquery context', function(){
+ var elements = [ 'sndp', 'en', 'sap' ];
+ for(var i = 0, max = elements.length; i<max; i++){
+
+ expect(jQuery('#' + elements[i], jQuery("div p", main).get())).to.be.ok(); // deepEqual( jQuery("div p", main).get(), q("sndp", "en", "sap"), "Basic selector with jQuery object as context" );
+ };
+ })
+
+ it('should have only 1 code element in code var',function(){
+ expect(code.length).to.be(1);
+ })
+
+ it('shouldn\'t have any parent (code)', function(){
+ expect(code.parent().length).to.be(0);
+ })
+
+ it('should have generated only an image', function(){
+ expect(img.length).to.be(1);
+ })
+
+ it('shouldn\'t have any parent (img)', function(){
+ expect(img.parent().length).to.be(0);
+ })
+
+ it('should have 4 element ', function(){
+ expect(div.length).to.be(4);
+ })
+
+ it('shouldn\'t have any parent (div)', function(){
+ expect(div.parent().length).to.be(0);
+ })
+
+ it('should work with array', function(){
+ expect(+ jQuery([1,2,3]).get(1)).to.be(2);
+ })
+
+ it('should work with domnodes', function(){
+ expect(jQuery(document.body) == jQuery('body')).to.be.ok()
+ })
+
+ it('should handle options when creating domnodes', function(){
+
+
+
+ elem = jQuery("<div/>", attrObj );
+
+
+ console.dir(elem);
+ expect(elem[0].style.width).to.be("10px");
+ expect(elem[0].style.top).to.be("1px");
+ expect(elem[0].style.paddingLeft).to.be("1px");
+ expect(elem[0].style.paddingRight).to.be("1px");
+ expect(elem[0].getAttribute("desired")).to.be("very");
+
+ expect(elem[0].childNodes.length).to.be(1);
+ expect(elem[0].firstChild.nodeValue).to.be("test");
+ expect(elem[0].className).to.be("test2");
+ expect(elem[0].id).to.be("test3");
+ exec = false;
+ elem.click();
+ expect(exec).to.be.ok();
+ elem.remove();
+ for ( i = 0; i < 3; ++i ) {
+ elem = jQuery("<input type='text' value='TEST' />");
+ }
+ expect(elem[0].defaultValue).to.be("TEST");
+ elem.remove();
+
+ //expect(jQuery(" <div/> ").length).to.be(1)
+ //expect(jQuery(" a<div/>b ").length).to.be(1)
+
+ })
+
+/*
+
+ // manually clean up detached elements
+ elem.remove();
+
+ equal( jQuery(" <div/> ").length, 1, "Make sure whitespace is trimmed." );
+ equal( jQuery(" a<div/>b ").length, 1, "Make sure whitespace and other characters are trimmed." );
+
+ for ( i = 0; i < 128; i++ ) {
+ lng += "12345678";
+ }
+
+ equal( jQuery(" <div>" + lng + "</div> ").length, 1, "Make sure whitespace is trimmed on long strings." );
+ equal( jQuery(" a<div>" + lng + "</div>b ").length, 1, "Make sure whitespace and other characters are trimmed on long strings." );
+ */
+ });
+
+})
+/*
+
+
+
+test( "selector state", function() {
+ expect( 18 );
+
+ var test;
+
+ test = jQuery( undefined );
+ equal( test.selector, "", "Empty jQuery Selector" );
+ equal( test.context, undefined, "Empty jQuery Context" );
+
+ test = jQuery( document );
+ equal( test.selector, "", "Document Selector" );
+ equal( test.context, document, "Document Context" );
+
+ test = jQuery( document.body );
+ equal( test.selector, "", "Body Selector" );
+ equal( test.context, document.body, "Body Context" );
+
+ test = jQuery("#qunit-fixture");
+ equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" );
+ equal( test.context, document, "#qunit-fixture Context" );
+
+ test = jQuery("#notfoundnono");
+ equal( test.selector, "#notfoundnono", "#notfoundnono Selector" );
+ equal( test.context, document, "#notfoundnono Context" );
+
+ test = jQuery( "#qunit-fixture", document );
+ equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" );
+ equal( test.context, document, "#qunit-fixture Context" );
+
+ test = jQuery( "#qunit-fixture", document.body );
+ equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" );
+ equal( test.context, document.body, "#qunit-fixture Context" );
+
+ // Test cloning
+ test = jQuery( test );
+ equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" );
+ equal( test.context, document.body, "#qunit-fixture Context" );
+
+ test = jQuery( document.body ).find("#qunit-fixture");
+ equal( test.selector, "#qunit-fixture", "#qunit-fixture find Selector" );
+ equal( test.context, document.body, "#qunit-fixture find Context" );
+});
+
+test( "globalEval", function() {
+ expect( 3 );
+
+ jQuery.globalEval("globalEvalTest = 1;");
+ equal( window.globalEvalTest, 1, "Test variable assignments are global" );
+
+ jQuery.globalEval("var globalEvalTest = 2;");
+ equal( window.globalEvalTest, 2, "Test variable declarations are global" );
+
+ jQuery.globalEval("this.globalEvalTest = 3;");
+ equal( window.globalEvalTest, 3, "Test context (this) is the window object" );
+
+ jQuery.globalEval("delete globalEvalTest;");
+});
+
+test("noConflict", function() {
+ expect(7);
+
+ var $$ = jQuery;
+
+ strictEqual( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" );
+ strictEqual( window["jQuery"], $$, "Make sure jQuery wasn't touched." );
+ strictEqual( window["$"], original$, "Make sure $ was reverted." );
+
+ jQuery = $ = $$;
+
+ strictEqual( jQuery.noConflict(true), $$, "noConflict returned the jQuery object" );
+ strictEqual( window["jQuery"], originaljQuery, "Make sure jQuery was reverted." );
+ strictEqual( window["$"], original$, "Make sure $ was reverted." );
+ ok( $$().pushStack([]), "Make sure that jQuery still works." );
+
+ window["jQuery"] = jQuery = $$;
+});
+
+test("trim", function() {
+ expect(13);
+
+ var nbsp = String.fromCharCode(160);
+
+ equal( jQuery.trim("hello "), "hello", "trailing space" );
+ equal( jQuery.trim(" hello"), "hello", "leading space" );
+ equal( jQuery.trim(" hello "), "hello", "space on both sides" );
+ equal( jQuery.trim(" " + nbsp + "hello " + nbsp + " "), "hello", "&nbsp;" );
+
+ equal( jQuery.trim(), "", "Nothing in." );
+ equal( jQuery.trim( undefined ), "", "Undefined" );
+ equal( jQuery.trim( null ), "", "Null" );
+ equal( jQuery.trim( 5 ), "5", "Number" );
+ equal( jQuery.trim( false ), "false", "Boolean" );
+
+ equal( jQuery.trim(" "), "", "space should be trimmed" );
+ equal( jQuery.trim("ipad\xA0"), "ipad", "nbsp should be trimmed" );
+ equal( jQuery.trim("\uFEFF"), "", "zwsp should be trimmed" );
+ equal( jQuery.trim("\uFEFF \xA0! | \uFEFF"), "! |", "leading/trailing should be trimmed" );
+});
+
+test("type", function() {
+ expect( 24 );
+
+ equal( jQuery.type(null), "null", "null" );
+ equal( jQuery.type(undefined), "undefined", "undefined" );
+ equal( jQuery.type(true), "boolean", "Boolean" );
+ equal( jQuery.type(false), "boolean", "Boolean" );
+ equal( jQuery.type(Boolean(true)), "boolean", "Boolean" );
+ equal( jQuery.type(0), "number", "Number" );
+ equal( jQuery.type(1), "number", "Number" );
+ equal( jQuery.type(Number(1)), "number", "Number" );
+ equal( jQuery.type(""), "string", "String" );
+ equal( jQuery.type("a"), "string", "String" );
+ equal( jQuery.type(String("a")), "string", "String" );
+ equal( jQuery.type({}), "object", "Object" );
+ equal( jQuery.type(/foo/), "regexp", "RegExp" );
+ equal( jQuery.type(new RegExp("asdf")), "regexp", "RegExp" );
+ equal( jQuery.type([1]), "array", "Array" );
+ equal( jQuery.type(new Date()), "date", "Date" );
+ equal( jQuery.type(new Function("return;")), "function", "Function" );
+ equal( jQuery.type(function(){}), "function", "Function" );
+ equal( jQuery.type(new Error()), "error", "Error" );
+ equal( jQuery.type(window), "object", "Window" );
+ equal( jQuery.type(document), "object", "Document" );
+ equal( jQuery.type(document.body), "object", "Element" );
+ equal( jQuery.type(document.createTextNode("foo")), "object", "TextNode" );
+ equal( jQuery.type(document.getElementsByTagName("*")), "object", "NodeList" );
+});
+
+asyncTest("isPlainObject", function() {
+ expect(15);
+
+ var pass, iframe, doc,
+ fn = function() {};
+
+ // The use case that we want to match
+ ok( jQuery.isPlainObject({}), "{}" );
+
+ // Not objects shouldn't be matched
+ ok( !jQuery.isPlainObject(""), "string" );
+ ok( !jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number" );
+ ok( !jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean" );
+ ok( !jQuery.isPlainObject(null), "null" );
+ ok( !jQuery.isPlainObject(undefined), "undefined" );
+
+ // Arrays shouldn't be matched
+ ok( !jQuery.isPlainObject([]), "array" );
+
+ // Instantiated objects shouldn't be matched
+ ok( !jQuery.isPlainObject(new Date()), "new Date" );
+
+ // Functions shouldn't be matched
+ ok( !jQuery.isPlainObject(fn), "fn" );
+
+ // Again, instantiated objects shouldn't be matched
+ ok( !jQuery.isPlainObject(new fn()), "new fn (no methods)" );
+
+ // Makes the function a little more realistic
+ // (and harder to detect, incidentally)
+ fn.prototype["someMethod"] = function(){};
+
+ // Again, instantiated objects shouldn't be matched
+ ok( !jQuery.isPlainObject(new fn()), "new fn" );
+
+ // DOM Element
+ ok( !jQuery.isPlainObject( document.createElement("div") ), "DOM Element" );
+
+ // Window
+ ok( !jQuery.isPlainObject( window ), "window" );
+
+ pass = false;
+ try {
+ jQuery.isPlainObject( window.location );
+ pass = true;
+ } catch ( e ) {}
+ ok( pass, "Does not throw exceptions on host objects" );
+
+ // Objects from other windows should be matched
+ window.iframeCallback = function( otherObject, detail ) {
+ window.iframeCallback = undefined;
+ iframe.parentNode.removeChild( iframe );
+ ok( jQuery.isPlainObject(new otherObject()), "new otherObject" + ( detail ? " - " + detail : "" ) );
+ start();
+ };
+
+ try {
+ iframe = jQuery("#qunit-fixture")[0].appendChild( document.createElement("iframe") );
+ doc = iframe.contentDocument || iframe.contentWindow.document;
+ doc.open();
+ doc.write("<body onload='window.parent.iframeCallback(Object);'>");
+ doc.close();
+ } catch(e) {
+ window.iframeDone( Object, "iframes not supported" );
+ }
+});
+
+test("isFunction", function() {
+ expect(19);
+
+ // Make sure that false values return false
+ ok( !jQuery.isFunction(), "No Value" );
+ ok( !jQuery.isFunction( null ), "null Value" );
+ ok( !jQuery.isFunction( undefined ), "undefined Value" );
+ ok( !jQuery.isFunction( "" ), "Empty String Value" );
+ ok( !jQuery.isFunction( 0 ), "0 Value" );
+
+ // Check built-ins
+ // Safari uses "(Internal Function)"
+ ok( jQuery.isFunction(String), "String Function("+String+")" );
+ ok( jQuery.isFunction(Array), "Array Function("+Array+")" );
+ ok( jQuery.isFunction(Object), "Object Function("+Object+")" );
+ ok( jQuery.isFunction(Function), "Function Function("+Function+")" );
+
+ // When stringified, this could be misinterpreted
+ var mystr = "function";
+ ok( !jQuery.isFunction(mystr), "Function String" );
+
+ // When stringified, this could be misinterpreted
+ var myarr = [ "function" ];
+ ok( !jQuery.isFunction(myarr), "Function Array" );
+
+ // When stringified, this could be misinterpreted
+ var myfunction = { "function": "test" };
+ ok( !jQuery.isFunction(myfunction), "Function Object" );
+
+ // Make sure normal functions still work
+ var fn = function(){};
+ ok( jQuery.isFunction(fn), "Normal Function" );
+
+ var obj = document.createElement("object");
+
+ // Firefox says this is a function
+ ok( !jQuery.isFunction(obj), "Object Element" );
+
+ // IE says this is an object
+ // Since 1.3, this isn't supported (#2968)
+ //ok( jQuery.isFunction(obj.getAttribute), "getAttribute Function" );
+
+ var nodes = document.body.childNodes;
+
+ // Safari says this is a function
+ ok( !jQuery.isFunction(nodes), "childNodes Property" );
+
+ var first = document.body.firstChild;
+
+ // Normal elements are reported ok everywhere
+ ok( !jQuery.isFunction(first), "A normal DOM Element" );
+
+ var input = document.createElement("input");
+ input.type = "text";
+ document.body.appendChild( input );
+
+ // IE says this is an object
+ // Since 1.3, this isn't supported (#2968)
+ //ok( jQuery.isFunction(input.focus), "A default function property" );
+
+ document.body.removeChild( input );
+
+ var a = document.createElement("a");
+ a.href = "some-function";
+ document.body.appendChild( a );
+
+ // This serializes with the word 'function' in it
+ ok( !jQuery.isFunction(a), "Anchor Element" );
+
+ document.body.removeChild( a );
+
+ // Recursive function calls have lengths and array-like properties
+ function callme(callback){
+ function fn(response){
+ callback(response);
+ }
+
+ ok( jQuery.isFunction(fn), "Recursive Function Call" );
+
+ fn({ some: "data" });
+ }
+
+ callme(function(){
+ callme(function(){});
+ });
+});
+
+test( "isNumeric", function() {
+ expect( 36 );
+
+ var t = jQuery.isNumeric,
+ Traditionalists = function(n) {
+ this.value = n;
+ this.toString = function(){
+ return String(this.value);
+ };
+ },
+ answer = new Traditionalists( "42" ),
+ rong = new Traditionalists( "Devo" );
+
+ ok( t("-10"), "Negative integer string");
+ ok( t("0"), "Zero string");
+ ok( t("5"), "Positive integer string");
+ ok( t(-16), "Negative integer number");
+ ok( t(0), "Zero integer number");
+ ok( t(32), "Positive integer number");
+ ok( t("040"), "Octal integer literal string");
+ // OctalIntegerLiteral has been deprecated since ES3/1999
+ // It doesn't pass lint, so disabling until a solution can be found
+ //ok( t(0144), "Octal integer literal");
+ ok( t("0xFF"), "Hexadecimal integer literal string");
+ ok( t(0xFFF), "Hexadecimal integer literal");
+ ok( t("-1.6"), "Negative floating point string");
+ ok( t("4.536"), "Positive floating point string");
+ ok( t(-2.6), "Negative floating point number");
+ ok( t(3.1415), "Positive floating point number");
+ ok( t(8e5), "Exponential notation");
+ ok( t("123e-2"), "Exponential notation string");
+ ok( t(answer), "Custom .toString returning number");
+ equal( t(""), false, "Empty string");
+ equal( t(" "), false, "Whitespace characters string");
+ equal( t("\t\t"), false, "Tab characters string");
+ equal( t("abcdefghijklm1234567890"), false, "Alphanumeric character string");
+ equal( t("xabcdefx"), false, "Non-numeric character string");
+ equal( t(true), false, "Boolean true literal");
+ equal( t(false), false, "Boolean false literal");
+ equal( t("bcfed5.2"), false, "Number with preceding non-numeric characters");
+ equal( t("7.2acdgs"), false, "Number with trailling non-numeric characters");
+ equal( t(undefined), false, "Undefined value");
+ equal( t(null), false, "Null value");
+ equal( t(NaN), false, "NaN value");
+ equal( t(Infinity), false, "Infinity primitive");
+ equal( t(Number.POSITIVE_INFINITY), false, "Positive Infinity");
+ equal( t(Number.NEGATIVE_INFINITY), false, "Negative Infinity");
+ equal( t(rong), false, "Custom .toString returning non-number");
+ equal( t({}), false, "Empty object");
+ equal( t(function(){} ), false, "Instance of a function");
+ equal( t( new Date() ), false, "Instance of a Date");
+ equal( t(function(){} ), false, "Instance of a function");
+});
+
+test("isXMLDoc - HTML", function() {
+ expect(4);
+
+ ok( !jQuery.isXMLDoc( document ), "HTML document" );
+ ok( !jQuery.isXMLDoc( document.documentElement ), "HTML documentElement" );
+ ok( !jQuery.isXMLDoc( document.body ), "HTML Body Element" );
+
+ var iframe = document.createElement("iframe");
+ document.body.appendChild( iframe );
+
+ try {
+ var body = jQuery(iframe).contents()[0];
+
+ try {
+ ok( !jQuery.isXMLDoc( body ), "Iframe body element" );
+ } catch(e) {
+ ok( false, "Iframe body element exception" );
+ }
+
+ } catch(e) {
+ ok( true, "Iframe body element - iframe not working correctly" );
+ }
+
+ document.body.removeChild( iframe );
+});
+
+test("XSS via location.hash", function() {
+ expect(1);
+
+ stop();
+ jQuery["_check9521"] = function(x){
+ ok( x, "script called from #id-like selector with inline handler" );
+ jQuery("#check9521").remove();
+ delete jQuery["_check9521"];
+ start();
+ };
+ try {
+ // This throws an error because it's processed like an id
+ jQuery( "#<img id='check9521' src='no-such-.gif' onerror='jQuery._check9521(false)'>" ).appendTo("#qunit-fixture");
+ } catch (err) {
+ jQuery["_check9521"](true);
+ }
+});
+
+test("isXMLDoc - XML", function() {
+ expect(3);
+ var xml = createDashboardXML();
+ ok( jQuery.isXMLDoc( xml ), "XML document" );
+ ok( jQuery.isXMLDoc( xml.documentElement ), "XML documentElement" );
+ ok( jQuery.isXMLDoc( jQuery("tab", xml)[0] ), "XML Tab Element" );
+});
+
+test("isWindow", function() {
+ expect( 14 );
+
+ ok( jQuery.isWindow(window), "window" );
+ ok( jQuery.isWindow(document.getElementsByTagName("iframe")[0].contentWindow), "iframe.contentWindow" );
+ ok( !jQuery.isWindow(), "empty" );
+ ok( !jQuery.isWindow(null), "null" );
+ ok( !jQuery.isWindow(undefined), "undefined" );
+ ok( !jQuery.isWindow(document), "document" );
+ ok( !jQuery.isWindow(document.documentElement), "documentElement" );
+ ok( !jQuery.isWindow(""), "string" );
+ ok( !jQuery.isWindow(1), "number" );
+ ok( !jQuery.isWindow(true), "boolean" );
+ ok( !jQuery.isWindow({}), "object" );
+ ok( !jQuery.isWindow({ setInterval: function(){} }), "fake window" );
+ ok( !jQuery.isWindow(/window/), "regexp" );
+ ok( !jQuery.isWindow(function(){}), "function" );
+});
+
+test("jQuery('html')", function() {
+ expect( 15 );
+
+ QUnit.reset();
+ jQuery["foo"] = false;
+ var s = jQuery("<script>jQuery.foo='test';</script>")[0];
+ ok( s, "Creating a script" );
+ ok( !jQuery["foo"], "Make sure the script wasn't executed prematurely" );
+ jQuery("body").append("<script>jQuery.foo='test';</script>");
+ ok( jQuery["foo"], "Executing a scripts contents in the right context" );
+
+ // Test multi-line HTML
+ var div = jQuery("<div>\r\nsome text\n<p>some p</p>\nmore text\r\n</div>")[0];
+ equal( div.nodeName.toUpperCase(), "DIV", "Make sure we're getting a div." );
+ equal( div.firstChild.nodeType, 3, "Text node." );
+ equal( div.lastChild.nodeType, 3, "Text node." );
+ equal( div.childNodes[1].nodeType, 1, "Paragraph." );
+ equal( div.childNodes[1].firstChild.nodeType, 3, "Paragraph text." );
+
+ QUnit.reset();
+ ok( jQuery("<link rel='stylesheet'/>")[0], "Creating a link" );
+
+ ok( !jQuery("<script/>")[0].parentNode, "Create a script" );
+
+ ok( jQuery("<input/>").attr("type", "hidden"), "Create an input and set the type." );
+
+ var j = jQuery("<span>hi</span> there <!-- mon ami -->");
+ ok( j.length >= 2, "Check node,textnode,comment creation (some browsers delete comments)" );
+
+ ok( !jQuery("<option>test</option>")[0].selected, "Make sure that options are auto-selected #2050" );
+
+ ok( jQuery("<div></div>")[0], "Create a div with closing tag." );
+ ok( jQuery("<table></table>")[0], "Create a table with closing tag." );
+
+ // equal( jQuery("element[attribute='<div></div>']").length, 0, "When html is within brackets, do not recognize as html." );
+ // equal( jQuery("element[attribute=<div></div>]").length, 0, "When html is within brackets, do not recognize as html." );
+ // equal( jQuery("element:not(<div></div>)").length, 0, "When html is within parens, do not recognize as html." );
+ // equal( jQuery("\\<div\\>").length, 0, "Ignore escaped html characters" );
+});
+
+test("jQuery('massive html #7990')", function() {
+ expect( 3 );
+
+ var i;
+ var li = "<li>very very very very large html string</li>";
+ var html = ["<ul>"];
+ for ( i = 0; i < 30000; i += 1 ) {
+ html[html.length] = li;
+ }
+ html[html.length] = "</ul>";
+ html = jQuery(html.join(""))[0];
+ equal( html.nodeName.toLowerCase(), "ul");
+ equal( html.firstChild.nodeName.toLowerCase(), "li");
+ equal( html.childNodes.length, 30000 );
+});
+
+test("jQuery('html', context)", function() {
+ expect(1);
+
+ var $div = jQuery("<div/>")[0];
+ var $span = jQuery("<span/>", $div);
+ equal($span.length, 1, "Verify a span created with a div context works, #1763");
+});
+
+test("jQuery(selector, xml).text(str) - Loaded via XML document", function() {
+ expect(2);
+
+ var xml = createDashboardXML();
+ // tests for #1419 where IE was a problem
+ var tab = jQuery("tab", xml).eq(0);
+ equal( tab.text(), "blabla", "Verify initial text correct" );
+ tab.text("newtext");
+ equal( tab.text(), "newtext", "Verify new text correct" );
+});
+
+test("end()", function() {
+ expect(3);
+ equal( "Yahoo", jQuery("#yahoo").parent().end().text(), "Check for end" );
+ ok( jQuery("#yahoo").end(), "Check for end with nothing to end" );
+
+ var x = jQuery("#yahoo");
+ x.parent();
+ equal( "Yahoo", jQuery("#yahoo").text(), "Check for non-destructive behaviour" );
+});
+
+test("length", function() {
+ expect(1);
+ equal( jQuery("#qunit-fixture p").length, 6, "Get Number of Elements Found" );
+});
+
+test("size()", function() {
+ expect(1);
+ equal( jQuery("#qunit-fixture p").size(), 6, "Get Number of Elements Found" );
+});
+
+test("get()", function() {
+ expect(1);
+ deepEqual( jQuery("#qunit-fixture p").get(), q("firstp","ap","sndp","en","sap","first"), "Get All Elements" );
+});
+
+test("toArray()", function() {
+ expect(1);
+ deepEqual( jQuery("#qunit-fixture p").toArray(),
+ q("firstp","ap","sndp","en","sap","first"),
+ "Convert jQuery object to an Array" );
+});
+
+test("inArray()", function() {
+ expect(19);
+
+ var selections = {
+ p: q("firstp", "sap", "ap", "first"),
+ em: q("siblingnext", "siblingfirst"),
+ div: q("qunit-testrunner-toolbar", "nothiddendiv", "nothiddendivchild", "foo"),
+ a: q("mark", "groups", "google", "simon1"),
+ empty: []
+ },
+ tests = {
+ p: { elem: jQuery("#ap")[0], index: 2 },
+ em: { elem: jQuery("#siblingfirst")[0], index: 1 },
+ div: { elem: jQuery("#nothiddendiv")[0], index: 1 },
+ a: { elem: jQuery("#simon1")[0], index: 3 }
+ },
+ falseTests = {
+ p: jQuery("#liveSpan1")[0],
+ em: jQuery("#nothiddendiv")[0],
+ empty: ""
+ };
+
+ jQuery.each( tests, function( key, obj ) {
+ equal( jQuery.inArray( obj.elem, selections[ key ] ), obj.index, "elem is in the array of selections of its tag" );
+ // Third argument (fromIndex)
+ equal( !!~jQuery.inArray( obj.elem, selections[ key ], 5 ), false, "elem is NOT in the array of selections given a starting index greater than its position" );
+ equal( !!~jQuery.inArray( obj.elem, selections[ key ], 1 ), true, "elem is in the array of selections given a starting index less than or equal to its position" );
+ equal( !!~jQuery.inArray( obj.elem, selections[ key ], -3 ), true, "elem is in the array of selections given a negative index" );
+ });
+
+ jQuery.each( falseTests, function( key, elem ) {
+ equal( !!~jQuery.inArray( elem, selections[ key ] ), false, "elem is NOT in the array of selections" );
+ });
+
+});
+
+test("get(Number)", function() {
+ expect(2);
+ equal( jQuery("#qunit-fixture p").get(0), document.getElementById("firstp"), "Get A Single Element" );
+ strictEqual( jQuery("#firstp").get(1), undefined, "Try get with index larger elements count" );
+});
+
+test("get(-Number)",function() {
+ expect(2);
+ equal( jQuery("p").get(-1), document.getElementById("first"), "Get a single element with negative index" );
+ strictEqual( jQuery("#firstp").get(-2), undefined, "Try get with index negative index larger then elements count" );
+});
+
+test("each(Function)", function() {
+ expect(1);
+ var div = jQuery("div");
+ div.each(function(){this.foo = "zoo";});
+ var pass = true;
+ for ( var i = 0; i < div.size(); i++ ) {
+ if ( div.get(i).foo != "zoo" ) {
+ pass = false;
+ }
+ }
+ ok( pass, "Execute a function, Relative" );
+});
+
+test("slice()", function() {
+ expect(7);
+
+ var $links = jQuery("#ap a");
+
+ deepEqual( $links.slice(1,2).get(), q("groups"), "slice(1,2)" );
+ deepEqual( $links.slice(1).get(), q("groups", "anchor1", "mark"), "slice(1)" );
+ deepEqual( $links.slice(0,3).get(), q("google", "groups", "anchor1"), "slice(0,3)" );
+ deepEqual( $links.slice(-1).get(), q("mark"), "slice(-1)" );
+
+ deepEqual( $links.eq(1).get(), q("groups"), "eq(1)" );
+ deepEqual( $links.eq("2").get(), q("anchor1"), "eq('2')" );
+ deepEqual( $links.eq(-1).get(), q("mark"), "eq(-1)" );
+});
+
+test("first()/last()", function() {
+ expect(4);
+
+ var $links = jQuery("#ap a"), $none = jQuery("asdf");
+
+ deepEqual( $links.first().get(), q("google"), "first()" );
+ deepEqual( $links.last().get(), q("mark"), "last()" );
+
+ deepEqual( $none.first().get(), [], "first() none" );
+ deepEqual( $none.last().get(), [], "last() none" );
+});
+
+test("map()", function() {
+ expect(8);
+
+ deepEqual(
+ jQuery("#ap").map(function(){
+ return jQuery(this).find("a").get();
+ }).get(),
+ q("google", "groups", "anchor1", "mark"),
+ "Array Map"
+ );
+
+ deepEqual(
+ jQuery("#ap > a").map(function(){
+ return this.parentNode;
+ }).get(),
+ q("ap","ap","ap"),
+ "Single Map"
+ );
+
+ var keys, values, scripts, nonsense, mapped, flat;
+ //for #2616
+ keys = jQuery.map( {"a":1,"b":2}, function( v, k ){
+ return k;
+ });
+ equal( keys.join(""), "ab", "Map the keys from a hash to an array" );
+
+ values = jQuery.map( {a:1,b:2}, function( v, k ){
+ return v;
+ });
+ equal( values.join(""), "12", "Map the values from a hash to an array" );
+
+ // object with length prop
+ values = jQuery.map( {a:1,b:2, length:3}, function( v, k ){
+ return v;
+ });
+ equal( values.join(""), "123", "Map the values from a hash with a length property to an array" );
+
+ scripts = document.getElementsByTagName("script");
+ mapped = jQuery.map( scripts, function( v, k ){
+ return v;
+ });
+ equal( mapped.length, scripts.length, "Map an array(-like) to a hash" );
+
+ nonsense = document.getElementsByTagName("asdf");
+ mapped = jQuery.map( nonsense, function( v, k ){
+ return v;
+ });
+ equal( mapped.length, nonsense.length, "Map an empty array(-like) to a hash" );
+
+ flat = jQuery.map( Array(4), function( v, k ){
+ return k % 2 ? k : [k,k,k];//try mixing array and regular returns
+ });
+ equal( flat.join(""), "00012223", "try the new flatten technique(#2616)" );
+});
+
+test("jQuery.merge()", function() {
+ expect(8);
+
+ var parse = jQuery.merge;
+
+ deepEqual( parse([],[]), [], "Empty arrays" );
+
+ deepEqual( parse([1],[2]), [1,2], "Basic" );
+ deepEqual( parse([1,2],[3,4]), [1,2,3,4], "Basic" );
+
+ deepEqual( parse([1,2],[]), [1,2], "Second empty" );
+ deepEqual( parse([],[1,2]), [1,2], "First empty" );
+
+ // Fixed at [5998], #3641
+ deepEqual( parse([-2,-1], [0,1,2]), [-2,-1,0,1,2], "Second array including a zero (falsy)");
+
+ // After fixing #5527
+ deepEqual( parse([], [null, undefined]), [null, undefined], "Second array including null and undefined values");
+ deepEqual( parse({"length":0}, [1,2]), {length:2, 0:1, 1:2}, "First array like");
+});
+
+test("jQuery.extend(Object, Object)", function() {
+ expect(28);
+
+ var settings = { "xnumber1": 5, "xnumber2": 7, "xstring1": "peter", "xstring2": "pan" },
+ options = { "xnumber2": 1, "xstring2": "x", "xxx": "newstring" },
+ optionsCopy = { "xnumber2": 1, "xstring2": "x", "xxx": "newstring" },
+ merged = { "xnumber1": 5, "xnumber2": 1, "xstring1": "peter", "xstring2": "x", "xxx": "newstring" },
+ deep1 = { "foo": { "bar": true } },
+ deep1copy = { "foo": { "bar": true } },
+ deep2 = { "foo": { "baz": true }, "foo2": document },
+ deep2copy = { "foo": { "baz": true }, "foo2": document },
+ deepmerged = { "foo": { "bar": true, "baz": true }, "foo2": document },
+ arr = [1, 2, 3],
+ nestedarray = { "arr": arr };
+
+ jQuery.extend(settings, options);
+ deepEqual( settings, merged, "Check if extended: settings must be extended" );
+ deepEqual( options, optionsCopy, "Check if not modified: options must not be modified" );
+
+ jQuery.extend(settings, null, options);
+ deepEqual( settings, merged, "Check if extended: settings must be extended" );
+ deepEqual( options, optionsCopy, "Check if not modified: options must not be modified" );
+
+ jQuery.extend(true, deep1, deep2);
+ deepEqual( deep1["foo"], deepmerged["foo"], "Check if foo: settings must be extended" );
+ deepEqual( deep2["foo"], deep2copy["foo"], "Check if not deep2: options must not be modified" );
+ equal( deep1["foo2"], document, "Make sure that a deep clone was not attempted on the document" );
+
+ ok( jQuery.extend(true, {}, nestedarray)["arr"] !== arr, "Deep extend of object must clone child array" );
+
+ // #5991
+ ok( jQuery.isArray( jQuery.extend(true, { "arr": {} }, nestedarray)["arr"] ), "Cloned array heve to be an Array" );
+ ok( jQuery.isPlainObject( jQuery.extend(true, { "arr": arr }, { "arr": {} })["arr"] ), "Cloned object heve to be an plain object" );
+
+ var empty = {};
+ var optionsWithLength = { "foo": { "length": -1 } };
+ jQuery.extend(true, empty, optionsWithLength);
+ deepEqual( empty["foo"], optionsWithLength["foo"], "The length property must copy correctly" );
+
+ empty = {};
+ var optionsWithDate = { "foo": { "date": new Date() } };
+ jQuery.extend(true, empty, optionsWithDate);
+ deepEqual( empty["foo"], optionsWithDate["foo"], "Dates copy correctly" );
+
+
+ var myKlass = function() {};
+ var customObject = new myKlass();
+ var optionsWithCustomObject = { "foo": { "date": customObject } };
+ empty = {};
+ jQuery.extend(true, empty, optionsWithCustomObject);
+ ok( empty["foo"] && empty["foo"]["date"] === customObject, "Custom objects copy correctly (no methods)" );
+
+ // Makes the class a little more realistic
+ myKlass.prototype = { "someMethod": function(){} };
+ empty = {};
+ jQuery.extend(true, empty, optionsWithCustomObject);
+ ok( empty["foo"] && empty["foo"]["date"] === customObject, "Custom objects copy correctly" );
+
+ var MyNumber = Number;
+ var ret = jQuery.extend(true, { "foo": 4 }, { "foo": new MyNumber(5) } );
+ ok( ret.foo == 5, "Wrapped numbers copy correctly" );
+
+ var nullUndef;
+ nullUndef = jQuery.extend({}, options, { "xnumber2": null });
+ ok( nullUndef["xnumber2"] === null, "Check to make sure null values are copied");
+
+ nullUndef = jQuery.extend({}, options, { "xnumber2": undefined });
+ ok( nullUndef["xnumber2"] === options["xnumber2"], "Check to make sure undefined values are not copied");
+
+ nullUndef = jQuery.extend({}, options, { "xnumber0": null });
+ ok( nullUndef["xnumber0"] === null, "Check to make sure null values are inserted");
+
+ var target = {};
+ var recursive = { foo:target, bar:5 };
+ jQuery.extend(true, target, recursive);
+ deepEqual( target, { bar:5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" );
+
+ ret = jQuery.extend(true, { foo: [] }, { foo: [0] } ); // 1907
+ equal( ret.foo.length, 1, "Check to make sure a value with coersion 'false' copies over when necessary to fix #1907" );
+
+ ret = jQuery.extend(true, { foo: "1,2,3" }, { foo: [1, 2, 3] } );
+ ok( typeof ret.foo != "string", "Check to make sure values equal with coersion (but not actually equal) overwrite correctly" );
+
+ ret = jQuery.extend(true, { foo:"bar" }, { foo:null } );
+ ok( typeof ret.foo !== "undefined", "Make sure a null value doesn't crash with deep extend, for #1908" );
+
+ var obj = { foo:null };
+ jQuery.extend(true, obj, { foo:"notnull" } );
+ equal( obj.foo, "notnull", "Make sure a null value can be overwritten" );
+
+ function func() {}
+ jQuery.extend(func, { key: "value" } );
+ equal( func.key, "value", "Verify a function can be extended" );
+
+ var defaults = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
+ defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
+ options1 = { xnumber2: 1, xstring2: "x" },
+ options1Copy = { xnumber2: 1, xstring2: "x" },
+ options2 = { xstring2: "xx", xxx: "newstringx" },
+ options2Copy = { xstring2: "xx", xxx: "newstringx" },
+ merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" };
+
+ settings = jQuery.extend({}, defaults, options1, options2);
+ deepEqual( settings, merged2, "Check if extended: settings must be extended" );
+ deepEqual( defaults, defaultsCopy, "Check if not modified: options1 must not be modified" );
+ deepEqual( options1, options1Copy, "Check if not modified: options1 must not be modified" );
+ deepEqual( options2, options2Copy, "Check if not modified: options2 must not be modified" );
+});
+
+test("jQuery.each(Object,Function)", function() {
+ expect(14);
+ jQuery.each( [0,1,2], function(i, n){
+ equal( i, n, "Check array iteration" );
+ });
+
+ jQuery.each( [5,6,7], function(i, n){
+ equal( i, n - 5, "Check array iteration" );
+ });
+
+ jQuery.each( { name: "name", lang: "lang" }, function(i, n){
+ equal( i, n, "Check object iteration" );
+ });
+
+ var total = 0;
+ jQuery.each([1,2,3], function(i,v){ total += v; });
+ equal( total, 6, "Looping over an array" );
+ total = 0;
+ jQuery.each([1,2,3], function(i,v){
+ total += v;
+ if ( i == 1 ) {
+ return false;
+ }
+ });
+ equal( total, 3, "Looping over an array, with break" );
+ total = 0;
+ jQuery.each({"a":1,"b":2,"c":3}, function(i,v){ total += v; });
+ equal( total, 6, "Looping over an object" );
+ total = 0;
+ jQuery.each({"a":3,"b":3,"c":3}, function(i,v){ total += v; return false; });
+ equal( total, 3, "Looping over an object, with break" );
+
+ var f = function(){};
+ f.foo = "bar";
+ jQuery.each(f, function(i){
+ f[i] = "baz";
+ });
+ equal( "baz", f.foo, "Loop over a function" );
+
+ var stylesheet_count = 0;
+ jQuery.each(document.styleSheets, function(i){
+ stylesheet_count++;
+ });
+ equal(stylesheet_count, 2, "should not throw an error in IE while looping over document.styleSheets and return proper amount");
+
+});
+
+test("jQuery.makeArray", function(){
+ expect(17);
+
+ equal( jQuery.makeArray(jQuery("html>*"))[0].nodeName.toUpperCase(), "HEAD", "Pass makeArray a jQuery object" );
+
+ equal( jQuery.makeArray(document.getElementsByName("PWD")).slice(0,1)[0].name, "PWD", "Pass makeArray a nodelist" );
+
+ equal( (function(arg1, arg2){ return jQuery.makeArray(arguments); })(1,2).join(""), "12", "Pass makeArray an arguments array" );
+
+ equal( jQuery.makeArray([1,2,3]).join(""), "123", "Pass makeArray a real array" );
+
+ equal( jQuery.makeArray().length, 0, "Pass nothing to makeArray and expect an empty array" );
+
+ equal( jQuery.makeArray( 0 )[0], 0 , "Pass makeArray a number" );
+
+ equal( jQuery.makeArray( "foo" )[0], "foo", "Pass makeArray a string" );
+
+ equal( jQuery.makeArray( true )[0].constructor, Boolean, "Pass makeArray a boolean" );
+
+ equal( jQuery.makeArray( document.createElement("div") )[0].nodeName.toUpperCase(), "DIV", "Pass makeArray a single node" );
+
+ equal( jQuery.makeArray( {length:2, 0:"a", 1:"b"} ).join(""), "ab", "Pass makeArray an array like map (with length)" );
+
+ ok( !!jQuery.makeArray( document.documentElement.childNodes ).slice(0,1)[0].nodeName, "Pass makeArray a childNodes array" );
+
+ // function, is tricky as it has length
+ equal( jQuery.makeArray( function(){ return 1;} )[0](), 1, "Pass makeArray a function" );
+
+ //window, also has length
+ equal( jQuery.makeArray(window)[0], window, "Pass makeArray the window" );
+
+ equal( jQuery.makeArray(/a/)[0].constructor, RegExp, "Pass makeArray a regex" );
+
+ ok( jQuery.makeArray(document.getElementById("form")).length >= 13, "Pass makeArray a form (treat as elements)" );
+
+ // For #5610
+ deepEqual( jQuery.makeArray({length: "0"}), [], "Make sure object is coerced properly.");
+ deepEqual( jQuery.makeArray({length: "5"}), [], "Make sure object is coerced properly.");
+});
+
+test("jQuery.inArray", function(){
+ expect(3);
+
+ equal( jQuery.inArray( 0, false ), -1 , "Search in 'false' as array returns -1 and doesn't throw exception" );
+
+ equal( jQuery.inArray( 0, null ), -1 , "Search in 'null' as array returns -1 and doesn't throw exception" );
+
+ equal( jQuery.inArray( 0, undefined ), -1 , "Search in 'undefined' as array returns -1 and doesn't throw exception" );
+});
+
+test("jQuery.isEmptyObject", function(){
+ expect(2);
+
+ equal(true, jQuery.isEmptyObject({}), "isEmptyObject on empty object literal" );
+ equal(false, jQuery.isEmptyObject({a:1}), "isEmptyObject on non-empty object literal" );
+
+ // What about this ?
+ // equal(true, jQuery.isEmptyObject(null), "isEmptyObject on null" );
+});
+
+test("jQuery.proxy", function(){
+ expect( 9 );
+
+ var test = function(){ equal( this, thisObject, "Make sure that scope is set properly." ); };
+ var thisObject = { foo: "bar", method: test };
+
+ // Make sure normal works
+ test.call( thisObject );
+
+ // Basic scoping
+ jQuery.proxy( test, thisObject )();
+
+ // Another take on it
+ jQuery.proxy( thisObject, "method" )();
+
+ // Make sure it doesn't freak out
+ equal( jQuery.proxy( null, thisObject ), undefined, "Make sure no function was returned." );
+
+ // Partial application
+ var test2 = function( a ){ equal( a, "pre-applied", "Ensure arguments can be pre-applied." ); };
+ jQuery.proxy( test2, null, "pre-applied" )();
+
+ // Partial application w/ normal arguments
+ var test3 = function( a, b ){ equal( b, "normal", "Ensure arguments can be pre-applied and passed as usual." ); };
+ jQuery.proxy( test3, null, "pre-applied" )( "normal" );
+
+ // Test old syntax
+ var test4 = { "meth": function( a ){ equal( a, "boom", "Ensure old syntax works." ); } };
+ jQuery.proxy( test4, "meth" )( "boom" );
+
+ // jQuery 1.9 improved currying with `this` object
+ var fn = function() {
+ equal( Array.prototype.join.call( arguments, "," ), "arg1,arg2,arg3", "args passed" );
+ equal( this.foo, "bar", "this-object passed" );
+ };
+ var cb = jQuery.proxy( fn, null, "arg1", "arg2" );
+ cb.call( thisObject, "arg3" );
+});
+
+test("jQuery.parseHTML", function() {
+ expect( 11 );
+
+ equal( jQuery.parseHTML(), null, "Nothing in, null out." );
+ equal( jQuery.parseHTML( null ), null, "Nothing in, null out." );
+ equal( jQuery.parseHTML( "" ), null, "Nothing in, null out." );
+ raises(function() {
+ jQuery.parseHTML( "<div>", document.getElementById("form") );
+ }, "Passing an element as the context raises an exception (context should be a document)");
+
+ var elems = jQuery.parseHTML( jQuery("body").html() );
+ ok( elems.length > 10, "Parse a large html string" );
+ equal( jQuery.type( elems ), "array", "parseHTML returns an array rather than a nodelist" );
+
+ var script = "<script>undefined()</script>";
+ equal( jQuery.parseHTML( script ).length, 0, "Passing a script is not allowed by default" );
+ raises(function() {
+ jQuery(jQuery.parseHTML( script, true )).appendTo("#qunit-fixture");
+ }, "Passing a script is allowed if allowScripts is true");
+
+ var html = script + "<div></div>";
+ equal( jQuery.parseHTML( html )[0].nodeName.toLowerCase(), "div", "Ignore scripts by default" );
+ raises(function() {
+ jQuery(jQuery.parseHTML( html, true )).appendTo("#qunit-fixture");
+ }, "Passing a script is allowed if allowScripts is true");
+
+ equal( jQuery.parseHTML("text")[0].nodeType, 3, "Parsing text returns a text node" );
+});
+
+test("jQuery.parseJSON", function(){
+ expect( 9 );
+
+ equal( jQuery.parseJSON( null ), null, "Actual null returns null" );
+ equal( jQuery.isEmptyObject( jQuery.parseJSON("{}") ), true, "Empty object returns empty object" );
+ deepEqual( jQuery.parseJSON("{\"test\":1}"), { "test": 1 }, "Plain object parses" );
+ deepEqual( jQuery.parseJSON("\n{\"test\":1}"), { "test": 1 }, "Leading whitespaces are ignored." );
+ raises(function() {
+ jQuery.parseJSON();
+ }, null, "Undefined raises an error" );
+ raises( function() {
+ jQuery.parseJSON( "" );
+ }, null, "Empty string raises an error" );
+ raises(function() {
+ jQuery.parseJSON("''");
+ }, null, "Single-quoted string raises an error" );
+ raises(function() {
+ jQuery.parseJSON("{a:1}");
+ }, null, "Unquoted property raises an error" );
+ raises(function() {
+ jQuery.parseJSON("{'a':1}");
+ }, null, "Single-quoted property raises an error" );
+});
+
+test("jQuery.parseXML", 8, function(){
+ var xml, tmp;
+ try {
+ xml = jQuery.parseXML( "<p>A <b>well-formed</b> xml string</p>" );
+ tmp = xml.getElementsByTagName( "p" )[ 0 ];
+ ok( !!tmp, "<p> present in document" );
+ tmp = tmp.getElementsByTagName( "b" )[ 0 ];
+ ok( !!tmp, "<b> present in document" );
+ strictEqual( tmp.childNodes[ 0 ].nodeValue, "well-formed", "<b> text is as expected" );
+ } catch (e) {
+ strictEqual( e, undefined, "unexpected error" );
+ }
+ try {
+ xml = jQuery.parseXML( "<p>Not a <<b>well-formed</b> xml string</p>" );
+ ok( false, "invalid xml not detected" );
+ } catch( e ) {
+ strictEqual( e.message, "Invalid XML: <p>Not a <<b>well-formed</b> xml string</p>", "invalid xml detected" );
+ }
+ try {
+ xml = jQuery.parseXML( "" );
+ strictEqual( xml, null, "empty string => null document" );
+ xml = jQuery.parseXML();
+ strictEqual( xml, null, "undefined string => null document" );
+ xml = jQuery.parseXML( null );
+ strictEqual( xml, null, "null string => null document" );
+ xml = jQuery.parseXML( true );
+ strictEqual( xml, null, "non-string => null document" );
+ } catch( e ) {
+ ok( false, "empty input throws exception" );
+ }
+});
+
+// Skip this test because IE6 takes too long; reinstate in the compat plugin
+if ( jQuery.sub_runs_too_slow_in_IE6 ) {
+
+ test("jQuery.sub() - Static Methods", function(){
+ expect(18);
+ var Subclass = jQuery.sub();
+ Subclass.extend({
+ "topLevelMethod": function() {return this.debug;},
+ "debug": false,
+ "config": {
+ "locale": "en_US"
+ },
+ "setup": function(config) {
+ this.extend(true, this["config"], config);
+ }
+ });
+ Subclass.fn.extend({"subClassMethod": function() { return this;}});
+
+ //Test Simple Subclass
+ ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
+ ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
+ deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
+ equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");
+
+ //Create a SubSubclass
+ var SubSubclass = Subclass.sub();
+
+ //Make Sure the SubSubclass inherited properly
+ ok(SubSubclass["topLevelMethod"]() === false, "SubSubclass.topLevelMethod thought debug was true");
+ ok(SubSubclass["config"]["locale"] == "en_US", SubSubclass["config"]["locale"] + " is wrong!");
+ deepEqual(SubSubclass["config"]["test"], undefined, "SubSubclass.config.test is set incorrectly");
+ equal(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");
+
+ //Modify The Subclass and test the Modifications
+ SubSubclass.fn.extend({"subSubClassMethod": function() { return this;}});
+ SubSubclass["setup"]({"locale": "es_MX", "test": "worked"});
+ SubSubclass["debug"] = true;
+ SubSubclass.ajax = function() {return false;};
+ ok(SubSubclass["topLevelMethod"](), "SubSubclass.topLevelMethod thought debug was false");
+ deepEqual(SubSubclass(document)["subClassMethod"], Subclass.fn["subClassMethod"], "Methods Differ!");
+ ok(SubSubclass["config"]["locale"] == "es_MX", SubSubclass["config"]["locale"] + " is wrong!");
+ ok(SubSubclass["config"]["test"] == "worked", "SubSubclass.config.test is set incorrectly");
+ notEqual(jQuery.ajax, SubSubclass.ajax, "The subsubclass failed to get all top level methods");
+
+ //This shows that the modifications to the SubSubClass did not bubble back up to it's superclass
+ ok(Subclass["topLevelMethod"]() === false, "Subclass.topLevelMethod thought debug was true");
+ ok(Subclass["config"]["locale"] == "en_US", Subclass["config"]["locale"] + " is wrong!");
+ deepEqual(Subclass["config"]["test"], undefined, "Subclass.config.test is set incorrectly");
+ deepEqual(Subclass(document)["subSubClassMethod"], undefined, "subSubClassMethod set incorrectly");
+ equal(jQuery.ajax, Subclass.ajax, "The subclass failed to get all top level methods");
+ });
+
+ test("jQuery.sub() - .fn Methods", function(){
+ expect(378);
+
+ var Subclass = jQuery.sub(),
+ SubclassSubclass = Subclass.sub(),
+ jQueryDocument = jQuery(document),
+ selectors, contexts, methods, method, arg, description;
+
+ jQueryDocument.toString = function(){ return "jQueryDocument"; };
+
+ Subclass.fn.subclassMethod = function(){};
+ SubclassSubclass.fn.subclassSubclassMethod = function(){};
+
+ selectors = [
+ "body",
+ "html, body",
+ "<div></div>"
+ ];
+
+ contexts = [undefined, document, jQueryDocument];
+
+ jQuery.expandedEach = jQuery.each;
+ jQuery.each(selectors, function(i, selector){
+
+ jQuery.expandedEach({ // all methods that return a new jQuery instance
+ "eq": 1 ,
+ "add": document,
+ "end": undefined,
+ "has": undefined,
+ "closest": "div",
+ "filter": document,
+ "find": "div"
+ }, function(method, arg){
+ jQuery.each(contexts, function(i, context){
+
+ description = "(\""+selector+"\", "+context+")."+method+"("+(arg||"")+")";
+
+ deepEqual(
+ (function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassMethod; })(arg),
+ undefined, "jQuery"+description+" doesn't have Subclass methods"
+ );
+ deepEqual(
+ (function(var_args){ return jQuery.fn[method].apply(jQuery(selector, context), arguments).subclassSubclassMethod; })(arg),
+ undefined, "jQuery"+description+" doesn't have SubclassSubclass methods"
+ );
+ deepEqual(
+ Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+ "Subclass"+description+" has Subclass methods"
+ );
+ deepEqual(
+ Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
+ "Subclass"+description+" doesn't have SubclassSubclass methods"
+ );
+ deepEqual(
+ SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+ "SubclassSubclass"+description+" has Subclass methods"
+ );
+ deepEqual(
+ SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
+ "SubclassSubclass"+description+" has SubclassSubclass methods"
+ );
+
+ });
+ });
+ });
+
+ });
+
+} // jQuery.sub
+
+test("jQuery.camelCase()", function() {
+
+ var tests = {
+ "foo-bar": "fooBar",
+ "foo-bar-baz": "fooBarBaz",
+ "girl-u-want": "girlUWant",
+ "the-4th-dimension": "the4thDimension",
+ "-o-tannenbaum": "OTannenbaum",
+ "-moz-illa": "MozIlla",
+ "-ms-take": "msTake"
+ };
+
+ expect(7);
+
+ jQuery.each( tests, function( key, val ) {
+ equal( jQuery.camelCase( key ), val, "Converts: " + key + " => " + val );
+ });
+});
+
+*/
View
25 Test/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Marrow Tests</title>
+ <link href="mocha.css" rel="stylesheet" type="text/css" media="screen" />
+ <style>
+ li {
+ list-style-type: none;
+ border-left: 8px solid #b0c4de;
+ border-bottom: 1px solid #b0c4de;
+ padding-left: 1em;
+ margin-bottom: 0.1em;
+ border-radius: 4px;
+ }
+ </style>
+</head>
+<body>
+
+<ul>
+ <li><a href="/core.html">core</a></li>
+</ul>
+
+</body>
+</html>
View
42 Test/live/test.html
@@ -0,0 +1,42 @@
+<html>
+<!-- this code was originally in http://jsfiddle.net/tBS4X/1/ from http://leanpub.com/backbonetutorials -->
+<head>
+ <script src="../../Build/Marrow.js"></script>
+ <script src="http://underscorejs.org/underscore-min.js"></script> <!-- this will eventually be removed in favor of underprime -->
+ <script src="http://backbonejs.org/backbone-min.js"></script>
+</head>
+<body>
+<div id="search_container">a</div>
+<script type="text/template" id="search_template">
+ <label>Search</label>
+ <input type="text" id="search_input" />
+ <input type="button" id="search_button" value="Search" />
+</script>
+<script id="app.js">
+ var $ = jQuery; //Marrow doesn't export $ for now.
+
+ var SearchView = Backbone.View.extend({
+ initialize: function(){
+ this.render();
+ },
+ render: function(){
+ // Compile the template using underscore
+ var template = _.template( $("#search_template").html(), {} );
+ // Load the compiled HTML into the Backbone "el"
+ this.$el.html( template );
+ },
+ events: {
+ "click input[type=button]": "doSearch"
+ },
+ doSearch: function( event ){
+ // Button clicked, you can access the element that was clicked with event.currentTarget
+ alert( "Search for " + $("#search_input").val() );
+ }
+ });
+
+ onload = function(){
+ var search_view = new SearchView({ el: $("#search_container") });
+ }
+</script>
+</body>
+</html>
View
62 Test/server.js
@@ -0,0 +1,62 @@
+"use strict";
+
+var fs = require('fs')
+var qs = require('querystring')
+var url = require('url')
+var wrapup = require('wrapup')
+
+var app = require('http').createServer(function(req, res){
+
+ var parsed = url.parse(req.url)
+ var pathname = parsed.pathname
+ console.log(pathname);
+ if (pathname == '/test.js' && parsed.search){
+
+ var query = qs.parse(parsed.search.slice(1))
+ var wrup = wrapup()
+
+ for (var q in query){
+ if (query[q]) wrup.require(q, __dirname + '/../' + query[q])
+ else wrup.require(__dirname + '/../' + q)
+ }
+
+ res.writeHead(200, {'Content-Type': 'text/javascript'})
+ wrup.up(function(err, js){
+ res.end(js)
+ })
+
+ } else {
+
+ var paths = {
+ '/Build/Marrow.js': __dirname + '/../Build/Marrow.js',
+ '/mocha.js': __dirname + '/../node_modules/mocha/mocha.js',
+ '/mocha.css': __dirname + '/../node_modules/mocha/mocha.css',
+ '/': __dirname + '/index.html'
+ };
+
+ var file = paths[pathname] || __dirname + pathname
+
+ fs.readFile(file, function(err, data){
+ if (err){
+ console.log('NOT FOUND: '+ file)
+ res.writeHead(404)
+ res.end()
+ } else {
+
+ var contentType = {
+ 'css': 'text/css',
+ 'js': 'text/javascript'
+ }[pathname.split('.').pop()] || 'text/html'
+
+ res.writeHead(200, {'Content-Type': contentType})
+ res.end(String(data))
+
+ }
+ })
+
+ }
+
+})
+
+app.listen('666')
+console.log('running the tests on http://localhost:666')
View
25 package.json
@@ -0,0 +1,25 @@
+{
+ "name": "Marrow",
+ "version": "0.0.0",
+ "description": "The marrow your backbone needs",
+ "author": "Cristian Carlesso <@kentaromiura> (http://mykenta.blogspot.com)",
+ "main": "Source/index",
+ "repository": {
+ "url": ""
+ },
+ "dependencies": {
+ "prime": "*",
+ "elements": "*",
+ "moofx": "*",
+ "agent": "*"
+ },
+ "devDependencies": {
+ "mocha" : "*",
+ "expect.js":"*" ,
+ "wrapup": "0.11.2"
+ },
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.