chart updated etc
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
(function (root, factory) {
|
||||
// if (typeof define === 'function' && define.amd) {
|
||||
// // AMD. Register as an anonymous module.
|
||||
// define([], function () {
|
||||
// return (root.returnExportsGlobal = factory());
|
||||
// });
|
||||
// } else if (typeof exports === 'object') {
|
||||
// // Node. Does not work with strict CommonJS, but
|
||||
// // only CommonJS-like enviroments that support module.exports,
|
||||
// // like Node.
|
||||
// module.exports = factory();
|
||||
// } else {
|
||||
root['Chartist.plugins.ctAxisTitle'] = factory();
|
||||
// }
|
||||
}(this, function () {
|
||||
|
||||
/**
|
||||
* Chartist.js plugin to display a title for 1 or 2 axises.
|
||||
*
|
||||
*/
|
||||
/* global Chartist */
|
||||
(function (window, document, Chartist) {
|
||||
'use strict';
|
||||
|
||||
var axisDefaults = {
|
||||
axisTitle: '',
|
||||
axisClass: 'ct-axis-title',
|
||||
offset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
textAnchor: 'middle',
|
||||
flipText: false
|
||||
};
|
||||
var defaultOptions = {
|
||||
axisX: axisDefaults,
|
||||
axisY: axisDefaults
|
||||
};
|
||||
|
||||
Chartist.plugins = Chartist.plugins || {};
|
||||
Chartist.plugins.ctAxisTitle = function (options) {
|
||||
|
||||
options = Chartist.extend({}, defaultOptions, options);
|
||||
|
||||
console.log(options);
|
||||
|
||||
return function ctAxisTitle(chart) {
|
||||
|
||||
chart.on('created', function (data) {
|
||||
//
|
||||
// if (!options.axisX.axisTitle && !options.axisY.axisTitle) {
|
||||
// throw new Error('ctAxisTitle plugin - You must provide at least one axis title');
|
||||
// } else if (!data.axisX && !data.axisY) {
|
||||
// throw new Error('ctAxisTitle plugin can only be used on charts that have at least one axis');
|
||||
// }
|
||||
|
||||
var xPos;
|
||||
var yPos;
|
||||
var title;
|
||||
|
||||
//position axis X title
|
||||
if (options.axisX.axisTitle && data.axisX) {
|
||||
|
||||
xPos = (data.axisX.axisLength / 2) + data.options.axisY.offset + data.options.chartPadding.left;
|
||||
|
||||
yPos = data.options.chartPadding.top;
|
||||
|
||||
if (data.options.axisY.position === 'end') {
|
||||
xPos -= data.options.axisY.offset;
|
||||
}
|
||||
|
||||
if (data.options.axisX.position === 'end') {
|
||||
yPos += data.axisY.axisLength;
|
||||
}
|
||||
|
||||
title = new Chartist.Svg("text");
|
||||
title.addClass(options.axisX.axisClass);
|
||||
title.text(options.axisX.axisTitle);
|
||||
title.attr({
|
||||
x: xPos + options.axisX.offset.x,
|
||||
y: yPos + options.axisX.offset.y,
|
||||
"text-anchor": options.axisX.textAnchor
|
||||
});
|
||||
|
||||
data.svg.append(title, true);
|
||||
|
||||
}
|
||||
|
||||
//position axis Y title
|
||||
if (options.axisY.axisTitle && data.axisY) {
|
||||
xPos = 0;
|
||||
|
||||
|
||||
yPos = (data.axisY.axisLength / 2) + data.options.chartPadding.top;
|
||||
|
||||
if (data.options.axisX.position === 'start') {
|
||||
yPos += data.options.axisX.offset;
|
||||
}
|
||||
|
||||
if (data.options.axisY.position === 'end') {
|
||||
xPos = data.axisX.axisLength;
|
||||
}
|
||||
|
||||
var transform = 'rotate(' + (options.axisY.flipText ? -90 : 90) + ', ' + xPos + ', ' + yPos + ')';
|
||||
|
||||
title = new Chartist.Svg("text");
|
||||
title.addClass(options.axisY.axisClass);
|
||||
title.text(options.axisY.axisTitle);
|
||||
title.attr({
|
||||
x: xPos + options.axisY.offset.x,
|
||||
y: yPos + options.axisY.offset.y,
|
||||
transform: transform,
|
||||
"text-anchor": options.axisY.textAnchor
|
||||
});
|
||||
|
||||
data.svg.append(title, true);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
}(window, document, Chartist));
|
||||
|
||||
return Chartist.plugins.ctAxisTitle;
|
||||
|
||||
}));
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,272 @@
|
||||
(function (root, factory) {
|
||||
// if (typeof define === 'function' && define.amd) {
|
||||
// // AMD. Register as an anonymous module.
|
||||
// define([], function () {
|
||||
// return (root.returnExportsGlobal = factory());
|
||||
// });
|
||||
// } else if (typeof exports === 'object') {
|
||||
// // Node. Does not work with strict CommonJS, but
|
||||
// // only CommonJS-like enviroments that support module.exports,
|
||||
// // like Node.
|
||||
// module.exports = factory();
|
||||
// } else {
|
||||
root['Chartist.plugins.zoom'] = factory();
|
||||
// }
|
||||
}(this, function () {
|
||||
|
||||
/**
|
||||
* Chartist.js zoom plugin.
|
||||
*
|
||||
*/
|
||||
(function (window, document, Chartist) {
|
||||
'use strict';
|
||||
|
||||
var defaultOptions = {
|
||||
// onZoom
|
||||
// resetOnRightMouseBtn
|
||||
};
|
||||
|
||||
|
||||
Chartist.plugins = Chartist.plugins || {};
|
||||
Chartist.plugins.zoom = function (options) {
|
||||
|
||||
options = Chartist.extend({}, defaultOptions, options);
|
||||
|
||||
return function zoom(chart) {
|
||||
|
||||
if (!(chart instanceof Chartist.Line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect, svg, axisX, axisY, chartRect;
|
||||
var downPosition;
|
||||
var onZoom = options.onZoom;
|
||||
var ongoingTouches = [];
|
||||
|
||||
chart.on('draw', function (data) {
|
||||
var type = data.type;
|
||||
if (type === 'line' || type === 'bar' || type === 'area' || type === 'point') {
|
||||
data.element.attr({
|
||||
'clip-path': 'url(#zoom-mask)'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
chart.on('created', function (data) {
|
||||
axisX = data.axisX;
|
||||
axisY = data.axisY;
|
||||
chartRect = data.chartRect;
|
||||
svg = data.svg._node;
|
||||
rect = data.svg.elem('rect', {
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 100,
|
||||
height: 100,
|
||||
}, 'ct-zoom-rect');
|
||||
hide(rect);
|
||||
|
||||
var defs = data.svg.querySelector('defs') || data.svg.elem('defs');
|
||||
var width = chartRect.width();
|
||||
var height = chartRect.height();
|
||||
|
||||
defs
|
||||
.elem('clipPath', {
|
||||
id: 'zoom-mask'
|
||||
})
|
||||
.elem('rect', {
|
||||
x: chartRect.x1,
|
||||
y: chartRect.y2,
|
||||
width: width,
|
||||
height: height,
|
||||
fill: 'white'
|
||||
});
|
||||
|
||||
svg.addEventListener('mousedown', onMouseDown);
|
||||
svg.addEventListener('mouseup', onMouseUp);
|
||||
svg.addEventListener('mousemove', onMouseMove);
|
||||
svg.addEventListener('touchstart', onTouchStart);
|
||||
svg.addEventListener('touchmove', onTouchMove);
|
||||
svg.addEventListener('touchend', onTouchEnd);
|
||||
svg.addEventListener('touchcancel', onTouchCancel);
|
||||
});
|
||||
|
||||
function copyTouch(touch) {
|
||||
var p = position(touch, svg);
|
||||
p.id = touch.identifier;
|
||||
return p;
|
||||
}
|
||||
|
||||
function ongoingTouchIndexById(idToFind) {
|
||||
for (var i = 0; i < ongoingTouches.length; i++) {
|
||||
var id = ongoingTouches[i].id;
|
||||
if (id === idToFind) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function onTouchStart(event) {
|
||||
var touches = event.changedTouches;
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
ongoingTouches.push(copyTouch(touches[i]));
|
||||
}
|
||||
|
||||
if (ongoingTouches.length > 1) {
|
||||
rect.attr(getRect(ongoingTouches[0], ongoingTouches[1]));
|
||||
show(rect);
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchMove(event) {
|
||||
var touches = event.changedTouches;
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
var idx = ongoingTouchIndexById(touches[i].identifier);
|
||||
ongoingTouches.splice(idx, 1, copyTouch(touches[i]));
|
||||
}
|
||||
|
||||
if (ongoingTouches.length > 1) {
|
||||
rect.attr(getRect(ongoingTouches[0], ongoingTouches[1]));
|
||||
show(rect);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchCancel(event) {
|
||||
removeTouches(event.changedTouches);
|
||||
}
|
||||
|
||||
function removeTouches(touches) {
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
var idx = ongoingTouchIndexById(touches[i].identifier);
|
||||
if (idx >= 0) {
|
||||
ongoingTouches.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchEnd(event) {
|
||||
if (ongoingTouches.length > 1) {
|
||||
zoomIn(getRect(ongoingTouches[0], ongoingTouches[1]));
|
||||
}
|
||||
removeTouches(event.changedTouches);
|
||||
hide(rect);
|
||||
}
|
||||
|
||||
function onMouseDown(event) {
|
||||
if (event.button === 0) {
|
||||
downPosition = position(event, svg);
|
||||
rect.attr(getRect(downPosition, downPosition));
|
||||
show(rect);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
var reset = function () {
|
||||
chart.options.axisX.highLow = null;
|
||||
chart.options.axisY.highLow = null;
|
||||
chart.update(chart.data, chart.options);
|
||||
};
|
||||
|
||||
function onMouseUp(event) {
|
||||
if (event.button === 0) {
|
||||
var box = getRect(downPosition, position(event, svg));
|
||||
zoomIn(box);
|
||||
downPosition = null;
|
||||
hide(rect);
|
||||
event.preventDefault();
|
||||
}
|
||||
else if (options.resetOnRightMouseBtn && event.button === 2) {
|
||||
reset();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function zoomIn(rect) {
|
||||
if (rect.width > 5 && rect.height > 5) {
|
||||
var x1 = rect.x - chartRect.x1;
|
||||
var x2 = x1 + rect.width;
|
||||
var y2 = chartRect.y1 - rect.y;
|
||||
var y1 = y2 - rect.height;
|
||||
|
||||
chart.options.axisX.highLow = { low: project(x1, axisX), high: project(x2, axisX) };
|
||||
chart.options.axisY.highLow = { low: project(y1, axisY), high: project(y2, axisY) };
|
||||
|
||||
chart.update(chart.data, chart.options);
|
||||
onZoom && onZoom(chart, reset);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
if (downPosition) {
|
||||
var point = position(event, svg);
|
||||
rect.attr(getRect(downPosition, point));
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
function hide(rect) {
|
||||
rect.attr({ style: 'display:none' });
|
||||
}
|
||||
|
||||
function show(rect) {
|
||||
rect.attr({ style: 'display:block' });
|
||||
}
|
||||
|
||||
function getRect(firstPoint, secondPoint) {
|
||||
var x = firstPoint.x;
|
||||
var y = firstPoint.y;
|
||||
var width = secondPoint.x - x;
|
||||
var height = secondPoint.y - y;
|
||||
if (width < 0) {
|
||||
width = -width;
|
||||
x = secondPoint.x;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
y = secondPoint.y;
|
||||
}
|
||||
return {
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
|
||||
function position(event, svg) {
|
||||
return transform(event.clientX, event.clientY, svg);
|
||||
}
|
||||
|
||||
function transform(x, y, svgElement) {
|
||||
var svg = svgElement.tagName === 'svg' ? svgElement : svgElement.ownerSVGElement;
|
||||
var matrix = svg.getScreenCTM();
|
||||
var point = svg.createSVGPoint();
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
point = point.matrixTransform(matrix.inverse());
|
||||
return point || { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
function project(value, axis) {
|
||||
var max = axis.bounds.max;
|
||||
var min = axis.bounds.min;
|
||||
if (axis.scale && axis.scale.type === 'log') {
|
||||
var base = axis.scale.base;
|
||||
return Math.pow(base,
|
||||
value * baseLog(max / min, base) / axis.axisLength) * min;
|
||||
}
|
||||
return (value * axis.bounds.range / axis.axisLength) + min;
|
||||
}
|
||||
|
||||
function baseLog(val, base) {
|
||||
return Math.log(val) / Math.log(base);
|
||||
}
|
||||
|
||||
} (window, document, Chartist));
|
||||
return Chartist.plugins.zoom;
|
||||
|
||||
}));
|
||||
@@ -0,0 +1,706 @@
|
||||
/*!chibi 3.0.7, Copyright 2012-2016 Kyle Barrow, released under MIT license */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var readyfn = [],
|
||||
loadedfn = [],
|
||||
domready = false,
|
||||
pageloaded = false,
|
||||
jsonpcount = 0,
|
||||
d = document,
|
||||
w = window;
|
||||
|
||||
// Fire any function calls on ready event
|
||||
function fireReady() {
|
||||
var i;
|
||||
domready = true;
|
||||
for (i = 0; i < readyfn.length; i += 1) {
|
||||
readyfn[i]();
|
||||
}
|
||||
readyfn = [];
|
||||
}
|
||||
|
||||
// Fire any function calls on loaded event
|
||||
function fireLoaded() {
|
||||
var i;
|
||||
pageloaded = true;
|
||||
// For browsers with no DOM loaded support
|
||||
if (!domready) {
|
||||
fireReady();
|
||||
}
|
||||
for (i = 0; i < loadedfn.length; i += 1) {
|
||||
loadedfn[i]();
|
||||
}
|
||||
loadedfn = [];
|
||||
}
|
||||
|
||||
// Check DOM ready, page loaded
|
||||
if (d.addEventListener) {
|
||||
// Standards
|
||||
d.addEventListener('DOMContentLoaded', fireReady, false);
|
||||
w.addEventListener('load', fireLoaded, false);
|
||||
} else if (d.attachEvent) {
|
||||
// IE
|
||||
d.attachEvent('onreadystatechange', fireReady);
|
||||
// IE < 9
|
||||
w.attachEvent('onload', fireLoaded);
|
||||
} else {
|
||||
// Anything else
|
||||
w.onload = fireLoaded;
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
|
||||
// Loop through node array
|
||||
function nodeLoop(fn, nodes) {
|
||||
var i;
|
||||
// Good idea to walk up the DOM
|
||||
for (i = nodes.length - 1; i >= 0; i -= 1) {
|
||||
fn(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to camel case
|
||||
function cssCamel(property) {
|
||||
return property.replace(/-\w/g, function (result) {return result.charAt(1).toUpperCase(); });
|
||||
}
|
||||
|
||||
// Get computed style
|
||||
function computeStyle(elm, property) {
|
||||
// IE, everything else or null
|
||||
return (elm.currentStyle) ? elm.currentStyle[cssCamel(property)] : (w.getComputedStyle) ? w.getComputedStyle(elm, null).getPropertyValue(property) : null;
|
||||
|
||||
}
|
||||
|
||||
// Returns URI encoded query string pair
|
||||
function queryPair(name, value) {
|
||||
return encodeURIComponent(name).replace(/%20/g, '+') + '=' + encodeURIComponent(value).replace(/%20/g, '+');
|
||||
}
|
||||
|
||||
// Set CSS, important to wrap in try to prevent error thown on unsupported property
|
||||
function setCss(elm, property, value) {
|
||||
try {
|
||||
elm.style[cssCamel(property)] = value;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Show CSS
|
||||
function showCss(elm) {
|
||||
elm.style.display = '';
|
||||
// For elements still hidden by style block
|
||||
if (computeStyle(elm, 'display') === 'none') {
|
||||
elm.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize form & JSON values
|
||||
function serializeData(nodes) {
|
||||
var querystring = '', subelm, i, j;
|
||||
if (nodes.constructor === Object) { // Serialize JSON data
|
||||
for (subelm in nodes) {
|
||||
if (nodes.hasOwnProperty(subelm)) {
|
||||
if (nodes[subelm].constructor === Array) {
|
||||
for (i = 0; i < nodes[subelm].length; i += 1) {
|
||||
querystring += '&' + queryPair(subelm, nodes[subelm][i]);
|
||||
}
|
||||
} else {
|
||||
querystring += '&' + queryPair(subelm, nodes[subelm]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // Serialize node data
|
||||
nodeLoop(function (elm) {
|
||||
if (elm.nodeName === 'FORM') {
|
||||
for (i = 0; i < elm.elements.length; i += 1) {
|
||||
subelm = elm.elements[i];
|
||||
|
||||
if (!subelm.disabled) {
|
||||
switch (subelm.type) {
|
||||
// Ignore buttons, unsupported XHR 1 form fields
|
||||
case 'button':
|
||||
case 'image':
|
||||
case 'file':
|
||||
case 'submit':
|
||||
case 'reset':
|
||||
break;
|
||||
|
||||
case 'select-one':
|
||||
if (subelm.length > 0) {
|
||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'select-multiple':
|
||||
for (j = 0; j < subelm.length; j += 1) {
|
||||
if (subelm[j].selected) {
|
||||
querystring += '&' + queryPair(subelm.name, subelm[j].value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
case 'radio':
|
||||
if (subelm.checked) {
|
||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
||||
}
|
||||
break;
|
||||
|
||||
// Everything else including shinny new HTML5 input types
|
||||
default:
|
||||
querystring += '&' + queryPair(subelm.name, subelm.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, nodes);
|
||||
}
|
||||
// Tidy up first &
|
||||
return (querystring.length > 0) ? querystring.substring(1) : '';
|
||||
}
|
||||
|
||||
// Class helper
|
||||
function classHelper(classes, action, nodes) {
|
||||
var classarray, search, i, has = false;
|
||||
if (classes) {
|
||||
// Trim any whitespace
|
||||
classarray = classes.split(/\s+/);
|
||||
nodeLoop(function (elm) {
|
||||
for (i = 0; i < classarray.length; i += 1) {
|
||||
search = new RegExp('\\b' + classarray[i] + '\\b', 'g');
|
||||
if (action === 'remove') {
|
||||
elm.className = elm.className.replace(search, '');
|
||||
} else if (action === 'toggle') {
|
||||
elm.className = (elm.className.match(search)) ? elm.className.replace(search, '') : elm.className + ' ' + classarray[i];
|
||||
} else if (action === 'has') {
|
||||
if (elm.className.match(search)) {
|
||||
has = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, nodes);
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
// HTML insertion helper
|
||||
function insertHtml(value, position, nodes) {
|
||||
var tmpnodes, tmpnode;
|
||||
if (value) {
|
||||
nodeLoop(function (elm) {
|
||||
// No insertAdjacentHTML support for FF < 8 and IE doesn't allow insertAdjacentHTML table manipulation, so use this instead
|
||||
// Convert string to node. We can't innerHTML on a document fragment
|
||||
tmpnodes = d.createElement('div');
|
||||
tmpnodes.innerHTML = value;
|
||||
while ((tmpnode = tmpnodes.lastChild) !== null) {
|
||||
// Catch error in unlikely case elm has been removed
|
||||
try {
|
||||
if (position === 'before') {
|
||||
elm.parentNode.insertBefore(tmpnode, elm);
|
||||
} else if (position === 'after') {
|
||||
elm.parentNode.insertBefore(tmpnode, elm.nextSibling);
|
||||
} else if (position === 'append') {
|
||||
elm.appendChild(tmpnode);
|
||||
} else if (position === 'prepend') {
|
||||
elm.insertBefore(tmpnode, elm.firstChild);
|
||||
}
|
||||
} catch (e) {break; }
|
||||
}
|
||||
}, nodes);
|
||||
}
|
||||
}
|
||||
|
||||
// Get nodes and return chibi
|
||||
function chibi(selector) {
|
||||
var cb, nodes = [], json = false, nodelist, i;
|
||||
|
||||
if (selector) {
|
||||
|
||||
// Element node, would prefer to use (selector instanceof HTMLElement) but no IE support
|
||||
if (selector.nodeType && selector.nodeType === 1) {
|
||||
nodes = [selector]; // return element as node list
|
||||
} else if (typeof selector === 'object') {
|
||||
// JSON, document object or node list, would prefer to use (selector instanceof NodeList) but no IE support
|
||||
json = (typeof selector.length !== 'number');
|
||||
nodes = selector;
|
||||
} else if (typeof selector === 'string') {
|
||||
|
||||
// A very light querySelectorAll polyfill for IE < 8. It suits my needs but is restricted to IE CSS support, is no speed demon, and does leave older mobile browsers in the cold (that support neither querySelectorAll nor currentStyle/getComputedStyle). If you want to use a fuller featured selector engine like Qwery, Sizzle et al, just return results to the nodes array: nodes = altselectorengine(selector)
|
||||
|
||||
// IE < 8
|
||||
if (!d.querySelectorAll) {
|
||||
// Polyfill querySelectorAll
|
||||
d.querySelectorAll = function (selector) {
|
||||
|
||||
var style, head = d.getElementsByTagName('head')[0], allnodes, selectednodes = [], i;
|
||||
|
||||
style = d.createElement('STYLE');
|
||||
style.type = 'text/css';
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = selector + ' {a:b}';
|
||||
|
||||
head.appendChild(style);
|
||||
|
||||
allnodes = d.getElementsByTagName('*');
|
||||
|
||||
for (i = 0; i < allnodes.length; i += 1) {
|
||||
if (computeStyle(allnodes[i], 'a') === 'b') {
|
||||
selectednodes.push(allnodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
head.removeChild(style);
|
||||
}
|
||||
|
||||
return selectednodes;
|
||||
};
|
||||
}
|
||||
|
||||
nodelist = d.querySelectorAll(selector);
|
||||
|
||||
// Convert node list to array so results have full access to array methods
|
||||
// Array.prototype.slice.call not supported in IE < 9 and often slower than loop anyway
|
||||
for (i = 0; i < nodelist.length; i += 1) {
|
||||
nodes[i] = nodelist[i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Only attach nodes if not JSON
|
||||
cb = json ? {} : nodes;
|
||||
|
||||
// Public functions
|
||||
|
||||
// Fire on DOM ready
|
||||
cb.ready = function (fn) {
|
||||
if (fn) {
|
||||
if (domready) {
|
||||
fn();
|
||||
return cb;
|
||||
} else {
|
||||
readyfn.push(fn);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Fire on page loaded
|
||||
cb.loaded = function (fn) {
|
||||
if (fn) {
|
||||
if (pageloaded) {
|
||||
fn();
|
||||
return cb;
|
||||
} else {
|
||||
loadedfn.push(fn);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Executes a function on nodes
|
||||
cb.each = function (fn) {
|
||||
if (typeof fn === 'function') {
|
||||
nodeLoop(function (elm) {
|
||||
// <= IE 8 loses scope so need to apply
|
||||
return fn.apply(elm, arguments);
|
||||
}, nodes);
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
// Find first
|
||||
cb.first = function () {
|
||||
return chibi(nodes.shift());
|
||||
};
|
||||
// Find last
|
||||
cb.last = function () {
|
||||
return chibi(nodes.pop());
|
||||
};
|
||||
// Find odd
|
||||
cb.odd = function () {
|
||||
var odds = [], i;
|
||||
for (i = 0; i < nodes.length; i += 2) {
|
||||
odds.push(nodes[i]);
|
||||
}
|
||||
return chibi(odds);
|
||||
};
|
||||
// Find even
|
||||
cb.even = function () {
|
||||
var evens = [], i;
|
||||
for (i = 1; i < nodes.length; i += 2) {
|
||||
evens.push(nodes[i]);
|
||||
}
|
||||
return chibi(evens);
|
||||
};
|
||||
// Hide node
|
||||
cb.hide = function () {
|
||||
nodeLoop(function (elm) {
|
||||
elm.style.display = 'none';
|
||||
}, nodes);
|
||||
return cb;
|
||||
};
|
||||
// Show node
|
||||
cb.show = function () {
|
||||
nodeLoop(function (elm) {
|
||||
showCss(elm);
|
||||
}, nodes);
|
||||
return cb;
|
||||
};
|
||||
// Toggle node display
|
||||
cb.toggle = function (state) {
|
||||
if (typeof state != 'undefined') { // ADDED
|
||||
if(state)
|
||||
cb.show();
|
||||
else
|
||||
cb.hide();
|
||||
} else {
|
||||
nodeLoop(function (elm) {
|
||||
// computeStyle instead of style.display == 'none' catches elements that are hidden via style block
|
||||
if (computeStyle(elm, 'display') === 'none') {
|
||||
showCss(elm);
|
||||
} else {
|
||||
elm.style.display = 'none';
|
||||
}
|
||||
|
||||
}, nodes);
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
// Remove node
|
||||
cb.remove = function () {
|
||||
nodeLoop(function (elm) {
|
||||
// Catch error in unlikely case elm has been removed
|
||||
try {
|
||||
elm.parentNode.removeChild(elm);
|
||||
} catch (e) {}
|
||||
}, nodes);
|
||||
return chibi();
|
||||
};
|
||||
// Get/Set CSS
|
||||
cb.css = function (property, value) {
|
||||
if (property) {
|
||||
if (value || value === '') {
|
||||
nodeLoop(function (elm) {
|
||||
setCss(elm, property, value);
|
||||
}, nodes);
|
||||
return cb;
|
||||
}
|
||||
if (nodes[0]) {
|
||||
if (nodes[0].style[cssCamel(property)]) {
|
||||
return nodes[0].style[cssCamel(property)];
|
||||
}
|
||||
if (computeStyle(nodes[0], property)) {
|
||||
return computeStyle(nodes[0], property);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// Get class(es)
|
||||
cb.getClass = function () {
|
||||
if (nodes[0] && nodes[0].className.length > 0) {
|
||||
// Weak IE trim support
|
||||
return nodes[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '').replace(/\s+/,' ');
|
||||
}
|
||||
};
|
||||
// Set (replaces) classes
|
||||
cb.setClass = function (classes) {
|
||||
if (classes || classes === '') {
|
||||
nodeLoop(function (elm) {
|
||||
elm.className = classes;
|
||||
}, nodes);
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
// Add class
|
||||
cb.addClass = function (classes) {
|
||||
if (classes) {
|
||||
nodeLoop(function (elm) {
|
||||
elm.className += ' ' + classes;
|
||||
}, nodes);
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
// Remove class
|
||||
cb.removeClass = function (classes) {
|
||||
classHelper(classes, 'remove', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Toggle class
|
||||
cb.toggleClass = function (classes) {
|
||||
classHelper(classes, 'toggle', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Has class
|
||||
cb.hasClass = function (classes) {
|
||||
return classHelper(classes, 'has', nodes);
|
||||
};
|
||||
// Get/set HTML
|
||||
cb.html = function (value) {
|
||||
if (value || value === '') {
|
||||
nodeLoop(function (elm) {
|
||||
elm.innerHTML = value;
|
||||
}, nodes);
|
||||
return cb;
|
||||
}
|
||||
if (nodes[0]) {
|
||||
return nodes[0].innerHTML;
|
||||
}
|
||||
};
|
||||
// Insert HTML before selector
|
||||
cb.htmlBefore = function (value) {
|
||||
insertHtml(value, 'before', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Insert HTML after selector
|
||||
cb.htmlAfter = function (value) {
|
||||
insertHtml(value, 'after', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Insert HTML after selector innerHTML
|
||||
cb.htmlAppend = function (value) {
|
||||
insertHtml(value, 'append', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Insert HTML before selector innerHTML
|
||||
cb.htmlPrepend = function (value) {
|
||||
insertHtml(value, 'prepend', nodes);
|
||||
return cb;
|
||||
};
|
||||
// Get/Set HTML attributes
|
||||
cb.attr = function (property, value) {
|
||||
if (property) {
|
||||
property = property.toLowerCase();
|
||||
// IE < 9 doesn't allow style or class via get/setAttribute so switch. cssText returns prettier CSS anyway
|
||||
if (typeof value !== 'undefined') {//FIXED BUG HERE
|
||||
nodeLoop(function (elm) {
|
||||
if (property === 'style') {
|
||||
elm.style.cssText = value;
|
||||
} else if (property === 'class') {
|
||||
elm.className = value;
|
||||
} else {
|
||||
elm.setAttribute(property, value);
|
||||
}
|
||||
}, nodes);
|
||||
return cb;
|
||||
}
|
||||
if (nodes[0]) {
|
||||
if (property === 'style') {
|
||||
if (nodes[0].style.cssText) {
|
||||
return nodes[0].style.cssText;
|
||||
}
|
||||
} else if (property === 'class') {
|
||||
if (nodes[0].className) {
|
||||
return nodes[0].className;
|
||||
}
|
||||
} else {
|
||||
if (nodes[0].getAttribute(property)) {
|
||||
return nodes[0].getAttribute(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// Get/Set HTML data property
|
||||
cb.data = function (key, value) {
|
||||
if (key) {
|
||||
return cb.attr('data-'+key, value);
|
||||
}
|
||||
};
|
||||
// Get/Set form element values
|
||||
cb.val = function (value) {
|
||||
var values, i, j;
|
||||
if (value || value === '') {
|
||||
nodeLoop(function (elm) {
|
||||
switch (elm.nodeName) {
|
||||
case 'SELECT':
|
||||
if (typeof value === 'string' || typeof value === 'number') {
|
||||
value = [value];
|
||||
}
|
||||
for (i = 0; i < elm.length; i += 1) {
|
||||
// Multiple select
|
||||
for (j = 0; j < value.length; j += 1) {
|
||||
elm[i].selected = '';
|
||||
if (elm[i].value === value[j]) {
|
||||
elm[i].selected = 'selected';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'INPUT':
|
||||
case 'TEXTAREA':
|
||||
case 'BUTTON':
|
||||
elm.value = value;
|
||||
break;
|
||||
}
|
||||
}, nodes);
|
||||
|
||||
return cb;
|
||||
}
|
||||
if (nodes[0]) {
|
||||
switch (nodes[0].nodeName) {
|
||||
case 'SELECT':
|
||||
values = [];
|
||||
for (i = 0; i < nodes[0].length; i += 1) {
|
||||
if (nodes[0][i].selected) {
|
||||
values.push(nodes[0][i].value);
|
||||
}
|
||||
}
|
||||
return (values.length > 1) ? values : values[0];
|
||||
case 'INPUT':
|
||||
case 'TEXTAREA':
|
||||
case 'BUTTON':
|
||||
return nodes[0].value;
|
||||
}
|
||||
}
|
||||
};
|
||||
// Return matching checked checkbox or radios
|
||||
cb.checked = function (check) {
|
||||
if (typeof check === 'boolean') {
|
||||
nodeLoop(function (elm) {
|
||||
if (elm.nodeName === 'INPUT' && (elm.type === 'checkbox' || elm.type === 'radio')) {
|
||||
elm.checked = check;
|
||||
}
|
||||
}, nodes);
|
||||
return cb;
|
||||
}
|
||||
if (nodes[0] && nodes[0].nodeName === 'INPUT' && (nodes[0].type === 'checkbox' || nodes[0].type === 'radio')) {
|
||||
return (!!nodes[0].checked);
|
||||
}
|
||||
};
|
||||
// Add event handler
|
||||
cb.on = function (event, fn) {
|
||||
if (selector === w || selector === d) {
|
||||
nodes = [selector];
|
||||
}
|
||||
nodeLoop(function (elm) {
|
||||
if (d.addEventListener) {
|
||||
elm.addEventListener(event, fn, false);
|
||||
} else if (d.attachEvent) {
|
||||
// <= IE 8 loses scope so need to apply, we add this to object so we can detach later (can't detach anonymous functions)
|
||||
elm[event + fn] = function () { return fn.apply(elm, arguments); };
|
||||
elm.attachEvent('on' + event, elm[event + fn]);
|
||||
}
|
||||
}, nodes);
|
||||
return cb;
|
||||
};
|
||||
// Remove event handler
|
||||
cb.off = function (event, fn) {
|
||||
if (selector === w || selector === d) {
|
||||
nodes = [selector];
|
||||
}
|
||||
nodeLoop(function (elm) {
|
||||
if (d.addEventListener) {
|
||||
elm.removeEventListener(event, fn, false);
|
||||
} else if (d.attachEvent) {
|
||||
elm.detachEvent('on' + event, elm[event + fn]);
|
||||
// Tidy up
|
||||
elm[event + fn] = null;
|
||||
}
|
||||
}, nodes);
|
||||
return cb;
|
||||
};
|
||||
// Basic XHR 1, no file support. Shakes fist at IE
|
||||
cb.ajax = function (url, method, callback, nocache, nojsonp) {
|
||||
var xhr,
|
||||
query = serializeData(nodes),
|
||||
type = (method) ? method.toUpperCase() : 'GET',
|
||||
hostsearch = new RegExp('http[s]?://(.*?)/', 'gi'),
|
||||
domain = hostsearch.exec(url),
|
||||
timestamp = '_ts=' + (+new Date()),
|
||||
head = d.getElementsByTagName('head')[0],
|
||||
jsonpcallback = 'chibi' + (+new Date()) + (jsonpcount += 1),
|
||||
script;
|
||||
|
||||
if (query && (type === 'GET' || type === 'DELETE')) {
|
||||
url += (url.indexOf('?') === -1) ? '?' + query : '&' + query;
|
||||
query = null;
|
||||
}
|
||||
|
||||
// JSONP if cross domain url
|
||||
if (type === 'GET' && !nojsonp && domain && w.location.host !== domain[1]) {
|
||||
|
||||
if (nocache) {
|
||||
url += (url.indexOf('?') === -1) ? '?' + timestamp : '&' + timestamp;
|
||||
}
|
||||
|
||||
// Replace possible encoded ?
|
||||
url = url.replace('=%3F', '=?');
|
||||
|
||||
// Replace jsonp ? with callback
|
||||
if (callback && url.indexOf('=?') !== -1) {
|
||||
|
||||
url = url.replace('=?', '=' + jsonpcallback);
|
||||
|
||||
w[jsonpcallback] = function (data) {
|
||||
try {
|
||||
callback(data, 200);
|
||||
} catch (e) {}
|
||||
|
||||
// Tidy up
|
||||
w[jsonpcallback] = undefined;
|
||||
};
|
||||
}
|
||||
|
||||
// JSONP
|
||||
script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = url;
|
||||
|
||||
// Tidy up
|
||||
script.onload = function () {
|
||||
head.removeChild(script);
|
||||
};
|
||||
|
||||
head.appendChild(script);
|
||||
|
||||
} else {
|
||||
|
||||
if (w.XMLHttpRequest) {
|
||||
xhr = new XMLHttpRequest();
|
||||
} else if (w.ActiveXObject) {
|
||||
xhr = new ActiveXObject('Microsoft.XMLHTTP'); // IE < 9
|
||||
}
|
||||
|
||||
if (xhr) {
|
||||
|
||||
if (nocache) {
|
||||
url += (url.indexOf('?') === -1) ? '?' + timestamp : '&' + timestamp;
|
||||
}
|
||||
|
||||
// Douglas Crockford: "Synchronous programming is disrespectful and should not be employed in applications which are used by people"
|
||||
xhr.open(type, url, true);
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === 4) {
|
||||
if (callback) {
|
||||
callback(xhr.responseText, xhr.status);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
|
||||
if (type === 'POST' || type === 'PUT') {
|
||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
|
||||
xhr.send(query);
|
||||
|
||||
}
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
// Alias to cb.ajax(url, 'get', callback, nocache, nojsonp)
|
||||
cb.get = function (url, callback, nocache, nojsonp) {
|
||||
return cb.ajax(url, 'get', callback, nocache, nojsonp);
|
||||
};
|
||||
// Alias to cb.ajax(url, 'post', callback, nocache)
|
||||
cb.post = function (url, callback, nocache) {
|
||||
return cb.ajax(url, 'post', callback, nocache);
|
||||
};
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
// Set Chibi's global namespace here ($)
|
||||
w.$ = chibi;
|
||||
|
||||
}());
|
||||
Reference in New Issue
Block a user