651 lines
24 KiB
JavaScript
651 lines
24 KiB
JavaScript
|
/*
|
||
|
|
||
|
# EQCSS
|
||
|
## version 1.7.0
|
||
|
|
||
|
A JavaScript plugin to read EQCSS syntax to provide:
|
||
|
scoped styles, element queries, container queries,
|
||
|
meta-selectors, eval(), and element-based units.
|
||
|
|
||
|
- github.com/eqcss/eqcss
|
||
|
- elementqueries.com
|
||
|
|
||
|
Authors: Tommy Hodgins, Maxime Euzière, Azareal
|
||
|
|
||
|
License: MIT
|
||
|
|
||
|
*/
|
||
|
|
||
|
// Uses Node, AMD or browser globals to create a module
|
||
|
(function (root, factory) {
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
// AMD: Register as an anonymous module
|
||
|
define([], factory);
|
||
|
} else if (typeof module === 'object' && module.exports) {
|
||
|
// Node: Does not work with strict CommonJS, but
|
||
|
// only CommonJS-like environments that support module.exports,
|
||
|
// like Node
|
||
|
module.exports = factory();
|
||
|
} else {
|
||
|
// Browser globals (root is window)
|
||
|
root.EQCSS = factory();
|
||
|
}
|
||
|
}(this, function() {
|
||
|
var EQCSS = {
|
||
|
data: []
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.load()
|
||
|
* Called automatically on page load.
|
||
|
* Call it manually after adding EQCSS code in the page.
|
||
|
* Loads and parses all the EQCSS code.
|
||
|
*/
|
||
|
EQCSS.load = function() {
|
||
|
// Retrieve all style blocks
|
||
|
var styles = document.getElementsByTagName('style');
|
||
|
|
||
|
for (var i = 0; i < styles.length; i++) {
|
||
|
// Test if the style is not read yet
|
||
|
if (styles[i].getAttribute('data-eqcss-read') === null) {
|
||
|
|
||
|
// Mark the style block as read
|
||
|
styles[i].setAttribute('data-eqcss-read', 'true');
|
||
|
|
||
|
EQCSS.process(styles[i].innerHTML);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Retrieve all link tags
|
||
|
var link = document.getElementsByTagName('link');
|
||
|
|
||
|
for (i = 0; i < link.length; i++) {
|
||
|
// Test if the link is not read yet, and has rel=stylesheet
|
||
|
if (link[i].getAttribute('data-eqcss-read') === null && link[i].rel === 'stylesheet') {
|
||
|
// retrieve the file content with AJAX and process it
|
||
|
if (link[i].href) {
|
||
|
(function() {
|
||
|
var xhr = new XMLHttpRequest;
|
||
|
xhr.open('GET', link[i].href, true);
|
||
|
xhr.send(null);
|
||
|
xhr.onreadystatechange = function() {
|
||
|
EQCSS.process(xhr.responseText);
|
||
|
}
|
||
|
})();
|
||
|
}
|
||
|
// Mark the link as read
|
||
|
link[i].setAttribute('data-eqcss-read', 'true');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.parse()
|
||
|
* Called by load for each script / style / link resource.
|
||
|
* Generates data for each Element Query found
|
||
|
*/
|
||
|
EQCSS.parse = function(code) {
|
||
|
var parsed_queries = new Array();
|
||
|
|
||
|
// Cleanup
|
||
|
code = code.replace(/\s+/g, ' '); // reduce spaces and line breaks
|
||
|
code = code.replace(/\/\*[\w\W]*?\*\//g, ''); // remove comments
|
||
|
code = code.replace(/@element/g, '\n@element'); // one element query per line
|
||
|
code = code.replace(/(@element.*?\{([^}]*?\{[^}]*?\}[^}]*?)*\}).*/g, '$1'); // Keep the queries only (discard regular css written around them)
|
||
|
|
||
|
// Parse
|
||
|
|
||
|
// For each query
|
||
|
code.replace(/(@element.*(?!@element))/g, function(string, query) {
|
||
|
// Create a data entry
|
||
|
var dataEntry = {};
|
||
|
|
||
|
// Extract the selector
|
||
|
query.replace(/(@element)\s*(".*?"|'.*?'|.*?)\s*(and\s*\(|{)/g, function(string, atrule, selector, extra) {
|
||
|
// Strip outer quotes if present
|
||
|
selector = selector.replace(/^\s?['](.*)[']/, '$1');
|
||
|
selector = selector.replace(/^\s?["](.*)["]/, '$1');
|
||
|
|
||
|
dataEntry.selector = selector;
|
||
|
})
|
||
|
|
||
|
// Extract the conditions (measure, value, unit)
|
||
|
dataEntry.conditions = [];
|
||
|
query.replace(/and ?\( ?([^:]*) ?: ?([^)]*) ?\)/g, function(string, measure, value) {
|
||
|
// Separate value and unit if it's possible
|
||
|
var unit = null;
|
||
|
unit = value.replace(/^(\d*\.?\d+)(\D+)$/, '$2');
|
||
|
|
||
|
if (unit === value) {
|
||
|
unit = null;
|
||
|
}
|
||
|
value = value.replace(/^(\d*\.?\d+)\D+$/, '$1');
|
||
|
dataEntry.conditions.push({measure: measure, value: value, unit: unit});
|
||
|
});
|
||
|
|
||
|
// Extract the styles
|
||
|
query.replace(/{(.*)}/g, function(string, style) {
|
||
|
dataEntry.style = style;
|
||
|
});
|
||
|
|
||
|
parsed_queries.push(dataEntry);
|
||
|
});
|
||
|
|
||
|
return parsed_queries;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.register()
|
||
|
* Add a single object, or an array of objects to EQCSS.data
|
||
|
*
|
||
|
*/
|
||
|
EQCSS.register = function(queries) {
|
||
|
if (Object.prototype.toString.call(queries) === '[object Object]') {
|
||
|
EQCSS.data.push(queries);
|
||
|
EQCSS.apply();
|
||
|
}
|
||
|
|
||
|
if (Object.prototype.toString.call(queries) === '[object Array]') {
|
||
|
for (var i=0; i<queries.length; i++) {
|
||
|
EQCSS.data.push(queries[i]);
|
||
|
}
|
||
|
EQCSS.apply();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.process()
|
||
|
* Parse and Register queries with `EQCSS.data`
|
||
|
*/
|
||
|
|
||
|
EQCSS.process = function(code) {
|
||
|
var queries = EQCSS.parse(code)
|
||
|
return EQCSS.register(queries)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.apply()
|
||
|
* Called on load, on resize and manually on DOM update
|
||
|
* Enable the Element Queries in which the conditions are true
|
||
|
*/
|
||
|
EQCSS.apply = function() {
|
||
|
var elements; // Elements targeted by each query
|
||
|
var element_guid; // GUID for current element
|
||
|
var css_block; // CSS block corresponding to each targeted element
|
||
|
var element_guid_parent; // GUID for current element's parent
|
||
|
var element_guid_prev; // GUID for current element's previous sibling element
|
||
|
var element_guid_next; // GUID for current element's next sibling element
|
||
|
var css_code; // CSS code to write in each CSS block (one per targeted element)
|
||
|
var element_width, parent_width; // Computed widths
|
||
|
var element_height, parent_height;// Computed heights
|
||
|
var element_line_height; // Computed line-height
|
||
|
var test; // Query's condition test result
|
||
|
var computed_style; // Each targeted element's computed style
|
||
|
var parent_computed_style; // Each targeted element parent's computed style
|
||
|
|
||
|
// Loop on all element queries
|
||
|
for (var i = 0; i < EQCSS.data.length; i++) {
|
||
|
// Find all the elements targeted by the query
|
||
|
elements = document.querySelectorAll(EQCSS.data[i].selector);
|
||
|
|
||
|
// Loop on all the elements
|
||
|
for (var j = 0; j < elements.length; j++) {
|
||
|
// Create a guid for this element
|
||
|
// Pattern: 'EQCSS_{element-query-index}_{matched-element-index}'
|
||
|
element_guid = 'data-eqcss-' + i + '-' + j;
|
||
|
|
||
|
// Add this guid as an attribute to the element
|
||
|
elements[j].setAttribute(element_guid, '');
|
||
|
|
||
|
// Create a guid for the parent of this element
|
||
|
// Pattern: 'EQCSS_{element-query-index}_{matched-element-index}_parent'
|
||
|
element_guid_parent = 'data-eqcss-' + i + '-' + j + '-parent';
|
||
|
|
||
|
// Add this guid as an attribute to the element's parent (except if element is the root element)
|
||
|
if (elements[j] != document.documentElement) {
|
||
|
elements[j].parentNode.setAttribute(element_guid_parent, '');
|
||
|
}
|
||
|
|
||
|
// Get the CSS block associated to this element (or create one in the <HEAD> if it doesn't exist)
|
||
|
css_block = document.querySelector('#' + element_guid);
|
||
|
|
||
|
if (!css_block) {
|
||
|
css_block = document.createElement('style');
|
||
|
css_block.id = element_guid;
|
||
|
css_block.setAttribute('data-eqcss-read', 'true');
|
||
|
document.querySelector('head').appendChild(css_block);
|
||
|
}
|
||
|
css_block = document.querySelector('#' + element_guid);
|
||
|
|
||
|
// Reset the query test's result (first, we assume that the selector is matched)
|
||
|
test = true;
|
||
|
|
||
|
// Loop on the conditions
|
||
|
test_conditions: for (var k = 0; k < EQCSS.data[i].conditions.length; k++) {
|
||
|
// Reuse element and parent's computed style instead of computing it everywhere
|
||
|
computed_style = window.getComputedStyle(elements[j], null);
|
||
|
|
||
|
parent_computed_style = null;
|
||
|
|
||
|
if (elements[j] != document.documentElement) {
|
||
|
parent_computed_style = window.getComputedStyle(elements[j].parentNode, null);
|
||
|
}
|
||
|
|
||
|
// Do we have to reconvert the size in px at each call?
|
||
|
// This is true only for vw/vh/vmin/vmax
|
||
|
var recomputed = false;
|
||
|
|
||
|
// If the condition's unit is vw, convert current value in vw, in px
|
||
|
if (EQCSS.data[i].conditions[k].unit === 'vw') {
|
||
|
recomputed = true;
|
||
|
|
||
|
var value = parseInt(EQCSS.data[i].conditions[k].value);
|
||
|
EQCSS.data[i].conditions[k].recomputed_value = value * window.innerWidth / 100;
|
||
|
}
|
||
|
|
||
|
// If the condition's unit is vh, convert current value in vh, in px
|
||
|
else if (EQCSS.data[i].conditions[k].unit === 'vh') {
|
||
|
recomputed = true;
|
||
|
|
||
|
var value = parseInt(EQCSS.data[i].conditions[k].value);
|
||
|
EQCSS.data[i].conditions[k].recomputed_value = value * window.innerHeight / 100;
|
||
|
}
|
||
|
|
||
|
// If the condition's unit is vmin, convert current value in vmin, in px
|
||
|
else if (EQCSS.data[i].conditions[k].unit === 'vmin') {
|
||
|
recomputed = true;
|
||
|
|
||
|
var value = parseInt(EQCSS.data[i].conditions[k].value);
|
||
|
EQCSS.data[i].conditions[k].recomputed_value = value * Math.min(window.innerWidth, window.innerHeight) / 100;
|
||
|
}
|
||
|
|
||
|
// If the condition's unit is vmax, convert current value in vmax, in px
|
||
|
else if (EQCSS.data[i].conditions[k].unit === 'vmax') {
|
||
|
recomputed = true;
|
||
|
|
||
|
var value = parseInt(EQCSS.data[i].conditions[k].value);
|
||
|
EQCSS.data[i].conditions[k].recomputed_value = value * Math.max(window.innerWidth, window.innerHeight) / 100;
|
||
|
}
|
||
|
|
||
|
// If the condition's unit is set and is not px or %, convert it into pixels
|
||
|
else if (EQCSS.data[i].conditions[k].unit != null && EQCSS.data[i].conditions[k].unit != 'px' && EQCSS.data[i].conditions[k].unit != '%') {
|
||
|
// Create a hidden DIV, sibling of the current element (or its child, if the element is <html>)
|
||
|
// Set the given measure and unit to the DIV's width
|
||
|
// Measure the DIV's width in px
|
||
|
// Remove the DIV
|
||
|
var div = document.createElement('div');
|
||
|
|
||
|
div.style.visibility = 'hidden';
|
||
|
div.style.border = '1px solid red';
|
||
|
div.style.width = EQCSS.data[i].conditions[k].value + EQCSS.data[i].conditions[k].unit;
|
||
|
|
||
|
var position = elements[j];
|
||
|
if (elements[j] != document.documentElement) {
|
||
|
position = elements[j].parentNode;
|
||
|
}
|
||
|
|
||
|
position.appendChild(div);
|
||
|
EQCSS.data[i].conditions[k].value = parseInt(window.getComputedStyle(div, null).getPropertyValue('width'));
|
||
|
EQCSS.data[i].conditions[k].unit = 'px';
|
||
|
position.removeChild(div);
|
||
|
}
|
||
|
|
||
|
// Store the good value in final_value depending if the size is recomputed or not
|
||
|
var final_value = recomputed ? EQCSS.data[i].conditions[k].recomputed_value : parseInt(EQCSS.data[i].conditions[k].value);
|
||
|
|
||
|
// Check each condition for this query and this element
|
||
|
// If at least one condition is false, the element selector is not matched
|
||
|
switch (EQCSS.data[i].conditions[k].measure) {
|
||
|
case 'min-width':
|
||
|
// Min-width in px
|
||
|
if (recomputed === true || EQCSS.data[i].conditions[k].unit === 'px') {
|
||
|
element_width = parseInt(computed_style.getPropertyValue('width'));
|
||
|
if (!(element_width >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Min-width in %
|
||
|
if (EQCSS.data[i].conditions[k].unit === '%') {
|
||
|
element_width = parseInt(computed_style.getPropertyValue('width'));
|
||
|
parent_width = parseInt(parent_computed_style.getPropertyValue('width'));
|
||
|
if (!(parent_width / element_width <= 100 / final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'max-width':
|
||
|
// Max-width in px
|
||
|
if (recomputed === true || EQCSS.data[i].conditions[k].unit === 'px') {
|
||
|
element_width = parseInt(computed_style.getPropertyValue('width'));
|
||
|
if (!(element_width <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Max-width in %
|
||
|
if (EQCSS.data[i].conditions[k].unit === '%') {
|
||
|
element_width = parseInt(computed_style.getPropertyValue('width'));
|
||
|
parent_width = parseInt(parent_computed_style.getPropertyValue('width'));
|
||
|
if (!(parent_width / element_width >= 100 / final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'min-height':
|
||
|
// Min-height in px
|
||
|
if (recomputed === true || EQCSS.data[i].conditions[k].unit === 'px') {
|
||
|
element_height = parseInt(computed_style.getPropertyValue('height'));
|
||
|
if (!(element_height >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Min-height in %
|
||
|
if (EQCSS.data[i].conditions[k].unit === '%') {
|
||
|
element_height = parseInt(computed_style.getPropertyValue('height'));
|
||
|
parent_height = parseInt(parent_computed_style.getPropertyValue('height'));
|
||
|
if (!(parent_height / element_height <= 100 / final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'max-height':
|
||
|
// Max-height in px
|
||
|
if (recomputed === true || EQCSS.data[i].conditions[k].unit === 'px') {
|
||
|
element_height = parseInt(computed_style.getPropertyValue('height'));
|
||
|
if (!(element_height <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Max-height in %
|
||
|
if (EQCSS.data[i].conditions[k].unit === '%') {
|
||
|
element_height = parseInt(computed_style.getPropertyValue('height'));
|
||
|
parent_height = parseInt(parent_computed_style.getPropertyValue('height'));
|
||
|
if (!(parent_height / element_height >= 100 / final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Min-characters
|
||
|
case 'min-characters':
|
||
|
// form inputs
|
||
|
if (elements[j].value) {
|
||
|
if (!(elements[j].value.length >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
// blocks
|
||
|
else {
|
||
|
if (!(elements[j].textContent.length >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Max-characters
|
||
|
case 'max-characters':
|
||
|
// form inputs
|
||
|
if (elements[j].value) {
|
||
|
if (!(elements[j].value.length <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
// blocks
|
||
|
else {
|
||
|
if (!(elements[j].textContent.length <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Min-children
|
||
|
case 'min-children':
|
||
|
if (!(elements[j].children.length >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Max-children
|
||
|
case 'max-children':
|
||
|
if (!(elements[j].children.length <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Min-lines
|
||
|
case 'min-lines':
|
||
|
element_height =
|
||
|
parseInt(computed_style.getPropertyValue('height'))
|
||
|
- parseInt(computed_style.getPropertyValue('border-top-width'))
|
||
|
- parseInt(computed_style.getPropertyValue('border-bottom-width'))
|
||
|
- parseInt(computed_style.getPropertyValue('padding-top'))
|
||
|
- parseInt(computed_style.getPropertyValue('padding-bottom'));
|
||
|
|
||
|
element_line_height = computed_style.getPropertyValue('line-height');
|
||
|
if (element_line_height === 'normal') {
|
||
|
var element_font_size = parseInt(computed_style.getPropertyValue('font-size'));
|
||
|
element_line_height = element_font_size * 1.125;
|
||
|
} else {
|
||
|
element_line_height = parseInt(element_line_height);
|
||
|
}
|
||
|
|
||
|
if (!(element_height / element_line_height >= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Max-lines
|
||
|
case 'max-lines':
|
||
|
element_height =
|
||
|
parseInt(computed_style.getPropertyValue('height'))
|
||
|
- parseInt(computed_style.getPropertyValue('border-top-width'))
|
||
|
- parseInt(computed_style.getPropertyValue('border-bottom-width'))
|
||
|
- parseInt(computed_style.getPropertyValue('padding-top'))
|
||
|
- parseInt(computed_style.getPropertyValue('padding-bottom'));
|
||
|
|
||
|
element_line_height = computed_style.getPropertyValue('line-height');
|
||
|
if (element_line_height === 'normal') {
|
||
|
var element_font_size = parseInt(computed_style.getPropertyValue('font-size'));
|
||
|
element_line_height = element_font_size * 1.125;
|
||
|
} else {
|
||
|
element_line_height = parseInt(element_line_height);
|
||
|
}
|
||
|
|
||
|
if (!(element_height / element_line_height + 1 <= final_value)) {
|
||
|
test = false;
|
||
|
break test_conditions;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update CSS block:
|
||
|
// If all conditions are met: copy the CSS code from the query to the corresponding CSS block
|
||
|
if (test === true) {
|
||
|
// Get the CSS code to apply to the element
|
||
|
css_code = EQCSS.data[i].style;
|
||
|
|
||
|
// Replace eval('xyz') with the result of try{with(element){eval(xyz)}} in JS
|
||
|
css_code = css_code.replace(
|
||
|
/eval\( *((".*?")|('.*?')) *\)/g,
|
||
|
function(string, match) {
|
||
|
return EQCSS.tryWithEval(elements[j], match);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
// Replace '$this' or 'eq_this' with '[element_guid]'
|
||
|
css_code = css_code.replace(/(\$|eq_)this/gi, '[' + element_guid + ']');
|
||
|
|
||
|
// Replace '$parent' or 'eq_parent' with '[element_guid_parent]'
|
||
|
css_code = css_code.replace(/(\$|eq_)parent/gi, '[' + element_guid_parent + ']');
|
||
|
|
||
|
if(css_block.innerHTML != css_code){
|
||
|
css_block.innerHTML = css_code;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If condition is not met: empty the CSS block
|
||
|
else if(css_block.innerHTML != '') {
|
||
|
css_block.innerHTML = '';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Eval('') and $it
|
||
|
* (…yes with() was necessary, and eval() too!)
|
||
|
*/
|
||
|
EQCSS.tryWithEval = function(element, string) {
|
||
|
var $it = element;
|
||
|
var ret = '';
|
||
|
|
||
|
try {
|
||
|
with ($it) { ret = eval(string.slice(1, -1)) }
|
||
|
}
|
||
|
catch(e) {
|
||
|
ret = '';
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.reset
|
||
|
* Deletes parsed queries removes EQCSS-generated tags and attributes
|
||
|
* To reload EQCSS again after running EQCSS.reset() use EQCSS.load()
|
||
|
*/
|
||
|
EQCSS.reset = function() {
|
||
|
// Reset EQCSS.data, removing previously parsed queries
|
||
|
EQCSS.data = [];
|
||
|
|
||
|
// Remove EQCSS-generated style tags from head
|
||
|
var style_tag = document.querySelectorAll('head style[id^="data-eqcss-"]');
|
||
|
for (var i = 0; i < style_tag.length; i++) {
|
||
|
style_tag[i].parentNode.removeChild(style_tag[i]);
|
||
|
}
|
||
|
|
||
|
// Remove EQCSS-generated attributes from all tags
|
||
|
var tag = document.querySelectorAll('*');
|
||
|
|
||
|
// For each tag in the document
|
||
|
for (var j = 0; j < tag.length; j++) {
|
||
|
// Loop through all attributes
|
||
|
for (var k = 0; k < tag[j].attributes.length; k++) {
|
||
|
// If an attribute begins with 'data-eqcss-'
|
||
|
if (tag[j].attributes[k].name.indexOf('data-eqcss-') === 0) {
|
||
|
// Remove the attribute from the tag
|
||
|
tag[j].removeAttribute(tag[j].attributes[k].name)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 'DOM Ready' cross-browser polyfill / Diego Perini / MIT license
|
||
|
* Forked from: https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js
|
||
|
*/
|
||
|
EQCSS.domReady = function(fn) {
|
||
|
var done = false;
|
||
|
var top = true;
|
||
|
var doc = window.document;
|
||
|
var root = doc.documentElement;
|
||
|
var modern = !~navigator.userAgent.indexOf('MSIE 8');
|
||
|
var add = modern ? 'addEventListener' : 'attachEvent';
|
||
|
var rem = modern ? 'removeEventListener' : 'detachEvent';
|
||
|
var pre = modern ? '' : 'on';
|
||
|
var init = function(e) {
|
||
|
if (e.type === 'readystatechange' && doc.readyState !== 'complete') return;
|
||
|
(e.type === 'load' ? window : doc)[rem](pre + e.type, init, false);
|
||
|
if (!done && (done = true)) fn.call(window, e.type || e);
|
||
|
},
|
||
|
poll = function() {
|
||
|
try {
|
||
|
root.doScroll('left');
|
||
|
}
|
||
|
catch(e) {
|
||
|
setTimeout(poll, 50);
|
||
|
return;
|
||
|
}
|
||
|
init('poll');
|
||
|
};
|
||
|
|
||
|
if (doc.readyState === 'complete') {
|
||
|
fn.call(window, 'lazy');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!modern && root.doScroll) {
|
||
|
try {
|
||
|
top = !window.frameElement;
|
||
|
}
|
||
|
catch(e) {}
|
||
|
if (top) poll();
|
||
|
}
|
||
|
doc[add](pre + 'DOMContentLoaded', init, false);
|
||
|
doc[add](pre + 'readystatechange', init, false);
|
||
|
window[add](pre + 'load', init, false);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* EQCSS.throttle
|
||
|
* Ensures EQCSS.apply() is not called more than once every (EQCSS_timeout)ms
|
||
|
*/
|
||
|
var EQCSS_throttle_available = true;
|
||
|
var EQCSS_throttle_queued = false;
|
||
|
var EQCSS_mouse_down = false;
|
||
|
var EQCSS_timeout = 200;
|
||
|
|
||
|
EQCSS.throttle = function() {
|
||
|
/* if (EQCSS_throttle_available) {*/
|
||
|
EQCSS.apply();
|
||
|
/*EQCSS_throttle_available = false;
|
||
|
|
||
|
setTimeout(function() {
|
||
|
EQCSS_throttle_available = true;
|
||
|
if (EQCSS_throttle_queued) {
|
||
|
EQCSS_throttle_queued = false;
|
||
|
EQCSS.apply();
|
||
|
}
|
||
|
}, EQCSS_timeout);
|
||
|
} else {
|
||
|
EQCSS_throttle_queued = true;
|
||
|
}*/
|
||
|
}
|
||
|
|
||
|
// Call load (and apply, indirectly) on page load
|
||
|
EQCSS.domReady(function() {
|
||
|
EQCSS.load();
|
||
|
EQCSS.throttle();
|
||
|
});
|
||
|
|
||
|
// On resize, click, call EQCSS.throttle.
|
||
|
window.addEventListener('resize', EQCSS.throttle);
|
||
|
window.addEventListener('click', EQCSS.throttle);
|
||
|
|
||
|
// Debug: here's a shortcut for console.log
|
||
|
function l(a) { console.log(a) }
|
||
|
|
||
|
return EQCSS;
|
||
|
}));
|