put-selector
Advanced tools
Comparing version 0.1.3 to 0.2.0
@@ -14,2 +14,7 @@ "use strict"; | ||
prototype.nodeType = 1; | ||
prototype.put = function(){ | ||
var args = [this]; | ||
args.push.apply(args, arguments); | ||
return put.apply(null, args); | ||
} | ||
prototype.toString = function(noClose){ | ||
@@ -39,2 +44,5 @@ var tag = this.tag; | ||
prototype.sendTo = function(stream){ | ||
if(typeof stream == 'function'){ // write function itself | ||
stream = {write: stream, end: stream}; | ||
} | ||
var active = this; | ||
@@ -166,6 +174,4 @@ var streamIndentation = ''; | ||
module.exports = function(putModule, putFactory){ | ||
put = putModule.exports = putFactory(); | ||
put.indentation = ' '; | ||
put = putModule.exports = putFactory().forDocument({ | ||
// setup a document for string-based HTML creation, using our classes | ||
put.setDocument({ | ||
createElement: function(tag){ | ||
@@ -181,3 +187,7 @@ return new Element(tag); | ||
} | ||
}); | ||
}); | ||
put.indentation = ' '; | ||
put.Page = function(stream){ | ||
return put('html').sendTo(stream); | ||
}; | ||
}; |
{ | ||
"name": "put-selector", | ||
"author": "Kris Zyp", | ||
"version": "0.1.3", | ||
"version": "0.2.0", | ||
"description": "A high-performance, lightweight function for creating and manipulating DOM elements with succinct, elegant, familiar CSS selector-based syntax", | ||
@@ -26,3 +26,4 @@ "licenses": [ | ||
"main": "./put", | ||
"icon": "http://packages.dojofoundation.org/images/xstyle.jpg" | ||
"icon": "http://packages.dojofoundation.org/images/xstyle.jpg", | ||
"dojoBuild": "package.js" | ||
} |
46
put.js
(function(define){ | ||
define([], function(){ | ||
var forDocument, fragmentFasterHeuristic = /[-+,> ]/; // if it has any of these combinators, it is probably going to be faster with a document fragment | ||
define([], forDocument = function(doc, newFragmentFasterHeuristic){ | ||
"use strict"; | ||
@@ -13,9 +14,8 @@ // module: | ||
// | put("div.foo"); | ||
var selectorParse = /(([-+])|[,<> ])?\s*(\.|!|#)?([-\w$]+)?(?:\[([^\]=]+)=?['"]?([^\]'"]*)['"]?\])?/g, | ||
fragmentFasterHeuristic = /[-+,> ]/, // if it has any of these combinators, it is probably going to be faster with a document fragment | ||
doc, undefined; | ||
fragmentFasterHeuristic = newFragmentFasterHeuristic || fragmentFasterHeuristic; | ||
try{ | ||
doc = document; | ||
var ieCreateElement = 1; | ||
var selectorParse = /(?:\s*([-+ ,<>]))?\s*(\.|!\.?|#)?([-\w%$]+)?(?:\[([^\]=]+)=?['"]?([^\]'"]*)['"]?\])?/g, | ||
undefined, | ||
doc = doc || document, | ||
ieCreateElement = 1; | ||
put('i', {name:'a'}); | ||
@@ -46,3 +46,3 @@ }catch(e){ | ||
|| referenceElement). | ||
insertBefore(current, nextSibling); // do the actual insertion | ||
insertBefore(current, nextSibling || null); // do the actual insertion | ||
} | ||
@@ -53,2 +53,11 @@ } | ||
if(typeof argument == "object"){ | ||
lastSelectorArg = false; | ||
if(argument instanceof Array){ | ||
// an array | ||
returnValue = doc.createDocumentFragment(); | ||
for(var key = 0; key < argument.length; key++){ | ||
returnValue.appendChild(put(argument[key])); | ||
} | ||
argument = returnValue; | ||
} | ||
if(argument.nodeType){ | ||
@@ -58,3 +67,3 @@ current = argument; | ||
referenceElement = argument; | ||
nextSibling = null; | ||
nextSibling = 0; | ||
}else{ | ||
@@ -66,6 +75,7 @@ // an object hash | ||
} | ||
}else if(lastSelectorArg === i - 1){ | ||
}else if(lastSelectorArg){ | ||
// a text node should be created | ||
// take a scalar value, use createTextNode so it is properly escaped | ||
// createTextNode is generally several times faster than doing an escaped innerHTML insertion: http://jsperf.com/createtextnode-vs-innerhtml/2 | ||
lastSelectorArg = false; | ||
insertTextNode(current, argument); | ||
@@ -77,8 +87,8 @@ }else{ | ||
} | ||
lastSelectorArg = i; | ||
var leftoverCharacters = argument.replace(selectorParse, function(t, combinator, siblingCombinator, prefix, value, attrName, attrValue){ | ||
lastSelectorArg = true; | ||
var leftoverCharacters = argument.replace(selectorParse, function(t, combinator, prefix, value, attrName, attrValue){ | ||
if(combinator){ | ||
// insert the last current object | ||
insertLastElement(); | ||
if(siblingCombinator){ | ||
if(combinator == '-' || combinator == '+'){ | ||
// + or - combinator, | ||
@@ -88,3 +98,3 @@ // TODO: add support for >- as a means of indicating before the first child? | ||
current = null; | ||
if(siblingCombinator == "+"){ | ||
if(combinator == "+"){ | ||
nextSibling = nextSibling.nextSibling; | ||
@@ -106,3 +116,3 @@ }// else a - operator, again not in CSS, but obvious in it's meaning (create next element before the current/referenceElement) | ||
} | ||
nextSibling = null; | ||
nextSibling = 0; | ||
} | ||
@@ -191,6 +201,3 @@ if(current){ | ||
put.defaultTag = "div"; | ||
put.setDocument = function(document, newFragmentHeuristic){ | ||
doc = document; | ||
fragmentFasterHeuristic = newFragmentHeuristic || fragmentFasterHeuristic; | ||
} | ||
put.forDocument = forDocument; | ||
return put; | ||
@@ -202,3 +209,2 @@ }); | ||
require("./node-html")(module, factory); | ||
// module.exports = factory(); | ||
}else{ | ||
@@ -205,0 +211,0 @@ // plain script in a browser |
@@ -133,2 +133,4 @@ This put-selector/put module/package provides a high-performance, lightweight | ||
This new span element will be inserted before the reference element in the DOM order. | ||
Note that "-" is valid character in tags and classes, so it will only be interpreted as a | ||
combinator if it is the first character or if it is preceded by a space. | ||
@@ -180,3 +182,3 @@ The sibling operator can reference the last created element as well. For example | ||
put(parent, "div.second-", first); | ||
put(parent, "div.second -", first); | ||
@@ -252,5 +254,12 @@ The put() function takes an unlimited number of arguments, so we could combine as | ||
The end(leaveOpen) method will end the current streaming, closing all the necessary | ||
tags and closing the stream (unless the argument is true). Here is an example of | ||
how we could create a full page in NodeJS that is streamed to the response: | ||
tags and closing the stream (unless the argument is true). | ||
The returned elements also include a put() method so you can directly add to or apply | ||
CSS selector-based additions to elements, for example: | ||
element.put('div.test'); // create a <div class="test"></div> as a child of element | ||
Here is an example of how we could create a full page in NodeJS that is streamed to | ||
the response: | ||
var http = require('http'); | ||
@@ -261,4 +270,4 @@ var put = require('put-selector'); | ||
var page = put('html').sendTo(res); // create an HTML page, and pipe to the response | ||
put(page, 'head script[src=app.js]'); // each element is sent immediately | ||
put(page, 'body div.content', 'Hello, World'); | ||
page.put('head script[src=app.js]'); // each element is sent immediately | ||
page.put('body div.content', 'Hello, World'); | ||
page.end(); // close all the tags, and end the stream | ||
@@ -285,1 +294,13 @@ }).listen(80); | ||
newInput = put("input[type=checkbox]", {name: "works"}); | ||
Using on Different document | ||
------------------------- | ||
If you are using multiple frames in your web page, you may encounter a situation where | ||
you want to use put-selector to make DOM changes on a different HTML document. | ||
You can create a separate instance of the put() function for a separate document by | ||
calling the put.forDocument(document) function. For example: | ||
put2 = put.forDocument(frames[1].document); | ||
put2("div") <- creates a div element that belongs to the document in the second frame. | ||
put("div") <- the original put still functions on the main document for this window/context |
@@ -31,4 +31,4 @@ var assert = require("assert"), | ||
+div.content', 'Hello World'); | ||
put(content, 'div.left', 'Left'); | ||
put(content, 'div.right', {innerHTML: 'Right <b>text</b>'}); | ||
content.put('div.left', 'Left'); | ||
content.put('div.right', {innerHTML: 'Right <b>text</b>'}); | ||
page.end(); | ||
@@ -35,0 +35,0 @@ assert.equal(output, '<!DOCTYPE html>\n<html><head><script src=\"test.js\"></script><link href=\"test.css\"><link href=\"test2.css\"></head><body><div class=\"header\">Hello World</div><div class=\"content\"><div class=\"left\">Left</div><div class=\"right\">Right <b>text</b></div></div></body>\n</html>'); |
@@ -7,5 +7,5 @@ var div = put("div"); | ||
var parent = div; | ||
var parentDiv = div; | ||
var span1 = put(parent, "span.class-name-1.class-name-2[name=span1]"); | ||
var span1 = put(parentDiv, "span.class-name-1.class-name-2[name=span1]"); | ||
console.assert(span1.className == "class-name-1 class-name-2"); | ||
@@ -16,6 +16,8 @@ console.assert(span1.getAttribute("name") == "span1"); | ||
console.assert(span1.className == "class-name-2 class-name-3"); | ||
put(span1, "!.class-name-3"); | ||
console.assert(span1.className == "class-name-2"); | ||
console.assert(span1.getAttribute("name") == null); | ||
put(span1, "[name=span1]"); // readd the attribute | ||
var defaultTag = put(parent, " .class"); | ||
var defaultTag = put(parentDiv, " .class"); | ||
console.assert(defaultTag.tagName.toLowerCase() == "div"); | ||
@@ -35,5 +37,5 @@ var span2, span3 = put(span1, "+span[name=span2] + span[name=span3]"); | ||
var parent = put("div.parent span.first $ + span.second $<", "inside first", "inside second"); | ||
console.assert(parent.firstChild.innerHTML, "inside first"); | ||
console.assert(parent.lastChild.innerHTML, "inside second"); | ||
var parentDiv = put("div.parent span.first $ + span.second $<", "inside first", "inside second"); | ||
console.assert(parentDiv.firstChild.innerHTML, "inside first"); | ||
console.assert(parentDiv.lastChild.innerHTML, "inside second"); | ||
@@ -46,6 +48,10 @@ put(span3, "!"); // destroy span3 | ||
var spanWithId = put(parent, "span#with-id"); | ||
var spanMinusTwo = put(span0, "-span -span"); | ||
console.assert(spanMinusTwo.nextSibling.nextSibling == span0); | ||
var spanWithId = put(parentDiv, "span#with-id"); | ||
console.assert(spanWithId.id == "with-id"); | ||
var table = put(parent, "table.class-name#id tr.class-name td[colSpan=2]<<tr.class-name td+td<<"); | ||
var table = put(parentDiv, "table.class-name#id tr.class-name td[colSpan=2]<<tr.class-name td+td<<"); | ||
console.assert(table.tagName.toLowerCase() == "table"); | ||
@@ -66,2 +72,11 @@ console.assert(table.childNodes.length == 2); | ||
var div = put("div"); | ||
var arrayFrag = put(div, ["span.c1", "span.c2", "span.c3"]); | ||
console.assert(arrayFrag.nodeType == 11); | ||
console.assert(div.firstChild.className == "c1"); | ||
console.assert(div.lastChild.className == "c3"); | ||
put(div, "#encode%3A%20d"); | ||
console.assert(div.id == "encode%3A%20d"); | ||
put(body, "div", {innerHTML: "finished tests, check console for errors"}); |
32799
9
513
301