<commit_before>// ui functions
ZenPen = window.ZenPen || {};
ZenPen.ui = (function() {

	// Base elements
	var body, article, uiContainer, overlay, aboutButton, descriptionModal, header;

	// Buttons
	var screenSizeElement, colorLayoutElement, targetElement, saveElement;

	// Tabs
	var addTabElement, tabsElement, tabs;

	// Word Counter
	var wordCountValue, wordCountBox, wordCountElement, wordCounter, wordCounterProgress;

	//save support
	var supportSave, saveFormat, textToWrite;

	var expandScreenIcon = '';
	var shrinkScreenIcon = '';

	var darkLayout = false;

	function init() {

		supportsSave = !!new Blob()?true:false;

		bindElements();

		wordCountActive = false;

		if ( ZenPen.util.supportsHtmlStorage() ) {
			loadState();
		}

		console.log( "Checkin under the hood eh? We've probably got a lot in common. You should totally check out ZenPen on github! (https://github.com/tholman/zenpen)." );
	}

	function handleStorage ( event ) {
		console.log('storage', event);
	}

	function loadState() {

		// Activate word counter
		if ( localStorage['wordCount'] && localStorage['wordCount'] !== "0") {
			wordCountValue = parseInt(localStorage['wordCount']);
			wordCountElement.value = localStorage['wordCount'];
			wordCounter.className = "word-counter active";
			updateWordCount();
		}

		// Activate color switch
		if ( localStorage['darkLayout'] === 'true' ) {
			if ( darkLayout === false ) {
				document.body.className = 'yang';
			} else {
				document.body.className = 'yin';
			}
			darkLayout = !darkLayout;
		}

		if ( localStorage['tabs'] ) {
			tabs = JSON.parse(localStorage['tabs']);
			tabs.forEach(function (t) {
				appendTab(t);
			});
		}
	}

	function saveState() {

		if ( ZenPen.util.supportsHtmlStorage() ) {
			localStorage[ 'darkLayout' ] = darkLayout;
			localStorage[ 'wordCount' ] = wordCountElement.value;
		}
	}

	function bindElements() {

		// Body element for light/dark styles
		body = document.body;

		uiContainer = document.querySelector( '.ui' );

		// UI element for color flip
		colorLayoutElement = document.querySelector( '.color-flip' );
		colorLayoutElement.onclick = onColorLayoutClick;

		// UI element for full screen
		screenSizeElement = document.querySelector( '.fullscreen' );
		screenSizeElement.onclick = onScreenSizeClick;

		targetElement = document.querySelector( '.target ');
		targetElement.onclick = onTargetClick;

		//init event listeners only if browser can save
		if (supportsSave) {

			saveElement = document.querySelector( '.save' );
			saveElement.onclick = onSaveClick;

			var formatSelectors = document.querySelectorAll( '.saveselection span' );
			for( var i in formatSelectors ) {
				formatSelectors[i].onclick = selectFormat;
			}

			document.querySelector('.savebutton').onclick = saveText;
		} else {
			document.querySelector('.save.useicons').style.display = "none";
		}

		// Overlay when modals are active
		overlay = document.querySelector( '.overlay' );
		overlay.onclick = onOverlayClick;

		article = document.querySelector( '.content' );
		article.onkeyup = onArticleKeyUp;

		wordCountBox = overlay.querySelector( '.wordcount' );
		wordCountElement = wordCountBox.querySelector( 'input' );
		wordCountElement.onchange = onWordCountChange;
		wordCountElement.onkeyup = onWordCountKeyUp;

		descriptionModal = overlay.querySelector( '.description' );

		saveModal = overlay.querySelector('.saveoverlay');

		wordCounter = document.querySelector( '.word-counter' );
		wordCounterProgress = wordCounter.querySelector( '.progress' );

		aboutButton = document.querySelector( '.about' );
		aboutButton.onclick = onAboutButtonClick;

		header = document.querySelector( '.header' );
		header.onkeypress = onHeaderKeyPress;

		tabsElement = document.querySelector( '.tabs' );
		tabsElement.onclick = onTabClick;
		addTabElement = document.querySelector( '.add-tab' );
		addTabElement.onclick = onAddTabClick;
	}

	function onTabClick ( event ) {
		var target = event.target,
			tabId;

		// clicked on the span not on the button
		if (!target.matches('button')) {
			target = target.parentNode;
		}

		if ( target.hasAttribute('data-tabid') ) {
			tabId = target.getAttribute('data-tabid');
			ZenPen.editor.loadTab(tabId);
			[].forEach.call(target.parentNode.childNodes, function (n) {
				if ( n.classList ) {
					n.classList.remove('current');
				}
			});
			target.classList.add('current');
		}

		if ( target.classList.contains('tab-remove')) {
			target = target.parentNode;
			removeTab(target.getAttribute('data-tabid'));
		}
	};

	function tabTitleChange ( id, title ) {
		findTabButton(id, 'span').innerText = title;
	}

	function onAddTabClick( event ) {
		var newTab = ZenPen.editor.addTab(),
			btn = appendTab( newTab );

		[].forEach.call(btn.parentNode.childNodes, function (n) {
			if ( n.classList ) {
				n.classList.remove('current');
			}
		});
		btn.classList.add('current');
	};

	function appendTab ( tabId ) {
		var tabBtn = document.createElement('button'),
			title = localStorage[tabId + '.header' ];

		tabsElement.appendChild(tabBtn);
		tabBtn.setAttribute('data-tabid', tabId);
		tabBtn.setAttribute('title', title);
		tabBtn.classList.add('tab');
		tabBtn.innerHTML = '<button class="tab-remove">x</button>' +
			'' + title + '';

		return tabBtn;
	}

	function removeTab ( tabId ) {
		var ix = tabs.indexOf(tabId),
			tabClone = tabs.slice(0),
			savePrepend = tabId + '.';

		tabClone.slice(ix, ix + 1);
		localStorage.removeItem(savePrepend + 'header');
		localStorage.removeItem(savePrepend + 'content');
		localStorage['tabs'] = JSON.stringify(tabClone);
		findTabButton(tabId).remove();
	}

	function findTabButton ( id, child ) {
		var sel = 'button[data-tabid="' + id + '"]';
		if ( child ) {
			sel += ' ' + child;
		}
		return document.querySelector(sel);
	}

	function onScreenSizeClick( event ) {

		screenfull.toggle();
   		if ( screenfull.enabled ) {
			document.addEventListener( screenfull.raw.fullscreenchange, function () {
				if ( screenfull.isFullscreen ) {
					screenSizeElement.innerHTML = shrinkScreenIcon;
				} else {
					screenSizeElement.innerHTML = expandScreenIcon;
				}
    		});
    	}
	};

	function onColorLayoutClick( event ) {
		if ( darkLayout === false ) {
			document.body.className = 'yang';
		} else {
			document.body.className = 'yin';
		}
		darkLayout = !darkLayout;

		saveState();
	}

	function onTargetClick( event ) {
		overlay.style.display = "block";
		wordCountBox.style.display = "block";
		wordCountElement.focus();
	}

	function onAboutButtonClick( event ) {
		overlay.style.display = "block";
		descriptionModal.style.display = "block";
	}

	function onSaveClick( event ) {
		overlay.style.display = "block";
		saveModal.style.display = "block";
	}

	function saveText( event ) {

		if (typeof saveFormat != 'undefined' && saveFormat != '') {
			var blob = new Blob([textToWrite], {type: "text/plain;charset=utf-8"});
			/* remove tabs and line breaks from header */
			var headerText = header.innerHTML.replace(/(\t|\n|\r)/gm,"");
			if (headerText === "") {
			    headerText = "ZenPen";
			}
			saveAs(blob, headerText + '.txt');
		} else {
			document.querySelector('.saveoverlay h1').style.color = '#FC1E1E';
		}
	}

	/* Allows the user to press enter to tab from the title */
	function onHeaderKeyPress( event ) {

		if ( event.keyCode === 13 ) {
			event.preventDefault();
			article.focus();
		}
	}

	/* Allows the user to press enter to tab from the word count modal */
	function onWordCountKeyUp( event ) {

		if ( event.keyCode === 13 ) {
			event.preventDefault();

			setWordCount( parseInt(this.value) );

			removeOverlay();

			article.focus();
		}
	}

	function onWordCountChange( event ) {

		setWordCount( parseInt(this.value) );
	}

	function setWordCount( count ) {

		// Set wordcount ui to active
		if ( count > 0) {

			wordCountValue = count;
			wordCounter.className = "word-counter active";
			updateWordCount();

		} else {

			wordCountValue = 0;
			wordCounter.className = "word-counter";
		}

		saveState();
	}

	function onArticleKeyUp( event ) {

		if ( wordCountValue > 0 ) {
			updateWordCount();
		}
	}

	function updateWordCount() {

		var wordCount = ZenPen.editor.getWordCount();
		var percentageComplete = wordCount / wordCountValue;
		wordCounterProgress.style.height = percentageComplete * 100 + '%';

		if ( percentageComplete >= 1 ) {
			wordCounterProgress.className = "progress complete";
		} else {
			wordCounterProgress.className = "progress";
		}
	}

	function selectFormat( e ) {

		if ( document.querySelectorAll('span.activesave').length > 0 ) {
			document.querySelector('span.activesave').className = '';
		}

		document.querySelector('.saveoverlay h1').style.cssText = '';

		var targ;
		if (!e) var e = window.event;
		if (e.target) targ = e.target;
		else if (e.srcElement) targ = e.srcElement;

		// defeat Safari bug
		if (targ.nodeType == 3) {
			targ = targ.parentNode;
		}

		targ.className ='activesave';

		saveFormat = targ.getAttribute('data-format');

		var header = document.querySelector('header.header');
		var headerText = header.innerHTML.replace(/(\r\n|\n|\r)/gm,"") + "\n";

		var body = document.querySelector('article.content');
		var bodyText = body.innerHTML;

		textToWrite = formatText(saveFormat,headerText,bodyText);

		var textArea = document.querySelector('.hiddentextbox');
		textArea.value = textToWrite;
		textArea.focus();
		textArea.select();

	}

	function formatText( type, header, body ) {

		var text;
		switch( type ) {

			case 'html':
				header = "
" + header + "
";
				text = header + body;
				text = text.replace(/\t/g, '');
			break;

			case 'markdown':
				header = header.replace(/\t/g, '');
				header = header.replace(/\n$/, '');
				header = "#" + header + "#";

				text = body.replace(/\t/g, '');

				text = text.replace(/|<\/b>/g,"**")
					.replace(/\r\n+|\r+|\n+|\t+/ig,"")
					.replace(/|<\/i>/g,"_")
					.replace(/
/g,"> ")
					.replace(/<\/blockquote>/g,"")
					.replace(/
|<\/p>/gi,"\n")
					.replace(/
/g,"\n");

				var links = text.match(/(.+)<\/a>/gi);

                                if (links !== null) {
                                        for ( var i = 0; i<links.length; i++ ) {
                                                var tmpparent = document.createElement('div');
                                                tmpparent.innerHTML = links[i];

                                                var tmp = tmpparent.firstChild;

                                                var href = tmp.getAttribute('href');
                                                var linktext = tmp.textContent || tmp.innerText || "";

                                                text = text.replace(links[i],'['+linktext+']('+href+')');
                                        }
                                }

				text = header +"\n\n"+ text;
			break;

			case 'plain':
				header = header.replace(/\t/g, '');

				var tmp = document.createElement('div');
				tmp.innerHTML = body;
				text = tmp.textContent || tmp.innerText || "";

				text = text.replace(/\t/g, '')
					.replace(/\n{3}/g,"\n")
					.replace(/\n/,""); //replace the opening line break

				text = header + text;
			break;
			default:
			break;
		}

		return text;
	}

	function onOverlayClick( event ) {

		if ( event.target.className === "overlay" ) {
			removeOverlay();
		}
	}

	function removeOverlay() {

		overlay.style.display = "none";
		wordCountBox.style.display = "none";
		descriptionModal.style.display = "none";
		saveModal.style.display = "none";

		if ( document.querySelectorAll('span.activesave' ).length > 0) {
			document.querySelector('span.activesave').className = '';
		}

		saveFormat='';
	}

	return {
		init: init,
		tabTitleChange: tabTitleChange
	}

})();
<commit_msg>fix a tab delete issue<commit_after>// ui functions
ZenPen = window.ZenPen || {};
ZenPen.ui = (function() {

	// Base elements
	var body, article, uiContainer, overlay, aboutButton, descriptionModal, header;

	// Buttons
	var screenSizeElement, colorLayoutElement, targetElement, saveElement;

	// Tabs
	var addTabElement, tabsElement, tabs;

	// Word Counter
	var wordCountValue, wordCountBox, wordCountElement, wordCounter, wordCounterProgress;

	//save support
	var supportSave, saveFormat, textToWrite;

	var expandScreenIcon = '';
	var shrinkScreenIcon = '';

	var darkLayout = false;

	function init() {

		supportsSave = !!new Blob()?true:false;

		bindElements();

		wordCountActive = false;

		if ( ZenPen.util.supportsHtmlStorage() ) {
			loadState();
		}

		console.log( "Checkin under the hood eh? We've probably got a lot in common. You should totally check out ZenPen on github! (https://github.com/tholman/zenpen)." );
	}

	function handleStorage ( event ) {
		console.log('storage', event);
	}

	function loadState() {

		// Activate word counter
		if ( localStorage['wordCount'] && localStorage['wordCount'] !== "0") {
			wordCountValue = parseInt(localStorage['wordCount']);
			wordCountElement.value = localStorage['wordCount'];
			wordCounter.className = "word-counter active";
			updateWordCount();
		}

		// Activate color switch
		if ( localStorage['darkLayout'] === 'true' ) {
			if ( darkLayout === false ) {
				document.body.className = 'yang';
			} else {
				document.body.className = 'yin';
			}
			darkLayout = !darkLayout;
		}

		if ( localStorage['tabs'] ) {
			tabs = JSON.parse(localStorage['tabs']);
			tabs.forEach(function (t) {
				appendTab(t);
			});
		}
	}

	function saveState() {

		if ( ZenPen.util.supportsHtmlStorage() ) {
			localStorage[ 'darkLayout' ] = darkLayout;
			localStorage[ 'wordCount' ] = wordCountElement.value;
		}
	}

	function bindElements() {

		// Body element for light/dark styles
		body = document.body;

		uiContainer = document.querySelector( '.ui' );

		// UI element for color flip
		colorLayoutElement = document.querySelector( '.color-flip' );
		colorLayoutElement.onclick = onColorLayoutClick;

		// UI element for full screen
		screenSizeElement = document.querySelector( '.fullscreen' );
		screenSizeElement.onclick = onScreenSizeClick;

		targetElement = document.querySelector( '.target ');
		targetElement.onclick = onTargetClick;

		//init event listeners only if browser can save
		if (supportsSave) {

			saveElement = document.querySelector( '.save' );
			saveElement.onclick = onSaveClick;

			var formatSelectors = document.querySelectorAll( '.saveselection span' );
			for( var i in formatSelectors ) {
				formatSelectors[i].onclick = selectFormat;
			}

			document.querySelector('.savebutton').onclick = saveText;
		} else {
			document.querySelector('.save.useicons').style.display = "none";
		}

		// Overlay when modals are active
		overlay = document.querySelector( '.overlay' );
		overlay.onclick = onOverlayClick;

		article = document.querySelector( '.content' );
		article.onkeyup = onArticleKeyUp;

		wordCountBox = overlay.querySelector( '.wordcount' );
		wordCountElement = wordCountBox.querySelector( 'input' );
		wordCountElement.onchange = onWordCountChange;
		wordCountElement.onkeyup = onWordCountKeyUp;

		descriptionModal = overlay.querySelector( '.description' );

		saveModal = overlay.querySelector('.saveoverlay');

		wordCounter = document.querySelector( '.word-counter' );
		wordCounterProgress = wordCounter.querySelector( '.progress' );

		aboutButton = document.querySelector( '.about' );
		aboutButton.onclick = onAboutButtonClick;

		header = document.querySelector( '.header' );
		header.onkeypress = onHeaderKeyPress;

		tabsElement = document.querySelector( '.tabs' );
		tabsElement.onclick = onTabClick;
		addTabElement = document.querySelector( '.add-tab' );
		addTabElement.onclick = onAddTabClick;
	}

	function onTabClick ( event ) {
		var target = event.target,
			tabId;

		// clicked on the span not on the button
		if (!target.matches('button')) {
			target = target.parentNode;
		}

		if ( target.hasAttribute('data-tabid') ) {
			tabId = target.getAttribute('data-tabid');
			ZenPen.editor.loadTab(tabId);
			[].forEach.call(target.parentNode.childNodes, function (n) {
				if ( n.classList ) {
					n.classList.remove('current');
				}
			});
			target.classList.add('current');
		}

		if ( target.classList.contains('tab-remove')) {
			target = target.parentNode;
			removeTab(target.getAttribute('data-tabid'));
		}
	};

	function tabTitleChange ( id, title ) {
		var tabBtn = findTabButton(id, 'span');
		if (tabBtn) {
			tabBtn.innerText = title;
		}
	}

	function onAddTabClick( event ) {
		var newTab = ZenPen.editor.addTab(),
			btn = appendTab( newTab );

		[].forEach.call(btn.parentNode.childNodes, function (n) {
			if ( n.classList ) {
				n.classList.remove('current');
			}
		});
		btn.classList.add('current');
	};

	function appendTab ( tabId ) {
		var tabBtn = document.createElement('button'),
			title = localStorage[tabId + '.header' ];

		tabsElement.appendChild(tabBtn);
		tabBtn.setAttribute('data-tabid', tabId);
		tabBtn.setAttribute('title', title);
		tabBtn.classList.add('tab');
		tabBtn.innerHTML = '<button class="tab-remove">x</button>' +
			'' + title + '';

		return tabBtn;
	}

	function removeTab ( tabId ) {
		var ix = tabs.indexOf(tabId),
			tabClone = tabs.slice(0),
			savePrepend = tabId + '.';

		tabClone.splice(ix, 1);
		tabs = tabClone;
		localStorage.removeItem(savePrepend + 'header');
		localStorage.removeItem(savePrepend + 'content');
		localStorage['tabs'] = JSON.stringify(tabClone);
		findTabButton(tabId).remove();
	}

	function findTabButton ( id, child ) {
		var sel = 'button[data-tabid="' + id + '"]';
		if ( child ) {
			sel += ' ' + child;
		}
		return document.querySelector(sel);
	}

	function onScreenSizeClick( event ) {

		screenfull.toggle();
   		if ( screenfull.enabled ) {
			document.addEventListener( screenfull.raw.fullscreenchange, function () {
				if ( screenfull.isFullscreen ) {
					screenSizeElement.innerHTML = shrinkScreenIcon;
				} else {
					screenSizeElement.innerHTML = expandScreenIcon;
				}
    		});
    	}
	};

	function onColorLayoutClick( event ) {
		if ( darkLayout === false ) {
			document.body.className = 'yang';
		} else {
			document.body.className = 'yin';
		}
		darkLayout = !darkLayout;

		saveState();
	}

	function onTargetClick( event ) {
		overlay.style.display = "block";
		wordCountBox.style.display = "block";
		wordCountElement.focus();
	}

	function onAboutButtonClick( event ) {
		overlay.style.display = "block";
		descriptionModal.style.display = "block";
	}

	function onSaveClick( event ) {
		overlay.style.display = "block";
		saveModal.style.display = "block";
	}

	function saveText( event ) {

		if (typeof saveFormat != 'undefined' && saveFormat != '') {
			var blob = new Blob([textToWrite], {type: "text/plain;charset=utf-8"});
			/* remove tabs and line breaks from header */
			var headerText = header.innerHTML.replace(/(\t|\n|\r)/gm,"");
			if (headerText === "") {
			    headerText = "ZenPen";
			}
			saveAs(blob, headerText + '.txt');
		} else {
			document.querySelector('.saveoverlay h1').style.color = '#FC1E1E';
		}
	}

	/* Allows the user to press enter to tab from the title */
	function onHeaderKeyPress( event ) {

		if ( event.keyCode === 13 ) {
			event.preventDefault();
			article.focus();
		}
	}

	/* Allows the user to press enter to tab from the word count modal */
	function onWordCountKeyUp( event ) {

		if ( event.keyCode === 13 ) {
			event.preventDefault();

			setWordCount( parseInt(this.value) );

			removeOverlay();

			article.focus();
		}
	}

	function onWordCountChange( event ) {

		setWordCount( parseInt(this.value) );
	}

	function setWordCount( count ) {

		// Set wordcount ui to active
		if ( count > 0) {

			wordCountValue = count;
			wordCounter.className = "word-counter active";
			updateWordCount();

		} else {

			wordCountValue = 0;
			wordCounter.className = "word-counter";
		}

		saveState();
	}

	function onArticleKeyUp( event ) {

		if ( wordCountValue > 0 ) {
			updateWordCount();
		}
	}

	function updateWordCount() {

		var wordCount = ZenPen.editor.getWordCount();
		var percentageComplete = wordCount / wordCountValue;
		wordCounterProgress.style.height = percentageComplete * 100 + '%';

		if ( percentageComplete >= 1 ) {
			wordCounterProgress.className = "progress complete";
		} else {
			wordCounterProgress.className = "progress";
		}
	}

	function selectFormat( e ) {

		if ( document.querySelectorAll('span.activesave').length > 0 ) {
			document.querySelector('span.activesave').className = '';
		}

		document.querySelector('.saveoverlay h1').style.cssText = '';

		var targ;
		if (!e) var e = window.event;
		if (e.target) targ = e.target;
		else if (e.srcElement) targ = e.srcElement;

		// defeat Safari bug
		if (targ.nodeType == 3) {
			targ = targ.parentNode;
		}

		targ.className ='activesave';

		saveFormat = targ.getAttribute('data-format');

		var header = document.querySelector('header.header');
		var headerText = header.innerHTML.replace(/(\r\n|\n|\r)/gm,"") + "\n";

		var body = document.querySelector('article.content');
		var bodyText = body.innerHTML;

		textToWrite = formatText(saveFormat,headerText,bodyText);

		var textArea = document.querySelector('.hiddentextbox');
		textArea.value = textToWrite;
		textArea.focus();
		textArea.select();

	}

	function formatText( type, header, body ) {

		var text;
		switch( type ) {

			case 'html':
				header = "
" + header + "
";
				text = header + body;
				text = text.replace(/\t/g, '');
			break;

			case 'markdown':
				header = header.replace(/\t/g, '');
				header = header.replace(/\n$/, '');
				header = "#" + header + "#";

				text = body.replace(/\t/g, '');

				text = text.replace(/|<\/b>/g,"**")
					.replace(/\r\n+|\r+|\n+|\t+/ig,"")
					.replace(/|<\/i>/g,"_")
					.replace(/
/g,"> ")
					.replace(/<\/blockquote>/g,"")
					.replace(/
|<\/p>/gi,"\n")
					.replace(/
/g,"\n");

				var links = text.match(/(.+)<\/a>/gi);

                                if (links !== null) {
                                        for ( var i = 0; i<links.length; i++ ) {
                                                var tmpparent = document.createElement('div');
                                                tmpparent.innerHTML = links[i];

                                                var tmp = tmpparent.firstChild;

                                                var href = tmp.getAttribute('href');
                                                var linktext = tmp.textContent || tmp.innerText || "";

                                                text = text.replace(links[i],'['+linktext+']('+href+')');
                                        }
                                }

				text = header +"\n\n"+ text;
			break;

			case 'plain':
				header = header.replace(/\t/g, '');

				var tmp = document.createElement('div');
				tmp.innerHTML = body;
				text = tmp.textContent || tmp.innerText || "";

				text = text.replace(/\t/g, '')
					.replace(/\n{3}/g,"\n")
					.replace(/\n/,""); //replace the opening line break

				text = header + text;
			break;
			default:
			break;
		}

		return text;
	}

	function onOverlayClick( event ) {

		if ( event.target.className === "overlay" ) {
			removeOverlay();
		}
	}

	function removeOverlay() {

		overlay.style.display = "none";
		wordCountBox.style.display = "none";
		descriptionModal.style.display = "none";
		saveModal.style.display = "none";

		if ( document.querySelectorAll('span.activesave' ).length > 0) {
			document.querySelector('span.activesave').className = '';
		}

		saveFormat='';
	}

	return {
		init: init,
		tabTitleChange: tabTitleChange
	}

})();
<|endoftext|>


<commit_before>/**
 * FN is a functional library providing functions
 * inspired (ripped off) by LISP/Clojure.
 *
 * No, I have no shame.
 *
 * This is kinda just research, experimenting with
 * functional programming in JS. If you however
 * find this library useful let me know and I'll
 * keep working on it, if you have suggestions, I
 * might even incorporate your ideas.
 *
 * This is designed to be used from within ES6.
 * Other older versions of ES may not work properly.
 *
 * Copyright (c) Neil Munro 2015-2016.
 * @author Neil Munro <neilmunro@gmail.com>
 */

/*
 * Throw FN into it's own frozen constant variable.
 * Hopefully this means users can't fiddle with it.
 */
const FN = Object.freeze(Object.create({
  /**
   * FN.any is a function which evaluates a number of
   * expressions and runs a callback function if
   * any of the expressions are true.
   *
   * Example:
   * FN.any(() => {
   *   console.log("One of the expressions is true.");
   * }, 1 === 1, 5 === 5);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to any. Any takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if no expressions
   * evaluated to true or the users didn't pass in a callback.
   */
  "any": (cb, ...lst) => {
    "use strict";
    var result = false;

    lst.forEach((element) => { if(element) result = true; });

    return(cb !== undefined && result) ? cb() : undefined;
  },

  /**
   * FN.all is a function which evaluates a number of
   * expressions and runs a callback function if
   * all of the expressions are true.
   *
   * Example:
   * FN.all(() => {
   *   console.log("All of the expressions are true.");
   * }, 1 === 1, 5 === 5);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to all. All takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if even one
   * expression evaluated to false or the user didn't pass in a callback.
   */
  "all": (cb, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb !== undefined && result) ? cb() : undefined;
  },

  /**
   * FN.first runs a callback with the first element of
   * a list as its one and only parameter. The list
   * in question is just a set of values passed to first.
   *
   * Example:
   * FN.first((firstElement) => {
   *   console.log(firstElement);
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (firstElement) =>  {...}
   * @param {array} lst - The arguments to first. First takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or at least one element passed into first.
   */
  "first": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[0] !== undefined) ? cb(lst[0]) : undefined;
  },

  /**
   * FN.last is the inverse of FN.first and instead of
   * passing the first element of a list into a callback
   * passes the last element passed to FN.last.
   *
   * Example:
   * FN.last((lastElement) => {
   *   console.log(lastElement);
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (lastElement) =>  {...}
   * @param {array} lst - The arguments to last. Last takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or at least one element passed into last.
   * @see FN.first
   */
  "last": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[0] !== undefined) ? cb(lst[lst.length-1]) :
      (lst[lst.length-1] !== undefined) ? lst[lst.length-1] : undefined;
  },

  /**
   * FN.nth complements FN.first and FN.last by providing
   * a means to grab an arbitrary element in a list by numeric
   * index. The callback is executed with the second argument to
   * FN.nth being the index and the rest of the arguments converted
   * to the list of items to grab the index of.
   *
   * Example:
   * FN.nth((nthElement) => {
   *   console.log(nthElement);
   * }, 2, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (nthElement) =>  {...}
   * @param {number} n - The nth element in the list to try and get.
   * @param {array} lst - The arguments to nth. Nth takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or the nth element does not exist.
   * @see FN.first
   * @see FN.last
   */
  "nth": (cb, n, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[n] !== undefined) ? cb(n, lst[n]) : undefined;
  },

  /**
   * FN.rest complements FN.first by passing everything
   * execept the first element into a callback.
   *
   * Example:
   * FN.rest((remainingElements) => {
   *   remainingElements.forEach((element) => {
   *    console.log(element);
   *   });
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (remainingElements) =>  {...}
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback, a list or the argument list is smaller than one.
   * @see FN.first
   */
  "rest": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst !== undefined && lst.length > 1) ? cb(lst.slice(1)) : undefined;
  },

  /**
   * FN.take runs the supplied callback with a number and a
   * list of items. The supplied callback is executed with
   * an array containing the first n elements in the list of
   * items passed into FN.take.
   *
   * Example:
   * FN.take((elements) => {
   *   elements.forEach((element) => {
   *     console.log(element);
   *   });
   * }, 2, "Lions", "Tigers", "Bears");
   *
   * @param {function} cb - The callback to execute in the form: (elements) =>  {...}
   * @param {number} n - The number of elements to take from the remaining arguments.
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   */
  "take": (cb, n, ...lst) => {
    "use strict";
    return(cb !== undefined && n !== undefined) ? cb(lst.slice(0, n)) : undefined;
  },

  /**
   * FN.if is a single branch function. It expects a
   * callback and any number of values. The values
   * are treated as if they were a list and the
   * callback is executed with no arguments.
   *
   * Example:
   * FN.if(() => {
   *   console.log("Is true");
   * }, 1 === 1, 2 === 2);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   * @see FN.ifElse
   */
  "if": (cb, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb !== undefined && lst !== undefined && lst.length > 0 && result) ? cb() : undefined;
  },

  /**
   * FN.ifElse expands upon FN.if by permitting the user
   * to provide a second callback function to be executed
   * in the event that the if expression evaluates to false.
   *
   * NOTE: Multiple FNi.fElse can be nested inside of the callback functions.
   *
   * Example:
   * FN.ifElse(() => {
   *   console.log("Is true");
   * }, () => {
   *  console.log("Is false");
   * }, 1 === 1, 2 === 2);
   *
   * @param {function} cb1 - The callback to execute in the form: () =>  {...} if true.
   * @param {function} cb2 - The callback to execute in the form: () =>  {...} if false.
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   * @see FN.if
   */
  "ifElse": (cb1, cb2, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb1 !== undefined && cb2 !== undefined && lst !== undefined && lst.length > 0 && result) ? cb1() : cb2();
  },

  /**
   * FN.let creates a new isolated execution context with a set of values initilised
   * within the context and visible only for the duration of the callback function.
   * Note that it acts as a closure and does have access to outer variables.
   *
   * Example:
   * FN.let(() => {
	 *   console.log(`Hi my name is ${name} and I am ${age} years old.`);
	 * }, {"age": 29, "name": "Neil Munro"});
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}.
   * @param {object} objectContext - An object containing the key/value pairs
	 * that are to be created inside the execution context.
	 * @return The return value of the callback function.
   * @see FN.if
   */
	"let": (cb, objectContext) => {
    "use strict";
		return(() => {
			Object.keys(objectContext).forEach((key) => this[key] = objectContext[key]);
			return cb.call(this);
		})();
	}
}));
<commit_msg>Fixed indentation.<commit_after>/**
 * FN is a functional library providing functions
 * inspired (ripped off) by LISP/Clojure.
 *
 * No, I have no shame.
 *
 * This is kinda just research, experimenting with
 * functional programming in JS. If you however
 * find this library useful let me know and I'll
 * keep working on it, if you have suggestions, I
 * might even incorporate your ideas.
 *
 * This is designed to be used from within ES6.
 * Other older versions of ES may not work properly.
 *
 * Copyright (c) Neil Munro 2015-2016.
 * @author Neil Munro <neilmunro@gmail.com>
 */

/*
 * Throw FN into it's own frozen constant variable.
 * Hopefully this means users can't fiddle with it.
 */
const FN = Object.freeze(Object.create({
  /**
   * FN.any is a function which evaluates a number of
   * expressions and runs a callback function if
   * any of the expressions are true.
   *
   * Example:
   * FN.any(() => {
   *   console.log("One of the expressions is true.");
   * }, 1 === 1, 5 === 5);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to any. Any takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if no expressions
   * evaluated to true or the users didn't pass in a callback.
   */
  "any": (cb, ...lst) => {
    "use strict";
    var result = false;

    lst.forEach((element) => { if(element) result = true; });

    return(cb !== undefined && result) ? cb() : undefined;
  },

  /**
   * FN.all is a function which evaluates a number of
   * expressions and runs a callback function if
   * all of the expressions are true.
   *
   * Example:
   * FN.all(() => {
   *   console.log("All of the expressions are true.");
   * }, 1 === 1, 5 === 5);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to all. All takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if even one
   * expression evaluated to false or the user didn't pass in a callback.
   */
  "all": (cb, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb !== undefined && result) ? cb() : undefined;
  },

  /**
   * FN.first runs a callback with the first element of
   * a list as its one and only parameter. The list
   * in question is just a set of values passed to first.
   *
   * Example:
   * FN.first((firstElement) => {
   *   console.log(firstElement);
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (firstElement) =>  {...}
   * @param {array} lst - The arguments to first. First takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or at least one element passed into first.
   */
  "first": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[0] !== undefined) ? cb(lst[0]) : undefined;
  },

  /**
   * FN.last is the inverse of FN.first and instead of
   * passing the first element of a list into a callback
   * passes the last element passed to FN.last.
   *
   * Example:
   * FN.last((lastElement) => {
   *   console.log(lastElement);
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (lastElement) =>  {...}
   * @param {array} lst - The arguments to last. Last takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or at least one element passed into last.
   * @see FN.first
   */
  "last": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[0] !== undefined) ? cb(lst[lst.length-1]) :
      (lst[lst.length-1] !== undefined) ? lst[lst.length-1] : undefined;
  },

  /**
   * FN.nth complements FN.first and FN.last by providing
   * a means to grab an arbitrary element in a list by numeric
   * index. The callback is executed with the second argument to
   * FN.nth being the index and the rest of the arguments converted
   * to the list of items to grab the index of.
   *
   * Example:
   * FN.nth((nthElement) => {
   *   console.log(nthElement);
   * }, 2, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (nthElement) =>  {...}
   * @param {number} n - The nth element in the list to try and get.
   * @param {array} lst - The arguments to nth. Nth takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback or the nth element does not exist.
   * @see FN.first
   * @see FN.last
   */
  "nth": (cb, n, ...lst) => {
    "use strict";
    return(cb !== undefined && lst[n] !== undefined) ? cb(n, lst[n]) : undefined;
  },

  /**
   * FN.rest complements FN.first by passing everything
   * execept the first element into a callback.
   *
   * Example:
   * FN.rest((remainingElements) => {
   *   remainingElements.forEach((element) => {
   *    console.log(element);
   *   });
   * }, 1, 2, 3, 4, 5);
   *
   * @param {function} cb - The callback to execute in the form: (remainingElements) =>  {...}
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback or undefined if there wasn't
   * a callback, a list or the argument list is smaller than one.
   * @see FN.first
   */
  "rest": (cb, ...lst) => {
    "use strict";
    return(cb !== undefined && lst !== undefined && lst.length > 1) ? cb(lst.slice(1)) : undefined;
  },

  /**
   * FN.take runs the supplied callback with a number and a
   * list of items. The supplied callback is executed with
   * an array containing the first n elements in the list of
   * items passed into FN.take.
   *
   * Example:
   * FN.take((elements) => {
   *   elements.forEach((element) => {
   *     console.log(element);
   *   });
   * }, 2, "Lions", "Tigers", "Bears");
   *
   * @param {function} cb - The callback to execute in the form: (elements) =>  {...}
   * @param {number} n - The number of elements to take from the remaining arguments.
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   */
  "take": (cb, n, ...lst) => {
    "use strict";
    return(cb !== undefined && n !== undefined) ? cb(lst.slice(0, n)) : undefined;
  },

  /**
   * FN.if is a single branch function. It expects a
   * callback and any number of values. The values
   * are treated as if they were a list and the
   * callback is executed with no arguments.
   *
   * Example:
   * FN.if(() => {
   *   console.log("Is true");
   * }, 1 === 1, 2 === 2);
   *
   * @param {function} cb - The callback to execute in the form: () =>  {...}
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   * @see FN.ifElse
   */
  "if": (cb, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb !== undefined && lst !== undefined && lst.length > 0 && result) ? cb() : undefined;
  },

  /**
   * FN.ifElse expands upon FN.if by permitting the user
   * to provide a second callback function to be executed
   * in the event that the if expression evaluates to false.
   *
   * NOTE: Multiple FNi.fElse can be nested inside of the callback functions.
   *
   * Example:
   * FN.ifElse(() => {
   *   console.log("Is true");
   * }, () => {
   *  console.log("Is false");
   * }, 1 === 1, 2 === 2);
   *
   * @param {function} cb1 - The callback to execute in the form: () =>  {...} if true.
   * @param {function} cb2 - The callback to execute in the form: () =>  {...} if false.
   * @param {array} lst - The arguments to rest. Rest takes a variable number of
   * arguments and processes them all as if they were an array.
   * @return The result of the callback.
   * @see FN.if
   */
  "ifElse": (cb1, cb2, ...lst) => {
    "use strict";
    var result = true;

    lst.forEach((element) => { if(!element) result = false; });

    return(cb1 !== undefined && cb2 !== undefined && lst !== undefined && lst.length > 0 && result) ? cb1() : cb2();
  },

  /**
  * FN.let creates a new isolated execution context with a set of values initilised
  * within the context and visible only for the duration of the callback function.
  * Note that it acts as a closure and does have access to outer variables.
  *
  * Example:
  * FN.let(() => {
  *   console.log(`Hi my name is ${name} and I am ${age} years old.`);
  * }, {"age": 29, "name": "Neil Munro"});
  *
  * @param {function} cb - The callback to execute in the form: () =>  {...}.
  * @param {object} objectContext - An object containing the key/value pairs
  * that are to be created inside the execution context.
  * @return The return value of the callback function.
  * @see FN.if
  */
  "let": (cb, objectContext) => {
    "use strict";
    return(() => {
      Object.keys(objectContext).forEach((key) => this[key] = objectContext[key]);
      return cb.call(this);
    })();
  }
}));
<|endoftext|>


<commit_before>(function($, undefined){
  $.fn.anim = function(properties, duration, ease, callback){
    var transforms = [], opacity, key;
    for (key in properties)
      if (key === 'opacity') opacity = properties[key];
      else transforms.push(key + '(' + properties[key] + ')');

    if (parseFloat(duration) !== 0) {
      $.isFunction(callback) && this.one('webkitTransitionEnd', callback);
    } else {
      setTimeout(callback, 0);
    }

    return this.css({
      '-webkit-transition': 'all ' + (duration !== undefined ? duration : 0.5) + 's ' + (ease || ''),
      '-webkit-transform': transforms.join(' '),
      opacity: opacity
    });
  }
})(Zepto);
<commit_msg>Set transition to none after webkitTransitionEnd event (closes #206)<commit_after>(function($, undefined){
  $.fn.anim = function(properties, duration, ease, callback){
    var transforms = [], opacity, key, that = this;
    for (key in properties)
      if (key === 'opacity') opacity = properties[key];
      else transforms.push(key + '(' + properties[key] + ')');

    var wrappedCallback = function () {
        that.css( { '-webkit-transition': 'none' } );
        if ( $.isFunction(callback) ) {
            callback();
        }
    };

    if (parseFloat(duration) !== 0) {
      this.one('webkitTransitionEnd', wrappedCallback);
    } else {
      setTimeout(wrappedCallback, 0);
    }

    return this.css({
      '-webkit-transition': 'all ' + (duration !== undefined ? duration : 0.5) + 's ' + (ease || ''),
      '-webkit-transform': transforms.join(' '),
      opacity: opacity
    });
  }
})(Zepto);
<|endoftext|>


<commit_before>jQuery.fn.extend({
	show: function(speed,callback){
		return speed ?
			this.animate({
				height: "show", width: "show", opacity: "show"
			}, speed, callback) :

			this.filter(":hidden").each(function(){
				this.style.display = this.oldblock || "";
				if ( jQuery.css(this,"display") == "none" ) {
					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
					this.style.display = elem.css("display");
					// handle an edge condition where css is - div { display:none; } or similar
					if (this.style.display == "none")
						this.style.display = "block";
					elem.remove();
				}
			}).end();
	},

	hide: function(speed,callback){
		return speed ?
			this.animate({
				height: "hide", width: "hide", opacity: "hide"
			}, speed, callback) :

			this.filter(":visible").each(function(){
				this.oldblock = this.oldblock || jQuery.css(this,"display");
				this.style.display = "none";
			}).end();
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2 ){
		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
			this._toggle.apply( this, arguments ) :
			fn ?
				this.animate({
					height: "toggle", width: "toggle", opacity: "toggle"
				}, fn, fn2) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
				});
	},

	fadeTo: function(speed,to,callback){
		return this.animate({opacity: to}, speed, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		return this[ optall.queue === false ? "each" : "queue" ](function(){

			var opt = jQuery.extend({}, optall), p,
				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
				self = this;

			for ( p in prop ) {
				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
					return opt.complete.call(this);

				if ( ( p == "height" || p == "width" ) && this.style ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}
			}

			if ( opt.overflow != null )
				this.style.overflow = "hidden";

			opt.curAnim = jQuery.extend({}, prop);

			jQuery.each( prop, function(name, val){
				var e = new jQuery.fx( self, opt, name );

				if ( /toggle|show|hide/.test(val) )
					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
				else {
					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat(parts[2]),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit != "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] )
							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;

						e.custom( start, end, unit );
					} else
						e.custom( start, val, "" );
				}
			});

			// For JS strict compliance
			return true;
		});
	},

	queue: function(type, fn){
		if ( jQuery.isFunction(type) || jQuery.isArray(type) ) {
			fn = type;
			type = "fx";
		}

		if ( !type || (typeof type === "string" && !fn) )
			return queue( this[0], type );

		return this.each(function(){
			if ( jQuery.isArray(fn) )
				queue(this, type, fn);
			else {
				queue(this, type).push( fn );

				if ( queue(this, type).length == 1 )
					fn.call(this);
			}
		});
	},

	stop: function(clearQueue, gotoEnd){
		var timers = jQuery.timers;

		if (clearQueue)
			this.queue([]);

		this.each(function(){
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- )
				if ( timers[i].elem == this ) {
					if (gotoEnd)
						// force the next step to be the last
						timers[i](true);
					timers.splice(i, 1);
				}
		});

		// start the next in the queue if the last step wasn't forced
		if (!gotoEnd)
			this.dequeue();

		return this;
	}

});

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: { height:"show" },
	slideUp: { height: "hide" },
	slideToggle: { height: "toggle" },
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" }
}, function( name, props ){
	jQuery.fn[ name ] = function( speed, callback ){
		return this.animate( props, speed, callback );
	};
});

var queue = function( elem, type, array ) {
	if ( elem ){

		type = type || "fx";

		var q = jQuery.data( elem, type + "queue" );

		if ( !q || array )
			q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );

	}
	return q;
};

jQuery.fn.dequeue = function(type){
	type = type || "fx";

	return this.each(function(){
		var q = queue(this, type);

		q.shift();

		if ( q.length )
			q[0].call( this );
	});
};

jQuery.extend({

	speed: function(speed, easing, fn) {
		var opt = typeof speed === "object" ? speed : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function(){
			if ( opt.queue !== false )
				jQuery(this).dequeue();
			if ( jQuery.isFunction( opt.old ) )
				opt.old.call( this );
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},

	timers: [],
	timerId: null,

	fx: function( elem, options, prop ){
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig )
			options.orig = {};
	}

});

jQuery.fx.prototype = {

	// Simple function for setting a style value
	update: function(){
		if ( this.options.step )
			this.options.step.call( this.elem, this.now, this );

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
			this.elem.style.display = "block";
	},

	// Get the current size
	cur: function(force){
		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
			return this.elem[ this.prop ];

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function(from, to, unit){
		this.startTime = now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;

		var self = this;
		function t(gotoEnd){
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		jQuery.timers.push(t);

		if ( t() && jQuery.timerId == null ) {
			jQuery.timerId = setInterval(function(){
				var timers = jQuery.timers;

				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) {
					clearInterval( jQuery.timerId );
					jQuery.timerId = null;
				}
			}, 13);
		}
	},

	// Simple 'show' function
	show: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.show = true;

		// Begin the animation
		this.custom(0, this.cur());

		// Make sure that we start at a small width/height to avoid any
		// flash of content
		if ( this.prop == "width" || this.prop == "height" )
			this.elem.style[this.prop] = "1px";

		// Start by showing the element
		jQuery(this.elem).show();
	},

	// Simple 'hide' function
	hide: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function(gotoEnd){
		var t = now();

		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			var done = true;
			for ( var i in this.options.curAnim )
				if ( this.options.curAnim[i] !== true )
					done = false;

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;

					// Reset the display
					this.elem.style.display = this.options.display;
					if ( jQuery.css(this.elem, "display") == "none" )
						this.elem.style.display = "block";
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide )
					this.elem.style.display = "none";

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show )
					for ( var p in this.options.curAnim )
						jQuery.attr(this.elem.style, p, this.options.orig[p]);
			}

			if ( done )
				// Execute the complete function
				this.options.complete.call( this.elem );

			return false;
		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}

};

jQuery.extend( jQuery.fx, {
	speeds:{
		slow: 600,
 		fast: 200,
 		// Default speed
 		_default: 400
	},
	step: {

		opacity: function(fx){
			jQuery.attr(fx.elem.style, "opacity", fx.now);
		},

		_default: function(fx){
			if( fx.prop in fx.elem )
				fx.elem[ fx.prop ] = fx.now;
			else if( fx.elem.style )
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
		}
	}
});
<commit_msg>Rewrote the hide and show methods to fix the issue with Safari not hiding distached elements. Fixed #1239, #2233, #3038, #3343, #3395. They're also faster now, as well.<commit_after>var elemdisplay = {};

jQuery.fn.extend({
	show: function(speed,callback){
		if ( speed ) {
			return this.animate({
				height: "show", width: "show", opacity: "show"
			}, speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");

				this[i].style.display = old || "";

				if ( jQuery.css(this[i], "display") === "none" ) {
					var tagName = this[i].tagName, display;

					if ( elemdisplay[ tagName ] ) {
						display = elemdisplay[ tagName ];
					} else {
						var elem = jQuery("<" + this[i].tagName + " />").appendTo("body");

						display = elem.css("display");
						if ( display === "none" )
							display = "block";

						elem.remove();

						elemdisplay[ this[i].tagName ] = display;
					}

					this[i].style.display = jQuery.data(this[i], "olddisplay", display);
				}
			}

			return this;
		}
	},

	hide: function(speed,callback){
		if ( speed ) {
			return this.animate({
				height: "hide", width: "hide", opacity: "hide"
			}, speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");
				if ( !old && old !== "none" )
					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
				this[i].style.display = "none";
			}
			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2 ){
		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
			this._toggle.apply( this, arguments ) :
			fn ?
				this.animate({
					height: "toggle", width: "toggle", opacity: "toggle"
				}, fn, fn2) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
				});
	},

	fadeTo: function(speed,to,callback){
		return this.animate({opacity: to}, speed, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		return this[ optall.queue === false ? "each" : "queue" ](function(){

			var opt = jQuery.extend({}, optall), p,
				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
				self = this;

			for ( p in prop ) {
				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
					return opt.complete.call(this);

				if ( ( p == "height" || p == "width" ) && this.style ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}
			}

			if ( opt.overflow != null )
				this.style.overflow = "hidden";

			opt.curAnim = jQuery.extend({}, prop);

			jQuery.each( prop, function(name, val){
				var e = new jQuery.fx( self, opt, name );

				if ( /toggle|show|hide/.test(val) )
					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
				else {
					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat(parts[2]),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit != "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] )
							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;

						e.custom( start, end, unit );
					} else
						e.custom( start, val, "" );
				}
			});

			// For JS strict compliance
			return true;
		});
	},

	queue: function(type, fn){
		if ( jQuery.isFunction(type) || jQuery.isArray(type) ) {
			fn = type;
			type = "fx";
		}

		if ( !type || (typeof type === "string" && !fn) )
			return queue( this[0], type );

		return this.each(function(){
			if ( jQuery.isArray(fn) )
				queue(this, type, fn);
			else {
				queue(this, type).push( fn );

				if ( queue(this, type).length == 1 )
					fn.call(this);
			}
		});
	},

	stop: function(clearQueue, gotoEnd){
		var timers = jQuery.timers;

		if (clearQueue)
			this.queue([]);

		this.each(function(){
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- )
				if ( timers[i].elem == this ) {
					if (gotoEnd)
						// force the next step to be the last
						timers[i](true);
					timers.splice(i, 1);
				}
		});

		// start the next in the queue if the last step wasn't forced
		if (!gotoEnd)
			this.dequeue();

		return this;
	}

});

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: { height:"show" },
	slideUp: { height: "hide" },
	slideToggle: { height: "toggle" },
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" }
}, function( name, props ){
	jQuery.fn[ name ] = function( speed, callback ){
		return this.animate( props, speed, callback );
	};
});

var queue = function( elem, type, array ) {
	if ( elem ){

		type = type || "fx";

		var q = jQuery.data( elem, type + "queue" );

		if ( !q || array )
			q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );

	}
	return q;
};

jQuery.fn.dequeue = function(type){
	type = type || "fx";

	return this.each(function(){
		var q = queue(this, type);

		q.shift();

		if ( q.length )
			q[0].call( this );
	});
};

jQuery.extend({

	speed: function(speed, easing, fn) {
		var opt = typeof speed === "object" ? speed : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function(){
			if ( opt.queue !== false )
				jQuery(this).dequeue();
			if ( jQuery.isFunction( opt.old ) )
				opt.old.call( this );
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},

	timers: [],
	timerId: null,

	fx: function( elem, options, prop ){
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig )
			options.orig = {};
	}

});

jQuery.fx.prototype = {

	// Simple function for setting a style value
	update: function(){
		if ( this.options.step )
			this.options.step.call( this.elem, this.now, this );

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
			this.elem.style.display = "block";
	},

	// Get the current size
	cur: function(force){
		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
			return this.elem[ this.prop ];

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function(from, to, unit){
		this.startTime = now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;

		var self = this;
		function t(gotoEnd){
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		jQuery.timers.push(t);

		if ( t() && jQuery.timerId == null ) {
			jQuery.timerId = setInterval(function(){
				var timers = jQuery.timers;

				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) {
					clearInterval( jQuery.timerId );
					jQuery.timerId = null;
				}
			}, 13);
		}
	},

	// Simple 'show' function
	show: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.show = true;

		// Begin the animation
		this.custom(0, this.cur());

		// Make sure that we start at a small width/height to avoid any
		// flash of content
		if ( this.prop == "width" || this.prop == "height" )
			this.elem.style[this.prop] = "1px";

		// Start by showing the element
		jQuery(this.elem).show();
	},

	// Simple 'hide' function
	hide: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function(gotoEnd){
		var t = now();

		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			var done = true;
			for ( var i in this.options.curAnim )
				if ( this.options.curAnim[i] !== true )
					done = false;

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;

					// Reset the display
					this.elem.style.display = this.options.display;
					if ( jQuery.css(this.elem, "display") == "none" )
						this.elem.style.display = "block";
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide )
					this.elem.style.display = "none";

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show )
					for ( var p in this.options.curAnim )
						jQuery.attr(this.elem.style, p, this.options.orig[p]);
			}

			if ( done )
				// Execute the complete function
				this.options.complete.call( this.elem );

			return false;
		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}

};

jQuery.extend( jQuery.fx, {
	speeds:{
		slow: 600,
 		fast: 200,
 		// Default speed
 		_default: 400
	},
	step: {

		opacity: function(fx){
			jQuery.attr(fx.elem.style, "opacity", fx.now);
		},

		_default: function(fx){
			if( fx.prop in fx.elem )
				fx.elem[ fx.prop ] = fx.now;
			else if( fx.elem.style )
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
		}
	}
});
<|endoftext|>


<commit_before>Ext.define('AIDRFM.common.AIDRFMFunctions', {

    initMessageContainer: function (){
        msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
        msgCt.setStyle('position', 'absolute');
        msgCt.setStyle('z-index', 99999);
        msgCt.setWidth(400);
    },

    setAlert: function (status, msg) {
        var message = '
';
        var delay = 3;
        if (Ext.isArray(msg)) {
            Ext.each(msg, function (ms) {
                message += '
' + ms + '
';
            });
            var arrSize  = msg.length;
            if (arrSize  < 2) {
                delay = 3;
            } else {
                delay = 9;
            }
        } else {
            message = '
' + msg + '
';

            // add some smarts to msg's duration (div by 13.3 between 3 & 9 seconds)
            var delayMeasure  = msg.length / 13.3;
            if (delayMeasure  < 3) {
                delay = 3;
            } else if (delayMeasure  > 9) {
                delay = 9;
            } else {
                delay = delayMeasure ;
            }
        }
        message += '
';
        delay = delay * 1000;

        msgCt.alignTo(document, 't-t');
        Ext.DomHelper.append(msgCt, {html: this.buildMessageBox(status.toLowerCase(), message)}, true).slideIn('t').ghost("t", {delay: delay, remove: true});
    },

    buildMessageBox : function(title, msg) {
        return [
            '',
                '',
                    this.capitaliseFirstLetter(title),
                '',
                '',
                    msg,
                '',
            ''
        ].join('');
    },

    capitaliseFirstLetter: function (string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    },

    maskCount: 0,

    showMask: function(mask){
        if (mask) {
            if (this.maskCount == 0) {
                mask.show();
            }
            this.maskCount++;
        }
    },

    hideMask: function(mask){
        if (mask) {
            this.maskCount--;
            if (this.maskCount == 0) {
                mask.hide();
            }
        }
    },

    getMask: function (showMessage, msg) {
        if (showMessage) {
            if (!msg) {
                msg = 'Loading ...';
            }
        }
        if (this.maskScreen == null) {
            this.maskScreen = new Ext.LoadMask(Ext.getBody(), {msg: msg});
        } else {
            this.maskScreen.msg = msg;
        }
        return this.maskScreen;
    },

    mandatoryFieldsEntered: function () {
        var me = this;

        var isValid = true;
        var form = Ext.getCmp('collectionForm').getForm();
        if (!form.findField('code').getValue()) {
            form.findField('code').markInvalid(['Collection Code is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Code is mandatory');
            isValid = false;
        }
        if (form.findField('code').getValue() && form.findField('code').getValue().length > 64) {
            form.findField('code').markInvalid(['The maximum length for Collection Code field is 64']);
            AIDRFMFunctions.setAlert('Error', 'The maximum length for Collection Code field is 64');
            isValid = false;
        }
        if (!form.findField('name').getValue()) {
            form.findField('name').markInvalid(['Collection Name is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Name is mandatory');
            isValid = false;
        }
        if (!form.findField('crisisType').getValue()) {
            form.findField('crisisType').markInvalid(['Collection Type is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Type is mandatory');
            isValid = false;
        }
        if (!(form.findField('track').getValue() || form.findField('geo').getValue() || form.findField('follow').getValue())) {
            AIDRFMFunctions.setAlert('Error', 'One of Keywords, Geo or Follow field is mandatory');
            isValid = false;
        }
        if (form.findField('track').getValue()) {
            var value = form.findField('track').getValue(),
                keywords = value.split(","),
                errors = [],
                isKeywordValid = true;
            Ext.Array.each(keywords, function(v) {
                if (v.length > 60) {
                    if (isKeywordValid){
                        errors.push('Each keywords should not exceed 60 chars.');
                    }
                    errors.push('' + v + ' has more than 60 chars');
                    isKeywordValid = false;
                }
            });
            if (!isKeywordValid) {
                isValid = isKeywordValid;
                AIDRFMFunctions.setAlert('Error', errors);
            }
        }
        return isValid;
    },

    getQueryParam: function (name) {
        name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
        var regexS = "[\\?&]" + name + "=([^&#]*)";
        var regex = new RegExp(regexS);
        var results = regex.exec(window.location.href);
        if (results == null)
            return null;
        else
            return results[1];
    },

    getStatusWithStyle: function(raw) {
        var statusText = '';
        if (raw == 'RUNNING') {
            statusText = " RUNNING ";
        } else if (raw == 'INITIALIZING') {
            statusText = " INITIALIZING ";
        } else if (raw == 'STOPPED' || raw == 'FATAL-ERROR') {
            statusText = "" + raw + " ";
        }  else if (raw == 'NOT_RUNNING') {
            statusText = "" + raw + " " + ' (Click on "Start" to start this collection.)';
        } else {
            statusText = "" + raw + " ";
        }
        return statusText;
    },

    getAucNumberWithColors: function(r) {
        var style;
        if (r){
            if (r < 0.6){
                style = 'redInfo';
            } else if (r <= 0.8){
                style = 'warningFont';
            } else {
                style = 'greenInfo';
            }
        } else {
            r = 0;
            style = 'redInfo';
        }
        return '' + r.toFixed(2) + '';
    },

    getAucNumberAsPercentageWithColors: function(r) {
        var style;
        if (r){
            if (r < 0.6){
                style = 'redInfo';
            } else if (r <= 0.8){
                style = 'warningFont';
            } else {
                style = 'greenInfo';
            }
        } else {
            r = 0;
            style = 'redInfo';
        }
        return '' + (r * 100).toFixed(2) + '%';
    }

});

AIDRFMFunctions = new AIDRFM.common.AIDRFMFunctions();

NA_CATEGORY_NAME = 'N/A: does not apply, or cannot judge';

Number.prototype.format = function(n, x) {
    var re = '(\\d)(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$1,');
};

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /\w+@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern, '$&')
            .replace(pseudoUrlPattern, '$1$2')
            .replace(emailAddressPattern, '$&');
    };
}

Ext.Ajax.on('requestexception', function (conn, response, options) {
    if (response.status == 901) {
        document.location.href = BASE_URL + '/index.jsp'
    } else{
        if(response.status != 0){
            AIDRFMFunctions.setAlert("Error", "System is down or under maintenance. For further inquiries please contact admin.");
        }
    }
});

Ext.Date.patterns = {
    ISO8601Long:"Y-m-d H:i:s",
    ISO8601Short:"Y-m-d",
    ShortDate: "n/j/Y",
    LongDate: "l, F d, Y",
    FullDateTime: "l, F d, Y g:i:s A",
    MedumDateTime: "F d, Y g:i:s A",
    MonthDay: "F d",
    ShortTime: "g:i A",
    LongTime: "g:i:s A",
    SortableDateTime: "Y-m-d\\TH:i:s",
    UniversalSortableDateTime: "Y-m-d H:i:sO",
    YearMonth: "F, Y"
};<commit_msg>fixed create SMS collection created<commit_after>Ext.define('AIDRFM.common.AIDRFMFunctions', {

    initMessageContainer: function (){
        msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
        msgCt.setStyle('position', 'absolute');
        msgCt.setStyle('z-index', 99999);
        msgCt.setWidth(400);
    },

    setAlert: function (status, msg) {
        var message = '
';
        var delay = 3;
        if (Ext.isArray(msg)) {
            Ext.each(msg, function (ms) {
                message += '
' + ms + '
';
            });
            var arrSize  = msg.length;
            if (arrSize  < 2) {
                delay = 3;
            } else {
                delay = 9;
            }
        } else {
            message = '
' + msg + '
';

            // add some smarts to msg's duration (div by 13.3 between 3 & 9 seconds)
            var delayMeasure  = msg.length / 13.3;
            if (delayMeasure  < 3) {
                delay = 3;
            } else if (delayMeasure  > 9) {
                delay = 9;
            } else {
                delay = delayMeasure ;
            }
        }
        message += '
';
        delay = delay * 1000;

        msgCt.alignTo(document, 't-t');
        Ext.DomHelper.append(msgCt, {html: this.buildMessageBox(status.toLowerCase(), message)}, true).slideIn('t').ghost("t", {delay: delay, remove: true});
    },

    buildMessageBox : function(title, msg) {
        return [
            '',
                '',
                    this.capitaliseFirstLetter(title),
                '',
                '',
                    msg,
                '',
            ''
        ].join('');
    },

    capitaliseFirstLetter: function (string) {
        return string.charAt(0).toUpperCase() + string.slice(1);
    },

    maskCount: 0,

    showMask: function(mask){
        if (mask) {
            if (this.maskCount == 0) {
                mask.show();
            }
            this.maskCount++;
        }
    },

    hideMask: function(mask){
        if (mask) {
            this.maskCount--;
            if (this.maskCount == 0) {
                mask.hide();
            }
        }
    },

    getMask: function (showMessage, msg) {
        if (showMessage) {
            if (!msg) {
                msg = 'Loading ...';
            }
        }
        if (this.maskScreen == null) {
            this.maskScreen = new Ext.LoadMask(Ext.getBody(), {msg: msg});
        } else {
            this.maskScreen.msg = msg;
        }
        return this.maskScreen;
    },

    mandatoryFieldsEntered: function () {
        var me = this;

        var isValid = true;
        var form = Ext.getCmp('collectionForm').getForm();
        if (!form.findField('code').getValue()) {
            form.findField('code').markInvalid(['Collection Code is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Code is mandatory');
            isValid = false;
        }
        if (form.findField('code').getValue() && form.findField('code').getValue().length > 64) {
            form.findField('code').markInvalid(['The maximum length for Collection Code field is 64']);
            AIDRFMFunctions.setAlert('Error', 'The maximum length for Collection Code field is 64');
            isValid = false;
        }
        if (!form.findField('name').getValue()) {
            form.findField('name').markInvalid(['Collection Name is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Name is mandatory');
            isValid = false;
        }
        if (!form.findField('crisisType').getValue()) {
            form.findField('crisisType').markInvalid(['Collection Type is mandatory']);
            AIDRFMFunctions.setAlert('Error', 'Collection Type is mandatory');
            isValid = false;
        }
        if (form.findField('collectionType').getValue() === 'Twitter' && !(form.findField('track').getValue() || form.findField('geo').getValue() || form.findField('follow').getValue())) {
            AIDRFMFunctions.setAlert('Error', 'One of Keywords, Geo or Follow field is mandatory');
            isValid = false;
        }
        if (form.findField('track').getValue()) {
            var value = form.findField('track').getValue(),
                keywords = value.split(","),
                errors = [],
                isKeywordValid = true;
            Ext.Array.each(keywords, function(v) {
                if (v.length > 60) {
                    if (isKeywordValid){
                        errors.push('Each keywords should not exceed 60 chars.');
                    }
                    errors.push('' + v + ' has more than 60 chars');
                    isKeywordValid = false;
                }
            });
            if (!isKeywordValid) {
                isValid = isKeywordValid;
                AIDRFMFunctions.setAlert('Error', errors);
            }
        }
        return isValid;
    },

    getQueryParam: function (name) {
        name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
        var regexS = "[\\?&]" + name + "=([^&#]*)";
        var regex = new RegExp(regexS);
        var results = regex.exec(window.location.href);
        if (results == null)
            return null;
        else
            return results[1];
    },

    getStatusWithStyle: function(raw) {
        var statusText = '';
        if (raw == 'RUNNING') {
            statusText = " RUNNING ";
        } else if (raw == 'INITIALIZING') {
            statusText = " INITIALIZING ";
        } else if (raw == 'STOPPED' || raw == 'FATAL-ERROR') {
            statusText = "" + raw + " ";
        }  else if (raw == 'NOT_RUNNING') {
            statusText = "" + raw + " " + ' (Click on "Start" to start this collection.)';
        } else {
            statusText = "" + raw + " ";
        }
        return statusText;
    },

    getAucNumberWithColors: function(r) {
        var style;
        if (r){
            if (r < 0.6){
                style = 'redInfo';
            } else if (r <= 0.8){
                style = 'warningFont';
            } else {
                style = 'greenInfo';
            }
        } else {
            r = 0;
            style = 'redInfo';
        }
        return '' + r.toFixed(2) + '';
    },

    getAucNumberAsPercentageWithColors: function(r) {
        var style;
        if (r){
            if (r < 0.6){
                style = 'redInfo';
            } else if (r <= 0.8){
                style = 'warningFont';
            } else {
                style = 'greenInfo';
            }
        } else {
            r = 0;
            style = 'redInfo';
        }
        return '' + (r * 100).toFixed(2) + '%';
    }

});

AIDRFMFunctions = new AIDRFM.common.AIDRFMFunctions();

NA_CATEGORY_NAME = 'N/A: does not apply, or cannot judge';

Number.prototype.format = function(n, x) {
    var re = '(\\d)(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$1,');
};

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /\w+@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern, '$&')
            .replace(pseudoUrlPattern, '$1$2')
            .replace(emailAddressPattern, '$&');
    };
}

Ext.Ajax.on('requestexception', function (conn, response, options) {
    if (response.status == 901) {
        document.location.href = BASE_URL + '/index.jsp'
    } else{
        if(response.status != 0){
            AIDRFMFunctions.setAlert("Error", "System is down or under maintenance. For further inquiries please contact admin.");
        }
    }
});

Ext.Date.patterns = {
    ISO8601Long:"Y-m-d H:i:s",
    ISO8601Short:"Y-m-d",
    ShortDate: "n/j/Y",
    LongDate: "l, F d, Y",
    FullDateTime: "l, F d, Y g:i:s A",
    MedumDateTime: "F d, Y g:i:s A",
    MonthDay: "F d",
    ShortTime: "g:i A",
    LongTime: "g:i:s A",
    SortableDateTime: "Y-m-d\\TH:i:s",
    UniversalSortableDateTime: "Y-m-d H:i:sO",
    YearMonth: "F, Y"
};<|endoftext|>