?
Current File : /home/cideo/sainchargny/wp-content/themes/astra/skrollr.stylesheets.js
/*!
 * skrollr stylesheets.
 * Parses stylesheets and searches for skrollr keyframe declarations.
 * Converts them to data-attributes.
 * Doesn't expose any globals.
 */
(function(window, document, undefined) {
	'use strict';

	var content;
	var contents = [];

	//Finds the declaration of an animation block.
	var rxAnimation = /@-skrollr-keyframes\s+([\w-]+)/g;

	//Finds the block of keyframes inside an animation block.
	//http://regexpal.com/ saves your ass with stuff like this.
	var rxKeyframes = /\s*\{\s*((?:[^{]+\{[^}]*\}\s*)+?)\s*\}/g;

	//Gets a single keyframe and the properties inside.
	var rxSingleKeyframe = /([\w\-]+)\s*\{([^}]+)\}/g;

	//Optional keyframe name prefix to work around SASS (>3.4) issues
	var keyframeNameOptionalPrefix = 'skrollr-';

	//Finds usages of the animation.
	var rxAnimationUsage = /-skrollr-animation-name\s*:\s*([\w-]+)/g;

	//Finds usages of attribute setters.
	var rxAttributeSetter = /-skrollr-(anchor-target|smooth-scrolling|emit-events|menu-offset)\s*:\s*['"]([^'"]+)['"]/g;

	var fetchRemote = function(url) {
		var xhr = new XMLHttpRequest();

		/*
		 * Yes, these are SYNCHRONOUS requests.
		 * Simply because skrollr stylesheets should run while the page is loaded.
		 * Get over it.
		 */
		try {
			xhr.open('GET', url, false);
			xhr.send(null);
		} catch (e) {
			//Fallback to XDomainRequest if available
			if (window.XDomainRequest) {
				xhr = new XDomainRequest();
				xhr.open('GET', url, false);
				xhr.send(null);
			}
		}

		return xhr.responseText;
	};

	//"main"
	var kickstart = function(stylesheets) {
		//Iterate over all stylesheets, embedded and remote.
		for(var stylesheetIndex = 0; stylesheetIndex < stylesheets.length; stylesheetIndex++) {
			var sheet = stylesheets[stylesheetIndex];

			if(sheet.tagName === 'LINK') {
				if(sheet.getAttribute('data-skrollr-stylesheet') === null) {
					continue;
				}

				//Test media attribute if matchMedia available.
				if(window.matchMedia) {
					var media = sheet.getAttribute('media');

					if(media && !matchMedia(media).matches) {
						continue;
					}
				}

				//Remote stylesheet, fetch it (synchrnonous).
				content = fetchRemote(sheet.href);
			} else {
				//Embedded stylesheet, grab the node content.
				content = sheet.textContent || sheet.innerText || sheet.innerHTML;
			}

			if(content) {
				contents.push(content);
			}
		}

		//We take the stylesheets in reverse order.
		//This is needed to ensure correct order of stylesheets and inline styles.
		contents.reverse();

		var animations = {};
		var selectors = [];
		var attributes = [];

		//Now parse all stylesheets.
		for(var contentIndex = 0; contentIndex < contents.length; contentIndex++) {
			content = contents[contentIndex];

			parseAnimationDeclarations(content, animations);
			parseAnimationUsage(content, selectors);
			parseAttributeSetters(content, attributes);
		}

		applyKeyframeAttributes(animations, selectors);
		applyAttributeSetters(attributes);
	};

	//Finds animation declarations and puts them into the output map.
	var parseAnimationDeclarations = function(input, output) {
		rxAnimation.lastIndex = 0;

		var animation;
		var rawKeyframes;
		var keyframe;
		var curAnimation;

		while((animation = rxAnimation.exec(input)) !== null) {
			//Grab the keyframes inside this animation.
			rxKeyframes.lastIndex = rxAnimation.lastIndex;
			rawKeyframes = rxKeyframes.exec(input);

			//Grab the single keyframes with their CSS properties.
			rxSingleKeyframe.lastIndex = 0;

			//Save the animation in an object using it's name as key.
			curAnimation = output[animation[1]] = {};

			while((keyframe = rxSingleKeyframe.exec(rawKeyframes[1])) !== null) {
				//Put all keyframes inside the animation using the keyframe (like botttom-top, or 100) as key
				//and the properties as value (just the raw string, newline stripped).
				curAnimation[keyframe[1]] = keyframe[2].replace(/[\n\r\t]/g, '');
			}
		}
	};

	//Extracts the selector of the given block by walking backwards to the start of the block.
	var extractSelector = function(input, startIndex) {
		var begin;
		var end = startIndex;

		//First find the curly bracket that opens this block.
		while(end-- && input.charAt(end) !== '{') {}

		//The end is now fixed to the right of the selector.
		//Now start there to find the begin of the selector.
		begin = end;

		//Now walk farther backwards until we grabbed the whole selector.
		//This either ends at beginning of string or at end of next block.
		while(begin-- && input.charAt(begin - 1) !== '}') {}

		//Return the cleaned selector.
		return input.substring(begin, end).replace(/[\n\r\t]/g, '');
	};

	//Finds usage of animations and puts the selectors into the output array.
	var parseAnimationUsage = function(input, output) {
		var match;
		var selector;

		rxAnimationUsage.lastIndex = 0;

		while((match = rxAnimationUsage.exec(input)) !== null) {
			//Extract the selector of the block we found the animation in.
			selector = extractSelector(input, rxAnimationUsage.lastIndex);

			//Associate this selector with the animation name.
			output.push([selector, match[1]]);
		}
	};

	//Finds usage of attribute setters and puts the selector and attribute data into the output array.
	var parseAttributeSetters = function(input, output) {
		var match;
		var selector;

		rxAttributeSetter.lastIndex = 0;

		while((match = rxAttributeSetter.exec(input)) !== null) {
			//Extract the selector of the block we found the animation in.
			selector = extractSelector(input, rxAttributeSetter.lastIndex);

			//Associate this selector with the attribute name and value.
			output.push([selector, match[1], match[2]]);
		}
	};

	//Applies the keyframes (as data-attributes) to the elements.
	var applyKeyframeAttributes = function(animations, selectors) {
		var elements;
		var keyframes;
		var keyframeName;
		var cleanKeyframeName;
		var elementIndex;
		var attributeName;
		var attributeValue;
		var curElement;

		for(var selectorIndex = 0; selectorIndex < selectors.length; selectorIndex++) {
			elements = document.querySelectorAll(selectors[selectorIndex][0]);

			if(!elements) {
				continue;
			}

			keyframes = animations[selectors[selectorIndex][1]];

			for(keyframeName in keyframes) {
				if(keyframeName.indexOf(keyframeNameOptionalPrefix) === 0) {
					cleanKeyframeName = keyframeName.substring(keyframeNameOptionalPrefix.length);
				} else {
					cleanKeyframeName = keyframeName;
				}

				for(elementIndex = 0; elementIndex < elements.length; elementIndex++) {
					curElement = elements[elementIndex];
					attributeName = 'data-' + cleanKeyframeName;
					attributeValue = keyframes[keyframeName];

					//If the element already has this keyframe inline, give the inline one precedence by putting it on the right side.
					//The inline one may actually be the result of the keyframes from another stylesheet.
					//Since we reversed the order of the stylesheets, everything comes together correctly here.
					if(curElement.hasAttribute(attributeName)) {
						attributeValue += curElement.getAttribute(attributeName);
					}

					curElement.setAttribute(attributeName, attributeValue);
				}
			}
		}
	};

	//Applies the keyframes (as data-attributes) to the elements.
	var applyAttributeSetters = function(selectors) {
		var curSelector;
		var elements;
		var attributeName;
		var attributeValue;
		var elementIndex;

		for(var selectorIndex = 0; selectorIndex < selectors.length; selectorIndex++) {
			curSelector = selectors[selectorIndex];
			elements = document.querySelectorAll(curSelector[0]);
			attributeName = 'data-' + curSelector[1];
			attributeValue = curSelector[2];

			if(!elements) {
				continue;
			}

			for(elementIndex = 0; elementIndex < elements.length; elementIndex++) {
				elements[elementIndex].setAttribute(attributeName, attributeValue);
			}
		}
	};

	kickstart(document.querySelectorAll('link, style'));
}(window, document));