/*jslint browser: true */ /*global jQuery: true */ /** * jQuery Cookie plugin * * Copyright (c) 2010 Klaus Hartl (stilbuero.de) * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * */ // TODO JsDoc /** * Create a cookie with the given key and value and other optional parameters. * * @example $.cookie('the_cookie', 'the_value'); * @desc Set the value of a cookie. * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); * @desc Create a cookie with all available options. * @example $.cookie('the_cookie', 'the_value'); * @desc Create a session cookie. * @example $.cookie('the_cookie', null); * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain * used when the cookie was set. * * @param String key The key of the cookie. * @param String value The value of the cookie. * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. * If set to null or omitted, the cookie will be a session cookie and will not be retained * when the the browser exits. * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will * require a secure protocol (like HTTPS). * @type undefined * * @name $.cookie * @cat Plugins/Cookie * @author Klaus Hartl/klaus.hartl@stilbuero.de */ /** * Get the value of a cookie with the given key. * * @example $.cookie('the_cookie'); * @desc Get the value of a cookie. * * @param String key The key of the cookie. * @return The value of the cookie. * @type String * * @name $.cookie * @cat Plugins/Cookie * @author Klaus Hartl/klaus.hartl@stilbuero.de */ jQuery.cookie = function (key, value, options) { // key and value given, set cookie... if (arguments.length > 1 && (value === null || typeof value !== "object")) { options = jQuery.extend({}, options); if (value === null) { options.expires = -1; } if (typeof options.expires === 'number') { var days = options.expires, t = options.expires = new Date(); t.setDate(t.getDate() + days); } return (document.cookie = [ encodeURIComponent(key), '=', options.raw ? String(value) : encodeURIComponent(String(value)), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join('')); } // key and possibly options given, get cookie... options = value || {}; var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; }; ;/*})'"*/ ;/*})'"*/ /*! * jQuery Form Plugin * version: 4.2.1 * Requires jQuery v1.7 or later * Copyright 2017 Kevin Morris * Copyright 2006 M. Alsup * Project repository: https://github.com/jquery-form/form * Dual licensed under the MIT and LGPLv3 licenses. * https://github.com/jquery-form/form#license */ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(b,c){return void 0===c&&(c="undefined"!=typeof window?require("jquery"):require("jquery")(b)),a(c),c}:a(jQuery)}(function(a){"use strict";function b(b){var c=b.data;b.isDefaultPrevented()||(b.preventDefault(),a(b.target).closest("form").ajaxSubmit(c))}function c(b){var c=b.target,d=a(c);if(!d.is("[type=submit],[type=image]")){var e=d.closest("[type=submit]");if(0===e.length)return;c=e[0]}var f=c.form;if(f.clk=c,"image"===c.type)if(void 0!==b.offsetX)f.clk_x=b.offsetX,f.clk_y=b.offsetY;else if("function"==typeof a.fn.offset){var g=d.offset();f.clk_x=b.pageX-g.left,f.clk_y=b.pageY-g.top}else f.clk_x=b.pageX-c.offsetLeft,f.clk_y=b.pageY-c.offsetTop;setTimeout(function(){f.clk=f.clk_x=f.clk_y=null},100)}function d(){if(a.fn.ajaxSubmit.debug){var b="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(b):window.opera&&window.opera.postError&&window.opera.postError(b)}}var e={};e.fileapi=void 0!==a('').get(0).files,e.formdata=void 0!==window.FormData;var f=!!a.fn.prop;a.fn.attr2=function(){if(!f)return this.attr.apply(this,arguments);var a=this.prop.apply(this,arguments);return a&&a.jquery||"string"==typeof a?a:this.attr.apply(this,arguments)},a.fn.ajaxSubmit=function(b,c,g,h){function i(c){var d,e,f=a.param(c,b.traditional).split("&"),g=f.length,h=[];for(d=0;d',z).val(k.extraData[j].value).appendTo(x)[0]):i.push(a('',z).val(k.extraData[j]).appendTo(x)[0]));k.iframeTarget||p.appendTo(A),q.attachEvent?q.attachEvent("onload",h):q.addEventListener("load",h,!1),setTimeout(b,15);try{x.submit()}catch(a){var m=document.createElement("form").submit;m.apply(x)}}finally{x.setAttribute("action",f),x.setAttribute("enctype",g),c?x.setAttribute("target",c):o.removeAttr("target"),a(i).remove()}}function h(b){if(!r.aborted&&!F){if(E=e(q),E||(d("cannot access response document"),b=2),1===b&&r)return r.abort("timeout"),void y.reject(r,"timeout");if(2===b&&r)return r.abort("server abort"),void y.reject(r,"error","server abort");if(E&&E.location.href!==k.iframeSrc||v){q.detachEvent?q.detachEvent("onload",h):q.removeEventListener("load",h,!1);var c,f="success";try{if(v)throw"timeout";var g="xml"===k.dataType||E.XMLDocument||a.isXMLDoc(E);if(d("isXml="+g),!g&&window.opera&&(null===E.body||!E.body.innerHTML)&&--G)return d("requeing onLoad callback, DOM not available"),void setTimeout(h,250);var i=E.body?E.body:E.documentElement;r.responseText=i?i.innerHTML:null,r.responseXML=E.XMLDocument?E.XMLDocument:E,g&&(k.dataType="xml"),r.getResponseHeader=function(a){return{"content-type":k.dataType}[a.toLowerCase()]},i&&(r.status=Number(i.getAttribute("status"))||r.status,r.statusText=i.getAttribute("statusText")||r.statusText);var j=(k.dataType||"").toLowerCase(),l=/(json|script|text)/.test(j);if(l||k.textarea){var n=E.getElementsByTagName("textarea")[0];if(n)r.responseText=n.value,r.status=Number(n.getAttribute("status"))||r.status,r.statusText=n.getAttribute("statusText")||r.statusText;else if(l){var o=E.getElementsByTagName("pre")[0],s=E.getElementsByTagName("body")[0];o?r.responseText=o.textContent?o.textContent:o.innerText:s&&(r.responseText=s.textContent?s.textContent:s.innerText)}}else"xml"===j&&!r.responseXML&&r.responseText&&(r.responseXML=H(r.responseText));try{D=J(r,j,k)}catch(a){f="parsererror",r.error=c=a||f}}catch(a){d("error caught: ",a),f="error",r.error=c=a||f}r.aborted&&(d("upload aborted"),f=null),r.status&&(f=r.status>=200&&r.status<300||304===r.status?"success":"error"),"success"===f?(k.success&&k.success.call(k.context,D,"success",r),y.resolve(r.responseText,"success",r),m&&a.event.trigger("ajaxSuccess",[r,k])):f&&(void 0===c&&(c=r.statusText),k.error&&k.error.call(k.context,r,f,c),y.reject(r,"error",c),m&&a.event.trigger("ajaxError",[r,k,c])),m&&a.event.trigger("ajaxComplete",[r,k]),m&&!--a.active&&a.event.trigger("ajaxStop"),k.complete&&k.complete.call(k.context,r,f),F=!0,k.timeout&&clearTimeout(w),setTimeout(function(){k.iframeTarget?p.attr("src",k.iframeSrc):p.remove(),r.responseXML=null},100)}}}var i,j,k,m,n,p,q,r,t,u,v,w,x=o[0],y=a.Deferred();if(y.abort=function(a){r.abort(a)},c)for(j=0;j',z),p.css({position:"absolute",top:"-1000px",left:"-1000px"})),q=p[0],r={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(b){var c="timeout"===b?"timeout":"aborted";d("aborting upload... "+c),this.aborted=1;try{q.contentWindow.document.execCommand&&q.contentWindow.document.execCommand("Stop")}catch(a){}p.attr("src",k.iframeSrc),r.error=c,k.error&&k.error.call(k.context,r,c,b),m&&a.event.trigger("ajaxError",[r,k,c]),k.complete&&k.complete.call(k.context,r,c)}},m=k.global,m&&0==a.active++&&a.event.trigger("ajaxStart"),m&&a.event.trigger("ajaxSend",[r,k]),k.beforeSend&&k.beforeSend.call(k.context,r,k)===!1)return k.global&&a.active--,y.reject(),y;if(r.aborted)return y.reject(),y;(t=x.clk)&&(u=t.name)&&!t.disabled&&(k.extraData=k.extraData||{},k.extraData[u]=t.value,"image"===t.type&&(k.extraData[u+".x"]=x.clk_x,k.extraData[u+".y"]=x.clk_y));var B=a("meta[name=csrf-token]").attr("content"),C=a("meta[name=csrf-param]").attr("content");C&&B&&(k.extraData=k.extraData||{},k.extraData[C]=B),k.forceSync?g():setTimeout(g,10);var D,E,F,G=50,H=a.parseXML||function(a,b){return window.ActiveXObject?(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(a)):b=(new DOMParser).parseFromString(a,"text/xml"),b&&b.documentElement&&"parsererror"!==b.documentElement.nodeName?b:null},I=a.parseJSON||function(a){return window.eval("("+a+")")},J=function(b,c,d){var e=b.getResponseHeader("content-type")||"",f=("xml"===c||!c)&&e.indexOf("xml")>=0,g=f?b.responseXML:b.responseText;return f&&"parsererror"===g.documentElement.nodeName&&a.error&&a.error("parsererror"),d&&d.dataFilter&&(g=d.dataFilter(g,c)),"string"==typeof g&&(("json"===c||!c)&&e.indexOf("json")>=0?g=I(g):("script"===c||!c)&&e.indexOf("javascript")>=0&&a.globalEval(g)),g};return y}if(!this.length)return d("ajaxSubmit: skipping submit process - no element selected"),this;var l,m,n,o=this;"function"==typeof b?b={success:b}:"string"==typeof b||b===!1&&arguments.length>0?(b={url:b,data:c,dataType:g},"function"==typeof h&&(b.success=h)):void 0===b&&(b={}),l=b.method||b.type||this.attr2("method"),m=b.url||this.attr2("action"),n="string"==typeof m?a.trim(m):"",n=n||window.location.href||"",n&&(n=(n.match(/^([^#]+)/)||[])[1]),b=a.extend(!0,{url:n,success:a.ajaxSettings.success,type:l||a.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},b);var p={};if(this.trigger("form-pre-serialize",[this,b,p]),p.veto)return d("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(b.beforeSerialize&&b.beforeSerialize(this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var q=b.traditional;void 0===q&&(q=a.ajaxSettings.traditional);var r,s=[],t=this.formToArray(b.semantic,s,b.filtering);if(b.data){var u=a.isFunction(b.data)?b.data(t):b.data;b.extraData=u,r=a.param(u,q)}if(b.beforeSubmit&&b.beforeSubmit(t,this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[t,this,b,p]),p.veto)return d("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var v=a.param(t,q);r&&(v=v?v+"&"+r:r),"GET"===b.type.toUpperCase()?(b.url+=(b.url.indexOf("?")>=0?"&":"?")+v,b.data=null):b.data=v;var w=[];if(b.resetForm&&w.push(function(){o.resetForm()}),b.clearForm&&w.push(function(){o.clearForm(b.includeHidden)}),!b.dataType&&b.target){var x=b.success||function(){};w.push(function(c,d,e){var f=arguments,g=b.replaceTarget?"replaceWith":"html";a(b.target)[g](c).each(function(){x.apply(this,f)})})}else b.success&&(a.isArray(b.success)?a.merge(w,b.success):w.push(b.success));if(b.success=function(a,c,d){for(var e=b.context||this,f=0,g=w.length;f0,C="multipart/form-data",D=o.attr("enctype")===C||o.attr("encoding")===C,E=e.fileapi&&e.formdata;d("fileAPI :"+E);var F,G=(B||D)&&!E;b.iframe!==!1&&(b.iframe||G)?b.closeKeepAlive?a.get(b.closeKeepAlive,function(){F=k(t)}):F=k(t):F=(B||D)&&E?j(t):a.ajax(b),o.removeData("jqxhr").data("jqxhr",F);for(var H=0;H0)&&(e={url:e,data:f,dataType:g},"function"==typeof h&&(e.success=h)),e=e||{},e.delegation=e.delegation&&a.isFunction(a.fn.on),!e.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!a.isReady&&i.s?(d("DOM not ready, queuing ajaxForm"),a(function(){a(i.s,i.c).ajaxForm(e)}),this):(d("terminating; zero elements found by selector"+(a.isReady?"":" (DOM not ready)")),this)}return e.delegation?(a(document).off("submit.form-plugin",this.selector,b).off("click.form-plugin",this.selector,c).on("submit.form-plugin",this.selector,e,b).on("click.form-plugin",this.selector,e,c),this):this.ajaxFormUnbind().on("submit.form-plugin",e,b).on("click.form-plugin",e,c)},a.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},a.fn.formToArray=function(b,c,d){var f=[];if(0===this.length)return f;var g,h=this[0],i=this.attr("id"),j=b||void 0===h.elements?h.getElementsByTagName("*"):h.elements;if(j&&(j=a.makeArray(j)),i&&(b||/(Edge|Trident)\//.test(navigator.userAgent))&&(g=a(':input[form="'+i+'"]').get(),g.length&&(j=(j||[]).concat(g))),!j||!j.length)return f;a.isFunction(d)&&(j=a.map(j,d));var k,l,m,n,o,p,q;for(k=0,p=j.length;k

'+Drupal.t('No results found')+'

' ].join('\n'), suggestion: function (data) { return '

[' + data.type + ']' + data.title + '' + ((data.hasOwnProperty('created')) ? ' - ' + data.created : '') + '

'; } } }); }); } }; })(jQuery); jQuery(document).ready(function () { jQuery('.search-choice-close').click(function() {jQuery("#intsys-search-advanced-form").submit();}); jQuery('#edit_type_chosen').click(function(event) { UpdateInputType(event.target.textContent,event.target);}); }); function UpdateInputType(t,e) { if(t!=''){ var all=['']; jQuery('#edit-type option').each(function(){all.push(jQuery(this).text()); }); if( all.indexOf(t)==-1) t=''; var Mval=jQuery('#edit-type').val(); if (Mval.length == 0) {ClassInputType(''); return;} if( t==SearchGetText('all') ) RemoveInputType('all'); else if( t==SearchGetText('posts') ) RemoveInputType('posts'); else if( t==SearchGetText('members')) RemoveInputType('members'); else if( t==SearchGetText('tags')) RemoveInputType('tags'); else RemoveInputType('4'); jQuery('#edit_type_chosen [class*=search-choice] span').each( function(e){ var $elEvents = jQuery(this); }); if(e!='') { if (e.outerHTML.indexOf("= this.maxSize) { this.list.remove(tailItem); delete this.hash[tailItem.key]; this.size--; } if (node = this.hash[key]) { node.val = val; this.list.moveToFront(node); } else { node = new Node(key, val); this.list.add(node); this.hash[key] = node; this.size++; } }, get: function get(key) { var node = this.hash[key]; if (node) { this.list.moveToFront(node); return node.val; } }, reset: function reset() { this.size = 0; this.hash = {}; this.list = new List(); } }); function List() { this.head = this.tail = null; } _.mixin(List.prototype, { add: function add(node) { if (this.head) { node.next = this.head; this.head.prev = node; } this.head = node; this.tail = this.tail || node; }, remove: function remove(node) { node.prev ? node.prev.next = node.next : this.head = node.next; node.next ? node.next.prev = node.prev : this.tail = node.prev; }, moveToFront: function(node) { this.remove(node); this.add(node); } }); function Node(key, val) { this.key = key; this.val = val; this.prev = this.next = null; } return LruCache; }(); var PersistentStorage = function() { "use strict"; var LOCAL_STORAGE; try { LOCAL_STORAGE = window.localStorage; LOCAL_STORAGE.setItem("~~~", "!"); LOCAL_STORAGE.removeItem("~~~"); } catch (err) { LOCAL_STORAGE = null; } function PersistentStorage(namespace, override) { this.prefix = [ "__", namespace, "__" ].join(""); this.ttlKey = "__ttl__"; this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); this.ls = override || LOCAL_STORAGE; !this.ls && this._noop(); } _.mixin(PersistentStorage.prototype, { _prefix: function(key) { return this.prefix + key; }, _ttlKey: function(key) { return this._prefix(key) + this.ttlKey; }, _noop: function() { this.get = this.set = this.remove = this.clear = this.isExpired = _.noop; }, _safeSet: function(key, val) { try { this.ls.setItem(key, val); } catch (err) { if (err.name === "QuotaExceededError") { this.clear(); this._noop(); } } }, get: function(key) { if (this.isExpired(key)) { this.remove(key); } return decode(this.ls.getItem(this._prefix(key))); }, set: function(key, val, ttl) { if (_.isNumber(ttl)) { this._safeSet(this._ttlKey(key), encode(now() + ttl)); } else { this.ls.removeItem(this._ttlKey(key)); } return this._safeSet(this._prefix(key), encode(val)); }, remove: function(key) { this.ls.removeItem(this._ttlKey(key)); this.ls.removeItem(this._prefix(key)); return this; }, clear: function() { var i, keys = gatherMatchingKeys(this.keyMatcher); for (i = keys.length; i--; ) { this.remove(keys[i]); } return this; }, isExpired: function(key) { var ttl = decode(this.ls.getItem(this._ttlKey(key))); return _.isNumber(ttl) && now() > ttl ? true : false; } }); return PersistentStorage; function now() { return new Date().getTime(); } function encode(val) { return JSON.stringify(_.isUndefined(val) ? null : val); } function decode(val) { return $.parseJSON(val); } function gatherMatchingKeys(keyMatcher) { var i, key, keys = [], len = LOCAL_STORAGE.length; for (i = 0; i < len; i++) { if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) { keys.push(key.replace(keyMatcher, "")); } } return keys; } }(); var Transport = function() { "use strict"; var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); function Transport(o) { o = o || {}; this.cancelled = false; this.lastReq = null; this._send = o.transport; this._get = o.limiter ? o.limiter(this._get) : this._get; this._cache = o.cache === false ? new LruCache(0) : sharedCache; } Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { maxPendingRequests = num; }; Transport.resetCache = function resetCache() { sharedCache.reset(); }; _.mixin(Transport.prototype, { _fingerprint: function fingerprint(o) { o = o || {}; return o.url + o.type + $.param(o.data || {}); }, _get: function(o, cb) { var that = this, fingerprint, jqXhr; fingerprint = this._fingerprint(o); if (this.cancelled || fingerprint !== this.lastReq) { return; } if (jqXhr = pendingRequests[fingerprint]) { jqXhr.done(done).fail(fail); } else if (pendingRequestsCount < maxPendingRequests) { pendingRequestsCount++; pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always); } else { this.onDeckRequestArgs = [].slice.call(arguments, 0); } function done(resp) { cb(null, resp); that._cache.set(fingerprint, resp); } function fail() { cb(true); } function always() { pendingRequestsCount--; delete pendingRequests[fingerprint]; if (that.onDeckRequestArgs) { that._get.apply(that, that.onDeckRequestArgs); that.onDeckRequestArgs = null; } } }, get: function(o, cb) { var resp, fingerprint; cb = cb || $.noop; o = _.isString(o) ? { url: o } : o || {}; fingerprint = this._fingerprint(o); this.cancelled = false; this.lastReq = fingerprint; if (resp = this._cache.get(fingerprint)) { cb(null, resp); } else { this._get(o, cb); } }, cancel: function() { this.cancelled = true; } }); return Transport; }(); var SearchIndex = window.SearchIndex = function() { "use strict"; var CHILDREN = "c", IDS = "i"; function SearchIndex(o) { o = o || {}; if (!o.datumTokenizer || !o.queryTokenizer) { $.error("datumTokenizer and queryTokenizer are both required"); } this.identify = o.identify || _.stringify; this.datumTokenizer = o.datumTokenizer; this.queryTokenizer = o.queryTokenizer; this.reset(); } _.mixin(SearchIndex.prototype, { bootstrap: function bootstrap(o) { this.datums = o.datums; this.trie = o.trie; }, add: function(data) { var that = this; data = _.isArray(data) ? data : [ data ]; _.each(data, function(datum) { var id, tokens; that.datums[id = that.identify(datum)] = datum; tokens = normalizeTokens(that.datumTokenizer(datum)); _.each(tokens, function(token) { var node, chars, ch; node = that.trie; chars = token.split(""); while (ch = chars.shift()) { node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode()); node[IDS].push(id); } }); }); }, get: function get(ids) { var that = this; return _.map(ids, function(id) { return that.datums[id]; }); }, search: function search(query) { var that = this, tokens, matches; tokens = normalizeTokens(this.queryTokenizer(query)); _.each(tokens, function(token) { var node, chars, ch, ids; if (matches && matches.length === 0) { return false; } node = that.trie; chars = token.split(""); while (node && (ch = chars.shift())) { node = node[CHILDREN][ch]; } if (node && chars.length === 0) { ids = node[IDS].slice(0); matches = matches ? getIntersection(matches, ids) : ids; } else { matches = []; return false; } }); return matches ? _.map(unique(matches), function(id) { return that.datums[id]; }) : []; }, all: function all() { var values = []; for (var key in this.datums) { values.push(this.datums[key]); } return values; }, reset: function reset() { this.datums = {}; this.trie = newNode(); }, serialize: function serialize() { return { datums: this.datums, trie: this.trie }; } }); return SearchIndex; function normalizeTokens(tokens) { tokens = _.filter(tokens, function(token) { return !!token; }); tokens = _.map(tokens, function(token) { return token.toLowerCase(); }); return tokens; } function newNode() { var node = {}; node[IDS] = []; node[CHILDREN] = {}; return node; } function unique(array) { var seen = {}, uniques = []; for (var i = 0, len = array.length; i < len; i++) { if (!seen[array[i]]) { seen[array[i]] = true; uniques.push(array[i]); } } return uniques; } function getIntersection(arrayA, arrayB) { var ai = 0, bi = 0, intersection = []; arrayA = arrayA.sort(); arrayB = arrayB.sort(); var lenArrayA = arrayA.length, lenArrayB = arrayB.length; while (ai < lenArrayA && bi < lenArrayB) { if (arrayA[ai] < arrayB[bi]) { ai++; } else if (arrayA[ai] > arrayB[bi]) { bi++; } else { intersection.push(arrayA[ai]); ai++; bi++; } } return intersection; } }(); var Prefetch = function() { "use strict"; var keys; keys = { data: "data", protocol: "protocol", thumbprint: "thumbprint" }; function Prefetch(o) { this.url = o.url; this.ttl = o.ttl; this.cache = o.cache; this.prepare = o.prepare; this.transform = o.transform; this.transport = o.transport; this.thumbprint = o.thumbprint; this.storage = new PersistentStorage(o.cacheKey); } _.mixin(Prefetch.prototype, { _settings: function settings() { return { url: this.url, type: "GET", dataType: "json" }; }, store: function store(data) { if (!this.cache) { return; } this.storage.set(keys.data, data, this.ttl); this.storage.set(keys.protocol, location.protocol, this.ttl); this.storage.set(keys.thumbprint, this.thumbprint, this.ttl); }, fromCache: function fromCache() { var stored = {}, isExpired; if (!this.cache) { return null; } stored.data = this.storage.get(keys.data); stored.protocol = this.storage.get(keys.protocol); stored.thumbprint = this.storage.get(keys.thumbprint); isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol; return stored.data && !isExpired ? stored.data : null; }, fromNetwork: function(cb) { var that = this, settings; if (!cb) { return; } settings = this.prepare(this._settings()); this.transport(settings).fail(onError).done(onResponse); function onError() { cb(true); } function onResponse(resp) { cb(null, that.transform(resp)); } }, clear: function clear() { this.storage.clear(); return this; } }); return Prefetch; }(); var Remote = function() { "use strict"; function Remote(o) { this.url = o.url; this.prepare = o.prepare; this.transform = o.transform; this.transport = new Transport({ cache: o.cache, limiter: o.limiter, transport: o.transport }); } _.mixin(Remote.prototype, { _settings: function settings() { return { url: this.url, type: "GET", dataType: "json" }; }, get: function get(query, cb) { var that = this, settings; if (!cb) { return; } query = query || ""; settings = this.prepare(query, this._settings()); return this.transport.get(settings, onResponse); function onResponse(err, resp) { err ? cb([]) : cb(that.transform(resp)); } }, cancelLastRequest: function cancelLastRequest() { this.transport.cancel(); } }); return Remote; }(); var oParser = function() { "use strict"; return function parse(o) { var defaults, sorter; defaults = { initialize: true, identify: _.stringify, datumTokenizer: null, queryTokenizer: null, sufficient: 5, sorter: null, local: [], prefetch: null, remote: null }; o = _.mixin(defaults, o || {}); !o.datumTokenizer && $.error("datumTokenizer is required"); !o.queryTokenizer && $.error("queryTokenizer is required"); sorter = o.sorter; o.sorter = sorter ? function(x) { return x.sort(sorter); } : _.identity; o.local = _.isFunction(o.local) ? o.local() : o.local; o.prefetch = parsePrefetch(o.prefetch); o.remote = parseRemote(o.remote); return o; }; function parsePrefetch(o) { var defaults; if (!o) { return null; } defaults = { url: null, ttl: 24 * 60 * 60 * 1e3, cache: true, cacheKey: null, thumbprint: "", prepare: _.identity, transform: _.identity, transport: null }; o = _.isString(o) ? { url: o } : o; o = _.mixin(defaults, o); !o.url && $.error("prefetch requires url to be set"); o.transform = o.filter || o.transform; o.cacheKey = o.cacheKey || o.url; o.thumbprint = VERSION + o.thumbprint; o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; return o; } function parseRemote(o) { var defaults; if (!o) { return; } defaults = { url: null, cache: true, prepare: null, replace: null, wildcard: null, limiter: null, rateLimitBy: "debounce", rateLimitWait: 300, transform: _.identity, transport: null }; o = _.isString(o) ? { url: o } : o; o = _.mixin(defaults, o); !o.url && $.error("remote requires url to be set"); o.transform = o.filter || o.transform; o.prepare = toRemotePrepare(o); o.limiter = toLimiter(o); o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; delete o.replace; delete o.wildcard; delete o.rateLimitBy; delete o.rateLimitWait; return o; } function toRemotePrepare(o) { var prepare, replace, wildcard; prepare = o.prepare; replace = o.replace; wildcard = o.wildcard; if (prepare) { return prepare; } if (replace) { prepare = prepareByReplace; } else if (o.wildcard) { prepare = prepareByWildcard; } else { prepare = idenityPrepare; } return prepare; function prepareByReplace(query, settings) { settings.url = replace(settings.url, query); return settings; } function prepareByWildcard(query, settings) { settings.url = settings.url.replace(wildcard, encodeURIComponent(query)); return settings; } function idenityPrepare(query, settings) { return settings; } } function toLimiter(o) { var limiter, method, wait; limiter = o.limiter; method = o.rateLimitBy; wait = o.rateLimitWait; if (!limiter) { limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait); } return limiter; function debounce(wait) { return function debounce(fn) { return _.debounce(fn, wait); }; } function throttle(wait) { return function throttle(fn) { return _.throttle(fn, wait); }; } } function callbackToDeferred(fn) { return function wrapper(o) { var deferred = $.Deferred(); fn(o, onSuccess, onError); return deferred; function onSuccess(resp) { _.defer(function() { deferred.resolve(resp); }); } function onError(err) { _.defer(function() { deferred.reject(err); }); } }; } }(); var Bloodhound = function() { "use strict"; var old; old = window && window.Bloodhound; function Bloodhound(o) { o = oParser(o); this.sorter = o.sorter; this.identify = o.identify; this.sufficient = o.sufficient; this.local = o.local; this.remote = o.remote ? new Remote(o.remote) : null; this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null; this.index = new SearchIndex({ identify: this.identify, datumTokenizer: o.datumTokenizer, queryTokenizer: o.queryTokenizer }); o.initialize !== false && this.initialize(); } Bloodhound.noConflict = function noConflict() { window && (window.Bloodhound = old); return Bloodhound; }; Bloodhound.tokenizers = tokenizers; _.mixin(Bloodhound.prototype, { __ttAdapter: function ttAdapter() { var that = this; return this.remote ? withAsync : withoutAsync; function withAsync(query, sync, async) { return that.search(query, sync, async); } function withoutAsync(query, sync) { return that.search(query, sync); } }, _loadPrefetch: function loadPrefetch() { var that = this, deferred, serialized; deferred = $.Deferred(); if (!this.prefetch) { deferred.resolve(); } else if (serialized = this.prefetch.fromCache()) { this.index.bootstrap(serialized); deferred.resolve(); } else { this.prefetch.fromNetwork(done); } return deferred.promise(); function done(err, data) { if (err) { return deferred.reject(); } that.add(data); that.prefetch.store(that.index.serialize()); deferred.resolve(); } }, _initialize: function initialize() { var that = this, deferred; this.clear(); (this.initPromise = this._loadPrefetch()).done(addLocalToIndex); return this.initPromise; function addLocalToIndex() { that.add(that.local); } }, initialize: function initialize(force) { return !this.initPromise || force ? this._initialize() : this.initPromise; }, add: function add(data) { this.index.add(data); return this; }, get: function get(ids) { ids = _.isArray(ids) ? ids : [].slice.call(arguments); return this.index.get(ids); }, search: function search(query, sync, async) { var that = this, local; local = this.sorter(this.index.search(query)); sync(this.remote ? local.slice() : local); if (this.remote && local.length < this.sufficient) { this.remote.get(query, processRemote); } else if (this.remote) { this.remote.cancelLastRequest(); } return this; function processRemote(remote) { var nonDuplicates = []; _.each(remote, function(r) { !_.some(local, function(l) { return that.identify(r) === that.identify(l); }) && nonDuplicates.push(r); }); async && async(nonDuplicates); } }, all: function all() { return this.index.all(); }, clear: function clear() { this.index.reset(); return this; }, clearPrefetchCache: function clearPrefetchCache() { this.prefetch && this.prefetch.clear(); return this; }, clearRemoteCache: function clearRemoteCache() { Transport.resetCache(); return this; }, ttAdapter: function ttAdapter() { return this.__ttAdapter(); } }); return Bloodhound; }(); return Bloodhound; }); (function(root, factory) { if (typeof define === "function" && define.amd) { define("typeahead.js", [ "jquery" ], function(a0) { return factory(a0); }); } else if (typeof exports === "object") { module.exports = factory(require("jquery")); } else { factory(jQuery); } })(this, function($) { var _ = function() { "use strict"; return { isMsie: function() { return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; }, isBlankString: function(str) { return !str || /^\s*$/.test(str); }, escapeRegExChars: function(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); }, isString: function(obj) { return typeof obj === "string"; }, isNumber: function(obj) { return typeof obj === "number"; }, isArray: $.isArray, isFunction: $.isFunction, isObject: $.isPlainObject, isUndefined: function(obj) { return typeof obj === "undefined"; }, isElement: function(obj) { return !!(obj && obj.nodeType === 1); }, isJQuery: function(obj) { return obj instanceof $; }, toStr: function toStr(s) { return _.isUndefined(s) || s === null ? "" : s + ""; }, bind: $.proxy, each: function(collection, cb) { $.each(collection, reverseArgs); function reverseArgs(index, value) { return cb(value, index); } }, map: $.map, filter: $.grep, every: function(obj, test) { var result = true; if (!obj) { return result; } $.each(obj, function(key, val) { if (!(result = test.call(null, val, key, obj))) { return false; } }); return !!result; }, some: function(obj, test) { var result = false; if (!obj) { return result; } $.each(obj, function(key, val) { if (result = test.call(null, val, key, obj)) { return false; } }); return !!result; }, mixin: $.extend, identity: function(x) { return x; }, clone: function(obj) { return $.extend(true, {}, obj); }, getIdGenerator: function() { var counter = 0; return function() { return counter++; }; }, templatify: function templatify(obj) { return $.isFunction(obj) ? obj : template; function template() { return String(obj); } }, defer: function(fn) { setTimeout(fn, 0); }, debounce: function(func, wait, immediate) { var timeout, result; return function() { var context = this, args = arguments, later, callNow; later = function() { timeout = null; if (!immediate) { result = func.apply(context, args); } }; callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { result = func.apply(context, args); } return result; }; }, throttle: function(func, wait) { var context, args, timeout, result, previous, later; previous = 0; later = function() { previous = new Date(); timeout = null; result = func.apply(context, args); }; return function() { var now = new Date(), remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0) { clearTimeout(timeout); timeout = null; previous = now; result = func.apply(context, args); } else if (!timeout) { timeout = setTimeout(later, remaining); } return result; }; }, stringify: function(val) { return _.isString(val) ? val : JSON.stringify(val); }, noop: function() {} }; }(); var WWW = function() { "use strict"; var defaultClassNames = { wrapper: "twitter-typeahead", input: "tt-input", hint: "tt-hint", menu: "tt-menu", dataset: "tt-dataset", suggestion: "tt-suggestion", selectable: "tt-selectable", empty: "tt-empty", open: "tt-open", cursor: "tt-cursor", highlight: "tt-highlight" }; return build; function build(o) { var www, classes; classes = _.mixin({}, defaultClassNames, o); www = { css: buildCss(), classes: classes, html: buildHtml(classes), selectors: buildSelectors(classes) }; return { css: www.css, html: www.html, classes: www.classes, selectors: www.selectors, mixin: function(o) { _.mixin(o, www); } }; } function buildHtml(c) { return { wrapper: '', menu: '
' }; } function buildSelectors(classes) { var selectors = {}; _.each(classes, function(v, k) { selectors[k] = "." + v; }); return selectors; } function buildCss() { var css = { wrapper: { position: "relative", display: "inline-block" }, hint: { position: "absolute", top: "0", left: "0", borderColor: "transparent", boxShadow: "none", opacity: "1" }, input: { position: "relative", verticalAlign: "top", backgroundColor: "transparent" }, inputWithNoHint: { position: "relative", verticalAlign: "top" }, menu: { position: "absolute", top: "100%", left: "0", zIndex: "100", // display: "none" }, ltr: { left: "0", right: "auto" }, rtl: { left: "auto", right: " 0" } }; if (_.isMsie()) { _.mixin(css.input, { backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" }); } return css; } }(); var EventBus = function() { "use strict"; var namespace, deprecationMap; namespace = "typeahead:"; deprecationMap = { render: "rendered", cursorchange: "cursorchanged", select: "selected", autocomplete: "autocompleted" }; function EventBus(o) { if (!o || !o.el) { $.error("EventBus initialized without el"); } this.$el = $(o.el); } _.mixin(EventBus.prototype, { _trigger: function(type, args) { var $e; $e = $.Event(namespace + type); (args = args || []).unshift($e); this.$el.trigger.apply(this.$el, args); return $e; }, before: function(type) { var args, $e; args = [].slice.call(arguments, 1); $e = this._trigger("before" + type, args); return $e.isDefaultPrevented(); }, trigger: function(type) { var deprecatedType; this._trigger(type, [].slice.call(arguments, 1)); if (deprecatedType = deprecationMap[type]) { this._trigger(deprecatedType, [].slice.call(arguments, 1)); } } }); return EventBus; }(); var EventEmitter = function() { "use strict"; var splitter = /\s+/, nextTick = getNextTick(); return { onSync: onSync, onAsync: onAsync, off: off, trigger: trigger }; function on(method, types, cb, context) { var type; if (!cb) { return this; } types = types.split(splitter); cb = context ? bindContext(cb, context) : cb; this._callbacks = this._callbacks || {}; while (type = types.shift()) { this._callbacks[type] = this._callbacks[type] || { sync: [], async: [] }; this._callbacks[type][method].push(cb); } return this; } function onAsync(types, cb, context) { return on.call(this, "async", types, cb, context); } function onSync(types, cb, context) { return on.call(this, "sync", types, cb, context); } function off(types) { var type; if (!this._callbacks) { return this; } types = types.split(splitter); while (type = types.shift()) { delete this._callbacks[type]; } return this; } function trigger(types) { var type, callbacks, args, syncFlush, asyncFlush; if (!this._callbacks) { return this; } types = types.split(splitter); args = [].slice.call(arguments, 1); while ((type = types.shift()) && (callbacks = this._callbacks[type])) { syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); syncFlush() && nextTick(asyncFlush); } return this; } function getFlush(callbacks, context, args) { return flush; function flush() { var cancelled; for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { cancelled = callbacks[i].apply(context, args) === false; } return !cancelled; } } function getNextTick() { var nextTickFn; if (window.setImmediate) { nextTickFn = function nextTickSetImmediate(fn) { setImmediate(function() { fn(); }); }; } else { nextTickFn = function nextTickSetTimeout(fn) { setTimeout(function() { fn(); }, 0); }; } return nextTickFn; } function bindContext(fn, context) { return fn.bind ? fn.bind(context) : function() { fn.apply(context, [].slice.call(arguments, 0)); }; } }(); var highlight = function(doc) { "use strict"; var defaults = { node: null, pattern: null, tagName: "strong", className: null, wordsOnly: false, caseSensitive: false }; return function hightlight(o) { var regex; o = _.mixin({}, defaults, o); if (!o.node || !o.pattern) { return; } o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); traverse(o.node, hightlightTextNode); function hightlightTextNode(textNode) { var match, patternNode, wrapperNode; if (match = regex.exec(textNode.data)) { wrapperNode = doc.createElement(o.tagName); o.className && (wrapperNode.className = o.className); patternNode = textNode.splitText(match.index); patternNode.splitText(match[0].length); wrapperNode.appendChild(patternNode.cloneNode(true)); textNode.parentNode.replaceChild(wrapperNode, patternNode); } return !!match; } function traverse(el, hightlightTextNode) { var childNode, TEXT_NODE_TYPE = 3; for (var i = 0; i < el.childNodes.length; i++) { childNode = el.childNodes[i]; if (childNode.nodeType === TEXT_NODE_TYPE) { i += hightlightTextNode(childNode) ? 1 : 0; } else { traverse(childNode, hightlightTextNode); } } } }; function getRegex(patterns, caseSensitive, wordsOnly) { var escapedPatterns = [], regexStr; for (var i = 0, len = patterns.length; i < len; i++) { escapedPatterns.push(_.escapeRegExChars(patterns[i])); } regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); } }(window.document); var Input = function() { "use strict"; var specialKeyCodeMap; specialKeyCodeMap = { 9: "tab", 27: "esc", 37: "left", 39: "right", // 13: "enter", 38: "up", 40: "down" }; function Input(o, www) { o = o || {}; if (!o.input) { $.error("input is missing"); } www.mixin(this); this.$hint = $(o.hint); this.$input = $(o.input); this.query = this.$input.val(); this.queryWhenFocused = this.hasFocus() ? this.query : null; this.$overflowHelper = buildOverflowHelper(this.$input); this._checkLanguageDirection(); if (this.$hint.length === 0) { this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; } } Input.normalizeQuery = function(str) { return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); }; _.mixin(Input.prototype, EventEmitter, { _onBlur: function onBlur() { this.resetInputValue(); this.trigger("blurred"); }, _onFocus: function onFocus() { this.queryWhenFocused = this.query; this.trigger("focused"); }, _onKeydown: function onKeydown($e) { var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; this._managePreventDefault(keyName, $e); if (keyName && this._shouldTrigger(keyName, $e)) { this.trigger(keyName + "Keyed", $e); } }, _onInput: function onInput() { this._setQuery(this.getInputValue()); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, _managePreventDefault: function managePreventDefault(keyName, $e) { var preventDefault; switch (keyName) { case "up": case "down": preventDefault = !withModifier($e); break; default: preventDefault = false; } preventDefault && $e.preventDefault(); }, _shouldTrigger: function shouldTrigger(keyName, $e) { var trigger; switch (keyName) { case "tab": trigger = !withModifier($e); break; default: trigger = true; } return trigger; }, _checkLanguageDirection: function checkLanguageDirection() { var dir = (this.$input.css("direction") || "ltr").toLowerCase(); if (this.dir !== dir) { this.dir = dir; this.$hint.attr("dir", dir); this.trigger("langDirChanged", dir); } }, _setQuery: function setQuery(val, silent) { var areEquivalent, hasDifferentWhitespace; areEquivalent = areQueriesEquivalent(val, this.query); hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; this.query = val; if (!silent && !areEquivalent) { this.trigger("queryChanged", this.query); } else if (!silent && hasDifferentWhitespace) { this.trigger("whitespaceChanged", this.query); } }, bind: function() { var that = this, onBlur, onFocus, onKeydown, onInput; onBlur = _.bind(this._onBlur, this); onFocus = _.bind(this._onFocus, this); onKeydown = _.bind(this._onKeydown, this); onInput = _.bind(this._onInput, this); this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); if (!_.isMsie() || _.isMsie() > 9) { this.$input.on("input.tt", onInput); } else { this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { if (specialKeyCodeMap[$e.which || $e.keyCode]) { return; } _.defer(_.bind(that._onInput, that, $e)); }); } return this; }, focus: function focus() { this.$input.focus(); }, blur: function blur() { this.$input.blur(); }, getLangDir: function getLangDir() { return this.dir; }, getQuery: function getQuery() { return this.query || ""; }, setQuery: function setQuery(val, silent) { this.setInputValue(val); this._setQuery(val, silent); }, hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { return this.query !== this.queryWhenFocused; }, getInputValue: function getInputValue() { return this.$input.val(); }, setInputValue: function setInputValue(value) { this.$input.val(value); this.clearHintIfInvalid(); this._checkLanguageDirection(); }, resetInputValue: function resetInputValue() { this.setInputValue(this.query); }, getHint: function getHint() { return this.$hint.val(); }, setHint: function setHint(value) { this.$hint.val(value); }, clearHint: function clearHint() { this.setHint(""); }, clearHintIfInvalid: function clearHintIfInvalid() { var val, hint, valIsPrefixOfHint, isValid; val = this.getInputValue(); hint = this.getHint(); valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); !isValid && this.clearHint(); }, hasFocus: function hasFocus() { return this.$input.is(":focus"); }, hasOverflow: function hasOverflow() { var constraint = this.$input.width() - 2; this.$overflowHelper.text(this.getInputValue()); return this.$overflowHelper.width() >= constraint; }, isCursorAtEnd: function() { var valueLength, selectionStart, range; valueLength = this.$input.val().length; selectionStart = this.$input[0].selectionStart; if (_.isNumber(selectionStart)) { return selectionStart === valueLength; } else if (document.selection) { range = document.selection.createRange(); range.moveStart("character", -valueLength); return valueLength === range.text.length; } return true; }, destroy: function destroy() { this.$hint.off(".tt"); this.$input.off(".tt"); this.$overflowHelper.remove(); this.$hint = this.$input = this.$overflowHelper = $("
"); } }); return Input; function buildOverflowHelper($input) { return $('').css({ position: "absolute", visibility: "hidden", whiteSpace: "pre", fontFamily: $input.css("font-family"), fontSize: $input.css("font-size"), fontStyle: $input.css("font-style"), fontVariant: $input.css("font-variant"), fontWeight: $input.css("font-weight"), wordSpacing: $input.css("word-spacing"), letterSpacing: $input.css("letter-spacing"), textIndent: $input.css("text-indent"), textRendering: $input.css("text-rendering"), textTransform: $input.css("text-transform") }).insertAfter($input); } function areQueriesEquivalent(a, b) { return Input.normalizeQuery(a) === Input.normalizeQuery(b); } function withModifier($e) { return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; } }(); var Dataset = function() { "use strict"; var keys, nameGenerator; keys = { val: "tt-selectable-display", obj: "tt-selectable-object" }; nameGenerator = _.getIdGenerator(); function Dataset(o, www) { o = o || {}; o.templates = o.templates || {}; o.templates.notFound = o.templates.notFound || o.templates.empty; if (!o.source) { $.error("missing source"); } if (!o.node) { $.error("missing node"); } if (o.name && !isValidName(o.name)) { $.error("invalid dataset name: " + o.name); } www.mixin(this); this.highlight = !!o.highlight; this.name = o.name || nameGenerator(); this.limit = o.limit || 5; this.displayFn = getDisplayFn(o.display || o.displayKey); this.templates = getTemplates(o.templates, this.displayFn); this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; this._resetLastSuggestion(); this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); } Dataset.extractData = function extractData(el) { var $el = $(el); if ($el.data(keys.obj)) { return { val: $el.data(keys.val) || "", obj: $el.data(keys.obj) || null }; } return null; }; _.mixin(Dataset.prototype, EventEmitter, { _overwrite: function overwrite(query, suggestions) { suggestions = suggestions || []; if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (this.async && this.templates.pending) { this._renderPending(query); } else if (!this.async && this.templates.notFound) { this._renderNotFound(query); } else { this._empty(); } this.trigger("rendered", this.name, suggestions, false); }, _append: function append(query, suggestions) { suggestions = suggestions || []; if (suggestions.length && this.$lastSuggestion.length) { this._appendSuggestions(query, suggestions); } else if (suggestions.length) { this._renderSuggestions(query, suggestions); } else if (!this.$lastSuggestion.length && this.templates.notFound) { this._renderNotFound(query); } this.trigger("rendered", this.name, suggestions, true); }, _renderSuggestions: function renderSuggestions(query, suggestions) { var $fragment; $fragment = this._getSuggestionsFragment(query, suggestions); this.$lastSuggestion = $fragment.children().last(); this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); }, _appendSuggestions: function appendSuggestions(query, suggestions) { var $fragment, $lastSuggestion; $fragment = this._getSuggestionsFragment(query, suggestions); $lastSuggestion = $fragment.children().last(); this.$lastSuggestion.after($fragment); this.$lastSuggestion = $lastSuggestion; }, _renderPending: function renderPending(query) { var template = this.templates.pending; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _renderNotFound: function renderNotFound(query) { var template = this.templates.notFound; this._resetLastSuggestion(); template && this.$el.html(template({ query: query, dataset: this.name })); }, _empty: function empty() { this.$el.empty(); this._resetLastSuggestion(); }, _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { var that = this, fragment; fragment = document.createDocumentFragment(); _.each(suggestions, function getSuggestionNode(suggestion) { var $el, context; context = that._injectQuery(query, suggestion); $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); fragment.appendChild($el[0]); }); this.highlight && highlight({ className: this.classes.highlight, node: fragment, pattern: query }); return $(fragment); }, _getFooter: function getFooter(query, suggestions) { return this.templates.footer ? this.templates.footer({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _getHeader: function getHeader(query, suggestions) { return this.templates.header ? this.templates.header({ query: query, suggestions: suggestions, dataset: this.name }) : null; }, _resetLastSuggestion: function resetLastSuggestion() { this.$lastSuggestion = $(); }, _injectQuery: function injectQuery(query, obj) { return _.isObject(obj) ? _.mixin({ _query: query }, obj) : obj; }, update: function update(query) { var that = this, canceled = false, syncCalled = false, rendered = 0; this.cancel(); this.cancel = function cancel() { canceled = true; that.cancel = $.noop; that.async && that.trigger("asyncCanceled", query); }; this.source(query, sync, async); !syncCalled && sync([]); function sync(suggestions) { if (syncCalled) { return; } syncCalled = true; suggestions = (suggestions || []).slice(0, that.limit); rendered = suggestions.length; that._overwrite(query, suggestions); if (rendered < that.limit && that.async) { that.trigger("asyncRequested", query); } } function async(suggestions) { suggestions = suggestions || []; if (!canceled && rendered < that.limit) { that.cancel = $.noop; suggestions = (suggestions || []).slice(0, that.limit); rendered = suggestions.length; that._append(query, suggestions); that.async && that.trigger("asyncReceived", query); } } }, cancel: $.noop, clear: function clear() { this._empty(); this.cancel(); this.trigger("cleared"); }, isEmpty: function isEmpty() { return this.$el.is(":empty"); }, destroy: function destroy() { this.$el = $("
"); } }); return Dataset; function getDisplayFn(display) { display = display || _.stringify; return _.isFunction(display) ? display : displayFn; function displayFn(obj) { return obj[display]; } } function getTemplates(templates, displayFn) { return { notFound: templates.notFound && _.templatify(templates.notFound), pending: templates.pending && _.templatify(templates.pending), header: templates.header && _.templatify(templates.header), footer: templates.footer && _.templatify(templates.footer), suggestion: templates.suggestion || suggestionTemplate }; function suggestionTemplate(context) { return $("
").text(displayFn(context)); } } function isValidName(str) { return /^[_a-zA-Z0-9-]+$/.test(str); } }(); var Menu = function() { "use strict"; function Menu(o, www) { var that = this; o = o || {}; if (!o.node) { $.error("node is required"); } www.mixin(this); this.$node = $(o.node); this.query = null; this.datasets = _.map(o.datasets, initializeDataset); function initializeDataset(oDataset) { var node = that.$node.find(oDataset.node).first(); oDataset.node = node.length ? node : $("
").appendTo(that.$node); return new Dataset(oDataset, www); } } _.mixin(Menu.prototype, EventEmitter, { _onSelectableClick: function onSelectableClick($e) { this.trigger("selectableClicked", $($e.currentTarget)); }, _onRendered: function onRendered(type, dataset, suggestions, async) { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetRendered", dataset, suggestions, async); }, _onCleared: function onCleared() { this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); this.trigger("datasetCleared"); }, _propagate: function propagate() { this.trigger.apply(this, arguments); }, _allDatasetsEmpty: function allDatasetsEmpty() { return _.every(this.datasets, isDatasetEmpty); function isDatasetEmpty(dataset) { return dataset.isEmpty(); } }, _getSelectables: function getSelectables() { return this.$node.find(this.selectors.selectable); }, _removeCursor: function _removeCursor() { var $selectable = this.getActiveSelectable(); $selectable && $selectable.removeClass(this.classes.cursor); }, _ensureVisible: function ensureVisible($el) { var elTop, elBottom, nodeScrollTop, nodeHeight; elTop = $el.position().top; elBottom = elTop + $el.outerHeight(true); nodeScrollTop = this.$node.scrollTop(); nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); if (elTop < 0) { this.$node.scrollTop(nodeScrollTop + elTop); } else if (nodeHeight < elBottom) { this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); } }, bind: function() { var that = this, onSelectableClick; onSelectableClick = _.bind(this._onSelectableClick, this); this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); _.each(this.datasets, function(dataset) { dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); }); return this; }, isOpen: function isOpen() { return this.$node.hasClass(this.classes.open); }, open: function open() { this.$node.addClass(this.classes.open); }, close: function close() { this.$node.removeClass(this.classes.open); this._removeCursor(); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.attr("dir", dir); }, selectableRelativeToCursor: function selectableRelativeToCursor(delta) { var $selectables, $oldCursor, oldIndex, newIndex; $oldCursor = this.getActiveSelectable(); $selectables = this._getSelectables(); oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; newIndex = oldIndex + delta; newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; return newIndex === -1 ? null : $selectables.eq(newIndex); }, setCursor: function setCursor($selectable) { this._removeCursor(); if ($selectable = $selectable && $selectable.first()) { $selectable.addClass(this.classes.cursor); this._ensureVisible($selectable); } }, getSelectableData: function getSelectableData($el) { return $el && $el.length ? Dataset.extractData($el) : null; }, getActiveSelectable: function getActiveSelectable() { var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); return $selectable.length ? $selectable : null; }, getTopSelectable: function getTopSelectable() { var $selectable = this._getSelectables().first(); return $selectable.length ? $selectable : null; }, update: function update(query) { var isValidUpdate = query !== this.query; if (isValidUpdate) { this.query = query; _.each(this.datasets, updateDataset); } return isValidUpdate; function updateDataset(dataset) { dataset.update(query); } }, empty: function empty() { _.each(this.datasets, clearDataset); this.query = null; this.$node.addClass(this.classes.empty); function clearDataset(dataset) { dataset.clear(); } }, destroy: function destroy() { this.$node.off(".tt"); this.$node = $("
"); _.each(this.datasets, destroyDataset); function destroyDataset(dataset) { dataset.destroy(); } } }); return Menu; }(); var DefaultMenu = function() { "use strict"; var s = Menu.prototype; function DefaultMenu() { Menu.apply(this, [].slice.call(arguments, 0)); } _.mixin(DefaultMenu.prototype, Menu.prototype, { open: function open() { !this._allDatasetsEmpty() && this._show(); return s.open.apply(this, [].slice.call(arguments, 0)); }, close: function close() { this._hide(); //jQuery( "#block-intsys-search-intsys-search" ).hide(); return s.close.apply(this, [].slice.call(arguments, 0)); }, _onRendered: function onRendered() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onRendered.apply(this, [].slice.call(arguments, 0)); }, _onCleared: function onCleared() { if (this._allDatasetsEmpty()) { this._hide(); } else { this.isOpen() && this._show(); } return s._onCleared.apply(this, [].slice.call(arguments, 0)); }, setLanguageDirection: function setLanguageDirection(dir) { this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); }, _hide: function hide() { this.$node.hide(); }, _show: function show() { this.$node.css("display", "block"); } }); return DefaultMenu; }(); var Typeahead = function() { "use strict"; function Typeahead(o, www) { var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; o = o || {}; if (!o.input) { $.error("missing input"); } if (!o.menu) { $.error("missing menu"); } if (!o.eventBus) { $.error("missing event bus"); } www.mixin(this); this.eventBus = o.eventBus; this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; this.input = o.input; this.menu = o.menu; this.enabled = true; this.active = false; this.input.hasFocus() && this.activate(); this.dir = this.input.getLangDir(); this._hacks(); this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); onFocused = c(this, "activate", "open", "_onFocused"); onBlurred = c(this, "deactivate", "_onBlurred"); onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); onEscKeyed = c(this, "isActive", "_onEscKeyed"); onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); } _.mixin(Typeahead.prototype, { _hacks: function hacks() { var $input, $menu; $input = this.input.$input || $("
"); $menu = this.menu.$node || $("
"); $input.on("blur.tt", function($e) { var active, isActive, hasActive; active = document.activeElement; isActive = $menu.is(active); hasActive = $menu.has(active).length > 0; if (_.isMsie() && (isActive || hasActive)) { $e.preventDefault(); $e.stopImmediatePropagation(); _.defer(function() { $input.focus(); }); } }); $menu.on("mousedown.tt", function($e) { $e.preventDefault(); }); }, _onSelectableClicked: function onSelectableClicked(type, $el) { this.select($el); }, _onDatasetCleared: function onDatasetCleared() { this._updateHint(); }, _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { this._updateHint(); this.eventBus.trigger("render", suggestions, async, dataset); }, _onAsyncRequested: function onAsyncRequested(type, dataset, query) { this.eventBus.trigger("asyncrequest", query, dataset); }, _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { this.eventBus.trigger("asynccancel", query, dataset); }, _onAsyncReceived: function onAsyncReceived(type, dataset, query) { this.eventBus.trigger("asyncreceive", query, dataset); }, _onFocused: function onFocused() { this._minLengthMet() && this.menu.update(this.input.getQuery()); }, _onBlurred: function onBlurred() { if (this.input.hasQueryChangedSinceLastFocus()) { this.eventBus.trigger("change", this.input.getQuery()); } }, _onEnterKeyed: function onEnterKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { this.select($selectable) && $e.preventDefault(); } }, _onTabKeyed: function onTabKeyed(type, $e) { var $selectable; if ($selectable = this.menu.getActiveSelectable()) { this.select($selectable) && $e.preventDefault(); } else if ($selectable = this.menu.getTopSelectable()) { this.autocomplete($selectable) && $e.preventDefault(); } }, _onEscKeyed: function onEscKeyed() { this.close(); }, _onUpKeyed: function onUpKeyed() { this.moveCursor(-1); }, _onDownKeyed: function onDownKeyed() { this.moveCursor(+1); }, _onLeftKeyed: function onLeftKeyed() { if (this.dir === "rtl" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getTopSelectable()); } }, _onRightKeyed: function onRightKeyed() { if (this.dir === "ltr" && this.input.isCursorAtEnd()) { this.autocomplete(this.menu.getTopSelectable()); } }, _onQueryChanged: function onQueryChanged(e, query) { this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); }, _onWhitespaceChanged: function onWhitespaceChanged() { this._updateHint(); }, _onLangDirChanged: function onLangDirChanged(e, dir) { if (this.dir !== dir) { this.dir = dir; this.menu.setLanguageDirection(dir); } }, _openIfActive: function openIfActive() { this.isActive() && this.open(); }, _minLengthMet: function minLengthMet(query) { query = _.isString(query) ? query : this.input.getQuery() || ""; return query.length >= this.minLength; }, _updateHint: function updateHint() { var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; $selectable = this.menu.getTopSelectable(); data = this.menu.getSelectableData($selectable); val = this.input.getInputValue(); if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { query = Input.normalizeQuery(val); escapedQuery = _.escapeRegExChars(query); frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); match = frontMatchRegEx.exec(data.val); match && this.input.setHint(val + match[1]); } else { this.input.clearHint(); } }, isEnabled: function isEnabled() { return this.enabled; }, enable: function enable() { this.enabled = true; }, disable: function disable() { this.enabled = false; }, isActive: function isActive() { return this.active; }, activate: function activate() { if (this.isActive()) { return true; } else if (!this.isEnabled() || this.eventBus.before("active")) { return false; } else { this.active = true; this.eventBus.trigger("active"); return true; } }, deactivate: function deactivate() { if (!this.isActive()) { return true; } else if (this.eventBus.before("idle")) { return false; } else { this.active = false; this.close(); this.eventBus.trigger("idle"); return true; } }, isOpen: function isOpen() { return this.menu.isOpen(); }, open: function open() { if (!this.isOpen() && !this.eventBus.before("open")) { this.menu.open(); this._updateHint(); this.eventBus.trigger("open"); } return this.isOpen(); }, close: function close() { if (this.isOpen() && !this.eventBus.before("close")) { this.menu.close(); this.input.clearHint(); this.input.resetInputValue(); this.eventBus.trigger("close"); } return !this.isOpen(); }, setVal: function setVal(val) { this.input.setQuery(_.toStr(val)); }, getVal: function getVal() { return this.input.getQuery(); }, select: function select($selectable) { var data = this.menu.getSelectableData($selectable); if (data && !this.eventBus.before("select", data.obj)) { this.input.setQuery(data.val, true); this.eventBus.trigger("select", data.obj); this.close(); return true; } return false; }, autocomplete: function autocomplete($selectable) { var query, data, isValid; query = this.input.getQuery(); data = this.menu.getSelectableData($selectable); isValid = data && query !== data.val; if (isValid && !this.eventBus.before("autocomplete", data.obj)) { this.input.setQuery(data.val); this.eventBus.trigger("autocomplete", data.obj); return true; } return false; }, moveCursor: function moveCursor(delta) { var query, $candidate, data, payload, cancelMove; query = this.input.getQuery(); $candidate = this.menu.selectableRelativeToCursor(delta); data = this.menu.getSelectableData($candidate); payload = data ? data.obj : null; cancelMove = this._minLengthMet() && this.menu.update(query); if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { this.menu.setCursor($candidate); if (data) { this.input.setInputValue(data.val); } else { this.input.resetInputValue(); this._updateHint(); } this.eventBus.trigger("cursorchange", payload); return true; } return false; }, destroy: function destroy() { this.input.destroy(); this.menu.destroy(); } }); return Typeahead; function c(ctx) { var methods = [].slice.call(arguments, 1); return function() { var args = [].slice.call(arguments); _.each(methods, function(method) { return ctx[method].apply(ctx, args); }); }; } }(); (function() { "use strict"; var old, keys, methods; old = $.fn.typeahead; keys = { www: "tt-www", attrs: "tt-attrs", typeahead: "tt-typeahead" }; methods = { initialize: function initialize(o, datasets) { var www; datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); o = o || {}; www = WWW(o.classNames); return this.each(attach); function attach() { var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; _.each(datasets, function(d) { d.highlight = !!o.highlight; }); $input = $(this); $wrapper = $(www.html.wrapper); $hint = $elOrNull(o.hint); $menu = $elOrNull(o.menu); defaultHint = o.hint !== false && !$hint; defaultMenu = o.menu !== false && !$menu; defaultHint && ($hint = buildHintFromInput($input, www)); defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); $hint && $hint.val(""); $input = prepInput($input, www); if (defaultHint || defaultMenu) { $wrapper.css(www.css.wrapper); $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); } MenuConstructor = defaultMenu ? DefaultMenu : Menu; eventBus = new EventBus({ el: $input }); input = new Input({ hint: $hint, input: $input }, www); menu = new MenuConstructor({ node: $menu, datasets: datasets }, www); typeahead = new Typeahead({ input: input, menu: menu, eventBus: eventBus, minLength: o.minLength }, www); $input.data(keys.www, www); $input.data(keys.typeahead, typeahead); } }, isEnabled: function isEnabled() { var enabled; ttEach(this.first(), function(t) { enabled = t.isEnabled(); }); return enabled; }, enable: function enable() { ttEach(this, function(t) { t.enable(); }); return this; }, disable: function disable() { ttEach(this, function(t) { t.disable(); }); return this; }, isActive: function isActive() { var active; ttEach(this.first(), function(t) { active = t.isActive(); }); return active; }, activate: function activate() { ttEach(this, function(t) { t.activate(); }); return this; }, deactivate: function deactivate() { ttEach(this, function(t) { t.deactivate(); }); return this; }, isOpen: function isOpen() { var open; ttEach(this.first(), function(t) { open = t.isOpen(); }); return open; }, open: function open() { ttEach(this, function(t) { t.open(); }); return this; }, close: function close() { ttEach(this, function(t) { t.close(); }); return this; }, select: function select(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.select($el); }); return success; }, autocomplete: function autocomplete(el) { var success = false, $el = $(el); ttEach(this.first(), function(t) { success = t.autocomplete($el); }); return success; }, moveCursor: function moveCursoe(delta) { var success = false; ttEach(this.first(), function(t) { success = t.moveCursor(delta); }); return success; }, val: function val(newVal) { var query; if (!arguments.length) { ttEach(this.first(), function(t) { query = t.getVal(); }); return query; } else { ttEach(this, function(t) { t.setVal(newVal); }); return this; } }, destroy: function destroy() { ttEach(this, function(typeahead, $input) { revert($input); typeahead.destroy(); }); return this; } }; $.fn.typeahead = function(method) { if (methods[method]) { return methods[method].apply(this, [].slice.call(arguments, 1)); } else { return methods.initialize.apply(this, arguments); } }; $.fn.typeahead.noConflict = function noConflict() { $.fn.typeahead = old; return this; }; function ttEach($els, fn) { $els.each(function() { var $input = $(this), typeahead; (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); }); } function buildHintFromInput($input, www) { return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ autocomplete: "off", spellcheck: "false", tabindex: -1 }); } function prepInput($input, www) { $input.data(keys.attrs, { dir: $input.attr("dir"), autocomplete: $input.attr("autocomplete"), spellcheck: $input.attr("spellcheck"), style: $input.attr("style") }); $input.addClass(www.classes.input).attr({ autocomplete: "off", spellcheck: false }); try { !$input.attr("dir") && $input.attr("dir", "auto"); } catch (e) {} return $input; } function getBackgroundStyles($el) { return { backgroundAttachment: $el.css("background-attachment"), backgroundClip: $el.css("background-clip"), backgroundColor: $el.css("background-color"), backgroundImage: $el.css("background-image"), backgroundOrigin: $el.css("background-origin"), backgroundPosition: $el.css("background-position"), backgroundRepeat: $el.css("background-repeat"), backgroundSize: $el.css("background-size") }; } function revert($input) { var www, $wrapper; www = $input.data(keys.www); $wrapper = $input.parent().filter(www.selectors.wrapper); _.each($input.data(keys.attrs), function(val, key) { _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); }); $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); if ($wrapper.length) { $input.detach().insertAfter($wrapper); $wrapper.remove(); } } function $elOrNull(obj) { var isValid, $el; isValid = _.isJQuery(obj) || _.isElement(obj); $el = isValid ? $(obj).first() : []; return $el.length ? $el : null; } })(); }); ;/*})'"*/ ;/*})'"*/ Drupal.wysiwyg = Drupal.wysiwyg || { 'instances': {}, 'excludeIdSelectors': { 'tokens': ['[id^="token-"]'] } }; Drupal.wysiwyg.editor = Drupal.wysiwyg.editor || { 'init': {}, 'update': {}, 'attach': {}, 'detach': {}, 'instance': {} }; Drupal.wysiwyg.plugins = Drupal.wysiwyg.plugins || {}; (function ($) { // Determine support for queryCommandEnabled(). // An exception should be thrown for non-existing commands. // Safari and Chrome (WebKit based) return -1 instead. try { document.queryCommandEnabled('__wysiwygTestCommand'); $.support.queryCommandEnabled = false; } catch (error) { $.support.queryCommandEnabled = true; } })(jQuery); ;/*})'"*/ ;/*})'"*/ /*! Chosen, a Select Box Enhancer for jQuery and Prototype by Patrick Filler for Harvest, http://getharvest.com Version 1.8.7 Full source at https://github.com/harvesthq/chosen Copyright (c) 2011-2018 Harvest http://getharvest.com MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md This file is generated by `grunt build`, do not edit it by hand. */ (function() { var $, AbstractChosen, Chosen, SelectParser, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; SelectParser = (function() { function SelectParser() { this.options_index = 0; this.parsed = []; } SelectParser.prototype.add_node = function(child) { if (child.nodeName.toUpperCase() === "OPTGROUP") { return this.add_group(child); } else { return this.add_option(child); } }; SelectParser.prototype.add_group = function(group) { var group_position, i, len, option, ref, results1; group_position = this.parsed.length; this.parsed.push({ array_index: group_position, group: true, label: group.label, title: group.title ? group.title : void 0, children: 0, disabled: group.disabled, classes: group.className }); ref = group.childNodes; results1 = []; for (i = 0, len = ref.length; i < len; i++) { option = ref[i]; results1.push(this.add_option(option, group_position, group.disabled)); } return results1; }; SelectParser.prototype.add_option = function(option, group_position, group_disabled) { if (option.nodeName.toUpperCase() === "OPTION") { if (option.text !== "") { if (group_position != null) { this.parsed[group_position].children += 1; } this.parsed.push({ array_index: this.parsed.length, options_index: this.options_index, value: option.value, text: option.text, html: option.innerHTML, title: option.title ? option.title : void 0, selected: option.selected, disabled: group_disabled === true ? group_disabled : option.disabled, group_array_index: group_position, group_label: group_position != null ? this.parsed[group_position].label : null, classes: option.className, style: option.style.cssText }); } else { this.parsed.push({ array_index: this.parsed.length, options_index: this.options_index, empty: true }); } return this.options_index += 1; } }; return SelectParser; })(); SelectParser.select_to_array = function(select) { var child, i, len, parser, ref; parser = new SelectParser(); ref = select.childNodes; for (i = 0, len = ref.length; i < len; i++) { child = ref[i]; parser.add_node(child); } return parser.parsed; }; AbstractChosen = (function() { function AbstractChosen(form_field, options1) { this.form_field = form_field; this.options = options1 != null ? options1 : {}; this.label_click_handler = bind(this.label_click_handler, this); if (!AbstractChosen.browser_is_supported()) { return; } this.is_multiple = this.form_field.multiple; this.set_default_text(); this.set_default_values(); this.setup(); this.set_up_html(); this.register_observers(); this.on_ready(); } AbstractChosen.prototype.set_default_values = function() { this.click_test_action = (function(_this) { return function(evt) { return _this.test_active_click(evt); }; })(this); this.activate_action = (function(_this) { return function(evt) { return _this.activate_field(evt); }; })(this); this.active_field = false; this.mouse_on_container = false; this.results_showing = false; this.result_highlighted = null; this.is_rtl = this.options.rtl || /\bchosen-rtl\b/.test(this.form_field.className); this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; this.disable_search_threshold = this.options.disable_search_threshold || 0; this.disable_search = this.options.disable_search || false; this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true; this.group_search = this.options.group_search != null ? this.options.group_search : true; this.search_contains = this.options.search_contains || false; this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true; this.max_selected_options = this.options.max_selected_options || Infinity; this.inherit_select_classes = this.options.inherit_select_classes || false; this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true; this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true; this.include_group_label_in_selected = this.options.include_group_label_in_selected || false; this.max_shown_results = this.options.max_shown_results || Number.POSITIVE_INFINITY; this.case_sensitive_search = this.options.case_sensitive_search || false; return this.hide_results_on_select = this.options.hide_results_on_select != null ? this.options.hide_results_on_select : false; }; AbstractChosen.prototype.set_default_text = function() { if (this.form_field.getAttribute("data-placeholder")) { this.default_text = this.form_field.getAttribute("data-placeholder"); } else if (this.is_multiple) { this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text; if(this.form_field.id=='edit-field-tag-und') this.default_text = this.options.placeholder_text_multiple_group; if(this.form_field.id=='edit-field-tags-und') this.default_text = this.options.placeholder_text_multiple_tags; } else { this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text; } this.default_text = this.escape_html(this.default_text); return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text; }; AbstractChosen.prototype.choice_label = function(item) { if (this.include_group_label_in_selected && (item.group_label != null)) { return "" + (this.escape_html(item.group_label)) + "" + item.html; } else { return item.html; } }; AbstractChosen.prototype.mouse_enter = function() { return this.mouse_on_container = true; }; AbstractChosen.prototype.mouse_leave = function() { return this.mouse_on_container = false; }; AbstractChosen.prototype.input_focus = function(evt) { if (this.is_multiple) { if (!this.active_field) { return setTimeout(((function(_this) { return function() { return _this.container_mousedown(); }; })(this)), 50); } } else { if (!this.active_field) { return this.activate_field(); } } }; AbstractChosen.prototype.input_blur = function(evt) { if (!this.mouse_on_container) { this.active_field = false; return setTimeout(((function(_this) { return function() { return _this.blur_test(); }; })(this)), 100); } }; AbstractChosen.prototype.label_click_handler = function(evt) { if (this.is_multiple) { return this.container_mousedown(evt); } else { return this.activate_field(); } }; AbstractChosen.prototype.results_option_build = function(options) { var content, data, data_content, i, len, ref, shown_results; content = ''; shown_results = 0; ref = this.results_data; for (i = 0, len = ref.length; i < len; i++) { data = ref[i]; data_content = ''; if (data.group) { data_content = this.result_add_group(data); } else { data_content = this.result_add_option(data); } if (data_content !== '') { shown_results++; content += data_content; } if (options != null ? options.first : void 0) { if (data.selected && this.is_multiple) { this.choice_build(data); } else if (data.selected && !this.is_multiple) { this.single_set_selected_text(this.choice_label(data)); } } if (shown_results >= this.max_shown_results) { break; } } return content; }; AbstractChosen.prototype.result_add_option = function(option) { var classes, option_el; if (!option.search_match) { return ''; } if (!this.include_option_in_results(option)) { return ''; } classes = []; if (!option.disabled && !(option.selected && this.is_multiple)) { classes.push("active-result"); } if (option.disabled && !(option.selected && this.is_multiple)) { classes.push("disabled-result"); } if (option.selected) { classes.push("result-selected"); } if (option.group_array_index != null) { classes.push("group-option"); } if (option.classes !== "") { classes.push(option.classes); } option_el = document.createElement("li"); option_el.className = classes.join(" "); if (option.style) { option_el.style.cssText = option.style; } option_el.setAttribute("data-option-array-index", option.array_index); option_el.innerHTML = option.highlighted_html || option.html; if (option.title) { option_el.title = option.title; } return this.outerHTML(option_el); }; AbstractChosen.prototype.result_add_group = function(group) { var classes, group_el; if (!(group.search_match || group.group_match)) { return ''; } if (!(group.active_options > 0)) { return ''; } classes = []; classes.push("group-result"); if (group.classes) { classes.push(group.classes); } group_el = document.createElement("li"); group_el.className = classes.join(" "); group_el.innerHTML = group.highlighted_html || this.escape_html(group.label); if (group.title) { group_el.title = group.title; } return this.outerHTML(group_el); }; AbstractChosen.prototype.results_update_field = function() { this.set_default_text(); if (!this.is_multiple) { this.results_reset_cleanup(); } this.result_clear_highlight(); this.results_build(); if (this.results_showing) { return this.winnow_results(); } }; AbstractChosen.prototype.reset_single_select_options = function() { var i, len, ref, result, results1; ref = this.results_data; results1 = []; for (i = 0, len = ref.length; i < len; i++) { result = ref[i]; if (result.selected) { results1.push(result.selected = false); } else { results1.push(void 0); } } return results1; }; AbstractChosen.prototype.results_toggle = function() { if (this.results_showing) { return this.results_hide(); } else { return this.results_show(); } }; AbstractChosen.prototype.results_search = function(evt) { if (this.results_showing) { return this.winnow_results(); } else { return this.results_show(); } }; AbstractChosen.prototype.winnow_results = function(options) { var escapedQuery, fix, i, len, option, prefix, query, ref, regex, results, results_group, search_match, startpos, suffix, text; this.no_results_clear(); results = 0; query = this.get_search_text(); escapedQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); regex = this.get_search_regex(escapedQuery); ref = this.results_data; for (i = 0, len = ref.length; i < len; i++) { option = ref[i]; option.search_match = false; results_group = null; search_match = null; option.highlighted_html = ''; if (this.include_option_in_results(option)) { if (option.group) { option.group_match = false; option.active_options = 0; } if ((option.group_array_index != null) && this.results_data[option.group_array_index]) { results_group = this.results_data[option.group_array_index]; if (results_group.active_options === 0 && results_group.search_match) { results += 1; } results_group.active_options += 1; } text = option.group ? option.label : option.text; if (!(option.group && !this.group_search)) { search_match = this.search_string_match(text, regex); option.search_match = search_match != null; if (option.search_match && !option.group) { results += 1; } if (option.search_match) { if (query.length) { startpos = search_match.index; prefix = text.slice(0, startpos); fix = text.slice(startpos, startpos + query.length); suffix = text.slice(startpos + query.length); option.highlighted_html = (this.escape_html(prefix)) + "" + (this.escape_html(fix)) + "" + (this.escape_html(suffix)); } if (results_group != null) { results_group.group_match = true; } } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) { option.search_match = true; } } } } this.result_clear_highlight(); if (results < 1 && query.length) { this.update_results_content(""); return this.no_results(query); } else { this.update_results_content(this.results_option_build()); if (!(options != null ? options.skip_highlight : void 0)) { return this.winnow_results_set_highlight(); } } }; AbstractChosen.prototype.get_search_regex = function(escaped_search_string) { var regex_flag, regex_string; regex_string = this.search_contains ? escaped_search_string : "(^|\\s|\\b)" + escaped_search_string + "[^\\s]*"; if (!(this.enable_split_word_search || this.search_contains)) { regex_string = "^" + regex_string; } regex_flag = this.case_sensitive_search ? "" : "i"; return new RegExp(regex_string, regex_flag); }; AbstractChosen.prototype.search_string_match = function(search_string, regex) { var match; match = regex.exec(search_string); if (!this.search_contains && (match != null ? match[1] : void 0)) { match.index += 1; } return match; }; AbstractChosen.prototype.choices_count = function() { var i, len, option, ref; if (this.selected_option_count != null) { return this.selected_option_count; } this.selected_option_count = 0; ref = this.form_field.options; for (i = 0, len = ref.length; i < len; i++) { option = ref[i]; if (option.selected) { this.selected_option_count += 1; } } return this.selected_option_count; }; AbstractChosen.prototype.choices_click = function(evt) { evt.preventDefault(); this.activate_field(); if (!(this.results_showing || this.is_disabled)) { return this.results_show(); } }; AbstractChosen.prototype.keydown_checker = function(evt) { var ref, stroke; stroke = (ref = evt.which) != null ? ref : evt.keyCode; this.search_field_scale(); if (stroke !== 8 && this.pending_backstroke) { this.clear_backstroke(); } switch (stroke) { case 8: this.backstroke_length = this.get_search_field_value().length; break; case 9: if (this.results_showing && !this.is_multiple) { this.result_select(evt); } this.mouse_on_container = false; break; case 13: if (this.results_showing) { evt.preventDefault(); } break; case 27: if (this.results_showing) { evt.preventDefault(); } break; case 32: if (this.disable_search) { evt.preventDefault(); } break; case 38: evt.preventDefault(); this.keyup_arrow(); break; case 40: evt.preventDefault(); this.keydown_arrow(); break; } }; AbstractChosen.prototype.keyup_checker = function(evt) { var ref, stroke; stroke = (ref = evt.which) != null ? ref : evt.keyCode; this.search_field_scale(); switch (stroke) { case 8: if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) { this.keydown_backstroke(); } else if (!this.pending_backstroke) { this.result_clear_highlight(); this.results_search(); } break; case 13: evt.preventDefault(); if (this.results_showing) { this.result_select(evt); } break; case 27: if (this.results_showing) { this.results_hide(); } break; case 9: case 16: case 17: case 18: case 38: case 40: case 91: break; default: this.results_search(); break; } }; AbstractChosen.prototype.clipboard_event_checker = function(evt) { if (this.is_disabled) { return; } return setTimeout(((function(_this) { return function() { return _this.results_search(); }; })(this)), 50); }; AbstractChosen.prototype.container_width = function() { if (this.options.width != null) { return this.options.width; } else { return this.form_field.offsetWidth + "px"; } }; AbstractChosen.prototype.include_option_in_results = function(option) { if (this.is_multiple && (!this.display_selected_options && option.selected)) { return false; } if (!this.display_disabled_options && option.disabled) { return false; } if (option.empty) { return false; } return true; }; AbstractChosen.prototype.search_results_touchstart = function(evt) { this.touch_started = true; return this.search_results_mouseover(evt); }; AbstractChosen.prototype.search_results_touchmove = function(evt) { this.touch_started = false; return this.search_results_mouseout(evt); }; AbstractChosen.prototype.search_results_touchend = function(evt) { if (this.touch_started) { return this.search_results_mouseup(evt); } }; AbstractChosen.prototype.outerHTML = function(element) { var tmp; if (element.outerHTML) { return element.outerHTML; } tmp = document.createElement("div"); tmp.appendChild(element); return tmp.innerHTML; }; AbstractChosen.prototype.get_single_html = function() { return "\n " + this.default_text + "\n
\n
\n
\n
\n \n
\n
    \n
    "; }; AbstractChosen.prototype.get_multi_html = function() { return "
      \n
    • \n \n
    • \n
    \n
    \n
      \n
      "; }; AbstractChosen.prototype.get_no_results_html = function(terms) { return "
    • \n " + this.results_none_found + " " + (this.escape_html(terms)) + "\n
    • "; }; AbstractChosen.browser_is_supported = function() { if ("Microsoft Internet Explorer" === window.navigator.appName) { return document.documentMode >= 8; } return true; if (/iP(od|hone)/i.test(window.navigator.userAgent) || /IEMobile/i.test(window.navigator.userAgent) || /Windows Phone/i.test(window.navigator.userAgent) || /BlackBerry/i.test(window.navigator.userAgent) || /BB10/i.test(window.navigator.userAgent) || /Android.*Mobile/i.test(window.navigator.userAgent)) { return false; } return true; }; AbstractChosen.default_multiple_text = "Select Some Options"; AbstractChosen.default_single_text = "Select an Option"; AbstractChosen.default_no_result_text = "No results match"; return AbstractChosen; })(); $ = jQuery; $.fn.extend({ chosen: function(options) { if (!AbstractChosen.browser_is_supported()) { return this; } return this.each(function(input_field) { var $this, chosen; $this = $(this); chosen = $this.data('chosen'); if (options === 'destroy') { if (chosen instanceof Chosen) { chosen.destroy(); } return; } if (!(chosen instanceof Chosen)) { $this.data('chosen', new Chosen(this, options)); } }); } }); Chosen = (function(superClass) { extend(Chosen, superClass); function Chosen() { return Chosen.__super__.constructor.apply(this, arguments); } Chosen.prototype.setup = function() { this.form_field_jq = $(this.form_field); return this.current_selectedIndex = this.form_field.selectedIndex; }; Chosen.prototype.set_up_html = function() { var container_classes, container_props; container_classes = ["chosen-container"]; container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single")); if (this.inherit_select_classes && this.form_field.className) { container_classes.push(this.form_field.className); } if (this.is_rtl) { container_classes.push("chosen-rtl"); } container_props = { 'class': container_classes.join(' '), 'title': this.form_field.title }; if (this.form_field.id.length) { container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen"; } this.container = $("
      ", container_props); this.container.width(this.container_width()); if (this.is_multiple) { this.container.html(this.get_multi_html()); } else { this.container.html(this.get_single_html()); } this.form_field_jq.hide().after(this.container); this.dropdown = this.container.find('div.chosen-drop').first(); this.search_field = this.container.find('input').first(); this.search_results = this.container.find('ul.chosen-results').first(); this.search_field_scale(); this.search_no_results = this.container.find('li.no-results').first(); if (this.is_multiple) { this.search_choices = this.container.find('ul.chosen-choices').first(); this.search_container = this.container.find('li.search-field').first(); } else { this.search_container = this.container.find('div.chosen-search').first(); this.selected_item = this.container.find('.chosen-single').first(); } this.results_build(); this.set_tab_index(); return this.set_label_behavior(); }; Chosen.prototype.on_ready = function() { return this.form_field_jq.trigger("chosen:ready", { chosen: this }); }; Chosen.prototype.register_observers = function() { this.container.on('touchstart.chosen', (function(_this) { return function(evt) { _this.container_mousedown(evt); }; })(this)); this.container.on('touchend.chosen', (function(_this) { return function(evt) { _this.container_mouseup(evt); }; })(this)); this.container.on('mousedown.chosen', (function(_this) { return function(evt) { _this.container_mousedown(evt); }; })(this)); this.container.on('mouseup.chosen', (function(_this) { return function(evt) { _this.container_mouseup(evt); }; })(this)); this.container.on('mouseenter.chosen', (function(_this) { return function(evt) { _this.mouse_enter(evt); }; })(this)); this.container.on('mouseleave.chosen', (function(_this) { return function(evt) { _this.mouse_leave(evt); }; })(this)); this.search_results.on('mouseup.chosen', (function(_this) { return function(evt) { _this.search_results_mouseup(evt); }; })(this)); this.search_results.on('mouseover.chosen', (function(_this) { return function(evt) { _this.search_results_mouseover(evt); }; })(this)); this.search_results.on('mouseout.chosen', (function(_this) { return function(evt) { _this.search_results_mouseout(evt); }; })(this)); this.search_results.on('mousewheel.chosen DOMMouseScroll.chosen', (function(_this) { return function(evt) { _this.search_results_mousewheel(evt); }; })(this)); this.search_results.on('touchstart.chosen', (function(_this) { return function(evt) { _this.search_results_touchstart(evt); }; })(this)); this.search_results.on('touchmove.chosen', (function(_this) { return function(evt) { _this.search_results_touchmove(evt); }; })(this)); this.search_results.on('touchend.chosen', (function(_this) { return function(evt) { _this.search_results_touchend(evt); }; })(this)); this.form_field_jq.on("chosen:updated.chosen", (function(_this) { return function(evt) { _this.results_update_field(evt); }; })(this)); this.form_field_jq.on("chosen:activate.chosen", (function(_this) { return function(evt) { _this.activate_field(evt); }; })(this)); this.form_field_jq.on("chosen:open.chosen", (function(_this) { return function(evt) { _this.container_mousedown(evt); }; })(this)); this.form_field_jq.on("chosen:close.chosen", (function(_this) { return function(evt) { _this.close_field(evt); }; })(this)); this.search_field.on('blur.chosen', (function(_this) { return function(evt) { _this.input_blur(evt); }; })(this)); this.search_field.on('keyup.chosen', (function(_this) { return function(evt) { _this.keyup_checker(evt); }; })(this)); this.search_field.on('keydown.chosen', (function(_this) { return function(evt) { _this.keydown_checker(evt); }; })(this)); this.search_field.on('focus.chosen', (function(_this) { return function(evt) { _this.input_focus(evt); }; })(this)); this.search_field.on('cut.chosen', (function(_this) { return function(evt) { _this.clipboard_event_checker(evt); }; })(this)); this.search_field.on('paste.chosen', (function(_this) { return function(evt) { _this.clipboard_event_checker(evt); }; })(this)); if (this.is_multiple) { return this.search_choices.on('click.chosen', (function(_this) { return function(evt) { _this.choices_click(evt); }; })(this)); } else { return this.container.on('click.chosen', function(evt) { evt.preventDefault(); }); } }; Chosen.prototype.destroy = function() { $(this.container[0].ownerDocument).off('click.chosen', this.click_test_action); if (this.form_field_label.length > 0) { this.form_field_label.off('click.chosen'); } if (this.search_field[0].tabIndex) { this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex; } this.container.remove(); this.form_field_jq.removeData('chosen'); return this.form_field_jq.show(); }; Chosen.prototype.search_field_disabled = function() { this.is_disabled = this.form_field.disabled || this.form_field_jq.parents('fieldset').is(':disabled'); this.container.toggleClass('chosen-disabled', this.is_disabled); this.search_field[0].disabled = this.is_disabled; if (!this.is_multiple) { this.selected_item.off('focus.chosen', this.activate_field); } if (this.is_disabled) { return this.close_field(); } else if (!this.is_multiple) { return this.selected_item.on('focus.chosen', this.activate_field); } }; Chosen.prototype.container_mousedown = function(evt) { var ref; if (this.is_disabled) { return; } if (evt && ((ref = evt.type) === 'mousedown' || ref === 'touchstart') && !this.results_showing) { evt.preventDefault(); } if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) { if (!this.active_field) { if (this.is_multiple) { this.search_field.val(""); } $(this.container[0].ownerDocument).on('click.chosen', this.click_test_action); this.results_show(); } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) { evt.preventDefault(); this.results_toggle(); } return this.activate_field(); } }; Chosen.prototype.container_mouseup = function(evt) { if (evt.target.nodeName === "ABBR" && !this.is_disabled) { return this.results_reset(evt); } }; Chosen.prototype.search_results_mousewheel = function(evt) { var delta; if (evt.originalEvent) { delta = evt.originalEvent.deltaY || -evt.originalEvent.wheelDelta || evt.originalEvent.detail; } if (delta != null) { evt.preventDefault(); if (evt.type === 'DOMMouseScroll') { delta = delta * 40; } return this.search_results.scrollTop(delta + this.search_results.scrollTop()); } }; Chosen.prototype.blur_test = function(evt) { if (!this.active_field && this.container.hasClass("chosen-container-active")) { return this.close_field(); } }; Chosen.prototype.close_field = function() { $(this.container[0].ownerDocument).off("click.chosen", this.click_test_action); this.active_field = false; this.results_hide(); this.container.removeClass("chosen-container-active"); this.clear_backstroke(); this.show_search_field_default(); this.search_field_scale(); return this.search_field.blur(); }; Chosen.prototype.activate_field = function() { if (this.is_disabled) { return; } this.container.addClass("chosen-container-active"); this.active_field = true; this.search_field.val(this.search_field.val()); return this.search_field.focus(); }; Chosen.prototype.test_active_click = function(evt) { var active_container; active_container = $(evt.target).closest('.chosen-container'); if (active_container.length && this.container[0] === active_container[0]) { return this.active_field = true; } else { return this.close_field(); } }; Chosen.prototype.results_build = function() { this.parsing = true; this.selected_option_count = null; this.results_data = SelectParser.select_to_array(this.form_field); if (this.is_multiple) { this.search_choices.find("li.search-choice").remove(); } else { this.single_set_selected_text(); if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) { this.search_field[0].readOnly = true; this.container.addClass("chosen-container-single-nosearch"); } else { this.search_field[0].readOnly = false; this.container.removeClass("chosen-container-single-nosearch"); } } this.update_results_content(this.results_option_build({ first: true })); this.search_field_disabled(); this.show_search_field_default(); this.search_field_scale(); return this.parsing = false; }; Chosen.prototype.result_do_highlight = function(el) { var high_bottom, high_top, maxHeight, visible_bottom, visible_top; if (el.length) { this.result_clear_highlight(); this.result_highlight = el; this.result_highlight.addClass("highlighted"); maxHeight = parseInt(this.search_results.css("maxHeight"), 10); visible_top = this.search_results.scrollTop(); visible_bottom = maxHeight + visible_top; high_top = this.result_highlight.position().top + this.search_results.scrollTop(); high_bottom = high_top + this.result_highlight.outerHeight(); if (high_bottom >= visible_bottom) { return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); } else if (high_top < visible_top) { return this.search_results.scrollTop(high_top); } } }; Chosen.prototype.result_clear_highlight = function() { if (this.result_highlight) { this.result_highlight.removeClass("highlighted"); } return this.result_highlight = null; }; Chosen.prototype.results_show = function() { if (this.is_multiple && this.max_selected_options <= this.choices_count()) { this.form_field_jq.trigger("chosen:maxselected", { chosen: this }); return false; } this.container.addClass("chosen-with-drop"); this.results_showing = true; this.search_field.focus(); this.search_field.val(this.get_search_field_value()); this.winnow_results(); return this.form_field_jq.trigger("chosen:showing_dropdown", { chosen: this }); }; Chosen.prototype.update_results_content = function(content) { return this.search_results.html(content); }; Chosen.prototype.results_hide = function() { if (this.results_showing) { this.result_clear_highlight(); this.container.removeClass("chosen-with-drop"); this.form_field_jq.trigger("chosen:hiding_dropdown", { chosen: this }); } return this.results_showing = false; }; Chosen.prototype.set_tab_index = function(el) { var ti; if (this.form_field.tabIndex) { ti = this.form_field.tabIndex; this.form_field.tabIndex = -1; return this.search_field[0].tabIndex = ti; } }; Chosen.prototype.set_label_behavior = function() { this.form_field_label = this.form_field_jq.parents("label"); if (!this.form_field_label.length && this.form_field.id.length) { this.form_field_label = $("label[for='" + this.form_field.id + "']"); } if (this.form_field_label.length > 0) { return this.form_field_label.on('click.chosen', this.label_click_handler); } }; Chosen.prototype.show_search_field_default = function() { if (this.is_multiple && this.choices_count() < 1 && !this.active_field) { this.search_field.val(this.default_text); return this.search_field.addClass("default"); } else { this.search_field.val(""); return this.search_field.removeClass("default"); } }; Chosen.prototype.search_results_mouseup = function(evt) { var target; target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); if (target.length) { this.result_highlight = target; this.result_select(evt); return this.search_field.focus(); } }; Chosen.prototype.search_results_mouseover = function(evt) { var target; target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); if (target) { return this.result_do_highlight(target); } }; Chosen.prototype.search_results_mouseout = function(evt) { if ($(evt.target).hasClass("active-result") || $(evt.target).parents('.active-result').first()) { return this.result_clear_highlight(); } }; Chosen.prototype.choice_build = function(item) { var choice, close_link; choice = $('
    • ', { "class": "search-choice" }).html("" + (this.choice_label(item)) + ""); if (item.disabled) { choice.addClass('search-choice-disabled'); } else { close_link = $('', { "class": 'search-choice-close', 'data-option-array-index': item.array_index }); close_link.on('click.chosen', (function(_this) { return function(evt) { return _this.choice_destroy_link_click(evt); }; })(this)); close_link.on('touchstart', (function(_this) { return function(evt) { return _this.choice_destroy_link_click(evt); }; })(this)); choice.append(close_link); } return this.search_container.before(choice); }; Chosen.prototype.choice_destroy_link_click = function(evt) { evt.preventDefault(); evt.stopPropagation(); if (!this.is_disabled) { return this.choice_destroy($(evt.target)); } }; Chosen.prototype.choice_destroy = function(link) { if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) { if (this.active_field) { this.search_field.focus(); } else { this.show_search_field_default(); } if (this.is_multiple && this.choices_count() > 0 && this.get_search_field_value().length < 1) { this.results_hide(); } link.parents('li').first().remove(); return this.search_field_scale(); } }; Chosen.prototype.results_reset = function() { this.reset_single_select_options(); this.form_field.options[0].selected = true; this.single_set_selected_text(); this.show_search_field_default(); this.results_reset_cleanup(); this.trigger_form_field_change(); if (this.active_field) { return this.results_hide(); } }; Chosen.prototype.results_reset_cleanup = function() { this.current_selectedIndex = this.form_field.selectedIndex; return this.selected_item.find("abbr").remove(); }; Chosen.prototype.result_select = function(evt) { var high, item; if (this.result_highlight) { high = this.result_highlight; this.result_clear_highlight(); if (this.is_multiple && this.max_selected_options <= this.choices_count()) { this.form_field_jq.trigger("chosen:maxselected", { chosen: this }); return false; } if (this.is_multiple) { high.removeClass("active-result"); } else { this.reset_single_select_options(); } high.addClass("result-selected"); item = this.results_data[high[0].getAttribute("data-option-array-index")]; item.selected = true; this.form_field.options[item.options_index].selected = true; this.selected_option_count = null; if (this.is_multiple) { this.choice_build(item); } else { this.single_set_selected_text(this.choice_label(item)); } if (this.is_multiple && (!this.hide_results_on_select || (evt.metaKey || evt.ctrlKey))) { if (evt.metaKey || evt.ctrlKey) { this.winnow_results({ skip_highlight: true }); } else { this.search_field.val(""); this.winnow_results(); } } else { this.results_hide(); this.show_search_field_default(); } if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) { this.trigger_form_field_change({ selected: this.form_field.options[item.options_index].value }); } this.current_selectedIndex = this.form_field.selectedIndex; evt.preventDefault(); return this.search_field_scale(); } }; Chosen.prototype.single_set_selected_text = function(text) { if (text == null) { text = this.default_text; } if (text === this.default_text) { this.selected_item.addClass("chosen-default"); } else { this.single_deselect_control_build(); this.selected_item.removeClass("chosen-default"); } return this.selected_item.find("span").html(text); }; Chosen.prototype.result_deselect = function(pos) { var result_data; result_data = this.results_data[pos]; if (!this.form_field.options[result_data.options_index].disabled) { result_data.selected = false; this.form_field.options[result_data.options_index].selected = false; this.selected_option_count = null; this.result_clear_highlight(); if (this.results_showing) { this.winnow_results(); } this.trigger_form_field_change({ deselected: this.form_field.options[result_data.options_index].value }); this.search_field_scale(); return true; } else { return false; } }; Chosen.prototype.single_deselect_control_build = function() { if (!this.allow_single_deselect) { return; } if (!this.selected_item.find("abbr").length) { this.selected_item.find("span").first().after(""); } return this.selected_item.addClass("chosen-single-with-deselect"); }; Chosen.prototype.get_search_field_value = function() { return this.search_field.val(); }; Chosen.prototype.get_search_text = function() { return $.trim(this.get_search_field_value()); }; Chosen.prototype.escape_html = function(text) { return $('
      ').text(text).html(); }; Chosen.prototype.winnow_results_set_highlight = function() { var do_high, selected_results; selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); if (do_high != null) { return this.result_do_highlight(do_high); } }; Chosen.prototype.no_results = function(terms) { var no_results_html; no_results_html = this.get_no_results_html(terms); this.search_results.append(no_results_html); return this.form_field_jq.trigger("chosen:no_results", { chosen: this }); }; Chosen.prototype.no_results_clear = function() { return this.search_results.find(".no-results").remove(); }; Chosen.prototype.keydown_arrow = function() { var next_sib; if (this.results_showing && this.result_highlight) { next_sib = this.result_highlight.nextAll("li.active-result").first(); if (next_sib) { return this.result_do_highlight(next_sib); } } else { return this.results_show(); } }; Chosen.prototype.keyup_arrow = function() { var prev_sibs; if (!this.results_showing && !this.is_multiple) { return this.results_show(); } else if (this.result_highlight) { prev_sibs = this.result_highlight.prevAll("li.active-result"); if (prev_sibs.length) { return this.result_do_highlight(prev_sibs.first()); } else { if (this.choices_count() > 0) { this.results_hide(); } return this.result_clear_highlight(); } } }; Chosen.prototype.keydown_backstroke = function() { var next_available_destroy; if (this.pending_backstroke) { this.choice_destroy(this.pending_backstroke.find("a").first()); return this.clear_backstroke(); } else { next_available_destroy = this.search_container.siblings("li.search-choice").last(); if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) { this.pending_backstroke = next_available_destroy; if (this.single_backstroke_delete) { return this.keydown_backstroke(); } else { return this.pending_backstroke.addClass("search-choice-focus"); } } } }; Chosen.prototype.clear_backstroke = function() { if (this.pending_backstroke) { this.pending_backstroke.removeClass("search-choice-focus"); } return this.pending_backstroke = null; }; Chosen.prototype.search_field_scale = function() { var div, i, len, style, style_block, styles, width; if (!this.is_multiple) { return; } style_block = { position: 'absolute', left: '-1000px', top: '-1000px', display: 'none', whiteSpace: 'pre' }; styles = ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing']; for (i = 0, len = styles.length; i < len; i++) { style = styles[i]; style_block[style] = this.search_field.css(style); } div = $('
      ').css(style_block); div.text(this.get_search_field_value()); $('body').append(div); width = div.width() + 25; div.remove(); if (this.container.is(':visible')) { width = Math.min(this.container.outerWidth() - 10, width); } return this.search_field.width(width); }; Chosen.prototype.trigger_form_field_change = function(extra) { this.form_field_jq.trigger("input", extra); return this.form_field_jq.trigger("change", extra); }; return Chosen; })(AbstractChosen); }).call(this); ;/*})'"*/ ;/*})'"*/ /** * @license MIT */ (function(window, document, undefined) {'use strict'; // ie10+ var ie10plus = window.navigator.msPointerEnabled; /** * Flow.js is a library providing multiple simultaneous, stable and * resumable uploads via the HTML5 File API. * @param [opts] * @param {number} [opts.chunkSize] * @param {bool} [opts.forceChunkSize] * @param {number} [opts.simultaneousUploads] * @param {bool} [opts.singleFile] * @param {string} [opts.fileParameterName] * @param {number} [opts.progressCallbacksInterval] * @param {number} [opts.speedSmoothingFactor] * @param {Object|Function} [opts.query] * @param {Object|Function} [opts.headers] * @param {bool} [opts.withCredentials] * @param {Function} [opts.preprocess] * @param {string} [opts.method] * @param {string|Function} [opts.testMethod] * @param {string|Function} [opts.uploadMethod] * @param {bool} [opts.prioritizeFirstAndLastChunk] * @param {bool} [opts.allowDuplicateUploads] * @param {string|Function} [opts.target] * @param {number} [opts.maxChunkRetries] * @param {number} [opts.chunkRetryInterval] * @param {Array.} [opts.permanentErrors] * @param {Array.} [opts.successStatuses] * @param {Function} [opts.initFileFn] * @param {Function} [opts.readFileFn] * @param {Function} [opts.generateUniqueIdentifier] * @constructor */ function Flow(opts) { /** * Supported by browser? * @type {boolean} */ this.support = ( typeof File !== 'undefined' && typeof Blob !== 'undefined' && typeof FileList !== 'undefined' && ( !!Blob.prototype.slice || !!Blob.prototype.webkitSlice || !!Blob.prototype.mozSlice || false ) // slicing files support ); if (!this.support) { return ; } /** * Check if directory upload is supported * @type {boolean} */ this.supportDirectory = /Chrome/.test(window.navigator.userAgent); /** * List of FlowFile objects * @type {Array.} */ this.files = []; /** * Default options for flow.js * @type {Object} */ this.defaults = { chunkSize: 1024 * 1024, forceChunkSize: false, simultaneousUploads: 3, singleFile: false, fileParameterName: 'file', progressCallbacksInterval: 500, speedSmoothingFactor: 0.1, query: {}, headers: {}, withCredentials: false, preprocess: null, method: 'multipart', testMethod: 'GET', uploadMethod: 'POST', prioritizeFirstAndLastChunk: false, allowDuplicateUploads: false, target: '/', testChunks: true, generateUniqueIdentifier: null, maxChunkRetries: 0, chunkRetryInterval: null, permanentErrors: [404, 413, 415, 500, 501], successStatuses: [200, 201, 202], onDropStopPropagation: false, initFileFn: null, readFileFn: webAPIFileRead }; /** * Current options * @type {Object} */ this.opts = {}; /** * List of events: * key stands for event name * value array list of callbacks * @type {} */ this.events = {}; var $ = this; /** * On drop event * @function * @param {MouseEvent} event */ this.onDrop = function (event) { if ($.opts.onDropStopPropagation) { event.stopPropagation(); } event.preventDefault(); var dataTransfer = event.dataTransfer; if (dataTransfer.items && dataTransfer.items[0] && dataTransfer.items[0].webkitGetAsEntry) { $.webkitReadDataTransfer(event); } else { $.addFiles(dataTransfer.files, event); } }; /** * Prevent default * @function * @param {MouseEvent} event */ this.preventEvent = function (event) { event.preventDefault(); }; /** * Current options * @type {Object} */ this.opts = Flow.extend({}, this.defaults, opts || {}); } Flow.prototype = { /** * Set a callback for an event, possible events: * fileSuccess(file), fileProgress(file), fileAdded(file, event), * fileRemoved(file), fileRetry(file), fileError(file, message), * complete(), progress(), error(message, file), pause() * @function * @param {string} event * @param {Function} callback */ on: function (event, callback) { event = event.toLowerCase(); if (!this.events.hasOwnProperty(event)) { this.events[event] = []; } this.events[event].push(callback); }, /** * Remove event callback * @function * @param {string} [event] removes all events if not specified * @param {Function} [fn] removes all callbacks of event if not specified */ off: function (event, fn) { if (event !== undefined) { event = event.toLowerCase(); if (fn !== undefined) { if (this.events.hasOwnProperty(event)) { arrayRemove(this.events[event], fn); } } else { delete this.events[event]; } } else { this.events = {}; } }, /** * Fire an event * @function * @param {string} event event name * @param {...} args arguments of a callback * @return {bool} value is false if at least one of the event handlers which handled this event * returned false. Otherwise it returns true. */ fire: function (event, args) { // `arguments` is an object, not array, in FF, so: args = Array.prototype.slice.call(arguments); event = event.toLowerCase(); var preventDefault = false; if (this.events.hasOwnProperty(event)) { each(this.events[event], function (callback) { preventDefault = callback.apply(this, args.slice(1)) === false || preventDefault; }, this); } if (event != 'catchall') { args.unshift('catchAll'); preventDefault = this.fire.apply(this, args) === false || preventDefault; } return !preventDefault; }, /** * Read webkit dataTransfer object * @param event */ webkitReadDataTransfer: function (event) { var $ = this; var queue = event.dataTransfer.items.length; var files = []; each(event.dataTransfer.items, function (item) { var entry = item.webkitGetAsEntry(); if (!entry) { decrement(); return ; } if (entry.isFile) { // due to a bug in Chrome's File System API impl - #149735 fileReadSuccess(item.getAsFile(), entry.fullPath); } else { readDirectory(entry.createReader()); } }); function readDirectory(reader) { reader.readEntries(function (entries) { if (entries.length) { queue += entries.length; each(entries, function(entry) { if (entry.isFile) { var fullPath = entry.fullPath; entry.file(function (file) { fileReadSuccess(file, fullPath); }, readError); } else if (entry.isDirectory) { readDirectory(entry.createReader()); } }); readDirectory(reader); } else { decrement(); } }, readError); } function fileReadSuccess(file, fullPath) { // relative path should not start with "/" file.relativePath = fullPath.substring(1); files.push(file); decrement(); } function readError(fileError) { throw fileError; } function decrement() { if (--queue == 0) { $.addFiles(files, event); } } }, /** * Generate unique identifier for a file * @function * @param {FlowFile} file * @returns {string} */ generateUniqueIdentifier: function (file) { var custom = this.opts.generateUniqueIdentifier; if (typeof custom === 'function') { return custom(file); } // Some confusion in different versions of Firefox var relativePath = file.relativePath || file.webkitRelativePath || file.fileName || file.name; return file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, ''); }, /** * Upload next chunk from the queue * @function * @returns {boolean} * @private */ uploadNextChunk: function (preventEvents) { // In some cases (such as videos) it's really handy to upload the first // and last chunk of a file quickly; this let's the server check the file's // metadata and determine if there's even a point in continuing. var found = false; if (this.opts.prioritizeFirstAndLastChunk) { each(this.files, function (file) { if (!file.paused && file.chunks.length && file.chunks[0].status() === 'pending') { file.chunks[0].send(); found = true; return false; } if (!file.paused && file.chunks.length > 1 && file.chunks[file.chunks.length - 1].status() === 'pending') { file.chunks[file.chunks.length - 1].send(); found = true; return false; } }); if (found) { return found; } } // Now, simply look for the next, best thing to upload each(this.files, function (file) { if (!file.paused) { each(file.chunks, function (chunk) { if (chunk.status() === 'pending') { chunk.send(); found = true; return false; } }); } if (found) { return false; } }); if (found) { return true; } // The are no more outstanding chunks to upload, check is everything is done var outstanding = false; each(this.files, function (file) { if (!file.isComplete()) { outstanding = true; return false; } }); if (!outstanding && !preventEvents) { // All chunks have been uploaded, complete async(function () { this.fire('complete'); }, this); } return false; }, /** * Assign a browse action to one or more DOM nodes. * @function * @param {Element|Array.} domNodes * @param {boolean} isDirectory Pass in true to allow directories to * @param {boolean} singleFile prevent multi file upload * @param {Object} attributes set custom attributes: * http://www.w3.org/TR/html-markup/input.file.html#input.file-attributes * eg: accept: 'image/*' * be selected (Chrome only). */ assignBrowse: function (domNodes, isDirectory, singleFile, attributes) { if (domNodes instanceof Element) { domNodes = [domNodes]; } each(domNodes, function (domNode) { var input; if (domNode.tagName === 'INPUT' && domNode.type === 'file') { input = domNode; } else { input = document.createElement('input'); input.setAttribute('type', 'file'); // display:none - not working in opera 12 extend(input.style, { visibility: 'hidden', position: 'absolute', width: '1px', height: '1px' }); // for opera 12 browser, input must be assigned to a document domNode.appendChild(input); // https://developer.mozilla.org/en/using_files_from_web_applications) // event listener is executed two times // first one - original mouse click event // second - input.click(), input is inside domNode domNode.addEventListener('click', function() { input.click(); }, false); } if (!this.opts.singleFile && !singleFile) { input.setAttribute('multiple', 'multiple'); } if (isDirectory) { input.setAttribute('webkitdirectory', 'webkitdirectory'); } each(attributes, function (value, key) { input.setAttribute(key, value); }); // When new files are added, simply append them to the overall list var $ = this; input.addEventListener('change', function (e) { if (e.target.value) { $.addFiles(e.target.files, e); e.target.value = ''; } }, false); }, this); }, /** * Assign one or more DOM nodes as a drop target. * @function * @param {Element|Array.} domNodes */ assignDrop: function (domNodes) { if (typeof domNodes.length === 'undefined') { domNodes = [domNodes]; } each(domNodes, function (domNode) { domNode.addEventListener('dragover', this.preventEvent, false); domNode.addEventListener('dragenter', this.preventEvent, false); domNode.addEventListener('drop', this.onDrop, false); }, this); }, /** * Un-assign drop event from DOM nodes * @function * @param domNodes */ unAssignDrop: function (domNodes) { if (typeof domNodes.length === 'undefined') { domNodes = [domNodes]; } each(domNodes, function (domNode) { domNode.removeEventListener('dragover', this.preventEvent); domNode.removeEventListener('dragenter', this.preventEvent); domNode.removeEventListener('drop', this.onDrop); }, this); }, /** * Returns a boolean indicating whether or not the instance is currently * uploading anything. * @function * @returns {boolean} */ isUploading: function () { var uploading = false; each(this.files, function (file) { if (file.isUploading()) { uploading = true; return false; } }); return uploading; }, /** * should upload next chunk * @function * @returns {boolean|number} */ _shouldUploadNext: function () { var num = 0; var should = true; var simultaneousUploads = this.opts.simultaneousUploads; each(this.files, function (file) { each(file.chunks, function(chunk) { if (chunk.status() === 'uploading') { num++; if (num >= simultaneousUploads) { should = false; return false; } } }); }); // if should is true then return uploading chunks's length return should && num; }, /** * Start or resume uploading. * @function */ upload: function () { // Make sure we don't start too many uploads at once var ret = this._shouldUploadNext(); if (ret === false) { return; } // Kick off the queue this.fire('uploadStart'); var started = false; for (var num = 1; num <= this.opts.simultaneousUploads - ret; num++) { started = this.uploadNextChunk(true) || started; } if (!started) { async(function () { this.fire('complete'); }, this); } }, /** * Resume uploading. * @function */ resume: function () { each(this.files, function (file) { file.resume(); }); }, /** * Pause uploading. * @function */ pause: function () { each(this.files, function (file) { file.pause(); }); }, /** * Cancel upload of all FlowFile objects and remove them from the list. * @function */ cancel: function () { for (var i = this.files.length - 1; i >= 0; i--) { this.files[i].cancel(); } }, /** * Returns a number between 0 and 1 indicating the current upload progress * of all files. * @function * @returns {number} */ progress: function () { var totalDone = 0; var totalSize = 0; // Resume all chunks currently being uploaded each(this.files, function (file) { totalDone += file.progress() * file.size; totalSize += file.size; }); return totalSize > 0 ? totalDone / totalSize : 0; }, /** * Add a HTML5 File object to the list of files. * @function * @param {File} file * @param {Event} [event] event is optional */ addFile: function (file, event) { this.addFiles([file], event); }, /** * Add a HTML5 File object to the list of files. * @function * @param {FileList|Array} fileList * @param {Event} [event] event is optional */ addFiles: function (fileList, event) { var files = []; each(fileList, function (file) { // https://github.com/flowjs/flow.js/issues/55 if ((!ie10plus || ie10plus && file.size > 0) && !(file.size % 4096 === 0 && (file.name === '.' || file.fileName === '.')) && (this.opts.allowDuplicateUploads || !this.getFromUniqueIdentifier(this.generateUniqueIdentifier(file)))) { var f = new FlowFile(this, file); if (this.fire('fileAdded', f, event)) { files.push(f); } } }, this); if (this.fire('filesAdded', files, event)) { each(files, function (file) { if (this.opts.singleFile && this.files.length > 0) { this.removeFile(this.files[0]); } this.files.push(file); }, this); this.fire('filesSubmitted', files, event); } }, /** * Cancel upload of a specific FlowFile object from the list. * @function * @param {FlowFile} file */ removeFile: function (file) { for (var i = this.files.length - 1; i >= 0; i--) { if (this.files[i] === file) { this.files.splice(i, 1); file.abort(); this.fire('fileRemoved', file); } } }, /** * Look up a FlowFile object by its unique identifier. * @function * @param {string} uniqueIdentifier * @returns {boolean|FlowFile} false if file was not found */ getFromUniqueIdentifier: function (uniqueIdentifier) { var ret = false; each(this.files, function (file) { if (file.uniqueIdentifier === uniqueIdentifier) { ret = file; } }); return ret; }, /** * Returns the total size of all files in bytes. * @function * @returns {number} */ getSize: function () { var totalSize = 0; each(this.files, function (file) { totalSize += file.size; }); return totalSize; }, /** * Returns the total size uploaded of all files in bytes. * @function * @returns {number} */ sizeUploaded: function () { var size = 0; each(this.files, function (file) { size += file.sizeUploaded(); }); return size; }, /** * Returns remaining time to upload all files in seconds. Accuracy is based on average speed. * If speed is zero, time remaining will be equal to positive infinity `Number.POSITIVE_INFINITY` * @function * @returns {number} */ timeRemaining: function () { var sizeDelta = 0; var averageSpeed = 0; each(this.files, function (file) { if (!file.paused && !file.error) { sizeDelta += file.size - file.sizeUploaded(); averageSpeed += file.averageSpeed; } }); if (sizeDelta && !averageSpeed) { return Number.POSITIVE_INFINITY; } if (!sizeDelta && !averageSpeed) { return 0; } return Math.floor(sizeDelta / averageSpeed); } }; /** * FlowFile class * @name FlowFile * @param {Flow} flowObj * @param {File} file * @constructor */ function FlowFile(flowObj, file) { /** * Reference to parent Flow instance * @type {Flow} */ this.flowObj = flowObj; /** * Used to store the bytes read * @type {Blob|string} */ this.bytes = null; /** * Reference to file * @type {File} */ this.file = file; /** * File name. Some confusion in different versions of Firefox * @type {string} */ this.name = file.fileName || file.name; /** * File size * @type {number} */ this.size = file.size; /** * Relative file path * @type {string} */ this.relativePath = file.relativePath || file.webkitRelativePath || this.name; /** * File unique identifier * @type {string} */ this.uniqueIdentifier = flowObj.generateUniqueIdentifier(file); /** * List of chunks * @type {Array.} */ this.chunks = []; /** * Indicated if file is paused * @type {boolean} */ this.paused = false; /** * Indicated if file has encountered an error * @type {boolean} */ this.error = false; /** * Average upload speed * @type {number} */ this.averageSpeed = 0; /** * Current upload speed * @type {number} */ this.currentSpeed = 0; /** * Date then progress was called last time * @type {number} * @private */ this._lastProgressCallback = Date.now(); /** * Previously uploaded file size * @type {number} * @private */ this._prevUploadedSize = 0; /** * Holds previous progress * @type {number} * @private */ this._prevProgress = 0; this.bootstrap(); } FlowFile.prototype = { /** * Update speed parameters * @link http://stackoverflow.com/questions/2779600/how-to-estimate-download-time-remaining-accurately * @function */ measureSpeed: function () { var timeSpan = Date.now() - this._lastProgressCallback; if (!timeSpan) { return ; } var smoothingFactor = this.flowObj.opts.speedSmoothingFactor; var uploaded = this.sizeUploaded(); // Prevent negative upload speed after file upload resume this.currentSpeed = Math.max((uploaded - this._prevUploadedSize) / timeSpan * 1000, 0); this.averageSpeed = smoothingFactor * this.currentSpeed + (1 - smoothingFactor) * this.averageSpeed; this._prevUploadedSize = uploaded; }, /** * For internal usage only. * Callback when something happens within the chunk. * @function * @param {FlowChunk} chunk * @param {string} event can be 'progress', 'success', 'error' or 'retry' * @param {string} [message] */ chunkEvent: function (chunk, event, message) { switch (event) { case 'progress': if (Date.now() - this._lastProgressCallback < this.flowObj.opts.progressCallbacksInterval) { break; } this.measureSpeed(); this.flowObj.fire('fileProgress', this, chunk); this.flowObj.fire('progress'); this._lastProgressCallback = Date.now(); break; case 'error': this.error = true; this.abort(true); this.flowObj.fire('fileError', this, message, chunk); this.flowObj.fire('error', message, this, chunk); break; case 'success': if (this.error) { return; } this.measureSpeed(); this.flowObj.fire('fileProgress', this, chunk); this.flowObj.fire('progress'); this._lastProgressCallback = Date.now(); if (this.isComplete()) { this.currentSpeed = 0; this.averageSpeed = 0; this.flowObj.fire('fileSuccess', this, message, chunk); } break; case 'retry': this.flowObj.fire('fileRetry', this, chunk); break; } }, /** * Pause file upload * @function */ pause: function() { this.paused = true; this.abort(); }, /** * Resume file upload * @function */ resume: function() { this.paused = false; this.flowObj.upload(); }, /** * Abort current upload * @function */ abort: function (reset) { this.currentSpeed = 0; this.averageSpeed = 0; var chunks = this.chunks; if (reset) { this.chunks = []; } each(chunks, function (c) { if (c.status() === 'uploading') { c.abort(); this.flowObj.uploadNextChunk(); } }, this); }, /** * Cancel current upload and remove from a list * @function */ cancel: function () { this.flowObj.removeFile(this); }, /** * Retry aborted file upload * @function */ retry: function () { this.bootstrap(); this.flowObj.upload(); }, /** * Clear current chunks and slice file again * @function */ bootstrap: function () { if (typeof this.flowObj.opts.initFileFn === "function") { this.flowObj.opts.initFileFn(this); } this.abort(true); this.error = false; // Rebuild stack of chunks from file this._prevProgress = 0; var round = this.flowObj.opts.forceChunkSize ? Math.ceil : Math.floor; var chunks = Math.max( round(this.size / this.flowObj.opts.chunkSize), 1 ); for (var offset = 0; offset < chunks; offset++) { this.chunks.push( new FlowChunk(this.flowObj, this, offset) ); } }, /** * Get current upload progress status * @function * @returns {number} from 0 to 1 */ progress: function () { if (this.error) { return 1; } if (this.chunks.length === 1) { this._prevProgress = Math.max(this._prevProgress, this.chunks[0].progress()); return this._prevProgress; } // Sum up progress across everything var bytesLoaded = 0; each(this.chunks, function (c) { // get chunk progress relative to entire file bytesLoaded += c.progress() * (c.endByte - c.startByte); }); var percent = bytesLoaded / this.size; // We don't want to lose percentages when an upload is paused this._prevProgress = Math.max(this._prevProgress, percent > 0.9999 ? 1 : percent); return this._prevProgress; }, /** * Indicates if file is being uploaded at the moment * @function * @returns {boolean} */ isUploading: function () { var uploading = false; each(this.chunks, function (chunk) { if (chunk.status() === 'uploading') { uploading = true; return false; } }); return uploading; }, /** * Indicates if file is has finished uploading and received a response * @function * @returns {boolean} */ isComplete: function () { var outstanding = false; each(this.chunks, function (chunk) { var status = chunk.status(); if (status === 'pending' || status === 'uploading' || status === 'reading' || chunk.preprocessState === 1 || chunk.readState === 1) { outstanding = true; return false; } }); return !outstanding; }, /** * Count total size uploaded * @function * @returns {number} */ sizeUploaded: function () { var size = 0; each(this.chunks, function (chunk) { size += chunk.sizeUploaded(); }); return size; }, /** * Returns remaining time to finish upload file in seconds. Accuracy is based on average speed. * If speed is zero, time remaining will be equal to positive infinity `Number.POSITIVE_INFINITY` * @function * @returns {number} */ timeRemaining: function () { if (this.paused || this.error) { return 0; } var delta = this.size - this.sizeUploaded(); if (delta && !this.averageSpeed) { return Number.POSITIVE_INFINITY; } if (!delta && !this.averageSpeed) { return 0; } return Math.floor(delta / this.averageSpeed); }, /** * Get file type * @function * @returns {string} */ getType: function () { return this.file.type && this.file.type.split('/')[1]; }, /** * Get file extension * @function * @returns {string} */ getExtension: function () { return this.name.substr((~-this.name.lastIndexOf(".") >>> 0) + 2).toLowerCase(); } }; /** * Default read function using the webAPI * * @function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk) * */ function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk) { var function_name = 'slice'; if (fileObj.file.slice) function_name = 'slice'; else if (fileObj.file.mozSlice) function_name = 'mozSlice'; else if (fileObj.file.webkitSlice) function_name = 'webkitSlice'; chunk.readFinished(fileObj.file[function_name](startByte, endByte, fileType)); } /** * Class for storing a single chunk * @name FlowChunk * @param {Flow} flowObj * @param {FlowFile} fileObj * @param {number} offset * @constructor */ function FlowChunk(flowObj, fileObj, offset) { /** * Reference to parent flow object * @type {Flow} */ this.flowObj = flowObj; /** * Reference to parent FlowFile object * @type {FlowFile} */ this.fileObj = fileObj; /** * File offset * @type {number} */ this.offset = offset; /** * Indicates if chunk existence was checked on the server * @type {boolean} */ this.tested = false; /** * Number of retries performed * @type {number} */ this.retries = 0; /** * Pending retry * @type {boolean} */ this.pendingRetry = false; /** * Preprocess state * @type {number} 0 = unprocessed, 1 = processing, 2 = finished */ this.preprocessState = 0; /** * Read state * @type {number} 0 = not read, 1 = reading, 2 = finished */ this.readState = 0; /** * Bytes transferred from total request size * @type {number} */ this.loaded = 0; /** * Total request size * @type {number} */ this.total = 0; /** * Size of a chunk * @type {number} */ this.chunkSize = this.flowObj.opts.chunkSize; /** * Chunk start byte in a file * @type {number} */ this.startByte = this.offset * this.chunkSize; /** * Compute the endbyte in a file * */ this.computeEndByte = function() { var endByte = Math.min(this.fileObj.size, (this.offset + 1) * this.chunkSize); if (this.fileObj.size - endByte < this.chunkSize && !this.flowObj.opts.forceChunkSize) { // The last chunk will be bigger than the chunk size, // but less than 2 * this.chunkSize endByte = this.fileObj.size; } return endByte; } /** * Chunk end byte in a file * @type {number} */ this.endByte = this.computeEndByte(); /** * XMLHttpRequest * @type {XMLHttpRequest} */ this.xhr = null; var $ = this; /** * Send chunk event * @param event * @param {...} args arguments of a callback */ this.event = function (event, args) { args = Array.prototype.slice.call(arguments); args.unshift($); $.fileObj.chunkEvent.apply($.fileObj, args); }; /** * Catch progress event * @param {ProgressEvent} event */ this.progressHandler = function(event) { if (event.lengthComputable) { $.loaded = event.loaded ; $.total = event.total; } $.event('progress', event); }; /** * Catch test event * @param {Event} event */ this.testHandler = function(event) { var status = $.status(true); if (status === 'error') { $.event(status, $.message()); $.flowObj.uploadNextChunk(); } else if (status === 'success') { $.tested = true; $.event(status, $.message()); $.flowObj.uploadNextChunk(); } else if (!$.fileObj.paused) { // Error might be caused by file pause method // Chunks does not exist on the server side $.tested = true; $.send(); } }; /** * Upload has stopped * @param {Event} event */ this.doneHandler = function(event) { var status = $.status(); if (status === 'success' || status === 'error') { delete this.data; $.event(status, $.message()); $.flowObj.uploadNextChunk(); } else { $.event('retry', $.message()); $.pendingRetry = true; $.abort(); $.retries++; var retryInterval = $.flowObj.opts.chunkRetryInterval; if (retryInterval !== null) { setTimeout(function () { $.send(); }, retryInterval); } else { $.send(); } } }; } FlowChunk.prototype = { /** * Get params for a request * @function */ getParams: function () { return { flowChunkNumber: this.offset + 1, flowChunkSize: this.flowObj.opts.chunkSize, flowCurrentChunkSize: this.endByte - this.startByte, flowTotalSize: this.fileObj.size, flowIdentifier: this.fileObj.uniqueIdentifier, flowFilename: this.fileObj.name, flowRelativePath: this.fileObj.relativePath, flowTotalChunks: this.fileObj.chunks.length }; }, /** * Get target option with query params * @function * @param params * @returns {string} */ getTarget: function(target, params){ if(target.indexOf('?') < 0) { target += '?'; } else { target += '&'; } return target + params.join('&'); }, /** * Makes a GET request without any data to see if the chunk has already * been uploaded in a previous session * @function */ test: function () { // Set up request and listen for event this.xhr = new XMLHttpRequest(); this.xhr.addEventListener("load", this.testHandler, false); this.xhr.addEventListener("error", this.testHandler, false); var testMethod = evalOpts(this.flowObj.opts.testMethod, this.fileObj, this); var data = this.prepareXhrRequest(testMethod, true); this.xhr.send(data); }, /** * Finish preprocess state * @function */ preprocessFinished: function () { // Re-compute the endByte after the preprocess function to allow an // implementer of preprocess to set the fileObj size this.endByte = this.computeEndByte(); this.preprocessState = 2; this.send(); }, /** * Finish read state * @function */ readFinished: function (bytes) { this.readState = 2; this.bytes = bytes; this.send(); }, /** * Uploads the actual data in a POST call * @function */ send: function () { var preprocess = this.flowObj.opts.preprocess; var read = this.flowObj.opts.readFileFn; if (typeof preprocess === 'function') { switch (this.preprocessState) { case 0: this.preprocessState = 1; preprocess(this); return; case 1: return; } } switch (this.readState) { case 0: this.readState = 1; read(this.fileObj, this.startByte, this.endByte, this.fileObj.file.type, this); return; case 1: return; } if (this.flowObj.opts.testChunks && !this.tested) { this.test(); return; } this.loaded = 0; this.total = 0; this.pendingRetry = false; // Set up request and listen for event this.xhr = new XMLHttpRequest(); this.xhr.upload.addEventListener('progress', this.progressHandler, false); this.xhr.addEventListener("load", this.doneHandler, false); this.xhr.addEventListener("error", this.doneHandler, false); var uploadMethod = evalOpts(this.flowObj.opts.uploadMethod, this.fileObj, this); var data = this.prepareXhrRequest(uploadMethod, false, this.flowObj.opts.method, this.bytes); this.xhr.send(data); }, /** * Abort current xhr request * @function */ abort: function () { // Abort and reset var xhr = this.xhr; this.xhr = null; if (xhr) { xhr.abort(); } }, /** * Retrieve current chunk upload status * @function * @returns {string} 'pending', 'uploading', 'success', 'error' */ status: function (isTest) { if (this.readState === 1) { return 'reading'; } else if (this.pendingRetry || this.preprocessState === 1) { // if pending retry then that's effectively the same as actively uploading, // there might just be a slight delay before the retry starts return 'uploading'; } else if (!this.xhr) { return 'pending'; } else if (this.xhr.readyState < 4) { // Status is really 'OPENED', 'HEADERS_RECEIVED' // or 'LOADING' - meaning that stuff is happening return 'uploading'; } else { if (this.flowObj.opts.successStatuses.indexOf(this.xhr.status) > -1) { // HTTP 200, perfect // HTTP 202 Accepted - The request has been accepted for processing, but the processing has not been completed. return 'success'; } else if (this.flowObj.opts.permanentErrors.indexOf(this.xhr.status) > -1 || !isTest && this.retries >= this.flowObj.opts.maxChunkRetries) { // HTTP 413/415/500/501, permanent error return 'error'; } else { // this should never happen, but we'll reset and queue a retry // a likely case for this would be 503 service unavailable this.abort(); return 'pending'; } } }, /** * Get response from xhr request * @function * @returns {String} */ message: function () { return this.xhr ? this.xhr.responseText : ''; }, /** * Get upload progress * @function * @returns {number} */ progress: function () { if (this.pendingRetry) { return 0; } var s = this.status(); if (s === 'success' || s === 'error') { return 1; } else if (s === 'pending') { return 0; } else { return this.total > 0 ? this.loaded / this.total : 0; } }, /** * Count total size uploaded * @function * @returns {number} */ sizeUploaded: function () { var size = this.endByte - this.startByte; // can't return only chunk.loaded value, because it is bigger than chunk size if (this.status() !== 'success') { size = this.progress() * size; } return size; }, /** * Prepare Xhr request. Set query, headers and data * @param {string} method GET or POST * @param {bool} isTest is this a test request * @param {string} [paramsMethod] octet or form * @param {Blob} [blob] to send * @returns {FormData|Blob|Null} data to send */ prepareXhrRequest: function(method, isTest, paramsMethod, blob) { // Add data from the query options var query = evalOpts(this.flowObj.opts.query, this.fileObj, this, isTest); query = extend(query, this.getParams()); var target = evalOpts(this.flowObj.opts.target, this.fileObj, this, isTest); var data = null; if (method === 'GET' || paramsMethod === 'octet') { // Add data from the query options var params = []; each(query, function (v, k) { params.push([encodeURIComponent(k), encodeURIComponent(v)].join('=')); }); target = this.getTarget(target, params); data = blob || null; } else { // Add data from the query options data = new FormData(); each(query, function (v, k) { data.append(k, v); }); data.append(this.flowObj.opts.fileParameterName, blob, this.fileObj.file.name); } this.xhr.open(method, target, true); this.xhr.withCredentials = this.flowObj.opts.withCredentials; // Add data from header options each(evalOpts(this.flowObj.opts.headers, this.fileObj, this, isTest), function (v, k) { this.xhr.setRequestHeader(k, v); }, this); return data; } }; /** * Remove value from array * @param array * @param value */ function arrayRemove(array, value) { var index = array.indexOf(value); if (index > -1) { array.splice(index, 1); } } /** * If option is a function, evaluate it with given params * @param {*} data * @param {...} args arguments of a callback * @returns {*} */ function evalOpts(data, args) { if (typeof data === "function") { // `arguments` is an object, not array, in FF, so: args = Array.prototype.slice.call(arguments); data = data.apply(null, args.slice(1)); } return data; } Flow.evalOpts = evalOpts; /** * Execute function asynchronously * @param fn * @param context */ function async(fn, context) { setTimeout(fn.bind(context), 0); } /** * Extends the destination object `dst` by copying all of the properties from * the `src` object(s) to `dst`. You can specify multiple `src` objects. * @function * @param {Object} dst Destination object. * @param {...Object} src Source object(s). * @returns {Object} Reference to `dst`. */ function extend(dst, src) { each(arguments, function(obj) { if (obj !== dst) { each(obj, function(value, key){ dst[key] = value; }); } }); return dst; } Flow.extend = extend; /** * Iterate each element of an object * @function * @param {Array|Object} obj object or an array to iterate * @param {Function} callback first argument is a value and second is a key. * @param {Object=} context Object to become context (`this`) for the iterator function. */ function each(obj, callback, context) { if (!obj) { return ; } var key; // Is Array? // Array.isArray won't work, not only arrays can be iterated by index https://github.com/flowjs/ng-flow/issues/236# if (typeof(obj.length) !== 'undefined') { for (key = 0; key < obj.length; key++) { if (callback.call(context, obj[key], key) === false) { return ; } } } else { for (key in obj) { if (obj.hasOwnProperty(key) && callback.call(context, obj[key], key) === false) { return ; } } } } Flow.each = each; /** * FlowFile constructor * @type {FlowFile} */ Flow.FlowFile = FlowFile; /** * FlowFile constructor * @type {FlowChunk} */ Flow.FlowChunk = FlowChunk; /** * Library version * @type {string} */ Flow.version = '2.11.2'; if ( typeof module === "object" && module && typeof module.exports === "object" ) { // Expose Flow as module.exports in loaders that implement the Node // module pattern (including browserify). Do not create the global, since // the user will be storing it themselves locally, and globals are frowned // upon in the Node module world. module.exports = Flow; } else { // Otherwise expose Flow to the global object as usual window.Flow = Flow; // Register as a named AMD module, since Flow can be concatenated with other // files that may use define, but not via a proper concatenation script that // understands anonymous AMD modules. A named AMD is safest and most robust // way to register. Lowercase flow is used because AMD module names are // derived from file names, and Flow is normally delivered in a lowercase // file name. Do this after creating the global so that if an AMD module wants // to call noConflict to hide this version of Flow, it will work. if ( typeof define === "function" && define.amd ) { define( "flow", [], function () { return Flow; } ); } } })(window, document); ;/*})'"*/ ;/*})'"*/ (function ($) { Drupal.ocupload = Drupal.ocupload || {}; /** * Create and configure Flow.js object. */ Drupal.ocupload.createFlow = function () { // Create Flow.js instance var flow = new Flow({ target: Drupal.settings.basePath + 'ocupload/upload', testChunks: false, chunkSize: 5*1024*1024, simultaneousUploads: 1 }); if (!flow.support) { return flow; } flow.on('fileAdded', Drupal.ocupload.onFileAdded); flow.on('filesSubmitted', Drupal.ocupload.onFilesSubmitted); flow.on('fileProgress', Drupal.ocupload.onFileProgress); flow.on('fileSuccess', Drupal.ocupload.onFileSuccess); flow.on('error', Drupal.ocupload.onError); flow.on('complete', Drupal.ocupload.onComplete); return flow; }; /** * Return true if response in JSON format. */ Drupal.ocupload.checkResponse = function (response) { return $.trim(response).substring(0, 1) == '{'; }; /** * Return target textarea. */ Drupal.ocupload.findTextarea = function(element) { var $parent = $(element).parent(); var $textarea = $parent.find('textarea:first'); return ($textarea.length == 0) ? Drupal.ocupload.findTextarea($parent) : $textarea; }; /** * File added handler. */ Drupal.ocupload.onFileAdded = function (file, event) { if ($.inArray(file.getExtension(), Drupal.settings.ocupload.allowedExt) == -1) { alert(Drupal.t('You can not upload files of type .@file_ext', {'@file_ext':file.getExtension()})); return false; } }; /** * Files selected handler. */ Drupal.ocupload.onFilesSubmitted = function (files, event) { var flow = this; var $textarea = Drupal.ocupload.findTextarea(event.target); var $queue = $('#upload-queue'); if ($queue.length == 0) { $queue = $('
      ').appendTo('body'); } $.each(files, function (index, file) { $queue.prepend('
      ' + file.name + '
      '); }); flow.opts.query.fieldName = $textarea.attr('name'); flow.opts.query.formId = $textarea.closest('form').find('input[name="form_id"]').val(); }; /** * File upload progress handler. */ Drupal.ocupload.onFileProgress = function (file, chunk) { var $fileQueue = $('#queue-' + file.uniqueIdentifier); $fileQueue.css({ 'background': 'url(' + Drupal.settings.basePath + 'misc/progress.gif) repeat-x 0 center', 'color': 'white' }); }; /** * File uploaded handler. */ Drupal.ocupload.onFileSuccess = function (file, response, chunk) { var $fileQueue = $('#queue-' + file.uniqueIdentifier); $fileQueue.hide('fast', function () { $fileQueue.remove(); }); if (!Drupal.ocupload.checkResponse(response)) { alert(Drupal.t('Server response came not in JSON format: @response', {'@response':response})); } }; /** * Upload error handler. */ Drupal.ocupload.onError = function (message, file, chunk) { alert(Drupal.t('Upload error: @message', {'@message': message})) }; /** * Files uploaded handler. */ Drupal.ocupload.onComplete = function () { var flow = this; flow.cancel(); }; })(jQuery); // Translate string because plugin.js not visible in locale_js_alter() // Drupal.t('Upload file'); // Drupal.t('Your browser not support HTML5 File API'); ;/*})'"*/ ;/*})'"*/ (function ($) { Drupal.behaviors.ocuploadTextarea = { attach: function (context, settings) { if (!Drupal.settings.ocupload || !Drupal.settings.ocupload.allowedExt) { return; } $('textarea.ocupload-drop', context).once('ocupload-drop').each(function () { var textarea = this; // Lazy create and configure Flow.js object if (!Drupal.ocupload.textareaPlugin.flow) { Drupal.ocupload.textareaPlugin.createFlow(); } // Process textarea if (Drupal.ocupload.textareaPlugin.flow.support) { Drupal.ocupload.textareaPlugin.flow.assignDrop(textarea); // Hack for IE. IE loses textarea selection on drag start. if (Drupal.ocupload.textareaPlugin.isIE) { $(textarea).bind('blur', Drupal.ocupload.textareaPlugin.saveSelection); } } }); } }; Drupal.ocupload = Drupal.ocupload || {}; Drupal.ocupload.textareaPlugin = Drupal.ocupload.textareaPlugin || {}; Drupal.ocupload.textareaPlugin.isIE = document.documentMode ? true : false; /** * Create and configure Flow.js object. */ Drupal.ocupload.textareaPlugin.createFlow = function () { Drupal.ocupload.textareaPlugin.flow = Drupal.ocupload.createFlow(); if (!Drupal.ocupload.textareaPlugin.flow.support) { return false; } Drupal.ocupload.textareaPlugin.flow.on('filesSubmitted', Drupal.ocupload.textareaPlugin.onFilesSubmitted); Drupal.ocupload.textareaPlugin.flow.on('fileSuccess', Drupal.ocupload.textareaPlugin.onFileSuccess); Drupal.ocupload.textareaPlugin.flow.on('complete', Drupal.ocupload.textareaPlugin.onComplete); return true; }; /** * Get selected text in textarea. */ Drupal.ocupload.textareaPlugin.getSelectedText = function (element) { if (element instanceof jQuery) { element = element[0]; } return element.value.substring(element.selectionStart, element.selectionEnd); }; /** * Save selection info in element data attribute. */ Drupal.ocupload.textareaPlugin.saveSelection = function (event) { var textarea = this; $(textarea).data('ocuploadSelection', { selectedText: Drupal.ocupload.textareaPlugin.getSelectedText(textarea), selectionStart: textarea.selectionStart, selectionEnd: textarea.selectionEnd, }); }; /** * Files selected handler. */ Drupal.ocupload.textareaPlugin.onFilesSubmitted = function (files, event) { var $textarea = $(event.target).closest('.form-item').find('textarea'); var selectedText = Drupal.ocupload.textareaPlugin.getSelectedText($textarea); // Hack for IE. Restore selection from data if (Drupal.ocupload.textareaPlugin.isIE) { selectedText = $textarea.data('ocuploadSelection').selectedText; } Drupal.ocupload.textareaPlugin.flow.opts.query.selectedText = selectedText; Drupal.ocupload.textareaPlugin.flow.upload(); $textarea[0].disabled = true; // Save textarea id in global var, because event 'complete' not contains this information Drupal.ocupload.textareaPlugin.activeTextareaId = $textarea.attr('id'); }; /** * File uploaded handler. */ Drupal.ocupload.textareaPlugin.onFileSuccess = function (file, response, chunk) { if (!Drupal.ocupload.checkResponse(response)) { return; } response = $.parseJSON(response); if (response.status) { var $textarea = $('#' + Drupal.ocupload.textareaPlugin.activeTextareaId); var textarea = $textarea[0]; var selectionStart = textarea.selectionStart; var selectionEnd = textarea.selectionEnd; var insertedText = response.data; // Hack for IE if (Drupal.ocupload.textareaPlugin.isIE) { var selection = $textarea.data('ocuploadSelection'); selectionStart = selection.selectionStart; selectionEnd = selection.selectionEnd; textarea.disabled = false; textarea.focus(); } if (selectionStart == selectionEnd) { insertedText += "\n"; } textarea.value = textarea.value.substring(0, selectionStart) + insertedText + textarea.value.substring(selectionEnd, textarea.value.length); var cursorPosition = selectionStart + insertedText.length; textarea.selectionStart = cursorPosition; textarea.selectionEnd = cursorPosition; // Hack for IE if (Drupal.ocupload.textareaPlugin.isIE) { textarea.disabled = true; $textarea.data('ocuploadSelection', { selectionStart: cursorPosition, selectionEnd: cursorPosition, }) } } else { alert(response.data); } }; /** * Files uploaded handler. */ Drupal.ocupload.textareaPlugin.onComplete = function () { var $textarea = $('#' + Drupal.ocupload.textareaPlugin.activeTextareaId); $textarea[0].disabled = false; $textarea.focus(); }; })(jQuery); ;/*})'"*/ ;/*})'"*/ (function ($) { /** * Retrieves the summary for the first element. */ $.fn.drupalGetSummary = function () { var callback = this.data('summaryCallback'); return (this[0] && callback) ? $.trim(callback(this[0])) : ''; }; /** * Sets the summary for all matched elements. * * @param callback * Either a function that will be called each time the summary is * retrieved or a string (which is returned each time). */ $.fn.drupalSetSummary = function (callback) { var self = this; // To facilitate things, the callback should always be a function. If it's // not, we wrap it into an anonymous function which just returns the value. if (typeof callback != 'function') { var val = callback; callback = function () { return val; }; } return this .data('summaryCallback', callback) // To prevent duplicate events, the handlers are first removed and then // (re-)added. .unbind('formUpdated.summary') .bind('formUpdated.summary', function () { self.trigger('summaryUpdated'); }) // The actual summaryUpdated handler doesn't fire when the callback is // changed, so we have to do this manually. .trigger('summaryUpdated'); }; /** * Sends a 'formUpdated' event each time a form element is modified. */ Drupal.behaviors.formUpdated = { attach: function (context) { // These events are namespaced so that we can remove them later. var events = 'change.formUpdated click.formUpdated blur.formUpdated keyup.formUpdated'; $(context) // Since context could be an input element itself, it's added back to // the jQuery object and filtered again. .find(':input').andSelf().filter(':input') // To prevent duplicate events, the handlers are first removed and then // (re-)added. .unbind(events).bind(events, function () { $(this).trigger('formUpdated'); }); } }; /** * Prepopulate form fields with information from the visitor cookie. */ Drupal.behaviors.fillUserInfoFromCookie = { attach: function (context, settings) { $('form.user-info-from-cookie').once('user-info-from-cookie', function () { var formContext = this; $.each(['name', 'mail', 'homepage'], function () { var $element = $('[name=' + this + ']', formContext); var cookie = $.cookie('Drupal.visitor.' + this); if ($element.length && cookie) { $element.val(cookie); } }); }); } }; })(jQuery); ;/*})'"*/ ;/*})'"*/ (function ($) { /** * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML). * * Ajax is a method of making a request via JavaScript while viewing an HTML * page. The request returns an array of commands encoded in JSON, which is * then executed to make any changes that are necessary to the page. * * Drupal uses this file to enhance form elements with #ajax['path'] and * #ajax['wrapper'] properties. If set, this file will automatically be included * to provide Ajax capabilities. */ Drupal.ajax = Drupal.ajax || {}; Drupal.settings.urlIsAjaxTrusted = Drupal.settings.urlIsAjaxTrusted || {}; /** * Attaches the Ajax behavior to each Ajax form element. */ Drupal.behaviors.AJAX = { attach: function (context, settings) { // Load all Ajax behaviors specified in the settings. for (var base in settings.ajax) { if (!$('#' + base + '.ajax-processed').length) { var element_settings = settings.ajax[base]; if (typeof element_settings.selector == 'undefined') { element_settings.selector = '#' + base; } $(element_settings.selector).each(function () { element_settings.element = this; Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); }); $('#' + base).addClass('ajax-processed'); } } // Bind Ajax behaviors to all items showing the class. $('.use-ajax:not(.ajax-processed)').addClass('ajax-processed').each(function () { var element_settings = {}; // Clicked links look better with the throbber than the progress bar. element_settings.progress = { 'type': 'throbber' }; // For anchor tags, these will go to the target of the anchor rather // than the usual location. if ($(this).attr('href')) { element_settings.url = $(this).attr('href'); element_settings.event = 'click'; } var base = $(this).attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); }); // This class means to submit the form to the action using Ajax. $('.use-ajax-submit:not(.ajax-processed)').addClass('ajax-processed').each(function () { var element_settings = {}; // Ajax submits specified in this manner automatically submit to the // normal form action. element_settings.url = $(this.form).attr('action'); // Form submit button clicks need to tell the form what was clicked so // it gets passed in the POST request. element_settings.setClick = true; // Form buttons use the 'click' event rather than mousedown. element_settings.event = 'click'; // Clicked form buttons look better with the throbber than the progress bar. element_settings.progress = { 'type': 'throbber' }; var base = $(this).attr('id'); Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); }); } }; /** * Ajax object. * * All Ajax objects on a page are accessible through the global Drupal.ajax * object and are keyed by the submit button's ID. You can access them from * your module's JavaScript file to override properties or functions. * * For example, if your Ajax enabled button has the ID 'edit-submit', you can * redefine the function that is called to insert the new content like this * (inside a Drupal.behaviors attach block): * @code * Drupal.behaviors.myCustomAJAXStuff = { * attach: function (context, settings) { * Drupal.ajax['edit-submit'].commands.insert = function (ajax, response, status) { * new_content = $(response.data); * $('#my-wrapper').append(new_content); * alert('New content was appended to #my-wrapper'); * } * } * }; * @endcode */ Drupal.ajax = function (base, element, element_settings) { var defaults = { url: 'system/ajax', event: 'mousedown', keypress: true, selector: '#' + base, effect: 'none', speed: 'none', method: 'replaceWith', progress: { type: 'throbber', message: Drupal.t('Please wait...') }, submit: { 'js': true } }; $.extend(this, defaults, element_settings); this.element = element; this.element_settings = element_settings; // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let // the server detect when it needs to degrade gracefully. // There are five scenarios to check for: // 1. /nojs/ // 2. /nojs$ - The end of a URL string. // 3. /nojs? - Followed by a query (with clean URLs enabled). // E.g.: path/nojs?destination=foobar // 4. /nojs& - Followed by a query (without clean URLs enabled). // E.g.: ?q=path/nojs&destination=foobar // 5. /nojs# - Followed by a fragment. // E.g.: path/nojs#myfragment this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1'); // If the 'nojs' version of the URL is trusted, also trust the 'ajax' version. if (Drupal.settings.urlIsAjaxTrusted[element_settings.url]) { Drupal.settings.urlIsAjaxTrusted[this.url] = true; } this.wrapper = '#' + element_settings.wrapper; // If there isn't a form, jQuery.ajax() will be used instead, allowing us to // bind Ajax to links as well. if (this.element.form) { this.form = $(this.element.form); } // Set the options for the ajaxSubmit function. // The 'this' variable will not persist inside of the options object. var ajax = this; ajax.options = { url: Drupal.sanitizeAjaxUrl(ajax.url), data: ajax.submit, beforeSerialize: function (element_settings, options) { return ajax.beforeSerialize(element_settings, options); }, beforeSubmit: function (form_values, element_settings, options) { ajax.ajaxing = true; return ajax.beforeSubmit(form_values, element_settings, options); }, beforeSend: function (xmlhttprequest, options) { ajax.ajaxing = true; return ajax.beforeSend(xmlhttprequest, options); }, success: function (response, status, xmlhttprequest) { // Sanity check for browser support (object expected). // When using iFrame uploads, responses must be returned as a string. if (typeof response == 'string') { response = $.parseJSON(response); } // Prior to invoking the response's commands, verify that they can be // trusted by checking for a response header. See // ajax_set_verification_header() for details. // - Empty responses are harmless so can bypass verification. This avoids // an alert message for server-generated no-op responses that skip Ajax // rendering. // - Ajax objects with trusted URLs (e.g., ones defined server-side via // #ajax) can bypass header verification. This is especially useful for // Ajax with multipart forms. Because IFRAME transport is used, the // response headers cannot be accessed for verification. if (response !== null && !Drupal.settings.urlIsAjaxTrusted[ajax.url]) { if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') { var customMessage = Drupal.t("The response failed verification so will not be processed."); return ajax.error(xmlhttprequest, ajax.url, customMessage); } } return ajax.success(response, status); }, complete: function (xmlhttprequest, status) { ajax.ajaxing = false; if (status == 'error' || status == 'parsererror') { return ajax.error(xmlhttprequest, ajax.url); } }, dataType: 'json', jsonp: false, type: 'POST' }; // For multipart forms (e.g., file uploads), jQuery Form targets the form // submission to an iframe instead of using an XHR object. The initial "src" // of the iframe, prior to the form submission, is set to options.iframeSrc. // "about:blank" is the semantically correct, standards-compliant, way to // initialize a blank iframe; however, some old IE versions (possibly only 6) // incorrectly report a mixed content warning when iframes with an // "about:blank" src are added to a parent document with an https:// origin. // jQuery Form works around this by defaulting to "javascript:false" instead, // but that breaks on Chrome 83, so here we force the semantically correct // behavior for all browsers except old IE. // @see https://www.drupal.org/project/drupal/issues/3143016 // @see https://github.com/jquery-form/form/blob/df9cb101b9c9c085c8d75ad980c7ff1cf62063a1/jquery.form.js#L68 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=1084874 // @see https://html.spec.whatwg.org/multipage/browsers.html#creating-browsing-contexts // @see https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy if (navigator.userAgent.indexOf("MSIE") === -1) { ajax.options.iframeSrc = 'about:blank'; } // Bind the ajaxSubmit function to the element event. $(ajax.element).bind(element_settings.event, function (event) { if (!Drupal.settings.urlIsAjaxTrusted[ajax.url] && !Drupal.urlIsLocal(ajax.url)) { throw new Error(Drupal.t('The callback URL is not local and not trusted: !url', {'!url': ajax.url})); } return ajax.eventResponse(this, event); }); // If necessary, enable keyboard submission so that Ajax behaviors // can be triggered through keyboard input as well as e.g. a mousedown // action. if (element_settings.keypress) { $(ajax.element).keypress(function (event) { return ajax.keypressResponse(this, event); }); } // If necessary, prevent the browser default action of an additional event. // For example, prevent the browser default action of a click, even if the // AJAX behavior binds to mousedown. if (element_settings.prevent) { $(ajax.element).bind(element_settings.prevent, false); } }; /** * Handle a key press. * * The Ajax object will, if instructed, bind to a key press response. This * will test to see if the key press is valid to trigger this event and * if it is, trigger it for us and prevent other keypresses from triggering. * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13 * and 32. RETURN is often used to submit a form when in a textfield, and * SPACE is often used to activate an element without submitting. */ Drupal.ajax.prototype.keypressResponse = function (element, event) { // Create a synonym for this to reduce code confusion. var ajax = this; // Detect enter key and space bar and allow the standard response for them, // except for form elements of type 'text' and 'textarea', where the // spacebar activation causes inappropriate activation if #ajax['keypress'] is // TRUE. On a text-type widget a space should always be a space. if (event.which == 13 || (event.which == 32 && element.type != 'text' && element.type != 'textarea')) { $(ajax.element_settings.element).trigger(ajax.element_settings.event); return false; } }; /** * Handle an event that triggers an Ajax response. * * When an event that triggers an Ajax response happens, this method will * perform the actual Ajax call. It is bound to the event using * bind() in the constructor, and it uses the options specified on the * ajax object. */ Drupal.ajax.prototype.eventResponse = function (element, event) { // Create a synonym for this to reduce code confusion. var ajax = this; // Do not perform another ajax command if one is already in progress. if (ajax.ajaxing) { return false; } try { if (ajax.form) { // If setClick is set, we must set this to ensure that the button's // value is passed. if (ajax.setClick) { // Mark the clicked button. 'form.clk' is a special variable for // ajaxSubmit that tells the system which element got clicked to // trigger the submit. Without it there would be no 'op' or // equivalent. element.form.clk = element; } ajax.form.ajaxSubmit(ajax.options); } else { ajax.beforeSerialize(ajax.element, ajax.options); $.ajax(ajax.options); } } catch (e) { // Unset the ajax.ajaxing flag here because it won't be unset during // the complete response. ajax.ajaxing = false; alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message); } // For radio/checkbox, allow the default event. On IE, this means letting // it actually check the box. if (typeof element.type != 'undefined' && (element.type == 'checkbox' || element.type == 'radio')) { return true; } else { return false; } }; /** * Handler for the form serialization. * * Runs before the beforeSend() handler (see below), and unlike that one, runs * before field data is collected. */ Drupal.ajax.prototype.beforeSerialize = function (element, options) { // Allow detaching behaviors to update field values before collecting them. // This is only needed when field values are added to the POST data, so only // when there is a form such that this.form.ajaxSubmit() is used instead of // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize() // isn't called, but don't rely on that: explicitly check this.form. if (this.form) { var settings = this.settings || Drupal.settings; Drupal.detachBehaviors(this.form, settings, 'serialize'); } // Prevent duplicate HTML ids in the returned markup. // @see drupal_html_id() options.data['ajax_html_ids[]'] = []; $('[id]').each(function () { options.data['ajax_html_ids[]'].push(this.id); }); // Allow Drupal to return new JavaScript and CSS files to load without // returning the ones already loaded. // @see ajax_base_page_theme() // @see drupal_get_css() // @see drupal_get_js() options.data['ajax_page_state[theme]'] = Drupal.settings.ajaxPageState.theme; options.data['ajax_page_state[theme_token]'] = Drupal.settings.ajaxPageState.theme_token; for (var key in Drupal.settings.ajaxPageState.css) { options.data['ajax_page_state[css][' + key + ']'] = 1; } for (var key in Drupal.settings.ajaxPageState.js) { options.data['ajax_page_state[js][' + key + ']'] = 1; } }; /** * Modify form values prior to form submission. */ Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) { // This function is left empty to make it simple to override for modules // that wish to add functionality here. }; /** * Prepare the Ajax request before it is sent. */ Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) { // For forms without file inputs, the jQuery Form plugin serializes the form // values, and then calls jQuery's $.ajax() function, which invokes this // handler. In this circumstance, options.extraData is never used. For forms // with file inputs, the jQuery Form plugin uses the browser's normal form // submission mechanism, but captures the response in a hidden IFRAME. In this // circumstance, it calls this handler first, and then appends hidden fields // to the form to submit the values in options.extraData. There is no simple // way to know which submission mechanism will be used, so we add to extraData // regardless, and allow it to be ignored in the former case. if (this.form) { options.extraData = options.extraData || {}; // Let the server know when the IFRAME submission mechanism is used. The // server can use this information to wrap the JSON response in a TEXTAREA, // as per http://jquery.malsup.com/form/#file-upload. options.extraData.ajax_iframe_upload = '1'; // The triggering element is about to be disabled (see below), but if it // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that // value is included in the submission. As per above, submissions that use // $.ajax() are already serialized prior to the element being disabled, so // this is only needed for IFRAME submissions. var v = $.fieldValue(this.element); if (v !== null) { options.extraData[this.element.name] = Drupal.checkPlain(v); } } // Disable the element that received the change to prevent user interface // interaction while the Ajax request is in progress. ajax.ajaxing prevents // the element from triggering a new request, but does not prevent the user // from changing its value. $(this.element).addClass('progress-disabled').attr('disabled', true); // Insert progressbar or throbber. if (this.progress.type == 'bar') { var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, $.noop, this.progress.method, $.noop); if (this.progress.message) { progressBar.setProgress(-1, this.progress.message); } if (this.progress.url) { progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500); } this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar'); this.progress.object = progressBar; $(this.element).after(this.progress.element); } else if (this.progress.type == 'throbber') { this.progress.element = $('
       
      '); if (this.progress.message) { $('.throbber', this.progress.element).after('
      ' + this.progress.message + '
      '); } $(this.element).after(this.progress.element); } }; /** * Handler for the form redirection completion. */ Drupal.ajax.prototype.success = function (response, status) { // Remove the progress element. if (this.progress.element) { $(this.progress.element).remove(); } if (this.progress.object) { this.progress.object.stopMonitoring(); } $(this.element).removeClass('progress-disabled').removeAttr('disabled'); Drupal.freezeHeight(); for (var i in response) { if (response.hasOwnProperty(i) && response[i]['command'] && this.commands[response[i]['command']]) { this.commands[response[i]['command']](this, response[i], status); } } // Reattach behaviors, if they were detached in beforeSerialize(). The // attachBehaviors() called on the new content from processing the response // commands is not sufficient, because behaviors from the entire form need // to be reattached. if (this.form) { var settings = this.settings || Drupal.settings; Drupal.attachBehaviors(this.form, settings); } Drupal.unfreezeHeight(); // Remove any response-specific settings so they don't get used on the next // call by mistake. this.settings = null; }; /** * Build an effect object which tells us how to apply the effect when adding new HTML. */ Drupal.ajax.prototype.getEffect = function (response) { var type = response.effect || this.effect; var speed = response.speed || this.speed; var effect = {}; if (type == 'none') { effect.showEffect = 'show'; effect.hideEffect = 'hide'; effect.showSpeed = ''; } else if (type == 'fade') { effect.showEffect = 'fadeIn'; effect.hideEffect = 'fadeOut'; effect.showSpeed = speed; } else { effect.showEffect = type + 'Toggle'; effect.hideEffect = type + 'Toggle'; effect.showSpeed = speed; } return effect; }; /** * Handler for the form redirection error. */ Drupal.ajax.prototype.error = function (xmlhttprequest, uri, customMessage) { Drupal.displayAjaxError(Drupal.ajaxError(xmlhttprequest, uri, customMessage)); // Remove the progress element. if (this.progress.element) { $(this.progress.element).remove(); } if (this.progress.object) { this.progress.object.stopMonitoring(); } // Undo hide. $(this.wrapper).show(); // Re-enable the element. $(this.element).removeClass('progress-disabled').removeAttr('disabled'); // Reattach behaviors, if they were detached in beforeSerialize(). if (this.form) { var settings = this.settings || Drupal.settings; Drupal.attachBehaviors(this.form, settings); } }; /** * Provide a series of commands that the server can request the client perform. */ Drupal.ajax.prototype.commands = { /** * Command to insert new content into the DOM. */ insert: function (ajax, response, status) { // Get information from the response. If it is not there, default to // our presets. var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper); var method = response.method || ajax.method; var effect = ajax.getEffect(response); // We don't know what response.data contains: it might be a string of text // without HTML, so don't rely on jQuery correctly iterpreting // $(response.data) as new HTML rather than a CSS selector. Also, if // response.data contains top-level text nodes, they get lost with either // $(response.data) or $('
      ').replaceWith(response.data). var new_content_wrapped = $('
      ').html(response.data); var new_content = new_content_wrapped.contents(); // For legacy reasons, the effects processing code assumes that new_content // consists of a single top-level element. Also, it has not been // sufficiently tested whether attachBehaviors() can be successfully called // with a context object that includes top-level text nodes. However, to // give developers full control of the HTML appearing in the page, and to // enable Ajax content to be inserted in places where DIV elements are not // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new // content satisfies the requirement of a single top-level element, and // only use the container DIV created above when it doesn't. For more // information, please see http://drupal.org/node/736066. if (new_content.length != 1 || new_content.get(0).nodeType != 1) { new_content = new_content_wrapped; } // If removing content from the wrapper, detach behaviors first. switch (method) { case 'html': case 'replaceWith': case 'replaceAll': case 'empty': case 'remove': var settings = response.settings || ajax.settings || Drupal.settings; Drupal.detachBehaviors(wrapper, settings); } // Add the new content to the page. wrapper[method](new_content); // Immediately hide the new content if we're using any effects. if (effect.showEffect != 'show') { new_content.hide(); } // Determine which effect to use and what content will receive the // effect, then show the new content. if ($('.ajax-new-content', new_content).length > 0) { $('.ajax-new-content', new_content).hide(); new_content.show(); $('.ajax-new-content', new_content)[effect.showEffect](effect.showSpeed); } else if (effect.showEffect != 'show') { new_content[effect.showEffect](effect.showSpeed); } // Attach all JavaScript behaviors to the new content, if it was successfully // added to the page, this if statement allows #ajax['wrapper'] to be // optional. if (new_content.parents('html').length > 0) { // Apply any settings from the returned JSON if available. var settings = response.settings || ajax.settings || Drupal.settings; Drupal.attachBehaviors(new_content, settings); } }, /** * Command to remove a chunk from the page. */ remove: function (ajax, response, status) { var settings = response.settings || ajax.settings || Drupal.settings; Drupal.detachBehaviors($(response.selector), settings); $(response.selector).remove(); }, /** * Command to mark a chunk changed. */ changed: function (ajax, response, status) { if (!$(response.selector).hasClass('ajax-changed')) { $(response.selector).addClass('ajax-changed'); if (response.asterisk) { $(response.selector).find(response.asterisk).append(' * '); } } }, /** * Command to provide an alert. */ alert: function (ajax, response, status) { alert(response.text, response.title); }, /** * Command to provide the jQuery css() function. */ css: function (ajax, response, status) { $(response.selector).css(response.argument); }, /** * Command to set the settings that will be used for other commands in this response. */ settings: function (ajax, response, status) { if (response.merge) { $.extend(true, Drupal.settings, response.settings); } else { ajax.settings = response.settings; } }, /** * Command to attach data using jQuery's data API. */ data: function (ajax, response, status) { $(response.selector).data(response.name, response.value); }, /** * Command to apply a jQuery method. */ invoke: function (ajax, response, status) { var $element = $(response.selector); $element[response.method].apply($element, response.arguments); }, /** * Command to restripe a table. */ restripe: function (ajax, response, status) { // :even and :odd are reversed because jQuery counts from 0 and // we count from 1, so we're out of sync. // Match immediate children of the parent element to allow nesting. $('> tbody > tr:visible, > tr:visible', $(response.selector)) .removeClass('odd even') .filter(':even').addClass('odd').end() .filter(':odd').addClass('even'); }, /** * Command to add css. * * Uses the proprietary addImport method if available as browsers which * support that method ignore @import statements in dynamically added * stylesheets. */ add_css: function (ajax, response, status) { // Add the styles in the normal way. $('head').prepend(response.data); // Add imports in the styles using the addImport method if available. var match, importMatch = /^@import url\("(.*)"\);$/igm; if (document.styleSheets[0].addImport && importMatch.test(response.data)) { importMatch.lastIndex = 0; while (match = importMatch.exec(response.data)) { document.styleSheets[0].addImport(match[1]); } } }, /** * Command to update a form's build ID. */ updateBuildId: function(ajax, response, status) { $('input[name="form_build_id"][value="' + response['old'] + '"]').val(response['new']); } }; })(jQuery); ;/*})'"*/ ;/*})'"*/ (function (D) { var beforeSerialize = D.ajax.prototype.beforeSerialize; D.ajax.prototype.beforeSerialize = function (element, options) { beforeSerialize.call(this, element, options); options.data['ajax_page_state[jquery_version]'] = D.settings.ajaxPageState.jquery_version; } })(Drupal); ;/*})'"*/ ;/*})'"*/