Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 253dfef5ec1459d001b6ec5f88a4f1b13b61be8f @tj tj committed Aug 28, 2012
Showing with 5,492 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +3 −0 .gitmodules
  3. +4 −0 .npmignore
  4. 0 History.md
  5. +11 −0 Makefile
  6. +33 −0 Readme.md
  7. +12 −0 component.json
  8. +327 −0 index.js
  9. +188 −0 test/dom.js
  10. +22 −0 test/index.html
  11. +199 −0 test/mocha/mocha.css
  12. +4,674 −0 test/mocha/mocha.js
  13. +16 −0 test/mocha/tests.html
3 .gitignore
@@ -0,0 +1,3 @@
+node_modules
+build
+components
3 .gitmodules
@@ -0,0 +1,3 @@
+[submodule "test/mocha"]
+ path = test/mocha
+ url = git://github.com/visionmedia/mocha.git
4 .npmignore
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
0 History.md
No changes.
11 Makefile
@@ -0,0 +1,11 @@
+
+build: index.js components
+ @component build
+
+components:
+ @component install
+
+clean:
+ rm -fr build components
+
+.PHONY: clean
33 Readme.md
@@ -0,0 +1,33 @@
+
+# dom
+
+ jQuery inspired DOM traversal / manipulation component. Aggregates the
+ following components to create a more familiar experience when you need
+ the combined functionality of:
+
+ - [domify](http://github.com/component/domify) to convert HTML to DOM nodes
+ - [classes](http://github.com/component/classes) to add, remove, and toggle classes
+
+## Installation
+
+```
+$ component install component/dom
+```
+
+## Example
+
+```js
+var dom = require('dom');
+
+dom('li').select(function(el){
+ return el.text() == 'Maru';
+}).addClass('amazing');
+```
+
+## API
+
+ ... not even remotely done ...
+
+## License
+
+ MIT
12 component.json
@@ -0,0 +1,12 @@
+{
+ "name": "dom",
+ "version": "0.0.1",
+ "description": "DOM traversal, manipulation and events aggregate library",
+ "keywords": ["html", "dom", "ui", "jquery"],
+ "scripts": ["index.js"],
+ "dependencies": {
+ "component/indexof": "*",
+ "component/domify": "*",
+ "component/classes": "*"
+ }
+}
327 index.js
@@ -0,0 +1,327 @@
+
+/**
+ * Module dependencies.
+ */
+
+var domify = require('domify')
+ , classes = require('classes')
+ , indexof = require('indexof');
+
+/**
+ * Expose `dom()`.
+ */
+
+exports = module.exports = dom;
+
+/**
+ * Return a dom `List` for the given `html` or selector.
+ *
+ * @param {String} html or selector
+ * @return {List}
+ * @api public
+ */
+
+function dom(selector, context) {
+ var ctx = context
+ ? (context.els ? context.els[0] : context)
+ : document.firstChild;
+
+ // html
+ if ('<' == selector.charAt(0)) {
+ return new List([domify(selector)]);
+ }
+
+ // selector
+ if ('string' == typeof selector) {
+ return new List([ctx.querySelector(selector)]);
+ }
+}
+
+/**
+ * Expose `List` constructor.
+ */
+
+exports.List = List;
+
+/**
+ * Initialize a new `List` with the given array-ish of `els`.
+ *
+ * @param {Mixed} els
+ * @api private
+ */
+
+function List(els) {
+ this.els = els || [];
+}
+
+/**
+ * Return a `List` containing the element at `i`.
+ *
+ * @param {Number} i
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.at = function(i){
+ return new List([this.els[i]]);
+};
+
+/**
+ * Return a `List` containing the first element.
+ *
+ * @param {Number} i
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.first = function(){
+ return new List([this.els[0]]);
+};
+
+/**
+ * Return a `List` containing the last element.
+ *
+ * @param {Number} i
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.last = function(){
+ return new List([this.els[this.els.length - 1]]);
+};
+
+/**
+ * Return an `Element` at `i`.
+ *
+ * @param {Number} i
+ * @return {Element}
+ * @api public
+ */
+
+List.prototype.get = function(i){
+ return this.els[i];
+};
+
+/**
+ * Return list length.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+List.prototype.length = function(){
+ return this.els.length;
+};
+
+/**
+ * Return element text.
+ *
+ * @return {String}
+ * @api public
+ */
+
+List.prototype.text = function(){
+ // TODO: real impl
+ var str = '';
+ for (var i = 0; i < this.els.length; ++i) {
+ str += this.els[i].textContent;
+ }
+ return str;
+};
+
+/**
+ * Iterate elements and invoke `fn(list, i)`.
+ *
+ * @param {Function} fn
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.each = function(fn){
+ for (var i = 0; i < this.els.length; ++i) {
+ fn(new List([this.els[i]]), i);
+ }
+ return this;
+};
+
+/**
+ * Iterate elements and invoke `fn(el, i)`.
+ *
+ * @param {Function} fn
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.forEach = function(fn){
+ for (var i = 0; i < this.els.length; ++i) {
+ fn(this.els[i], i);
+ }
+ return this;
+};
+
+/**
+ * Map elements invoking `fn(list, i)`.
+ *
+ * @param {Function} fn
+ * @return {Array}
+ * @api public
+ */
+
+List.prototype.map = function(fn){
+ var arr = [];
+ for (var i = 0; i < this.els.length; ++i) {
+ arr.push(fn(new List([this.els[i]]), i));
+ }
+ return arr;
+};
+
+/**
+ * Filter elements invoking `fn(list, i)`, returning
+ * a new `List` of elements when a truthy value is returned.
+ *
+ * @param {Function} fn
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.select =
+List.prototype.filter = function(fn){
+ var el;
+ var list = new List;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ if (fn(new List([el]), i)) list.els.push(el);
+ }
+ return list;
+};
+
+/**
+ * Add the given class `name`.
+ *
+ * @param {String} name
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.addClass = function(name){
+ var el;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ el._classes = el._classes || classes(el);
+ el._classes.add(name);
+ }
+ return this;
+};
+
+/**
+ * Remove the given class `name`.
+ *
+ * @param {String} name
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.removeClass = function(name){
+ var el;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ el._classes = el._classes || classes(el);
+ el._classes.remove(name);
+ }
+ return this;
+};
+
+/**
+ * Toggle the given class `name`.
+ *
+ * @param {String} name
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.toggleClass = function(name){
+ var el;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ el._classes = el._classes || classes(el);
+ el._classes.toggle(name);
+ }
+ return this;
+};
+
+/**
+ * Check if the given class `name` is present.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+List.prototype.hasClass = function(name){
+ var el;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ el._classes = el._classes || classes(el);
+ if (el._classes.has(name)) return true;
+ }
+ return false;
+};
+
+/**
+ * Set CSS `prop` to `val` or get `prop` value.
+ *
+ * @param {String} prop
+ * @param {Mixed} val
+ * @return {List|String}
+ * @api public
+ */
+
+List.prototype.css = function(prop, val){
+ if (2 == arguments.length) return this.setStyle(prop, val);
+ return this.getStyle(prop);
+};
+
+/**
+ * Set CSS `prop` to `val`.
+ *
+ * @param {String} prop
+ * @param {Mixed} val
+ * @return {List}
+ * @api private
+ */
+
+List.prototype.setStyle = function(prop, val){
+ for (var i = 0; i < this.els.length; ++i) {
+ this.els[i].style[prop] = val;
+ }
+ return this;
+};
+
+/**
+ * Get CSS `prop` value.
+ *
+ * @param {String} prop
+ * @return {String}
+ * @api private
+ */
+
+List.prototype.getStyle = function(prop){
+ var el = this.els[0];
+ if (el) return el.style[prop];
+};
+
+List.prototype.find = function(selector){
+ // TODO: real implementation
+ var list = new List;
+ var el, els;
+ for (var i = 0; i < this.els.length; ++i) {
+ el = this.els[i];
+ els = el.querySelectorAll(selector);
+ for (var j = 0; j < els.length; ++j) {
+ list.els.push(els[j]);
+ }
+ }
+ return list;
+};
+
+
188 test/dom.js
@@ -0,0 +1,188 @@
+
+var dom = require('dom');
+
+describe('dom(id)', function(){
+ it('should return an element by id', function(){
+ var list = dom('<ul><li id="one">foo</li><li id="two">bar</li></ul>');
+ list = dom('#two', list);
+ assert(1 == list.length(), 'expected length of 1');
+ assert('bar' == list.get(0).textContent);
+ })
+})
+
+describe('dom(html)', function(){
+ it('should return a dom List of elements', function(){
+ var list = dom('<em>Hello</em>');
+ assert('Hello' == list.get(0).textContent);
+ })
+})
+
+describe('.length()', function(){
+ it('should return the number of elements', function(){
+ var list = dom('<em>Hello</em>');
+ assert(1 == list.length());
+ })
+})
+
+describe('.get(i)', function(){
+ it('should return the element at i', function(){
+ var list = dom('<em>Hello</em>');
+ assert('Hello' == list.get(0).textContent);
+ })
+})
+
+describe('.at(i)', function(){
+ it('should return the element at i as a List', function(){
+ var list = dom('<em>Hello</em>');
+ assert('Hello' == list.at(0).get(0).textContent);
+ })
+})
+
+describe('.first()', function(){
+ it('should return the first element in the List', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+ assert('foo' == list.first().text());
+ })
+})
+
+describe('.last()', function(){
+ it('should return the last element in the List', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+ assert('bar' == list.last().text());
+ })
+})
+
+describe('.addClass(name)', function(){
+ it('should add the given class name', function(){
+ var list = dom('<em>Hello</em>');
+ list.addClass('foo').addClass('bar');
+ assert('foo bar' == list.get(0).className);
+ })
+})
+
+describe('.removeClass(name)', function(){
+ it('should remove the given class name', function(){
+ var list = dom('<em>Hello</em>');
+ list.addClass('foo').addClass('bar').removeClass('foo');
+ assert('bar' == list.get(0).className);
+ })
+})
+
+describe('.toggleClass(name)', function(){
+ it('should toggle the given class name', function(){
+ var list = dom('<em>Hello</em>');
+
+ list.toggleClass('show');
+ assert('show' == list.get(0).className);
+
+ list.toggleClass('show');
+ assert('' == list.get(0).className);
+ })
+})
+
+describe('.hasClass(name)', function(){
+ it('should return true when the classname is present', function(){
+ var list = dom('<em>Hello</em>').addClass('show');
+ assert(true === list.hasClass('show'));
+ })
+
+ it('should return false when the classname is not present', function(){
+ var list = dom('<em>Hello</em>').addClass('show');
+ assert(false === list.hasClass('hide'));
+ })
+})
+
+describe('.find(selector)', function(){
+ it('should return descendants matching the selector', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>');
+ list = list.find('li');
+ assert(2 == list.length());
+ })
+})
+
+describe('.each(fn)', function(){
+ it('should iterate passing (list, i)', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+
+ var indexes = [];
+ var values = [];
+ var ret = list.each(function(el, i){
+ indexes.push(i);
+ values.push(el);
+ });
+
+ assert(ret == list, 'should return self for chaining');
+ assert(0 == indexes[0]);
+ assert(1 == indexes[1]);
+ assert(values[0] instanceof dom.List, 'values should be dom lists');
+ assert(list.get(0) == values[0].get(0));
+ assert(list.get(1) == values[1].get(0));
+ })
+})
+
+describe('.forEach(fn)', function(){
+ it('should iterate passing (el, i)', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+
+ var indexes = [];
+ var values = [];
+ var ret = list.forEach(function(el, i){
+ indexes.push(i);
+ values.push(el);
+ });
+
+ assert(ret == list, 'should return self for chaining');
+ assert(0 == indexes[0]);
+ assert(1 == indexes[1]);
+ assert(!(values[0] instanceof dom.List), 'values should be elements');
+ assert(list.get(0) == values[0]);
+ assert(list.get(1) == values[1]);
+ })
+})
+
+describe('.map(fn)', function(){
+ it('should map passing (list, i)', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+
+ var ret = list.map(function(el, i){
+ return el.text();
+ }).join('|');
+
+ assert('foo|bar' == ret);
+ })
+})
+
+describe('.select(fn)', function(){
+ it('should filter passing (list, i)', function(){
+ var list = dom('<ul><li>foo</li><li>bar</li></ul>').find('li');
+
+ var selected = list.select(function(el){
+ return el.text() == 'bar';
+ });
+
+ assert(1 == selected.length(), 'invalid length');
+ assert(selected.get(0) == list.get(1));
+ })
+})
+
+describe('.filter(fn)', function(){
+ it('should alias .select', function(){
+ assert(dom.List.prototype.filter == dom.List.prototype.select);
+ })
+})
+
+describe('.css(prop, value)', function(){
+ it('should set a style value', function(){
+ var list = dom('<em>Hello</em>');
+ list.css('display', 'none');
+ assert('none' == list.get(0).style.display);
+ })
+})
+
+describe('.css(prop)', function(){
+ it('should get a style value', function(){
+ var list = dom('<em>Hello</em>');
+ list.css('display', 'none');
+ assert('none' == list.css('display'));
+ })
+})
22 test/index.html
@@ -0,0 +1,22 @@
+<html>
+ <head>
+ <title>dom tests</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="mocha/mocha.css" />
+ <script src="mocha/mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+ </head>
+ <body>
+ <div id="mocha"></div>
+ <script src="../build/build.js"></script>
+ <script src="dom.js"></script>
+ <script>
+ mocha.run();
+ </script>
+ </body>
+</html>
199 test/mocha/mocha.css
@@ -0,0 +1,199 @@
+@charset "UTF-8";
+body {
+ font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ padding: 60px 50px;
+}
+
+#mocha ul, #mocha li {
+ margin: 0;
+ padding: 0;
+}
+
+#mocha ul {
+ list-style: none;
+}
+
+#mocha h1, #mocha h2 {
+ margin: 0;
+}
+
+#mocha h1 {
+ margin-top: 15px;
+ font-size: 1em;
+ font-weight: 200;
+}
+
+#mocha h1 a {
+ text-decoration: none;
+ color: inherit;
+}
+
+#mocha h1 a:hover {
+ text-decoration: underline;
+}
+
+#mocha .suite .suite h1 {
+ margin-top: 0;
+ font-size: .8em;
+}
+
+#mocha h2 {
+ font-size: 12px;
+ font-weight: normal;
+ cursor: pointer;
+}
+
+#mocha .suite {
+ margin-left: 15px;
+}
+
+#mocha .test {
+ margin-left: 15px;
+}
+
+#mocha .test:hover h2::after {
+ position: relative;
+ top: 0;
+ right: -10px;
+ content: '(view source)';
+ font-size: 12px;
+ font-family: arial;
+ color: #888;
+}
+
+#mocha .test.pending:hover h2::after {
+ content: '(pending)';
+ font-family: arial;
+}
+
+#mocha .test.pass.medium .duration {
+ background: #C09853;
+}
+
+#mocha .test.pass.slow .duration {
+ background: #B94A48;
+}
+
+#mocha .test.pass::before {
+ content: '';
+ font-size: 12px;
+ display: block;
+ float: left;
+ margin-right: 5px;
+ color: #00d6b2;
+}
+
+#mocha .test.pass .duration {
+ font-size: 9px;
+ margin-left: 5px;
+ padding: 2px 5px;
+ color: white;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#mocha .test.pass.fast .duration {
+ display: none;
+}
+
+#mocha .test.pending {
+ color: #0b97c4;
+}
+
+#mocha .test.pending::before {
+ content: '';
+ color: #0b97c4;
+}
+
+#mocha .test.fail {
+ color: #c00;
+}
+
+#mocha .test.fail pre {
+ color: black;
+}
+
+#mocha .test.fail::before {
+ content: '';
+ font-size: 12px;
+ display: block;
+ float: left;
+ margin-right: 5px;
+ color: #c00;
+}
+
+#mocha .test pre.error {
+ color: #c00;
+}
+
+#mocha .test pre {
+ display: inline-block;
+ font: 12px/1.5 monaco, monospace;
+ margin: 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ border-bottom-color: #ddd;
+ -webkit-border-radius: 3px;
+ -webkit-box-shadow: 0 1px 3px #eee;
+}
+
+#report.pass .test.fail {
+ display: none;
+}
+
+#report.fail .test.pass {
+ display: none;
+}
+
+#error {
+ color: #c00;
+ font-size: 1.5 em;
+ font-weight: 100;
+ letter-spacing: 1px;
+}
+
+#stats {
+ position: fixed;
+ top: 15px;
+ right: 10px;
+ font-size: 12px;
+ margin: 0;
+ color: #888;
+}
+
+#stats .progress {
+ float: right;
+ padding-top: 0;
+}
+
+#stats em {
+ color: black;
+}
+
+#stats a {
+ text-decoration: none;
+ color: inherit;
+}
+
+#stats a:hover {
+ border-bottom: 1px solid #eee;
+}
+
+#stats li {
+ display: inline-block;
+ margin: 0 5px;
+ list-style: none;
+ padding-top: 11px;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
4,674 test/mocha/mocha.js
4,674 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
16 test/mocha/tests.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <title>Mocha</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="mocha.css" />
+ </head>
+ <body>
+ <div id="mocha"></div>
+ <script src="mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script src="my-tests.js"></script>
+ <script>
+ mocha.run();
+ </script>
+ </body>
+</html>

1 comment on commit 253dfef

@sebs

And I wanted to ask where mocha testing is in component. Here you go ;)

Please sign in to comment.