<commit_before>// A library to make it easier to use the JavaScript Fullscreen API.
(function(window, document, iframe) {
	'use strict';

	var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
	var iOS7 = /i(Pad|Phone|Pod)/.test(navigator.userAgent) && parseInt(navigator.userAgent.replace(/^.*OS (\d+)_(\d+).*$/, '$1.$2'), 10) >= 7;

	var fn = (function() {
		var testElement = document.createElement('video');
		var browserProperties = {
			request: ['requestFullscreen', 'webkitRequestFullscreen', 'webkitRequestFullScreen', 'mozRequestFullScreen', 'msRequestFullscreen'],
			exit: ['exitFullscreen', 'webkitCancelFullScreen', 'webkitExitFullscreen', 'mozCancelFullScreen', 'msExitFullscreen'],
			enabled: ['fullscreenEnabled', 'webkitFullscreenEnabled', 'mozFullScreenEnabled', 'msFullscreenEnabled'],
			element: ['fullscreenElement', 'webkitFullscreenElement', 'webkitCurrentFullScreenElement', 'mozFullScreenElement', 'msFullscreenElement'],
			change: ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'],
			error: ['fullscreenerror', 'webkitfullscreenerror', 'mozfullscreenerror', 'MSFullscreenError']
		};

		var properties = {};

		// Loop thorugh each property/event/function and find the ones that work
		// in this browser.
		for (var prop in browserProperties) {
			for (var i = 0, length = browserProperties[prop].length; i < length; i++) {
				if (browserProperties[prop][i] in testElement || browserProperties[prop][i] in document || 'on' + browserProperties[prop][i] in document) {
					properties[prop] = browserProperties[prop][i];
					break;
				}
			}
		}

		return properties;
	}());

	// Find a child video in the element passed.
	function _getVideo(element) {
		var videoElement = null;

		if (element.tagName === 'VIDEO') {
			videoElement = element;
		}
		else {
			var videos = element.getElementsByTagName('video');
			if (videos[0]) {
				videoElement = videos[0];
			}
		}

		return videoElement;
	}

	var lastVideoElement = null;
	var hasControls = null;
	var emptyFunction = function() {};
	var elements = [];
	var chromeAndroid = navigator.userAgent.indexOf('Android') > -1 && navigator.userAgent.indexOf('Chrome') > -1;

	// Attempt to put a child video into full screen using webkitEnterFullscreen.
	// The metadata must be loaded in order for it to work, so load it automatically
	// if it isn't already.
	function videoEnterFullscreen(element) {
		var videoElement = _getVideo(element);

		if (videoElement && videoElement.webkitEnterFullscreen) {
			try {
				if (videoElement.readyState < videoElement.HAVE_METADATA) {
					videoElement.addEventListener('loadedmetadata', function onMetadataLoaded() {
						videoElement.removeEventListener('loadedmetadata', onMetadataLoaded, false);
						videoElement.webkitEnterFullscreen();
						hasControls = !!videoElement.getAttribute('controls');
					}, false);
					videoElement.load();
				}
				else {
					videoElement.webkitEnterFullscreen();
					hasControls = !!videoElement.getAttribute('controls');
				}

				lastVideoElement = videoElement;
			}
			catch (err) {
				return callOnError('not_supported', element);
			}

			return true;
		}

		return callOnError(fn.request === undefined ? 'not_supported' : 'not_enabled', element);
	}

	// There is a bug in older versions of WebKit that will fire `webkitfullscreenchange` twice when
	// entering full screen from inside an iframe, and won't fire it when exiting. We can listen for
	// a resize event once we enter to tell when it returns to normal size (and thus has exited full
	// screen). See the [Safari bug](rdar://11927884).
	function resizeExitHack() {
		if (!bigscreen.element) {
			callOnExit();
			removeWindowResizeHack();
		}
	}

	// Add the listener for the resize hack, but only when inside an iframe in WebKit.
	function addWindowResizeHack() {
		if (iframe && fn.change === 'webkitfullscreenchange') {
			window.addEventListener('resize', resizeExitHack, false);
		}
	}

	function removeWindowResizeHack() {
		if (iframe && fn.change === 'webkitfullscreenchange') {
			window.removeEventListener('resize', resizeExitHack, false);
		}
	}

	var callOnEnter = function(actualElement) {
		// Return if the element entering has actually entered already. In older WebKit versions the
		// browser will fire 2 `webkitfullscreenchange` events when entering full screen from inside an
		// iframe. This is the result of the same bug as the resizeExitHack.
		var lastElement = elements[elements.length - 1];
		if ((actualElement === lastElement.element || actualElement === lastVideoElement) && lastElement.hasEntered) {
			return;
		}

		// If the element is a video, store it here for the enabled check.
		if (actualElement.tagName === 'VIDEO') {
			lastVideoElement = actualElement;
		}

		// Call the global enter handler only if this is the first element.
		if (elements.length === 1) {
			bigscreen.onenter(bigscreen.element);
		}

		// Call the stored callback for the request call and record that we did so we don't do it
		// again if there is a duplicate call (see above).
		lastElement.enter.call(lastElement.element, actualElement || lastElement.element);
		lastElement.hasEntered = true;
	};

	var callOnExit = function() {
		// Fix a bug present in some versions of WebKit that will show the native controls when
		// exiting, even if they were not showing before. In iOS 7, this actually causes the
		// native controls to show up, although once they hide they stay hidden.
		if (lastVideoElement && !hasControls && !iOS7) {
			lastVideoElement.setAttribute('controls', 'controls');
			lastVideoElement.removeAttribute('controls');
		}

		lastVideoElement = null;
		hasControls = null;

		var element = elements.pop();

		// Check to make sure that the element exists. This function will get called a second
		// time from the iframe resize hack.
		if (element) {
			element.exit.call(element.element);

			// When the browser has fully exited full screen, make sure to loop
			// through and call the rest of the callbacks and then the global exit.
			if (!bigscreen.element) {
				elements.forEach(function(element) {
					element.exit.call(element.element);
				});
				elements = [];

				bigscreen.onexit();
			}
		}
	};

	// Make a callback to the error handlers and clear the element from the stack when
	// an error occurs.
	var callOnError = function(reason, element) {
		if (elements.length > 0) {
			var obj = elements.pop();
			element = element || obj.element;

			obj.error.call(element, reason);
			bigscreen.onerror(element, reason);
		}
	};

	var bigscreen = {
		// ### request
		// The meat of BigScreen is here. Run through a bunch of checks to try to get
		// something into full screen that's a child of the element passed in.
		request: function(element, enterCallback, exitCallback, errorCallback) {
			element = element || document.body;

			elements.push({
				element: element,
				enter: enterCallback || emptyFunction,
				exit: exitCallback || emptyFunction,
				error: errorCallback || emptyFunction
			});

			// iOS only supports webkitEnterFullscreen on videos, so try that.
			// Browsers that don't support full screen at all will also go through this,
			// but they will fire an error.
			if (fn.request === undefined) {
				return videoEnterFullscreen(element);
			}

			// `document.fullscreenEnabled` defined, but is `false`, so try a video if there is one.
			if (iframe && document[fn.enabled] === false) {
				return videoEnterFullscreen(element);
			}

			// Chrome on Android reports that fullscreen is enabled, but it isn't really.
			if (chromeAndroid) {
				return videoEnterFullscreen(element);
			}

			// If we're in an iframe, it needs to have the `allowfullscreen` attribute in order for element full screen
			// to work. Safari 5.1 supports element full screen, but doesn't have `document.webkitFullScreenEnabled`,
			// so the only way to tell if it will work is to just try it.
			if (iframe && fn.enabled === undefined) {
				fn.enabled = 'webkitFullscreenEnabled';

				element[fn.request]();

				setTimeout(function() {
					// It didn't work, so set `webkitFullscreenEnabled` to false so we don't
					// have to try again next time. Then try to fall back to video full screen.
					if (!document[fn.element]) {
						document[fn.enabled] = false;
						videoEnterFullscreen(element);
					}
					// It worked! set `webkitFullscreenEnabled` so we know next time.
					else {
						document[fn.enabled] = true;
					}
				}, 250);

				return;
			}

			try {
				// Safari 5.1 doesn't actually support asking for keyboard support,
				// so don't try it. The alternative is to add another `setTimeout`
				// below, which isn't nice.
				if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
					element[fn.request]();
				}
				else {
					element[fn.request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
				}

				// If there's no element after 100ms, it didn't work. This check is for Safari 5.1
				// which fails to fire a `webkitfullscreenerror` if the request wasn't from a user
				// action.
				setTimeout(function() {
					if (!document[fn.element]) {
						callOnError(iframe ? 'not_enabled' : 'not_allowed', element);
					}
				}, 100);
			}
			catch (err) {
				callOnError('not_enabled', element);
			}
		},
		// ### exit
		// Pops the last full screen element off the stack.
		exit: function() {
			// Remove the resize hack here if exit is called manually, so it doesn't fire twice.
			removeWindowResizeHack();
			document[fn.exit]();
		},
		// ### toggle
		// Shortcut function if you only plan on putting one element into full screen.
		toggle: function(element, enterCallback, exitCallback, errorCallback) {
			if (bigscreen.element) {
				bigscreen.exit();
			}
			else {
				bigscreen.request(element, enterCallback, exitCallback, errorCallback);
			}
		},

		// ### videoEnabled
		// Mobile Safari and earlier versions of desktop Safari support sending a `<video>` into full screen,
		// even if the `allowfullscreen` attribute isn't present on the iframe. Checks can't be performed to
		// verify full screen capabilities unless we know about that element, and it has loaded its metadata.
		videoEnabled: function(element) {
			if (bigscreen.enabled) {
				return true;
			}

			element = element || document.body;
			var video = _getVideo(element);

			if (!video || video.webkitSupportsFullscreen === undefined) {
				return false;
			}

			return video.readyState < video.HAVE_METADATA ? 'maybe' : video.webkitSupportsFullscreen;
		},

		// ### onenter, onexit, onchange, onerror
		// Populate the global handlers with empty functions.
		onenter: emptyFunction,
		onexit: emptyFunction,
		onchange: emptyFunction,
		onerror: emptyFunction
	};

	// Define the two properties `element` and `enabled` with getters.
	try {
		Object.defineProperties(bigscreen, {
			// ### element
			// Get the current element that is displaying full screen.
			element: {
				enumerable: true,
				get: function() {
					if (lastVideoElement && lastVideoElement.webkitDisplayingFullscreen) {
						return lastVideoElement;
					}

					return document[fn.element] || null;
				}
			},
			// ### enabled
			// Check if element full screen is supported.
			enabled: {
				enumerable: true,
				get: function() {
					// Safari 5.1 supports full screen, but doesn't have a fullScreenEnabled property,
					// but it should work if not in an iframe. If it doesn't work when tried for the
					// first time, we'll set this to `false` then.
					if (fn.exit === 'webkitCancelFullScreen' && !iframe) {
						return true;
					}

					// Chrome on Android reports that fullscreen is enabled, but it isn't really.
					if (chromeAndroid) {
						return false;
					}

					return document[fn.enabled] || false;
				}
			}
		});
	}
	// If the define fails, set them to `null` and `false`, respectively.
	catch (err) {
		bigscreen.element = null;
		bigscreen.enabled = false;
	}

	// If there is a valid `fullscreenchange` event, set up the listener for it.
	if (fn.change) {
		document.addEventListener(fn.change, function onFullscreenChange(event) {
			bigscreen.onchange(bigscreen.element);

			if (bigscreen.element) {
				// This should be treated an exit if the element that is in full screen
				// is the previous element in our stack.
				var previousElement = elements[elements.length - 2];
				if (previousElement && previousElement.element === bigscreen.element) {
					callOnExit();
				}
				else {
					callOnEnter(bigscreen.element);
					addWindowResizeHack();
				}
			}
			else {
				callOnExit();
			}
		}, false);
	}

	// Listen for the video-only fullscreen events. Only applies to mobile browsers.
	// Desktop Safari and Chrome will fire the normal `fullscreenchange` event instead.
	// Use the capture phase because that seems to be the only way to get them.
	document.addEventListener('webkitbeginfullscreen', function onBeginFullscreen(event) {
		elements.push({
			element: event.srcElement,
			enter: emptyFunction,
			exit: emptyFunction,
			error: emptyFunction
		});

		bigscreen.onchange(event.srcElement);
		callOnEnter(event.srcElement);
	}, true);

	document.addEventListener('webkitendfullscreen', function onEndFullscreen(event) {
		bigscreen.onchange(event.srcElement);
		callOnExit(event.srcElement);
	}, true);

	// If there is a valid `fullscreenerror` event, set up the listener for it.
	if (fn.error) {
		document.addEventListener(fn.error, function onFullscreenError(event) {
			callOnError('not_allowed');
		}, false);
	}

	// Externalize the BigScreen object. Use array notation to play nicer with
	// Closure Compiler.
	window['BigScreen'] = bigscreen;

}(window, document, self !== top));
<commit_msg>Fix IE 11 fullscreen change bug<commit_after>// A library to make it easier to use the JavaScript Fullscreen API.
(function(window, document, iframe) {
	'use strict';

	var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
	var iOS7 = /i(Pad|Phone|Pod)/.test(navigator.userAgent) && parseInt(navigator.userAgent.replace(/^.*OS (\d+)_(\d+).*$/, '$1.$2'), 10) >= 7;

	var fn = (function() {
		var testElement = document.createElement('video');
		var browserProperties = {
			request: ['requestFullscreen', 'webkitRequestFullscreen', 'webkitRequestFullScreen', 'mozRequestFullScreen', 'msRequestFullscreen'],
			exit: ['exitFullscreen', 'webkitCancelFullScreen', 'webkitExitFullscreen', 'mozCancelFullScreen', 'msExitFullscreen'],
			enabled: ['fullscreenEnabled', 'webkitFullscreenEnabled', 'mozFullScreenEnabled', 'msFullscreenEnabled'],
			element: ['fullscreenElement', 'webkitFullscreenElement', 'webkitCurrentFullScreenElement', 'mozFullScreenElement', 'msFullscreenElement'],
			change: ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'],
			error: ['fullscreenerror', 'webkitfullscreenerror', 'mozfullscreenerror', 'MSFullscreenError']
		};

		var properties = {};

		// Loop thorugh each property/event/function and find the ones that work
		// in this browser.
		for (var prop in browserProperties) {
			for (var i = 0, length = browserProperties[prop].length; i < length; i++) {
				if (browserProperties[prop][i] in testElement || browserProperties[prop][i] in document || 'on' + browserProperties[prop][i].toLowerCase() in document) {
					properties[prop] = browserProperties[prop][i];
					break;
				}
			}
		}

		return properties;
	}());

	// Find a child video in the element passed.
	function _getVideo(element) {
		var videoElement = null;

		if (element.tagName === 'VIDEO') {
			videoElement = element;
		}
		else {
			var videos = element.getElementsByTagName('video');
			if (videos[0]) {
				videoElement = videos[0];
			}
		}

		return videoElement;
	}

	var lastVideoElement = null;
	var hasControls = null;
	var emptyFunction = function() {};
	var elements = [];
	var chromeAndroid = navigator.userAgent.indexOf('Android') > -1 && navigator.userAgent.indexOf('Chrome') > -1;

	// Attempt to put a child video into full screen using webkitEnterFullscreen.
	// The metadata must be loaded in order for it to work, so load it automatically
	// if it isn't already.
	function videoEnterFullscreen(element) {
		var videoElement = _getVideo(element);

		if (videoElement && videoElement.webkitEnterFullscreen) {
			try {
				if (videoElement.readyState < videoElement.HAVE_METADATA) {
					videoElement.addEventListener('loadedmetadata', function onMetadataLoaded() {
						videoElement.removeEventListener('loadedmetadata', onMetadataLoaded, false);
						videoElement.webkitEnterFullscreen();
						hasControls = !!videoElement.getAttribute('controls');
					}, false);
					videoElement.load();
				}
				else {
					videoElement.webkitEnterFullscreen();
					hasControls = !!videoElement.getAttribute('controls');
				}

				lastVideoElement = videoElement;
			}
			catch (err) {
				return callOnError('not_supported', element);
			}

			return true;
		}

		return callOnError(fn.request === undefined ? 'not_supported' : 'not_enabled', element);
	}

	// There is a bug in older versions of WebKit that will fire `webkitfullscreenchange` twice when
	// entering full screen from inside an iframe, and won't fire it when exiting. We can listen for
	// a resize event once we enter to tell when it returns to normal size (and thus has exited full
	// screen). See the [Safari bug](rdar://11927884).
	function resizeExitHack() {
		if (!bigscreen.element) {
			callOnExit();
			removeWindowResizeHack();
		}
	}

	// Add the listener for the resize hack, but only when inside an iframe in WebKit.
	function addWindowResizeHack() {
		if (iframe && fn.change === 'webkitfullscreenchange') {
			window.addEventListener('resize', resizeExitHack, false);
		}
	}

	function removeWindowResizeHack() {
		if (iframe && fn.change === 'webkitfullscreenchange') {
			window.removeEventListener('resize', resizeExitHack, false);
		}
	}

	var callOnEnter = function(actualElement) {
		// Return if the element entering has actually entered already. In older WebKit versions the
		// browser will fire 2 `webkitfullscreenchange` events when entering full screen from inside an
		// iframe. This is the result of the same bug as the resizeExitHack.
		var lastElement = elements[elements.length - 1];
		if ((actualElement === lastElement.element || actualElement === lastVideoElement) && lastElement.hasEntered) {
			return;
		}

		// If the element is a video, store it here for the enabled check.
		if (actualElement.tagName === 'VIDEO') {
			lastVideoElement = actualElement;
		}

		// Call the global enter handler only if this is the first element.
		if (elements.length === 1) {
			bigscreen.onenter(bigscreen.element);
		}

		// Call the stored callback for the request call and record that we did so we don't do it
		// again if there is a duplicate call (see above).
		lastElement.enter.call(lastElement.element, actualElement || lastElement.element);
		lastElement.hasEntered = true;
	};

	var callOnExit = function() {
		// Fix a bug present in some versions of WebKit that will show the native controls when
		// exiting, even if they were not showing before. In iOS 7, this actually causes the
		// native controls to show up, although once they hide they stay hidden.
		if (lastVideoElement && !hasControls && !iOS7) {
			lastVideoElement.setAttribute('controls', 'controls');
			lastVideoElement.removeAttribute('controls');
		}

		lastVideoElement = null;
		hasControls = null;

		var element = elements.pop();

		// Check to make sure that the element exists. This function will get called a second
		// time from the iframe resize hack.
		if (element) {
			element.exit.call(element.element);

			// When the browser has fully exited full screen, make sure to loop
			// through and call the rest of the callbacks and then the global exit.
			if (!bigscreen.element) {
				elements.forEach(function(element) {
					element.exit.call(element.element);
				});
				elements = [];

				bigscreen.onexit();
			}
		}
	};

	// Make a callback to the error handlers and clear the element from the stack when
	// an error occurs.
	var callOnError = function(reason, element) {
		if (elements.length > 0) {
			var obj = elements.pop();
			element = element || obj.element;

			obj.error.call(element, reason);
			bigscreen.onerror(element, reason);
		}
	};

	var bigscreen = {
		// ### request
		// The meat of BigScreen is here. Run through a bunch of checks to try to get
		// something into full screen that's a child of the element passed in.
		request: function(element, enterCallback, exitCallback, errorCallback) {
			element = element || document.body;

			elements.push({
				element: element,
				enter: enterCallback || emptyFunction,
				exit: exitCallback || emptyFunction,
				error: errorCallback || emptyFunction
			});

			// iOS only supports webkitEnterFullscreen on videos, so try that.
			// Browsers that don't support full screen at all will also go through this,
			// but they will fire an error.
			if (fn.request === undefined) {
				return videoEnterFullscreen(element);
			}

			// `document.fullscreenEnabled` defined, but is `false`, so try a video if there is one.
			if (iframe && document[fn.enabled] === false) {
				return videoEnterFullscreen(element);
			}

			// Chrome on Android reports that fullscreen is enabled, but it isn't really.
			if (chromeAndroid) {
				return videoEnterFullscreen(element);
			}

			// If we're in an iframe, it needs to have the `allowfullscreen` attribute in order for element full screen
			// to work. Safari 5.1 supports element full screen, but doesn't have `document.webkitFullScreenEnabled`,
			// so the only way to tell if it will work is to just try it.
			if (iframe && fn.enabled === undefined) {
				fn.enabled = 'webkitFullscreenEnabled';

				element[fn.request]();

				setTimeout(function() {
					// It didn't work, so set `webkitFullscreenEnabled` to false so we don't
					// have to try again next time. Then try to fall back to video full screen.
					if (!document[fn.element]) {
						document[fn.enabled] = false;
						videoEnterFullscreen(element);
					}
					// It worked! set `webkitFullscreenEnabled` so we know next time.
					else {
						document[fn.enabled] = true;
					}
				}, 250);

				return;
			}

			try {
				// Safari 5.1 doesn't actually support asking for keyboard support,
				// so don't try it. The alternative is to add another `setTimeout`
				// below, which isn't nice.
				if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
					element[fn.request]();
				}
				else {
					element[fn.request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
				}

				// If there's no element after 100ms, it didn't work. This check is for Safari 5.1
				// which fails to fire a `webkitfullscreenerror` if the request wasn't from a user
				// action.
				setTimeout(function() {
					if (!document[fn.element]) {
						callOnError(iframe ? 'not_enabled' : 'not_allowed', element);
					}
				}, 100);
			}
			catch (err) {
				callOnError('not_enabled', element);
			}
		},
		// ### exit
		// Pops the last full screen element off the stack.
		exit: function() {
			// Remove the resize hack here if exit is called manually, so it doesn't fire twice.
			removeWindowResizeHack();
			document[fn.exit]();
		},
		// ### toggle
		// Shortcut function if you only plan on putting one element into full screen.
		toggle: function(element, enterCallback, exitCallback, errorCallback) {
			if (bigscreen.element) {
				bigscreen.exit();
			}
			else {
				bigscreen.request(element, enterCallback, exitCallback, errorCallback);
			}
		},

		// ### videoEnabled
		// Mobile Safari and earlier versions of desktop Safari support sending a `<video>` into full screen,
		// even if the `allowfullscreen` attribute isn't present on the iframe. Checks can't be performed to
		// verify full screen capabilities unless we know about that element, and it has loaded its metadata.
		videoEnabled: function(element) {
			if (bigscreen.enabled) {
				return true;
			}

			element = element || document.body;
			var video = _getVideo(element);

			if (!video || video.webkitSupportsFullscreen === undefined) {
				return false;
			}

			return video.readyState < video.HAVE_METADATA ? 'maybe' : video.webkitSupportsFullscreen;
		},

		// ### onenter, onexit, onchange, onerror
		// Populate the global handlers with empty functions.
		onenter: emptyFunction,
		onexit: emptyFunction,
		onchange: emptyFunction,
		onerror: emptyFunction
	};

	// Define the two properties `element` and `enabled` with getters.
	try {
		Object.defineProperties(bigscreen, {
			// ### element
			// Get the current element that is displaying full screen.
			element: {
				enumerable: true,
				get: function() {
					if (lastVideoElement && lastVideoElement.webkitDisplayingFullscreen) {
						return lastVideoElement;
					}

					return document[fn.element] || null;
				}
			},
			// ### enabled
			// Check if element full screen is supported.
			enabled: {
				enumerable: true,
				get: function() {
					// Safari 5.1 supports full screen, but doesn't have a fullScreenEnabled property,
					// but it should work if not in an iframe. If it doesn't work when tried for the
					// first time, we'll set this to `false` then.
					if (fn.exit === 'webkitCancelFullScreen' && !iframe) {
						return true;
					}

					// Chrome on Android reports that fullscreen is enabled, but it isn't really.
					if (chromeAndroid) {
						return false;
					}

					return document[fn.enabled] || false;
				}
			}
		});
	}
	// If the define fails, set them to `null` and `false`, respectively.
	catch (err) {
		bigscreen.element = null;
		bigscreen.enabled = false;
	}

	// If there is a valid `fullscreenchange` event, set up the listener for it.
	if (fn.change) {
		document.addEventListener(fn.change, function onFullscreenChange(event) {
			bigscreen.onchange(bigscreen.element);

			if (bigscreen.element) {
				// This should be treated an exit if the element that is in full screen
				// is the previous element in our stack.
				var previousElement = elements[elements.length - 2];
				if (previousElement && previousElement.element === bigscreen.element) {
					callOnExit();
				}
				else {
					callOnEnter(bigscreen.element);
					addWindowResizeHack();
				}
			}
			else {
				callOnExit();
			}
		}, false);
	}

	// Listen for the video-only fullscreen events. Only applies to mobile browsers.
	// Desktop Safari and Chrome will fire the normal `fullscreenchange` event instead.
	// Use the capture phase because that seems to be the only way to get them.
	document.addEventListener('webkitbeginfullscreen', function onBeginFullscreen(event) {
		elements.push({
			element: event.srcElement,
			enter: emptyFunction,
			exit: emptyFunction,
			error: emptyFunction
		});

		bigscreen.onchange(event.srcElement);
		callOnEnter(event.srcElement);
	}, true);

	document.addEventListener('webkitendfullscreen', function onEndFullscreen(event) {
		bigscreen.onchange(event.srcElement);
		callOnExit(event.srcElement);
	}, true);

	// If there is a valid `fullscreenerror` event, set up the listener for it.
	if (fn.error) {
		document.addEventListener(fn.error, function onFullscreenError(event) {
			callOnError('not_allowed');
		}, false);
	}

	// Externalize the BigScreen object. Use array notation to play nicer with
	// Closure Compiler.
	window['BigScreen'] = bigscreen;

}(window, document, self !== top));
<|endoftext|>


<commit_before>const RUBY_REGEX = /(\#.+(\r|\n|\r\n)|\|[\w]+\||(\d+\.\d+|0x[\dA-F]+|\d+|[!<>+\-*\/=]| [\&\|]{1,2} )|(\b| )(if|new|else|elsif|while|case|break|switch|do|end|default|return|def [a-z][\w]+\??|class [A-Z][\w]+)(\b| )|'[^']+'|"[^"]+")/g;
const JS_REGEX = /(\/\/.+(\r|\n|\r\n)|(\d+\.\d+|0x[\dA-F]+|\d+|[!<>+\-*\/=]| [\&\|]{1,2} |&[lg]t;|&{1,2})|(\b| )(if|new|else|while|case|break|switch|default|return|const|var|document|window|undefined|null|NaN|Array|Boolean|Date|Error|EvalError|Function|Map|Math|Number|Object|Promise|Proxy|RangeError|ReferenceError|RegExp|Set|String|SyntaxError|TypeError|URIError|WeakMap|([A-Z][\w]+(?=\.))|(?=\.)[a-z][\w]+(?=\()|(function )?[a-z][\w]+(?=\())(\b| )|'[^']+'|"[^"]+")/g;

const CODE_RED = '#F37';
const CODE_ORANGE = '#FA3';
const CODE_YELLOW = '#FF7';
const CODE_GREEN = '#AE4';
const CODE_BLUE = '#6CE';
const CODE_PURPLE = '#A7E';
const CODE_GRAY = '#999';

function regexHighlightCCode(match) {
  if (/^(\d+\.\d+f?|0x[\dA-F]+|\d+)$/g.test(match)) {
    return '' + match + ''
  }
  else if (/[\w]+/g.test(match)) {
    return '' + match + '';
  }
}

function highlightCCode(original) {
  const C_REGEX = /\b(\d+\.\d+f?|0x[\dA-F]+|\d+|[\w]+(?=\())\b/g;
  const TYPES = [
    'bool',
    'char',
    'int',
    'float',
    'double',
    'unsigned',
    'signed',
    'long',
    'short',
    'enum',
    'typedef',
    'union',
    'void'
  ];
  function getType(line) {
    var typesLength = TYPES.length;

    for (var t = 0; t < typesLength; t++) {
      if (line.indexOf(TYPES[t]) === 0) {
        return TYPES[t];
      }
    }
  }

  var highlighted = [];
  var word = '';
  var flags = {
    comment: false,
    include: false,
    declare: false,
    quotes: false
  };

  // Go line-by-line
  var lines = original.split("\n");
  var linesLength = lines.length;
  for (var i = 0; i < linesLength; i++) {
    var line = lines[i];

    if (line === '\n') {
      highlighted.push('');
    }
    else if (line.indexOf('#include') === 0) {
      highlighted.push('#include' + line.slice(8) + '');
    }
    else if (line.indexOf('#define') === 0) {
      var paren = line.indexOf('(');
      var space = line.indexOf(' ', 8);
      var sliceTo = paren !== -1 ? paren : space;

      highlighted.push('#define' + line.slice(7, sliceTo) + '' + line.slice(sliceTo).replace(C_REGEX, regexHighlightCCode));
    }
    else if (line[0] === '/' && line[1] === '/') {
      highlighted.push('' + line + '');
    }
    else {
      var type = getType(line);
      if (type) {
        highlighted.push('' + type + '');
        line = line.slice(type.length);

        var sliceTo = line.indexOf('(');
        if (sliceTo !== -1) {
          highlighted.push('' + line.slice(0, sliceTo) + '');
          line = line.slice(sliceTo);
        }
      }
      var length = line.length;
      if (length > 0) {
        word = '';

        for (var l = 0; l < length; l++) {
          type = getType(line.slice(l));
          if (type) {
            highlighted.push(word + '' + type + '');
            line = line.slice(type.length);
            length -= type.length;
            word = '';
          }
          else {
            if (flags.quotes) {
              if (line[l] === '"') {
                flags.quotes = false;
                highlighted.push('' + word + '"');
                l++;
                word = '';
              }
            }
            else {
              if (line[l] === '"') {
                flags.quotes = true;
                highlighted.push(word);
                word = '';
              }
              else if (line[l] === "'") {
                highlighted.push(word + '' + line.slice(l, l += 3) + '');
                word = '';
              }
              // Figure out how to exclude parentheses from this highlighting
              // else if (/ ?(true|false|NULL) ?/.test(word)) {
              //   highlighted.push('' + word + '');
              //   word = '';
              // }
              else if (/ ?(break|case|const|continue|default|else|for|goto|if|return|sizeof|switch|while) ?/.test(word)) {
                highlighted.push('' + word + '');
                word = '';
              }
            }
          }
          word += line[l];
        }
        highlighted.push(word.replace(C_REGEX, regexHighlightCCode));
      }
    }
    highlighted.push('\n');
  }

  return highlighted.join('');
}

function highlightCSSProperty(match, name, value) {
  var highlighted = ['', name, '', ''];

  var words = value.split(' ');
  var replacedValue = [];
  for (var i = 0; i < words.length; i++) {
    var word = words[i];
    var replacedWord = ['', word, '', ''];
    if (/(#[0-9a-fA-F]+|(\d+|\d+\.\d+)(px|em|%)?)/.test(word)) {
      replacedWord[1] = CODE_PURPLE;
    }
    else if (/\'.+\'/.test(word)) {
      replacedWord[1] = CODE_YELLOW;
    }
    replacedValue.push(replacedWord.join(''));
  }
  highlighted.push(replacedValue.join(' '));

  return highlighted.join('');
}

function highlightCSSCode(original) {
  var highlighted = [];
  var word = '';
  var flags = {
    inRule: false
  };

  var lines = original.split("\n");
  var linesLength = lines.length;
  for (var l = 0; l < linesLength; l++) {
    var line = lines[l];

    if (flags.inRule) {
      if (line.indexOf('}') !== -1) {
        flags.inRule = false;
      }
      else {
        line = line.replace(/(^ +[\w\-]+(?=\:))(.+(?=;))/, highlightCSSProperty);
      }
    }
    else {
      flags.inRule = line.indexOf('{') !== -1;
      if (flags.inRule || /\,$/.test(line)) {
        if (/ *#/.test(line)) {
          // ID selector
          line = line.replace(/#[\w\-]+/, function(match) { return '' + match + ''; });
        }
        else if (/ *\./.test(line)) {
          // Class selector
          line = line.replace(/\.[\w\-]+/, function(match) { return '' + match + ''; });
        }
        else {
          // Tag selector
          line = line.replace(/[\w\-]+/, function(match) { return '' + match + ''; });
        }
      }
    }
    highlighted.push(line);
  }

  return highlighted.join("\n");
}

function highlightRubyCode(match) {
  var replaced = ['', match, ''];

  if (!isNaN(parseInt(match)) || match === 'undefined' || match === 'null' || match === 'NaN') {
    replaced[1] = CODE_PURPLE;
  }
  else if (match[0] === '#') {
    replaced[1] = CODE_GRAY;
  }
  else if (/('.+'|".+")/.test(match)) {
    replaced[1] = CODE_YELLOW;
  }
  else if (/\|[\w]+\|/.test(match)) {
    replaced[1] = CODE_ORANGE + ';font-style:italic';
    replaced[3] = match.slice(1, match.length - 1);
    replaced.unshift('|');
    replaced.push('|');
  }
  else if (/[!<>+\-*\/=]|[\&\|]{1,2}|&[lg]t;|&{1,2}|if|new|else|elsif|while|case|break|switch|do|end|default|return/.test(match)) {
    replaced[1] = CODE_RED;
  }
  else if (match.trim().slice(0, 3) === 'def') {
    replaced[1] = CODE_RED;
    replaced[3] = match.replace('def ', 'def ');
  }
  else if (match.trim().slice(0, 5) === 'class') {
    replaced[1] = CODE_RED;
    replaced[3] = match.replace('class ', 'class ');
  }

  return replaced.join('');
}

function highlightJSCode(match) {
  var replaced = ['', match, ''];
  // match = match.trim();

  if (!isNaN(parseInt(match))) {
    replaced[1] = CODE_PURPLE;
  }
  else if (/ *\/\//.test(match)) {
    replaced[1] = CODE_GRAY;
  }
  else if (/ *('.+'|".+")/.test(match)) {
    replaced[1] = CODE_YELLOW;
  }
  else if (/ *[!<>+\-*\/=]|[\&\|]{1,2}|if|new|else|while|case|break|switch|default|return/.test(match)) {
    replaced[1] = CODE_RED;
  }
  else if (/ *function/.test(match)) {
    replaced[1] = CODE_BLUE + ';font-style:italic';
    // If a function declaration
    if (/function \w+/.test(match)) {
      replaced[3] = match.match(/^ */)[0] + 'function ' + match.replace(/ *function /, '');
    }
  }
  else if (/^ *[A-Z]/.test(match)) {
    replaced[1] = CODE_BLUE + ';font-style:italic';
  }
  else {
    switch (match) {
      case "document":
      case "window":
      case "const":
      case "var":
      case "Array":
      case "Boolean":
      case "Date":
      case "Error":
      case "EvalError":
      case "Function":
      case "Map":
      case "Math":
      case "Number":
      case "Object":
      case "Promise":
      case "Proxy":
      case "RangeError":
      case "ReferenceError":
      case "RegExp":
      case "Set":
      case "String":
      case "SyntaxError":
      case "TypeError":
      case "URIError":
      case "WeakMap":
        replaced[1] = CODE_BLUE + ';font-style:italic';
        break;
      default:
        replaced[1] = CODE_BLUE;
        break;
    }
  }

  return replaced.join('');
}

function highlightHTMLCode(original) {
  var highlighted = [];
  var word = '';
  var flags = {
    tag: false,
    tagName: false,
    doubleQuotes: false,
    styleTag: false,
    scriptTag: false
  };

  var stylesheet = '';
  var javascript = '';

  var length = original.length;
  for (var i = 0; i < length; i++) {
    if (!flags.tag) {
      if (original.slice(i, i + 4) === '<') {
        if (word) {
          if (flags.styleTag) {
            highlighted.push(highlightCSSCode(word));
          }
          else if (flags.scriptTag) {
            highlighted.push(word.replace(JS_REGEX, highlightJSCode));
          }
          else {
            highlighted.push(word);
          }
        }
        if (original[i + 4] === '/') {
          highlighted.push('</');
          i += 5;
        }
        else {
          highlighted.push('<');
          i += 4;
        }
        word = '';
        flags.tag = true;
        flags.tagName = true;
      }
      word += original[i];
    }
    else {
      if (flags.tagName) {
        if (!/[a-zA-Z0-9]/.test(original[i])) {
          if (original[i] === ' ') {
            highlighted.push(word + ' ');
            i++;
          }
          else {
            highlighted.push(word + '');
          }
          // Check whether this is a style or script tag
          if (word === 'style') {
            flags.styleTag = !flags.styleTag;
          }
          else if (word === 'script') {
            flags.scriptTag = !flags.scriptTag;
          }
          word = '';
          flags.tagName = false;
        }
      }
      else {
        if (!flags.doubleQuotes) {
          if (original[i] === '"') {
            flags.doubleQuotes = true;
            highlighted.push('="');
            word = '';
            i++;
          }
          else if (original[i] === '=') {
            highlighted.push('');
            highlighted.push(word);
            highlighted.push('');
            word = '';
          }
        }
        else {
          if (original[i] === '"') {
            flags.doubleQuotes = false;
            highlighted.push('');
            highlighted.push(word);
            highlighted.push('"');
            word = '';
            i++;
          }
        }
      }

      if (flags.tag && original.slice(i, i + 4) === '>') {
        flags.tag = false;
        highlighted.push('>');
        i += 3;
      }
      else {
        word += original[i];
      }
    }
  }

  return highlighted.join('');
}

function highlightPreTagsContent() {
  var preTags = document.getElementsByTagName('pre');
  var preTagsLength = preTags.length;

  for (var i = 0; i < preTagsLength; i++) {
    var originalHTML = preTags[i].innerHTML;

    switch (preTags[i].className) {
      case 'code-c'         : preTags[i].innerHTML = highlightCCode(originalHTML); break;
      case 'code-css'       : preTags[i].innerHTML = highlightCSSCode(originalHTML); break;
      case 'code-ruby'      : preTags[i].innerHTML = originalHTML.replace(RUBY_REGEX, highlightRubyCode); break;
      case 'code-javascript': preTags[i].innerHTML = originalHTML.replace(JS_REGEX, highlightJSCode); break;
      case 'code-html'      : preTags[i].innerHTML = highlightHTMLCode(originalHTML); break;
    }
  }
}

ready(highlightPreTagsContent);
<commit_msg>Add instanceof and typeof to js highlighter<commit_after>const RUBY_REGEX = /(\#.+(\r|\n|\r\n)|\|[\w]+\||(\d+\.\d+|0x[\dA-F]+|\d+|[!<>+\-*\/=]| [\&\|]{1,2} )|(\b| )(if|new|else|elsif|while|case|break|switch|do|end|default|return|def [a-z][\w]+\??|class [A-Z][\w]+)(\b| )|'[^']+'|"[^"]+")/g;
const JS_REGEX = /(\/\/.+(\r|\n|\r\n)|(\d+\.\d+|0x[\dA-F]+|\d+|[!<>+\-*\/=]| [\&\|]{1,2} |&[lg]t;|&{1,2})|(\b| )(if|new|else|while|case|break|switch|default|typeof|instanceof|return|const|var|document|window|undefined|null|NaN|Array|Boolean|Date|Error|EvalError|Function|Map|Math|Number|Object|Promise|Proxy|RangeError|ReferenceError|RegExp|Set|String|SyntaxError|TypeError|URIError|WeakMap|([A-Z][\w]+(?=\.))|(?=\.)[a-z][\w]+(?=\()|(function )?[a-z][\w]+(?=\())(\b| )|'[^']+'|"[^"]+")/g;

const CODE_RED = '#F37';
const CODE_ORANGE = '#FA3';
const CODE_YELLOW = '#FF7';
const CODE_GREEN = '#AE4';
const CODE_BLUE = '#6CE';
const CODE_PURPLE = '#A7E';
const CODE_GRAY = '#999';

function regexHighlightCCode(match) {
  if (/^(\d+\.\d+f?|0x[\dA-F]+|\d+)$/g.test(match)) {
    return '' + match + ''
  }
  else if (/[\w]+/g.test(match)) {
    return '' + match + '';
  }
}

function highlightCCode(original) {
  const C_REGEX = /\b(\d+\.\d+f?|0x[\dA-F]+|\d+|[\w]+(?=\())\b/g;
  const TYPES = [
    'bool',
    'char',
    'int',
    'float',
    'double',
    'unsigned',
    'signed',
    'long',
    'short',
    'enum',
    'typedef',
    'union',
    'void'
  ];
  function getType(line) {
    var typesLength = TYPES.length;

    for (var t = 0; t < typesLength; t++) {
      if (line.indexOf(TYPES[t]) === 0) {
        return TYPES[t];
      }
    }
  }

  var highlighted = [];
  var word = '';
  var flags = {
    comment: false,
    include: false,
    declare: false,
    quotes: false
  };

  // Go line-by-line
  var lines = original.split("\n");
  var linesLength = lines.length;
  for (var i = 0; i < linesLength; i++) {
    var line = lines[i];

    if (line === '\n') {
      highlighted.push('');
    }
    else if (line.indexOf('#include') === 0) {
      highlighted.push('#include' + line.slice(8) + '');
    }
    else if (line.indexOf('#define') === 0) {
      var paren = line.indexOf('(');
      var space = line.indexOf(' ', 8);
      var sliceTo = paren !== -1 ? paren : space;

      highlighted.push('#define' + line.slice(7, sliceTo) + '' + line.slice(sliceTo).replace(C_REGEX, regexHighlightCCode));
    }
    else if (line[0] === '/' && line[1] === '/') {
      highlighted.push('' + line + '');
    }
    else {
      var type = getType(line);
      if (type) {
        highlighted.push('' + type + '');
        line = line.slice(type.length);

        var sliceTo = line.indexOf('(');
        if (sliceTo !== -1) {
          highlighted.push('' + line.slice(0, sliceTo) + '');
          line = line.slice(sliceTo);
        }
      }
      var length = line.length;
      if (length > 0) {
        word = '';

        for (var l = 0; l < length; l++) {
          type = getType(line.slice(l));
          if (type) {
            highlighted.push(word + '' + type + '');
            line = line.slice(type.length);
            length -= type.length;
            word = '';
          }
          else {
            if (flags.quotes) {
              if (line[l] === '"') {
                flags.quotes = false;
                highlighted.push('' + word + '"');
                l++;
                word = '';
              }
            }
            else {
              if (line[l] === '"') {
                flags.quotes = true;
                highlighted.push(word);
                word = '';
              }
              else if (line[l] === "'") {
                highlighted.push(word + '' + line.slice(l, l += 3) + '');
                word = '';
              }
              // Figure out how to exclude parentheses from this highlighting
              // else if (/ ?(true|false|NULL) ?/.test(word)) {
              //   highlighted.push('' + word + '');
              //   word = '';
              // }
              else if (/ ?(break|case|const|continue|default|else|for|goto|if|return|sizeof|switch|while) ?/.test(word)) {
                highlighted.push('' + word + '');
                word = '';
              }
            }
          }
          word += line[l];
        }
        highlighted.push(word.replace(C_REGEX, regexHighlightCCode));
      }
    }
    highlighted.push('\n');
  }

  return highlighted.join('');
}

function highlightCSSProperty(match, name, value) {
  var highlighted = ['', name, '', ''];

  var words = value.split(' ');
  var replacedValue = [];
  for (var i = 0; i < words.length; i++) {
    var word = words[i];
    var replacedWord = ['', word, '', ''];
    if (/(#[0-9a-fA-F]+|(\d+|\d+\.\d+)(px|em|%)?)/.test(word)) {
      replacedWord[1] = CODE_PURPLE;
    }
    else if (/\'.+\'/.test(word)) {
      replacedWord[1] = CODE_YELLOW;
    }
    replacedValue.push(replacedWord.join(''));
  }
  highlighted.push(replacedValue.join(' '));

  return highlighted.join('');
}

function highlightCSSCode(original) {
  var highlighted = [];
  var word = '';
  var flags = {
    inRule: false
  };

  var lines = original.split("\n");
  var linesLength = lines.length;
  for (var l = 0; l < linesLength; l++) {
    var line = lines[l];

    if (flags.inRule) {
      if (line.indexOf('}') !== -1) {
        flags.inRule = false;
      }
      else {
        line = line.replace(/(^ +[\w\-]+(?=\:))(.+(?=;))/, highlightCSSProperty);
      }
    }
    else {
      flags.inRule = line.indexOf('{') !== -1;
      if (flags.inRule || /\,$/.test(line)) {
        if (/ *#/.test(line)) {
          // ID selector
          line = line.replace(/#[\w\-]+/, function(match) { return '' + match + ''; });
        }
        else if (/ *\./.test(line)) {
          // Class selector
          line = line.replace(/\.[\w\-]+/, function(match) { return '' + match + ''; });
        }
        else {
          // Tag selector
          line = line.replace(/[\w\-]+/, function(match) { return '' + match + ''; });
        }
      }
    }
    highlighted.push(line);
  }

  return highlighted.join("\n");
}

function highlightRubyCode(match) {
  var replaced = ['', match, ''];

  if (!isNaN(parseInt(match)) || match === 'undefined' || match === 'null' || match === 'NaN') {
    replaced[1] = CODE_PURPLE;
  }
  else if (match[0] === '#') {
    replaced[1] = CODE_GRAY;
  }
  else if (/('.+'|".+")/.test(match)) {
    replaced[1] = CODE_YELLOW;
  }
  else if (/\|[\w]+\|/.test(match)) {
    replaced[1] = CODE_ORANGE + ';font-style:italic';
    replaced[3] = match.slice(1, match.length - 1);
    replaced.unshift('|');
    replaced.push('|');
  }
  else if (/[!<>+\-*\/=]|[\&\|]{1,2}|&[lg]t;|&{1,2}|if|new|else|elsif|while|case|break|switch|do|end|default|return/.test(match)) {
    replaced[1] = CODE_RED;
  }
  else if (match.trim().slice(0, 3) === 'def') {
    replaced[1] = CODE_RED;
    replaced[3] = match.replace('def ', 'def ');
  }
  else if (match.trim().slice(0, 5) === 'class') {
    replaced[1] = CODE_RED;
    replaced[3] = match.replace('class ', 'class ');
  }

  return replaced.join('');
}

function highlightJSCode(match) {
  var replaced = ['', match, ''];
  // match = match.trim();

  if (!isNaN(parseInt(match))) {
    replaced[1] = CODE_PURPLE;
  }
  else if (/ *\/\//.test(match)) {
    replaced[1] = CODE_GRAY;
  }
  else if (/ *('.+'|".+")/.test(match)) {
    replaced[1] = CODE_YELLOW;
  }
  else if (/ *[!<>+\-*\/=]|[\&\|]{1,2}|if|new|else|while|case|break|switch|default|typeof|instanceof|return/.test(match)) {
    replaced[1] = CODE_RED;
  }
  else if (/ *function/.test(match)) {
    replaced[1] = CODE_BLUE + ';font-style:italic';
    // If a function declaration
    if (/function \w+/.test(match)) {
      replaced[3] = match.match(/^ */)[0] + 'function ' + match.replace(/ *function /, '');
    }
  }
  else if (/^ *[A-Z]/.test(match)) {
    replaced[1] = CODE_BLUE + ';font-style:italic';
  }
  else {
    switch (match) {
      case "document":
      case "window":
      case "const":
      case "var":
      case "Array":
      case "Boolean":
      case "Date":
      case "Error":
      case "EvalError":
      case "Function":
      case "Map":
      case "Math":
      case "Number":
      case "Object":
      case "Promise":
      case "Proxy":
      case "RangeError":
      case "ReferenceError":
      case "RegExp":
      case "Set":
      case "String":
      case "SyntaxError":
      case "TypeError":
      case "URIError":
      case "WeakMap":
        replaced[1] = CODE_BLUE + ';font-style:italic';
        break;
      default:
        replaced[1] = CODE_BLUE;
        break;
    }
  }

  return replaced.join('');
}

function highlightHTMLCode(original) {
  var highlighted = [];
  var word = '';
  var flags = {
    tag: false,
    tagName: false,
    doubleQuotes: false,
    styleTag: false,
    scriptTag: false
  };

  var stylesheet = '';
  var javascript = '';

  var length = original.length;
  for (var i = 0; i < length; i++) {
    if (!flags.tag) {
      if (original.slice(i, i + 4) === '<') {
        if (word) {
          if (flags.styleTag) {
            highlighted.push(highlightCSSCode(word));
          }
          else if (flags.scriptTag) {
            highlighted.push(word.replace(JS_REGEX, highlightJSCode));
          }
          else {
            highlighted.push(word);
          }
        }
        if (original[i + 4] === '/') {
          highlighted.push('</');
          i += 5;
        }
        else {
          highlighted.push('<');
          i += 4;
        }
        word = '';
        flags.tag = true;
        flags.tagName = true;
      }
      word += original[i];
    }
    else {
      if (flags.tagName) {
        if (!/[a-zA-Z0-9]/.test(original[i])) {
          if (original[i] === ' ') {
            highlighted.push(word + ' ');
            i++;
          }
          else {
            highlighted.push(word + '');
          }
          // Check whether this is a style or script tag
          if (word === 'style') {
            flags.styleTag = !flags.styleTag;
          }
          else if (word === 'script') {
            flags.scriptTag = !flags.scriptTag;
          }
          word = '';
          flags.tagName = false;
        }
      }
      else {
        if (!flags.doubleQuotes) {
          if (original[i] === '"') {
            flags.doubleQuotes = true;
            highlighted.push('="');
            word = '';
            i++;
          }
          else if (original[i] === '=') {
            highlighted.push('');
            highlighted.push(word);
            highlighted.push('');
            word = '';
          }
        }
        else {
          if (original[i] === '"') {
            flags.doubleQuotes = false;
            highlighted.push('');
            highlighted.push(word);
            highlighted.push('"');
            word = '';
            i++;
          }
        }
      }

      if (flags.tag && original.slice(i, i + 4) === '>') {
        flags.tag = false;
        highlighted.push('>');
        i += 3;
      }
      else {
        word += original[i];
      }
    }
  }

  return highlighted.join('');
}

function highlightPreTagsContent() {
  var preTags = document.getElementsByTagName('pre');
  var preTagsLength = preTags.length;

  for (var i = 0; i < preTagsLength; i++) {
    var originalHTML = preTags[i].innerHTML;

    switch (preTags[i].className) {
      case 'code-c'         : preTags[i].innerHTML = highlightCCode(originalHTML); break;
      case 'code-css'       : preTags[i].innerHTML = highlightCSSCode(originalHTML); break;
      case 'code-ruby'      : preTags[i].innerHTML = originalHTML.replace(RUBY_REGEX, highlightRubyCode); break;
      case 'code-javascript': preTags[i].innerHTML = originalHTML.replace(JS_REGEX, highlightJSCode); break;
      case 'code-html'      : preTags[i].innerHTML = highlightHTMLCode(originalHTML); break;
    }
  }
}

ready(highlightPreTagsContent);
<|endoftext|>


<commit_before>(function($) {
	$.fn.dribbbleshot = function(options) {

		// Sanitize options
		var settings = $.extend({}, $.fn.dribbbleshot.defaults, options);

		// Player is required
		if(!settings.player || (typeof(settings.player) != "string" && typeof(settings.player) != "number")) {
			throw new TypeError("Required setting 'player' must be a string or a number.");
		}

		// Shots per page
		settings.per_page = parseInt(settings.per_page);
		if(settings.per_page > 30 || settings.per_page < 1) {
			settings.per_page = 30;
		}

		// Current page
		settings.page = parseInt(settings.page);

		// Request URL
		settings.url = "//api.dribbble.com/players/" + settings.player + "/shots?page=" + settings.page + "&per_page=" + settings.per_page;

		// Allow chaining
		return this.each(function() {

			var $container = $(this);

			var request = $.ajax({
				url: settings.url,
				dataType: "jsonp"
			});

			if(typeof(settings.always) == "function") {
				request.always(settings.always);
			}

			if(typeof(settings.fail) == "function") {
				request.fail(settings.fail);
			}

			if(typeof(settings.done) == "function") {
				request.done(settings.done);
			}
			else {
				request.done(function(response, textStatus, jqxhr) {

					if(jqxhr.status != 200) {
						return false;
					}

					$.each(response.shots, function(index, element) {
						$container.append(settings.format(element));
					});

					$container.append(settings.pagination(response.pages));
				});
			}

		});

	};

	$.fn.dribbbleshot.format = function(shot) {
		var markup = '

';

		return $.parseHTML(markup);
	};

	$.fn.dribbbleshot.pagination = function(pages) {
		var markup = '
';
		markup += '
' + settings.paginationPreviousText + '
';

		for(var p = 1; p <= pages; p++) {
			markup += '
';

			if(settings.showPaginationPages) {
				markup += p;
			}

			markup += '
';
		}

		markup += '
' + settings.paginationNextText + '
';
		markup += '
';

		return $.parseHTML(markup);
	};

	$.fn.dribbbleshot.defaults = {
		format : $.fn.dribbbleshot.format,
		page : 1,
		per_page : 15,
		showPaginationControls : true,
		showPaginationPages : false,
		paginationPreviousText : "Previous",
		paginationNextText : "Next"
	};

}(jQuery));<commit_msg>Learned more about jsonp<commit_after>(function($) {
	$.fn.dribbbleshot = function(options) {

		// Sanitize options
		var settings = $.extend({}, $.fn.dribbbleshot.defaults, options);

		// Player is required
		if(!settings.player || (typeof(settings.player) != "string" && typeof(settings.player) != "number")) {
			throw new TypeError("Required setting 'player' must be a string or a number.");
		}

		// Shots per page
		settings.per_page = parseInt(settings.per_page);
		if(settings.per_page > 30 || settings.per_page < 1) {
			settings.per_page = 30;
		}

		// Current page
		settings.page = parseInt(settings.page);

		// Request URL
		settings.url = "//api.dribbble.com/players/" + settings.player + "/shots?page=" + settings.page + "&per_page=" + settings.per_page + "&callback=?";

		// Allow chaining
		return this.each(function() {

			var $container = $(this);

			var request = $.ajax({
				url: settings.url,
				dataType: "jsonp"
			});

			if(typeof(settings.always) == "function") {
				request.always(settings.always);
			}

			if(typeof(settings.fail) == "function") {
				request.fail(settings.fail);
			}

			if(typeof(settings.done) == "function") {
				request.done(settings.done);
			}
			else {
				request.done(function(response, textStatus, jqxhr) {

					if(jqxhr.status != 200) {
						return false;
					}

					$.each(response.shots, function(index, element) {
						$container.append(settings.format(element));
					});

					$container.append(settings.pagination(response.pages));
				});
			}

		});

	};

	$.fn.dribbbleshot.format = function(shot) {
		var markup = '

';

		return $.parseHTML(markup);
	};

	$.fn.dribbbleshot.pagination = function(pages) {
		var markup = '
';
		markup += '
' + settings.paginationPreviousText + '
';

		for(var p = 1; p <= pages; p++) {
			markup += '
';

			if(settings.showPaginationPages) {
				markup += p;
			}

			markup += '
';
		}

		markup += '
' + settings.paginationNextText + '
';
		markup += '
';

		return $.parseHTML(markup);
	};

	$.fn.dribbbleshot.defaults = {
		format : $.fn.dribbbleshot.format,
		page : 1,
		per_page : 15,
		showPaginationControls : true,
		showPaginationPages : false,
		paginationPreviousText : "Previous",
		paginationNextText : "Next"
	};

}(jQuery));
<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on filters, and services
var adminApp = angular.module('blogae.admin', ['blogae.topbar', 'blogae.scroll']);

adminApp.controller('AdminCtrl', function($scope, $http, $window, topbar) {
  var admin = this;

  admin.title = '';
  admin.content = '';
  admin.content_html = '';
  admin.tags = '';
  admin.permalink = '';
  admin.date_published = '';

  admin.posts = [];
  admin.next_post_id = '';

  admin.selected_post = null;
  admin.edited = false;

  admin.help_showing = false;

  admin.saving = false;
  admin.metadata_editing = 'tags'; // or published or permalink.
  admin.blogae_scripts = $blogae_scripts;

  admin.edit = function(postid) {
    angular.forEach(admin.posts, function(post) {
      if (post.id == postid) {
        admin.fill_post_form(post);
      }
    });
  }

  // fills the post form. will lose the current post if any.
  admin.fill_post_form = function(post) {
    if (admin.has_changed() &&
	!$window.confirm('You will lose you data. Are you sure?')) {
      return;
    }

    admin.selected_post = post;
    admin.title = post.title;
    admin.content = post.content;
    admin.content_html = post.content_html;
    admin.tags = post.tags;
    admin.permalink = post.permalink;
    admin.date_published = post.date_published;

    admin.edited = false;
    admin.content_changed();
  }

  admin.has_changed = function() {
    var is_empty = !(admin.title || admin.content || admin.selected_post);
    return !is_empty && admin.edited;
  }

  admin.view = function(postid) {
    angular.forEach(admin.posts, function(post) {
      if (post.id == postid) {
	var permalink = post.permalink_full;
	$window.open(permalink, 'view');
      }
    });
  }

  admin.content_changed = function() {
    var html = markdown.toHTML(admin.content);
    if (/iframe.*youtube.com.*\/iframe/.exec(html)) {
      // post-process to support youtube iframes.
      html = html.replace(/<iframe /g, '<iframe ');
      html = html.replace(/<\/iframe/g, '</iframe');
      html = html.replace(/>/g, '>');
      html = html.replace(/"/g, '"');
      html = html.replace(/<iframe width=".*?" height=".*?"/g,
                          '<iframe width="100%" height="auto"');
    }
    $('#post-preview').html(html);
  }

  admin.toggle_metadata_editing = function() {
    if (admin.metadata_editing == 'tags') {
      admin.metadata_editing = 'published';
    } else if (admin.metadata_editing == 'published') {
      admin.metadata_editing = 'permalink';
    } else {
      admin.metadata_editing = 'tags';
    }
  }

  admin.check_date_format = function() {
    var format = /\d{1,2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{1,2}:\d{1,2}/;
    return admin.date_published.length == 0 || format.test(admin.date_published);
  }

  admin.delete_post = function() {
    if (!$window.confirm('Are you sure you delete the post?')) {
      return;
    }

    var params = $.param({'postid': admin.selected_post.id});
    topbar.show_message('deleting...');
    $http.post('/_/delete/', params).success(function(data) {
      var i = 0;
      for (; i < admin.posts.length; i++) {
	if (admin.posts[i].id == data.postid) {
	  break;
	}
      }
      admin.posts.splice(i, 1);
      admin.prepare_new_post();
      topbar.hide_message();
    }).error(function() {
      // todo(iwongu): show better error message.
      topbar.show_error('failed to delete...');
    });
  }

  admin.publish = function() {
    admin.save_post('/_/publish/', false);
  }

  admin.save = function() {
    admin.save_post('/_/save/', true);
  }

  admin.save_post = function(api_path, is_draft) {
    if (!admin.check_date_format()) {
      $window.alert('The published date format is wrong.');
      return;
    }
    admin.saving = true;
    var params = admin.prepare_save();
    topbar.show_message('saving...');
    $http.post(api_path, params).success(function(post) {
      admin.saving = false;
      admin.edited = false;
      if (!admin.selected_post) { // new post.
	admin.selected_post = post;
	admin.posts.unshift(post);
      } else {
	angular.forEach(admin.posts, function(current, i) {
	  if (current.id == admin.selected_post.id) {
	    admin.posts[i] = post;
	  }
	});
      }
      admin.fill_post_form(post);
      topbar.hide_message();
    }).error(function() {
      admin.saving = false;
      // todo(iwongu): show better error message.
      topbar.show_error('failed to save...');
    });
  }

  admin.new_post = function() {
    if (admin.has_changed() &&
	!$window.confirm('You will lose you data. Are you sure?')) {
      return;
    }
    admin.prepare_new_post();
  }

  admin.prepare_new_post = function() {
    admin.title = '';
    admin.content = '';
    admin.content_html = '';
    admin.tags = '';
    admin.permalink = '';
    admin.date_published = '';

    admin.selected_post = null;
    admin.edited = false;
    admin.content_changed();
  }

  admin.prepare_save = function() {
    // save changes locally.
    if (admin.selected_post) {
      admin.selected_post.title = admin.title;
      admin.selected_post.content = admin.content;
      admin.selected_post.tags = admin.tags;
      admin.selected_post.permalink = admin.permalink;
      admin.selected_post.date_published = admin.date_published;
    }

    return $.param({
      'postid': admin.selected_post ? admin.selected_post.id : '',
      'title': admin.title,
      'content': admin.content,
      'tags': admin.tags,
      'permalink': admin.selected_post ? admin.selected_post.permalink : '',
      'date_published': admin.selected_post ?
        admin.selected_post.date_published : '',
    });
  }

  admin.load_more = function() {
    if (admin.next_post_id) {
      admin.fetch_next(admin.next_post_id);
    }
  };

  admin.call_blogae_script = function(num) {
    admin.content = admin.blogae_scripts[num](admin.content);
    admin.edited = true;
    admin.content_changed();
  }

  admin.open_photo_picker = function() {
    var picker = $window.open('/admin/picker', 'picker');
    var timer = $window.setInterval(function() {
      if (picker.closed !== false) {
	$window.clearInterval(timer);
	admin.photos_selected();
      }
    }, 200);
  }

  admin.photos_selected = function() {
    var value = $('#selected_photos').val();
    if (!value) {
      return;
    }
    var photos = value.split(' ');
    var content_el = $('#content').get(0);
    var caret = content_el.selectionStart;
    var new_content = admin.content.slice(0, caret);
    new_content += '\n';
    for (var i = 0; i < photos.length; i++) {
      new_content += '\n![](' + photos[i] + ')\n';
    }
    new_content += '\n';
    new_content += admin.content.slice(caret, admin.content.length);
    admin.content = new_content;
    admin.edited = true;

    admin.$apply();
    admin.content_changed();
  }

  admin.fetch_next = function(next_post_id) {
    var params = $.param({'next_post_id': next_post_id});
    topbar.show_message('loading...');
    $http.post('/_/get_posts/', params).success(function(data) {
      admin.posts = admin.posts.concat(data.posts);
      admin.next_post_id = data.next_post_id;
      topbar.hide_message();
    }).error(function() {
      // todo(iwongu): show beter error message.
      topbar.show_error('failed to fetch more posts...');
    });
  }

  // set default header.
  $http.defaults.headers.post["Content-Type"] =
    "application/x-www-form-urlencoded";

  // fetch the posts when app is started.
  admin.fetch_next('')
});
<commit_msg>update admin.js to use this.<commit_after>'use strict';

// Declare app level module which depends on filters, and services
var adminApp = angular.module('blogae.admin', ['blogae.topbar', 'blogae.scroll']);

adminApp.controller('AdminCtrl', function($scope, $http, $window, topbar) {
  var admin = this;

  this.title = '';
  this.content = '';
  this.content_html = '';
  this.tags = '';
  this.permalink = '';
  this.date_published = '';

  this.posts = [];
  this.next_post_id = '';

  this.selected_post = null;
  this.edited = false;

  this.help_showing = false;

  this.saving = false;
  this.metadata_editing = 'tags'; // or published or permalink.
  this.blogae_scripts = $blogae_scripts;

  this.edit = function(postid) {
    angular.forEach(this.posts, angular.bind(this, function(post) {
      if (post.id == postid) {
        this.fill_post_form(post);
      }
    }));
  }

  // fills the post form. will lose the current post if any.
  this.fill_post_form = function(post) {
    if (this.has_changed() &&
	!$window.confirm('You will lose you data. Are you sure?')) {
      return;
    }

    this.selected_post = post;
    this.title = post.title;
    this.content = post.content;
    this.content_html = post.content_html;
    this.tags = post.tags;
    this.permalink = post.permalink;
    this.date_published = post.date_published;

    this.edited = false;
    this.content_changed();
  }

  this.has_changed = function() {
    var is_empty = !(this.title || this.content || this.selected_post);
    return !is_empty && this.edited;
  }

  this.view = function(postid) {
    angular.forEach(this.posts, angular.bind(this, function(post) {
      if (post.id == postid) {
	var permalink = post.permalink_full;
	$window.open(permalink, 'view');
      }
    }));
  }

  this.content_changed = function() {
    var html = markdown.toHTML(this.content);
    if (/iframe.*youtube.com.*\/iframe/.exec(html)) {
      // post-process to support youtube iframes.
      html = html.replace(/<iframe /g, '<iframe ');
      html = html.replace(/<\/iframe/g, '</iframe');
      html = html.replace(/>/g, '>');
      html = html.replace(/"/g, '"');
      html = html.replace(/<iframe width=".*?" height=".*?"/g,
                          '<iframe width="100%" height="auto"');
    }
    $('#post-preview').html(html);
  }

  this.toggle_metadata_editing = function() {
    if (this.metadata_editing == 'tags') {
      this.metadata_editing = 'published';
    } else if (this.metadata_editing == 'published') {
      this.metadata_editing = 'permalink';
    } else {
      this.metadata_editing = 'tags';
    }
  }

  this.check_date_format = function() {
    var format = /\d{1,2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{1,2}:\d{1,2}/;
    return this.date_published.length == 0 || format.test(this.date_published);
  }

  this.delete_post = function() {
    if (!$window.confirm('Are you sure you delete the post?')) {
      return;
    }

    var params = $.param({'postid': this.selected_post.id});
    topbar.show_message('deleting...');
    $http.post('/_/delete/', params).success(angular.bind(this, function(data) {
      var i = 0;
      for (; i < this.posts.length; i++) {
	if (this.posts[i].id == data.postid) {
	  break;
	}
      }
      this.posts.splice(i, 1);
      this.prepare_new_post();
      topbar.hide_message();
    })).error(angular.bind(this, function() {
      // todo(iwongu): show better error message.
      topbar.show_error('failed to delete...');
    }));
  }

  this.publish = function() {
    this.save_post('/_/publish/', false);
  }

  this.save = function() {
    this.save_post('/_/save/', true);
  }

  this.save_post = function(api_path, is_draft) {
    if (!this.check_date_format()) {
      $window.alert('The published date format is wrong.');
      return;
    }
    this.saving = true;
    var params = this.prepare_save();
    topbar.show_message('saving...');
    $http.post(api_path, params).success(angular.bind(this, function(post) {
      this.saving = false;
      this.edited = false;
      if (!this.selected_post) { // new post.
	this.selected_post = post;
	this.posts.unshift(post);
      } else {
	angular.forEach(this.posts, angular.bind(this, function(current, i) {
	  if (current.id == this.selected_post.id) {
	    this.posts[i] = post;
	  }
	}));
      }
      this.fill_post_form(post);
      topbar.hide_message();
    })).error(angular.bind(this, function() {
      this.saving = false;
      // todo(iwongu): show better error message.
      topbar.show_error('failed to save...');
    }));
  }

  this.new_post = function() {
    if (this.has_changed() &&
	!$window.confirm('You will lose you data. Are you sure?')) {
      return;
    }
    this.prepare_new_post();
  }

  this.prepare_new_post = function() {
    this.title = '';
    this.content = '';
    this.content_html = '';
    this.tags = '';
    this.permalink = '';
    this.date_published = '';

    this.selected_post = null;
    this.edited = false;
    this.content_changed();
  }

  this.prepare_save = function() {
    // save changes locally.
    if (this.selected_post) {
      this.selected_post.title = this.title;
      this.selected_post.content = this.content;
      this.selected_post.tags = this.tags;
      this.selected_post.permalink = this.permalink;
      this.selected_post.date_published = this.date_published;
    }

    return $.param({
      'postid': this.selected_post ? this.selected_post.id : '',
      'title': this.title,
      'content': this.content,
      'tags': this.tags,
      'permalink': this.selected_post ? this.selected_post.permalink : '',
      'date_published': this.selected_post ?
        this.selected_post.date_published : '',
    });
  }

  this.load_more = function() {
    if (this.next_post_id) {
      this.fetch_next(this.next_post_id);
    }
  };

  this.call_blogae_script = function(num) {
    this.content = this.blogae_scripts[num](this.content);
    this.edited = true;
    this.content_changed();
  }

  this.open_photo_picker = function() {
    var picker = $window.open('/admin/picker', 'picker');
    var timer = $window.setInterval(angular.bind(this, function() {
      if (picker.closed !== false) {
	$window.clearInterval(timer);
	this.photos_selected();
      }
    }), 200);
  }

  this.photos_selected = function() {
    var value = $('#selected_photos').val();
    if (!value) {
      return;
    }
    var photos = value.split(' ');
    var content_el = $('#content').get(0);
    var caret = content_el.selectionStart;
    var new_content = this.content.slice(0, caret);
    new_content += '\n';
    for (var i = 0; i < photos.length; i++) {
      new_content += '\n![](' + photos[i] + ')\n';
    }
    new_content += '\n';
    new_content += this.content.slice(caret, this.content.length);
    this.content = new_content;
    this.edited = true;

    this.$apply();
    this.content_changed();
  }

  this.fetch_next = function(next_post_id) {
    var params = $.param({'next_post_id': next_post_id});
    topbar.show_message('loading...');
    $http.post('/_/get_posts/', params).success(angular.bind(this, function(data) {
      this.posts = this.posts.concat(data.posts);
      this.next_post_id = data.next_post_id;
      topbar.hide_message();
    })).error(angular.bind(this, function() {
      // todo(iwongu): show beter error message.
      topbar.show_error('failed to fetch more posts...');
    }));
  }

  // set default header.
  $http.defaults.headers.post["Content-Type"] =
    "application/x-www-form-urlencoded";

  // fetch the posts when app is started.
  this.fetch_next('')
});
<|endoftext|>


<commit_before>/**
 * @ngdoc controller
 * @name ValueConstraintController
 * @description
 * Handles the scope variable for value constraints
 */
angular.module('locApp.modules.profile.controllers')
    .controller('ValueConstraintController', function($scope, Server, localStorageService) {
        $scope.selectList = localStorageService.get('templateRefs');
        $scope.constraintFields = [];
        $scope.templateFields = [];
        $scope.valueFields = [];

        $scope.valueConstraint = {};

        // Method to check for import
        if($scope.importy){
            // override fields
            $scope.valueConstraint = $scope.propertyTemplate.valueConstraint;

            // checked to see if a value constraint is defined
            if($scope.valueConstraint) {
                $scope.importCascade($scope.templateFields, $scope.valueConstraint.valueTemplateRefs);
                $scope.importCascade($scope.valueFields, $scope.valueConstraint.useValuesFrom);

                if($scope.valueConstraint.useValuesFrom == null) {
                    $scope.valueConstraint.useValuesFrom = [];
                }
                if($scope.valueConstraint.valueTemplateRefs == null) {
                    $scope.valueConstraint.valueTemplateRefs = [];
                }
            }
            else {
                // create an empty one if none exists
                $scope.valueConstraint = {};
                $scope.valueConstraint.valueTemplateRefs = [];
                $scope.valueConstraint.useValuesFrom = [];
                $scope.propertyTemplate.valueConstraint = $scope.valueConstraint;
            }

            $scope.constraintFields.push("");
            $scope.loadCount++;
        }
        else {
            $scope.valueConstraint.valueTemplateRefs = [];
            $scope.valueConstraint.useValuesFrom = [];

            $scope.propertyTemplate.valueConstraint = $scope.valueConstraint;

            $scope.constraintFields.push("");
            $scope.loadCount++;
        }

        // Method to get the template references
        if(!$scope.selectList) {
            var rts = [];
            Server.get('/verso/api/configs?filter[where][configType]=profile', {})
                .then(function(response) {
                    response.forEach(function(prof) {
                        prof.json.Profile.resourceTemplates.forEach(function(rt){
                            rts.push(rt.id);
                        });
                    });
                    $scope.selectList = rts;
                    localStorageService.set('templateRefs', $scope.selectList);
                });
        }

        /**
         * @ngdoc function
         * @name addTemplate
         * @description
         * Adds a template reference to the value constraint
         */
        $scope.addTemplate = function() {
            $scope.importy = false;
            $scope.valueConstraint.valueTemplateRefs.push("");
            $scope.templateFields.push($scope.valueConstraint.valueTemplateRefs.length - 1);
        };

        /**
         * @ngdoc function
         * @name deleteTemplate
         * @description
         * Deletes a template reference from the list.
         */
        $scope.deleteTemplate = function() {
            $scope.deleteItem($scope.parentId, $scope.templateFields);
            $scope.deleteItem($scope.parentId, $scope.valueConstraint.valueTemplateRefs);
        };

        /**
         * @ngdoc function
         * @name addValue
         * @description
         * Adds a value data type to the value constraint
         */
        $scope.addValue = function() {
            $scope.importy = false;
            $scope.valueConstraint.useValuesFrom.push("");
            $scope.valueFields.push($scope.valueConstraint.useValuesFrom.length - 1);
        };

        /**
         * @ngdoc function
         * @name deleteValue
         * @description
         * Deletes a value reference from the list
         */
        $scope.deleteValue = function() {
            $scope.deleteItem($scope.parentId, $scope.valueFields);
            $scope.deleteItem($scope.parentId, $scope.valueConstraint.useValuesFrom);
        };
    });
<commit_msg>Sort templateRef list.<commit_after>/**
 * @ngdoc controller
 * @name ValueConstraintController
 * @description
 * Handles the scope variable for value constraints
 */
angular.module('locApp.modules.profile.controllers')
    .controller('ValueConstraintController', function($scope, Server, localStorageService) {
        $scope.selectList = localStorageService.get('templateRefs');
        $scope.constraintFields = [];
        $scope.templateFields = [];
        $scope.valueFields = [];

        $scope.valueConstraint = {};

        // Method to check for import
        if($scope.importy){
            // override fields
            $scope.valueConstraint = $scope.propertyTemplate.valueConstraint;

            // checked to see if a value constraint is defined
            if($scope.valueConstraint) {
                $scope.importCascade($scope.templateFields, $scope.valueConstraint.valueTemplateRefs);
                $scope.importCascade($scope.valueFields, $scope.valueConstraint.useValuesFrom);

                if($scope.valueConstraint.useValuesFrom == null) {
                    $scope.valueConstraint.useValuesFrom = [];
                }
                if($scope.valueConstraint.valueTemplateRefs == null) {
                    $scope.valueConstraint.valueTemplateRefs = [];
                }
            }
            else {
                // create an empty one if none exists
                $scope.valueConstraint = {};
                $scope.valueConstraint.valueTemplateRefs = [];
                $scope.valueConstraint.useValuesFrom = [];
                $scope.propertyTemplate.valueConstraint = $scope.valueConstraint;
            }

            $scope.constraintFields.push("");
            $scope.loadCount++;
        }
        else {
            $scope.valueConstraint.valueTemplateRefs = [];
            $scope.valueConstraint.useValuesFrom = [];

            $scope.propertyTemplate.valueConstraint = $scope.valueConstraint;

            $scope.constraintFields.push("");
            $scope.loadCount++;
        }

        // Method to get the template references
        if(!$scope.selectList) {
            var rts = [];
            Server.get('/verso/api/configs?filter[where][configType]=profile', {})
                .then(function(response) {
                    response.forEach(function(prof) {
                        prof.json.Profile.resourceTemplates.forEach(function(rt){
                            rts.push(rt.id);
                        });
                    });
                    rts.sort();
                    $scope.selectList = rts;
                    localStorageService.set('templateRefs', $scope.selectList);
                });
        }

        /**
         * @ngdoc function
         * @name addTemplate
         * @description
         * Adds a template reference to the value constraint
         */
        $scope.addTemplate = function() {
            $scope.importy = false;
            $scope.valueConstraint.valueTemplateRefs.push("");
            $scope.templateFields.push($scope.valueConstraint.valueTemplateRefs.length - 1);
        };

        /**
         * @ngdoc function
         * @name deleteTemplate
         * @description
         * Deletes a template reference from the list.
         */
        $scope.deleteTemplate = function() {
            $scope.deleteItem($scope.parentId, $scope.templateFields);
            $scope.deleteItem($scope.parentId, $scope.valueConstraint.valueTemplateRefs);
        };

        /**
         * @ngdoc function
         * @name addValue
         * @description
         * Adds a value data type to the value constraint
         */
        $scope.addValue = function() {
            $scope.importy = false;
            $scope.valueConstraint.useValuesFrom.push("");
            $scope.valueFields.push($scope.valueConstraint.useValuesFrom.length - 1);
        };

        /**
         * @ngdoc function
         * @name deleteValue
         * @description
         * Deletes a value reference from the list
         */
        $scope.deleteValue = function() {
            $scope.deleteItem($scope.parentId, $scope.valueFields);
            $scope.deleteItem($scope.parentId, $scope.valueConstraint.useValuesFrom);
        };
    });
<|endoftext|>


<commit_before>import { getLabel } from '../shared/nodeHelpers'

export default class ArticlePlainTextExporter {
  export (article) {
    console.error('TODO: implement full article to plain-text conversion')
  }

  exportNode (node) {
    if (node.isContainer()) {
      return this._exportContainer(node)
    } else if (node.isText()) {
      return this._exportText(node.getDocument(), node.getPath())
    } else {
      switch (node.type) {
        case 'figure':
          return this._exportFigure(node)
        case 'table':
          return this._exportTable(node)
        case 'table-figure':
          return this._exportTableFigure(node)
        default:
          //
      }
    }

    if (node._isXMLNode) {
      return node.toXML().textContent || ''
    } else {
      console.error('TODO: implement node -> plain-text conversion for node type', node.type)
      return ''
    }
  }

  _exportContainer (node) {
    if (!node) return ''
    return node.getNodes().map(node => {
      return this.exportNode(node)
    }).join('\n\n')
  }

  _exportText (doc, path) {
    return doc.get(path) || ''
  }

  _exportTable (node) {
    if (!node) return ''
    return node.getCellMatrix().map(row => {
      return row.map(cell => {
        if (cell.isShadowed()) {
          return ''
        } else {
          return cell.getText()
        }
      }).join('\t')
    }).join('\n')
  }

  _exportFigure (node) {
    if (!node) return ''
    let doc = node.getDocument()
    let result = []
    result.push(getLabel(node) + ': ' + this._exportText(doc, [node.id, 'title']))
    result.push(this._exportContainer(node.getCaption()))
    return result.join('\n')
  }

  _exportTableFigure (node) {
    if (!node) return ''
    let doc = node.getDocument()
    let result = []
    result.push(getLabel(node) + ': ' + this._exportText(doc, [node.id, 'title']))
    result.push(this._exportTable(node.getContent()))
    result.push(this._exportContainer(node.getCaption()))
    return result.join('\n')
  }
}
<commit_msg>Remove broken text exporter code.<commit_after>// TODO: provide a proper implementation (maybe driven by document schema) including tests
export default class ArticlePlainTextExporter {
  export (article) {
    console.error('TODO: implement full article to plain-text conversion')
  }

  exportNode (node) {
    if (node.isContainer()) {
      return this._exportContainer(node)
    } else if (node.isText()) {
      return this._exportText(node.getDocument(), node.getPath())
    }
    return ''
  }

  _exportContainer (node) {
    if (!node) return ''
    return node.getNodes().map(node => {
      return this.exportNode(node)
    }).join('\n\n')
  }

  _exportText (doc, path) {
    return doc.get(path) || ''
  }
}
<|endoftext|>


<commit_before>(function ( $ ) {
	"use strict";

	$(function () {

		// Place your administration-specific JavaScript here
		function validateURL(value){
	    	return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
	    }

		$('#uconn-banner-settings').on('submit', function() {

			var url = $("#department_url").val();
			var title = $("#department_title").val();

		    if (!validateURL(url)) {
		        alert("Please enter a valid URL, remember including http://");
		        return false;
		    } else if (title=="" || title==null) {
		    	alert("Please enter a department title.");
		    	return false;
		    } else {
		    	return true;
		    }

		});

	});

}(jQuery));

<commit_msg>testing<commit_after>(function ( $ ) {
	"use strict";

	// test

	$(function () {

		// Place your administration-specific JavaScript here
		function validateURL(value){
	    	return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
	    }

		$('#uconn-banner-settings').on('submit', function() {

			var url = $("#department_url").val();
			var title = $("#department_title").val();

		    if (!validateURL(url)) {
		        alert("Please enter a valid URL, remember including http://");
		        return false;
		    } else if (title=="" || title==null) {
		    	alert("Please enter a department title.");
		    	return false;
		    } else {
		    	return true;
		    }

		});

	});

}(jQuery));

<|endoftext|>


<commit_before>'use strict'
module.exports = stdoutToComments

const acorn = require('acorn')
const walk = require('acorn/dist/walk')
const fs = require('fs')
const spawn = require('cross-spawn-async')
const path = require('path')
const SourceMapConsumer = require('source-map').SourceMapConsumer
const normalizePath = require('normalize-path')
const hookPath = normalizePath(path.resolve(__dirname, './hook-console-log'))
const position = require('file-position')
const normalizeNewline = require('normalize-newline')
const consoleStringify = require('./console-stringify')

function stdoutToComments (opts) {
  if (typeof opts === 'string') opts = { code: opts }

  const cwd = opts.cwd || process.cwd()

  return new Promise((resolve, reject) => {
    const content = normalizeNewline(opts.code)

    const tmpFileName = normalizePath(path.resolve(cwd, `_${Math.random()}.js`))
    fs.writeFileSync(tmpFileName, addHook({
      code: content,
      filePath: tmpFileName,
    }), 'utf8')

    const outputs = []
    let failed = false

    const cp = spawn('node', [tmpFileName])
    cp.stdout.setEncoding('utf8')
    cp.stderr.setEncoding('utf8')
    cp.stdout.on('data', data => {
      try {
        data.split('\n$\n')
          .filter(outputJSON => !!outputJSON)
          .map(outputJSON => JSON.parse(outputJSON))
          .forEach(outputInfo => outputs.push(outputInfo))
      } catch (err) {
        failed = true
        reject(err)
      }
    })
    let errData = ''
    cp.stderr.on('data', data => { errData += data })
    cp.on('close', code => {
      fs.unlinkSync(tmpFileName)

      if (errData) {
        return reject(new Error(errData))
      }

      if (failed) {
        return
      }

      if (!opts.map) {
        return resolve(insertOutputsToCode(content, outputs))
      }
      const consumer = new SourceMapConsumer(opts.map)
      const originalOutputs = outputs
        .map(output => Object.assign({}, output, consumer.originalPositionFor({
          line: output.line,
          column: output.column,
        })))
      const sourcesContent = JSON.parse(opts.map).sourcesContent
      const sourceContent = sourcesContent[sourcesContent.length - 1]
      resolve(insertOutputsToCode(sourceContent, originalOutputs))
    })
  })
}

function insertOutputsToCode (content, outputs) {
  const codeLines = splitIntoLines(content)
  const sOutputs = moveOutputsBeloveStatement(outputs, codeLines, content)

  return codeLines.reduce((contentLines, line, index) => {
    contentLines.push(line)
    const lineNo = index + 1
    while (sOutputs.length && sOutputs[0].line === lineNo) {
      const matches = (contentLines[contentLines.length - 1] || '').match(/^(\s*)/)
      const linePadding = matches && matches[0] || ''
      const output = consoleStringify.apply(null, sOutputs.shift().args)
      contentLines.push(outputToComment(output, linePadding))
    }
    return contentLines
  }, []).join('\n')
}

function outputToComment (output, padding) {
  return `${padding}//> ${output.replace(/\r?\n/g, `\n${padding}//  `)}`
}

function moveOutputsBeloveStatement (outputs, codeLines, content) {
  const ast = acorn.parse(content, {locations: true, sourceType: 'module'})
  const getPosition = position(content)

  return outputs.reduce((semanticOutput, output) => {
    const pos = getPosition(output.line - 1, output.column)
    const semanticLineNo = outputSemanticPosition(ast, pos)
    return semanticOutput.concat(Object.assign(
      {},
      output,
      {
        line: semanticLineNo,
      }
    ))
  }, [])
}

function splitIntoLines (txt) {
  return txt.split('\n')
}

function outputSemanticPosition (ast, pos) {
  const node = walk.findNodeAround(ast, pos, 'ExpressionStatement')
  return node.node.loc.end.line
}

function addHook (opts) {
  if (!opts.code.match(/['"]use strict['"]/)) {
    return `require('${hookPath}')('${opts.filePath}');\n` + opts.code
  }
  return `'use strict';require('${hookPath}')('${opts.filePath}');\n` + opts.code
}
<commit_msg>refactor(stdout-to-comments): rename content to code<commit_after>'use strict'
module.exports = stdoutToComments

const acorn = require('acorn')
const walk = require('acorn/dist/walk')
const fs = require('fs')
const spawn = require('cross-spawn-async')
const path = require('path')
const SourceMapConsumer = require('source-map').SourceMapConsumer
const normalizePath = require('normalize-path')
const hookPath = normalizePath(path.resolve(__dirname, './hook-console-log'))
const position = require('file-position')
const normalizeNewline = require('normalize-newline')
const consoleStringify = require('./console-stringify')

function stdoutToComments (opts) {
  if (typeof opts === 'string') opts = { code: opts }

  const cwd = opts.cwd || process.cwd()

  return new Promise((resolve, reject) => {
    const code = normalizeNewline(opts.code)

    const tmpFileName = normalizePath(path.resolve(cwd, `_${Math.random()}.js`))
    fs.writeFileSync(tmpFileName, addHook({
      code,
      filePath: tmpFileName,
    }), 'utf8')

    const outputs = []
    let failed = false

    const cp = spawn('node', [tmpFileName])
    cp.stdout.setEncoding('utf8')
    cp.stderr.setEncoding('utf8')
    cp.stdout.on('data', data => {
      try {
        data.split('\n$\n')
          .filter(outputJSON => !!outputJSON)
          .map(outputJSON => JSON.parse(outputJSON))
          .forEach(outputInfo => outputs.push(outputInfo))
      } catch (err) {
        failed = true
        reject(err)
      }
    })
    let errData = ''
    cp.stderr.on('data', data => { errData += data })
    cp.on('close', () => {
      fs.unlinkSync(tmpFileName)

      if (errData) {
        return reject(new Error(errData))
      }

      if (failed) {
        return
      }

      if (!opts.map) {
        return resolve(insertOutputsToCode(code, outputs))
      }
      const consumer = new SourceMapConsumer(opts.map)
      const originalOutputs = outputs
        .map(output => Object.assign({}, output, consumer.originalPositionFor({
          line: output.line,
          column: output.column,
        })))
      const sourcesContent = JSON.parse(opts.map).sourcesContent
      const sourceContent = sourcesContent[sourcesContent.length - 1]
      resolve(insertOutputsToCode(sourceContent, originalOutputs))
    })
  })
}

function insertOutputsToCode (code, outputs) {
  const codeLines = splitIntoLines(code)
  const sOutputs = moveOutputsBeloveStatement(outputs, codeLines, code)

  return codeLines.reduce((contentLines, line, index) => {
    contentLines.push(line)
    const lineNo = index + 1
    while (sOutputs.length && sOutputs[0].line === lineNo) {
      const matches = (contentLines[contentLines.length - 1] || '').match(/^(\s*)/)
      const linePadding = matches && matches[0] || ''
      const output = consoleStringify.apply(null, sOutputs.shift().args)
      contentLines.push(outputToComment(output, linePadding))
    }
    return contentLines
  }, []).join('\n')
}

function outputToComment (output, padding) {
  return `${padding}//> ${output.replace(/\r?\n/g, `\n${padding}//  `)}`
}

function moveOutputsBeloveStatement (outputs, codeLines, content) {
  const ast = acorn.parse(content, {locations: true, sourceType: 'module'})
  const getPosition = position(content)

  return outputs.reduce((semanticOutput, output) => {
    const pos = getPosition(output.line - 1, output.column)
    const semanticLineNo = outputSemanticPosition(ast, pos)
    return semanticOutput.concat(Object.assign(
      {},
      output,
      {
        line: semanticLineNo,
      }
    ))
  }, [])
}

function splitIntoLines (txt) {
  return txt.split('\n')
}

function outputSemanticPosition (ast, pos) {
  const node = walk.findNodeAround(ast, pos, 'ExpressionStatement')
  return node.node.loc.end.line
}

function addHook (opts) {
  if (!opts.code.match(/['"]use strict['"]/)) {
    return `require('${hookPath}')('${opts.filePath}');\n` + opts.code
  }
  return `'use strict';require('${hookPath}')('${opts.filePath}');\n` + opts.code
}
<|endoftext|>