Skip to content

Instantly share code, notes, and snippets.

@panayotoff
Created June 23, 2015 21:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panayotoff/4c13f66953f06907317a to your computer and use it in GitHub Desktop.
Save panayotoff/4c13f66953f06907317a to your computer and use it in GitHub Desktop.
x.js is my first attempt to build jQuery-like micro library. It has most of the functionality you use every day - selectors, events, traversal, add/remove/toggle class, get/set attributes and handles most common cases.
;
(function (window) {
'use strict';
var xBuild = (function () {
var xGlobals = {
newElementRegex: /<(\w+)\s?\/>/,
};
var x = function (_expression, _context) {
return new x.fn.init(_expression, _context);
};
//--------------------------------------------------------------
// Extending X with util functions
//--------------------------------------------------------------
x.addHelper = function (_name, _fn) {
x[_name] = _fn;
};
//--------------------------------------------------------------
// Simple get request helper, just an example how to add helpers
//--------------------------------------------------------------
x.addHelper('get', function (_url, _onDone, _onFail) {
var request = new XMLHttpRequest();
request.open('GET', _url, true);
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
_onDone(request.responseText);
} else {
_onFail(request.responseText)
}
};
request.onerror = _onFail;
request.send();
});
//--------------------------------------------------------------
// Build prop is used internally
//--------------------------------------------------------------
x.addHelper('buildProp', function (_prop, _val) {
var props = {};
if (_val !== undefined) {
props[_prop] = _val;
} else {
props = _prop;
}
return props;
});
//--------------------------------------------------------------
// Core
//--------------------------------------------------------------
x.fn = x.prototype = {
init: function (_expression, _context) {
if (typeof _expression === 'function') {
document.addEventListener('DOMContentLoaded', _expression);
} else {
this.elements = [];
var newElement = xGlobals.newElementRegex.exec(_expression);
if (newElement) {
this.elements.push(document.createElement(newElement[1]));
} else if (_expression.tagName) {
this.elements.push(_expression);
} else if (_expression.constructor === Array) {
this.elements = _expression;
} else {
var nodes = (_context == null ? document : _context).querySelectorAll(_expression);
for (var i = 0, j = nodes.length; i < j; i++) {
this.elements.push(nodes[i]);
}
}
return this;
}
},
el: function () {
return this.first().elements[0];
},
forEach: function (_fn) {
this.elements.forEach(_fn);
return this;
},
on: function (_handler, _fn) {
return this.forEach(function (el) {
el.addEventListener(_handler, _fn);
});
},
off: function (_handler, _fn) {
return this.forEach(function (el) {
el.removeEventListener(_handler, _fn);
});
},
trigger: function (_event, _data) {
return this.forEach(function (elem) {
elem.dispatchEvent(new CustomEvent(_event, {detail: _data || {}}))
});
},
addClass: function (_className) {
return this.forEach(function (elem) {
elem.classList.add(_className);
});
},
removeClass: function (_className) {
return this.forEach(function (elem) {
elem.classList.remove(_className);
});
},
toggleClass: function (_className) {
return this.forEach(function (elem) {
elem.classList.toggle(_className);
});
},
hasClass: function (_className) {
var hasClass = false;
this.forEach(function (elem) {
if (elem.classList.contains(_className)) {
hasClass = true;
}
});
return hasClass;
},
text: function (_newText) {
if (_newText === undefined) {
return this.el().textContent;
}
return this.forEach(function (elem) {
elem.innerText = _newText;
});
},
html: function (_newHtml) {
if (_newHtml === undefined) {
return this.el().innerHTML;
}
return this.forEach(function (elem) {
elem.innerHTML = _newHtml;
});
},
find: function (_selector) {
var elements = [];
this.forEach(function (elem) {
var finds = elem.querySelectorAll(_selector);
if (finds.length) {
for (var i = 0, j = finds.length; i < j; i++) {
elements.push(finds[i]);
}
}
});
return x(elements);
},
empty: function () {
return this.html('');
},
remove: function () {
return this.forEach(function (elem) {
elem.parentNode.removeChild(elem);
});
},
//Need to implement those;
append: function (_elem) {
},
prepend: function (_elem) {
},
before: function (_elem) {
},
after: function (_elem) {
},
clone: function () {
return this.el().cloneNode(true);
},
attr: function (_attrName, _attrVal) {
if (_attrVal === undefined) {
return this.el().getAttribute(_attrName);
}
var attrObj = x.buildProp(_attrName, _attrVal);
this.forEach(function (elem) {
for (var attr in attrObj) {
if (attrObj.hasOwnProperty(attr)) {
elem.setAttribute(attr, attrObj[attr]);
}
}
});
return this;
},
css: function (_cssObj, _cssVal) {
var stylesObj = x.buildProp(_cssObj, _cssVal);
return this.forEach(function (elem) {
for (var rule in stylesObj) {
if (stylesObj.hasOwnProperty(rule)) {
elem.style[rule] = stylesObj[rule];
}
}
});
},
parent: function () {
return x(this.el().parentNode);
},
first: function () {
return this.eq(0);
},
last: function () {
return this.eq(this.elements.length - 1);
},
eq: function (_index) {
return x(this.elements[_index]);
}
};
//--------------------------------------------------------------
// Expose to global
//--------------------------------------------------------------
x.fn.init.prototype = x.fn;
window.x = x;
})();
})(window, undefined);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment