Permalink
Browse files

Inital commit

  • Loading branch information...
0 parents commit 106ed10337bbf5bc68512a0f34848914663ba305 @silentrob committed Jul 24, 2010
Showing with 1,468 additions and 0 deletions.
  1. +1 −0 README.md
  2. +315 −0 lib/apricot.js
  3. +1,066 −0 lib/sizzle.js
  4. +21 −0 test.html
  5. +65 −0 test.js
@@ -0,0 +1 @@
+.h1 Apricot
@@ -0,0 +1,315 @@
+
+exports.Apricot = Apricot;
+
+function Apricot(content) {
+
+ var dom = require('jsdom-0.0.1/level1/core').dom.level1.core;
+ var browser = require('jsdom-0.0.1/browser/index').windowAugmentation(dom);
+
+ // This is the item we are itterating on (DOM Elements)
+ this.matches = [];
+
+ // TODO, content should be applied to the whole document, not the body.
+ browser.document.body.innerHTML = content;
+ this.document = browser.document
+ this.matches = [];
+
+ this.__defineGetter__("toHTML", function(){
+ return this.document.body.innerHTML;
+ });
+
+ this.__defineGetter__("innerHTML", function(){
+ return this.document.body.firstChild.innerHTML;
+ });
+
+ this.__defineGetter__("toDOM", function(){
+ return this.document.body;
+ });
+}
+
+
+Apricot.prototype = {
+ find : function(pattern) {
+ var m = [];
+ var sizzleSandbox = {};
+ var sizzle = require("./sizzle").sizzleInit(sizzleSandbox,this.document);
+ m = sizzle(pattern);
+
+ for (var i = 0, len = m.length; i < len; ++i) {
+ this.matches.push(m[i]);
+ }
+ return this;
+ },
+
+ each : function(fn) {
+ for (var i = 0, len = this.matches.length; i < len; ++i) {
+ fn.call(this,this.matches[i]);
+ }
+ return this;
+ },
+
+ remove : function (html) { return this.html('remove', html); },
+ inner : function (html) { return this.html('inner', html); },
+ outer : function (html) { return this.html('outer', html); },
+ top : function (html) { return this.html('top', html); },
+ bottom : function (html) { return this.html('bottom', html); },
+ before : function (html) { return this.html('before', html); },
+ after : function (html) { return this.html('after', html); },
+
+ html : function(location, html) {
+ this._clean(this);
+
+ if (arguments.length == 0) {
+ return this[0].innerHTML;
+ }
+ if (arguments.length == 1 && arguments[0] != 'remove') {
+ html = location;
+ location = 'inner';
+ }
+
+ return this.each(function(el) {
+ var parent,
+ list,
+ len,
+ i = 0;
+ if (location == "inner") {
+ // Do we need this?!?
+ if (typeof html == 'string') {
+ el.innerHTML = html;
+ list = el.getElementsByTagName('SCRIPT');
+ len = list.length;
+ for (; i < len; i++) {
+ eval(list[i].text);
+ }
+ } else {
+ el.innerHTML = '';
+ el.appendChild(html);
+ }
+ } else if (location == "outer") {
+ el.parentNode.replaceChild(this._wrapHelper(html, el), el);
+ } else if (location == "top") {
+ el.insertBefore(this._wrapHelper(html, el), el.firstChild);
+ } else if (location == "bottom") {
+ el.insertBefore(this._wrapHelper(html, el), null);
+ } else if (location == "before") {
+ el.parentNode.insertBefore(this._wrapHelper(html, el.parentNode), el);
+ } else if (location == "after") {
+ el.parentNode.insertBefore(this._wrapHelper(html, el.parentNode), el.nextSibling);
+ } else if (location == "remove") {
+ el.parentNode.removeChild(el);
+ }
+ });
+ },
+
+ _wrapHelper : function(html, el) {
+ return (typeof html === "string") ? this._wrap(html, Apricot._getTag(el)) : html;
+ },
+
+ _clean : function(collection) {
+ var ns = /\S/;
+ collection.each(function(el) {
+ var d = el,
+ n = d.firstChild,
+ ni = -1,
+ nx;
+ while (n) {
+ nx = n.nextSibling;
+ if (n.nodeType == 3 && !ns.test(n.nodeValue)) {
+ d.removeChild(n);
+ } else {
+ n.nodeIndex = ++ni; // FIXME not sure what this is for, and causes IE to bomb (the setter) - @rem
+ }
+ n = nx;
+ }
+ });
+ },
+
+ // private method
+ // Wraps the HTML in a TAG, Tag is optional
+ // If the html starts with a Tag, it will wrap the context in that tag.
+ _wrap : function(xhtml, tag) {
+
+ var attributes = {},
+ re = /^<([A-Z][A-Z0-9]*)([^>]*)>(.*)<\/\1>/i,
+ element,
+ x,
+ a,
+ i = 0,
+ attr,
+ node,
+ attrList;
+
+ if (re.test(xhtml)) {
+ result = re.exec(xhtml);
+ tag = result[1];
+
+ // if the node has any attributes, convert to object
+ if (result[2] !== "") {
+ attrList = result[2].split(/([A-Z]*\s*=\s*['|"][A-Z0-9:;#\s]*['|"])/i);
+
+ for (; i < attrList.length; i++) {
+ attr = attrList[i].replace(/^\s*|\s*$/g, "");
+ if (attr !== "" && attr !== " ") {
+ node = attr.split('=');
+ attributes[node[0]] = node[1].replace(/(["']?)/g, '');
+ }
+ }
+ }
+ xhtml = result[3];
+ }
+
+ if (typeof(tag) === "undefined") {
+ element = this.document.createTextNode(xhtml)
+ } else {
+ element = this.document.createElement(tag);
+ for (x in attributes) {
+ a = doc.createAttribute(x);
+ a.nodeValue = attributes[x];
+ element.setAttributeNode(a);
+ }
+ element.innerHTML = xhtml;
+ }
+ return element;
+ },
+
+ /**
+ *
+ * Checks to see if classname is one the element. If a callback isn't passed, hasClass expects only one element in collection
+ *
+ * @param {String} className The class name.
+ * @param {Function} callback A callback function (optional)
+ * @return self if a callback is passed, otherwise true or false as to whether the element has the class
+ * @example
+ *
+ * ### hasClass
+ *
+ */
+ hasClass: function(className, callback) {
+
+ return (callback === undefined && this.matches.length == 1) ?
+ hasClass(this.matches[0], className) :
+ this.each(function(el) {
+ if (hasClass(el, className)) {
+ callback(el);
+ }
+ });
+ },
+ /**
+ *
+ * Removes the classname from all the elements in the collection.
+ *
+ * @param {String} className The class name.
+ * @return self
+ * @example
+ *
+ * ### removeClass
+ *
+ */
+ removeClass: function(className) {
+ if (className === undefined) {
+ this.each(function(el) {
+ el.className = '';
+ });
+ } else {
+ var re = getClassRegEx(className);
+ this.each(function(el) {
+ el.className = el.className.replace(re, '');
+ });
+ }
+ return this;
+ },
+ /**
+ *
+ * Adds the classname to all the elements in the collection.
+ *
+ * @param {String} className The class name.
+ * @return self
+ * @example
+ *
+ * ### addClass
+ */
+ addClass: function(className) {
+ return this.each(function(el) {
+ if (hasClass(el, className) === false) {
+ el.className = trim(el.className + ' ' + className);
+ }
+ });
+ },
+}
+
+
+var reClassNameCache = {},
+getClassRegEx = function(className) {
+ var re = reClassNameCache[className];
+ if (!re) {
+ re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
+ reClassNameCache[className] = re;
+ }
+ return re;
+};
+
+function hasClass(el, className) {
+ return getClassRegEx(className).test(el.className);
+}
+
+// Via jQuery - used to avoid el.className = ' foo';
+// Used for trimming whitespace
+var rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
+
+function trim(text) {
+ return (text || "").replace( rtrim, "" );
+}
+
+// private method for finding a dom element
+Apricot._getTag = function(el) {
+ return (el.firstChild === null) ? {'UL':'LI','DL':'DT','TR':'TD'}[el.tagName] || el.tagName : el.firstChild.tagName;
+}
+
+// Starting point for data, returns a new Apricot Object
+Apricot.parse = function(data,callback) {
+ callback(new Apricot(data));
+}
+
+// Starting point for File / HTTP, returns a new Apricot Object
+Apricot.open = function(file,callback) {
+ http = require('http'),
+ fs = require('fs'),
+ path = require('path'),
+ url = require('url'),
+
+ fnLoaderHandle = function (err, data) {
+ if (err) throw err;
+ var h = new Apricot(data);
+ callback(h);
+ }
+
+ if (file.match(/^https?:\/\//)) {
+ var urlInfo = url.parse(file, parseQueryString=false),
+ host = http.createClient(((urlInfo.protocol === 'http:') ? 80 : 443), urlInfo.hostname),
+ req_url = urlInfo.pathname;
+
+ if (urlInfo.search) {
+ req_url += urlInfo.search;
+ }
+ var request = host.request('GET', req_url, { host: urlInfo.hostname });
+
+ request.addListener('response', function (response) {
+ var data = '';
+ response.addListener('data', function (chunk) {
+ data += chunk;
+ });
+ response.addListener("end", function() {
+ fnLoaderHandle(null, data);
+ });
+ });
+ if (request.end) {
+ request.end();
+ } else {
+ request.close();
+ }
+
+ } else {
+ fs.readFile(file, encoding='utf8', fnLoaderHandle);
+ }
+}
+
Oops, something went wrong.

0 comments on commit 106ed10

Please sign in to comment.