PageSourceSearch

https://wavetheoryrecords.com/wp-content/themes/recordlabel.3.0.16…/includes/nxs-script.js?v=3.0.160825.0916

js wavetheoryrecords.com collected 2026-09-25 01:45:19 UTC 359,550 bytes, 9,434 lines download raw bytes

1/*************************************************************************/
2/*************************************************************************/
3/*
4    Copyright 2012-2014 Nexus Themes
5*/
6/*************************************************************************/
7/*************************************************************************/
8
9var nxs_js_windowhasfocus = true;
10var nxs_js_mapslazyloaded = false;
11var nxs_js_mapslazyloading = false;
12var nxs_js_maps = { };
13
14var nxs_js_panolazyloaded = false;
15var nxs_js_panolazyloading = false;
16var nxs_js_panos = { };
17
18var nxs_js_requirespagerefresh = false;
19var nxs_js_activeviewport = -1;
20
21var nxs_js_nxseditoractive = false;
22var nxs_js_editorstategrowltoken;
23
24var nxs_js_nxsmenuactive = true;
25var nxs_js_menustategrowltoken;
26
27var nxs_js_nxsisdragging = false;
28
29var nxs_js_runtimedimensionsrefreshtriggers = new Array();
30var nxs_js_queuedruntimedimensionsrefreshtriggers = new Array();
31var nxs_js_isruntimecssrefreshqueued = false;
32var nxs_js_isctrlkeydown = false;
33var nxs_js_seorefreshtriggers = { };
34var nxs_js_isseorefreshqueued = false;
35var nxs_js_vendorprefix_internal = null;
36
37var nxs_js_lazyloadedscripts = { };
38var nxs_js_lazyloadingscripts = { };
39var nxsboxL10n = {  };
40
41// scroll revert state (used to track pushing and popping of scroll positions)
42var nxs_js_scrollstatestack = { };
43var nxs_js_scrollstateidentifier = 0;
44
45var nxs_js_lazyloadinggrowl = false;
46var nxs_js_queuestatelookup = {};
47
48function nxs_js_replaceall(find, replace, str) 
49{
50  return str.replace(new RegExp(find, 'g'), replace);
51}
52
53// fix for jQuery 1.9
54jQuery.browser = {};
55jQuery.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
56jQuery.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
57jQuery.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
58jQuery.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
59
60// see http://api.jquery.com/jQuery.browser/
61function nxs_js_getvendorprefix()
62{
63	if (nxs_js_vendorprefix_internal == null)
64	{
65		// derive it 1x
66		var browser = jQuery.browser;
67		
68		//nxs_js_log(navigator.userAgent);
69		
70		if (navigator.userAgent.indexOf("Opera") >= 0 || navigator.userAgent.indexOf("OPR") >= 0)
71		{
72			nxs_js_vendorprefix_internal = "o";
73		}
74		else if (browser.webkit == true)
75		{
76			nxs_js_vendorprefix_internal = "webkit";
77		}
78		else if (browser.msie)
79		{
80			nxs_js_vendorprefix_internal = "msie";
81		}
82		else if (navigator.userAgent.indexOf("Trident") > -1)
83    {
84    	// http://stackoverflow.com/questions/20911175/ie-11-browser-recognizes-itself-as-mozilla
85      nxs_js_vendorprefix_internal = "msie";
86    }
87		else if (browser.mozilla)
88		{
89			nxs_js_vendorprefix_internal = "mozilla";
90		}
91		else
92		{
93			nxs_js_vendorprefix_internal = "unknown";
94		}
95	}
96	return nxs_js_vendorprefix_internal;
97}
98
99// the popupsessiondata is empty initially.
100// by filling this variable from the client (js),
101// a state is constructed that is accessible by both the client (js) as well as 
102// serverside (php). Values stored by the client are accessible in the upcoming
103// server post. By using the same keys as the variable names on the serverside,
104// its possible to create a temporary client side state, temporarily overriding
105// values persisted on the server side.
106// This state can be shared between multiple popup pages ("sheets").
107// This enables clients to even have a "cancel" button, wiping just only this
108// temporarily state, and not overriding persisted values if that was unwanted.
109var nxs_js_popupsessiondata = {};	// key values like dictionary
110
111// the shortscopedata is similar to popupsessiondata, difference is that the shortscopedata is wiped
112// so data in here is only available in the next server invocation and lost aftwards. This 
113// can be used to store triggers/events such a specific event, that should not be persisted,
114// but only result in a certain server side invocation
115var nxs_js_shortscopedata = {};	// key values like dictionary
116
117// similar to popupsessiondata, difference is that this container contains information about
118// the meta data, like what sheet is being rendered and other contextual data.
119var nxs_js_popupsessioncontext = {};	// key values like dictionary
120var nxs_js_popupshows = false;
121
122var nxs_js_menuid_preventendlessloop;
123var nxs_js_menuid_siblingcounters;
124
125var nxs_js_alert_identifier = 0;
126
127jQ_nxs(window).ready
128(
129	function()
130	{
131		nxsboxL10n = { loadingAnimation: nxs_js_getframeworkurl() + "/images/loadingnxsbox.png" };
132		
133		nxs_js_tagviewports();
134		nxs_js_tagdevices();
135		nxs_js_tagbrowsers();
136		nxs_js_tagfrontendbackend();
137		nxs_js_tagresponsiveness();
138		// some images load slower than the jquery code is executed.
139		// in that case the screen needs to be realigned
140		nxs_js_reenable_all_window_events();
141		//
142		nxs_js_processquerystring();
143		
144		// reload editor state, based on cookie
145		nxs_js_initiateeditorstate();
146		
147		// reload menu state, based on cookie
148		nxs_js_initiatemenustate();
149		
150		// no background scrolling when hovering over admin top menu
151		nxs_js_disabledocumentscrollwhenhoveringoverelement("#vg_manualcss");
152		
153		nxs_js_reenable_all_window_events();
154		nxs_js_register_windowresizedend_event();
155		nxs_js_hook_windowsresizeend_event();
156		
157		nxs_js_setupwindowscrolllistener();
158		nxs_js_hook_windowsscrolled_event();
159		nxs_js_setupviewportlistener();
160
161		
162		// after fonts are loaded, re-enable window events/ height-iq
163		jQ_nxs(window).bind("load", function() 
164		{
165			nxs_js_reenable_all_window_events();
166			
167			jQ_nxs(window).blur(function(){
168			  nxs_js_windowhasfocus = false;
169			  //nxs_js_log("no focus");
170
171	  		jQ_nxs("html").removeClass("nxs-window-focus");			  
172 			  jQ_nxs("html").addClass("nxs-window-blur");
173			});
174			jQ_nxs(window).focus(function()
175			{			
176			  nxs_js_windowhasfocus = true;
177			  //nxs_js_log("has focus");
178			  
179 			  jQ_nxs("html").removeClass("nxs-window-blur");
180	  		jQ_nxs("html").addClass("nxs-window-focus");			  
181
182			});
183		});
184
185		// see http://stackoverflow.com/questions/6677181/how-to-know-when-font-face-has-been-applied
186		document.onreadystatechange = function() {
187    if (document.readyState === 'complete') 
188    {
189    	nxs_js_reenable_all_window_events();
190    }
191};
192
193	}
194);
195
196function nxs_js_setupwindowscrolllistener()
197{
198	jQ_nxs(window).scroll
199	(
200		function() 		
201		{
202			if (this.scrollTO) clearTimeout(this.scrollTO);
203		  	this.scrollTO = setTimeout
204		  	(
205		  		function() 
206		  		{
207		  			jQ_nxs(this).trigger('nxs_event_windowscrolled');
208		  		}
209		  		, 
210		  		100
211		  	);
212
213		  	nxs_js_invokethrottled("scrolling", 100, function(){
214		  		jQ_nxs(document).trigger('nxs_event_windowscrolling');
215		  	});
216		}
217	);
218}
219
220function nxs_js_getscrollspeed(location) {
221	var scrollTop = jQ_nxs(window).scrollTop();
222	var dif = Math.abs(scrollTop - location);
223	var speed = 300 + Math.round(dif / 5);
224	return speed;
225}
226
227// FX --- BEGIN
228
229function nxs_js_getwindowheight() 
230{
231  var myWidth = 0, myHeight = 0;
232  if( typeof( window.innerWidth ) == 'number' ) {
233      //Non-IE
234      myHeight = window.innerHeight;
235  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
236      //IE 6+ in 'standards compliant mode'
237      myHeight = document.documentElement.clientHeight;
238  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
239      //IE 4 compatible
240      myHeight = document.body.clientHeight;
241	}
242
243	return myHeight
244}
245
246function nxs_js_appearbox(element, element_top, bottom_of_window) 
247{
248  /* If the object is completely visible in the window, fade it it */
249  var requirespercentage = 50;
250  var buffer = element.outerHeight() * requirespercentage / 100;
251  if( bottom_of_window > element_top + buffer) 
252  {
253  	var delay = 0;	// 0 is good for multitasking, alternative; element.data('delay')
254    setTimeout
255    (
256      function()
257      {
258        element.removeClass('nxs-fx-untriggered'); // .animate({'opacity':'1'}, element.data('speed'))
259      }, 
260      delay
261    );            
262  }
263}
264
265function nxs_js_appearboxwhenvisible(dom)
266{
267	var element_offset = dom.offset();
268  var element_top = element_offset.top;
269  
270  bottom_of_window = $(window).scrollTop() + nxs_js_getwindowheight();
271  
272  nxs_js_appearbox(dom, element_top, bottom_of_window);
273}
274
275// FX END
276
277// kudos to http://stackoverflow.com/questions/16323770/stop-page-from-scrolling-if-hovering-div
278function nxs_js_disabledocumentscrollwhenhoveringoverelement(e)
279{
280	jQ_nxs(e).on('DOMMouseScroll mousewheel', function(ev) {
281    var $this = $(this),
282        scrollTop = this.scrollTop,
283        scrollHeight = this.scrollHeight,
284        height = $this.height(),
285        delta = (ev.type == 'DOMMouseScroll' ?
286            ev.originalEvent.detail * -40 :
287            ev.originalEvent.wheelDelta),
288        up = delta > 0;
289
290    var prevent = function() {
291    	nxs_js_log("no propagation (7)");
292        ev.stopPropagation();
293        ev.preventDefault();
294        ev.returnValue = false;
295        return false;
296    }
297
298    if (!up && -delta > scrollHeight - height - scrollTop) {
299        // Scrolling down, but this will take us past the bottom.
300        $this.scrollTop(scrollHeight);
301        return prevent();
302    } else if (up && delta > scrollTop) {
303        // Scrolling up, but this will take us past the top.
304        $this.scrollTop(0);
305        return prevent();
306    }
307});
308}
309
310function nxs_js_menu_mini_expand(obj, placeholderid) 
311{
312	nxs_js_log("mini expand triggered");
313	nxs_js_log(obj);
314	nxs_js_log(placeholderid);
315	
316	//var expander = jQ_nxs(obj).siblings(".nxs-menu-mini-nav-expander-" + placeholderid);
317	var expander = jQ_nxs(".nxs-menu-mini-nav-expander-" + placeholderid);
318	nxs_js_log("expander:");
319	nxs_js_log(expander);
320	
321	var extendMenuHeight = nxs_js_calc_menu_mini_height(expander, obj);
322
323	jQ_nxs(expander).toggleClass("nxs-expand");
324
325	if (extendMenuHeight) {
326		jQ_nxs(expander).height(extendMenuHeight);
327	} else {
328		jQ_nxs(expander).height('');
329	}
330}
331
332function nxs_js_change_menu_mini_expand_height(obj, placeholderid) 
333{
334	var expander = jQ_nxs(obj).siblings(".nxs-menu-mini-nav-expander-" + placeholderid);
335	var extendMenuHeight = nxs_js_calc_menu_mini_height(expander, obj);
336
337	console.log(expander);
338
339	if (extendMenuHeight) {
340		jQ_nxs(expander).height(extendMenuHeight);
341	} else {
342		jQ_nxs(expander).height('');
343	}
344}
345 
346function nxs_js_calc_menu_mini_height(expander, obj) {
347	var extendMenuHeight = 0;
348
349	// set height on expander if the container is fixed and the menu does not fit in the screen
350	if (jQ_nxs('#nxs-fixed-header').length > 0) {
351		if (jQ_nxs(expander).closest('#nxs-fixed-header').length > 0) {
352			var top = jQ_nxs(obj).offset().top;
353			var bottom = top + jQ_nxs(obj).outerHeight();
354			var scrollTop = jQ_nxs(window).scrollTop();
355			var extendMenuHeight = jQ_nxs(window).height() - bottom + scrollTop;
356		}
357	}
358
359	return extendMenuHeight;
360}
361
362// kudos to http://stackoverflow.com/questions/3885817/how-to-check-if-a-number-is-float-or-integer
363function nxs_js_isint(n)
364{
365   return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
366}
367
368// kudos to http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
369function nxs_js_iselementinviewport(el) 
370{
371  var rect = el.getBoundingClientRect();
372  
373  nxs_js_log(rect);
374
375  return 
376  (
377      rect.top >= 0 &&
378      rect.left >= 0 &&
379      rect.bottom <= (window.innerHeight || document. documentElement.clientHeight) && /*or jQ_nxs(window).height() */
380      rect.right <= (window.innerWidth || document. documentElement.clientWidth) /*or jQ_nxs(window).width() */
381  );
382}
383
384// kudos to http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
385function nxs_js_iselementaboveviewport(el) 
386{
387  var rect = el.getBoundingClientRect();  
388	var result = rect.top <= 0;
389  return result;
390}
391
392// kudos to http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
393function nxs_js_iselementabovepieceofviewport(el, piece) 
394{
395	var viewportheight = jQ_nxs(window).height();
396	var halfviewportheight = viewportheight / piece;
397  var rect = el.getBoundingClientRect();  
398	var result = rect.top <= halfviewportheight;
399  return result;
400}
401
402function nxs_js_ui_pushscrollrevert()
403{
404	nxs_js_scrollstateidentifier++;
405	var value = { 'scrolltop' : jQ_nxs(window).scrollTop(), 'height' : jQ_nxs(window).height() };
406	/*
407	nxs_js_log('orig scroll pos:');
408	nxs_js_log(value.scrolltop);
409	nxs_js_log('orig height:');
410	nxs_js_log(value.height);
411	*/
412	nxs_js_scrollstatestack[nxs_js_scrollstateidentifier] = value;
413	return nxs_js_scrollstateidentifier;
414}
415
416function nxs_js_ui_popscrollrevert(scrollstateidentifier)
417{
418	var orig = nxs_js_scrollstatestack[nxs_js_scrollstateidentifier];
419	jQ_nxs(window).scrollTop(orig.scrolltop);	
420}
421
422function nxs_js_stringisblank(str) 
423{
424	// kudos to http://stackoverflow.com/questions/154059/how-do-you-check-for-an-empty-string-in-javascript
425  return (!str || /^\s*$/.test(str));
426}
427
428function nxs_js_stringcontains(haystack, needle)
429{
430	return haystack.indexOf(needle) > -1;
431}
432
433function nxs_js_processquerystring()
434{
435	var nxs_onpageload = nxs_js_getqueryparametervalue("nxs_onpageload")
436	if (nxs_onpageload != '')
437	{
438		var nxs_onpageload_splitted = nxs_onpageload.split("_");
439		var action = nxs_onpageload_splitted[0];
440		if (action == 'editwidget')
441		{
442			if (nxs_js_nxseditoractive)
443			{
444				var postid = nxs_onpageload_splitted[1];
445				var placeholderid = nxs_onpageload_splitted[2];
446				var domelementinwidget = jQ_nxs('.nxs-post-' + postid + ' #nxs-widget-' + placeholderid);
447				nxs_js_edit_widget(domelementinwidget);
448			}
449			else
450			{
451				// skip
452			}
453		}
454		else
455		{
456			nxs_js_log('unsupported action;' + action);
457		}
458	}
459	else
460	{
461		// no onpageload
462		//nxs_js_log('no onpageload')
463	}
464}
465
466function nxs_js_escaped_getqueryparametervalues()
467{
468	return nxs_js_getescapeddictionary(nxs_js_getqueryparametervalues());
469}
470
471// kudos to http://stackoverflow.com/questions/6539761/window-location-search-query-as-json
472function nxs_js_getqueryparametervalues()
473{
474  var pairs = window.location.search.substring(1).split("&"),
475    obj = {},
476    pair,
477    i;
478
479  for ( i in pairs ) 
480  {
481  	if (!pairs.hasOwnProperty(i)) 
482		{
483			continue;
484		}
485  	
486    if ( pairs[i] === "" ) continue;
487
488    pair = pairs[i].split("=");
489    obj[ decodeURIComponent( pair[0] ) ] = decodeURIComponent( pair[1] );
490  }
491
492	// nxs_js_log(obj);
493
494  return obj;
495}
496
497// kudos to http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values
498function nxs_js_getqueryparametervalue(name)
499{
500  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
501  var regexS = "[\\?&]" + name + "=([^&#]*)";
502  var regex = new RegExp(regexS);
503  var results = regex.exec(window.location.search);
504  if(results == null)
505    return "";
506  else
507    return decodeURIComponent(results[1].replace(/\+/g, " "));
508}
509
510function nxs_js_hook_windowsscrolled_event()
511{
512	jQ_nxs(window).bind
513	(
514		'nxs_event_windowscrolled', 
515		function() 
516		{
517			// nxs_js_log('receiving nxs_event_windowscrolled event');
518			
519			// todo: make treshhold configurable by theme/plugin
520			
521			var windowscrolltop = jQ_nxs(window).scrollTop();
522			var windowheight = jQ_nxs(window).height();
523			var documentheight = jQ_nxs(document).height();
524			treshhold = windowheight * 0.5;	// 50% scherm hoogte
525			
526			if(windowscrolltop + windowheight + treshhold >= documentheight) 
527			{
528		   		jQ_nxs(this).trigger('nxs_event_windowscrolledbottom');
529			}
530		}
531	);
532}
533
534function nxs_js_hook_windowsresizeend_event()
535{
536	// nxs_js_log('hooked to nxs_event_resizeend');
537	
538	jQ_nxs(document).bind
539	(
540		'nxs_event_resizeend', 
541		function() 
542		{
543			// nxs_js_log('receiving nxs_event_resizeend event');
544			
545			nxs_js_tagviewports();
546	    nxs_gui_set_runtime_dimensions_enqueuerequest('nxs-framework-windowresized');
547			nxs_js_reset_popup_dimensions();
548		}
549	);
550}
551
552// kudos to http://stackoverflow.com/questions/2996431/detect-when-a-window-is-resized-using-javascript and
553// plus IE8 fix; IE8 fires windowsresized if any element is resized
554// http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer
555function nxs_js_register_windowresizedend_event()
556{
557	//variables to confirm window height and width
558  var lastWindowHeight = jQ_nxs(window).height();
559  var lastWindowWidth = jQ_nxs(window).width();
560
561  jQ_nxs(window).resize(function() 
562  {
563    //confirm window was actually resized
564    if(jQ_nxs(window).height()!=lastWindowHeight || jQ_nxs(window).width()!=lastWindowWidth)
565    {
566      //set this windows size
567      lastWindowHeight = jQ_nxs(window).height();
568      lastWindowWidth = jQ_nxs(window).width();
569
570      // nxs_js_log('jquery resize event detected');
571		
572		  if(this.resizeTO) clearTimeout(this.resizeTO);
573		  this.resizeTO = setTimeout
574		  (
575		  	function() 
576		  	{
577		  		nxs_js_log('broadcasting nxs_event_resizeend');
578		  		jQ_nxs(document).trigger('nxs_event_resizeend');
579		  	}
580		  	, 
581		  	250
582		  );
583    }
584  });
585}
586
587// function that exposes outerhtml property
588jQuery.fn.outerHTML = function(s) 
589{
590	return s
591    ? this.before(s).remove()
592    : jQ_nxs("<p>").append(this.eq(0).clone()).html();
593};
594
595// the 'startsWith' function is added to string objects
596if (typeof String.prototype.startsWith != 'function') 
597{
598	String.prototype.startsWith = function (str)
599	{
600  	return this.indexOf(str) == 0;
601	};
602}
603
604// kudos to http://stackoverflow.com/questions/5999998/how-can-i-check-if-a-javascript-variable-is-function-type
605function nxs_js_isfunction(functionToCheck) {
606 var getType = {};
607 return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
608}
609
610function nxs_js_lazyexecute(scripturl, prependframeworkurl, functiontoinvoke)
611{
612	// ensure functiontoinvoke contains a "(" (parenthesis)
613	// otherwise the invocation will fail without the developer
614	// having a clue about what's wrong
615	if (nxs_js_isfunction(functiontoinvoke))
616	{
617	}
618	else if (!nxs_js_stringcontains(functiontoinvoke, "(") || !nxs_js_stringcontains(functiontoinvoke, ")"))
619	{
620		nxs_js_alert("parenthesis not found, use foo(), not foo");
621	}
622	
623	//nxs_js_log("lazy executing:");
624	
625	if (prependframeworkurl)
626	{
627		scripturl = nxs_js_getframeworkurl() + scripturl;
628	}
629	
630	//nxs_js_log(scripturl);
631	//nxs_js_log(functiontoinvoke);
632	
633	nxs_js_requirescript
634	(
635		scripturl,	// id == scripturl 
636		"js", 	// must be js
637		scripturl, // url
638		function() 
639		{
640			if (nxs_js_isfunction(functiontoinvoke))
641			{
642				functiontoinvoke();
643			}
644			else
645			{
646				eval(functiontoinvoke); 
647			}
648		}
649	);
650}
651
652// ensure the specified css or js script is injected
653function nxs_js_requirescript(scriptid, scripttype, scripturl, scriptcallbackafterload)
654{
655	if (scriptcallbackafterload == false)
656	{
657		// do nothing
658	}
659
660	if (scriptcallbackafterload == null)
661	{
662		nxs_js_alert("warning; loading scriptid; " + scriptid + "; no scriptcallbackafterload set?");
663	}
664
665	if (!nxs_js_isscriptlazyloaded(scriptid) && !nxs_js_isscriptlazyloading(scriptid))
666	{
667		var waitgrowltoken = -1; // nxs_js_alert_wait_start(nxs_js_gettrans("Loading script"));
668	
669		// nxs_js_log('processing script:' + scriptid);
670	
671		// markeer dat we deze nu aan het inladen zijn...
672		nxs_js_lazyloadingscripts[scriptid] = true;
673		var w = window;
674		
675		var d = w.document;
676		var script;
677		
678		if (scripttype == "js")
679		{
680			script = d.createElement('script');
681			script.setAttribute("type","text/javascript")
682  		script.setAttribute('src', scripturl);
683		}
684		else if (scripttype == "css")
685		{
686			script = d.createElement('link');
687		 	script.setAttribute("rel", "stylesheet")
688  		script.setAttribute("type", "text/css")
689  		script.setAttribute("href", scripturl);
690		}
691		
692		// set callback for errors, note this is not compatible with
693		// all browsers; see http://www.quirksmode.org/dom/events/error.html
694		script.onerror = function() 
695		{
696			nxs_js_alert_wait_finish(waitgrowltoken);
697			nxs_js_alert('Error loading resource (script/css); '+ scripturl); 
698		}
699		
700		// set callback function to execute when script is succesfully loaded
701		// regular browsers
702		script.onload = function()
703		{
704			nxs_js_alert_wait_finish(waitgrowltoken);
705			nxs_js_lazyloadedscripts[scriptid] = true;
706			nxs_js_lazyloadingscripts[scriptid] = false;
707			if (scriptcallbackafterload != null)
708			{
709				if (scriptcallbackafterload != false)
710				{
711					// nxs_js_log('executing... non-ie (fresh)');
712					scriptcallbackafterload();
713				}
714			}
715			else
716			{
717				// nxs_js_log('executing... nothing to execute');
718			}
719		}
720		// for ie browsers
721		script.onreadystatechange = function() 
722		{
723			// nxs_js_log('finished loading (IE)');
724		
725			if (this.readyState == 'complete' || this.readyState == 'loaded') 
726			{
727				nxs_js_alert_wait_finish(waitgrowltoken);
728				nxs_js_lazyloadedscripts[scriptid] = true;
729				nxs_js_lazyloadingscripts[scriptid] = false;
730				if (scriptcallbackafterload != null)
731				{
732					if (scriptcallbackafterload != false)
733					{
734						scriptcallbackafterload();
735					}
736				}
737			}	
738		}
739		
740		//document.head.appendChild(script);
741		document.getElementsByTagName("head")[0].appendChild(script);
742		//d.documentElement.firstChild.appendChild(script);
743		//nxs_js_log('script done');
744	}
745	else
746	{
747		// nxs_js_log('skipping (either already queued or already loaded)');
748		if (scriptcallbackafterload != null)
749		{
750			if (scriptcallbackafterload != false)
751			{
752				scriptcallbackafterload();
753			}
754		}
755	}
756}
757
758// checks if the specified script has finished loading
759function nxs_js_isscriptlazyloaded(scriptid)
760{
761	for (var currentscriptid in nxs_js_lazyloadedscripts)
762	{
763		if (currentscriptid == scriptid)
764		{
765			return true;
766		}
767	}	
768	return false;
769}
770
771// check if the specifiekd script is currently loading
772function nxs_js_isscriptlazyloading(scriptid)
773{
774	for (var currentscriptid in nxs_js_lazyloadingscripts)
775	{
776		if (currentscriptid == scriptid)
777		{
778			return true;
779		}
780	}	
781	return false;
782}
783
784function nxs_js_log(s)
785{
786	if ('console' in self && 'log' in console) 
787	{
788		console.log(s);
789		var stacktrace = nxs_js_getqueryparametervalue("stacktrace");
790		if (nxs_js_isctrlkeydown || stacktrace != "")
791		{
792			// practical debug tool; if ctrl is pressed, output the stacktrac
793			try { throw new Error("Stracktrace"); } catch (e) { console.log(e.stack); }
794		}
795	}
796}
797
798function nxs_js_getstacktrace()
799{
800	var result;
801	try { throw new Error("Stracktrace"); } catch (e) { result = e.stack; }
802	return result;
803}
804
805function nxs_js_isemptyorwhitespace(value)
806{
807	return /^\s*$/.test(value);
808}
809
810function nxs_js_doeskeycodemakedirty(e)
811{
812	var result = true;
813	
814	if (e.keyCode == 9)
815	{
816		// tab will not make dirty
817		result = false;
818	}
819	else if (e.keyCode >= 16 && e.keyCode <= 18)
820	{
821		// shift will not make dirty
822		// control will not make dirty
823		// alt will not make dirty
824		result = false;
825	}
826	else if (e.keyCode == 20)
827	{
828		// capslock
829		result = false;
830	}
831	else if (e.keyCode == 27)
832	{
833		//nxs_js_log('detected esc');
834	
835		// this closes the popup; do not mark it as dirty in this case
836		result = false;
837	}
838	else if (e.keyCode >= 33 && e.keyCode <= 45)
839	{
840		// page up will not make dirty
841		// page down, end, home, arrow left, up, right, down, printscreen, insert will not make dirty
842		result = false;
843	}
844	else if (e.keyCode >= 112 && e.keyCode <= 123)
845	{
846		// f1 t/m f12 will not make dirty
847		result = false;
848	}
849	
850	return result;
851}
852
853
854// -------------------------------------------------------------------------------------------
855	
856function nxs_js_getcurrentbrowserurl()
857{
858	return window.location.href;
859}
860	
861// return the url after setting/updating the parameter (other occurences of the same parameter are removed)
862function nxs_js_addqueryparametertourl(url, parameter, value)
863{
864	var result = url;
865	if (nxs_js_stringcontains(url, "?"))
866	{
867		result = result + "&";
868	}
869	else
870	{
871		result = result + "?";
872	}
873	result = result + parameter + "=" + value;
874	return result;
875}
876
877// refreshes the current page
878function nxs_js_refreshcurrentpage()
879{
880	location.reload(true);
881}
882
883function nxs_js_redirecttopostid(postid)
884{
885	nxs_js_geturl("postid", postid, "notused", 
886	function(response) 
887	{
888		var url = response.url;
889		nxs_js_log(url);
890		nxs_js_redirect(url);
891	},
892	function(response) 
893	{
894		nxs_js_alert(nxs_js_gettrans('Unable to retrieve the URL'));
895	}
896	);
897}
898
899function nxs_js_redirect(url)
900{
901	window.location = url;
902}
903
904function nxs_js_redirect_top(url)
905{
906	top.location = url;
907}
908
909		// execute the function, in such a way that only one invocation will occur during the period specified for the specified groupname
910		function nxs_js_invokethrottled(throttlegroupname, nxs_max_frequency_in_msecs, functiontoinvokethrottled)
911		{
912			if (!(throttlegroupname in nxs_js_queuestatelookup))
913			{
914				// nxs_js_log("first time throttle for group " + throttlegroupname);
915				// doesn't yet exist
916				nxs_js_queuestatelookup[throttlegroupname] = false;
917			}
918			var isqueued = nxs_js_queuestatelookup[throttlegroupname];
919			if (isqueued)
920			{
921				// nxs_js_log("speeding up performance for group " + throttlegroupname);
922				// its queued so will be processed soon...
923				return;
924			}
925			
926			// nxs_js_log("enqueued function to invoke for group " + throttlegroupname);
927						
928			// enqueue it!
929			nxs_js_queuestatelookup[throttlegroupname] = true;
930			
931			// optionally perform an immediate redraw to get a snappier user experience
932			setTimeout
933			(
934				function() 
935				{
936					// nxs_js_log("actual invoke request for group " + throttlegroupname);
937				
938					// first we dequeue! 
939					nxs_js_queuestatelookup[throttlegroupname] = false;
940					// invoke function!
941					functiontoinvokethrottled();
942				},
943				nxs_max_frequency_in_msecs
944			);
945		}		
946	
947		function nxs_js_reset_popup_dimensions()
948		{
949			//jQ_nxs('#nxsbox_ajaxContent').css('opacity', '0');
950
951			nxs_js_invokethrottled("reset_popup_dimensions_actualrequest", 50, nxs_js_reset_popup_dimensions_actualrequest);
952			nxs_js_invokethrottled("showpopup", 195, nxs_js_showpopup);
953		}
954	
955		function nxs_js_showpopup()
956		{
957			// display!
958			jQ_nxs('#nxsbox_window .nxs-table').css("opacity", 1);
959		}
960	
961		//
962		// reset de dimensies van de nxsbox op basis van de hoogte van het scherm
963		//
964		function nxs_js_reset_popup_dimensions_actualrequest()
965		{
966			// turn off footer fillter initially before making any calculations
967			jQ_nxs(".nxs-canvas-footerfiller").css("height", 0);
968			
969			if (nxs_js_popup_getsessiondata("popup_current_dimensions") == "gallerybox")
970			{
971			}
972			else
973			{
974				if(typeof nxs_js_popup_get_minwidth == 'function')
975				{
976					//
977					var minwidth = nxs_js_popup_get_minwidth();	// can be overriden
978					jQ_nxs(".nxs-popup-content-canvas-cropper").css('min-width', '' + minwidth + 'px');
979				}
980				else
981				{
982					// default
983				}
984				
985				
986				if(typeof nxs_js_popup_get_maxwidth == 'function')
987				{
988					//
989					var maxwidth = nxs_js_popup_get_maxwidth();	// can be overriden
990					jQ_nxs(".nxs-popup-content-canvas-cropper").css('max-width', '' + maxwidth + 'px');
991				}
992				else
993				{
994					// default
995				}
996				
997				
998				if(typeof nxs_js_popup_get_maxheight == 'function')
999				{
1000					var maxheight = nxs_js_popup_get_maxheight();	// can be overriden
1001					//nxs_js_log("max height is " + maxheight);
1002					jQ_nxs(".nxs-popup-content-canvas-cropper").css('height', '' + maxheight + 'px');
1003				}
1004				else
1005				{
1006					// default
1007				}
1008			}
1009			
1010			var applynewpopuplayoutposition = true;
1011		
1012			// maximize the nxsbox_window to consume 100% width and 100% height
1013			jQ_nxs('#nxsbox_window').css('width', '100%');
1014			jQ_nxs('#nxsbox_window').css('height', jQ_nxs(window).height() + "px");	// height of the window
1015			jQ_nxs('#nxsbox_window').css('margin-top', '0px');
1016			jQ_nxs('#nxsbox_window').css('margin-left', '0px');
1017			jQ_nxs('#nxsbox_window').css('top', '0px');
1018			jQ_nxs('#nxsbox_window').css('left', '0px');
1019			
1020			// 
1021			//jQ_nxs('#nxsbox_ajaxContent').css('width', 'auto');
1022
1023			jQ_nxs("#nxsbox_ajaxContent").width(jQ_nxs(window).width());
1024			var h = jQ_nxs(window).height();
1025			var hcontent = jQ_nxs(".nxs-popup-dyncontentcontainer").height();
1026			var htop = (h - hcontent) / 2;
1027			if (htop < 0) { htop = 0; }
1028			
1029			var w = jQ_nxs(window).width();
1030			var wcontent = jQ_nxs(".nxs-popup-content-canvas-cropper").width();
1031			var wleft = (w - wcontent) / 2;
1032			if (wleft < 0) { wleft = 0; }
1033			
1034			jQ_nxs('#nxsbox_ajaxContent').css('position', 'absolute');
1035			jQ_nxs('#nxsbox_ajaxContent').css('margin-top', htop + 'px');
1036			jQ_nxs('#nxsbox_ajaxContent').css('overflow', 'hidden');
1037			
1038			//
1039			jQ_nxs('#nxsbox_ajaxContent').each
1040			(
1041				function(index, element)
1042				{
1043					// horizontal positioning
1044					var parentWidth = jQ_nxs(element).parent().outerWidth();	// width of browser screen
1045					//nxs_js_log('parentwidth:' + parentWidth);
1046					
1047					var contentWidth = jQ_nxs(element).children().outerWidth();
1048					//nxs_js_log('contentWidth:' + contentWidth);
1049					
1050					if (contentWidth == 1)
1051					{
1052						// the popup opens initially with a size of 1 pixel wide (see #1283672893762),
1053						// we will enqueue the reset of the popup to ensure the position will be ok,
1054						// after the content is loaded (the content isn't positioned ok when we reach this
1055						// point)
1056						nxs_js_reset_popup_dimensions();
1057					}
1058					
1059					//nxs_js_log("parentWidth:");
1060					//nxs_js_log(parentWidth);
1061					//nxs_js_log("contentWidth:");
1062					//nxs_js_log(contentWidth);
1063					
1064					var minwidth = nxs_js_popup_get_minwidth();	// can be overriden
1065					if (contentWidth < minwidth)
1066					{
1067						contentWidth = minwidth;
1068					}
1069
1070					if (parentWidth >= contentWidth)
1071					{
1072						var leftvalue = Math.round((parentWidth - contentWidth)/2);
1073						//nxs_js_log('setting:' + leftvalue);
1074						jQ_nxs(element).css
1075						(
1076							{
1077								width: 'auto',
1078								left: leftvalue
1079						  }
1080						);
1081					}
1082					else
1083					{
1084						jQ_nxs(element).css
1085						(
1086							{
1087								width: parentWidth,
1088								left: '0px'
1089						  }
1090						);
1091					}
1092
1093					// ---------------
1094					
1095					// vertical positioning
1096					var parentHeight = jQ_nxs(element).parent().outerHeight();										
1097					var contentHeight = jQ_nxs(element).children().outerHeight();
1098				
1099					//nxs_js_log("parentHeight:");
1100					//nxs_js_log(parentHeight);
1101					//nxs_js_log("contentHeight:");
1102					//nxs_js_log(contentHeight);
1103					
1104					if (parentHeight >= contentHeight)
1105					{
1106						jQ_nxs(element).css
1107						(
1108							{
1109								height: 'auto',
1110								top: (parentHeight - contentHeight)/2
1111						  }
1112						);
1113					}
1114					else
1115					{
1116						nxs_js_log("setting to:" + parentHeight);
1117						
1118						jQ_nxs(element).css
1119						(
1120							{
1121								height: parentHeight,
1122								top: '0px'
1123						  }
1124						);
1125					}
1126				}
1127			);				
1128
1129			if (!jQ_nxs("#nxsbox_window").hasClass("nxs-active"))
1130			{
1131				jQ_nxs("#nxsbox_window").addClass("nxs-active");
1132			}
1133			else
1134			{
1135				// was already set, ignored
1136			}
1137			
1138			//jQ_nxs('#nxsbox_ajaxContent').css('opacity', '1');
1139			
1140			// add additional spacing at the bottom of the popup
1141			var footerfillerheight = 0;
1142			if(typeof nxs_js_popup_get_maxheight == 'function')
1143			{
1144				var footerfillerheight = nxs_js_popup_get_maxheight();
1145				footerfillerheight = footerfillerheight - 60;
1146				if (footerfillerheight < 0)
1147				{
1148					footerfillerheight = 0;
1149				}
1150			}
1151			jQ_nxs(".nxs-canvas-footerfiller").css("height", footerfillerheight);
1152			
1153			//
1154			jQ_nxs('#nxsbox_ajaxContent').css('left', '0px');
1155			jQ_nxs('#nxsbox_ajaxContent').css('top', '0px');
1156			
1157			var w = jQ_nxs(window).width();
1158			var wcontent = jQ_nxs(".nxs-popup-content-canvas-cropper").width();
1159			var wleft = (w - wcontent) / 2;
1160			if (wleft < 0) { wleft = 0; }
1161			
1162			jQ_nxs('#nxsbox_ajaxContent').css('position', 'absolute');
1163			
1164			if (jQ_nxs('#nxsbox_window').hasClass("nxs-gallerypopup"))
1165			{
1166				nxs_js_log("window has class");
1167				jQ_nxs('#nxsbox_ajaxContent').css('margin-left', '0px');
1168			}
1169			else
1170			{
1171				//nxs_js_log("window does not have class");
1172				jQ_nxs('#nxsbox_ajaxContent').css('margin-left', wleft + 'px');
1173			}
1174		}
1175		
1176		function nxs_js_toggle_editor_state()
1177		{
1178			// toggle!
1179	  	nxs_js_nxseditoractive = !nxs_js_nxseditoractive;
1180	  	
1181	  	var cookieval = "";
1182	  	if (nxs_js_nxseditoractive)
1183	  	{
1184	  		cookieval = "active";
1185	  	}
1186	  	else
1187	  	{
1188	  		cookieval = "inactive";
1189	  	}
1190	  	nxs_js_setcookie('nxs_cookie_editoractive', cookieval);
1191		  nxs_js_process_updated_editor_state();
1192		}
1193		
1194		function nxs_js_initiateeditorstate()
1195		{
1196			if (!nxs_js_userhasadminpermissions())
1197			{
1198				nxs_js_nxseditoractive = false;
1199				return;
1200			}
1201		
1202			var cookieval = nxs_js_getcookie('nxs_cookie_editoractive');
1203			if (cookieval == "active")
1204			{
1205				nxs_js_nxseditoractive = true;
1206			}
1207			else if (cookieval == "inactive")
1208			{
1209				nxs_js_nxseditoractive = false;
1210			}
1211			else
1212			{
1213				// first time, or else
1214				nxs_js_nxseditoractive = true;
1215			}
1216			
1217			nxs_js_process_updated_editor_state_silent();
1218		}
1219		
1220		function nxs_js_process_updated_editor_state()
1221		{
1222			var growl = true;
1223			if (jQ_nxs("body").hasClass("nxs-plugin-catalogitem"))
1224			{
1225				growl = false;
1226			}
1227			nxs_js_process_updated_editor_state_internal(growl);
1228		}
1229		
1230		function nxs_js_process_updated_editor_state_silent()
1231		{
1232			var growl = false;
1233			nxs_js_process_updated_editor_state_internal(growl);
1234		}
1235		
1236		// parameter growl is used to indicate whether
1237		function nxs_js_process_updated_editor_state_internal(growl)
1238		{
1239	    if (!nxs_js_userhasadminpermissions())
1240	    {
1241	    	// the popup mechanism is used for galleries too, and other parts,
1242	    	// if these popups are closed, the method is invoked too,
1243	    	// in that case we ignore the requests
1244	    	return;
1245	    }
1246
1247			if (!nxs_js_nxseditoractive) 
1248	  	{	  		
1249		    jQ_nxs(".nxs-cursor").addClass("nxs-suppress");
1250		    jQ_nxs(".nxs-hover-menu").addClass("nxs-suppress");
1251		    
1252		    if (growl)
1253		    {
1254		    	nxs_js_editorstategrowltoken = nxs_js_alert_wait_start(nxs_js_gettrans('Editor is now disabled'));
1255		    }
1256
1257		    jQ_nxs(".nxs-editor-toggler").find(".nxs-icon-pause").hide();
1258		    jQ_nxs(".nxs-editor-toggler").find(".nxs-icon-play").show();
1259
1260		    jQ_nxs(".nxs-editor-toggler").attr('title', nxs_js_gettrans('Click to reactivate editor '));
1261		    
1262		    // als de editor uit staat, moet de gebruiker weer "normaal" tekst kunnen selecteren
1263				jQ_nxs('body').enableSelection();
1264				
1265				// hide particular elements
1266				jQ_nxs(".nxs-hidewheneditorinactive").hide();
1267				jQ_nxs(".nxs-border-dash").hide();
1268			}
1269	  	else 
1270		  { 		  
1271		    jQ_nxs(".nxs-suppress").removeClass("nxs-suppress");
1272		    
1273		    if (growl)
1274		    {
1275	    		nxs_js_alert_wait_finish(nxs_js_editorstategrowltoken);
1276	    		nxs_js_alert_veryshort(nxs_js_gettrans('Editor is now active again'));
1277	    	}
1278		    
1279		    jQ_nxs(".nxs-editor-toggler").find(".nxs-icon-pause").show();
1280		    jQ_nxs(".nxs-editor-toggler").find(".nxs-icon-play").hide();
1281		    
1282		    jQ_nxs(".nxs-editor-toggler").attr('title', nxs_js_gettrans('Click to deactivate editor'));
1283		    		    
1284		    // als de editor aan staat, kan de gebruiker geen tekst kunnen selecteren (dit voorkomt irritante tekst selecties bij drag/droppen van widgets)
1285				jQ_nxs('body').disableSelection();		    
1286				
1287				// show particular elements
1288				jQ_nxs(".nxs-hidewheneditorinactive").show();
1289				jQ_nxs(".nxs-border-dash").show();
1290	  	}
1291	  	
1292	  	// add a class to the html element
1293	  	if (nxs_js_nxseditoractive)
1294	  	{
1295	  		jQ_nxs("html").removeClass("nxs-editor-inactive");
1296	  		jQ_nxs("html").addClass("nxs-editor-active");
1297	  	}
1298	  	else
1299	  	{
1300	  		jQ_nxs("html").removeClass("nxs-editor-active");
1301	  		jQ_nxs("html").addClass("nxs-editor-inactive");
1302	  	}
1303	  	
1304	  	nxs_js_refreshtopmenufillerheight();
1305	  	
1306	  	nxs_gui_set_runtime_dimensions_enqueuerequest("nxs-framework-editorstatechanged");	// update gui (for example, heights of "empty" rows)
1307		}
1308		
1309		function nxs_js_toggle_menu_state()
1310		{
1311			// toggle!
1312	  	nxs_js_nxsmenuactive = !nxs_js_nxsmenuactive;
1313	  	
1314	  	var cookieval = "";
1315	  	if (nxs_js_nxsmenuactive)
1316	  	{
1317	  		cookieval = "active";
1318	  	}
1319	  	else
1320	  	{
1321	  		cookieval = "inactive";
1322	  	}
1323	  	nxs_js_setcookie('nxs_cookie_menuactive', cookieval);
1324		  nxs_js_process_updated_menu_state();
1325		  
1326		  nxs_js_refreshtopmenufillerheight();
1327		}
1328		
1329		function nxs_js_initiatemenustate()
1330		{
1331			var cookieval = nxs_js_getcookie('nxs_cookie_menuactive');
1332			if (cookieval == "active")
1333			{
1334				nxs_js_nxsmenuactive = true;
1335			}
1336			else if (cookieval == "inactive")
1337			{
1338				nxs_js_nxsmenuactive = false;
1339			}
1340			else
1341			{
1342				// first time, or else
1343				nxs_js_nxsmenuactive = true;
1344			}
1345			nxs_js_process_updated_menu_state_silent();
1346		}
1347		
1348		function nxs_js_process_updated_menu_state()
1349		{
1350			var growl = true;
1351			nxs_js_process_updated_menu_state_internal(growl);
1352		}
1353		
1354		function nxs_js_process_updated_menu_state_silent()
1355		{
1356			var growl = false;
1357			nxs_js_process_updated_menu_state_internal(growl);
1358		}
1359		
1360		// parameter growl is used to indicate whether
1361		function nxs_js_process_updated_menu_state_internal(growl)
1362		{
1363	    if (!nxs_js_userhasadminpermissions())
1364	    {
1365	    	// the popup mechanism is used for galleries too, and other parts,
1366	    	// if these popups are closed, the method is invoked too,
1367	    	// in that case we ignore the requests
1368	    	return;
1369	    }
1370
1371			if (!nxs_js_nxsmenuactive) 
1372	  	{			  	
1373		    if (growl)
1374		    {
1375		    	nxs_js_menustategrowltoken = nxs_js_alert_wait_start(nxs_js_gettrans('menu is now disabled'));
1376		    }
1377
1378		    jQ_nxs(".nxs-menu-toggler").find(".nxs-icon-arrow-up").hide();
1379		    jQ_nxs(".nxs-menu-toggler").find(".nxs-icon-arrow-down").show();
1380
1381		    jQ_nxs(".nxs-menu-toggler").attr('title', nxs_js_gettrans('Click to reactivate menu'));
1382		    
1383				// hide particular elements
1384				jQ_nxs(".nxs-hidewhenmenuinactive").hide();
1385			}
1386	  	else 
1387		  { 		  
1388		    if (growl)
1389		    {
1390	    		nxs_js_alert_wait_finish(nxs_js_menustategrowltoken);
1391	    		nxs_js_alert_veryshort(nxs_js_gettrans('menu is now active again'));
1392	    	}
1393		    
1394		    jQ_nxs(".nxs-menu-toggler").find(".nxs-icon-arrow-up").show();
1395		    jQ_nxs(".nxs-menu-toggler").find(".nxs-icon-arrow-down").hide();
1396		    
1397		    jQ_nxs(".nxs-menu-toggler").attr('title', nxs_js_gettrans('Click to deactivate menu'));
1398				
1399				// show particular elements
1400				jQ_nxs(".nxs-hidewhenmenuinactive").show();
1401	  	}
1402	  	
1403	  	// add a class to the html element
1404	  	if (nxs_js_nxsmenuactive)
1405	  	{
1406	  		jQ_nxs("html").removeClass("nxs-menu-inactive");
1407	  		jQ_nxs("html").addClass("nxs-menu-active");
1408	  	}
1409	  	else
1410	  	{
1411	  		jQ_nxs("html").removeClass("nxs-menu-active");
1412	  		jQ_nxs("html").addClass("nxs-menu-inactive");
1413	  	}
1414	  	
1415	  	nxs_js_refreshtopmenufillerheight();
1416	  	
1417	  	// show the menu (its hidden when the page is loaded using inline style for
1418	  	// optimal UX)
1419	  	jQ_nxs("#nxs-menu-outerwrap").show();
1420		}
1421		
1422		function nxs_js_togglesidebar()
1423		{
1424			var ajaxurl = nxs_js_get_adminurladminajax();
1425			jQ_nxs.ajax
1426			(
1427				{
1428					type: 'POST',
1429					data: 
1430					{
1431						"action": "nxs_ajax_webmethods",
1432						"webmethod": "togglesidebar",
1433						"postid": nxs_js_getcontainerpostid()
1434					},
1435					cache: false,
1436					dataType: 'JSON',
1437					url: ajaxurl, 
1438					success: function(response) 
1439					{
1440						nxs_js_log(response);
1441						if (response.result == "OK")
1442						{
1443							// refresh screen to see the end result :)
1444							nxs_js_refreshcurrentpage();
1445						}
1446						else
1447						{
1448							nxs_js_popup_notifyservererror();
1449							nxs_js_log(response);
1450						}
1451					},
1452					error: function(response)
1453					{
1454						nxs_js_popup_notifyservererror();
1455						nxs_js_log(response);
1456					}
1457				}
1458			);
1459		}
1460		
1461		function nxs_js_handleplaceholderevent(eventname, e, placeholderdom)
1462		{
1463			if (!nxs_js_nxseditoractive)
1464			{
1465				nxs_js_log("ignoring event; editor is OFF");
1466				return false;
1467			}
1468			
1469			var isButton = e.target.nodeName == "BUTTON";
1470			var isSelect = e.target.nodeName == "SELECT";
1471			var isInput = e.target.nodeName == "INPUT";
1472			var isTextArea = e.target.nodeName == "TEXTAREA";
1473			var isInAnchor = e.target.nodeName == "A" || (jQuery(e.target).closest('a').length > 0);
1474			var isHandledOutsideFramework = isButton || isSelect || isInput || isTextArea || isInAnchor;
1475			
1476			nxs_js_log("isHandledOutsideFramework; " + isHandledOutsideFramework);
1477			nxs_js_log("isSelect? " + isSelect);
1478			nxs_js_log("isButton? " + isButton);
1479			nxs_js_log("isInput? " + isInput);
1480			nxs_js_log("isTextArea? " + isTextArea);
1481			nxs_js_log("isInAnchor? " + isInAnchor);
1482			
1483			if (isHandledOutsideFramework)
1484			{
1485				// if the event is a click, and the event is caused by an anchor that
1486				// has a "regular" href (no onclick), then follow that href, instead
1487				return false;
1488			}
1489			else
1490			{
1491				nxs_js_log("Event possibly handled by framework");
1492				// proceed
1493			}
1494			
1495			nxs_js_log("placeholderdom:");
1496			nxs_js_log(placeholderdom);
1497			
1498			// handle incoming event for the placeholder,
1499			// note; its possible (as it appears) the event is triggered by objects 
1500			// outside the framework (such as WooCommerce). We therefore first ensure 
1501			// we need to act upon this event (and absorb the event), or allow the 
1502			// event to propagate further
1503			
1504			var istriggeredbywidget = jQ_nxs(e.target).closest(".nxs-widget").length > 0;
1505			var istriggeredbycursor = jQ_nxs(e.target).hasClass("nxs-runtime-autocellsize");
1506			var istriggeredbynexusframework = (istriggeredbywidget || istriggeredbycursor);
1507			
1508			
1509			if (istriggeredbynexusframework)
1510			{
1511				nxs_js_log("no propagation (1)");
1512				// no further propagation of the click event...
1513				e.stopPropagation();
1514				nxs_js_popup_placeholder_handleclick(placeholderdom); 
1515			}
1516			else
1517			{
1518				// we won't act upon this event as we don't know who are what
1519				// triggered it. The event wil be logged to help debug problems,
1520				// and it will propagate further to be handled by someone else's code
1521				nxs_js_log("Widget detect an event that appears to be triggered outside the nxs framework. It propagates further:");
1522				nxs_js_log(e);
1523			}
1524		}
1525		
1526		function nxs_js_reregister_click_and_hover_events()
1527		{
1528			if (nxs_js_userhasadminpermissions())
1529			{
1530				jQ_nxs("input").unbind("click.reregister");
1531				jQ_nxs("input").bind("click.reregister", function(e) 
1532				{
1533					if (nxs_js_nxseditoractive)
1534					{
1535						// if the editor is on, we don't want events in input elements
1536						// to traverse
1537						nxs_js_log("no propagation (4)");
1538				  	e.stopPropagation();
1539				  }
1540				  else
1541			  	{
1542			  		// if the editor is off we allow these events to be handled
1543			  	}
1544				})
1545				
1546				// allow user to click on any widget within an editable section
1547				jQ_nxs(".nxs-widgets-editable .nxs-placeholder-list > .nxs-placeholder").each
1548				(
1549					function(index, placeholderelement)
1550					{
1551						// remove any previously defined click events
1552						jQ_nxs(placeholderelement).unbind("click.reregister");
1553						jQ_nxs(placeholderelement).bind
1554						(
1555							"click.reregister", 
1556							function(e)
1557							{
1558								var result = nxs_js_handleplaceholderevent('click', e, this);
1559								return true;
1560							}
1561						);
1562						
1563						// remove any previously defined dbl click events
1564						jQ_nxs(placeholderelement).unbind("dblclick.reregister");
1565						jQ_nxs(placeholderelement).bind
1566						(
1567							"dblclick.reregister", 
1568							function(e)
1569							{
1570								nxs_js_handleplaceholderevent('dblclick', e, this);
1571							}
1572						);
1573					}
1574				);
1575				
1576				//
1577				// als een gebruiker clickt op het 'verplaats' icoon
1578				// bij een placeholder moet het click event worden geabsorbeerd
1579				//
1580				jQ_nxs(".cursor").unbind("click.startdrag");
1581				jQ_nxs(".cursor").bind("click.startdrag", function(e) 
1582				{
1583					// stop het progageren van het event (bind("click") om te voorkomen dat onderliggende
1584					// elementen het click event gaan afhandelen (zoals het event dat de body click altijd opvangt...)
1585					nxs_js_log("no propagation (6)");
1586					e.stopPropagation();
1587					
1588					nxs_js_alert(nxs_js_gettrans('Tip to move widget'));
1589				});
1590				
1591				//
1592				Mousetrap.bind('alt+c', function(e, combo) 
1593	  		{
1594				  console.log(combo);
1595				  nxs_copytoserverclipboard("designproperties");
1596				});
1597				Mousetrap.bind('alt+v', function(e, combo) 
1598	  		{
1599				  console.log(combo);
1600				  nxs_pastefromserverclipboard("designproperties");
1601				});
1602				
1603				jQ_nxs(document).unbind("keydown.ctrlprocessing");
1604				jQ_nxs(document).bind("keydown.ctrlprocessing", function(evt)
1605				{
1606	    		if (!nxs_js_isctrlkeydown)
1607	    		{
1608		        if (evt.keyCode == 17)	// 17 = ctrl
1609		        { 
1610		        	nxs_js_isctrlkeydown = true;
1611		        	//nxs_js_log('ctrl pressed');
1612		        }
1613		        /*
1614		        else 
1615		        { 
1616		        	nxs_js_log('key pressed:' + evt.keyCode);
1617		        }
1618		        */
1619		      }
1620		    });
1621		     
1622				// control (ctrl) toets zet tijdelijk de cursors uit
1623				jQ_nxs(document).unbind("keyup.compound");
1624				jQ_nxs(document).bind("keyup.compound", function(evt)
1625				{
1626					if (evt.which == 27)	// handled
1627				  {				  
1628				  	if (nxs_js_popupshows)
1629				  	{
1630				  		// ignore the request when popup shows (popup itself is responsible for handling escape)
1631				  	}
1632				  	else if (nxs_js_nxsisdragging)
1633				  	{
1634				  		// ignore the request when user is drag'n'dropping
1635				  	}
1636				  	else
1637				  	{
1638					  	//nxs_js_log('debug; escape pressed (GJGJ), popup does not show');
1639				  	
1640				  		nxs_js_toggle_editor_state();
1641				  		return false;
1642				  	}
1643					}
1644				
1645					if (nxs_js_nxseditoractive)
1646		    	{
1647		        if (nxs_js_isctrlkeydown)
1648		        {
1649		        	// if keyboard focus is set to an element 
1650		        	// in the top menu, ignore the event to allow "normal"
1651		        	// copy and pasting of the clipboard
1652		        	var focusElement = jQ_nxs(document.activeElement);
1653		        	/*
1654		        	var isFocusSetOnTopMenu = jQ_nxs(focusElement).closest("#nxs-menu-outerwrap");
1655		        	if (isFocusSetOnTopMenu)
1656		        	{
1657		        		nxs_js_log("ignoring ctrl-keyboard; focus in top menu");
1658		        		return;
1659		        	}
1660		        	*/
1661		        	if (jQ_nxs(focusElement).is('input:text'))
1662		        	{
1663		        		nxs_js_log("ignoring ctrl-keyboard; focus in input textbox");
1664		        		return;
1665		        	}
1666		        	if (jQ_nxs(focusElement).is('textarea'))
1667		        	{
1668		        		nxs_js_log("ignoring ctrl-keyboard; focus in textarea");
1669		        		return;
1670		        	}
1671		        	
1672		        	// detect CTRL-related keyboard combinations like copy-paste
1673		        	
1674		        	//nxs_js_log("keycode:" + evt.keyCode);
1675		        
1676		        	// ctrl is pressed
1677		        	
1678		        	if (evt.keyCode == 67)
1679		        	{
1680		        		// CTRL-C / CMD-C
1681		        		nxs_js_isctrlkeydown = false;
1682		        		nxs_copytoserverclipboard("all");
1683		        		return false;
1684		        	}
1685		        	else if (evt.keyCode == 86)
1686		        	{
1687		        		// CTRL-V / CMD-V
1688		        		nxs_js_isctrlkeydown = false;
1689		        		nxs_pastefromserverclipboard("all");
1690		        		return false;
1691		        	}
1692		        	else if (evt.keyCode == 66)	// debug key: ctrl-b = re-enable js events (rebuild UI editor)
1693		        	{
1694		        		nxs_js_isctrlkeydown = false;
1695		        		nxs_js_alert('debug - invoking nxs_js_reenable_all_window_events() BEGIN');
1696		        		nxs_js_reenable_all_window_events();
1697		        		nxs_js_alert('debug - invoking nxs_js_reenable_all_window_events() DONE');
1698		        		return false;
1699		        	}
1700			        else if (evt.keyCode == 17) // 17 = ctrl
1701			        {
1702			        	nxs_js_isctrlkeydown = false;	// ctrl key released
1703			        	//nxs_js_log('ctrl released');
1704			        }
1705		        	else 
1706		        	{
1707		        		//nxs_js_log(evt.keyCode);
1708		        		//return false;
1709		        	}
1710						}
1711						else
1712						{
1713						  if (evt.keyCode == 46)	// delete key
1714							{
1715								if (!nxs_js_popupshows)
1716								{
1717									var widget = nxs_js_getwidgetdom_overwhichwehover();
1718									if (widget != null)
1719									{
1720										nxs_js_frontendediting_widgethandledelete(widget);
1721									}
1722									else
1723									{
1724										// not hovering over widget
1725									}
1726								}
1727							}
1728						}
1729					}
1730				});
1731				
1732				// if a user hovers over a placeholder that is editable,
1733				// we add a nxs-hovering class to its cell-cursor and hover-menu,
1734				// we remove the classes when the user moves out
1735				// OK
1736				jQ_nxs(".nxs-widgets-editable .nxs-placeholder").unbind("mouseover.glowwidget");
1737				jQ_nxs(".nxs-widgets-editable .nxs-placeholder").bind("mouseover.glowwidget", function(e)
1738				{
1739					if (!nxs_js_nxsisdragging)
1740					{
1741						// add nxs-hovering
1742						jQ_nxs(this).find(".nxs-cell-cursor").addClass("nxs-hovering");
1743						jQ_nxs(this).find(".nxs-hover-menu").addClass("nxs-hovering");
1744						jQ_nxs(this).addClass("nxs-hovering");
1745						
1746						// update height of child items (cursors) that should have the same size
1747						var height = jQ_nxs(this).height();
1748						jQ_nxs(this).find(".nxs-runtime-autocellsize").height(height);
1749					}
1750				});
1751				// OK
1752				jQ_nxs(".nxs-widgets-editable .nxs-placeholder").unbind("mouseleave.glowwidget");
1753				jQ_nxs(".nxs-widgets-editable .nxs-placeholder").bind("mouseleave.glowwidget", function(e)
1754				{
1755					//
1756					jQ_nxs(this).find(".nxs-cell-cursor").removeClass("nxs-hovering");
1757					jQ_nxs(this).find(".nxs-hover-menu").removeClass("nxs-hovering");
1758					jQ_nxs(this).removeClass("nxs-hovering");
1759				}
1760				);
1761				
1762				// if the user hovers over a hovermenu of a pagerow,
1763				// highlight all widgets within that row, and dim them when the mouse leaves the menu
1764				// OK
1765				jQ_nxs(".nxs-layout-editable .nxs-row .nxs-row-container > .nxs-hover-menu").unbind("mouseover.glowrow");
1766				jQ_nxs(".nxs-layout-editable .nxs-row .nxs-row-container > .nxs-hover-menu").bind("mouseover.glowrow", function(e)
1767				{
1768					if (!nxs_js_nxsisdragging)
1769					{
1770						jQ_nxs(this).closest(".nxs-row").find(".nxs-cell-cursor").addClass("nxs-hovering");
1771						jQ_nxs(this).closest(".nxs-row").find(".nxs-placeholder").addClass("nxs-hovering");
1772					}
1773				});
1774				// OK
1775				jQ_nxs(".nxs-layout-editable .nxs-row .nxs-row-container > .nxs-hover-menu").unbind("mouseleave.glowrow");
1776				jQ_nxs(".nxs-layout-editable .nxs-row .nxs-row-container > .nxs-hover-menu").bind("mouseleave.glowrow", function(e)
1777				{
1778					if (!nxs_js_nxsisdragging)
1779					{
1780						jQ_nxs(this).closest(".nxs-row").find(".nxs-cell-cursor").removeClass("nxs-hovering");
1781						jQ_nxs(this).closest(".nxs-row").find(".nxs-placeholder").removeClass("nxs-hovering");
1782					}
1783				}
1784				);
1785				
1786				// als de gebruiker boven een cursor hangt (bijv. sidebar)
1787				// moet de widget oplichten
1788				jQ_nxs(".nxs-cursor").unbind("mouseover.glowwidget");
1789				jQ_nxs(".nxs-cursor").bind("mouseover.glowwidget", function(e)
1790				{
1791					if (!nxs_js_nxsisdragging)
1792					{
1793						jQ_nxs(this).addClass("nxs-hovering");
1794						// geef ook nxs-hovering aan mogelijke hovermenu's die hier in zitten
1795						jQ_nxs(this).find(".nxs-hover-menu").addClass("nxs-hovering");
1796					}
1797				});
1798				jQ_nxs(".nxs-cursor").unbind("mouseleave.glowwidget");
1799				jQ_nxs(".nxs-cursor").bind("mouseleave.glowwidget", function(e)
1800				{
1801					//nxs_js_log('mouse leave detected nxs-cursor');
1802					jQ_nxs(this).removeClass("nxs-hovering");
1803					// verwijder ook nxs-hovering aan mogelijke hovermenu's die hier in zitten
1804					jQ_nxs(this).find(".nxs-hover-menu").removeClass("nxs-hovering");
1805				}
1806				);
1807				
1808				// als de gebruiker boven een container hangt met een immediate hover menu...
1809				
1810				jQ_nxs(".nxs-containsimmediatehovermenu").unbind("mouseover.glowwidget");
1811				jQ_nxs(".nxs-containsimmediatehovermenu").bind("mouseover.glowwidget", function(e)
1812				{
1813					if (!nxs_js_nxsisdragging)
1814					{
1815						jQ_nxs(this).children(".nxs-hover-menu").addClass("nxs-hovering");
1816					}
1817				});
1818				jQ_nxs(".nxs-containsimmediatehovermenu").unbind("mouseleave.glowwidget");
1819				jQ_nxs(".nxs-containsimmediatehovermenu").bind("mouseleave.glowwidget", function(e)
1820				{
1821					//nxs_js_log('mouse leave detected');
1822					jQ_nxs(this).children(".nxs-hover-menu").removeClass("nxs-hovering");
1823				}
1824				);
1825			}
1826			
1827			
1828			// allow extensions to extend this
1829			jQ_nxs(window).trigger('nxs_js_reregister_click_and_hover_events');
1830		}
1831		
1832		// returns the index of the current row element within the container of rows (nearest to 'element')
1833		function nxs_js_getrowindex(element)
1834		{
1835			var row = jQ_nxs(element).closest('.nxs-row');
1836			var container = jQ_nxs(element).closest('.nxs-postrows')[0];
1837			var rows = jQ_nxs(container).find('.nxs-row'); // alle nxs-rows binnen nxs-postrows
1838			var result = jQ_nxs(rows).index(row);	//  de index van de dichtsbijzijnde nxs-row binnen de lijst
1839			return result;
1840		}
1841		
1842		// returns the identifier of the row
1843		function nxs_js_getrowid(element)
1844		{
1845			var row = jQ_nxs(element).closest('.nxs-row');	// bijv. nxs-pagerow-prid1182682337
1846			var result = jQ_nxs(row).attr("id").split("-")[2];
1847			return result;
1848		}
1849		
1850		// returns the element of the dom element within the container for the specified postid and rowindex
1851		function nxs_js_getrowelement(postid, rowindex)
1852		{
1853			var element = nxs_js_getelementscontainer(postid);
1854			var result = jQ_nxs(element).children().children()[rowindex];
1855			return result;
1856		}
1857		
1858		function nxs_js_getplaceholderidsinrow(rowelement)
1859		{
1860			var result = [];
1861			jQ_nxs(rowelement).find(".nxs-widget").each
1862  		(
1863  			function(index, widgetelement) 
1864  			{
1865  				var widgetelementid = widgetelement.id;	// bijv. nxs-widget-a1362357679
1866  				var placeholderid = widgetelementid.split("-")[2];
1867  				result.push(placeholderid);
1868  			}
1869  		);
1870  		return result;
1871		}
1872		
1873		function nxs_js_row_render(postid, rowindex, invokewhenavailable)
1874		{
1875			if (rowindex == -1)
1876			{
1877				nxs_js_log("postid: " + postid);
1878				nxs_js_log("rowindex: " + rowindex);
1879				nxs_js_log("rowindex niet gevonden");
1880				alert("rowindex niet gevonden");
1881				return;
1882			}
1883			
1884			var postcontainerid = nxs_js_getcontainerpostid();
1885			
1886			var ajaxurl = nxs_js_get_adminurladminajax();
1887			jQ_nxs.ajax
1888			(
1889				{
1890					type: 'POST',
1891					data: 
1892					{
1893						"action": "nxs_ajax_webmethods",
1894						"webmethod": "getcontent",
1895						"clientpopupsessioncontext": nxs_js_getescaped_popupsession_context(),
1896						"contenttype": "webpart",
1897						"contentcontext": "row_" + postcontainerid + "_" + postid + "_" + rowindex,
1898						"webparttemplate": "render_htmlvisualization",
1899						"clientqueryparameters": nxs_js_escaped_getqueryparametervalues()
1900					},
1901					cache: false,
1902					dataType: 'JSON',
1903					url: ajaxurl, 
1904					success: function(response) 
1905					{
1906						nxs_js_log(response);
1907						if (response.result == "OK")
1908						{
1909							invokewhenavailable(postid, rowindex, response);
1910						}
1911						else
1912						{
1913							nxs_js_log("server response is valid, but not 'ok'");
1914							nxs_js_log(response);
1915							nxs_js_popup_notifyservererror_v2(response);
1916						}
1917					},
1918					error: function(xhr, ajaxOptions, thrownError)
1919					{
1920						// an error could occur if the user redirects before this operation is completed
1921						nxs_js_popup_notifyservererror_v2(thrownError);
1922					}
1923				}
1924			);
1925		}
1926		
1927		// helper function that gets the dom element of the elementscontainer for the specified postid,
1928		// if a page contains a header, sidebar, maincontent and footer, 
1929		// you can easily get the footer dom, knowing its postid
1930		function nxs_js_getelementscontainer(postid)
1931		{
1932			var result = jQ_nxs(".nxs-elements-container.nxs-post-" + postid).first();
1933			return result;
1934		}
1935		
1936		// helper function that returns the dom of the widget in the elementscontainer
1937		function nxs_js_getwidget_withinelementscontainer(elementscontainer, placeholderid)
1938		{
1939			var result = jQ_nxs(elementscontainer).find("#nxs-widget-" + placeholderid)[0];
1940			return result;
1941		}
1942		
1943		// helper function that returns the dom of the widget (placeholderid) in the elementscontainer (postid)
1944		function nxs_js_getwidgetinpostid(postid, placeholderid)
1945		{
1946			var elementscontainer = nxs_js_getelementscontainer(postid);
1947			var result = nxs_js_getwidget_withinelementscontainer(elementscontainer, placeholderid);
1948			return result;
1949		}
1950		
1951		// convenience function, rerenders the GUI row for the specified postid and placeholderid,
1952		// by using this function its possible to re-render a row in the header
1953		// on the screen.
1954		function nxs_js_rerender_row_for_placeholder(postid, placeholderid)
1955		{
1956			var widget = nxs_js_getwidgetinpostid(postid, placeholderid);
1957			nxs_js_rerender_row_for_element(widget);
1958		}
1959
1960		// convenience function
1961		function nxs_js_rerender_row_for_pagerow(postid, pagerowid)
1962		{
1963			var pagecontainer = jQ_nxs(".nxs-post-" + postid)[0];
1964			var element = jQ_nxs(pagecontainer).find("#nxs-pagerow-" + pagerowid)[0];
1965			nxs_js_rerender_row_for_element(element);
1966		}
1967		
1968		function nxs_js_getrowindex_forplaceholder(postid, placeholderid)
1969		{
1970			var element = nxs_js_getwidgetelement_forplaceholder(postid, placeholderid);
1971			var rowindex = nxs_js_getrowindex(element);
1972			return rowindex;
1973		}
1974		
1975		function nxs_js_getwidgetelement_forplaceholder(postid, placeholderid)
1976		{
1977			var pagecontainer = jQ_nxs(".nxs-post-" + postid)[0];
1978			var element = jQ_nxs(pagecontainer).find("#nxs-widget-" + placeholderid)[0];
1979			return element;
1980		}
1981		
1982		function nxs_js_rerender_row_for_element(element)
1983		{
1984			var postid = nxs_js_findclosestpostid_for_dom(element);
1985		
1986			var rowindex = nxs_js_getrowindex(element);
1987			//nxs_js_log("found:" + rowindex);
1988			nxs_js_row_render(postid, rowindex, function(postid, rowindex, response)
1989			{	
1990				var html = response.html;
1991				// we gaan er vanuit dat het opnieuw tekenen plaatsvindt op de article container en niet in de sidebar of footer ...							
1992				var pagecontainer = jQ_nxs(".nxs-post-" + postid)[0];
1993				var pagerowscontainer = jQ_nxs(pagecontainer).find(".nxs-postrows")[0];
1994				// afterwards update existing row
1995				var updateElement = jQ_nxs(pagerowscontainer).children()[rowindex];
1996
1997				// before updating the dom, we first wipe any functions for notification ajax used by the "old" widgets in this row
1998				nxs_js_clear_ajaxrefresh_notifications(updateElement);
1999				
2000				// 
2001				//nxs_js_log("replacing index " + rowindex);
2002				jQ_nxs(updateElement).replaceWith(html);
2003				
2004				// after updating the dom, invoke execute_after_clientrefresh_XYZ for each widget in the affected first row, if present
2005				var updateElement = jQ_nxs(pagerowscontainer).children()[rowindex];
2006				nxs_js_notify_widgets_after_ajaxrefresh(updateElement);
2007				
2008				jQuery(document).trigger('nxs_dom_changed');
2009				
2010				nxs_js_reenable_all_window_events();
2011			});
2012			//nxs_js_log("done:" + rowindex);
2013		}
2014
2015		function nxs_js_getfirstplaceholderid_in_dom(s)
2016		{
2017			var result = null;
2018			
2019  		jQ_nxs(s).find('.draggable_placeholder').each
2020  		(
2021  			function(idx2, elm2) 
2022  			{
2023  				var id = elm2.id;
2024  				result = id.split("-")[3];
2025				}
2026			);
2027			
2028			if (result == null)
2029			{
2030				jQ_nxs(s).find('.nxs-widget').each
2031	  		(
2032	  			function(idx2, elm2) 
2033	  			{
2034	  				var id = elm2.id;
2035	  				result = id.split("-")[2];
2036					}
2037				);
2038			}
2039			
2040			if (result == null)
2041			{
2042				nxs_js_log("placeholderid niet gevonden voor");
2043				nxs_js_log(s);
2044				nxs_js_log(jQ_nxs(s).html());
2045				nxs_js_alert('placeholderid niet gevonden');
2046				alert('placeholderid not found!');
2047			}
2048			
2049			return result;
2050		}
2051		
2052		function nxs_js_getmenuitemdepth_in_dom(s)
2053		{
2054			var result = -1;
2055			
2056			jQ_nxs(s).find('.nxs-widget').each
2057  		(
2058  			function(idx2, elm2) 
2059  			{
2060  				// de nxs-widget heeft een class 'nxs-listitem-depth-X'
2061  				var classes = this.className.split(" ");
2062				  for (var i = 0, len = classes.length; i < len; i++) 
2063				  {
2064				    if (classes[i].startsWith('nxs-listitem-depth-'))
2065				    {
2066				    	result = parseInt(classes[i].split("-", 4)[3]);
2067				    	break;
2068				    }
2069				  }
2070				}
2071			);
2072			
2073			//alert(result);
2074			
2075			return result;
2076		}
2077		
2078		function nxs_js_popup_placeholder_handleclick(placeholderdom)
2079		{
2080			var postid = nxs_js_findclosestpostid_for_dom(placeholderdom);
2081			var widget = jQ_nxs(placeholderdom).find(".nxs-widget").first();
2082			var placeholderid = jQ_nxs(widget).attr("id").split("-")[2];
2083			var rowindex = nxs_js_getrowindex(widget);
2084		
2085			// indien (optioneel) een "nxs-clickdefault" attribuut aanwezig
2086			// is binnen de dom van de widget, wordt het event doorgelust naar
2087			// dat element
2088			var widgetelement = nxs_js_getwidgetelement_forplaceholder(postid, placeholderid);				
2089			var defaultelement = jQ_nxs(placeholderdom).find(".nxs-defaultwidgetclickhandler");
2090			if (defaultelement.length >= 1)
2091			{
2092				// ja, er is een default element gedefinieerd
2093				jQ_nxs(defaultelement).click();
2094			}
2095			else
2096			{
2097				// nee, er is geen default gedrag gedefinieerd
2098				
2099				nxs_js_log('Warning; please upgrade deprecated widget; nxs-defaultwidgetclickhandler class attribute not set, defaulting to edit widget');
2100				// default implementation
2101				
2102				nxs_js_popup_placeholder_neweditsession(postid, placeholderid, rowindex, 'home');
2103			}
2104		}
2105		
2106		// converts dictionary to properties of the specified scope object
2107		function nxs_js_extract(data, scope)
2108		{
2109	    for (var key in data) 
2110	    {
2111	    	if (!data.hasOwnProperty(key)) 
2112				{
2113					continue;
2114				}
2115        scope[key] = data[key];
2116    	}
2117		}
2118		
2119		function nxs_js_popup_placeholder_neweditsession(postid, placeholderid, rowindex, sheet)
2120		{
2121			var containerpostid = nxs_js_getcontainerpostid();
2122			var args = 
2123			{
2124				containerpostid:containerpostid,
2125				postid:postid,
2126				placeholderid:placeholderid,
2127				rowindex:rowindex,
2128				sheet:sheet
2129			};
2130			return nxs_js_popup_placeholder_neweditsession_v2(args);
2131		}
2132		
2133		// opent een pop up voor het bewerken van de meegegeven placeholder
2134		function nxs_js_popup_placeholder_neweditsession_v2(args)
2135		{
2136			nxs_js_extract(args, this);
2137			
2138			if (sheet == null)
2139			{
2140				sheet = 'home'; // default, if not set
2141			}
2142		
2143			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2144			{
2145				return;
2146			}
2147			
2148			// wipe any existing popupsession data
2149			nxs_js_popupsession_startnewcontext();
2150
2151			if (typeof onsaverefreshpage === "undefined")
2152			{
2153				//
2154			}
2155			else
2156			{
2157				nxs_js_popup_setsessioncontext("onsaverefreshpage", true);
2158			}
2159
2160			//
2161			nxs_js_popup_setsessioncontext("contextprocessor", "widgets");
2162			nxs_js_popup_setsessioncontext("containerpostid", containerpostid);
2163			nxs_js_popup_setsessioncontext("postid", postid);
2164			nxs_js_popup_setsessioncontext("placeholderid", placeholderid);
2165			nxs_js_popup_setsessioncontext("rowindex", rowindex);
2166
2167			// show the popup			
2168			nxs_js_popup_navigateto(sheet);
2169		}
2170		
2171		// opent een pop up voor het bewerken van de meegegeven pagerowid
2172		function nxs_js_popup_row_neweditsession(postid, pagerowid, sheet)
2173		{
2174			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2175			{
2176				return;
2177			}
2178			
2179			// wipe any existing popupsession data
2180			nxs_js_popupsession_startnewcontext();
2181			
2182			//
2183			nxs_js_popup_setsessioncontext("contextprocessor", "pagerow");
2184			nxs_js_popup_setsessioncontext("postid", postid);
2185			nxs_js_popup_setsessioncontext("pagerowid", pagerowid);
2186
2187			// show the popup			
2188			nxs_js_popup_navigateto(sheet);
2189		}
2190		
2191		// opent een pop up voor het bewerken van de meegegeven pagina
2192		function nxs_js_popup_postcontent_neweditsession(sheet)
2193		{
2194			var postid = nxs_js_getcontainerpostid();
2195		
2196			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2197			{
2198				return;
2199			}
2200			
2201			// wipe any existing popupsession data
2202			nxs_js_popupsession_startnewcontext();
2203			
2204			nxs_js_popup_setsessioncontext("contextprocessor", "postcontent");
2205			nxs_js_popup_setsessioncontext("postid", postid);
2206
2207			// show the popup			
2208			nxs_js_popup_navigateto(sheet);
2209		}
2210		
2211		// opent een pop up voor het bewerken van de meegegeven pagina
2212		function nxs_js_popup_page_neweditsession(postid, sheet)
2213		{
2214			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2215			{
2216				return;
2217			}
2218			
2219			// wipe any existing popupsession data
2220			nxs_js_popupsession_startnewcontext();
2221			
2222			nxs_js_popup_setsessioncontext("contextprocessor", "post");
2223			nxs_js_popup_setsessioncontext("postid", postid);
2224
2225			// show the popup			
2226			nxs_js_popup_navigateto(sheet);
2227		}
2228		
2229		// opens a popup page to edit for example the footer, header or sidebar of the page
2230		function nxs_js_popup_pagetemplate_neweditsession(sheet)
2231		{	
2232			var postid = nxs_js_getcontainerpostid();
2233			var pagetemplate = nxs_js_getcontainerpagetemplate();
2234		
2235			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2236			{
2237				return;
2238			}
2239			
2240			// wipe any existing popupsession data
2241			nxs_js_popupsession_startnewcontext();
2242			
2243			//
2244			nxs_js_popup_setsessioncontext("contextprocessor", "pagetemplate");
2245			nxs_js_popup_setsessioncontext("postid", postid);
2246			nxs_js_popup_setsessioncontext("pagetemplate", pagetemplate);
2247
2248			// show the popup			
2249			nxs_js_popup_navigateto(sheet);
2250		}
2251		
2252		// opent een pop up voor het instellen van de meegegeven pagelet voor de meegegeven pagetemplate in de meegegeven post
2253		function nxs_js_popup_pageletinpagetemplate_neweditsession(postid, pagetemplate, pageletname, sheet)
2254		{
2255			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2256			{
2257				return;
2258			}
2259			
2260			// wipe any existing popupsession data
2261			nxs_js_popupsession_startnewcontext();
2262			
2263			nxs_js_popup_setsessioncontext("contextprocessor", "pageletinpagetemplate");
2264			nxs_js_popup_setsessioncontext("postid", postid);
2265			nxs_js_popup_setsessioncontext("pagetemplate", pagetemplate);
2266			nxs_js_popup_setsessioncontext("pageletname", pageletname);
2267
2268			// show the popup			
2269			nxs_js_popup_navigateto(sheet);
2270		}
2271		
2272		// opent een pop up voor het instellen van de meegegeven pagelet voor de meegegeven pagetemplate in de meegegeven post
2273		function nxs_js_popup_subheaderinpagetemplate_neweditsession(postid, pagetemplate, subheadername, sheet)
2274		{
2275			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2276			{
2277				return;
2278			}
2279			
2280			// wipe any existing popupsession data
2281			nxs_js_popupsession_startnewcontext();
2282			
2283			nxs_js_popup_setsessioncontext("contextprocessor", "pageletinpagetemplate");
2284			nxs_js_popup_setsessioncontext("postid", postid);
2285			nxs_js_popup_setsessioncontext("pagetemplate", pagetemplate);
2286			nxs_js_popup_setsessioncontext("subheadername", subheadername);
2287
2288			// show the popup			
2289			nxs_js_popup_navigateto(sheet);
2290		}
2291		
2292		// opent een pop up voor het instellen van de meegegeven pagelet voor de meegegeven pagetemplate in de meegegeven post
2293		function nxs_js_popup_subfooterinpagetemplate_neweditsession(postid, pagetemplate, subfootername, sheet)
2294		{
2295			if (nxs_js_popup_anyobjectionsforopeningnewpopup())
2296			{
2297				return;
2298			}
2299			
2300			// wipe any existing popupsession data
2301			nxs_js_popupsession_startnewcontext();
2302			
2303			nxs_js_popup_setsessioncontext("contextprocessor", "pageletinpagetemplate");
2304			nxs_js_popup_setsessioncontext("postid", postid);
2305			nxs_js_popup_setsessioncontext("pagetemplate", pagetemplate);
2306			nxs_js_popup_setsessioncontext("subfootername", subfootername);
2307
2308			// show the popup			
2309			nxs_js_popup_navigateto(sheet);
2310		}
2311		
2312		function nxs_js_trash_article(postid)
2313		{
2314			var answer = confirm(nxs_js_gettrans('Are you sure you want to delete this page?'));
2315			if (!answer)
2316			{
2317				return;
2318			}
2319			nxs_js_trash_article_no_question(postid);
2320		}
2321		
2322		function nxs_js_invokewebmethod(options, handlehappyflow, handlealternativeflow, handlefailureflow)
2323		{
2324			if ('confirmtext' in options)
2325			{
2326				var text = options.confirmtext;
2327				var answer = confirm(text);
2328				if (!answer)
2329				{
2330					// toch niet
2331					return true;
2332				}
2333			}
2334			var waitgrowltoken = -1;
2335			if ('waitgrowltext' in options)
2336			{
2337				var text = options.waitgrowltext;
2338				waitgrowltoken = nxs_js_alert_wait_start(text);
2339			}
2340			
2341			var data = options.webmethoddata;
2342			var async = true;	// default = async
2343			if ('async' in options)
2344			{
2345				async = options.async;
2346			}
2347			var cache = false;
2347	// default = no caching
2348			if ('cache' in options)
2349			{
2350				cache = options.cache;
2351			}
2352			data.action = "nxs_ajax_webmethods";
2353		
2354			// invoke ajax call
2355			var ajaxurl = nxs_js_get_adminurladminajax();
2356			jQ_nxs.ajax
2357			(
2358				{
2359					type: 'POST',
2360					url: ajaxurl, 
2361					data: data,
2362					async: async,
2363					cache: cache,
2364					dataType: 'JSON',
2365					success: function(response) 
2366					{
2367						// dismiss loading growl if exists						
2368						nxs_js_alert_wait_finish(waitgrowltoken);
2369						nxs_js_log(response);
2370						if (response.result == "OK")
2371						{
2372							if ('happyflowgrowltext' in options)
2373							{
2374								var text = options.happyflowgrowltext;
2375								nxs_js_alert(text);
2376							}
2377							
2378							if (handlehappyflow)
2379							{
2380								handlehappyflow(response);
2381							}
2382							else
2383							{
2384								nxs_js_log("if you want to invoke a function, pass a function as handlehappyflow parameter");
2385							}
2386						}
2387						else
2388						{
2389							
2390							
2391							handlealternativeflow(response);
2392						}
2393					},
2394					error: function(response)
2395					{
2396						// dismiss loading growl if exists
2397						nxs_js_alert_wait_finish(waitgrowltoken);
2398						nxs_js_popup_notifyservererror();
2399						nxs_js_log(response);
2400						
2401						if ('errorflowgrowltext' in options)
2402						{
2403							var text = options.errorflowgrowltext;
2404							nxs_js_alert(text);
2405						}
2406
2407						if (handlefailureflow && getClass.call(handlefailureflow) == '[object Function]')
2408						{
2409							handlefailureflow(response);
2410						}
2411						else
2412						{
2413							nxs_js_log("if you want to invoke a function, pass a function as handlefailureflow parameter");
2414						}
2415					}										
2416				}
2417			);
2418		}
2419		
2420		function nxs_js_trash_article_no_question(postid)
2421		{		
2422			// invoke ajax call
2423			var ajaxurl = nxs_js_get_adminurladminajax();
2424			jQ_nxs.ajax
2425			(
2426				{
2427					type: 'POST',
2428					data: 
2429					{
2430						"action": "nxs_ajax_webmethods",
2431						"webmethod": "removepage",
2432						"postid": postid,
2433						"howto": "trash"
2434					},
2435					async: false,
2436					cache: false,
2437					dataType: 'JSON',
2438					url: ajaxurl, 
2439					success: function(response) 
2440					{
2441						nxs_js_log(response);
2442						if (response.result == "OK")
2443						{
2444							// ok
2445						}
2446						else
2447						{
2448							nxs_js_popup_notifyservererror();
2449							nxs_js_log(response);
2450						}
2451					},
2452					error: function(response)
2453					{
2454						nxs_js_popup_notifyservererror();
2455						nxs_js_log(response);
2456					}										
2457				}
2458			);
2459		}
2460
2461		function nxs_js_delete_article_no_question(postid)
2462		{
2463			// invoke ajax call
2464			var ajaxurl = nxs_js_get_adminurladminajax();
2465			jQ_nxs.ajax
2466			(
2467				{
2468					type: 'POST',
2469					data: 
2470					{
2471						"action": "nxs_ajax_webmethods",
2472						"webmethod": "removepage",
2473						"postid": postid,
2474						"howto": "permanent"
2475					},
2476					async: false,
2477					cache: false,
2478					dataType: 'JSON',
2479					url: ajaxurl, 
2480					success: function(response) 
2481					{
2482						nxs_js_log(response);
2483						if (response.result == "OK")
2484						{
2485							// ok
2486						}
2487						else
2488						{
2489							nxs_js_popup_notifyservererror();
2490							nxs_js_log(response);
2491						}
2492					},
2493					error: function(response)
2494					{
2495						nxs_js_popup_notifyservererror();
2496						nxs_js_log(response);
2497					}										
2498				}
2499			);
2500		}
2501		
2502		function nxs_js_delete_article(postid)
2503		{
2504			var answer = confirm(nxs_js_gettrans('Are you sure you want to delete this page?'));
2505			if (!answer)
2506			{
2507				return;
2508			}
2509			
2510			nxs_js_delete_article_no_question(postid);
2511		}
2512
2513		function nxs_js_restore_article(postid)
2514		{
2515			// invoke ajax call
2516			var ajaxurl = nxs_js_get_adminurladminajax();
2517			jQ_nxs.ajax
2518			(
2519				{
2520					type: 'POST',
2521					data: 
2522					{
2523						"action": "nxs_ajax_webmethods",
2524						"webmethod": "restorepage",
2525						"postid": postid
2526					},
2527					async: false,
2528					cache: false,
2529					dataType: 'JSON',
2530					url: ajaxurl, 
2531					success: function(response) 
2532					{
2533						nxs_js_log(response);
2534						if (response.result == "OK")
2535						{
2536							// ok
2537						}
2538						else
2539						{
2540							nxs_js_popup_notifyservererror();
2541							nxs_js_log(response);
2542						}
2543					},
2544					error: function(response)
2545					{
2546						nxs_js_popup_notifyservererror();
2547						nxs_js_log(response);
2548					}										
2549				}
2550			);
2551		}			
2552		
2553		function nxs_js_popup_placeholder_wipe(postid, placeholderid)
2554		{
2555			nxs_js_log('Warning; obsolete function used; nxs_js_popup_placeholder_wipe(postid, placeholderid)');
2556			var widget = nxs_js_getwidgetinpostid(postid, placeholderid);
2557			nxs_js_popup_wipe_widget(widget);
2558		}
2559		
2560		function nxs_js_popup_wipe_closestwidgetindom(dom)
2561		{
2562			// first find the placeholder, then within the placeholder find the nxs-widget
2563			var placeholder = jQ_nxs(dom).closest(".nxs-placeholder");
2564			var widget = jQ_nxs(placeholder).find(".nxs-widget")[0];
2565			nxs_js_popup_wipe_widget(widget);
2566		}
2567		
2568		function nxs_js_frontendediting_widgethandledelete(placeholderdom)
2569		{
2570			var postid = nxs_js_findclosestpostid_for_dom(placeholderdom);
2571			var widget = placeholderdom;
2572			var placeholderid = jQ_nxs(widget).attr("id").split("-")[2];
2573			var rowindex = nxs_js_getrowindex(widget);
2574			var widgetelement = nxs_js_getwidgetelement_forplaceholder(postid, placeholderid);				
2575			var placeholderelement = jQ_nxs(placeholderdom).closest(".nxs-placeholder")[0];
2576			var defaultelement = jQ_nxs(placeholderelement).find(".nxs-defaultwidgetdeletehandler");
2577			if (defaultelement.length >= 1)
2578			{
2579				// ja, er is een default element gedefinieerd
2580				jQ_nxs(defaultelement).click();
2581			}
2582			else
2583			{
2584				nxs_js_log("Fallback scenario; no default delete handler found for this widget, explicity deleting this widget instead.");
2585				// nee, er is geen default gedrag gedefinieerd; wipe widget
2586				nxs_js_popup_wipe_widget(widget);
2587			}
2588		}
2589		
2590		function nxs_js_popup_wipe_widget(widget)
2591		{
2592			var postid = nxs_js_findclosestpostid_for_dom(widget);
2593			var placeholderid = nxs_js_getplaceholderidofwidgetdom(widget);
2594
2595			// verwijdert de placeholder
2596			var answer = confirm(nxs_js_gettrans('Are you sure you want to remove this widget?'));
2597			if (answer)
2598			{
2599				var waitgrowltoken = nxs_js_alert_wait_start(nxs_js_gettrans('Wiping element'));
2600				
2601				// invoke ajax call
2602				var ajaxurl = nxs_js_get_adminurladminajax();
2603				jQ_nxs.ajax
2604				(
2605					{
2606						type: 'POST',
2607						data: 
2608						{
2609							"action": "nxs_ajax_webmethods",
2610							"webmethod": "wipeplaceholder",
2611							"postid": postid,
2612							"placeholderid": placeholderid
2613						},
2614						cache: false,
2615						dataType: 'JSON',
2616						url: ajaxurl, 
2617						success: function(response) 
2618						{
2619							nxs_js_alert_wait_finish(waitgrowltoken);
2620							
2621							//nxs_js_log(response);
2622							if (response.result == "OK")
2623							{
2624								nxs_js_alert(nxs_js_gettrans('Widget is now empty'));
2625								
2626								// update screen
2627								nxs_js_rerender_row_for_placeholder(postid, placeholderid);
2628							}
2629							else
2630							{
2631								nxs_js_popup_notifyservererror();
2632								nxs_js_log(response);
2633							}
2634						},
2635						error: function(response)
2636						{
2637							nxs_js_alert_wait_finish(waitgrowltoken);
2638							
2639							nxs_js_popup_notifyservererror();
2640							nxs_js_log(response);
2641						}										
2642					}
2643				);			
2644			}
2645			else
2646			{
2647				// nop
2648			}
2649		}
2650		
2651		function nxs_js_refreshallpagerows(postid, containerElement, invokewhenavailable)
2652		{
2653			var rendermode = "default";
2654			var containerpostid = nxs_js_getcontainerpostid();
2655			nxs_js_rows_render(containerpostid, postid, rendermode, function(html)
2656			{
2657				jQ_nxs(containerElement).html(html);
2658				// reenable all events
2659				nxs_js_reenable_all_window_events();
2660				
2661				invokewhenavailable();
2662				jQuery(document).trigger('nxs_dom_changed');
2663			});
2664		}
2665		
2666		function nxs_js_refreshelementscontainerforelement(element, rendermode, invokewhenavailable)
2667		{
2668			// derive postid to be refreshed
2669			var containerElement = jQ_nxs(element).closest(".nxs-elements-container");
2670			var cursorofelementscontainer = jQ_nxs(containerElement).find(".nxs-elements-cursor");
2671			var elementtoreplace = jQ_nxs(containerElement).find(".nxs-postrows");
2672			var elementspostid = jQ_nxs(cursorofelementscontainer).attr("id").split("-")[2];
2673			var containerpostid = nxs_js_getcontainerpostid();
2674			
2675			//nxs_js_log("containerpostid;" + containerpostid);
2676			//nxs_js_log("elementspostid;" + elementspostid);
2677			// gjgj
2678			nxs_js_rows_render(containerpostid, elementspostid, rendermode, function(html)
2679			{
2680				jQ_nxs(elementtoreplace).replaceWith(html);
2681				// reenable all events
2682				nxs_js_reenable_all_window_events();
2683				
2684				invokewhenavailable();
2685			});
2686		}
2687		
2688		function nxs_js_rows_render(containerpostid, postid, rendermode, invokewhenavailable)
2689		{
2690			var ajaxurl = nxs_js_get_adminurladminajax();
2691			jQ_nxs.ajax
2692			(
2693				{
2694					type: 'POST',
2695					data: 
2696					{
2697						"action": "nxs_ajax_webmethods",
2698						"webmethod": "getcontent",
2699						"clientpopupsessioncontext": nxs_js_getescaped_popupsession_context(),
2700						"contenttype": "rows",
2701						"contentcontext": "rows_" + containerpostid + "_" + postid + "_" + rendermode,
2702						"clientqueryparameters": nxs_js_escaped_getqueryparametervalues()
2703					},
2704					async: false,
2705					cache: false,
2706					dataType: 'JSON',
2707					url: ajaxurl, 
2708					success: function(response) 
2709					{
2710						nxs_js_log(response);
2711						if (response.result == "OK")
2712						{
2713							invokewhenavailable(response.html);
2714						}
2715						else
2716						{
2717							nxs_js_popup_notifyservererror();
2718							nxs_js_log(response);
2719						}
2720					},
2721					error: function(response)
2722					{
2723						nxs_js_popup_notifyservererror();
2724						nxs_js_log(response);
2725					}
2726				}
2727			);
2728		}
2729
2730		// removes the row to which this domelement belongs
2731		// after asking for confirmation. This also updates the dom
2732		function nxs_js_row_remove(domelement)
2733		{
2734      //
2735			var postid = nxs_js_findclosestpostid_for_dom(domelement);
2736			var rowindex = nxs_js_getrowindex(domelement);
2737			var rowid = nxs_js_getrowid(domelement);
2738			var closestrow = jQ_nxs(domelement).closest('.nxs-row'); // find the row that is going to be deleted
2739      var widgetid = jQ_nxs(closestrow).find('.nxs-widget').attr('id');
2740			var num_of_menus_in_row = jQ_nxs(closestrow).find('.nxs-menu').length; // find if there is a menu in the specific row that is going to be deleted
2741			var firstconfirm = confirm(nxs_js_gettrans('Are you sure you want to delete this row?'));
2742				
2743			if(num_of_menus_in_row > 0){ // if there are menus in the row, give a confirm-dialog
2744				var secondconfirm = confirm(nxs_js_gettrans('There is a menu in this row, are you really sure you want to delete this row?'));
2745			}
2746			
2747			var shoulddotheactualdelete = false; // no deleting yet
2748			
2749			if(firstconfirm && (num_of_menus_in_row == 0)){ // first confirm is given and there are no menus in row
2750					shoulddotheactualdelete = true; // row can be deleted
2751			} else if((firstconfirm && (num_of_menus_in_row >
2751 0)) && secondconfirm){ // first confirm is given but there are menus in the row, so the second confirm is given
2752					shoulddotheactualdelete = true; // row can be deleted
2753			}
2754	
2755			if (shoulddotheactualdelete)
2756			{
2757				var waitgrowltokenx = nxs_js_alert_wait_start(nxs_js_gettrans('Removing row'));
2758				
2759				// invoke ajax call
2760				var ajaxurl = nxs_js_get_adminurladminajax();
2761				jQ_nxs.ajax
2762				(
2763					{
2764						type: 'POST',
2765						data: 
2766						{
2767							"action": "nxs_ajax_webmethods",
2768							"webmethod": "removerow",
2769							"postid": postid,
2770							"rowindex": rowindex,
2771							"rowid": rowid,
2772              "widgetid": widgetid
2773						},
2774						cache: false,
2775						dataType: 'JSON',
2776						url: ajaxurl, 
2777						success: function(response) 
2778						{
2779							nxs_js_alert_wait_finish(waitgrowltokenx);
2780							nxs_js_log(response);
2781							
2782							if (response.result == "OK")
2783							{
2784								if (response.pagedirty == "true")
2785								{
2786									var waitgrowltokenb = nxs_js_alert_wait_start(nxs_js_gettrans('Refreshing page'));
2787									
2788									// het hele scherm moet worden bijgewerkt (dit is het geval
2789									// wanneer bijvoorbeeld de laatste row is verwijderd,
2790									// en het systeem automatisch een nieuwe row heeft toegevoegd (rowsetup) 
2791									var containerElement = jQ_nxs(".nxs-post-" + postid)[0];		
2792									nxs_js_refreshallpagerows(postid, containerElement, function()
2793									{
2794										nxs_js_alert_wait_finish(waitgrowltokenb);
2795									});
2796								}
2797								else
2798								{
2799									nxs_js_log("row deleted succesfully, index: rowindex:" + rowindex);
2800									
2801									// update GUI
2802									if (false) // rowindex == 0)
2803									{
2804										var waitgrowltokenc = nxs_js_alert_wait_start(nxs_js_gettrans('Refreshing page'));
2805										
2806										// indien de eerste regel was gedelete moeten we de
2807										// regel daaronder (die nu dus de eerste regel is
2808										// geworden) refreshen, voor nu even eenvoudig opgelost
2809										// door het hele editable deel te verversen
2810										var containerElement = jQ_nxs(".nxs-post-" + postid)[0];
2811										
2812										nxs_js_refreshallpagerows(postid, containerElement, function()
2813										{
2814											nxs_js_alert_wait_finish(waitgrowltokenc);
2815										});
2816									}
2817									else
2818									{
2819										var waitgrowltokend = nxs_js_alert_wait_start(nxs_js_gettrans('Refreshing page'));
2820										var row = jQ_nxs(domelement).closest('.nxs-row');
2821										jQ_nxs(document).trigger('nxs_dom_changed');
2822										jQ_nxs(row).slideUp('slow', 
2823
2824										function()
2825										{
2826											jQ_nxs(row).remove();
2827											nxs_js_alert_wait_finish(waitgrowltokend);
2828											// de hoogte is aangepast, pas ook de sidebar hoogte aan (indien nodig)
2829											nxs_js_reenable_all_window_events();
2830										}
2831									);
2832									}
2833									//
2834								}
2835							}
2836							else
2837							{
2838								nxs_js_alert_wait_finish(waitgrowltoken);
2839								
2840								nxs_js_popup_notifyservererror();
2841								nxs_js_log(response);
2842							}
2843						},
2844						error: function(response)
2845						{
2846							nxs_js_alert_wait_finish(waitgrowltoken);
2847							nxs_js_popup_notifyservererror();
2848							nxs_js_log(response);
2849						}										
2850					}
2851				);			
2852			}
2853			else
2854			{
2855				// nop
2856			}
2857		}
2858		
2859		
2860		
2861		function nxs_js_menuitem_remove(postid, element)
2862		{
2863			var rowindex = nxs_js_getrowindex(element);
2864			// verwijdert de row
2865			var answer = confirm(nxs_js_gettrans('Are you sure you want to delete this menu item?'));
2866			if (answer)
2867			{
2868				var waitgrowltoken = nxs_js_alert_wait_start(nxs_js_gettrans('Removing row'));
2869				
2870				// invoke ajax call
2871				var ajaxurl = nxs_js_get_adminurladminajax();
2872				jQ_nxs.ajax
2873				(
2874					{
2875						type: 'POST',
2876						data: 
2877						{
2878							"action": "nxs_ajax_webmethods",
2879							"webmethod": "removemenuitem",
2880							"postid": postid,
2881							"rowid": rowindex
2882						},
2883						cache: false,
2884						dataType: 'JSON',
2885						url: ajaxurl, 
2886						success: function(response) 
2887						{
2888							nxs_js_alert_wait_finish(waitgrowltoken);
2889							nxs_js_log(response);
2890							
2891							var containerElement = jQ_nxs(".nxs-post-" + postid)[0];
2892							jQ_nxs(containerElement).html(response.html);
2893							// reenable all events
2894							nxs_js_reenable_all_window_events();
2895							nxs_js_alert(nxs_js_gettrans('Refreshed'));
2896						},
2897						error: function(response)
2898						{
2899							nxs_js_alert_wait_finish(waitgrowltoken);
2900							nxs_js_popup_notifyservererror();
2901							nxs_js_log(response);
2902						}										
2903					}
2904				);			
2905			}
2906			else
2907			{
2908				// nop
2909			}
2910		}
2911
2912		function nxs_js_reenable_all_window_events()
2913		{
2914			if (!nxs_js_enableguieffects())
2915			{
2916				// no further processing
2917				return;
2918			}
2919		
2920			nxs_js_reregister_click_and_hover_events();
2921			nxs_js_gui_setup_drag_listeners();
2922			
2923			// ensure that each img that finishes loading after we set the runtime
2924			// dimensions will trigger the runtime dimensions to be recalculated...
2925			jQ_nxs('img').load
2926			(
2927				function()
2928				{
2929					//nxs_js_log('debug; finished loading img after reenabling all windows events; solved bug');
2930					nxs_gui_set_runtime_dimensions_enqueuerequest("nxs-framework-imgloaded");
2931				}
2932			);
2933			
2934			nxs_gui_set_runtime_dimensions_enqueuerequest("nxs-framework-windoweventsreenabled");
2935
2936			if (nxs_js_userhasadminpermissions())
2937			{
2938				// als de gebruiker admin is, start het scherm altijd in edit modus,
2939				// hierbij staan we niet toe dat er tekst wordt geselecteerd
2940				if (nxs_js_nxseditoractive)
2941				{
2942					jQ_nxs('body').disableSelection();
2943				}
2944				else
2945				{
2946					jQ_nxs('body').enableSelection();
2947				}
2948			}
2949			//nxs_js_log('runtime dimensions set');	
2950		}
2951
2952		function nxs_gui_set_runtime_dimensions_enqueuerequest(trigger)
2953		{		
2954			//nxs_js_log('enqueued for:' + trigger);
2955		
2956			var skip = false;
2957			if (nxs_js_isruntimedimensionsrefreshqueued())
2958			{
2959				// already enqueued, mark to skip this request,
2960				// note we wont return yet, as we first need to mark that
2961				// the enqueue also involves the specified trigger
2962				skip = true;
2963			}
2964			
2965			var triggerarray;
2966			// convert trigger to array
2967			if (typeof trigger == 'string' || trigger instanceof String)
2968			{
2969				triggerarray = [trigger];
2970			}
2971			else if ($.isArray(trigger))
2972			{
2973				triggerarray = trigger;
2974				if (triggerarray.length == 0)
2975				{
2976					nxs_js_alert('Warning, trigger array is empty');
2977					nxs_js_log(trigger);
2978					return;	
2979				}
2980			}
2981			else
2982			{
2983				nxs_js_alert('Warning, unsupported trigger type');
2984				nxs_js_log(trigger);
2985				return;
2986			}
2987			
2988			for (var i = 0; i < triggerarray.length; i++) 
2989			{
2990			  var currenttrigger = triggerarray[i];
2991			  if (!nxs_js_isrefreshqueuetriggeredby(currenttrigger))
2992				{
2993					// mark as triggered for this specific trigger
2994					nxs_js_queuedruntimedimensionsrefreshtriggers.push(currenttrigger);
2995				}
2996				else
2997				{
2998					skip = true;
2999				}
3000			}
3001			
3002			if (skip)
3003			{
3004				return;
3005			}
3006			
3007			// if we reach this point, it means this is the first enqueued request
3008			var nxs_max_refresh_frequency_in_msecs = 100;	// lower this amount to get a snappier speed, but poorer performance, 100 = default
3009			setTimeout
3010			(
3011				function() 
3012				{
3013					//nxs_js_log('executing actual refresh work');
3014					// first we dequeue! 
3015					nxs_gui_set_runtime_dimensions_actualrequest();
3016				},nxs_max_refresh_frequency_in_msecs
3017			);
3018		}
3019		
3020		function nxs_js_getheightoftallestwidgetwithindomelement(domelement)
3021		{
3022			return nxs_js_getheightoftallestwidgetwithindomelement_v2(domelement, ".XYZ");
3023		}
3024		
3025		function nxs_js_getheightoftallestwidgetwithindomelement_v2(domelement, innerselector)
3026		{
3027			var domelements = jQ_nxs(domelement).find(innerselector);
3028			var result = 0;
3029			jQuery.each(domelements, function(index, currentdomelement)
3030			{
3031				var height = jQ_nxs(currentdomelement).outerHeight(true);
3032				if (height > result)
3033				{
3034					result = height;
3035				}
3036			}
3037			);
3038			return result;
3039		}
3040		
3041		// kudos to http://stackoverflow.com/questions/5503900/how-to-sort-an-array-of-objects-with-jquery-or-javascript
3042		function nxs_js_sortbyname(a, b){
3043		  var aName = a.toLowerCase();
3044		  var bName = b.toLowerCase(); 
3045		  return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
3046		}
3047		
3048		function nxs_js_shouldsetelementheight(element)
3049		{
3050			var result = true;
3051		
3052			if (jQ_nxs(element).hasClass("nxs-column-1-1"))
3053			{
3054				result = false;
3055			}
3056			else if (jQ_nxs(element).hasClass("nxs-widgettype-twittertweets"))
3057			{
3058				result = false;
3059			}
3060			else if (jQ_nxs(element).hasClass("nxs-widgettype-fblikebox"))
3061			{
3062				result = false;
3063			}
3064		
3065			return result;	
3066		}
3067		
3068		function nxs_js_alignheightofelementswithindomelement(domelement, innerselector)
3069		{
3070			//nxs_js_log('aligning height for row');
3071		
3072			var domelements = jQ_nxs(domelement).find(innerselector);
3073			
3074			var heighest = 0;
3075			jQuery.each(domelements, function(index, currentdomelement)
3076			{
3077				var currentheight = jQ_nxs(currentdomelement).outerHeight(true);
3078				if (currentheight > heighest)
3079				{
3080					heighest = currentheight;
3081					//nxs_js_log('new heighest:' + heighest);
3082				}
3083			}
3084			);
3085			
3086			jQuery.each(domelements, function(index, currentdomelement)
3087			{
3088				//nxs_js_log("align heights of elements to: " + heighest);
3089				jQ_nxs(currentdomelement).height(heighest);
3090			}
3091			);
3092		}
3093		
3094		function nxs_gui_set_runtime_dimensions_actualrequest()
3095		{
3096			var scrollrevertid = nxs_js_ui_pushscrollrevert();
3097		
3098			// todo: this can be optimized: the tagging of columns only has to occur when
3099			// the page is loaded, and after the core structure of the page is modified
3100			// basically when widgets/rows/containers are refreshed after a modification (delete, edit, drag... )
3101			// for now its most save to always invoke the method
3102			nxs_js_tagcolumns();
3103		
3104			// make clone of enqueued triggers
3105			nxs_js_runtimedimensionsrefreshtriggers = nxs_js_queuedruntimedimensionsrefreshtriggers.slice(0);
3106			
3107			// clear the enqueued triggers
3108			nxs_js_queuedruntimedimensionsrefreshtriggers = new Array();
3109			
3110			// verify that at least one trigger is set
3111			if (nxs_js_runtimedimensionsrefreshtriggers.length == 0)
3112			{
3113				// no trigger set?
3114				nxs_js_log('please set a trigger, absorbing this request');
3115				return;
3116			}
3117			else
3118			{
3119				//nxs_js_log('performing actual request, made by trigger(s):');
3120				//nxs_js_log(nxs_js_runtimedimensionsrefreshtriggers);
3121			}
3122		
3123			// stap 1; we resetten de hoogten, breedten en margins
3124			// deze undo-stap is belangrijk; als bijv. een lege placeholder naast een gevulde
3125			// placeholder staat, en de plapceholder er naast wordt korter door een modificatie,
3126			// dan zou de undefined placeholder de hoogte de hoogte row beinvloeden doordat
3127			// de hoogte reeds gezet is; dit is ongewenst. We verwijderen dus
3128			// allereerst de breedte en hoogtes van cellen die 'autocellsize' zijn.
3129			
3130			jQ_nxs(".nxs-valign-middle").css('margin-top', 0);
3131			jQ_nxs(".nxs-valign-bottom").css('margin-top', 0);
3132			
3133			jQuery.each
3134			(
3135				jQ_nxs(".nxs-runtime-autocellsize"), function(index, element)
3136				{
3137					// heights					
3138					if (jQ_nxs(element).hasClass("nxs-minheight"))
3139					{
3140						if (jQ_nxs(element).hasClass("nxs-minheight-40-0"))
3141						{
3142							jQ_nxs(element).css('height', '40');	// defaults to height when no height is set
3143						}
3144						else if (jQ_nxs(element).hasClass("nxs-minheight-80-0"))
3145						{
3146							jQ_nxs(element).css('height', '80');	// defaults to height when no height is set
3147						}
3148						else if (jQ_nxs(element).hasClass("nxs-minheight-120-0"))
3149						{
3150							jQ_nxs(element).css('height', '120');	// defaults to height when no height is set
3151						}
3152						else if (jQ_nxs(element).hasClass("nxs-minheight-160-0"))
3153						{
3154							jQ_nxs(element).css('height', '160');	// defaults to height when no height is set
3155						}
3156						else if (jQ_nxs(element).hasClass("nxs-minheight-200-0"))
3157						{
3158							jQ_nxs(element).css('height', '200');	// defaults to height when no height is set
3159						}
3160						else if (jQ_nxs(element).hasClass("nxs-minheight-240-0"))
3161						{
3162							jQ_nxs(element).css('height', '240');	// defaults to height when no height is set
3163						}
3164						else if (jQ_nxs(element).hasClass("nxs-minheight-280-0"))
3165						{
3166							jQ_nxs(element).css('height', '280');	// defaults to height when no height is set
3167						}
3168						else if (jQ_nxs(element).hasClass("nxs-minheight-320-0"))
3169						{
3170							jQ_nxs(element).css('height', '320');	// defaults to height when no height is set
3171						}
3172						else if (jQ_nxs(element).hasClass("nxs-minheight-360-0"))
3173						{
3174							jQ_nxs(element).css('height', '360');	// defaults to height when no height is set
3175						}
3176						else if (jQ_nxs(element).hasClass("nxs-minheight-400-0"))
3177						{
3178							jQ_nxs(element).css('height', '400');	// defaults to height when no height is set
3179						}
3180						else if (jQ_nxs(element).hasClass("nxs-minheight-440-0"))
3181						{
3182							jQ_nxs(element).css('height', '440');	// defaults to height when no height is set
3183						}
3184						else if (jQ_nxs(element).hasClass("nxs-minheight-480-0"))
3185						{
3186							jQ_nxs(element).css('height', '480');	// defaults to height when no height is set
3187						}
3188						else
3189						{
3190							nxs_js_log('warning; min height not (yet?) supported');
3191							jQ_nxs(element).height(88);	// defaults to height when no height is set
3192						}
3193					}
3194					else
3195					{
3196						// afhankelijk van of de editor aan- of uitstaat...
3197						if (nxs_js_nxseditoractive)
3198						{
3199							if (!nxs_js_shouldsetelementheight(element))
3200							{
3201								// if a row has just one column, we wont set the height of the row
3202								// to allow DOM updates to not mess up the layout
3203							}
3204							else
3205							{
3206								jQ_nxs(element).height(87);	// defaults to height when no height is set
3207							}
3208						}
3209						else
3210						{
3211							if (!nxs_js_shouldsetelementheight(element))
3212							{
3213								// if a row has just one column, we wont set the height of the row
3214								// to allow DOM updates to not mess up the layout
3215							}
3216							else
3217							{
3218								//nxs_js_log("c) setting height to 0");
3219								jQ_nxs(element).height(0);	// defaults to height when no height is set
3220							}
3221						}
3222					}
3223					
3224					// any future resetting ...
3225				}
3226			);
3227			
3228			//nxs_js_log('broadcasting event nxs_recalculateruntimedimensions_afterclear');
3229						
3230			var widthofbrowserwindow = jQ_nxs(window).width();
3231			// nxs_js_log("width of browser:" + widthofbrowserwindow);
3232			
3233			// revert heights set previous time
3234			// reset heigthiq heights
3235			// als we deze regel hieronder uitcommentarieren ontstaat het probleem
3236			// dat de browser omhoog scrollt indien slider2 wordt gebruikt
3237			// jQ_nxs(".nxs-heightiq").css({height:""});
3238			
3239			// allow widgets and/or plugins to extend the functionality of this function (act / bind to the hook / event)
3240  			jQ_nxs(window).trigger('nxs_recalculateruntimedimensions_afterclear');
3241
3242			// reset heights of placeholder elements
3243			jQ_nxs(".nxs-dyn-height").css('height', 'auto').removeClass("nxs-dyn-height");
3244
3245			var arerowsspreadalongmultirows = (widthofbrowserwindow <= 959);
3246			
3247			if (!arerowsspreadalongmultirows)
3248			{
3249				jQ_nxs("html").addClass("nxs-rows-nonresponsive");
3250				jQ_nxs("html").removeClass("nxs-rows-responsive");
3251			
3252				//nxs_js_log('regular - valign is active');
3253				
3254				// step 2; derive heights on a per-row basis, and set the heights of the nxs-runtime-autocellsizes
3255				jQuery.each
3256				(
3257					jQ_nxs(".nxs-row"), 
3258					function(index, rowelement)
3259					{						
3260						jQ_nxs(rowelement).find(".nxs-heightiq").css({height:""});
3261					
3262						// get list of "things" to align
3263						var distinctheightiqtypes = nxs_js_finddistinctclassidentifications(rowelement, "nxs-heightiq");
3264						// order items
3265						distinctheightiqtypes.sort(nxs_js_sortbyname);
3266						for (var i = 0; i < distinctheightiqtypes.length; i++)
3267						{
3268							var distinctheightiqtype = distinctheightiqtypes[i];	// bijv. "title"
3269							// nxs_js_log("distinctheightiqtype:" + distinctheightiqtype);
3270							nxs_js_alignheightofelementswithindomelement(rowelement, ".nxs-heightiq-" + distinctheightiqtype);
3271						}
3272						
3273						// determine height for each individual row; 
3274						// the height will be set to the height of the tallest widget 
3275						// within that specific row
3276						var heighestHeightInRow = nxs_js_getheightoftallestwidgetwithindomelement(rowelement);
3277						if (heighestHeightInRow == 0)
3278						{
3279							if (nxs_js_nxseditoractive)
3280							{
3281								// if all widgets are "empty" and the editor is active we will default to 81 pixels
3282								heighestHeightInRow = 81;
3283							}
3284							else
3285							{
3286								// suppress the row!
3287								// jQ_nxs(rowelement).addClass('nxs-suppress');
3288							}
3289						}
3290						
3291						// set height for all elements within this row
3292						var elementsToBeResized = jQ_nxs(rowelement).find(".nxs-runtime-autocellsize");
3293						jQuery.each(elementsToBeResized, function(index, element)
3294						{
3295							// houdt er rekening mee of de parent class een nxs-margin-bottom20 class heeft,
3296							// indien zo, dan moet de height 20 korter worden!
3297	
3298							var shouldshrinkforborder = false;
3299							if (jQ_nxs(element).hasClass("autosize-smaller"))
3300							{
3301								shouldshrinkforborder = true;
3302							}
3303							
3304							var numofmarginbottoms = jQ_nxs(element).closest(".nxs-placeholder").find(".nxs-margin-bottom20").length;
3305							var hasextendedmarginbottom = (numofmarginbottoms > 0);
3306							var shouldshorten = (hasextendedmarginbottom == true);
3307	
3308							var heightToSet = heighestHeightInRow;
3309							if (shouldshorten)
3310							{
3311								heightToSet = heightToSet - 20;
3312							}
3313							if (shouldshrinkforborder)
3314							{
3315								heightToSet = heightToSet - 2;
3316							}
3317							
3318							if (!nxs_js_shouldsetelementheight(element))
3319							{
3320								// absorb; if a row has just one column, there's no advantage
3321								// of setting the height. To allow DOM updates in the widget
3322								// to be reflected we dont set the height
3323							}
3324							else
3325							{
3326								//nxs_js_log("b) setting height to :" + heightToSet);
3327								jQ_nxs(element).height(heightToSet);
3328							}
3329						}
3330						);
3331						
3332						//nxs_js_log("heighest row:");
3333						//nxs_js_log(heighestHeightInRow);
3334						
3335						
3336						// set valign
3337						var innerplaceholders = jQ_nxs(rowelement).find(".XYZ");
3338						jQuery.each(innerplaceholders, function(index, currentinnerplaceholder)
3339						{
3340							var currentHeight = jQ_nxs(currentinnerplaceholder).outerHeight(true);
3341							
3342							// bottom
3343							var toBeValigned = jQ_nxs(currentinnerplaceholder).parent().find(".nxs-valign-bottom");
3344							jQuery.each(toBeValigned, function(index, currentToBeValigned)
3345							{
3346								//nxs_js_log("found");
3347															
3348								var deltaheight = heighestHeightInRow - currentHeight;
3349								//nxs_js_log("delta:" + deltaheight);
3350								jQ_nxs(currentToBeValigned).css('margin-top', deltaheight);
3351							});
3352							
3353							// middle
3354							var toBeValigned = jQ_nxs(currentinnerplaceholder).parent().find(".nxs-valign-middle");
3355							jQuery.each(toBeValigned, function(index, currentToBeValigned)
3356							{
3357								//nxs_js_log("found");
3358								var deltaheight = Math.floor((heighestHeightInRow - currentHeight) / 2);
3359								//nxs_js_log("delta:" + deltaheight);
3360								jQ_nxs(currentToBeValigned).css('margin-top', deltaheight);
3361							});
3362						}
3363						);
3364					}
3365				);
3366			}
3367			else
3368			{
3369				//nxs_js_log("scenario applies!!");
3370				
3371				jQ_nxs("html").addClass("nxs-rows-responsive");
3372				jQ_nxs("html").removeClass("nxs-rows-nonresponsive");
3373			
3374				// nxs_js_log('spread across multiple rows');	
3375				// rows are potentially spread across multiple rows; we should not set heights in that case
3376				
3377				// reset heights of heightiq elements
3378				jQ_nxs(".nxs-heightiq").css('height', 'auto');
3379				
3380				jQuery.each
3381				(
3382					jQ_nxs(".nxs-row"), 
3383					function(index, rowelement)
3384					{
3385						var columnindex = 1;
3386					
3387						// set height
3388						var innerplaceholders = jQ_nxs(rowelement).find(".XYZ");
3389						jQuery.each
3390						(
3391							innerplaceholders, function(index, currentinnerplaceholder)
3392							{
3393								jQ_nxs(currentinnerplaceholder).css('height', 'auto');
3394								jQ_nxs(currentinnerplaceholder).css('margin-top', '0');
3395								var height = jQ_nxs(currentinnerplaceholder).outerHeight(true);
3396								
3397								var element = jQ_nxs(currentinnerplaceholder).closest('.nxs-placeholder');
3398								jQ_nxs(element).each
3399								(
3400									function(index)
3401									{
3402										var element = this;
3403										if (nxs_js_shouldsetelementheight(element))
3404										{
3405											jQ_nxs(element).css('height', height).addClass("nxs-dyn-height");
3406											//nxs_js_log("f) setting height to: " + height);
3407										}
3408										else
3409										{
3410											// skip the element
3411										}
3412									}
3413								);
3414							}
3415						);
3416					}
3417				);
3418			}
3419			
3420			// step 3; (re) initialize google maps (if present)
3421			// todo: move this implementation to google maps widget...
3422			for (mapkey in nxs_js_maps)
3423			{
3424				if (!nxs_js_maps.hasOwnProperty(mapkey)) 
3425				{
3426					continue;
3427				}
3428				
3429				//nxs_js_log('resizing mapkey:' + mapkey);
3430				var center = nxs_js_maps[mapkey].getCenter();
3431				google.maps.event.trigger(nxs_js_maps[mapkey], 'resize'); 
3432				nxs_js_maps[mapkey].setCenter(center); 
3433			}
3434			
3435			//
3436			// automatically fit cursors that have a "nxs-autofit-to-parent" class
3437			// to the size of their parents 
3438			// 
3439			//nxs_js_log('auto fitting...');
3440			jQ_nxs(".nxs-autofit-to-parent").each
3441			(
3442				function(index)
3443				{
3444					var parent = jQ_nxs(this).parent();
3445					var width = jQ_nxs(parent).outerWidth(true);
3446					jQ_nxs(this).width(width);
3447					var height = jQ_nxs(parent).outerHeight(true);
3448					//nxs_js_log('d) height will be set to: ' + height);
3449					jQ_nxs(this).height(height);
3450				}
3451			);
3452
3453			//nxs_js_log('broadcasting event nxs_recalculateruntimedimensions');
3454			
3455			// allow widgets and/or plugins to extend the functionality of this function (act / bind to the hook / event)
3456  		jQ_nxs(window).trigger('nxs_recalculateruntimedimensions');
3457  		jQ_nxs(document).trigger('nxs_dom_changed');
3458  		
3459			nxs_js_ui_popscrollrevert(scrollrevertid);
3460		}
3461		
3462		function nxs_js_isrefreshtriggeredbyatleastoneof(trigger)
3463		{
3464			var triggerarray;
3465			// convert trigger to array
3466			if (typeof trigger == 'string' || trigger instanceof String)
3467			{
3468				triggerarray = [trigger];
3469			}
3470			else if (jQuery.isArray(trigger))
3471			{
3472				triggerarray = trigger;
3473				if (triggerarray.length == 0)
3474				{
3475					nxs_js_alert('Warning, trigger array is empty');
3476					nxs_js_log(trigger);
3477					return;	
3478				}
3479			}
3480			else
3481			{
3482				nxs_js_alert('Warning, unsupported trigger type');
3483				nxs_js_log(trigger);
3484				return;
3485			}
3486		
3487			var result = false;
3488			
3489			for (var i = 0; i < triggerarray.length; i++) 
3490			{
3491			  var currenttrigger = triggerarray[i];
3492				if (jQuery.inArray(currenttrigger, nxs_js_runtimedimensionsrefreshtriggers) > -1)
3493				{
3494					result = true;
3495				}
3496			}
3497			
3498			//nxs_js_log('question for ' + trigger + ' is ' + result);
3499			return result;
3500		}
3501		
3502		function nxs_js_isrefreshqueuetriggeredby(trigger)
3503		{
3504			var result = jQuery.inArray(trigger, nxs_js_queuedruntimedimensionsrefreshtriggers) > -1
3505			//nxs_js_log('question for queued ' + trigger + ' is ' + result);
3506			return result;
3507		}
3508		
3509		function nxs_js_isruntimedimensionsrefreshqueued()
3510		{
3511			return nxs_js_queuedruntimedimensionsrefreshtriggers.length > 0;
3512		}
3513		
3514		function nxs_js_getgrowlscripturl()
3515		{
3516			return nxs_js_getframeworkurl() + '/js/growl/jquery.jgrowl.x.js';
3517		}
3518		
3519		function nxs_js_htmldialogmessageok(title, html)
3520		{
3521			nxs_js_htmldialogmessageok_v2(title, html, "basic");
3522		}
3523		
3524		// custompopup custom popup htmlpopup html popup popup custom
3525		function nxs_js_htmldialogmessageok_v2(title, html, scaffoldingtype)
3526		{
3527			// show a popup
3528			nxs_js_popupsession_startnewcontext();
3529			nxs_js_popup_setsessioncontext("contextprocessor", "site");
3530			nxs_js_popup_setsessiondata("nxs_customhtml_scaffoldingtype", scaffoldingtype);
3531			nxs_js_popup_setsessiondata("nxs_customhtml_popupheadertitle", title);
3532			nxs_js_popup_setsessiondata("minwidth", "368");
3533			nxs_js_popup_setsessiondata("nxs_customhtml_customhtmlcanvascontent", html);
3534			nxs_js_popup_navigateto("customhtml");
3535		}
3536		
3537		function nxs_js_alert_sticky(text)
3538		{
3539			jQ_nxs.jGrowl(text, { sticky: true });
3540		}
3541		
3542		//
3543		//
3544		//
3545		
3546		function nxs_js_alert(text)
3547		{
3548			nxs_js_log("alerting:" + text);
3549			jQ_nxs.jGrowl(text, { sticky: false, life: 3000 });
3550		}
3551		
3552		//
3553		//
3554		//
3555		
3556		function nxs_js_alert_veryshort(text)
3557		{
3558			nxs_js_log("alerting very short:" + text);
3559			jQ_nxs.jGrowl(text, { sticky: false, life: 1000 });
3560		}
3561		
3562		//
3563		//
3564		//
3565		
3566				
3567		function nxs_js_alert_wait_start(message)
3568		{
3569			//nxs_js_log("nxs_js_getframeworkurl():" + nxs_js_get_frameworkurl());
3570			//nxs_js_log("alerting wait start:" + message);
3571			var stacktrace = nxs_js_getqueryparametervalue("stacktrace");
3572			if (nxs_js_isctrlkeydown || stacktrace != "")
3573			{
3574				// practical debug tool; if ctrl is pressed, output the stacktrac
3575				try { throw new Error("Stracktrace"); } catch (e) { console.log(e.stack); }
3576			}
3577			
3578			
3579			nxs_js_alert_identifier++;
3580			var token = "group-wait-" + nxs_js_alert_identifier;
3581			var text = "";
3582			text += "<div id='nxs-growl-" + token + "'>";
3583			text += "<span class='nxs-icon-clock' style='padding-right: 10px;'></span>";
3584			//text += "<img src='" + nxs_js_getframeworkurl() + "/images/icon-wait.png' style='padding-right: 10px;' />";
3585			if (message != null)
3586			{
3587				text = "<span style='padding-left: 10px;'>" + text + message + "</span>";
3588			}
3589			text += "</div>";
3590			jQ_nxs.jGrowl(text, { sticky: false, life: 3000, group: token });
3591			
3592			//nxs_js_log("created:" + token);
3593			
3594			return token;
3595		}
3596		
3597		//
3598		//
3599		//
3600		
3601		function nxs_js_alert_wait_finish(token)
3602		{
3603			if (token == -1)
3604			{
3605				return;
3606			}
3607		
3608			// if the finish is invoked soon after it was
3609			// started, the growl hasn't yet initialized
3610			// the growl popup. In that case the closing of the
3611			// growl does nothing, and the popup stays on the screen
3612			// too long. This is fixed by invoking the following function
3613			var retries = 10;
3614			nxs_js_alert_wait_finish_internal(token, retries);
3615		}
3616		
3617		function nxs_js_alert_wait_finish_internal(token, retriesleft)
3618		{
3619			if (jQ_nxs("#nxs-growl-" + token).length > 0)
3620			{
3621				// if dom element exists, invoke immediately
3622				nxs_js_alert_wait_finish_internal_actual(token);
3623			}
3624			else
3625			{
3626				//nxs_js_log('detected DOM doesnt (yet) have growl to close');
3627				if (retriesleft > 0)
3628				{
3629					// delayed invoked, but preventing endless loops...
3630					
3631					setTimeout
3632					(
3633						function()
3634						{
3635							//nxs_js_log("postponing close growl...");
3636							//nxs_js_log(token);
3637							retriesleft = retriesleft - 1;	
3638							//nxs_js_log(retriesleft);
3639							nxs_js_alert_wait_finish_internal(token, retriesleft);
3640						}
3641						,
3642						200);
3643				}
3644				else
3645				{
3646					//nxs_js_log('no more retries left...');
3647				}
3648			}
3649		}
3650		
3651		function nxs_js_alert_wait_finish_internal_actual(token)
3652		{
3653			//nxs_js_log("alerting wait finished:" + token);
3654			//nxs_js_log("closing token:" + token);
3655			
3656			jQ_nxs("div.jGrowl-notification." + token).trigger("jGrowl.close");
3657		}
3658		
3659		function nxs_js_logout()
3660		{
3661			var ajaxurl = nxs_js_get_adminurladminajax();
3662			jQ_nxs.ajax
3663			(
3664				{
3665					type: 'POST',
3666					data: 
3667					{
3668						"action": "nxs_ajax_webmethods",
3669						"webmethod": "logout"
3670					},
3671					dataType: 'JSON',
3672					url: ajaxurl, 
3673					success: function(response) 
3674					{
3675						nxs_js_log(response);
3676						if (response.result == "OK")
3677						{
3678							if (response.previousstate == "notauthenticated")
3679							{
3680								// either the user's session was timed out
3681								// or the webserver was reset if we reach this point
3682								nxs_js_log('note; user was not logged on');
3683							}
3684							
3685							// close the pop up
3686							nxs_js_closepopup_unconditionally();					
3687							nxs_js_refreshcurrentpage();
3688						}
3689						else
3690						{
3691							nxs_js_popup_notifyservererror();
3692							nxs_js_log(response);
3693						}
3694					},
3695					error: function(response)
3696					{
3697						nxs_js_popup_notifyservererror();
3698						nxs_js_log(response);
3699					}										
3700				}
3701			);
3702		}
3703		
3704		function nxs_js_help(helpid)
3705		{
3706			nxs_js_opensupportoptions();
3707		}
3708
3709		function nxs_js_copytoclipboard(text) 
3710		{
3711		  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
3712		}
3713		
3714		function nxs_js_popup_storestatecontroldata_checkbox(elementid, sessiondatakey)
3715		{
3716			if (jQ_nxs('#' + elementid).length > 0)
3717			{
3718				if (jQ_nxs('#' + elementid).is(':checked'))
3719				{
3720					nxs_js_popup_setsessiondata(sessiondatakey, 'checked=true');
3721				}
3722				else
3723				{
3724					nxs_js_popup_setsessiondata(sessiondatakey, '');
3725				}
3726			}
3727		}
3728		
3729		function nxs_js_popup_storestatecontroldata_checkbox_inverse(elementid, sessiondatakey)
3730		{
3731			if (jQ_nxs('#' + elementid).length > 0)
3732			{
3733				if (jQ_nxs('#' + elementid).is(':checked'))
3734				{
3735					nxs_js_popup_setsessiondata(sessiondatakey, '');
3736				}
3737				else
3738				{
3739					nxs_js_popup_setsessiondata(sessiondatakey, 'checked=true');
3740				}
3741			}
3742		}
3743
3744		function nxs_js_popup_storestatecontroldata_listofcheckbox(ulcontainerelementid, checkboxitemsclassname, sessiondatakey)
3745		{
3746			if (jQ_nxs('#' + ulcontainerelementid).length > 0)
3747			{
3748				var derivedselectedids = '';
3749				jQ_nxs('#' + ulcontainerelementid + " ." + checkboxitemsclassname).each
3750				(
3751					function(index)
3752					{
3753						if (jQ_nxs(this).prop('checked'))
3754						{
3755							var currentcheckboxelementid = jQ_nxs(this).attr('id');
3756							derivedselectedids = derivedselectedids + "[" + currentcheckboxelementid.split("_")[1] + "]";
3757						}
3758					}
3759				);
3760				nxs_js_popup_setsessiondata(sessiondatakey, derivedselectedids);
3761			}
3762			else
3763			{
3764				nxs_js_log('element not found');
3765			}
3766		}
3767		
3768		function nxs_js_popup_storestatecontroldata_textbox(elementid, sessiondatakey)
3769		{
3770			if (jQ_nxs('#' + elementid).length > 0)
3771			{
3772				nxs_js_popup_setsessiondata(sessiondatakey, jQ_nxs('#' + elementid).val());
3773			}
3774		}
3775		
3776		// kudos to http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric
3777		function isNumber(n) 
3778		{
3779  		return !isNaN(parseFloat(n)) && isFinite(n);
3780		}
3781		
3782		function nxs_js_popup_storestatecontroldata_hiddenfield(elementid, sessiondatakey)
3783		{
3784			if (jQ_nxs('#' + elementid).length > 0)
3785			{
3786				nxs_js_popup_setsessiondata(sessiondatakey, jQ_nxs('#' + elementid).val());
3787			}
3788		}
3789		
3790		function nxs_js_popup_storestatecontroldata_dropdown(elementid, sessiondatakey)
3791		{
3792			if (jQ_nxs('#' + elementid).length > 0)
3793			{
3794				nxs_js_popup_setsessiondata(sessiondatakey, jQ_nxs('#' + elementid).val());
3795			}
3796		}
3797		
3798		function nxs_js_postcomment(postid, containerpostid, placeholderid, parentcommentid, name, email, website, comment, invokewhenready, invokewhenfailed)
3799		{
3800			// invoke ajax call
3801			var ajaxurl = nxs_js_get_adminurladminajax();
3802			jQ_nxs.ajax
3803			(
3804				{
3805					type: 'POST',
3806					data: 
3807					{
3808						"action": "nxs_ajax_webmethods",
3809						"webmethod": "addcomment",
3810						"postid": postid,
3811						"name": name,
3812						"email": email,
3813						"website": website,
3814						"comment": comment,
3815						"parentcommentid": parentcommentid,
3816						"containerpostid": containerpostid,
3817						"placeholderid": placeholderid
3818					},
3819					async: false,
3820					cache: false,
3821					dataType: 'JSON',
3822					url: ajaxurl, 
3823					success: function(response) 
3824					{
3825						nxs_js_log(response);
3826						if (response.result == "OK")
3827						{
3828							// ok
3829							invokewhenready(response);
3830						}
3831						else
3832						{
3833							invokewhenfailed();
3834							nxs_js_popup_notifyservererror();
3835							nxs_js_log(response);
3836						}
3837					},
3838					error: function(response)
3839					{
3840						nxs_js_popup_notifyservererror();
3841						nxs_js_log(response);
3842					}										
3843				}
3844			);
3845		}
3846		
3847		function nxs_js_removecomment(postid, commentid, invokewhenready, invokewhenfailed)
3848		{
3849			// invoke ajax call
3850			var ajaxurl = nxs_js_get_adminurladminajax();
3851			jQ_nxs.ajax
3852			(
3853				{
3854					type: 'POST',
3855					data: 
3856					{
3857						"action": "nxs_ajax_webmethods",
3858						"webmethod": "removecomment",
3859						"postid": postid,
3860						"commentid": commentid
3861					},
3862					async: false,
3863					cache: false,
3864					dataType: 'JSON',
3865					url: ajaxurl, 
3866					success: function(response) 
3867					{
3868						nxs_js_log(response);
3869						if (response.result == "OK")
3870						{
3871							// ok
3872							invokewhenready();
3873						}
3874						else
3875						{
3876							invokewhenfailed();
3877							nxs_js_popup_notifyservererror();
3878							nxs_js_log(response);
3879						}
3880					},
3881					error: function(response)
3882					{
3883						nxs_js_popup_notifyservererror();
3884						nxs_js_log(response);
3885					}										
3886				}
3887			);
3888		}
3889		
3890		function nxs_js_getrandom(max)
3891		{
3892			return Math.floor(Math.random()*max);
3893		}
3894		
3895		function nxs_js_approvecomment(postid, commentid, invokewhenready, invokewhenfailed)
3896		{
3897			// invoke ajax call
3898			var ajaxurl = nxs_js_get_adminurladminajax();
3899			jQ_nxs.ajax
3900			(
3901				{
3902					type: 'POST',
3903					data: 
3904					{
3905						"action": "nxs_ajax_webmethods",
3906						"webmethod": "approvecomment",
3907						"postid": postid,
3908						"commentid": commentid
3909					},
3910					async: false,
3911					cache: false,
3912					dataType: 'JSON',
3913					url: ajaxurl, 
3914					success: function(response) 
3915					{
3916						nxs_js_log(response);
3917						if (response.result == "OK")
3918						{
3919							// ok
3920							invokewhenready();
3921						}
3922						else
3923						{
3924							invokewhenfailed();
3925							nxs_js_popup_notifyservererror();
3926							nxs_js_log(response);
3927						}
3928					},
3929					error: function(response)
3930					{
3931						nxs_js_popup_notifyservererror();
3932						nxs_js_log(response);
3933					}										
3934				}
3935			);
3936		}
3937		
3938		function nxs_js_geturl(destination, postid, nxsrefurlspecial, invokewhenready, invokewhenfailed)
3939		{
3940			// invoke ajax call
3941			var ajaxurl = nxs_js_get_adminurladminajax();
3942			jQ_nxs.ajax
3943			(
3944				{
3945					type: 'POST',
3946					data: 
3947					{
3948						"action": "nxs_ajax_webmethods",
3949						"webmethod": "geturl",
3950						"destination": destination,
3951						"containerpostid": nxs_js_getcontainerpostid(),
3952						"postid": postid,
3953						"nxsrefurlspecial": nxsrefurlspecial
3954					},
3955					async: false,
3956					cache: false,
3957					dataType: 'JSON',
3958					url: ajaxurl, 
3959					success: function(response) 
3960					{
3961						nxs_js_log(response);
3962						if (response.result == "OK")
3963						{
3964							// ok
3965							invokewhenready(response);
3966						}
3967						else
3968						{
3969							invokewhenfailed();
3970							nxs_js_popup_notifyservererror();
3971							nxs_js_log(response);
3972						}
3973					},
3974					error: function(response)
3975					{
3976						invokewhenfailed();
3977						nxs_js_popup_notifyservererror();
3978						nxs_js_log(response);
3979					}										
3980				}
3981			);
3982		}
3983		
3984		function nxs_js_clear_ajaxrefresh_notifications(container)
3985		{
3986			//nxs_js_log('invoking nxs_js_clear_ajaxrefresh_notifications');
3987		
3988			// container verwijst naar de regel waarvoor we de client refresh moeten
3989			// aanroepen (indien noodzakelijk / beschikbaar)
3990			jQ_nxs(container).find(".nxs-widget").each
3991  		(
3992  			function(idx2, elm2) 
3993  			{
3994  				var idwithfluff = elm2.id;
3995  				var id = idwithfluff.split("-")[2];
3996  				var functionname = "nxs_js_execute_after_ajaxrefresh_widget_" + id;
3997					var script = "<script>function " + functionname + "() { }</script>";
3998					// inject script in dom
3999					jQ_nxs(container).append(script);
4000					//nxs_js_log('injected:' + script);
4001				}
4002			);
4003		}
4004		
4005		// convenience function to get 
4006		// <div class="nxs-tag nxs-tag-foobar123"><domelement> will return "foobar123"
4007		// if invoked like nxs_js_findclassidentificationwithprefix_closest(domelement, ".nxs-tag", "nxs-tag-")
4008		function nxs_js_findclassidentificationwithprefix_closest(domelement, closestselector, prefix)
4009		{
4010			var closestElement = jQ_nxs(domelement).closest(closestselector);
4011			return nxs_js_findclassidentificationwithprefix(closestElement, prefix);
4012		}
4013		
4014		function nxs_js_finddistinctclassidentifications(domelement, prefixtype)
4015		{
4016			var result = [];
4017
4018			var prefixselector = "." + prefixtype;	// for example ".nxs-heightiq"
4019			var prefix = prefixtype + "-";	// for example "nxs-heightiq-"
4020			
4021			var elements = jQ_nxs(domelement).find(prefixselector).each
4022  		(
4023  			function(i,currentelement) 
4024  			{
4025  				var identification = nxs_js_findclassidentificationwithprefix(currentelement, prefix);
4026					if (jQuery.inArray(identification, result) == -1)
4027					{
4028						result.push(identification);
4029					}
4030				}
4031			);
4032			
4033			return result;
4034		}
4035		
4036		// function to return a specific id after a certain prefix in the class attribute,
4037		// specified on the domelement. for example if the dom element looks like <div class="nxs-post-123">,
4038		// the function will return 123 if the prefix "nxs-post-" is specified. The function can also
4039		// be used to return alfa characters, or a combination. <div class="nxs-object-foobar123"> will
4040		// return "foobar123"
4041		// tags: identifier, id, identification, find, get, retrieve, subset, prefix, classname, getclass, derive
4042		function nxs_js_findclassidentificationwithprefix(domelement, prefix, returnifnotfound)
4043		{
4044		 	var classname = jQ_nxs(domelement).attr("class");
4045			var pattern = prefix + "([^\\s]*)";	// any set of chars till the moment a whitespace is found
4046			var modifiers = "";
4047		 	var regularexpression=new RegExp(pattern,modifiers);
4048		 	
4049		 	var result = null;
4050			var regexpresult = regularexpression.exec(classname);
4051			if (regexpresult != null)
4052			{
4053				result = regexpresult[1];
4054			}
4055			else
4056			{
4057				if (typeof returnifnotfound !== 'undefined')
4058				{
4059					result = returnifnotfound;
4060				}
4061				else
4062				{
4063					// not found
4064					nxs_js_log('warning; identification not found;');
4065					nxs_js_log('domelement:');
4066					nxs_js_log(domelement);
4067					nxs_js_log('prefix:');
4068					nxs_js_log(prefix);
4069				}
4070			}
4071			
4072		 	return result;
4073		}
4074		
4075		// gets the postid that this domelement belongs to
4076		// by traversing up in the dom, and finding the closest "nxs-elements-container" element
4077		// and returning the XYZ value of its "nxs-post-XYZ" class attribute.
4078		function nxs_js_findclosestpostid_for_dom(domelement)
4079		{
4080			var result;
4081			var elementscontainer = jQ_nxs(domelement).closest(".nxs-elements-container");
4082			if (elementscontainer.length == 0)
4083			{
4084				//nxs_js_log('not found?!');
4085				result = null;
4086			}
4087			else
4088			{
4089				result = nxs_js_findclassidentificationwithprefix(elementscontainer, "nxs-post-");
4090			}
4091			return result;
4092		}
4093		
4094		function nxs_js_edit_widget(domelementinwidget)
4095		{
4096			nxs_js_edit_widget_v2(domelementinwidget, "home");
4097		}
4098		
4099		function nxs_js_edit_widget_v2(domelementinwidget, sheet)
4100		{
4101			// opens the popup window for this widget, defaults to the "home" sheet if not specified
4102			var postid = nxs_js_findclosestpostid_for_dom(domelementinwidget);
4103			var widget = jQ_nxs(domelementinwidget).closest(".nxs-placeholder").first();
4104			var placeholderid = nxs_js_getfirstplaceholderid_in_dom(widget);
4105			var rowindex = nxs_js_getrowindex(widget);
4106			//
4107			nxs_js_popup_placeholder_neweditsession(postid, placeholderid, rowindex, sheet);
4108		}
4109		
4110		function nxs_js_edit_row(domelementinwidget)
4111		{
4112			nxs_js_edit_row_v2(domelementinwidget, "home");
4113		}
4114		
4115		function nxs_js_edit_row_v2(domelementinwidget, sheet)
4116		{
4117			// opens the default "home" popup window for this row
4118			var postid = nxs_js_findclosestpostid_for_dom(domelementinwidget);
4119			//nxs_js_log(domelementinwidget);
4120			var row = jQ_nxs(domelementinwidget).closest(".nxs-row").first();
4121			var pagerowid = jQ_nxs(row).attr('id').split("-")[2];
4122
4123			nxs_js_popup_row_neweditsession(postid, pagerowid, sheet);
4124		}
4125		
4126		function nxs_js_notify_widgets_after_ajaxrefresh(container)
4127		{
4128			// stage 1
4129		
4130			// container verwijst naar de regel waarvoor we de client refresh moeten
4131			// aanroepen (indien noodzakelijk / beschikbaar)
4132			jQ_nxs(container).find(".nxs-widget").each
4133  		(
4134  			function(idx2, elm2) 
4135  			{
4136  				var idwithfluff = elm2.id;
4137  				var id = idwithfluff.split("-")[2];
4138  				var functionname = "nxs_js_execute_after_ajaxrefresh_widget_" + id;
4139  				
4140  				var fn = window[functionname];
4141  				if (typeof(fn) == 'function')
4142  				{
4143  					//nxs_js_log("invoking function " + functionname);
4144  					// invoke!
4145  					fn();
4146  				}
4147  				else
4148  				{
4149  					//nxs_js_log("ignoring (not found) function " + functionname);
4150  				}
4151				}
4152			);
4153			
4154			// stage 2; if SEO tab is active, (enqueue) the SEO refresh
4155			nxs_js_refresh_seoanalysis();
4156		}
4157		
4158		function nxs_js_saveplaceholdertoclipboard(postid, placeholderid)
4159		{
4160			nxs_js_log("about to copy widget data to memory :)");
4161			nxs_js_log("placeholderid: " + placeholderid);
4162			
4163			// invoke ajax call
4164			var ajaxurl = nxs_js_get_adminurladminajax();
4165			jQ_nxs.ajax
4166			(
4167				{
4168					type: 'POST',
4169					data: 
4170					{
4171						"action": "nxs_ajax_webmethods",
4172						"webmethod": nxs_js_getclipboardhandler() + "copy",
4173						"clipboardcontext" : "widget",
4174						"postid": postid,
4175						"placeholderid": placeholderid
4176					},
4177					cache: false,
4178					dataType: 'JSON',
4179					url: ajaxurl, 
4180					success: function(response) 
4181					{
4182						nxs_js_log(response);
4183						if (response.result == "OK")
4184						{
4185							nxs_js_alert(response.growl);
4186						}
4187						else
4188						{
4189							nxs_js_alert(nxs_js_gettrans('Clipboard failed'));
4190						}
4191					},
4192					error: function(response)
4193					{
4194						nxs_js_popup_notifyservererror();
4195						nxs_js_log(response);
4196						nxs_js_alert(nxs_js_gettrans('Clipboard failed'));
4197					}										
4198				}
4199			);
4200		}
4201		
4202		function nxs_js_saverowtoclipboard(postid, rowindex)
4203		{
4204			nxs_js_log("about to copy row data to memory :)");
4205			nxs_js_log("postid: " + postid);
4206			nxs_js_log("rowindex: " + rowindex);
4207			
4208			var options = 
4209			{
4210				"waitgrowltext": "One moment ...",
4211				"happyflowgrowltext": "Copied row to clipboard",
4212				"webmethoddata": 
4213				{
4214					"webmethod": nxs_js_getclipboardhandler() + "copy",
4215					"clipboardcontext" : "row",
4216					"postid": postid,
4217					"rowindex": rowindex,
4218				}
4219			};
4220			nxs_js_invokewebmethod(options, null, null, null);
4221		}
4222		
4223		function nxs_copytoserverclipboard(clipboardscope)
4224		{
4225			if (nxs_js_popupshows)
4226			{
4227				return;
4228			}
4229		
4230			// currently we only support copy pasting of individual widgets (no rows yet...)
4231			var selectedhovermenus = jQ_nxs(".nxs-widget-hover-menu.nxs-hovering.inside-right-top");
4232			var hoverrows = jQ_nxs(".nxs-row-container > .nxs-hover-menu.nxs-hovering");		
4233			if (jQ_nxs(selectedhovermenus).length == 1)
4234			{
4235				var postid = nxs_js_findclosestpostid_for_dom(selectedhovermenus[0]);
4236				var selectedwidget = jQ_nxs(selectedhovermenus).closest(".nxs-placeholder").find(".nxs-widget");
4237				var placeholderid = jQ_nxs(selectedwidget).attr("id").split("-")[2];
4238
4239				if (clipboardscope == "all")
4240				{
4241					nxs_js_saveplaceholdertoclipboard(postid, placeholderid);
4242				}
4243				else
4244				{
4245					nxs_js_log('unsupported clipboardscope; ' + clipboardscope);
4246				}
4247			}
4248			else if (jQ_nxs(hoverrows).length == 1)
4249			{
4250				nxs_js_log("copying while hovering over a row (not over a widget)");
4251				
4252				var postid = nxs_js_findclosestpostid_for_dom(hoverrows[0]);
4253				var rowindex = nxs_js_getrowindex(hoverrows[0]);
4254
4255				if (clipboardscope == "all")
4256				{
4257					nxs_js_saverowtoclipboard(postid, rowindex);
4258				}
4259				else
4260				{
4261					nxs_js_log('unsupported clipboardscope; ' + clipboardscope);
4262				}
4263			}
4264			else 
4265			{
4266				// show popup for copying info
4267				if (jQ_nxs("body").hasClass("single") || jQ_nxs("body").hasClass("post") || jQ_nxs("body").hasClass("page"))
4268				{
4269					nxs_js_popup_site_neweditsession('clipboardcopyselector');
4270				}
4271				else
4272				{
4273					nxs_js_alert("Ctrl-c is not supported for this context");
4274				}
4275			}
4276		}
4277		
4278		function nxs_pastefromserverclipboard(scope)
4279		{
4280			if (nxs_js_popupshows)
4281			{
4282				return;
4283			}
4284		
4285			var selectedhovermenus = jQ_nxs(".nxs-widget-hover-menu.nxs-hovering.inside-right-top");
4286			var hoverrows = jQ_nxs(".nxs-row-container > .nxs-hover-menu.nxs-hovering");
4287			if (jQ_nxs(selectedhovermenus).length == 1)
4288			{
4289				// hovering over a widget
4290				var postid = nxs_js_findclosestpostid_for_dom(selectedhovermenus[0]);
4291				var selectedwidget = jQ_nxs(selectedhovermenus).closest(".nxs-placeholder").find(".nxs-widget");
4292				var placeholderid = jQ_nxs(selectedwidget).attr("id").split("-")[2];
4293				
4294				// invoke ajax call
4295				var ajaxurl = nxs_js_get_adminurladminajax();
4296				jQ_nxs.ajax
4297				(
4298					{
4299						type: 'POST',
4300						data: 
4301						{
4302							"action": "nxs_ajax_webmethods",
4303							"webmethod": nxs_js_getclipboardhandler() + "paste",
4304							"clipboardcontext" : "widget",
4305							"containerpostid": nxs_js_getcontainerpostid(),
4306							"postid": postid,
4307							"placeholderid": placeholderid,
4308							"clientpopupsessioncontext": nxs_js_getescaped_popupsession_context(),
4309							"clientqueryparameters": nxs_js_escaped_getqueryparametervalues()
4310						},
4311						cache: false,
4312						dataType: 'JSON',
4313						url: ajaxurl, 
4314						success: function(response) 
4315						{
4316							nxs_js_log(response);
4317							if (response.result == "OK")
4318							{
4319								if (response.refresh == "row")
4320								{
4321									// update the DOM
4322									var rowindex = response.rowindex;
4323									var rowhtml = response.rowhtml;
4324									var pagecontainer = jQ_nxs(".nxs-layout-editable.nxs-post-" + postid)[0];
4325									var pagerowscontainer = jQ_nxs(pagecontainer).find(".nxs-postrows")[0];
4326									var element = jQ_nxs(pagerowscontainer).children()[rowindex];
4327									jQ_nxs(element).replaceWith(rowhtml);
4328									
4329									// update the GUI step 1
4330									// invoke execute_after_clientrefresh_XYZ for each widget in the affected first row, if present
4331									var container = jQ_nxs(pagerowscontainer).children()[rowindex];
4332									nxs_js_notify_widgets_after_ajaxrefresh(container);
4333									// update the GUI step 2
4334									nxs_js_reenable_all_window_events();
4335									
4336									// growl!
4337									nxs_js_alert(response.growl);
4338								}
4339								else
4340								{
4341									// assumed to have to refresh entire page
4342									
4343									nxs_js_refreshcurrentpage();
4344								}
4345							}
4346							else if (response.result == "ALTFLOW")
4347							{
4348								if (response.altflowid == "widgetnotallowed")
4349								{
4350									// inform used
4351									nxs_js_alert(response.msg);
4352								}
4353								else
4354								{
4355									nxs_js_popup_notifyservererror();
4356									nxs_js_log(response);
4357								}
4358							}
4359							else
4360							{
4361								nxs_js_alert(nxs_js_gettrans('Clipboard failed'));
4362							}
4363						},
4364						error: function(response)
4365						{
4366							nxs_js_popup_notifyservererror();
4367							nxs_js_log(response);
4368							nxs_js_alert(nxs_js_gettrans('Clipboard failed'));
4369						}										
4370					}
4371				);
4372			}
4373			else if (jQ_nxs(hoverrows).length == 1)
4374			{
4375				nxs_js_log("pasting while hovering over a row (not over a widget)");
4376				
4377				var postid = nxs_js_findclosestpostid_for_dom(hoverrows[0]);
4378				var rowindex = nxs_js_getrowindex(hoverrows[0]);
4379				var containerpostid = nxs_js_getcontainerpostid();
4380				
4381				function nxs_js_updaterow(response)
4382				{
4383					var postid = response.postid;
4384					var rowindex = response.rowindex;
4385					var html = response.html;
4386					
4387					// update the row; the html is already provided in the response
4388					var pagecontainer = jQ_nxs(".nxs-post-" + postid)[0];
4389					var pagerowscontainer = jQ_nxs(pagecontainer).find(".nxs-postrows")[0];
4390					// afterwards update existing row
4391					var updateElement = jQ_nxs(pagerowscontainer).children()[rowindex];
4392	
4393					// before updating the dom, we first wipe any functions for notification ajax used by the "old" widgets in this row
4394					nxs_js_clear_ajaxrefresh_notifications(updateElement);
4395					
4396					//nxs_js_log("replacing index " + rowindex);
4397					jQ_nxs(updateElement).replaceWith(html);
4398					
4399					// after updating the dom, invoke execute_after_clientrefresh_XYZ for each widget in the affected first row, if present
4400					var updateElement = jQ_nxs(pagerowscontainer).children()[rowindex];
4401					nxs_js_notify_widgets_after_ajaxrefresh(updateElement);
4402					
4403					nxs_js_reenable_all_window_events();
4404				}
4405				
4406				var options = 
4407				{
4408					"waitgrowltext": "One moment ...",
4409					"happyflowgrowltext": "Pasted row from clipboard",
4410					"webmethoddata": 
4411					{
4412						"webmethod": nxs_js_getclipboardhandler() + "paste",
4413						"clipboardcontext" : "row",
4414						"containerpostid": containerpostid,
4415						"postid": postid,
4416						"rowindex": rowindex,
4417					}
4418				};
4419				nxs_js_invokewebmethod(options, nxs_js_updaterow, null, null);
4420				
4421			}
4422			else
4423			{
4424				// Pasten of elements other than a widget will be handled using a popup
4425				if (jQ_nxs("body").hasClass("single") || jQ_nxs("body").hasClass("post") || jQ_nxs("body").hasClass("page"))
4426				{
4427					nxs_js_popup_site_neweditsession('clipboardpasteselector');
4428				}
4429				else
4430				{
4431					nxs_js_alert("Ctrl-C is not supported for this context");
4432				}	
4433							
4434			}
4435		}
4436		
4437		function nxs_js_getwidgetdom_overwhichwehover()
4438		{
4439			var result = null;
4440		
4441			var selectedhovermenus = jQ_nxs(".nxs-widget-hover-menu.nxs-hovering.inside-right-top");
4442			if (jQ_nxs(selectedhovermenus).length == 1)
4443			{
4444				result = jQ_nxs(selectedhovermenus).closest(".nxs-placeholder").find(".nxs-widget")[0];			
4445			}
4446			else
4447			{
4448				// not found
4449			}
4450			
4451			return result;
4452		}
4453		
4454		function nxs_js_getplaceholderidofwidgetdom(widget)
4455		{
4456			var result = jQ_nxs(widget).attr("id").split("-")[2];
4457			return result;
4458		}
4459		
4460		// 
4461		// this isn't yet correctly implement for IE, see http://stackoverflow.com/questions/69430/is-there-a-way-to-make-text-unselectable-on-an-html-page
4462		// disable selecting with mouse
4463		(
4464			function($)
4465			{		
4466				jQuery.fn.disableSelection = function() 
4467				{
4468				  return this.each
4469				  (
4470					  function() 
4471					  {
4472			        jQ_nxs(this).addClass('nxs-unselectable');
4473					  }
4474				  );
4475				};
4476			}
4477		)
4478		(
4479			jQuery
4480		);
4481		
4482		//
4483		// this isn't yet correctly implement for IE, see http://stackoverflow.com/questions/69430/is-there-a-way-to-make-text-unselectable-on-an-html-page		
4484		// enable selecting with mouse
4485		(
4486			function($)
4487			{		
4488				jQuery.fn.enableSelection = function() 
4489				{
4490				  return this.each
4491				  (
4492					  function() 
4493					  {
4494			        jQ_nxs(this).removeClass('nxs-unselectable');
4495					  }
4496				  );
4497				};
4498			}
4499		)
4500		(
4501			jQuery
4502		);
4503
4504		var nxs_js_facebookinjected = false;
4505		
4506		function nxs_js_inject_facebook()
4507		{
4508			if (nxs_js_facebookinjected)
4509			{
4510				// 
4511				nxs_js_fb_postprocessor();
4512				return;
4513			}
4514			nxs_js_facebookinjected = true;
4515			
4516			// kudos to http://cyrilmazur.com/2011/08/deferred-lazy-loading-facebook-widgets.html
4517			
4518			jQ_nxs('body').append('<div id="fb-root" style="display: none;"></div>');
4519			
4520			var locale = nxs_js_getlocale();
4521			if (locale == 'nl_NL')
4522			{
4523				// ok
4524			}
4525			else
4526			{
4527				locale = 'en_US';
4528			}
4529			var scripturl = '//connect.facebook.net/' + locale + '/all.js#xfbml=1';
4530			
4531			jQuery.getScript
4532			(
4533				scripturl, 
4534				function() 
4535				{
4536			    FB.init({status: true, cookie: true, xfbml: true}); 
4537			    // activate DOM
4538			    nxs_js_fb_postprocessor();
4539				}
4540			);
4541		}
4542		
4543		function nxs_js_fb_postprocessor()
4544		{
4545			nxs_js_log("fb post processor");
4546
4547			if (typeof(FB) != 'undefined' && FB != null ) 
4548			{
4549				FB.XFBML.parse();
4550			}
4551			
4552			// tell the layout engine to post process the layout
4553			// after the DOM is updated
4554			nxs_gui_set_runtime_dimensions_enqueuerequest('nxs-framework-fbpostprocessor');
4555		}
4556		
4557		var nxs_js_googleplusinjected = false;
4558		
4559		function nxs_js_inject_googleplus()
4560		{
4561			if (nxs_js_googleplusinjected)
4562			{
4563				return;
4564			}
4565			nxs_js_googleplusinjected = true;
4566			script = document.createElement('script');
4567	    script.async = true;
4568	    script.src = '//apis.google.com/js/plusone.js';
4569	    document.body.appendChild(script);
4570		}
4571		
4572		//
4573		// generic page redirector for editing header, sidebar, footer, subheader, subfooter or pagelets
4574		//
4575		// for example : 
4576		// layouttype = "header"
4577		// pagesheetwhennotavailable = "headerhome"
4578		// 
4579		function nxs_js_editpagesection(postid, layouttype, pagesheetwhennotavailable)
4580		{
4581			var nxsrefurlspecial = nxs_js_get_nxsrefurlspecial();
4582			nxs_js_geturl(
4583				layouttype, 
4584				postid, 
4585				nxsrefurlspecial, 
4586				function(response) 
4587				{
4588					var url = response.url;
4589					nxs_js_log(url);
4590					nxs_js_redirect(url);
4591				},
4592				function()
4593				{
4594					// fout, kan komen als de layout niet gekoppeld is
4595					nxs_js_popup_pagetemplate_neweditsession(pagesheetwhennotavailable);
4596				}
4597			);
4598		}
4599		
4600		function nxs_js_nop()
4601		{
4602			// no operation
4603		}	
4604		
4605		function nxs_js_opensupportoptions()
4606		{
4607			nxs_js_popup_site_neweditsession('supportoptions');
4608		}
4609		
4610		function nxs_js_generic_ws(webmethod, inputparameters, invokewhenavailable)
4611		{			
4612			var ajaxurl = nxs_js_get_adminurladminajax();
4613			jQ_nxs.ajax
4614			(
4615				{
4616					type: 'POST',
4617					data: 
4618					{
4619						"action": "nxs_ajax_webmethods",
4620						"webmethod": webmethod,
4621						"clientpopupsessioncontext": nxs_js_getescaped_popupsession_context(),
4622						"inputparameters": inputparameters
4623					},
4624					cache: false,
4625					dataType: 'JSON',
4626					url: ajaxurl, 
4627					success: function(response) 
4628					{
4629						nxs_js_log(response);
4630						if (response.result == "OK")
4631						{
4632							invokewhenavailable(response);
4633						}
4634						else
4635						{
4636							nxs_js_popup_notifyservererror();
4637							nxs_js_log(response);
4638						}
4639					},
4640					error: function(response)
4641					{
4642						nxs_js_popup_notifyservererror();
4643						nxs_js_log(response);
4644					}
4645				}
4646			);
4647		}
4648		
4649		// kudos to http://stackoverflow.com/questions/3431512/javascript-equivalent-to-phps-urldecode
4650		function nxs_js_urldecode(url)
4651		{
4652		  return decodeURIComponent(url.replace(/\+/g, ' '));
4653		}
4654		
4655		// encoding / base64
4656		
4657		function nxs_js_utf8_encode (argString) 
4658		{
4659			// http://kevin.vanzonneveld.net
4660			// +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
4661			// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
4662			// +   improved by: sowberry
4663			// +    tweaked by: Jack
4664			// +   bugfixed by: Onno Marsman
4665			// +   improved by: Yves Sucaet
4666			// +   bugfixed by: Onno Marsman
4667			// +   bugfixed by: Ulrich
4668			// +   bugfixed by: Rafal Kukawski
4669			// *     example 1: nxs_js_utf8_encode('Kevin van Zonneveld');
4670			// *     returns 1: 'Kevin van Zonneveld'
4671			
4672			if (argString === null || typeof argString === "undefined") {
4673			return "";
4674			}
4675			
4676			var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
4677			var utftext = "",
4678			start, end, stringl = 0;
4679			
4680			start = end = 0;
4681			stringl = string.length;
4682			for (var n = 0; n < stringl; n++) {
4683			var c1 = string.charCodeAt(n);
4684			var enc = null;
4685			
4686			if (c1 < 128) {
4687			end++;
4688			} else if (c1 > 127 && c1 < 2048) {
4689			enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
4690			} else {
4691			enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
4692			}
4693			if (enc !== null) {
4694			if (end > start) {
4695			utftext += string.slice(start, end);
4696			}
4697			utftext += enc;
4698			start = end = n + 1;
4699			}
4700			}
4701			
4702			if (end > start) {
4703			utftext += string.slice(start, stringl);
4704			}
4705			
4706			return utftext;
4707		}
4708			
4709		function nxs_js_base64_encode(data) 
4710		{
4711			// http://kevin.vanzonneveld.net
4712			// +   original by: Tyler Akins (http://rumkin.com)
4713			// +   improved by: Bayron Guevara
4714			// +   improved by: Thunder.m
4715			// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
4716			// +   bugfixed by: Pellentesque Malesuada
4717			// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
4718			// -    depends on: nxs_js_utf8_encode
4719			// *     example 1: base64_encode('Kevin van Zonneveld');
4720			// *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
4721			// mozilla has this native
4722			// - but breaks in 2.0.0.12!
4723			//if (typeof this.window['atob'] == 'function') {
4724			//    return atob(data);
4725			//}
4726			var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
4727			var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
4728			ac = 0,
4729			enc = "",
4730			tmp_arr = [];
4731			
4732			if (!data) {
4733			return data;
4734			}
4735			
4736			data = this.nxs_js_utf8_encode(data + '');
4737			
4738			do { // pack three octets into four hexets
4739			o1 = data.charCodeAt(i++);
4740			o2 = data.charCodeAt(i++);
4741			o3 = data.charCodeAt(i++);
4742			
4743			bits = o1 << 16 | o2 << 8 | o3;
4744			
4745			h1 = bits >> 18 & 0x3f;
4746			h2 = bits >> 12 & 0x3f;
4747			h3 = bits >> 6 & 0x3f;
4748			h4 = bits & 0x3f;
4749			
4750			// use hexets to index into b64, and append result to encoded string
4751			tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
4752			} while (i < data.length);
4753			
4754			enc = tmp_arr.join('');
4755			
4756			switch (data.length % 3) {
4757			case 1:
4758			enc = enc.slice(0, -2) + '==';
4759			break;
4760			case 2:
4761			enc = enc.slice(0, -1) + '=';
4762			break;
4763			}
4764			
4765			return enc;
4766		}
4767		
4768		//
4769		
4770		// ------------------------------------------------------------------------------------
4771		// seo functions
4772		
4773		function nxs_js_refresh_seoanalysis()
4774		{
4775			//nxs_js_log("seo:");
4776			//nxs_js_log(jQ_nxs('#tabs-seo'));
4777			if (jQ_nxs('#tabs-seo #nxsseoanalysisoutput').length > 0)
4778			{
4779				nxs_js_refresh_seoanalysis_enqueuerequest();
4780			}
4781			else
4782			{
4783				// SEO is disabled
4784			}
4785		}
4786		
4787		function nxs_js_refresh_seoanalysis_enqueuerequest(trigger)
4788		{
4789			// mark as triggered
4790			if (nxs_js_isseorefreshqueued == true)
4791			{
4792				// performance boost; we gaan hier niet nogmaals
4793				// alle berekeningen doorvoeren; er is reeds een ververs
4794				// request ingepland
4795				// nxs_js_log('skipping refresh, already queued');
4796				return;
4797			}
4798			else
4799			{
4800				// nxs_js_log('nothing in queue yet, enqueueing refresh request');
4801				// enqueue!
4802				nxs_js_isseorefreshqueued = true;
4803
4804				var nxs_max_refresh_frequency_in_msecs = 100;	// lager betekent meer overhead, maar "snappier" gedrag
4805				setTimeout
4806				(
4807					function() 
4808					{
4809						//nxs_js_log('executing actual refresh work');
4810						
4811						// first we dequeue! 
4812						nxs_js_isseorefreshqueued = false; 
4813						nxs_js_refresh_seoanalysis_actualrequest(); 
4814					},nxs_max_refresh_frequency_in_msecs
4815				);
4816			}
4817		}
4818		
4819		function nxs_js_refresh_seoanalysis_actualrequest()
4820		{
4821			jQ_nxs('#nxs-seofields').show();
4822
4823			// refresh yoast v3
4824			if ("undefined" !== typeof YoastSEO )
4825			{
4826				console.log("refreshing Yoast SEO v3!");
4827				YoastSEO.app.refresh();
4828			}
4829
4830			return;
4831		
4832			var postid = nxs_js_getcontainerpostid();
4833		
4834			var inputparameters = { "postid" : postid };
4835		
4836			nxs_js_generic_ws
4837			(
4838				"getseoanalysis",
4839				inputparameters,
4840				function(responseparameters)
4841				{
4842					// process
4843
4844					var outputhtml = '';
4845					
4846					//
4847					jQ_nxs('#nxs-seofocuskeyword').val(responseparameters.focuskw);
4848					jQ_nxs('#nxs-seotitle').val(responseparameters.title);
4849					jQ_nxs('#nxs-seometadescription').val(responseparameters.metadesc);
4850					
4851					// update title of current browser window too
4852					document.title = responseparameters.title;
4853
4854					var wperrors = responseparameters.wperrors;
4855					
4856					if (wperrors != null)
4857					{
4858						var numerrors = wperrors.length;
4859						for (var i = 0; i < numerrors; i++)
4860						{
4861						 	var currenterror = wperrors[i];
4862						
4863							nxs_js_log("current error:");
4864							nxs_js_log(currenterror);
4865							
4866							outputhtml += currenterror;
4867							//nxs_js_alert(currenterror);
4868						}
4869						// display output
4870						jQ_nxs('#nxs-seo-output').html(outputhtml);	
4871						
4872						// update height
4873						nxs_js_refreshtopmenufillerheight();
4874						
4875						// update counters
4876						nxs_js_shownumofchars('#nxs-seotitle', '#seotitlecharsused'); 
4877						nxs_js_shownumofchars('#nxs-seometadescription', '#seodescriptioncharsused'); 
4878						
4879						// cancel further processing
4880						return;
4881					}
4882					
4883					var calculatedresults = responseparameters.calculatedresults;
4884					nxs_js_log(calculatedresults);
4885					if (calculatedresults == null)
4886					{
4887						nxs_js_alert('No results found?!');
4888					}
4889					
4890					//
4891					//
4892					
4893					outputhtml += "<ul class='nxs-seoreport'>";
4894					
4895					for(var currentcalculatedresult in calculatedresults)
4896					{
4897						if (!calculatedresults.hasOwnProperty(currentcalculatedresult)) 
4898						{
4899							continue;
4900						}
4901						
4902					  var message = "";
4903					  message += "<li class='nxs-seoindicator-" + calculatedresults[currentcalculatedresult].indicator + "'>";
4904					  message += calculatedresults[currentcalculatedresult].msg;
4905						message += "</li>";
4906						  
4907						if (calculatedresults[currentcalculatedresult].msg != null)
4908						{
4909						  outputhtml += message;
4910						}
4911					}
4912					
4913					outputhtml += "</ul>";
4914					
4915					// display output
4916					jQ_nxs('#nxs-seo-output').html(outputhtml);	
4917
4918					// display snippet
4919					//nxs_js_log("snippet:");
4920					var snippet = responseparameters.snippet;
4921					//nxs_js_log(snippet);
4922					jQ_nxs('#nxs-seo-snippetwrapper').html(snippet);
4923					//nxs_js_log('snippet wrapped updated');
4924
4925					// update counters
4926					nxs_js_shownumofchars('#nxs-seotitle', '#seotitlecharsused'); 
4927					nxs_js_log('numchars');
4928					nxs_js_shownumofchars('#nxs-seometadescription', '#seodescriptioncharsused'); 
4929					nxs_js_log('numchars');
4930
4931					try 
4932					{
4933						// highlight focus keywordwords
4934						var words = responseparameters.focuskw;
4935						// highlighting is performed on a per-word basis
4936						var wordpieces = words.split(' ');
4937						for (var i = 0; i < wordpieces.length; i++) 
4938						{
4939							var word = wordpieces[i];
4940							if (word != '')
4941							{
4942								nxs_js_log('highlighting..[' + word + ']');
4943					    	nxs_js_highlightword(document.getElementById('nxs-seo-snippetwrapper'), word);
4944					    }
4945					    else
4946					    {
4947					    	// ignore (otherwise a browser lockup occurs...)
4948					    }
4949						}
4950					} 
4951					catch (err)
4952					{
4953						// absorb (for example, failed in < ie9
4954						nxs_js_log(err);
4955					}
4956					
4957					nxs_js_log('updating height');
4958					
4959					// update height top menu
4960					nxs_js_refreshtopmenufillerheight();					
4961				}
4962			);
4963		}
4964		
4965		function nxs_js_update_seooption(postid, key, val, success)
4966		{
4967			var ajaxurl = nxs_js_get_adminurladminajax();
4968			jQ_nxs.ajax
4969			(
4970				{
4971					type: 'POST',
4972					data: 
4973					{
4974						"action": "nxs_ajax_webmethods",
4975						"webmethod": "updateseooption",
4976						"postid": postid,
4977						"key": key,
4978						"val": val
4979					},
4980					async: false,
4981					cache: false,
4982					dataType: 'JSON',
4983					url: ajaxurl,
4984					success: function(response) 
4985					{
4986						nxs_js_log(response);
4987						if (response.result == "OK")
4988						{
4989							success(response);
4990							// ok
4991						}
4992						else
4993						{
4994							nxs_js_popup_notifyservererror();
4995							nxs_js_log(response);
4996						}
4997					},
4998					error: function(response)
4999					{
5000						nxs_js_popup_notifyservererror();
5001						nxs_js_log(response);
5002					}
5003				}
5004			);
5005		}
5006		
5007		function nxs_js_update_seoall()
5008		{
5009			nxs_js_update_seofocuskeyword();
5010			nxs_js_update_seotitle();
5011			nxs_js_update_seometadescription();
5012						
5013			nxs_js_refresh_seoanalysis();
5014			
5015			// turn off update button
5016			jQ_nxs('#nxs-seofield-updatebutton').hide();
5017		}
5018		
5019		function nxs_js_update_seofocuskeyword()
5020		{
5021			var postid = nxs_js_getcontainerpostid();
5022			var val = jQ_nxs('#nxs-seofocuskeyword').val();
5023			if (val != null && val.length > 0)
5024			{
5025				var key = 'focuskw';
5026				nxs_js_update_seooption
5027				(
5028					postid, 
5029					key, 
5030					val, 
5031					function()
5032					{
5033						//nxs_js_alert('update successful');
5034					}
5035				);
5036			}
5037			else
5038			{
5039				nxs_js_alert('focuskw not updated; empty');
5040			}
5041		}
5042		
5043		function nxs_js_update_seotitle()
5044		{
5045			var postid = nxs_js_getcontainerpostid();
5046			var val = jQ_nxs('#nxs-seotitle').val();
5047			if (val != null && val.length > 0)
5048			{
5049				var key = 'title';
5050				nxs_js_update_seooption
5051				(
5052					postid, 
5053					key, 
5054					val, 
5055					function()
5056					{
5057						//nxs_js_alert('update successful');
5058					}
5059				);
5060			}
5061			else
5062			{
5063				nxs_js_alert('title not updated; empty');
5064			}
5065
5066		}
5067
5068		function nxs_js_update_seometadescription()
5069		{
5070			var postid = nxs_js_getcontainerpostid();
5071			var val = jQ_nxs('#nxs-seometadescription').val();
5072			if (val != null && val.length > 0)
5073			{
5074				var key = 'metadesc';
5075				nxs_js_update_seooption
5076				(
5077					postid, 
5078					key, 
5079					val, 
5080					function()
5081					{
5082						//nxs_js_alert('update successful');
5083					}
5084				);
5085			}
5086			else
5087			{
5088				nxs_js_alert('meta desc not updated; empty');
5089			}
5090		}
5091		
5092		function nxs_js_shownumofchars(inputfield, outputfield)
5093		{
5094			if (jQ_nxs(inputfield) == null)
5095			{
5096				nxs_js_log("inputfield not found:" + inputfield);
5097				return;
5098			}
5099			if (jQ_nxs(outputfield) == null)
5100			{
5101				nxs_js_log("outputfield not found:" + outputfield);
5102				return;
5103			}
5104			var aantal = jQ_nxs(inputfield).val().length;
5105			jQ_nxs(outputfield).html(aantal);
5106		}
5107		
5108		// kudos to http://stackoverflow.com/questions/10729983/highlight-word-in-html-text-but-not-markup
5109		function nxs_js_highlightword(root,word){
5110		  nxs_js_textnodesunder(root).forEach(nxs_js_highlightwords);
5111		
5112		  function nxs_js_textnodesunder(root){
5113		    var n,a=[],w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,null,false);
5114		    while(n=w.nextNode()) a.push(n);
5115		    return a;
5116		  }
5117		
5118		  function nxs_js_highlightwords(n){
5119		  	// ignores casing
5120		    for (var i; (i=getnormalizedcomparable(n.nodeValue).indexOf(getnormalizedcomparable(word),i)) > -1; n=after){
5121		      var after = n.splitText(i+word.length);
5122		      var highlighted = n.splitText(i);
5123		      var span = document.createElement('span');
5124		      span.className = 'nxs-highlighted';
5125		      span.appendChild(highlighted);
5126		      after.parentNode.insertBefore(span,after);
5127		    }
5128		  }
5129		}
5130		
5131		// kudos to http://lehelk.com/2011/05/06/script-to-remove-diacritics/		
5132		var defaultDiacriticsRemovalMap = [
5133    {'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
5134    {'base':'AA','letters':/[\uA732]/g},
5135    {'base':'AE','letters':/[\u00C6\u01FC\u01E2]/g},
5136    {'base':'AO','letters':/[\uA734]/g},
5137    {'base':'AU','letters':/[\uA736]/g},
5138    {'base':'AV','letters':/[\uA738\uA73A]/g},
5139    {'base':'AY','letters':/[\uA73C]/g},
5140    {'base':'B', 'letters':/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
5141    {'base':'C', 'letters':/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
5142    {'base':'D', 'letters':/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
5143    {'base':'DZ','letters':/[\u01F1\u01C4]/g},
5144    {'base':'Dz','letters':/[\u01F2\u01C5]/g},
5145    {'base':'E', 'letters':/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
5146    {'base':'F', 'letters':/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
5147    {'base':'G', 'letters':/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
5148    {'base':'H', 'letters':/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
5149    {'base':'I', 'letters':/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
5150    {'base':'J', 'letters':/[\u004A\u24BF\uFF2A\u0134\u0248]/g},
5151    {'base':'K', 'letters':/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
5152    {'base':'L', 'letters':/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u014
51521\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
5153    {'base':'LJ','letters':/[\u01C7]/g},
5154    {'base':'Lj','letters':/[\u01C8]/g},
5155    {'base':'M', 'letters':/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
5156    {'base':'N', 'letters':/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
5157    {'base':'NJ','letters':/[\u01CA]/g},
5158    {'base':'Nj','letters':/[\u01CB]/g},
5159    {'base':'O', 'letters':/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
5160    {'base':'OI','letters':/[\u01A2]/g},
5161    {'base':'OO','letters':/[\uA74E]/g},
5162    {'base':'OU','letters':/[\u0222]/g},
5163    {'base':'P', 'letters':/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
5164    {'base':'Q', 'letters':/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
5165    {'base':'R', 'letters':/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
5166    {'base':'S', 'letters':/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
5167    {'base':'T', 'letters':/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
5168    {'base':'TZ','letters':/[\uA728]/g},
5169    {'base':'U', 'letters':/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
5170    {'base':'V', 'letters':/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
5171    {'base':'VY','letters':/[\uA760]/g},
5172    {'base':'W', 'letters':/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
5173    {'base':'X', 'letters':/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
5174    {'base':'Y', 'letters':/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
5175    {'base':'Z', 'letters':/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},
5176    {'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},
5177    {'base':'aa','letters':/[\uA733]/g},
5178    {'base':'ae','letters':/[\u00E6\u01FD\u01E3]/g},
5179    {'base':'ao','letters':/[\uA735]/g},
5180    {'base':'au','letters':/[\uA737]/g},
5181    {'base':'av','letters':/[\uA739\uA73B]/g},
5182    {'base':'ay','letters':/[\uA73D]/g},
5183    {'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},
5184    {'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},
5185    {'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},
5186    {'base':'dz','letters':/[\u01F3\u01C6]/g},
5187    {'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},
5188    {'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},
5189    {'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},
5190    {'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},
5191    {'base':'hv','letters':/[\u0195]/g},
5192    {'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},
5193    {'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},
5194    {'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},
5195    {'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},
5196    {'base':'lj','letters':/[\u01C9]/g},
5197    {'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},
5198    {'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},
5199    {'base':'nj','letters':/[\u01CC]/g},
5200    {'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u
52001ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},
5201    {'base':'oi','letters':/[\u01A3]/g},
5202    {'base':'ou','letters':/[\u0223]/g},
5203    {'base':'oo','letters':/[\uA74F]/g},
5204    {'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},
5205    {'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},
5206    {'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},
5207    {'base':'s','letters':/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},
5208    {'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},
5209    {'base':'tz','letters':/[\uA729]/g},
5210    {'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},
5211    {'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},
5212    {'base':'vy','letters':/[\uA761]/g},
5213    {'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},
5214    {'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},
5215    {'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},
5216    {'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}
5217		];
5218		function nxs_js_removediacritics(str) {
5219		    var changes = defaultDiacriticsRemovalMap;
5220		    for(var i=0; i<changes.length; i++) 
5221		    {
5222		      str = str.replace(changes[i].letters, changes[i].base);
5223		    }
5224		    return str;
5225		}
5226		
5227		function getnormalizedcomparable(str)
5228		{
5229			return nxs_js_removediacritics(str).toLowerCase();
5230		}
5231		
5232		/*
5233		-------------------------------------------------------
5234		------------------------------------------------------- 
5235		js color handling
5236		kudos to http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript 
5237		-------------------------------------------------------
5238		-------------------------------------------------------
5239		*/
5240		
5241		function nxs_js_rgbtohsl(rgb)
5242		{
5243			if (rgb == null)
5244			{
5245				return null;
5246			}
5247		var r = rgb.r;
5248		var g = rgb.g;
5249		var b = rgb.b;
5250		
5251    r /= 255, g /= 255, b /= 255;
5252    var max = Math.max(r, g, b), min = Math.min(r, g, b);
5253    var h, s, l = (max + min) / 2;
5254
5255    if(max == min){
5256        h = s = 0; // achromatic
5257    }else{
5258        var d = max - min;
5259        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
5260        switch(max){
5261            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
5262            case g: h = (b - r) / d + 2; break;
5263            case b: h = (r - g) / d + 4; break;
5264        }
5265        h /= 6;
5266    }
5267    
5268    var result = {
5269    h: h,
5270    s: s,
5271    l: l
5272    }
5273
5274    return result;
5275}
5276
5277function nxs_js_adjustlightnessforhsl(hsl, lightnessdelta)
5278{
5279	if (hsl == null)
5280	{
5281	return null;
5282	}
5283	//nxs_js_log(hsl);
5284
5285	var result = 
5286	{
5287		h : hsl.h,
5288		s : hsl.s,
5289		l : hsl.l + lightnessdelta
5290	}
5291	
5292	if (result.l < 0)
5293	{
5294		result.l = 0;
5295	}
5296	else if (result.l > 1)
5297	{
5298		result.l = 1;
5299	}
5300	
5301	return result; 
5302}
5303
5304function nxs_js_gethextransformedrgblight(rgb, delta)
5305{
5306	var hsl = nxs_js_rgbtohsl(rgb);
5307	var adjustedhsl = nxs_js_adjustlightnessforhsl(hsl, delta);
5308	var adjustedrgb = nxs_js_hsltorgb(adjustedhsl);
5309	var adjustedhex = nxs_js_rgbtohex(adjustedrgb);
5310	return adjustedhex;
5311}
5312
5313// within the given hue, select the reverse s and l
5314function nxs_js_getoppositesaturationandlightforhsl(hsl)
5315{
5316	nxs_js_log("before hsl:");
5317	nxs_js_log(hsl);
5318	
5319	var result = 
5320	{
5321		h : hsl.h,
5322		s : 1 - hsl.s,
5323		l : 1 - hsl.l
5324	}
5325	
5326	nxs_js_log("after hsl:");
5327	nxs_js_log(result);
5328	
5329	return result;
5330}
5331
5332function nxs_js_getcomplementaryhsl(hsl)
5333{
5334	var result = 
5335	{
5336		h : (0.5 + hsl.h) % 1,
5337		s : hsl.s,
5338		l : hsl.l
5339	}
5340	return result;
5341}
5342
5343function nxs_js_hslinbounds(hsl)
5344{
5345	// h
5346	if (hsl.h < 0)
5347	{
5348		hsl.h += 1;
5349	}
5350	else if (hsl.h > 1)
5351	{
5352		hsl.h -= 1;
5353	}
5354	// s
5355	if (hsl.s < 0)
5356	{
5357		hsl.s += 1;
5358	}
5359	else if (hsl.s > 1)
5360	{
5361		hsl.s -= 1;
5362	}
5363	// l
5364	if (hsl.l < 0)
5365	{
5366		hsl.l += 1;
5367	}
5368	else if (hsl.l > 1)
5369	{
5370		hsl.l -= 1;
5371	}
5372	return hsl;
5373}
5374
5375function nxs_js_getcomplementaryhsl(hsl)
5376{
5377	var result = [];
5378	var item;
5379	
5380	item =  
5381	{
5382		h : hsl.h,
5383		s : hsl.s,
5384		l : hsl.l
5385	}
5386	item = nxs_js_hslinbounds(item);
5387	result.push(item);
5388	
5389	item =  
5390	{
5391		h : hsl.h + (1/2),
5392		s : hsl.s,
5393		l : hsl.l
5394	}
5395	item = nxs_js_hslinbounds(item);
5396	result.push(item);
5397		
5398	return result;
5399}
5400
5401function nxs_js_getsplitcomplementaryhsl(hsl)
5402{
5403	nxs_js_log("before:");
5404	nxs_js_log(hsl);
5405
5406	var result = [];
5407	var item;
5408	
5409	item =  
5410	{
5411		h : hsl.h - (1/3),
5412		s : hsl.s,
5413		l : hsl.l
5414	}
5415	item = nxs_js_hslinbounds(item);
5416	result.push(item);
5417	
5418	//nxs_js_log("first:");
5419	//nxs_js_log(item);
5420	
5421	item =  
5422	{
5423		h : hsl.h,
5424		s : hsl.s,
5425		l : hsl.l
5426	}
5427	item = nxs_js_hslinbounds(item);
5428	result.push(item);
5429	
5430	//nxs_js_log("second:");
5431	//nxs_js_log(item);
5432	
5433	item =  
5434	{
5435		h : hsl.h + (1/3),
5436		s : hsl.s,
5437		l : hsl.l
5438	}
5439	item = nxs_js_hslinbounds(item);
5440	result.push(item);
5441
5442	//nxs_js_log("third1:");
5443	//nxs_js_log(item);
5444		
5445	return result;
5446}
5447
5448function nxs_js_getmonohsl(hsl)
5449{
5450	var result = [];
5451	var item;
5452	
5453	item =  
5454	{
5455		h : hsl.h,
5456		s : hsl.s,
5457		l : hsl.l
5458	}
5459	item = nxs_js_hslinbounds(item);
5460	result.push(item);
5461	
5462	return result;
5463}
5464
5465function nxs_js_gettriadbyanglehsl(hsl, angle)
5466{
5467	nxs_js_log("before:");
5468	nxs_js_log(hsl);
5469
5470	var result = [];
5471	var item;
5472	
5473	item =  
5474	{
5475		h : hsl.h + 0.5 - (angle/360),
5476		s : hsl.s,
5477		l : hsl.l
5478	}
5479	item = nxs_js_hslinbounds(item);
5480	result.push(item);
5481	
5482	//nxs_js_log("first:");
5483	//nxs_js_log(item);
5484	
5485	item =  
5486	{
5487		h : hsl.h,
5488		s : hsl.s,
5489		l : hsl.l
5490	}
5491	item = nxs_js_hslinbounds(item);
5492	result.push(item);
5493	
5494	//nxs_js_log("second:");
5495	//nxs_js_log(item);
5496	
5497	item =  
5498	{
5499		h : hsl.h + 0.5 + (angle/360),
5500		s : hsl.s,
5501		l : hsl.l
5502	}
5503	item = nxs_js_hslinbounds(item);
5504	result.push(item);
5505
5506	//nxs_js_log("third1:");
5507	//nxs_js_log(item);
5508		
5509	return result;
5510}
5511
5512function nxs_js_getanalogicbyanglehsl(hsl, angle)
5513{
5514	nxs_js_log("before:");
5515	nxs_js_log(hsl);
5516
5517	var result = [];
5518	var item;
5519	
5520	item =  
5521	{
5522		h : hsl.h - (angle/360),
5523		s : hsl.s,
5524		l : hsl.l
5525	}
5526	item = nxs_js_hslinbounds(item);
5527	result.push(item);
5528	
5529	//nxs_js_log("first:");
5530	//nxs_js_log(item);
5531	
5532	item =  
5533	{
5534		h : hsl.h,
5535		s : hsl.s,
5536		l : hsl.l
5537	}
5538	item = nxs_js_hslinbounds(item);
5539	result.push(item);
5540	
5541	//nxs_js_log("second:");
5542	//nxs_js_log(item);
5543	
5544	item =  
5545	{
5546		h : hsl.h + (angle/360),
5547		s : hsl.s,
5548		l : hsl.l
5549	}
5550	item = nxs_js_hslinbounds(item);
5551	result.push(item);
5552
5553	//nxs_js_log("third1:");
5554	//nxs_js_log(item);
5555		
5556	return result;
5557}
5558
5559
5560function nxs_js_getaccentedanalogicbyanglehsl(hsl, angle)
5561{
5562	var result = [];
5563	var item;
5564	
5565	item =  
5566	{
5567		h : hsl.h - (angle/360),
5568		s : hsl.s,
5569		l : hsl.l
5570	}
5571	item = nxs_js_hslinbounds(item);
5572	result.push(item);
5573	
5574	item =  
5575	{
5576		h : hsl.h,
5577		s : hsl.s,
5578		l : hsl.l
5579	}
5580	item = nxs_js_hslinbounds(item);
5581	result.push(item);
5582	
5583	item =  
5584	{
5585		h : hsl.h + (angle/360),
5586		s : hsl.s,
5587		l : hsl.l
5588	}
5589	item = nxs_js_hslinbounds(item);
5590	result.push(item);
5591
5592	item =  
5593	{
5594		h : hsl.h + 0.5,
5595		s : hsl.s,
5596		l : hsl.l
5597	}
5598	item = nxs_js_hslinbounds(item);
5599	result.push(item);
5600		
5601	return result;
5602}
5603
5604function nxs_js_gettetradbyanglehsl(hsl, angle)
5605{
5606	var result = [];
5607	var item;
5608	
5609	item =  
5610	{
5611		h : hsl.h,
5612		s : hsl.s,
5613		l : hsl.l
5614	}
5615	item = nxs_js_hslinbounds(item);
5616	result.push(item);
5617
5618	item =  
5619	{
5620		h : hsl.h + (angle/360),
5621		s : hsl.s,
5622		l : hsl.l
5623	}
5624	item = nxs_js_hslinbounds(item);
5625	result.push(item);
5626	
5627	item =  
5628	{
5629		h : hsl.h + 0.5,
5630		s : hsl.s,
5631		l : hsl.l
5632	}
5633	item = nxs_js_hslinbounds(item);
5634	result.push(item);
5635
5636	item =  
5637	{
5638		h : hsl.h + 0.5 + (angle/360),
5639		s : hsl.s,
5640		l : hsl.l
5641	}
5642	item = nxs_js_hslinbounds(item);
5643	result.push(item);
5644
5645		
5646	return result;
5647}
5648
5649
5650/**
5651 * Converts an HSL color value to RGB. Conversion formula
5652 * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
5653 * Assumes h, s, and l are contained in the set [0, 1] and
5654 * returns r, g, and b in the set [0, 255].
5655 *
5656 * @param   Number  h       The hue
5657 * @param   Number  s       The saturation
5658 * @param   Number  l       The lightness
5659 * @return  Array           The RGB representation
5660 */
5661function nxs_js_hsltorgb(hsl)
5662{
5663	if (hsl == null)	
5664	{
5665		return null;
5666	}
5667
5668	var h = hsl.h;
5669	var s = hsl.s;
5670	var l = hsl.l;
5671	
5672    var r, g, b;
5673
5674    if(s == 0){
5675        r = g = b = l; // achromatic
5676    }else{
5677        function hue2rgb(p, q, t){
5678            if(t < 0) t += 1;
5679            if(t > 1) t -= 1;
5680            if(t < 1/6) return p + (q - p) * 6 * t;
5681            if(t < 1/2) return q;
5682            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
5683            return p;
5684        }
5685
5686        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
5687        var p = 2 * l - q;
5688        r = hue2rgb(p, q, h + 1/3);
5689        g = hue2rgb(p, q, h);
5690        b = hue2rgb(p, q, h - 1/3);
5691    }
5692
5693    var result = {
5694    r : Math.round(r * 255), 
5695    g: Math.round(g * 255), 
5696    b: Math.round(b * 255)
5697    };
5698    
5699    return result;
5700}
5701
5702/*
5703kudos to http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
5704*/
5705function nxs_js_hextorgb(hex) {
5706	if (hex == null || hex == '')
5707	{
5708		nxs_js_log("warning; hex;" + hex);
5709		return { r: 0, g: 0, b: 0 }
5710	}
5711    // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
5712    var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
5713    hex = hex.replace(shorthandRegex, function(m, r, g, b) {
5714        return r + r + g + g + b + b;
5715    });
5716
5717    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
5718    return result ? {
5719        r: parseInt(result[1], 16),
5720        g: parseInt(result[2], 16),
5721        b: parseInt(result[3], 16)
5722    } : null;
5723}
5724
5725/* kudos to http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */
5726
5727function nxs_js_componenttohex(c) {
5728    var hex = c.toString(16);
5729    return hex.length == 1 ? "0" + hex : hex;
5730}
5731
5732function nxs_js_rgbtohex(rgb) 
5733{
5734	if (rgb == null)
5735	{
5736		return "#XXX";
5737	}
5738
5739	var r = rgb.r;
5740	var g = rgb.g;
5741	var b = rgb.b;
5742  return "#" + nxs_js_componenttohex(r) + nxs_js_componenttohex(g) + nxs_js_componenttohex(b);
5743}
5744
5745function nxs_js_hextohsl(hex)
5746{
5747	var rgb = nxs_js_hextorgb(hex);
5748	var hsl = nxs_js_rgbtohsl(rgb);
5749	return hsl;
5750}
5751
5752function nxs_js_displayStyleSheetProperties()
5753{
5754    var str = "";
5755    if( !document.styleSheets )
5756    {
5757        str = "Your browser does not support the stylesheets object.";
5758    }
5759    else if ( !document.styleSheets.length )
5760    {
5761        str = "There were no stylesheets found in the document.styleSheets collection.";
5762    }
5763    else
5764    {
5765    	nxs_js_log("outputting sheets:");
5766    	var sheetindex;
5767    	for (sheetindex in document.styleSheets)
5768    	{
5769    		if (!document.styleSheets.hasOwnProperty(sheetindex)) 
5770				{
5771					continue;
5772				}
5773
5774    		var sheet = document.styleSheets[sheetindex];
5775    		nxs_js_log(sheet);
5776    		 
5777    		nxs_js_log("HREF:" + sheet.href);
5778    		nxs_js_log("MEDIA:" + sheet.media);
5779    		nxs_js_log("OWNERNODE:");
5780    		nxs_js_log(sheet.ownerNode);
5781    	}
5782    }
5783    nxs_js_log(str);
5784}
5785
5786// css is the stylesheet contents to add / inject
5787// the stylesheetcontainer is an object that references the object of for example <style type="text/css" id="myObject"></style>
5788function nxs_js_setcss(css, containerbaseid)
5789{
5790	nxs_js_log("* setting css for " + containerbaseid);
5791	
5792	if(jQuery.browser.msie)
5793  {
5794		// great, thanks to MS we need multiple lame IE patches
5795		// first of all the injection itself is different...
5796		// see http://stackoverflow.com/questions/9050441/how-do-i-inject-styles-into-ie8
5797		// and second (even worse), IE 8 + 9 are only capable of handling 4095 selectors for
5798		// each css script. Thus, if the amount is too big, we need to split the css into
5799		// multiple parts and inject each
5800
5801		// var countmsg = nxs_js_getcssselectorcount(css);
5802		
5803		var chunksresult = nxs_js_getchunksofcss(css);
5804		for (var i = 0; i < nxs_js_getmaxservercsschunks(); i++)
5805		{
5806			// get script for this chunk
5807			var stylesheetcontainer = jQ_nxs(containerbaseid + i);
5808			var stylesheet = stylesheetcontainer.prop('styleSheet');
5809	  	if (stylesheet != null)
5810	  	{
5811	    	stylesheet.cssText=chunksresult.chunks[i];
5812	    }
5813	    else
5814	    {
5815	    	nxs_js_alert('failed to apply css!');
5816	    	nxs_js_log(stylesheet);
5817	    	nxs_js_log('likely the problem is that the number of stylesheets that can be applied in IE is limited to 32; did you exceed the number of allowed stylesheets?');
5818	    	nxs_js_displayStyleSheetProperties();
5819	    }
5820		}
5821  }
5822	else
5823	{
5824		// always store in containerbaseid 0 for non-ie browsers
5825		var i = 0;
5826		var stylesheetcontainer = jQ_nxs(containerbaseid + i);
5827		jQ_nxs(stylesheetcontainer).html(css);
5828	}
5829}
5830
5831function nxs_js_getkeys(lookup)
5832{
5833	var result = new Array();
5834	for(var key in lookup)
5835	{
5836		if (!lookup.hasOwnProperty(key)) 
5837		{
5838			continue;
5839		}
5840		
5841	  result[result.length] = key;
5842	}	
5843	return result;
5844}
5845
5846function nxs_js_sortbylength(a,b)
5847{
5848	var al = a.length;
5849	var bl = b.length;
5850	if (al == bl)
5851	{
5852		return 0;
5853	}
5854	else if (al < bl)
5855	{
5856		return 1;
5857	}
5858	else
5859	{
5860		return -1;
5861	}
5862}
5863
5864function nxs_js_removelinebreaks(content)
5865{
5866	return content.replace(/(\r\n|\n|\r)/gm,"");
5867}
5868
5869function nxs_js_removetabs(content)
5870{
5871	return content.replace(/\t/g, '');
5872}
5873
5874// kudos to http://stackoverflow.com/questions/3286874/remove-all-multiple-spaces-in-javascript-and-replace-with-single-space
5875function nxs_js_replacemultiplespaceswithsinglespace(content)
5876{
5877	return content.replace(/ +(?= )/g,'');
5878}
5879
5880function nxs_js_blendtemplatewithvariables(template, lookup)
5881{
5882	return nxs_js_blendtemplatewithvariables_v2(template, lookup, '$nxs_', '');
5883}
5884
5885// mixed the colorscheme template with the dictionary
5886function nxs_js_blendtemplatewithvariables_v2(template, lookup, keyprefix, keysuffix)
5887{
5888	if (template == null) { nxs_js_log('template not set?'); }
5889	if (lookup == null) { nxs_js_log('lookup not set?'); }
5890
5891	// "lineair" blending (note; this is not as sophisticated as SASS or LESS, but sufficient enough for now,
5892	// could be further enhanced for more complex replacements, like producing gradients
5893
5894	var keys;
5895	keys = nxs_js_getkeys(lookup);
5896	keys.sort(nxs_js_sortbylength);
5897	
5898	// replace placeholders 	
5899	for (index = 0; index < keys.length; ++index)
5900	{
5901		var key = keys[index];
5902		var key2 = keyprefix + key + keysuffix;
5903		// note: the regexp "g" part is required to replace all instances instead of just the first
5904		var valuetouse = lookup[key];
5905		//nxs_js_log('replacing key:' + key2 + ' with value:' + valuetouse);
5906		template=template.replace(new RegExp('\\' + key2, "g"), valuetouse);
5907	}
5908	
5909	if (template.indexOf("$") >= 0)
5910	{
5911		// it looks like we missed something...
5912		nxs_js_log('Warning, blender detected $ placeholder not being replaced; is the syntax of the template correct? did you miss a lookup placeholder? (for example use $nxs_color_base2_m)');
5913		nxs_js_log('template:');
5914		nxs_js_log(template);
5915		nxs_js_log('lookup:');
5916		nxs_js_log(lookup);
5917	}
5918	else
5919	{
5920		/*
5921		nxs_js_log('Blender ok');
5922		nxs_js_log('template:');
5923		nxs_js_log(template);
5924		nxs_js_log('lookup:');
5925		nxs_js_log(lookup);
5926		*/
5927	}
5928	
5929	return template;
5930}
5931
5932//
5933function nxs_js_updatecss_themecss_actualrequest(shouldusecacheifavailable, shouldupdatedom)
5934{
5935	
5936	var actualcss = null;
5937	var isdirty = false;
5938	var storagekey = nxs_js_get_adminurladminajax() + "nxs-dynamiccss-server-chunk";
5939	var localstorageavailable = Modernizr.localstorage;
5940	
5941	localstorageavailable = false; // overruled for now
5942	
5943	// store css
5944	if (shouldusecacheifavailable && localstorageavailable)
5945	{
5946		nxs_js_log("* Retrieving CSS from local storage, hopefull its there");
5947		actualcss = localStorage.getItem(storagekey);
5948	}
5949	
5950	if (actualcss == null)
5951	{
5952		nxs_js_log("* Cached data is not available, (re)producing CSS the hard way");
5953		
5954		// get active colorscheme 
5955		var colorschemelookup = nxs_js_getruntimecolorschemelookup();
5956		var runtimeurllookup = nxs_js_getruntimecsslookup();
5957		
5958		// blend all lookups
5959		var csslookup = jQuery.extend({}, colorschemelookup, runtimeurllookup);
5960	
5961		// the framework css will not be blended with lookups;
5962		// its required to contain end-css (if lookups
5963		// need to be translated, use the specifiekd csslookup parameter)
5964		var frameworkcss = nxs_js_get_frameworkcsstemplate(csslookup);
5965		var customcss = nxs_js_get_customcsstemplate(csslookup);
5966	
5967		// blend the customcss (note! we intentionally only blend the 
5968		// customcss, not the framework's css, this is done to keep performance high)
5969		var blendedcustomcss = nxs_js_blendtemplatewithvariables(customcss, csslookup);
5970	
5971		// we concatenate the end result; framework first, customcss is able 
5972		// to override styling as needed
5973		var actualcss = frameworkcss + blendedcustomcss;
5974		
5975		isdirty = true;
5976	}
5977	
5978	// store css
5979	if (isdirty && localstorageavailable)
5980	{
5981		nxs_js_log("* Updating CSS cache");
5982		try
5983		{
5984			localStorage.setItem(storagekey, actualcss);
5985		}
5986		catch(err)
5987		{
5988			// most likely reason; if a multisite
5989			// hosts multiple sites using sub folders,
5990			// the localstorage is shared with all sites,
5991			// if users accesses many sites, eventually will run
5992			// out of local storage, in that case we clear the 
5993			// localstorage to wipe cache of "other sites" too,
5994			// next time hopefully there will be enough storage left
5995			nxs_js_log("* Error storing cached CSS");
5996			localStorage.clear();
5997		}
5998	}
5999	else
6000	{
6001		nxs_js_log("* Leaving CSS cache as is (no update) because localstorage is n/a or because CSS is not dirty");
6002	}
6003	
6004	if (shouldupdatedom)
6005	{
6006		// update the css in the DOM
6007		nxs_js_setcss(actualcss, '#nxs-dynamiccss-server-chunk-');
6008		
6009		// if the dom was updated, and the cache was available and used, we will trigger another call
6010		// to update the cache in certain amount of msecs from now, based on the actual data (non-cached)
6011		// this way we have best of both worlds; an up to date cache, and a fast performing site :)
6012		if (localstorageavailable && shouldusecacheifavailable)
6013		{
6014			nxs_js_log("* CSS cache will be updated in 5000 msecs from now on");
6015			setTimeout(function() { nxs_js_log("* Waking up to update css cache"); nxs_js_updatecss_themecss_actualrequest(false, false); nxs_js_log("* Finished waking up (cache should now be up to date)"); }, 5000);
6016		}
6017	}
6018}
6019
6020// helper function to get the css output for a lineair gradient between the 2 specified colors
6021function nxs_js_getlineairgradientcss(colora, colorb)
6022{
6023	var result = "";
6024	
6025	var vendor = nxs_js_getvendorprefix();
6026	
6027	result += "background-color: " + colora + ";";
6028	result += "fill: " + colora + ";";
6029	
6030	if (vendor == "o" || vendor == "?")
6031	{
6032		result += "background: -o-linear-gradient(" + colorb + ", " + colora + ");";
6033	}
6034	else if (vendor == "mozilla" || vendor == "?")
6035	{
6036		result += "background: -moz-linear-gradient(" + colorb + ", " + colora + ");";
6037	}
6038	else if (vendor == "webkit" || vendor == "?")
6039	{
6040		result += "background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(" + colorb + "), to(" + colora + "));";
6041	}
6042	else if (vendor == "msie" || vendor == "?")
6043	{
6044
6045		result += "background: -ms-linear-gradient(" + colorb + ", " + colora + ");" + "filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=" + colorb + ",EndColorStr=" + colora + ");";
6046	}
6047	return result;
6048}
6049
6050// kudos to http://stackoverflow.com/questions/11333150/twitter-bootstrap-how-to-remove-gradient-mixin-in-subclass
6051function nxs_js_getflatbackgroundnogradientcss(hexcolor, alphafactor)
6052{
6053	var result = "";
6054	
6055	// NOTE the background-image: none is repeated intentionally, see link above function declaration
6056	
6057	var vendor = nxs_js_getvendorprefix();
6058		
6059	if (alphafactor == 1)
6060	{
6061		result += "background-color: " + hexcolor + ";";
6062		result += "fill: " + hexcolor + ";";
6063	}
6064	else if (alphafactor < 1)
6065	{
6066		// convert hex value to rgb
6067		var hexcolor = nxs_js_hextorgb(hexcolor);
6068		
6069		result += "background: rgb(" + hexcolor.r + ", " + hexcolor.g + ", " + hexcolor.b + "); /* The Fallback */ ";
6070		result += "background: rgba(" + hexcolor.r + ", " + hexcolor.g + ", " + hexcolor.b + ", " + alphafactor + ");";
6071
6072		result += "fill: rgb(" + hexcolor.r + ", " + hexcolor.g + ", " + hexcolor.b + "); /* The Fallback */ ";
6073		result += "fill: rgba(" + hexcolor.r + ", " + hexcolor.g + ", " + hexcolor.b + ", " + alphafactor + ");";
6074
6075		//nxs_js_log("hexcolor:" + hexcolor + "; alpha:" + alphafactor);   	
6076		//nxs_js_log("output:" + result);   	
6077	}
6078		
6079	result += "background-repeat: no-repeat;";
6080	
6081	if (vendor == "o" || vendor == "?")
6082	{
6083		result += "background-image: none;";
6084	}
6085	else if (vendor == "mozilla" || vendor == "?")
6086	{
6087		result += "background-image: none;";
6088	}
6089	else if (vendor == "webkit" || vendor == "?")
6090	{
6091		result += "background-image: none;";
6092		result += "background-image: none;";
6093	}
6094	else if (vendor == "msie" || vendor == "?")
6095	{
6096		result += "filter: none;";
6097	}
6098	
6099	// debug
6100	// result = "background-color: red !important;";
6101	
6102	return result;
6103}
6104
6105// helper function to get the css output for a lineair gradient between the 2 specified colors
6106function nxs_js_getflatcss(colora, alphafactor)
6107{
6108	return nxs_js_getflatbackgroundnogradientcss(colora, alphafactor);
6109}
6110
6111function nxs_js_updatecss_manualcss_actualrequest()
6112{
6113	// ------------------- UPDATE CSS
6114	
6115	// get active colorscheme 
6116	var colorschemelookup = nxs_js_getruntimecolorschemelookup();
6117	var runtimeurllookup = nxs_js_getruntimecsslookup();
6118
6119	// blend all lookups
6120	var csslookup = jQuery.extend({}, colorschemelookup, runtimeurllookup);
6121	
6122	var csstemplate = nxs_js_get_manualcsstemplate();
6123	var actualcss = nxs_js_blendtemplatewithvariables(csstemplate, csslookup);
6124	
6125	// update the css
6126	nxs_js_setcss(actualcss, '#nxs-dynamiccss-manual-chunk-');
6127}
6128
6129function nxs_js_rerender_facebookbom()
6130{
6131	if (typeof(FB) != "undefined" && FB != null ) 
6132	{
6133		FB.XFBML.parse();
6134	}
6135	else
6136	{
6137		// first time / not yet loaded
6138	}
6139}
6140
6141// kudos to http://stackoverflow.com/questions/4825683/how-do-i-create-and-read-a-value-from-cookie
6142// todo: the path of the cookie should be set to the root folder of the site, this is required for multisites that use folder names
6143function nxs_js_setcookie(name, value, expiretime) 
6144{
6145	var expires = "";
6146
6147	if (expiretime) {
6148		var d = new Date();
6149	    d.setTime(d.getTime() + expiretime);
6150	    var expires = " expires=" + d.toUTCString() + " ";
6151	}
6152
6153  	document.cookie = name + "=" + value + "; " + expires + "; path=/";
6154}
6155
6156function nxs_js_getcookie(c_name) 
6157{
6158  if (document.cookie.length > 0) 
6159  {
6160    c_start = document.cookie.indexOf(c_name + "=");
6161    if (c_start != -1) 
6162    {
6163      c_start = c_start + c_name.length + 1;
6164      c_end = document.cookie.indexOf(";", c_start);
6165      if (c_end == -1) {
6166          c_end = document.cookie.length;
6167      }
6168      return unescape(document.cookie.substring(c_start, c_end));
6169    }
6170  }
6171  return "";
6172}
6173
6174function nxs_js_tagcolumns()
6175{
6176	//nxs_js_log("tagging columns...");
6177	jQuery.each
6178	(
6179		jQ_nxs(".nxs-placeholder-list"), function(index, listelement)
6180		{
6181			// nxs_js_log('row found');
6182			var columnindex = 1;
6183		
6184			var placeholders = jQ_nxs(listelement).children(".nxs-placeholder");
6185			var columnmax = nxs_js_findclassidentificationwithprefix(listelement, "nxs-columnsperrow-", -1);
6186			if (columnmax == -1)
6187			{
6188				// if not found
6189				// nxs_js_log("fallback :)");
6190				columnmax = placeholders.length;
6191			}
6192			else
6193			{
6194				// nxs_js_log("got it :)");
6195			}
6196			
6197			jQuery.each
6198			(
6199				placeholders, function(index, currentplaceholder)
6200				{
6201					jQ_nxs(currentplaceholder).addClass("nxs-column-" + columnindex + "-" + columnmax);
6202					if (columnindex == columnmax)
6203					{
6204						// last column
6205						jQ_nxs(currentplaceholder).addClass("nxs-column-lastinrow");
6206					}
6207					columnindex++;
6208					if (columnindex > columnmax)
6209					{
6210						columnindex = 1;
6211					}
6212				}
6213			);
6214		}
6215	);
6216}
6217
6218// kudos to https://gist.github.com/padolsey/527683
6219var nxs_js_ie=function(){for(var a=3,b=document.createElement("b"),c=b.all||[];b.innerHTML="<!--[if gt IE "+ ++a+"]><i><![endif]-->",c[0];);return 4<a?a:document.documentMode}();
6220function nxs_js_tagbrowsers()
6221{
6222	jQ_nxs("html").addClass("nxs-vendor-" + nxs_js_getvendorprefix());
6223
6224	if (nxs_js_ie)
6225	{
6226		var ie = nxs_js_ie;
6227		jQ_nxs("html").addClass("nxs-ie");
6228		var classname = "nxs-ie-" + ie;
6229		jQ_nxs("html").addClass(classname);
6230
6231		var compatibleloop = 0;
6232		while (compatibleloop < 5)
6233		{
6234			var classname = "nxs-ie-lte-" + ie;
6235			jQ_nxs("html").addClass(classname);
6236			compatibleloop++;
6237			ie++;
6238		}
6239	}
6240	else
6241	{
6242		jQ_nxs("html").addClass("nxs-non-ie");
6243	}
6244}
6245
6246function nxs_js_deviceistouchdevice()
6247{
6248	var result = 'ontouchstart' in document.documentElement;
6249	return result;
6250}
6251
6252function nxs_js_tagresponsiveness()
6253{
6254	jQ_nxs("html").addClass("nxs-site-responsive");
6255}
6256
6257function nxs_js_tagfrontendbackend()
6258{
6259	if (nxs_js_isinfrontend())
6260	{
6261		jQ_nxs("html").addClass("nxs-frontend");
6262	}
6263	else
6264	{
6265		jQ_nxs("html").addClass("nxs-backend");
6266	}
6267}
6268
6269
6270function nxs_js_getviewports()
6271{
6272	var result = 
6273	[
6274	320, 		// iphone portrait
6275	480, 		// 
6276	720, 		// 
6277	960, 		// ipad landscape / desktop
6278	1200, 	// desktop
6279	1440		// desktop
6280	];	
6281	return result;
6282}
6283
6284function nxs_js_setupviewportlistener()
6285{
6286	jQ_nxs(document).bind('nxs_event_resizeend', function() { nxs_js_setupviewportlistener_actual(); });
6287	// initial call is used to set things up
6288	nxs_js_setupviewportlistener_actual();
6289}
6290
6291function nxs_js_setupviewportlistener_actual()
6292{
6293	nxs_js_log("nxs_js_setupviewportlistener_actual");
6294
6295	var previousactiveviewport = nxs_js_activeviewport;
6296	//nxs_js_log("previous:" + previousactiveviewport);
6297	
6298	var currentactiveviewport = nxs_js_deriveactiveviewport();
6299	//nxs_js_log("currentactiveviewport:" + currentactiveviewport);
6300	
6301	if (previousactiveviewport != currentactiveviewport)
6302	{
6303		// store new value
6304		nxs_js_activeviewport = currentactiveviewport;
6305		
6306		if (previousactiveviewport != -1)
6307		{
6308			nxs_js_log('broadcasting nxs_event_viewportchanged');
6309			jQ_nxs(document).trigger('nxs_event_viewportchanged');
6310		}
6311		else
6312		{
6313			// we don't trigger when the initial viewport is set (we consider that 'not changed')
6314		}
6315	}
6316}
6317
6318function nxs_js_deriveactiveviewport()
6319{
6320	var widthofbrowserwindow = jQ_nxs(window).width();
6321	var viewports = nxs_js_getviewports();
6322	var biggest = 0;
6323	for (var i = 0; i < viewports.length; i++)
6324	{
6325		var currentviewport = viewports[i];
6326		if (currentviewport >= biggest)
6327		{
6328			if (widthofbrowserwindow >= currentviewport)
6329			{
6330				biggest = currentviewport;
6331			}
6332		}
6333	}
6334	return biggest;
6335}
6336
6337function nxs_js_tagviewports()
6338{
6339	var widthofbrowserwindow = jQ_nxs(window).width();
6340	
6341	var viewports = nxs_js_getviewports();
6342	for (var i = 0; i < viewports.length; i++)
6343	{
6344		var currentviewport = viewports[i];
6345		
6346		// greater than classes
6347		var compareto = currentviewport - 1;
6348		if (widthofbrowserwindow >= compareto)
6349		{
6350			var classnaam = "nxs-viewport-gt-" + compareto;
6351			jQ_nxs("html").addClass(classnaam);
6352		}
6353		else
6354		{
6355			jQ_nxs("html").removeClass("nxs-viewport-gt-" + compareto);
6356		}
6357		
6358		// less than or equal classes
6359		var compareto = currentviewport - 1;
6360		if (widthofbrowserwindow <= compareto)
6361		{
6362			var classnaam = "nxs-viewport-lte-" + compareto;
6363			jQ_nxs("html").addClass(classnaam);
6364		}
6365		else
6366		{
6367			jQ_nxs("html").removeClass("nxs-viewport-lte-" + compareto);
6368		}
6369		
6370		// active viewport
6371		var compareto = currentviewport;
6372		jQ_nxs("html").removeClass("nxs-viewport-is-" + compareto);
6373		// the adding of the active class happens below
6374	}
6375	
6376	// equal classes
6377	jQ_nxs("html").addClass("nxs-viewport-is-" + nxs_js_deriveactiveviewport());
6378
6379	
6380}
6381
6382function nxs_js_tagdevices()
6383{
6384	var deviceistouchdevice = nxs_js_deviceistouchdevice()
6385	if (deviceistouchdevice)
6386	{
6387		jQ_nxs("html").addClass("nxs-touchdevice");
6388	}
6389	else
6390	{
6391		jQ_nxs("html").addClass("nxs-nontouchdevice");
6392	}
6393}
6394
6395function nxs_js_menuitemclick(domelement, event)
6396{
6397	if (event == "mouseleave")
6398	{
6399		jQ_nxs(domelement).closest(".nxs-widget").find("li.nxs-touched").removeClass("nxs-touched");
6400		//nxs_js_log("mouseleave");
6401		return;
6402	}
6403	
6404	var closestwidget = jQ_nxs(domelement).closest(".nxs-widget");
6405	
6406	if (event == "touch")
6407	{
6408		if (jQ_nxs(domelement).closest("li").hasClass("nxs-touched"))
6409		{
6410			// if item it touched for the 2nd time, hide all touched items
6411			jQ_nxs(closestwidget).find(".nxs-touched").removeClass("nxs-touched");
6412
6413			// if item has a link, redirect to link
6414			var href = jQ_nxs(domelement).attr('href');
6415			if (href){
6416				window.location.href = href;
6417			}
6418			return;
6419		}
6420	}
6421	
6422	if (event == "mouseenter" || event == "touch" || event == "click")
6423	{
6424		// wipe previous path
6425		jQ_nxs(closestwidget).find(".nxs-touched").removeClass("nxs-touched");
6426		// mark new path
6427		jQ_nxs(domelement).parentsUntil(".nxs-widget").addClass("nxs-touched");
6428	}
6429	
6430	// if user click on a domelement in the menu,
6431	// we shouldn't redirect immediately,
6432	// if the item has child items and the device is a touch device, 
6433	// and the sub menu is not yet showing, absorb the click
6434
6435	if (event == 'touch' || event == 'click')
6436	{
6437		if (nxs_js_deviceistouchdevice()) 
6438		{
6439			// the submenu is not an immediate child of the 'this' link,
6440			// its a child of a sibling element ...
6441			if (jQ_nxs(domelement).parent().children(".nxs-sub-menu").length > 0)
6442			{
6443				// nxs_js_log('NOT about to follow that link!');
6444			}
6445			else
6446			{
6447				var url = jQ_nxs(domelement).attr("nxsurl");
6448				if ((url == null || url == ""))
6449				{
6450					// empty element; no url, nothing to do
6451				}
6452				else
6453				{
6454					nxs_js_redirect(url);
6455				}
6456			}
6457		}
6458		else
6459		{
6460			var url = jQ_nxs(domelement).attr("nxsurl");
6461			if ((url == null || url == ""))
6462			{
6463				// nothing to do
6464			}
6465			else
6466			{
6467				// regular redirect
6468				nxs_js_redirect(url);
6469			}
6470		}
6471	}
6472}
6473
6474function nxs_js_doesuserimpactstyle()
6475{
6476	var result = false;
6477	if (nxs_js_userhasadminpermissions())
6478	{
6479		if (!nxs_js_inwpbackend())
6480		{
6481			// if menu shows... (color pickers, etc.)
6482			if (jQ_nxs("#nxs-admin-tabs").length > 0)
6483			{
6484				result = true;
6485			}
6486		}
6487	}
6488	
6489	return result;
6490}
6491
6492// returns the color scheme lookup, according to the runtime environment; if the 
6493// browser is in readonly mode, this means the lookup is used as defined on the serverside,
6494// otherwise the values from the flyout menu are used
6495function nxs_js_getruntimecolorschemelookup()
6496{
6497	var corecsslookup;
6498	if (nxs_js_doesuserimpactstyle())
6499	{ 
6500		// dynamic lookup
6501		corecsslookup = nxs_js_getcsslookupflyoutmenu();
6502		
6503		//nxs_js_log('nxs_js_getcsslookupflyoutmenu:');
6504		//nxs_js_log(corecsslookup);
6505		//nxs_js_log('-------------');
6506	}
6507	else
6508	{
6509		// static lookup
6510		corecsslookup = nxs_js_getcolorschemeaccordingtoserverside();
6511	}
6512	
6513	//
6514	//
6515	//
6516	
6517	var derivedcsslookup;
6518	derivedcsslookup = nxs_js_getderivedcsslookup(corecsslookup);
6519	
6520	var result = jQuery.extend({}, corecsslookup, derivedcsslookup);
6521
6522	//nxs_js_log('mixed:');
6523	//nxs_js_log(result);
6524	
6525	return result;
6526}
6527
6528// converts 1.0 into 1-0
6529function nxs_js_getdashedtextrepresentation_for_numericvalue(currentvalue)
6530{
6531	var wholepart = Math.floor(currentvalue);
6532	var fractionpart = nxs_js_getfractionasstring(currentvalue);
6533	var result = wholepart + '-' + fractionpart;
6534	return result;
6535}
6536
6537// gets derived css lookup variables based on existing lookup
6538function nxs_js_getderivedcsslookup(corecsslookup)
6539{
6540	//nxs_js_log(corecsslookup);
6541	var result = {}
6542	var colors = nxs_js_getcolorsinpalette();
6543	//nxs_js_log('colors:');
6544	//nxs_js_log(colors);
6545	
6546	var coloralphas = nxs_js_getcoloralphas();
6547	
6548	for(i=0;i<colors.length;i++)
6549	{
6550		var currentcolor = colors[i];
6551		
6552		for(subtypei=1;subtypei<=2; subtypei++)
6553		{
6554			var identity = currentcolor + subtypei;
6555			var hexcolor = corecsslookup['color_' + currentcolor + subtypei + '_m'];
6556			
6557			if (hexcolor != "" && hexcolor != null)
6558			{
6559				//nxs_js_log('hexcolor is set for ' + currentcolor + ':' + hexcolor);
6560				//nxs_js_log(hexcolor);
6561			
6562				var rgb = nxs_js_hextorgb(hexcolor);
6563				//nxs_js_log(rgb);
6564				
6565				var lightDelta = 0.2;
6566				
6567				result['color_' + identity + '_dd'] = nxs_js_gethextransformedrgblight(rgb, -lightDelta-lightDelta);	// 2x darker
6568				result['color_' + identity + '_d'] = nxs_js_gethextransformedrgblight(rgb, -lightDelta);								// 1x darker		
6569				result['color_' + identity + '_l'] = nxs_js_gethextransformedrgblight(rgb, +lightDelta);
6570				result['color_' + identity + '_ll'] = nxs_js_gethextransformedrgblight(rgb, +lightDelta+lightDelta);	// 2x lighter
6571				
6572				var nxsd = result['color_' + identity + '_d'];
6573				var nxsm = hexcolor;
6574				var nxsl = result['color_' + identity + '_l'];
6575				
6576				result['gradient_' + identity + '_dm'] = nxs_js_getlineairgradientcss(nxsd, nxsm);
6577				result['gradient_' + identity + '_ml'] = nxs_js_getlineairgradientcss(nxsm, nxsl);
6578				
6579				// flat colors have to take into consideration the alpha's (100%, 80%, 60%, etc.)
6580				for (var ca_i in coloralphas)
6581				{
6582					if (!coloralphas.hasOwnProperty(ca_i)) 
6583					{
6584						continue;
6585					}
6586					
6587					var currentcoloralpha = coloralphas[ca_i];
6588					var alphasuffix;
6589					
6590					if (currentcoloralpha < 1)
6591					{
6592						alphasuffix = '-a' + nxs_js_getdashedtextrepresentation_for_numericvalue(currentcoloralpha);
6593					}
6594					else if (currentcoloralpha == 1)
6595					{
6596						// not applicable
6597						alphasuffix = '';
6598					}
6599					else
6600					{
6601						nxs_js_log("unsupported currentcoloralpha;" + currentcoloralpha);
6602					}
6603				
6604					result['flat_' + identity + alphasuffix] = nxs_js_getflatcss(nxsm, currentcoloralpha);
6605				}
6606			}
6607			else
6608			{
6609				nxs_js_log('hexcolor is not set for ' + currentcolor);
6610			}
6611		}
6612	}
6613	
6614	return result;
6615}
6616
6617// return the color scheme lookup, according to the color pickers in the flyout menu
6618function nxs_js_getcsslookupflyoutmenu()
6619{
6620	// inject current colorscheme
6621	var colorschemelookup = {};
6622	
6623	var colortypes = nxs_js_getcolorsinpalette();
6624	var subtypes = ['1','2'];
6625	
6626	for (var i in colortypes)
6627	{
6628		if (!colortypes.hasOwnProperty(i)) 
6629		{
6630			continue;
6631		}
6632			
6633		var currentcolortype = colortypes[i];
6634		// for example 'primary' color, or 'secundary'
6635		
6636		for (var sti in subtypes)
6637		{
6638			if (!subtypes.hasOwnProperty(sti)) 
6639			{
6640				continue;
6641			}
6642			
6643			var currentsubtype = subtypes[sti];
6644			var identification = currentcolortype + currentsubtype;
6645			colorschemelookup['color_' + identification + '_m'] = jQ_nxs('#vg_color_' + identification + '_m').val();
6646		}
6647	};
6648	
6649	return colorschemelookup;
6650}
6651
6652function nxs_js_getfractionasstring(n) 
6653{
6654	var result;
6655  if (n != 0) 
6656  {
6657    var fractionpart = n.toString();
6658    
6659    fractionpart = fractionpart.split('.');
6660    if (fractionpart.length == 2)
6661    {
6662    	fractionpart = fractionpart[1];
6663    	result = fractionpart.toString();
6664    }
6665    else
6666    {
6667    	result = "0";
6668    }
6669    //
6670  }
6671  else
6672  {
6673  	result = "0";
6674  }
6675  
6676  return result;
6677}
6678
6679function nxs_js_debug_cssoutput(msg, css)
6680{
6681	nxs_js_log("--------------------------");
6682	nxs_js_log("DEBUG CSS FOR:" + msg);
6683
6684	css= nxs_js_replacemultiplespaceswithsinglespace(css);
6685	css = nxs_js_removetabs(css);
6686	
6687	var countmsg = nxs_js_getcssselectorcount(css);
6688	nxs_js_alert("selectors used:" + countmsg);
6689	
6690	nxs_js_log("css:");
6691	nxs_js_log(css);
6692}
6693
6694function nxs_js_createcssstyling_fontsizeheading(headingelement, multiplier, fontscale, factor_textfontsize)
6695{
6696	// step 1: ensure multiplier exists in available fontsizes
6697	var availablefontsizes = nxs_js_getstyletypevalues("fontsize");
6698	if (jQuery.inArray(multiplier, availablefontsizes) < 0)
6699	{
6700		nxs_js_alert('warning, unsupported multiplier;' + multiplier);
6701		nxs_js_log('multiplier:');
6702		nxs_js_log(multiplier);
6703		nxs_js_log('availablefontsizes:');
6704		nxs_js_log(availablefontsizes);
6705		return;
6706	}
6707	
6708	// step 2: build css
6709
6710	var u = '';
6711	u += nxs_js_createcssstyling(
6712  {
6713      multipliers: [multiplier], 
6714      cssparameters: 
6715      [ 
6716      	{
6717        	scale: fontscale,
6718        	factor: factor_textfontsize,
6719        	// remove #nxs-container selector from framework.css
6720          csstemplate: ' \
6721          	' + headingelement + ', \
6722          	#nxs-container #nxs-content-container ' + headingelement + ' span \
6723          	{ \
6724          		font-size: $nxs_formularesult;px;\
6725          		line-height: 1.2em;\
6726          	} \
6727          	'
6728        },
6729      ]
6730    }
6731  );
6732  return u;
6733}
6734
6735function nxs_js_createcssstyling(options) 
6736{    
6737  var result = '';
6738  var multipliers = options.multipliers;
6739  var cssparameters =  options.cssparameters;
6740  
6741  for (var i in multipliers) 
6742  {
6743		if (!multipliers.hasOwnProperty(i)) 
6744		{
6745			continue;
6746		}
6747
6748    var currentmultiplier = multipliers[i];
6749    
6750    var wholepart = Math.floor(currentmultiplier);
6751    
6752    // we need to return integers, not fractions to be able to concatenate with the class name
6753    var fractionpart = nxs_js_getfractionasstring(currentmultiplier);
6754    
6755    for (var j in cssparameters ) 
6756    {
6757    	if (!cssparameters.hasOwnProperty(j)) 
6758			{
6759				continue;
6760			}
6761			
6762    	var currentcssparameter = cssparameters[j];
6763
6764    	var identification = wholepart + '-' + fractionpart;
6765    	var csstemplate = currentcssparameter.csstemplate;
6766    	var csstemplate = nxs_js_removelinebreaks(csstemplate);
6767    	var csstemplate = nxs_js_removetabs(csstemplate);
6768    	var csstemplate = nxs_js_replacemultiplespaceswithsinglespace(csstemplate);
6769    		
6770 	    var factor = currentcssparameter.factor;
6771			if (factor == null)
6772			{
6773				// 
6774				factor = options.factor;
6775			}
6776			
6777			var resultoffset = currentcssparameter.resultoffset;
6778			if (resultoffset == null)
6779			{
6780				resultoffset = options.resultoffset;
6781				if (resultoffset == null)
6782				{
6783					resultoffset = 0;
6784				}
6785			}
6786			
6787			var scale = currentcssparameter.scale;
6788			if (scale == null)
6789			{
6790				scale = options.scale;
6791				if (scale == null)
6792				{
6793					scale = 1;
6794				}
6795			}
6796    	
6797      if (csstemplate != null)
6798      {
6799      	// apply template
6800      	var lookup = { 
6801      		"formularesult;": Math.round((currentmultiplier * factor * scale) + resultoffset), 	// will replace variable $nxs_formularesult;
6802      		"identification;": identification // will replace variable $nxs_identification;
6803      	};
6804      	
6805      	// apply template
6806      	result = result + nxs_js_blendtemplatewithvariables(csstemplate, lookup);
6807      }
6808			else
6809			{
6810				nxs_js_alert("no css template found");
6811				nxs_js_log(options);
6812      }
6813    }
6814  }
6815	//nxs_js_log(result);
6816	return result; 
6817}
6818
6819function nxs_js_get_themecsstemplate_part1_colorzen(cssprefix, csspostfix, zenprefix, csslookup, csspostfixanchors)
6820{
6821	if (csspostfixanchors == null)
6822	{
6823		csspostfixanchors = csspostfix;
6824	}
6825
6826	var u = "";
6827	var coloralphas = nxs_js_getcoloralphas();
6828	var colortypes = nxs_js_getcolorsinpalette();
6829	
6830	for (var i in colortypes)
6831	{
6832		if (!colortypes.hasOwnProperty(i)) 
6833		{
6834			continue;
6835		}
6836
6837		var currentcolortype = colortypes[i];
6838		
6839		// currentcolortype is for example 'c1', or 'base1'
6840		var identification = currentcolortype;
6841		if (zenprefix == null || zenprefix == "")
6842		{
6843			zenprefix = "nxs-colorzen-";
6844		}
6845		var cssinnerprefix = zenprefix + currentcolortype;
6846		
6847		var comparecolorhex = csslookup["color_" + identification + "2_m"];
6848		var comparecolorrgb = nxs_js_hextorgb(comparecolorhex);
6849		var comparecolorhsl = nxs_js_rgbtohsl(comparecolorrgb);			
6850		var lighttreshhold = 0.7;
6851		var isbackgroundcolorrelativelydark = comparecolorhsl.l < lighttreshhold;
6852		
6853		// COLOR IQ :)
6854		// GRADIENTS --------------
6855		
6856		if (currentcolortype == "base")
6857		{
6858			/* BACKGROUND COLOR AND TEXT & TITLES (OPPOSITE OF BACKGROUND) */
6859			u = u + cssprefix + "." + cssinnerprefix + "1-ml " + csspostfix + " \
6860			{ \
6861				border-color: " + csslookup["color_" + identification + "1_d"] + ";\
6862				color: " + csslookup["color_" + identification + "2_d"] + ";\
6863				text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + ";\
6864				" + csslookup["gradient_" + identification + "1_ml"] + "\
6865			}";
6866	
6867			u = u + cssprefix + "." + cssinnerprefix + "1-dm " + csspostfix + "\
6868			{\
6869				border-color: " + csslookup["color_" + identification + "1_dd"] + ";\
6870				color: " + csslookup["color_" + identification + "2_dd"] + ";\
6871				text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + ";\
6872				" + csslookup["gradient_" + identification + "1_dm"] + "\
6873			}";
6874		}
6875		else
6876		{
6877			// skip colorzen for the "1" variations for others than "base"; only base1 is used
6878		}
6879		
6880		if (isbackgroundcolorrelativelydark)
6881		{
6882			var textcolor = csslookup["color_" + identification + "1_ll"];
6883			var textshadowcolor = csslookup["color_" + identification + "2_dd"];
6884		}
6885		else
6886		{
6887			var textcolor = "black";
6888			var textshadowcolor = "white";
6889		}
6890		
6891		u = u + cssprefix + "." + cssinnerprefix + "2-ml " + csspostfix + "\
6892		{\
6893			border-color: " + csslookup["color_" + identification + "2_d"] + ";\
6894			" + csslookup["gradient_" + identification + "2_ml"] + "\
6895			color: " + textcolor + ";\
6896			text-shadow: 1px 1px 1px " + textshadowcolor + ";\
6897		}";
6898		
6899		if (isbackgroundcolorrelativelydark)
6900		{
6901			var textcolor = csslookup["color_" + identification + "1_l"];
6902			var textshadowcolor = csslookup["color_" + identification + "2_dd"];
6903		}
6904		else
6905		{
6906			var textcolor = "black";
6907			var textshadowcolor = "white";
6908		}
6909
6910		u = u + cssprefix + "." + cssinnerprefix + "2-dm " + csspostfix + "\
6911		{\
6912			border-color: " + csslookup["color_" + identification + "2_dd"] + ";\
6913			" + csslookup["gradient_" + identification + "2_dm"] + "\
6914			color: " + textcolor +";\
6915			text-shadow: 1px 1px 1px " + textshadowcolor + ";\
6916		}";
6917
6918		
6919		
6920		/* ANCHORS */
6921		
6922		if (currentcolortype == "base")
6923		{
6924			u = u + cssprefix + "." + cssinnerprefix + "1-ml " + csspostfixanchors + " a { color: " + csslookup["color_" + identification + "2_d"] + "; text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + "; }";
6925			u = u + cssprefix + "." + cssinnerprefix + "1-dm " + csspostfixanchors + " a { color: " + csslookup["color_" + identification + "2_dd"] + "; text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + "; }";
6926		}
6927		else
6928		{
6929			// skip colorzen for the "1" variations for others than "base"; only base1 is used
6930		}
6931		
6932		if (isbackgroundcolorrelativelydark)
6933		{
6934			var textcolor = csslookup["color_" + identification + "1_ll"];
6935			var textshadowcolor = csslookup["color_" + identification + "2_dd"];
6936		}
6937		else
6938		{
6939			var textcolor = "black";
6940			var textshadowcolor = "white";
6941		}
6942		
6943		u = u + cssprefix + "." + cssinnerprefix + "2-ml " + csspostfixanchors + " a\
6944		{\
6945			color: " + textcolor + ";\
6946			text-shadow: 1px 1px 1px " + textshadowcolor + ";\
6947		}";
6948		
6949		if (isbackgroundcolorrelativelydark)
6950		{
6951			var textcolor = csslookup["color_" + identification + "1_l"];
6952			var textshadowcolor = csslookup["color_" + identification + "2_dd"];
6953		}
6954		else
6955		{
6956			var textcolor = "black";
6957			var textshadowcolor = "white";
6958		}
6959		
6960		u = u + cssprefix + "." + cssinnerprefix + "2-dm " + csspostfixanchors + " a\
6961		{\
6962			color: " + textcolor + ";\
6963			text-shadow: 1px 1px 1px " + textshadowcolor + ";\
6964		}";
6965		
6966		
6967		
6968		// FLAT --------------
6969		
6970		/* TEXT & TITLES (OPPOSITE OF BACKGROUND) */
6971		
6972		// ------------
6973		// colorzen for flat colors
6974		
6975		var coloralphas = nxs_js_getcoloralphas();
6976		for (var i in coloralphas)
6977		{
6978			if (!coloralphas.hasOwnProperty(i)) 
6979			{
6980				continue;
6981			}
6982			
6983			var currentcoloralpha = coloralphas[i];
6984			var alphasuffix;
6985			
6986			if (currentcoloralpha < 1)
6987			{
6988				alphasuffix = '-a' + nxs_js_getdashedtextrepresentation_for_numericvalue(currentcoloralpha);
6989			}
6990			else if (currentcoloralpha == 1)
6991			{
6992				// not applicable
6993				alphasuffix = '';
6994			}
6995			else
6996			{
6997				nxs_js_log("unsupported currentcoloralpha;" + currentcoloralpha);
6998			}
6999			
7000			// overruled: background and border are 100% black
7001			u = u + cssprefix + "." + cssinnerprefix + "1" + alphasuffix + " " + csspostfix + "\
7002			{\
7003				" + nxs_js_getflatbackgroundnogradientcss('#FFFFFF', currentcoloralpha) + ";\
7004				border-color:  #C6C6C6;\
7005				color: " + csslookup["color_" + identification + "2_d"] + ";\
7006				text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + ";\
7007			}";
7008			
7009			// regular color			
7010			u = u + cssprefix + "." + cssinnerprefix + "2" + alphasuffix + " " + csspostfix + "\
7011			{";
7012			
7013				if (currentcolortype == "base")
7014				{
7015					// overruled: background and border are 100% black
7016					u = u + "\
7017						border-color: #000000;\
7018						" + nxs_js_getflatbackgroundnogradientcss('#000000', currentcoloralpha) + ";\
7019					";
7020				}
7021				else
7022				{
7023					u = u + "\
7024						border-color: " + csslookup["color_" + identification + "2_d"] + ";\
7025						" + csslookup["flat_" + identification + "2" + alphasuffix] + "\
7026					";
7027					//nxs_js_log("key:");
7028					//nxs_js_log("flat_" + identification + "2-a0-8");
7029				}
7030	
7031				if (isbackgroundcolorrelativelydark)
7032				{
7033					var textcolor = csslookup["color_" + identification + "1_ll"];
7034					var textshadowcolor = csslookup["color_" + identification + "2_dd"];
7035				}
7036				else
7037				{
7038					var textcolor = "black";
7039					var textshadowcolor = "white";
7040				}
7041			
7042				u = u + "\
7043					color: " + textcolor + ";\
7044					text-shadow: 1px 1px 1px " + textshadowcolor + ";\
7045					";
7046				
7047			u = u + "}";
7048		}
7049		
7050		/* ANCHORS FLAT COLOR */		
7051		
7052		u = u + cssprefix + "." + cssinnerprefix + "1 " + csspostfixanchors + " a\
7053		{\
7054			color: " + csslookup["color_" + identification + "2_dd"] + ";\
7055			text-shadow: 1px 1px 1px " + csslookup["color_" + identification + "1_ll"] + ";\
7056		}";
7057		
7058		if (isbackgroundcolorrelativelydark)
7059		{
7060			var textcolor = csslookup["color_" + identification + "1_l"];
7061			var textshadowcolor = csslookup["color_" + identification + "2_dd"];
7062		}
7063		else
7064		{
7065			var textcolor = "black";
7066			var textshadowcolor = "white";
7067		}
7068		
7069		u = u + cssprefix + "." + cssinnerprefix + "2 " + csspostfixanchors + " a\
7070		{\
7071			color: " + textcolor + ";\
7072			text-shadow: 1px 1px 1px " + textshadowcolor + ";\
7073		}";
7074	}
7075	
7076	//nxs_js_log("-");
7077	//nxs_js_log("colorzen output:" + csspostfixanchors);
7078	//nxs_js_log(u);
7079	
7080	return u;
7081}
7082
7083function nxs_js_get_themecsstemplate_part1_anchorlinkcolors(cssprefix, pseudo, csslookup)
7084{
7085	var u = "";
7086	
7087	u += "/* output of nxs_js_get_themecsstemplate_part1_anchorlinkcolors */";
7088	
7089	var colortypes = nxs_js_getcolorsinpalette();
7090
7091	for (var i in colortypes)
7092	{
7093		if (!colortypes.hasOwnProperty(i)) 
7094		{
7095			continue;
7096		}		
7097		
7098		var currentcolortype = colortypes[i];
7099		var identification = currentcolortype;
7100		
7101		/* EXPLICIT ANCHOR COLORS */
7102		
7103		var variations = ["dd", "d", "m", "l", "ll"];
7104		for (var i in variations) 
7105	  {
7106	    var currentvariation = variations[i];
7107	    
7108	    var selector = "nxs-linkcolorvar-" + currentcolortype + "2-" + currentvariation;
7109	    var colorvar = csslookup["color_" + identification + "2_" + currentvariation];
7110	    
7111	    // todo: isolate text-shadow: none in seperate css selector?
7112	     
7113			u = u + "\
7114				" + cssprefix + "." + selector + " .nxs-applylinkvarcolor a" + pseudo + "\
7115				{ \
7116					color: " + colorvar + ";\
7117					text-shadow: none;\
7118				}	\
7119				";
7120			
7121			
7122			if (currentcolortype == 'base')
7123			{
7124				// special case; if the currentcolortype == "base" we should also output the 1- version (for white colors)
7125				var selector = "nxs-linkcolorvar-" + currentcolortype + "1-" + currentvariation;
7126	   		var colorvar = csslookup["color_" + identification + "1_" + currentvariation];
7127	   		
7128	   		u = u + "\
7129				" + cssprefix + "." + selector + " .nxs-applylinkvarcolor a" + pseudo + "\
7130				{ \
7131					color: " + colorvar + ";\
7132					text-shadow: none;\
7133				}	\
7134				";
7135				
7136			}
7137		}
7138	}
7139
7140	return u;
7141}
7142
7143function nxs_js_get_nxsrefurlspecial() 
7144{ 
7145	var url = nxs_js_geturlcurrentpage();
7146	var base64encodedurl = nxs_js_base64_encode(url);
7147	var result = nxs_js_urldecode(base64encodedurl); 
7148	return result;
7149}
7150
7151function nxs_js_cssremovecomments(haystack)
7152{
7153	// *? = ungreedy
7154	// assumes single line css!
7155	return haystack.replace(/ *\/\*[^)]*?\*\/ */g, "");
7156}
7157
7158function nxs_js_getcssselectorcount(haystack)
7159{
7160	if (nxs_js_stringcontains(nxs_js_cssremovecomments(haystack), "@media"))
7161	{
7162		nxs_js_alert("It looks like media queries are used; these aren't supported in the css splitter (1)");
7163	}
7164
7165	var result = 0;
7166
7167  var splitted = haystack.split("}");
7168  
7169  var count = splitted.length;
7170  for (var i = 0; i < count; i++)
7171  {
7172  	var cssdeclaration = splitted[i];
7173  	  	
7174  	// splits selectors / assignment 
7175  	var splitted2 = cssdeclaration.split("{");
7176  	
7177  	var selectors = splitted2[0];
7178  	selectors = nxs_js_cssremovecomments(selectors);
7179  	
7180  	var splitted3 = selectors.split(",");
7181  	result += splitted3.length;
7182  }
7183  
7184  return result;
7185}
7186
7187function nxs_js_getchunksofcss(haystack)
7188{
7189	// precondition
7190	if (nxs_js_stringcontains(nxs_js_cssremovecomments(haystack), "@media"))
7191	{
7192		nxs_js_alert("It looks like media queries are used; these aren't supported in the css splitter (2)");
7193		nxs_js_log(haystack);
7194	}
7195	
7196	// initialization
7197	var maxchunksize = 4095;	// max # of css selectors allowed per chunk
7198	var result = {};
7199	var declarationsincurrentchunk = 0;
7200	result.chunks = {};
7201	for (var i = 0; i < nxs_js_getmaxservercsschunks(); i++)
7202	{
7203		result.chunks[currentchunk] = "";	// initial output
7204	}
7205	
7206	var splitted = haystack.split("}");
7207  
7208	var currentchunk = 0;
7209  var count = splitted.length;
7210  for (var i = 0; i < count; i++)
7211  {
7212  	var cssdeclaration = splitted[i];
7213  	  	
7214  	// splits selectors / assignment 
7215  	var splitted2 = cssdeclaration.split("{");
7216  	
7217  	var selectors = splitted2[0];
7218  	selectors = nxs_js_cssremovecomments(selectors);
7219  	
7220  	var splitted3 = selectors.split(","); 	
7221  	var numofdeclarations = splitted3.length;  	
7222  	if (declarationsincurrentchunk + numofdeclarations > maxchunksize)
7223  	{
7224  		// we need a new chunk
7225  		currentchunk++;
7226  		if (currentchunk >= nxs_js_getmaxservercsschunks())
7227  		{
7228  			nxs_js_alert('Please add additional css chunks; see nxsstyles.php');
7229  		}
7230  		result.chunks[currentchunk] = "";
7231  		declarationsincurrentchunk = 0;
7232  	}
7233  	
7234	 	// store in current chunk and continue
7235	 	result.chunks[currentchunk] += (cssdeclaration + "}");
7236	 	// increase counter of current chunk
7237	 	declarationsincurrentchunk += numofdeclarations;
7238  }
7239  
7240  return result;
7241}
7242
7243// returns the css generated by the framework,
7244// consists of all scaffolding classes like colors, widths, etc.
7245// it takes into consideration configured items like number of colors
7246function nxs_js_get_frameworkcsstemplate(csslookup)
7247{
7248	var u = "";
7249	u += "/* start Nexus framework css template */";
7250	
7251	var colortypes = nxs_js_getcolorsinpalette();
7252	
7253	u = u + ".nxs-colorzen { border-style: solid; }";
7254	u = u + "#nxs-menu-wrap { text-shadow: none; }";
7255	
7256	//
7257	// CONTAINER COLORZEN per element, no inheritance
7258	//		
7259	// colorzen's are defined on element level. The text and link colors are inherited
7260	// like body -> page -> container -> row -> placeholder 
7261	
7262	u = u + nxs_js_get_themecsstemplate_part1_colorzen("", "", "nxs-colorzen-", csslookup, "");
7263	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-colorzen ", "", "nxs-colorzen-", csslookup, "");
7264	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-colorzen .nxs-colorzen ", "", "nxs-colorzen-", csslookup, "");
7265	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-colorzen .nxs-colorzen .nxs-colorzen ", "", "nxs-colorzen-", csslookup, "");
7266	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-colorzen .nxs-colorzen .nxs-colorzen .nxs-colorzen ", "", "nxs-colorzen-", csslookup, "");
7267	
7268
7269	// SLIDETOTOP COLORZEN ==============================
7270
7271
7272	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applyhovercolors:hover ", "", "nxs-colorzen-hover-", csslookup, "");
7273	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applyactivecolors ", "", "nxs-colorzen-active-", csslookup, "");
7274
7275	//
7276	// 
7277	//
7278	
7279	//
7280	// MENU COLORZEN ==============================
7281
7282	// main items -----------
7283
7284	// colorzen for menu items
7285	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applymenucolors", " > li.nxs-inactive", "nxs-colorzen-menuitem-", csslookup, " > li > ");
7286		
7287	// colorzen for (top level) active menu items 
7288	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applymenucolors", " > li.nxs-active", "nxs-colorzen-menuitem-active-", csslookup, " > li.nxs-active > ");
7289	
7290	// colorzen for (top level) hover menu items 
7291	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applymenucolors", " > li:hover", "nxs-colorzen-menuitem-hover-", csslookup, " > li:hover > ");
7292	
7293	// colorzen for (top level) hover menu items 
7294	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-applymenucolors", " > li.nxs-active:hover", "nxs-colorzen-menuitem-active-", csslookup, " > li.nxs-active:hover > ");
7295	
7296	// sub items -----------
7297	
7298	// colorzen for submenu items
7299	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-sub-menu", "", "nxs-colorzen-menuitem-sub-", csslookup, " > li > ");
7300
7301	// colorzen for (top level) active menu items 
7302	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-sub-menu", " > li.nxs-active", "nxs-colorzen-menuitem-sub-active-", csslookup, "> li.nxs-active > ");
7303
7304	// colorzen for (top level) hover menu items 
7305	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-sub-menu", " > li:hover", "nxs-colorzen-menuitem-sub-hover-", csslookup, " > li:hover > ");
7306
7307	// colorzen for (top level) hover menu items 
7308	u = u + nxs_js_get_themecsstemplate_part1_colorzen(".nxs-sub-menu", " > li.nxs-active:hover", "nxs-colorzen-menuitem-sub-active-", csslookup, " > li.nxs-active:hover > ");
7309  
7310  //
7311	// ANCHOR LINKS nested inherited (!)
7312	//		
7313	// anchor link colors are inherited,
7314	// like body -> page -> container -> row -> placeholder 
7315	// anchor links are stronger than (generic) colorzen's
7316
7317	u = u + nxs_js_get_themecsstemplate_part1_anchorlinkcolors("","" , csslookup);
7318	u = u + nxs_js_get_themecsstemplate_part1_anchorlinkcolors(".nxs-linkcolorvar ","", csslookup);
7319	u = u + nxs_js_get_themecsstemplate_part1_anchorlinkcolors(".nxs-linkcolorvar .nxs-linkcolorvar ","", csslookup);
7320	u = u + nxs_js_get_themecsstemplate_part1_anchorlinkcolors(".nxs-linkcolorvar .nxs-linkcolorvar .nxs-linkcolorvar ","", csslookup);
7321	u = u + nxs_js_get_themecsstemplate_part1_anchorlinkcolors(".nxs-linkcolorvar .nxs-linkcolorvar .nxs-linkcolorvar .nxs-linkcolorvar ","", csslookup);
7322	
7323	//
7324  
7325  /* DEFAULT ICON WIDTH CLASSES
7326  ---------------------------------------------------------------------------------------------------- */
7327  
7328  u = u + nxs_js_createcssstyling(
7329      {
7330          factor: 80,
7331          multipliers: nxs_js_getstyletypevalues("image_size"),
7332          cssparameters: [ 
7333              {
7334                  csstemplate: '.nxs-icon-width-$nxs_identification; { width: $nxs_formularesult;px; height: $nxs_formularesult;px; }',
7335              }
7336          ]
7337      }
7338  );
7339    
7340  /* DEFAULT BORDER WIDTH CLASSES
7341  ---------------------------------------------------------------------------------------------------- */
7342    
7343  u = u + nxs_js_createcssstyling(
7344      {
7345          factor: 1,        
7346          multipliers: nxs_js_getstyletypevalues("border_width"),
7347          cssparameters: [ 
7348          		{
7349          			csstemplate: ' \
7350          				.nxs-border-width-$nxs_identification; { border-width: $nxs_formularesult;px; } 								\
7351          				.nxs-border-left-width-$nxs_identification; { border-left-width: $nxs_formularesult;px; } 			\
7352          				.nxs-border-right-width-$nxs_identification; { border-right-width: $nxs_formularesult;px; }		 	\
7353          				.nxs-border-top-width-$nxs_identification; { border-top-width: $nxs_formularesult;px; }					\
7354          				.nxs-border-bottom-width-$nxs_identification; { border-bottom-width: $nxs_formularesult;px; }'
7355          		}
7356          ]
7357      }
7358  );
7359  
7360  /* DEFAULT PADDING CLASSES
7361  ---------------------------------------------------------------------------------------------------- */
7362	
7363	u = u + nxs_js_createcssstyling(
7364  {
7365      factor: 30,
7366      multipliers: nxs_js_getstyletypevalues("padding"),
7367      cssparameters: [ 
7368					{
7369      			csstemplate: ' \
7370      				.nxs-padding-$nxs_identification; { padding: $nxs_formularesult;px; }			\
7371      				.nxs-padding-top-$nxs_identification; { padding-top: $nxs_formularesult;px; }	\
7372      				.nxs-padding-bottom-$nxs_identification; { padding-bottom: $nxs_formularesult;px; }'
7373      		}
7374     	]
7375  }
7376	);
7377    
7378  /* DEFAULT MARGIN CLASSES
7379  ---------------------------------------------------------------------------------------------------- */
7380
7381	u = u + nxs_js_createcssstyling(
7382  {
7383      factor: 30,
7384      multipliers: nxs_js_getstyletypevalues("margin"),
7385      cssparameters: [ 
7386          {
7387      			csstemplate: '\
7388      				.nxs-margin-$nxs_identification; { margin: $nxs_formularesult;px; }	\
7389      				.nxs-margin-top-$nxs_identification; { margin-top: $nxs_formularesult;px; }	\
7390      				.nxs-margin-bottom-$nxs_identification; { margin-bottom: $nxs_formularesult;px; }'
7391      		}
7392       ]
7393  }
7394  );
7395    
7396  /* DEFAULT BORDER RADIUS CLASSES
7397  ---------------------------------------------------------------------------------------------------- */
7398    
7399  u = u + nxs_js_createcssstyling(
7400  {
7401      factor: 3,
7402      multipliers: nxs_js_getstyletypevalues("border_radius"),
7403      cssparameters: [ 
7404					{
7405      			csstemplate: '.nxs-border-radius-$nxs_identification; { border-radius: $nxs_formularesult;px; }',
7406      		}
7407      ]
7408  }
7409  );
7410  
7411  /* MAX HEIGHT CLASSES
7412  ---------------------------------------------------------------------------------------------------- */
7413    
7414  u = u + nxs_js_createcssstyling(
7415  {
7416      factor: 100,
7417      multipliers: nxs_js_getstyletypevalues("maxheight"),
7418      cssparameters: [ 
7419					{
7420      			csstemplate: '.nxs-maxheight-$nxs_identification; { max-height: $nxs_formularesult;px; }',
7421      		}
7422      ]
7423  }
7424  );
7425    
7426  /* DEFAULT BUTTON SCALE CLASSES
7427  ---------------------------------------------------------------------------------------------------- */
7428  
7429  // padding top and bottom
7430  
7431  u = u + nxs_js_createcssstyling(
7432  {
7433      multipliers: nxs_js_getstyletypevalues("button_scale"),
7434      cssparameters: [ 
7435          {
7436          	factor: 6,
7437            csstemplate: '\
7438            	.nxs-button-scale-$nxs_identification; \
7439            	{ \
7440            		padding-top: $nxs_formularesult;px; \
7441            		padding-bottom: $nxs_formularesult;px; \
7442            	}',
7443          },
7444          {
7445          	factor: 10,
7446            csstemplate: '\
7447            	.nxs-button-scale-$nxs_identification; \
7448            	{ \
7449            		padding-left: $nxs_formularesult;px; \
7450            		padding-right: $nxs_formularesult;px; \
7451            	}',
7452          },
7453          {
7454          	factor: 12,
7455            csstemplate: '\
7456            	.nxs-button.nxs-button-scale-$nxs_identification; \
7457            	{ \
7458            		font-size: $nxs_formularesult;px; \
7459            	}',
7460          }
7461      ]
7462    }
7463  );
7464  
7465  /* DEFAULT BUTTON SCALE CLASSES
7466  ---------------------------------------------------------------------------------------------------- */
7467  
7468  // padding top and bottom
7469  
7470  u = u + nxs_js_createcssstyling(
7471  {
7472      multipliers: nxs_js_getstyletypevalues("icon_scale"),
7473      cssparameters: [ 
7474          {
7475          	factor: 32,
7476            csstemplate: '\
7477            	.nxs-icon-scale-$nxs_identification;, \
7478            	.nxs-text .top-wrapper span.nxs-icon-scale-$nxs_identification; \
7479            	{ \
7480            		font-size: $nxs_formularesult;px; \
7481            	}',
7482          }
7483      ]
7484    }
7485  );
7486  
7487  /* DEFAULT FONTSIZE SCALE CLASSES
7488  ---------------------------------------------------------------------------------------------------- */
7489  
7490  var fontscale = 10;
7491  var factor_textfontsize = 1.5;	/* TODO: make this configurable by end user in flyout menu */
7492    
7493  // font-sizes (1.0, 1.2, ... 2.0 = 15px ... 30px)
7494  u = u + nxs_js_createcssstyling(
7495  {
7496      multipliers: nxs_js_getstyletypevalues("fontsize"),
7497      cssparameters: 
7498      [ 
7499        {
7500        	scale: fontscale,
7501        	factor: factor_textfontsize, 
7502          csstemplate: '\
7503        	#nxs-container.nxs-text-fontsize-$nxs_identification; .nxs-default-p p, \
7504        	#nxs-container.nxs-text-fontsize-$nxs_identification; .nxs-default-p li, \
7505        	#nxs-container.nxs-text-fontsize-$nxs_identification; .nxs-default-p span, \
7506	       	#nxs-container .nxs-placeholder.nxs-text-fontsize-$nxs_identification; .nxs-default-p p, \
7507	       	#nxs-container .nxs-placeholder.nxs-text-fontsize-$nxs_identification; .nxs-default-p li, \
7508        	#nxs-container .nxs-placeholder.nxs-text-fontsize-$nxs_identification; .nxs-default-p span, \
7509        	#nxs-container.nxs-head-fontsize-$nxs_identification; .nxs-title, \
7510        	#nxs-container .nxs-placeholder.nxs-head-fontsize-$nxs_identification; .nxs-title, \
7511        	#nxs-container .nxs-placeholder .nxs-head-fontsize-$nxs_identification;.nxs-title \
7512        	{ \
7513        		 font-size: $nxs_formularesult;px; \
7514        	}',
7515        },
7516      ]
7517    }
7518  );
7519  
7520  u += nxs_js_createcssstyling_fontsizeheading("H1", 2.0, fontscale, factor_textfontsize);
7521  u += nxs_js_createcssstyling_fontsizeheading("H2", 1.8, fontscale, factor_textfontsize);
7522  u += nxs_js_createcssstyling_fontsizeheading("H3", 1.6, fontscale, factor_textfontsize);
7523  u += nxs_js_createcssstyling_fontsizeheading("H4", 1.4, fontscale, factor_textfontsize);
7524  u += nxs_js_createcssstyling_fontsizeheading("H5", 1.2, fontscale, factor_textfontsize);
7525  u += nxs_js_createcssstyling_fontsizeheading("H6", 1.0, fontscale, factor_textfontsize);
7526  
7527  u = u + ".nxs-image-wrapper img { width: 100%; display: block; }";
7528    
7529	u += "/* end injected by framework */";
7530	
7531	//nxs_js_log('part1:');
7532	//nxs_js_log(u);
7533
7534	//
7535	//
7536	//
7537	
7538	return u;
7539}
7540
7541function nxs_js_popuptogglewrapper(domelement, id)
7542{
7543	var container = jQ_nxs(domelement).closest(".nxs-option-toggler");
7544	jQ_nxs(container).toggleClass("nxs-toggled-open"); 
7545	jQ_nxs(container).toggleClass("nxs-toggled-closed");
7546	
7547	// after toggle: reposition the popup (immeditately)
7548	nxs_js_reset_popup_dimensions_actualrequest();	
7549}
7550
7551function nxs_js_refreshtopmenufillerheight()
7552{
7553	var height = jQ_nxs("#nxs-menu-wrap").height();
7554	//nxs_js_log('height nxs-menu-wrap is ' + height);
7555	jQ_nxs('#menufillerinlinecontent').height(height); // + 30);
7556}
7557
7558function nxs_js_rerender_dirty_rowcontainers()
7559{
7560  // TODO: this can be further optimized; rather than launching one AJAX call
7561  // for each row container, it would be possible to do one call for all
7562  jQ_nxs(".nxs-row-container.nxs-dirty").each
7563	(
7564		function(index, element) 
7565		{
7566			nxs_js_rerender_row_for_element(element);
7567		}
7568	);
7569}
7570
7571/* nicescroll */
7572
7573/* jquery.nicescroll 3.5.0 InuYaksa*2013 MIT http://areaaperta.com/nicescroll */(function(e){var z=!1,E=!1,L=5E3,M=2E3,y=0,N=function(){var e=document.getElementsByTagName("script"),e=e[e.length-1].src.split("?")[0];return 0<e.split("/").length?e.split("/").slice(0,-1).join("/")+"/":""}(),H=["ms","moz","webkit","o"],v=window.requestAnimationFrame||!1,w=window.cancelAnimationFrame||!1;if(!v)for(var O in H){var F=H[O];v||(v=window[F+"RequestAnimationFrame"]);w||(w=window[F+"CancelAnimationFrame"]||window[F+"CancelRequestAnimationFrame"])}var A=window.MutationObserver||window.WebKitMutationObserver||
7574!1,I={zindex:"auto",cursoropacitymin:0,cursoropacitymax:1,cursorcolor:"#424242",cursorwidth:"5px",cursorborder:"1px solid #fff",cursorborderradius:"5px",scrollspeed:60,mousescrollstep:24,touchbehavior:!1,hwacceleration:!0,usetransition:!0,boxzoom:!1,dblclickzoom:!0,gesturezoom:!0,grabcursorenabled:!0,autohidemode:!0,background:"",iframeautoresize:!0,cursorminheight:32,preservenativescrolling:!0,railoffset:!1,bouncescroll:!0,spacebarenabled:!0,railpadding:{top:0,right:0,left:0,bottom:0},disableoutline:!0,
7575horizrailenabled:!0,railalign:"right",railvalign:"bottom",enabletranslate3d:!0,enablemousewheel:!0,enablekeyboard:!0,smoothscroll:!0,sensitiverail:!0,enablemouselockapi:!0,cursorfixedheight:!1,directionlockdeadzone:6,hidecursordelay:400,nativeparentscrolling:!0,enablescrollonselection:!0,overflowx:!0,overflowy:!0,cursordragspeed:0.3,rtlmode:!1,cursordragontouch:!1,oneaxismousemode:"auto"},G=!1,P=function(){if(G)return G;var e=document.createElement("DIV"),c={haspointerlock:"pointerLockElement"in document||
7576"mozPointerLockElement"in document||"webkitPointerLockElement"in document};c.isopera="opera"in window;c.isopera12=c.isopera&&"getUserMedia"in navigator;c.isoperamini="[object OperaMini]"===Object.prototype.toString.call(window.operamini);c.isie="all"in document&&"attachEvent"in e&&!c.isopera;c.isieold=c.isie&&!("msInterpolationMode"in e.style);c.isie7=c.isie&&!c.isieold&&(!("documentMode"in document)||7==document.documentMode);c.isie8=c.isie&&"documentMode"in document&&8==document.documentMode;c.isie9=
7577c.isie&&"performance"in window&&9<=document.documentMode;c.isie10=c.isie&&"performance"in window&&10<=document.documentMode;c.isie9mobile=/iemobile.9/i.test(navigator.userAgent);c.isie9mobile&&(c.isie9=!1);c.isie7mobile=!c.isie9mobile&&c.isie7&&/iemobile/i.test(navigator.userAgent);c.ismozilla="MozAppearance"in e.style;c.iswebkit="WebkitAppearance"in e.style;c.ischrome="chrome"in window;c.ischrome22=c.ischrome&&c.haspointerlock;c.ischrome26=c.ischrome&&"transition"in e.style;c.cantouch="ontouchstart"in
7578document.documentElement||"ontouchstart"in window;c.hasmstouch=window.navigator.msPointerEnabled||!1;c.ismac=/^mac$/i.test(navigator.platform);c.isios=c.cantouch&&/iphone|ipad|ipod/i.test(navigator.platform);c.isios4=c.isios&&!("seal"in Object);c.isandroid=/android/i.test(navigator.userAgent);c.trstyle=!1;c.hastransform=!1;c.hastranslate3d=!1;c.transitionstyle=!1;c.hastransition=!1;c.transitionend=!1;for(var k=["transform","msTransform","webkitTransform","MozTransform","OTransform"],l=0;l<k.length;l++)if("undefined"!=
7579typeof e.style[k[l]]){c.trstyle=k[l];break}c.hastransform=!1!=c.trstyle;c.hastransform&&(e.style[c.trstyle]="translate3d(1px,2px,3px)",c.hastranslate3d=/translate3d/.test(e.style[c.trstyle]));c.transitionstyle=!1;c.prefixstyle="";c.transitionend=!1;for(var k="transition webkitTransition MozTransition OTransition OTransition msTransition KhtmlTransition".split(" "),q=" -webkit- -moz- -o- -o -ms- -khtml-".split(" "),t="transitionend webkitTransitionEnd transitionend otransitionend oTransitionEnd msTransitionEnd KhtmlTransitionEnd".split(" "),
7580l=0;l<k.length;l++)if(k[l]in e.style){c.transitionstyle=k[l];c.prefixstyle=q[l];c.transitionend=t[l];break}c.ischrome26&&(c.prefixstyle=q[1]);c.hastransition=c.transitionstyle;a:{k=["-moz-grab","-webkit-grab","grab"];
7580if(c.ischrome&&!c.ischrome22||c.isie)k=[];for(l=0;l<k.length;l++)if(q=k[l],e.style.cursor=q,e.style.cursor==q){k=q;break a}k="url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur),n-resize"}c.cursorgrabvalue=k;c.hasmousecapture="setCapture"in e;c.hasMutationObserver=!1!==A;return G=
7581c},Q=function(h,c){function k(){var d=b.win;if("zIndex"in d)return d.zIndex();for(;0<d.length&&9!=d[0].nodeType;){var c=d.css("zIndex");if(!isNaN(c)&&0!=c)return parseInt(c);d=d.parent()}return!1}function l(d,c,f){c=d.css(c);d=parseFloat(c);return isNaN(d)?(d=u[c]||0,f=3==d?f?b.win.outerHeight()-b.win.innerHeight():b.win.outerWidth()-b.win.innerWidth():1,b.isie8&&d&&(d+=1),f?d:0):d}function q(d,c,f,g){b._bind(d,c,function(b){b=b?b:window.event;var g={original:b,target:b.target||b.srcElement,type:"wheel",
7582deltaMode:"MozMousePixelScroll"==b.type?0:1,deltaX:0,deltaZ:0,preventDefault:function(){b.preventDefault?b.preventDefault():b.returnValue=!1;return!1},stopImmediatePropagation:function(){b.stopImmediatePropagation?b.stopImmediatePropagation():b.cancelBubble=!0}};"mousewheel"==c?(g.deltaY=-0.025*b.wheelDelta,b.wheelDeltaX&&(g.deltaX=-0.025*b.wheelDeltaX)):g.deltaY=b.detail;return f.call(d,g)},g)}function t(d,c,f){var g,e;0==d.deltaMode?(g=-Math.floor(d.deltaX*(b.opt.mousescrollstep/54)),e=-Math.floor(d.deltaY*
7583(b.opt.mousescrollstep/54))):1==d.deltaMode&&(g=-Math.floor(d.deltaX*b.opt.mousescrollstep),e=-Math.floor(d.deltaY*b.opt.mousescrollstep));c&&(b.opt.oneaxismousemode&&0==g&&e)&&(g=e,e=0);g&&(b.scrollmom&&b.scrollmom.stop(),b.lastdeltax+=g,b.debounced("mousewheelx",function(){var d=b.lastdeltax;b.lastdeltax=0;b.rail.drag||b.doScrollLeftBy(d)},120));if(e){if(b.opt.nativeparentscrolling&&f&&!b.ispage&&!b.zoomactive)if(0>e){if(b.getScrollTop()>=b.page.maxh)return!0}else if(0>=b.getScrollTop())return!0;
7584b.scrollmom&&b.scrollmom.stop();b.lastdeltay+=e;b.debounced("mousewheely",function(){var d=b.lastdeltay;b.lastdeltay=0;b.rail.drag||b.doScrollBy(d)},120)}d.stopImmediatePropagation();return d.preventDefault()}var b=this;this.version="3.5.0";this.name="nicescroll";this.me=c;this.opt={doc:e("body"),win:!1};e.extend(this.opt,I);this.opt.snapbackspeed=80;if(h)for(var p in b.opt)"undefined"!=typeof h[p]&&(b.opt[p]=h[p]);this.iddoc=(this.doc=b.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/BODY|HTML/.test(b.opt.win?
7585b.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper=!1!==b.opt.win;
7585this.win=b.opt.win||(this.ispage?e(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?e(window):this.win;this.body=e("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=b.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=
7586this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick=this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.observerremover=this.observer=this.scrollmom=this.scrollrunning=this.checkrtlmode=!1;do this.id="ascrail"+M++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=
7587this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=!1;this.cursoractive=!0;this.overflowx=b.opt.overflowx;this.overflowy=b.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=P();var g=e.extend({},this.detected);this.ishwscroll=(this.canhwscroll=g.hastransform&&b.opt.hwacceleration)&&b.haswrapper;this.istouchcapable=!1;g.cantouch&&(g.ischrome&&!g.isios&&!g.isandroid)&&
7588(this.istouchcapable=!0,g.cantouch=!1);g.cantouch&&(g.ismozilla&&!g.isios&&!g.isandroid)&&(this.istouchcapable=!0,g.cantouch=!1);b.opt.enablemouselockapi||(g.hasmousecapture=!1,g.haspointerlock=!1);this.delayed=function(d,c,f,g){var e=b.delaylist[d],k=(new Date).getTime();if(!g&&e&&e.tt)return!1;e&&e.tt&&clearTimeout(e.tt);if(e&&e.last+f>k&&!e.tt)b.delaylist[d]={last:k+f,tt:setTimeout(function(){b.delaylist[d].tt=0;c.call()},f)};else if(!e||!e.tt)b.delaylist[d]={last:k,tt:0},setTimeout(function(){c.call()},
75890)};this.debounced=function(d,c,f){var g=b.delaylist[d];(new Date).getTime();b.delaylist[d]=c;g||setTimeout(function(){var c=b.delaylist[d];b.delaylist[d]=!1;c.call()},f)};this.synched=function(d,c){b.synclist[d]=c;(function(){b.onsync||(v(function(){b.onsync=!1;for(d in b.synclist){var c=b.synclist[d];c&&c.call(b);b.synclist[d]=!1}}),b.onsync=!0)})();return d};this.unsynched=function(d){b.synclist[d]&&(b.synclist[d]=!1)};this.css=function(d,c){for(var f in c)b.saved.css.push([d,f,d.css(f)]),d.css(f,
7590c[f])};this.scrollTop=function(d){return"undefined"==typeof d?b.getScrollTop():b.setScrollTop(d)};this.scrollLeft=function(d){return"undefined"==typeof d?b.getScrollLeft():b.setScrollLeft(d)};BezierClass=function(b,c,f,g,e,k,l){this.st=b;this.ed=c;this.spd=f;this.p1=g||0;this.p2=e||1;this.p3=k||0;this.p4=l||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};BezierClass.prototype={B2:function(b){return 3*b*b*(1-b)},B3:function(b){return 3*b*(1-b)*(1-b)},B4:function(b){return(1-b)*(1-b)*(1-b)},
7591getNow:function(){var b=1-((new Date).getTime()-this.ts)/this.spd,c=this.B2(b)+this.B3(b)+this.B4(b);return 0>b?this.ed:this.st+Math.round(this.df*c)},update:function(b,c){this.st=this.getNow();this.ed=b;this.spd=c;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};g.hastranslate3d&&g.isios&&this.doc.css("-webkit-backface-visibility","hidden");var s=function(){var d=b.doc.css(g.trstyle);return d&&"matrix"==d.substr(0,
75926)?d.replace(/^.*\((.*)\)$/g,"$1").replace(/px/g,"").split(/, +/):!1};this.getScrollTop=function(d){if(!d){if(d=s())return 16==d.length?-d[13]:-d[5];if(b.timerscroll&&b.timerscroll.bz)return b.timerscroll.bz.getNow()}return b.doc.translate.y};this.getScrollLeft=function(d){if(!d){if(d=s())return 16==d.length?-d[12]:-d[4];if(b.timerscroll&&b.timerscroll.bh)return b.timerscroll.bh.getNow()}return b.doc.translate.x};this.notifyScrollEvent=document.createEvent?function(b){var c=document.createEvent("UIEvents");
7593c.initUIEvent("scroll",!1,!0,window,1);b.dispatchEvent(c)}:document.fireEvent?function(b){var c=document.createEventObject();
7593b.fireEvent("onscroll");c.cancelBubble=!0}:function(b,c){};g.hastranslate3d&&b.opt.enabletranslate3d?(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+"px";b.doc.css(g.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1*
7594d+"px";b.doc.css(g.trstyle,"translate3d("+b.doc.translate.tx+","+b.doc.translate.ty+",0px)");c||b.notifyScrollEvent(b.win[0])}):(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+"px";b.doc.css(g.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1*d+"px";b.doc.css(g.trstyle,"translate("+b.doc.translate.tx+","+b.doc.translate.ty+")");c||b.notifyScrollEvent(b.win[0])})}else this.getScrollTop=
7595function(){return b.docscroll.scrollTop()},this.setScrollTop=function(d){return b.docscroll.scrollTop(d)},this.getScrollLeft=function(){return b.docscroll.scrollLeft()},this.setScrollLeft=function(d){return b.docscroll.scrollLeft(d)};this.getTarget=function(b){return!b?!1:b.target?b.target:b.srcElement?b.srcElement:!1};this.hasParent=function(b,c){if(!b)return!1;for(var f=b.target||b.srcElement||b||!1;f&&f.id!=c;)f=f.parentNode||!1;return!1!==f};var u={thin:1,medium:3,thick:5};this.getOffset=function(){if(b.isfixed)return{top:parseFloat(b.win.css("top")),
7596left:parseFloat(b.win.css("left"))};if(!b.viewport)return b.win.offset();var d=b.win.offset(),c=b.viewport.offset();return{top:d.top-c.top+b.viewport.scrollTop(),left:d.left-c.left+b.viewport.scrollLeft()}};this.updateScrollBar=function(d){if(b.ishwscroll)b.rail.css({height:b.win.innerHeight()}
7596),b.railh&&b.railh.css({width:b.win.innerWidth()});else{var c=b.getOffset(),f=c.top,g=c.left,f=f+l(b.win,"border-top-width",!0);b.win.outerWidth();b.win.innerWidth();var g=g+(b.rail.align?b.win.outerWidth()-
7597l(b.win,"border-right-width")-b.rail.width:l(b.win,"border-left-width")),e=b.opt.railoffset;e&&(e.top&&(f+=e.top),b.rail.align&&e.left&&(g+=e.left));b.locked||b.rail.css({top:f,left:g,height:d?d.h:b.win.innerHeight()});b.zoom&&b.zoom.css({top:f+1,left:1==b.rail.align?g-20:g+b.rail.width+4});b.railh&&!b.locked&&(f=c.top,g=c.left,d=b.railh.align?f+l(b.win,"border-top-width",!0)+b.win.innerHeight()-b.railh.height:f+l(b.win,"border-top-width",!0),g+=l(b.win,"border-left-width"),b.railh.css({top:d,left:g,
7598width:b.railh.width}))}};this.doRailClick=function(d,c,f){var g;b.locked||(b.cancelEvent(d),c?(c=f?b.doScrollLeft:b.doScrollTop,g=f?(d.pageX-b.railh.offset().left-b.cursorwidth/2)*b.scrollratio.x:(d.pageY-b.rail.offset().top-b.cursorheight/2)*b.scrollratio.y,c(g)):(c=f?b.doScrollLeftBy:b.doScrollBy,g=f?b.scroll.x:b.scroll.y,d=f?d.pageX-b.railh.offset().left:d.pageY-b.rail.offset().top,f=f?b.view.w:b.view.h,g>=d?c(f):c(-f)))};b.hasanimationframe=v;b.hascancelanimationframe=w;b.hasanimationframe?b.hascancelanimationframe||
7599(w=function(){b.cancelAnimationFrame=!0}):(v=function(b){return setTimeout(b,15-Math.floor(+new Date/1E3)%16)},w=clearInterval);this.init=function(){b.saved.css=[];if(g.isie7mobile||g.isoperamini)return!0;g.hasmstouch&&b.css(b.ispage?e("html"):b.win,{"-ms-touch-action":"none"});b.zindex="auto";b.zindex=!b.ispage&&"auto"==b.opt.zindex?k()||"auto":b.opt.zindex;!b.ispage&&"auto"!=b.zindex&&b.zindex>y&&(y=b.zindex);b.isie&&(0==b.zindex&&"auto"==b.opt.zindex)&&(b.zindex="auto");if(!b.ispage||!g.cantouch&&
7600!g.isieold&&!g.isie9mobile){var d=b.docscroll;b.ispage&&(d=b.haswrapper?b.win:b.doc);g.isie9mobile||b.css(d,{"overflow-y":"hidden"});b.ispage&&g.isie7&&("BODY"==b.doc[0].nodeName?b.css(e("html"),{"overflow-y":"hidden"}):"HTML"==b.doc[0].nodeName&&b.css(e("body"),{"overflow-y":"hidden"}));g.isios&&(!b.ispage&&!b.haswrapper)&&b.css(e("body"),{"-webkit-overflow-scrolling":"touch"});var c=e(document.createElement("div"));c.css({position:"relative",top:0,"float":"right",width:b.opt.cursorwidth,height:"0px",
7601"background-color":b.opt.cursorcolor,border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius,"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});c.hborder=parseFloat(c.outerHeight()-c.innerHeight());b.cursor=c;var f=e(document.createElement("div"));f.attr("id",b.id);f.addClass("nicescroll-rails");var l,h,x=["left","right"],q;for(q in x)h=x[q],(l=b.opt.railpadding[h])?f.css("padding-"+h,l+"px"):b.opt.railpadding[h]=
76020;f.append(c);f.width=Math.max(parseFloat(b.opt.cursorwidth),c.outerWidth())+b.opt.railpadding.left+b.opt.railpadding.right;f.css({width:f.width+"px",zIndex:b.zindex,background:b.opt.background,cursor:"default"});f.visibility=!0;f.scrollable=!0;f.align="left"==b.opt.railalign?0:1;b.rail=f;c=b.rail.drag=!1;b.opt.boxzoom&&(!b.ispage&&!g.isieold)&&(c=document.createElement("div"),b.bind(c,"click",b.doZoom),b.zoom=e(c),b.zoom.css({cursor:"pointer","z-index":b.zindex,backgroundImage:"url("+N+"zoomico.png)",
7603height:18,width:18,backgroundPosition:"0px 0px"}),b.opt.dblclickzoom&&b.bind(b.win,"dblclick",b.doZoom),g.cantouch&&b.opt.gesturezoom&&(b.ongesturezoom=function(d){1.5<d.scale&&b.doZoomIn(d);0.8>d.scale&&b.doZoomOut(d);return b.cancelEvent(d)},b.bind(b.win,"gestureend",b.ongesturezoom)));b.railh=!1;if(b.opt.horizrailenabled){b.css(d,{"overflow-x":"hidden"});c=e(document.createElement("div"));c.css({position:"relative",top:0,height:b.opt.cursorwidth,width:"0px","background-color":b.opt.cursorcolor,
7604border:b.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":b.opt.cursorborderradius,"-moz-border-radius":b.opt.cursorborderradius,"border-radius":b.opt.cursorborderradius});c.wborder=parseFloat(c.outerWidth()-c.innerWidth());b.cursorh=c;var m=e(document.createElement("div"));m.attr("id",b.id+"-hr");m.addClass("nicescroll-rails");m.height=Math.max(parseFloat(b.opt.cursorwidth),c.outerHeight());m.css({height:m.height+"px",zIndex:b.zindex,background:b.opt.background});m.append(c);
7605m.visibility=!0;m.scrollable=!0;m.align="top"==b.opt.railvalign?0:1;b.railh=m;b.railh.drag=!1}b.ispage?(f.css({position:"fixed",top:"0px",height:"100%"}),f.align?f.css({right:"0px"}):f.css({left:"0px"}),b.body.append(f),b.railh&&(m.css({position:"fixed",left:"0px",width:"100%"}),m.align?m.css({bottom:"0px"}):m.css({top:"0px"}),b.body.append(m))):(b.ishwscroll?("static"==b.win.css("position")&&b.css(b.win,{position:"relative"}),d="HTML"==b.win[0].nodeName?b.body:b.win,b.zoom&&(b.zoom.css({position:"absolute",
7606top:1,right:0,"margin-right":f.width+4}),d.append(b.zoom)),f.css({position:"absolute",top:0}),f.align?f.css({right:0}):f.css({left:0}),d.append(f),m&&(m.css({position:"absolute",left:0,bottom:0}),m.align?m.css({bottom:0}):m.css({top:0}),d.append(m))):(b.isfixed="fixed"==b.win.css("position"),d=b.isfixed?"fixed":"absolute",b.isfixed||(b.viewport=b.getViewport(b.win[0])),b.viewport&&(b.body=b.viewport,!1==/fixed|relative|absolute/.test(b.viewport.css("position"))&&b.css(b.viewport,{position:"relative"})),
7607f.css({position:d}),b.zoom&&b.zoom.css({position:d}),b.updateScrollBar(),b.body.append(f),b.zoom&&b.body.append(b.zoom),b.railh&&(m.css({position:d}),b.body.append(m))),g.isios&&b.css(b.win,{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),g.isie&&b.opt.disableoutline&&b.win.attr("hideFocus","true"),g.iswebkit&&b.opt.disableoutline&&b.win.css({outline:"none"}));!1===b.opt.autohidemode?(b.autohidedom=!1,b.rail.css({opacity:b.opt.cursoropacitymax}),b.railh&&b.railh.css({opacity:b.opt.cursoropacitymax})):
7608!0===b.opt.autohidemode||"leave"===b.opt.autohidemode?(b.autohidedom=e().add(b.rail),g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursor)),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh)),b.railh&&g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"scroll"==b.opt.autohidemode?(b.autohidedom=e().add(b.rail),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh))):"cursor"==b.opt.autohidemode?(b.autohidedom=e().add(b.cursor),b.railh&&(b.autohidedom=b.autohidedom.add(b.cursorh))):"hidden"==b.opt.autohidemode&&
7609(b.autohidedom=!1,b.hide(),b.locked=!1);if(g.isie9mobile)b.scrollmom=new J(b),b.onmangotouch=function(d){d=b.getScrollTop();var c=b.getScrollLeft();if(d==b.scrollmom.lastscrolly&&c==b.scrollmom.lastscrollx)return!0;var f=d-b.mangotouch.sy,g=c-b.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(g,2)+Math.pow(f,2)))){var n=0>f?-1:1,e=0>g?-1:1,k=+new Date;b.mangotouch.lazy&&clearTimeout(b.mangotouch.lazy);80<k-b.mangotouch.tm||b.mangotouch.dry!=n||b.mangotouch.drx!=e?(b.scrollmom.stop(),b.scrollmom.reset(c,
7610d),b.mangotouch.sy=d,b.mangotouch.ly=d,b.mangotouch.sx=c,b.mangotouch.lx=c,b.mangotouch.dry=n,b.mangotouch.drx=e,b.mangotouch.tm=k):(b.scrollmom.stop(),b.scrollmom.update(b.mangotouch.sx-g,b.mangotouch.sy-f),b.mangotouch.tm=k,f=Math.max(Math.abs(b.mangotouch.ly-d),Math.abs(b.mangotouch.lx-c)),b.mangotouch.ly=d,b.mangotouch.lx=c,2<f&&(b.mangotouch.lazy=setTimeout(function(){b.mangotouch.lazy=!1;b.mangotouch.dry=0;b.mangotouch.drx=0;b.mangotouch.tm=0;b.scrollmom.doMomentum(30)},100)))}},f=b.getScrollTop(),
7611m=b.getScrollLeft(),b.mangotouch={sy:f,ly:f,dry:0,sx:m,lx:m,drx:0,lazy:!1,tm:0},b.bind(b.docscroll,"scroll",b.onmangotouch);else{if(g.cantouch||b.istouchcapable||b.opt.touchbehavior||g.hasmstouch){b.scrollmom=new J(b);b.ontouchstart=function(d){if(d.pointerType&&2!=d.pointerType)return!1;if(!b.locked){if(g.hasmstouch)for(var c=d.target?d.target:!1;c;){var f=e(c).getNiceScroll();if(0<f.length&&f[0].me==b.me)break;
7611if(0<f.length)return!1;if("DIV"==c.nodeName&&c.id==b.id)break;c=c.parentNode?c.parentNode:
7612!1}b.cancelScroll();if((c=b.getTarget(d))&&/INPUT/i.test(c.nodeName)&&/range/i.test(c.type))return b.stopPropagation(d);!("clientX"in d)&&"changedTouches"in d&&(d.clientX=d.changedTouches[0].clientX,d.clientY=d.changedTouches[0].clientY);b.forcescreen&&(f=d,d={original:d.original?d.original:d},d.clientX=f.screenX,d.clientY=f.screenY);b.rail.drag={x:d.clientX,y:d.clientY,sx:b.scroll.x,sy:b.scroll.y,st:b.getScrollTop(),sl:b.getScrollLeft(),pt:2,dl:!1};if(b.ispage||!b.opt.directionlockdeadzone)b.rail.drag.dl=
7613"f";else{var f=e(window).width(),n=e(window).height(),k=Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),l=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight),n=Math.max(0,l-n),f=Math.max(0,k-f);b.rail.drag.ck=!b.rail.scrollable&&b.railh.scrollable?0<n?"v":!1:b.rail.scrollable&&!b.railh.scrollable?0<f?"h":!1:!1;b.rail.drag.ck||(b.rail.drag.dl="f")}b.opt.touchbehavior&&(b.isiframe&&g.isie)&&(f=b.win.position(),b.rail.drag.x+=f.left,b.rail.drag.y+=f.top);
7614b.hasmoving=!1;b.lastmouseup=!1;b.scrollmom.reset(d.clientX,d.clientY);if(!g.cantouch&&!this.istouchcapable&&!g.hasmstouch){if(!c||!/INPUT|SELECT|TEXTAREA/i.test(c.nodeName))return!b.ispage&&g.hasmousecapture&&c.setCapture(),b.opt.touchbehavior?b.cancelEvent(d):b.stopPropagation(d);/SUBMIT|CANCEL|BUTTON/i.test(e(c).attr("type"))&&(pc={tg:c,click:!1},b.preventclick=pc)}}};b.ontouchend=function(d){if(d.pointerType&&2!=d.pointerType)return!1;if(b.rail.drag&&2==b.rail.drag.pt&&(b.scrollmom.doMomentum(),
7615b.rail.drag=!1,b.hasmoving&&(b.hasmoving=!1,b.lastmouseup=!0,b.hideCursor(),g.hasmousecapture&&document.releaseCapture(),!g.cantouch)))return b.cancelEvent(d)};var t=b.opt.touchbehavior&&b.isiframe&&!g.hasmousecapture;b.ontouchmove=function(d,c){if(d.pointerType&&2!=d.pointerType)return!1;if(b.rail.drag&&2==b.rail.drag.pt){if(g.cantouch&&"undefined"==typeof d.original)return!0;b.hasmoving=!0;b.preventclick&&!b.preventclick.click&&(b.preventclick.click=b.preventclick.tg.onclick||!1,b.preventclick.tg.onclick=
7616b.onpreventclick);d=e.extend({original:d},d);"changedTouches"in d&&(d.clientX=d.changedTouches[0].clientX,d.clientY=d.changedTouches[0].clientY);if(b.forcescreen){var f=d;d={original:d.original?d.original:d};d.clientX=f.screenX;d.clientY=f.screenY}f=ofy=0;if(t&&!c){var n=b.win.position(),f=-n.left;ofy=-n.top}var k=d.clientY+ofy,n=k-b.rail.drag.y,l=d.clientX+f,h=l-b.rail.drag.x,r=b.rail.drag.st-n;b.ishwscroll&&b.opt.bouncescroll?0>r?r=Math.round(r/2):r>b.page.maxh&&(r=b.page.maxh+Math.round((r-b.page.maxh)/
76172)):(0>r&&(k=r=0),r>b.page.maxh&&(r=b.page.maxh,k=0));if(b.railh&&b.railh.scrollable){var m=b.rail.drag.sl-h;b.ishwscroll&&b.opt.bouncescroll?0>m?m=Math.round(m/2):m>b.page.maxw&&(m=b.page.maxw+Math.round((m-b.page.maxw)/2)):(0>m&&(l=m=0),m>b.page.maxw&&(m=b.page.maxw,l=0))}f=!1;if(b.rail.drag.dl)f=!0,"v"==b.rail.drag.dl?m=b.rail.drag.sl:"h"==b.rail.drag.dl&&(r=b.rail.drag.st);else{var n=Math.abs(n),h=Math.abs(h),x=b.opt.directionlockdeadzone;if("v"==b.rail.drag.ck){if(n>x&&h<=0.3*n)return b.rail.drag=
7618!1,!0;h>x&&(b.rail.drag.dl="f",e("body").scrollTop(e("body").scrollTop()))}else if("h"==b.rail.drag.ck){if(h>x&&n<=0.3*h)return b.rail.drag=!1,!0;n>x&&(b.rail.drag.dl="f",e("body").scrollLeft(e("body").scrollLeft()))}}b.synched("touchmove",function(){b.rail.drag&&2==b.rail.drag.pt&&(b.prepareTransition&&b.prepareTransition(0),b.rail.scrollable&&b.setScrollTop(r),b.scrollmom.update(l,k),b.railh&&b.railh.scrollable?(b.setScrollLeft(m),b.showCursor(r,m)):b.showCursor(r),g.isie10&&document.selection.clear())});
7619g.ischrome&&b.istouchcapable&&(f=!1);if(f)return b.cancelEvent(d)}}}b.onmousedown=function(d,c){if(!(b.rail.drag&&1!=b.rail.drag.pt)){if(b.locked)return b.cancelEvent(d);b.cancelScroll();b.rail.drag={x:d.clientX,y:d.clientY,sx:b.scroll.x,sy:b.scroll.y,pt:1,hr:!!c};var f=b.getTarget(d);!b.ispage&&g.hasmousecapture&&f.setCapture();b.isiframe&&!g.hasmousecapture&&(b.saved.csspointerevents=b.doc.css("pointer-events"),b.css(b.doc,{"pointer-events":"none"}));return b.cancelEvent(d)}};b.onmouseup=function(d){if(b.rail.drag&&
7620(g.hasmousecapture&&document.releaseCapture(),b.isiframe&&!g.hasmousecapture&&b.doc.css("pointer-events",b.saved.csspointerevents),1==b.rail.drag.pt))return b.rail.drag=!1,b.cancelEvent(d)};b.onmousemove=function(d){if(b.rail.drag&&1==b.rail.drag.pt){if(g.ischrome&&0==d.which)return b.onmouseup(d);b.cursorfreezed=!0;if(b.rail.drag.hr){b.scroll.x=b.rail.drag.sx+(d.clientX-b.rail.drag.x);0>b.scroll.x&&(b.scroll.x=0);var c=b.scrollvaluemaxw;b.scroll.x>c&&(b.scroll.x=c)}else b.scroll.y=b.rail.drag.sy+
7621(d.clientY-b.rail.drag.y),0>b.scroll.y&&(b.scroll.y=0),c=b.scrollvaluemax,b.scroll.y>c&&(b.scroll.y=c);b.synched("mousemove",function(){b.rail.drag&&1==b.rail.drag.pt&&(b.showCursor(),b.rail.drag.hr?b.doScrollLeft(Math.round(b.scroll.x*b.scrollratio.x),b.opt.cursordragspeed):b.doScrollTop(Math.round(b.scroll.y*b.scrollratio.y),b.opt.cursordragspeed))});return b.cancelEvent(d)}};if(g.cantouch||b.opt.touchbehavior)b.onpreventclick=function(d){if(b.preventclick)return b.preventclick.tg.oncl
7621ick=b.preventclick.click,
7622b.preventclick=!1,b.cancelEvent(d)},b.bind(b.win,"mousedown",b.ontouchstart),b.onclick=g.isios?!1:function(d){return b.lastmouseup?(b.lastmouseup=!1,b.cancelEvent(d)):!0},b.opt.grabcursorenabled&&g.cursorgrabvalue&&(b.css(b.ispage?b.doc:b.win,{cursor:g.cursorgrabvalue}),b.css(b.rail,{cursor:g.cursorgrabvalue}));else{var p=function(d){if(b.selectiondrag){if(d){var c=b.win.outerHeight();d=d.pageY-b.selectiondrag.top;0<d&&d<c&&(d=0);d>=c&&(d-=c);b.selectiondrag.df=d}0!=b.selectiondrag.df&&(b.doScrollBy(2*
7623-Math.floor(b.selectiondrag.df/6)),b.debounced("doselectionscroll",function(){p()},50))}};b.hasTextSelected="getSelection"in document?function(){return 0<document.getSelection().rangeCount}:"selection"in document?function(){return"None"!=document.selection.type}:function(){return!1};b.onselectionstart=function(d){b.ispage||(b.selectiondrag=b.win.offset())};b.onselectionend=function(d){b.selectiondrag=!1};b.onselectiondrag=function(d){b.selectiondrag&&b.hasTextSelected()&&b.debounced("selectionscroll",
7624function(){p(d)},250)}}g.hasmstouch&&(b.css(b.rail,{"-ms-touch-action":"none"}),b.css(b.cursor,{"-ms-touch-action":"none"}),b.bind(b.win,"MSPointerDown",b.ontouchstart),b.bind(document,"MSPointerUp",b.ontouchend),b.bind(document,"MSPointerMove",b.ontouchmove),b.bind(b.cursor,"MSGestureHold",function(b){b.preventDefault()}),b.bind(b.cursor,"contextmenu",function(b){b.preventDefault()}));this.istouchcapable&&(b.bind(b.win,"touchstart",b.ontouchstart),b.bind(document,"touchend",b.ontouchend),b.bind(document,
7625"touchcancel",b.ontouchend),b.bind(document,"touchmove",b.ontouchmove));b.bind(b.cursor,"mousedown",b.onmousedown);b.bind(b.cursor,"mouseup",b.onmouseup);b.railh&&(b.bind(b.cursorh,"mousedown",function(d){b.onmousedown(d,!0)}),b.bind(b.cursorh,"mouseup",function(d){if(!(b.rail.drag&&2==b.rail.drag.pt))return b.rail.drag=!1,b.hasmoving=!1,b.hideCursor(),g.hasmousecapture&&document.releaseCapture(),b.cancelEvent(d)}));if(b.opt.cursordragontouch||!g.cantouch&&!b.opt.touchbehavior)b.rail.css({cursor:"default"}),
7626b.railh&&b.railh.css({cursor:"default"}),b.jqbind(b.rail,"mouseenter",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),b.jqbind(b.rail,"mouseleave",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}),b.opt.sensitiverail&&(b.bind(b.rail,"click",function(d){b.doRailClick(d,!1,!1)}),b.bind(b.rail,"dblclick",function(d){b.doRailClick(d,!0,!1)}),b.bind(b.cursor,"click",function(d){b.cancelEvent(d)}),b.bind(b.cursor,"dblclick",function(d){b.cancelEvent(d)})),b.railh&&(b.jqbind(b.railh,
7627"mouseenter",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),b.jqbind(b.railh,"mouseleave",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}),b.opt.sensitiverail&&(b.bind(b.railh,"click",function(d){b.doRailClick(d,!1,!0)}),b.bind(b.railh,"dblclick",function(d){b.doRailClick(d,!0,!0)}),b.bind(b.cursorh,"click",function(d){b.cancelEvent(d)}),b.bind(b.cursorh,"dblclick",function(d){b.cancelEvent(d)})));!g.cantouch&&!b.opt.touchbehavior?(b.bind(g.hasmousecapture?b.win:document,
7628"mouseup",b.onmouseup),b.bind(document,"mousemove",b.onmousemove),b.onclick&&b.bind(document,"click",b.onclick),!b.ispage&&b.opt.enablescrollonselection&&(b.bind(b.win[0],"mousedown",b.onselectionstart),b.bind(document,"mouseup",b.onselectionend),b.bind(b.cursor,"mouseup",b.onselectionend),b.cursorh&&b.bind(b.cursorh,"mouseup",b.onselectionend),b.bind(document,"mousemove",b.onselectiondrag)),b.zoom&&(b.jqbind(b.zoom,"mouseenter",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),
7629b.jqbind(b.zoom,"mouseleave",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}))):(b.bind(g.hasmousecapture?b.win:document,"mouseup",b.ontouchend),b.bind(document,"mousemove",b.ontouchmove),b.onclick&&b.bind(document,"click",b.onclick),b.opt.cursordragontouch&&(b.bind(b.cursor,"mousedown",b.onmousedown),b.bind(b.cursor,"mousemove",b.onmousemove),b.cursorh&&b.bind(b.cursorh,"mousedown",function(d){b.onmousedown(d,!0)}),b.cursorh&&b.bind(b.cursorh,"mousemove",b.onmousemove)));b.opt.enablemousewheel&&
7630(b.isiframe||b.bind(g.isie&&b.ispage?document:b.win,"mousewheel",b.onmousewheel),b.bind(b.rail,"mousewheel",b.onmousewheel),b.railh&&b.bind(b.railh,"mousewheel",b.onmousewheelhr));!b.ispage&&(!g.cantouch&&!/HTML|BODY/.test(b.win[0].nodeName))&&(b.win.attr("tabindex")||b.win.attr({tabindex:L++}),b.jqbind(b.win,"focus",function(d){z=b.getTarget(d).id||!0;b.hasfocus=!0;b.canshowonmouseevent&&b.noticeCursor()}),b.jqbind(b.win,"blur",function(d){z=!1;b.hasfocus=!1}),b.jqbind(b.win,"mouseenter",function(d){E=
7631b.getTarget(d).id||!0;b.hasmousefocus=!0;b.canshowonmouseevent&&b.noticeCursor()}),b.jqbind(b.win,"mouseleave",function(){E=!1;b.hasmousefocus=!1;b.rail.drag||b.hideCursor()}))}b.onkeypress=function(d){if(b.locked&&0==b.page.maxh)return!0;d=d?d:window.e;var c=b.getTarget(d);if(c&&/INPUT|TEXTAREA|SELECT|OPTION/.test(c.nodeName)&&(!c.getAttribute("type")&&!c.type||!/submit|button|cancel/i.tp))return!0;
7631if(b.hasfocus||b.hasmousefocus&&!z||b.ispage&&!z&&!E){c=d.keyCode;if(b.locked&&27!=c)return b.cancelEvent(d);
7632var f=d.ctrlKey||!1,n=d.shiftKey||!1,g=!1;switch(c){case 38:case 63233:b.doScrollBy(72);g=!0;break;case 40:case 63235:b.doScrollBy(-72);g=!0;break;case 37:case 63232:b.railh&&(f?b.doScrollLeft(0):b.doScrollLeftBy(72),g=!0);break;case 39:case 63234:b.railh&&(f?b.doScrollLeft(b.page.maxw):b.doScrollLeftBy(-72),g=!0);break;case 33:case 63276:b.doScrollBy(b.view.h);g=!0;break;case 34:case 63277:b.doScrollBy(-b.view.h);g=!0;break;case 36:case 63273:b.railh&&f?b.doScrollPos(0,0):b.doScrollTo(0);g=!0;break;
7633case 35:case 63275:b.railh&&f?b.doScrollPos(b.page.maxw,b.page.maxh):b.doScrollTo(b.page.maxh);g=!0;break;case 32:b.opt.spacebarenabled&&(n?b.doScrollBy(b.view.h):b.doScrollBy(-b.view.h),g=!0);break;case 27:b.zoomactive&&(b.doZoom(),g=!0)}if(g)return b.cancelEvent(d)}};b.opt.enablekeyboard&&b.bind(document,g.isopera&&!g.isopera12?"keypress":"keydown",b.onkeypress);b.bind(window,"resize",b.lazyResize);b.bind(window,"orientationchange",b.lazyResize);b.bind(window,"load",b.lazyResize);if(g.ischrome&&
7634!b.ispage&&!b.haswrapper){var s=b.win.attr("style"),f=parseFloat(b.win.css("width"))+1;b.win.css("width",f);b.synched("chromefix",function(){b.win.attr("style",s)})}b.onAttributeChange=function(d){b.lazyResize(250)};!b.ispage&&!b.haswrapper&&(!1!==A?(b.observer=new A(function(d){d.forEach(b.onAttributeChange)}),b.observer.observe(b.win[0],{childList:!0,characterData:!1,attributes:!0,subtree:!1}),b.observerremover=new A(function(d){d.forEach(function(d){if(0<d.removedNodes.length)for(var c in d.removedNodes)if(d.removedNodes[c]==
7635b.win[0])return b.remove()})}),b.observerremover.observe(b.win[0].parentNode,{childList:!0,characterData:!1,attributes:!1,subtree:!1})):(b.bind(b.win,g.isie&&!g.isie9?"propertychange":"DOMAttrModified",b.onAttributeChange),g.isie9&&b.win[0].attachEvent("onpropertychange",b.onAttributeChange),b.bind(b.win,"DOMNodeRemoved",function(d){d.target==b.win[0]&&b.remove()})));!b.ispage&&b.opt.boxzoom&&b.bind(window,"resize",b.resizeZoom);b.istextarea&&b.bind(b.win,"mouseup",b.lazyResize);b.checkrtlmode=!0;
7636b.lazyResize(30)}if("IFRAME"==this.doc[0].nodeName){var K=function(d){b.iframexd=!1;try{var c="contentDocument"in this?this.contentDocument:this.contentWindow.document}catch(f){b.iframexd=!0,c=!1}if(b.iframexd)return"console"in window&&console.log("NiceScroll error: policy restriced iframe"),!0;b.forcescreen=!0;b.isiframe&&(b.iframe={doc:e(c),html:b.doc.contents().find("html")[0],body:b.doc.contents().find("body")[0]},b.getContentSize=function(){return{w:Math.max(b.iframe.html.scrollWidth,b.iframe.body.scrollWidth),
7637h:Math.max(b.iframe.html.scrollHeight,b.iframe.body.scrollHeight)}},b.docscroll=e(b.iframe.body));!g.isios&&(b.opt.iframeautoresize&&!b.isiframe)&&(b.win.scrollTop(0),b.doc.height(""),d=Math.max(c.getElementsByTagName("html")[0].scrollHeight,c.body.scrollHeight),b.doc.height(d));b.lazyResize(30);g.isie7&&b.css(e(b.iframe.html),{"overflow-y":"hidden"});b.css(e(b.iframe.body),{"overflow-y":"hidden"});g.isios&&b.haswrapper&&b.css(e(c.body),{"-webkit-transform":"translate3d(0,0,0)"});"contentWindow"in
7638this?b.bind(this.contentWindow,"scroll",b.onscroll):b.bind(c,"scroll",b.onscroll);b.opt.enablemousewheel&&b.bind(c,"mousewheel",b.onmousewheel);b.opt.enablekeyboard&&b.bind(c,g.isopera?"keypress":"keydown",b.onkeypress);if(g.cantouch||b.opt.touchbehavior)b.bind(c,"mousedown",b.ontouchstart),b.bind(c,"mousemove",function(d){b.ontouchmove(d,!0)}),b.opt.grabcursorenabled&&g.cursorgrabvalue&&b.css(e(c.body),{cursor:g.cursorgrabvalue});b.bind(c,"mouseup",b.ontouchend);b.zoom&&(b.opt.dblclickzoom&&b.bind(c,
7639"dblclick",b.doZoom),b.ongesturezoom&&b.bind(c,"gestureend",b.ongesturezoom))};this.doc[0].readyState&&"complete"==this.doc[0].readyState&&setTimeout(function(){K.call(b.doc[0],!1)},500);b.bind(this.doc,"load",K)}};this.showCursor=function(d,c){b.cursortimeout&&(clearTimeout(b.cursortimeout),b.cursortimeout=0);if(b.rail){b.autohidedom&&(b.autohidedom.stop().css({opacity:b.opt.cursoropacitymax}),b.cursoractive=!0);if(!b.rail.drag||1!=b.rail.drag.pt)"undefined"!=typeof d&&!1!==d&&(b.scroll.y=Math.round(1*
7640d/b.scrollratio.y)),"undefined"!=typeof c&&(b.scroll.x=Math.round(1*c/b.scrollratio.x));b.cursor.css({height:b.cursorheight,top:b.scroll.y});b.cursorh&&(!b.rail.align&&b.rail.visibility?b.cursorh.css({width:b.cursorwidth,left:b.scroll.x+b.rail.width}):b.cursorh.css({width:b.cursorwidth,left:b.scroll.x}),b.cursoractive=!0);b.zoom&&b.zoom.stop().css({opacity:b.opt.cursoropacitymax})}};this.hideCursor=function(d){!b.cursortimeout&&(b.rail&&b.autohidedom&&!(b.hasmousefocus&&"leave"==b.opt.autohidemode))&&
7641(b.cursortimeout=setTimeout(function(){if(!b.rail.active||!b.showonmouseevent)b.autohidedom.stop().animate({opacity:b.opt.cursoropacitymin}),b.zoom&&b.zoom.stop().animate({opacity:b.opt.cursoropacitymin}),b.cursoractive=!1;
7641b.cursortimeout=0},d||b.opt.hidecursordelay))};this.noticeCursor=function(d,c,f){b.showCursor(c,f);b.rail.active||b.hideCursor(d)};this.getContentSize=b.ispage?function(){return{w:Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),h:Math.max(document.body.scrollHeight,
7642document.documentElement.scrollHeight)}}:b.haswrapper?function(){return{w:b.doc.outerWidth()+parseInt(b.win.css("paddingLeft"))+parseInt(b.win.css("paddingRight")),h:b.doc.outerHeight()+parseInt(b.win.css("paddingTop"))+parseInt(b.win.css("paddingBottom"))}}:function(){return{w:b.docscroll[0].scrollWidth,h:b.docscroll[0].scrollHeight}};this.onResize=function(d,c){if(!b.win)return!1;if(!b.haswrapper&&!b.ispage){if("none"==b.win.css("display"))return b.visibility&&b.hideRail().hideRailHr(),!1;!b.hidden&&
7643!b.visibility&&b.showRail().showRailHr()}var f=b.page.maxh,g=b.page.maxw,e=b.view.w;b.view={w:b.ispage?b.win.width():parseInt(b.win[0].clientWidth),h:b.ispage?b.win.height():parseInt(b.win[0].clientHeight)};b.page=c?c:b.getContentSize();b.page.maxh=Math.max(0,b.page.h-b.view.h);b.page.maxw=Math.max(0,b.page.w-b.view.w);if(b.page.maxh==f&&b.page.maxw==g&&b.view.w==e){if(b.ispage)return b;f=b.win.offset();if(b.lastposition&&(g=b.lastposition,g.top==f.top&&g.left==f.left))return b;b.lastposition=f}0==
7644b.page.maxh?(b.hideRail(),b.scrollvaluemax=0,b.scroll.y=0,b.scrollratio.y=0,b.cursorheight=0,b.setScrollTop(0),b.rail.scrollable=!1):b.rail.scrollable=!0;0==b.page.maxw?(b.hideRailHr(),b.scrollvaluemaxw=0,b.scroll.x=0,b.scrollratio.x=0,b.cursorwidth=0,b.setScrollLeft(0),b.railh.scrollable=!1):b.railh.scrollable=!0;b.locked=0==b.page.maxh&&0==b.page.maxw;if(b.locked)return b.ispage||b.updateScrollBar(b.view),!1;!b.hidden&&!b.visibility?b.showRail().showRailHr():!b.hidden&&!b.railh.visibility&&b.showRailHr();
7645b.istextarea&&(b.win.css("resize")&&"none"!=b.win.css("resize"))&&(b.view.h-=20);b.cursorheight=Math.min(b.view.h,Math.round(b.view.h*(b.view.h/b.page.h)));b.cursorheight=b.opt.cursorfixedheight?b.opt.cursorfixedheight:Math.max(b.opt.cursorminheight,b.cursorheight);b.cursorwidth=Math.min(b.view.w,Math.round(b.view.w*(b.view.w/b.page.w)));b.cursorwidth=b.opt.cursorfixedheight?b.opt.cursorfixedheight:Math.max(b.opt.cursorminheight,b.cursorwidth);b.scrollvaluemax=b.view.h-b.cursorheight-b.cursor.hborder;
7646b.railh&&(b.railh.width=0<b.page.maxh?b.view.w-b.rail.width:b.view.w,b.scrollvaluemaxw=b.railh.width-b.cursorwidth-b.cursorh.wborder);b.checkrtlmode&&b.railh&&(b.checkrtlmode=!1,b.opt.rtlmode&&0==b.scroll.x&&b.setScrollLeft(b.page.maxw));b.ispage||b.updateScrollBar(b.view);b.scrollratio={x:b.page.maxw/b.scrollvaluemaxw,y:b.page.maxh/b.scrollvaluemax};b.getScrollTop()>b.page.maxh?b.doScrollTop(b.page.maxh):(b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y)),b.scroll.x=Math.round(b.getScrollLeft()*
7647(1/b.scrollratio.x)),b.cursoractive&&b.noticeCursor());b.scroll.y&&0==b.getScrollTop()&&b.doScrollTo(Math.floor(b.scroll.y*b.scrollratio.y));return b};this.resize=b.onResize;this.lazyResize=function(d){d=isNaN(d)?30:d;b.delayed("resize",b.resize,d);return b};this._bind=function(d,c,f,g){b.events.push({e:d,n:c,f:f,b:g,q:!1});d.addEventListener?d.addEventListener(c,f,g||!1):d.attachEvent?d.attachEvent("on"+c,f):d["on"+c]=f};this.jqbind=function(d,c,f){b.events.push({e:d,n:c,f:f,q:!0});e(d).bind(c,f)};
7648this.bind=function(d,c,f,e){var k="jquery"in d?d[0]:d;"mousewheel"==c?"onwheel"in b.win?b._bind(k,"wheel",f,e||!1):(d="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",q(k,d,f,e||!1),"DOMMouseScroll"==d&&q(k,"MozMousePixelScroll",f,e||!1)):k.addEventListener?(g.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&b._bind(k,"mousedown"==c?"touchstart":"mouseup"==c?"touchend":"touchmove",function(b){if(b.touches){if(2>b.touches.length){var d=b.touches.length?b.touches[0]:b;d.original=
7649b;f.call(this,d)}}else b.changedTouches&&(d=b.changedTouches[0],d.original=b,f.call(this,d))},e||!1),b._bind(k,c,f,e||!1),g.cantouch&&"mouseup"==c&&b._bind(k,"touchcancel",f,e||!1)):b._bind(k,c,function(d){if((d=d||window.event||!1)&&d.srcElement)d.target=d.srcElement;"pageY"in d||(d.pageX=d.clientX+document.documentElement.scrollLeft,d.pageY=d.clientY+document.documentElement.scrollTop);return!1===f.call(k,d)||!1===e?b.cancelEvent(d):!0})};this._unbind=function(b,c,f,g){b.removeEventListener?b.removeEventListener(c,
7650f,g):b.detachEvent?b.detachEvent("on"+c,f):b["on"+c]=!1};this.unbindAll=function(){for(var d=0;d<b.events.length;d++){var c=b.events[d];c.q?c.e.unbind(c.n,c.f):b._unbind(c.e,c.n,c.f,c.b)}};this.cancelEvent=function(b){b=b.original?b.original:b?b:window.event||!1;if(!b)return!1;b.preventDefault&&b.preventDefault();b.stopPropagation&&b.stopPropagation();b.preventManipulation&&b.preventManipulation();b.cancelBubble=!0;b.cancel=!0;return b.returnValue=!1};this.stopPropagation=function(b){b=b.original?
7651b.original:b?b:window.event||!1;if(!b)return!1;if(b.stopPropagation)return b.stopPropagation();b.cancelBubble&&(b.cancelBubble=!0);return!1};this.showRail=function(){if(0!=b.page.maxh&&(b.ispage||"none"!=b.win.css("display")))b.visibility=!0,b.rail.visibility=!0,b.rail.css("display","block");return b};this.showRailHr=function(){if(!b.railh)return b;if(0!=b.page.maxw&&(b.ispage||"none"!=b.win.css("display")))b.railh.visibility=!0,b.railh.css("display","block");return b};this.hideRail=function(){b.visibility=
7652!1;b.rail.visibility=!1;b.rail.css("display","none");return b};this.hideRailHr=function(){if(!b.railh)return b;b.railh.visibility=!1;b.railh.css("display","none");return b};this.show=function(){b.hidden=!1;b.locked=!1;return b.showRail().showRailHr()};this.hide=function(){b.hidden=!0;b.locked=!0;return b.hideRail().hideRailHr()};this.toggle=function(){return b.hidden?b.show():b.hide()};this.remove=function(){b.stop();b.cursortimeout&&clearTimeout(b.cursortimeout);b.doZoomOut();b.unbindAll();g.isie9&&
7653b.win[0].detachEvent("onpropertychange",b.onAttributeChange);!1!==b.observer&&b.observer.disconnect();!1!==b.observerremover&&b.observerremover.disconnect();b.events=null;b.cursor&&b.cursor.remove();b.cursorh&&b.cursorh.remove();b.rail&&b.rail.remove();b.railh&&b.railh.remove();b.zoom&&b.zoom.remove();for(var d=0;d<b.saved.css.length;d++){var c=b.saved.css[d];c[0].css(c[1],"undefined"==typeof c[2]?"":c[2])}b.saved=!1;b.me.data("__nicescroll","");var f=e.nicescroll;f.each(function(d){if(this&&this.id===
7654b.id){delete f[d];for(var c=++d;c<f.length;c++,d++)f[d]=f[c];f.length--;f.length&&delete f[f.length]}});for(var k in b)b[k]=null,delete b[k];b=null};this.scrollstart=function(d){this.onscrollstart=d;return b};this.scrollend=function(d){this.onscrollend=d;return b};this.scrollcancel=function(d){this.onscrollcancel=d;return b};this.zoomin=function(d){this.onzoomin=d;return b};this.zoomout=function(d){this.onzoomout=d;return b};this.isScrollable=function(b){b=b.target?b.target:b;if("OPTION"==b.nodeName)return!0;
7655for(;b&&1==b.nodeType&&!/BODY|HTML/.test(b.nodeName);){var c=e(b),c=c.css("overflowY")||c.css("overflowX")||c.css("overflow")||"";if(/scroll|auto/.test(c))return b.clientHeight!=b.scrollHeight;b=b.parentNode?b.parentNode:!1}return!1};this.getViewport=function(b){for(b=b&&b.parentNode?b.parentNode:!1;b&&1==b.nodeType&&!/BODY|HTML/.test(b.nodeName);){var c=e(b);
7655if(/fixed|absolute/.test(c.css("position")))return c;var f=c.css("overflowY")||c.css("overflowX")||c.css("overflow")||"";if(/scroll|auto/.test(f)&&
7656b.clientHeight!=b.scrollHeight||0<c.getNiceScroll().length)return c;b=b.parentNode?b.parentNode:!1}return!1};this.onmousewheel=function(d){if(b.locked)return b.debounced("checkunlock",b.resize,250),!0;if(b.rail.drag)return b.cancelEvent(d);"auto"==b.opt.oneaxismousemode&&0!=d.deltaX&&(b.opt.oneaxismousemode=!1);if(b.opt.oneaxismousemode&&0==d.deltaX&&!b.rail.scrollable)return b.railh&&b.railh.scrollable?b.onmousewheelhr(d):!0;var c=+new Date,f=!1;b.opt.preservenativescrolling&&b.checkarea+600<c&&
7657(b.nativescrollingarea=b.isScrollable(d),f=!0);b.checkarea=c;if(b.nativescrollingarea)return!0;if(d=t(d,!1,f))b.checkarea=0;return d};this.onmousewheelhr=function(d){if(b.locked||!b.railh.scrollable)return!0;if(b.rail.drag)return b.cancelEvent(d);var c=+new Date,f=!1;b.opt.preservenativescrolling&&b.checkarea+600<c&&(b.nativescrollingarea=b.isScrollable(d),f=!0);b.checkarea=c;return b.nativescrollingarea?!0:b.locked?b.cancelEvent(d):t(d,!0,f)};this.stop=function(){b.cancelScroll();b.scrollmon&&b.scrollmon.stop();
7658b.cursorfreezed=!1;b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.noticeCursor();return b};this.getTransitionSpeed=function(d){var c=Math.round(10*b.opt.scrollspeed);d=Math.min(c,Math.round(d/20*b.opt.scrollspeed));return 20<d?d:0};b.opt.smoothscroll?b.ishwscroll&&g.hastransition&&b.opt.usetransition?(this.prepareTransition=function(d,c){var f=c?20<d?d:0:b.getTransitionSpeed(d),e=f?g.prefixstyle+"transform "+f+"ms ease-out":"";if(!b.lasttransitionstyle||b.lasttransitionstyle!=e)b.lasttransitionstyle=
7659e,b.doc.css(g.transitionstyle,e);return f},this.doScrollLeft=function(c,g){var f=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,g){var f=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(f,c,g)},this.doScrollPos=function(c,e,f){var k=b.getScrollTop(),l=b.getScrollLeft();(0>(b.newscrolly-k)*(e-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();!1==b.opt.bouncescroll&&(0>e?e=0:e>b.page.maxh&&(e=b.page.maxh),0>c?c=0:c>b.page.maxw&&(c=b.page.maxw));
7660if(b.scrollrunning&&c==b.newscrollx&&e==b.newscrolly)return!1;b.newscrolly=e;b.newscrollx=c;b.newscrollspeed=f||!1;if(b.timer)return!1;b.timer=setTimeout(function(){var f=b.getScrollTop(),k=b.getScrollLeft(),l,h;l=c-k;h=e-f;l=Math.round(Math.sqrt(Math.pow(l,2)+Math.pow(h,2)));l=b.newscrollspeed&&1<b.newscrollspeed?b.newscrollspeed:b.getTransitionSpeed(l);b.newscrollspeed&&1>=b.newscrollspeed&&(l*=b.newscrollspeed);b.prepareTransition(l,!0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);
76610<l&&(!b.scrollrunning&&b.onscrollstart&&b.onscrollstart.call(b,{type:"scrollstart",current:{x:k,y:f},request:{x:c,y:e},end:{x:b.newscrollx,y:b.newscrolly},speed:l}),g.transitionend?b.scrollendtrapped||(b.scrollendtrapped=!0,b.bind(b.doc,g.transitionend,b.onScrollEnd,!1)):(b.scrollendtrapped&&clearTimeout(b.scrollendtrapped),b.scrollendtrapped=setTimeout(b.onScrollEnd,l)),b.timerscroll={bz:new BezierClass(f,b.newscrolly,l,0,0,0.58,1),bh:new BezierClass(k,b.newscrollx,l,0,0,0.58,1)},b.cursorfreezed||
7662(b.timerscroll.tm=setInterval(function(){b.showCursor(b.getScrollTop(),b.getScrollLeft())},60)));b.synched("doScroll-set",function(){b.timer=0;b.scrollendtrapped&&(b.scrollrunning=!0);b.setScrollTop(b.newscrolly);b.setScrollLeft(b.newscrollx);if(!b.scrollendtrapped)b.onScrollEnd()})},50)},this.cancelScroll=function(){if(!b.scrollendtrapped)return!0;var c=b.getScrollTop(),e=b.getScrollLeft();b.scrollrunning=!1;g.transitionend||clearTimeout(g.transitionend);b.scrollendtrapped=!1;b._unbind(b.doc,g.transitionend,
7663b.onScrollEnd);b.prepareTransition(0);b.setScrollTop(c);b.railh&&b.setScrollLeft(e);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);b.timerscroll=!1;b.cursorfreezed=!1;b.showCursor(c,e);return b},this.onScrollEnd=function(){b.scrollendtrapped&&b._unbind(b.doc,g.transitionend,b.onScrollEnd);b.scrollendtrapped=!1;b.prepareTransition(0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);b.timerscroll=!1;var c=b.getScrollTop(),e=b.getScrollLeft();b.setScrollTop(c);b.railh&&
7664b.setScrollLeft(e);b.noticeCursor(!1,c,e);
7664b.cursorfreezed=!1;0>c?c=0:c>b.page.maxh&&(c=b.page.maxh);0>e?e=0:e>b.page.maxw&&(e=b.page.maxw);if(c!=b.newscrolly||e!=b.newscrollx)return b.doScrollPos(e,c,b.opt.snapbackspeed);b.onscrollend&&b.scrollrunning&&b.onscrollend.call(b,{type:"scrollend",current:{x:e,y:c},end:{x:b.newscrollx,y:b.newscrolly}});b.scrollrunning=!1}):(this.doScrollLeft=function(c,g){var f=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,
7665g){var f=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(f,c,g)},this.doScrollPos=function(c,g,f){function e(){if(b.cancelAnimationFrame)return!0;b.scrollrunning=!0;if(p=1-p)return b.timer=v(e)||1;var c=0,d=sy=b.getScrollTop();if(b.dst.ay){var d=b.bzscroll?b.dst.py+b.bzscroll.getNow()*b.dst.ay:b.newscrolly,f=d-sy;if(0>f&&d<b.newscrolly||0<f&&d>b.newscrolly)d=b.newscrolly;b.setScrollTop(d);d==b.newscrolly&&(c=1)}else c=1;var g=sx=b.getScrollLeft();if(b.dst.ax){g=b.bzscroll?b.dst.px+b.bzscroll.getNow()*
7666b.dst.ax:b.newscrollx;f=g-sx;if(0>f&&g<b.newscrollx||0<f&&g>b.newscrollx)g=b.newscrollx;b.setScrollLeft(g);g==b.newscrollx&&(c+=1)}else c+=1;2==c?(b.timer=0,b.cursorfreezed=!1,b.bzscroll=!1,b.scrollrunning=!1,0>d?d=0:d>b.page.maxh&&(d=b.page.maxh),0>g?g=0:g>b.page.maxw&&(g=b.page.maxw),g!=b.newscrollx||d!=b.newscrolly?b.doScrollPos(g,d):b.onscrollend&&b.onscrollend.call(b,{type:"scrollend",current:{x:sx,y:sy},end:{x:b.newscrollx,y:b.newscrolly}})):b.timer=v(e)||1}g="undefined"==typeof g||!1===g?b.getScrollTop(!0):
7667g;if(b.timer&&b.newscrolly==g&&b.newscrollx==c)return!0;b.timer&&w(b.timer);b.timer=0;var k=b.getScrollTop(),l=b.getScrollLeft();(0>(b.newscrolly-k)*(g-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();b.newscrolly=g;b.newscrollx=c;if(!b.bouncescroll||!b.rail.visibility)0>b.newscrolly?b.newscrolly=0:b.newscrolly>b.page.maxh&&(b.newscrolly=b.page.maxh);if(!b.bouncescroll||!b.railh.visibility)0>b.newscrollx?b.newscrollx=0:b.newscrollx>b.page.maxw&&(b.newscrollx=b.page.maxw);b.dst={};b.dst.x=c-l;b.dst.y=
7668g-k;b.dst.px=l;b.dst.py=k;var h=Math.round(Math.sqrt(Math.pow(b.dst.x,2)+Math.pow(b.dst.y,2)));b.dst.ax=b.dst.x/h;b.dst.ay=b.dst.y/h;var m=0,q=h;0==b.dst.x?(m=k,q=g,b.dst.ay=1,b.dst.py=0):0==b.dst.y&&(m=l,q=c,b.dst.ax=1,b.dst.px=0);h=b.getTransitionSpeed(h);f&&1>=f&&(h*=f);b.bzscroll=0<h?b.bzscroll?b.bzscroll.update(q,h):new BezierClass(m,q,h,0,1,0,1):!1;if(!b.timer){(k==b.page.maxh&&g>=b.page.maxh||l==b.page.maxw&&c>=b.page.maxw)&&b.checkContentSize();var p=1;b.cancelAnimationFrame=!1;b.timer=1;
7669b.onscrollstart&&!b.scrollrunning&&b.onscrollstart.call(b,{type:"scrollstart",current:{x:l,y:k},request:{x:c,y:g},end:{x:b.newscrollx,y:b.newscrolly},speed:h});e();(k==b.page.maxh&&g>=k||l==b.page.maxw&&c>=l)&&b.checkContentSize();b.noticeCursor()}},this.cancelScroll=function(){b.timer&&w(b.timer);b.timer=0;b.bzscroll=!1;b.scrollrunning=!1;return b}):(this.doScrollLeft=function(c,g){var f=b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,g){var f=b.getScrollLeft();b.doScrollPos(f,
7670c,g)},this.doScrollPos=function(c,g,f){var e=c>b.page.maxw?b.page.maxw:c;0>e&&(e=0);var k=g>b.page.maxh?b.page.maxh:g;0>k&&(k=0);b.synched("scroll",function(){b.setScrollTop(k);b.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.y-c)*b.scrollratio.y):(b.timer?b.newscrolly:b.getScrollTop(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.h/2);f<-e?f=-e:f>b.page.maxh+e&&(f=b.page.maxh+e)}b.cursorfreezed=!1;py=b.getScrollTop(!0);if(0>f&&
76710>=py)return b.noticeCursor();if(f>b.page.maxh&&py>=b.page.maxh)return b.checkContentSize(),b.noticeCursor();b.doScrollTop(f)};this.doScrollLeftBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.x-c)*b.scrollratio.x):(b.timer?b.newscrollx:b.getScrollLeft(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.w/2);f<-e?f=-e:f>b.page.maxw+e&&(f=b.page.maxw+e)}b.cursorfreezed=!1;px=b.getScrollLeft(!0);if(0>f&&0>=px||f>b.page.maxw&&px>=b.page.maxw)return b.noticeCursor();b.doScrollLeft(f)};this.doScrollTo=
7672function(c,g){g&&Math.round(c*b.scrollratio.y);b.cursorfreezed=!1;b.doScrollTop(c)};this.checkContentSize=function(){var c=b.getContentSize();(c.h!=b.page.h||c.w!=b.page.w)&&b.resize(!1,c)};b.onscroll=function(c){b.rail.drag||b.cursorfreezed||b.synched("scroll",function(){b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.railh&&(b.scroll.x=Math.round(b.getScrollLeft()*(1/b.scrollratio.x)));b.noticeCursor()})};
7672b.bind(b.docscroll,"scroll",b.onscroll);this.doZoomIn=function(c){if(!b.zoomactive){b.zoomactive=
7673!0;b.zoomrestore={style:{}};var k="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),f=b.win[0].style,l;for(l in k){var h=k[l];b.zoomrestore.style[h]="undefined"!=typeof f[h]?f[h]:""}b.zoomrestore.style.width=b.win.css("width");b.zoomrestore.style.height=b.win.css("height");b.zoomrestore.padding={w:b.win.outerWidth()-b.win.width(),h:b.win.outerHeight()-b.win.height()};g.isios4&&(b.zoomrestore.scrollTop=e(window).scrollTop(),e(window).scrollTop(0));
7674b.win.css({position:g.isios4?"absolute":"fixed",top:0,left:0,"z-index":y+100,margin:"0px"});k=b.win.css("backgroundColor");(""==k||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(k))&&b.win.css("backgroundColor","#fff");b.rail.css({"z-index":y+101});b.zoom.css({"z-index":y+102});b.zoom.css("backgroundPosition","0px -18px");b.resizeZoom();b.onzoomin&&b.onzoomin.call(b);return b.cancelEvent(c)}};this.doZoomOut=function(c){if(b.zoomactive)return b.zoomactive=!1,b.win.css("margin",""),b.win.css(b.zoomrestore.style),
7675g.isios4&&e(window).scrollTop(b.zoomrestore.scrollTop),b.rail.css({"z-index":b.zindex}),b.zoom.css({"z-index":b.zindex}),b.zoomrestore=!1,b.zoom.css("backgroundPosition","0px 0px"),b.onResize(),b.onzoomout&&b.onzoomout.call(b),b.cancelEvent(c)};this.doZoom=function(c){return b.zoomactive?b.doZoomOut(c):b.doZoomIn(c)};this.resizeZoom=function(){if(b.zoomactive){var c=b.getScrollTop();b.win.css({width:e(window).width()-b.zoomrestore.padding.w+"px",height:e(window).height()-b.zoomrestore.padding.h+"px"});
7676b.onResize();b.setScrollTop(Math.min(b.page.maxh,c))}};this.init();e.nicescroll.push(this)},J=function(e){var c=this;this.nc=e;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(e,l){c.stop();var h=c.time();c.steptime=0;c.lasttime=h;c.speedx=0;c.speedy=0;c.lastx=e;c.lasty=l;c.lastscrollx=-1;c.lastscrolly=
7677-1};this.update=function(e,l){var h=c.time();c.steptime=h-c.lasttime;c.lasttime=h;var h=l-c.lasty,t=e-c.lastx,b=c.nc.getScrollTop(),p=c.nc.getScrollLeft(),b=b+h,p=p+t;c.snapx=0>p||p>c.nc.page.maxw;c.snapy=0>b||b>c.nc.page.maxh;c.speedx=t;c.speedy=h;c.lastx=e;c.lasty=l};this.stop=function(){c.nc.unsynched("domomentum2d");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(e,l){var h=!1;0>l?(l=0,h=!0):l>c.nc.page.maxh&&(l=c.nc.page.maxh,h=!0);0>e?(e=0,h=
7678!0):e>c.nc.page.maxw&&(e=c.nc.page.maxw,h=!0);h&&c.nc.doScrollPos(e,l,c.nc.opt.snapbackspeed)};this.doMomentum=function(e){var l=c.time(),h=e?l+e:c.lasttime;e=c.nc.getScrollLeft();var t=c.nc.getScrollTop(),b=c.nc.page.maxh,p=c.nc.page.maxw;c.speedx=0<p?Math.min(60,c.speedx):0;c.speedy=0<b?Math.min(60,c.speedy):0;h=h&&60>=l-h;if(0>t||t>b||0>e||e>p)h=!1;e=c.speedx&&h?c.speedx:!1;if(c.speedy&&h&&c.speedy||e){var g=Math.max(16,c.steptime);50<g&&(e=g/50,c.speedx*=e,c.speedy*=e,g=50);c.demulxy=0;c.lastscrollx=
7679c.nc.getScrollLeft();c.chkx=c.lastscrollx;c.lastscrolly=c.nc.getScrollTop();c.chky=c.lastscrolly;var s=c.lastscrollx,u=c.lastscrolly,d=function(){var e=600<c.time()-l?0.04:0.02;if(c.speedx&&(s=Math.floor(c.lastscrollx-c.speedx*(1-c.demulxy)),c.lastscrollx=s,0>s||s>p))e=0.1;if(c.speedy&&(u=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=u,0>u||u>b))e=0.1;c.demulxy=Math.min(1,c.demulxy+e);c.nc.synched("domomentum2d",function(){c.speedx&&(c.nc.getScrollLeft()!=c.chkx&&c.stop(),c.chkx=
7680s,c.nc.setScrollLeft(s));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=u,c.nc.setScrollTop(u));c.timer||(c.nc.hideCursor(),c.doSnapy(s,u))});1>c.demulxy?c.timer=setTimeout(d,g):(c.stop(),c.nc.hideCursor(),c.doSnapy(s,u))};d()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},B=e.fn.scrollTop;e.cssHooks.pageYOffset={get:function(h,c,k){return(c=e.data(h,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollTop():B.call(h)},set:function(h,c){var k=e.data(h,"__nicescroll")||!1;k&&k.ishwscroll?
7681k.setScrollTop(parseInt(c)):B.call(h,c);return this}};e.fn.scrollTop=function(h){if("undefined"==typeof h){var c=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():B.call(this)}return this.each(function(){var c=e.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(h)):B.call(e(this),h)})};
7681var C=e.fn.scrollLeft;e.cssHooks.pageXOffset={get:function(h,c,k){return(c=e.data(h,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollLeft():C.call(h)},set:function(h,
7682c){var k=e.data(h,"__nicescroll")||!1;k&&k.ishwscroll?k.setScrollLeft(parseInt(c)):C.call(h,c);return this}};e.fn.scrollLeft=function(h){if("undefined"==typeof h){var c=this[0]?e.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():C.call(this)}return this.each(function(){var c=e.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(h)):C.call(e(this),h)})};var D=function(h){var c=this;this.length=0;this.name="nicescrollarray";this.each=function(e){for(var h=
76830,k=0;h<c.length;h++)e.call(c[h],k++);return c};this.push=function(e){c[c.length]=e;c.length++};this.eq=function(e){return c[e]};if(h)for(a=0;a<h.length;a++){var k=e.data(h[a],"__nicescroll")||!1;k&&(this[this.length]=k,this.length++)}return this};(function(e,c,k){for(var l=0;l<c.length;l++)k(e,c[l])})(D.prototype,"show hide toggle onResize resize remove stop doScrollPos".split(" "),function(e,c){e[c]=function(){var e=arguments;return this.each(function(){this[c].apply(this,e)})}});e.fn.getNiceScroll=
7684function(h){return"undefined"==typeof h?new D(this):this[h]&&e.data(this[h],"__nicescroll")||!1};e.extend(e.expr[":"],{nicescroll:function(h){return e.data(h,"__nicescroll")?!0:!1}});e.fn.niceScroll=function(h,c){"undefined"==typeof c&&("object"==typeof h&&!("jquery"in h))&&(c=h,h=!1);var k=new D;"undefined"==typeof c&&(c={});h&&(c.doc=e(h),c.win=e(this));var l=!("doc"in c);!l&&!("win"in c)&&(c.win=e(this));this.each(function(){var h=e(this).data("__nicescroll")||!1;h||(c.doc=l?e(this):c.doc,h=new Q(c,
7685e(this)),e(this).data("__nicescroll",h));k.push(h)});return 1==k.length?k[0]:k};window.NiceScroll={getjQuery:function(){return e}};e.nicescroll||(e.nicescroll=new D,e.nicescroll.options=I)})(jQuery);
7686
7687/* mousetrap v1.4.4 craig.is/killing/mice */
7688(function(){function s(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)}function z(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return" "==b?"space":b}return k[a.which]?k[a.which]:A[a.which]?A[a.which]:String.fromCharCode(a.which).toLowerCase()}function t(a){a=a||{};var b=!1,c;for(c in p)a[c]?b=!0:p[c]=0;b||(u=!1)}function B(a,b,c,d,e,g){var f,l,h=[],k=c.type;if(!m[a])return[];"keyup"==k&&v(a)&&(b=[a]);for(f=0;f<m[a].length;++f)if(l=
7689m[a][f],!(!d&&l.seq&&p[l.seq]!=l.level||k!=l.action||("keypress"!=k||c.metaKey||c.ctrlKey)&&b.sort().join(",")!==l.modifiers.sort().join(","))){var n=d&&l.seq==d&&l.level==g;(!d&&l.combo==e||n)&&m[a].splice(f,1);h.push(l)}return h}function I(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function w(a,b,c){n.stopCallback(b,b.target||b.srcElement,c)||!1!==a(b,c)||(b.preventDefault&&b.preventDefault(),b.stopPropagation&&b.stopPropagation(),
7690b.returnValue=!1,b.cancelBubble=!0)}function x(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=z(a);b&&("keyup"==a.type&&y===b?y=!1:n.handleKey(b,I(a),a))}function v(a){return"shift"==a||"ctrl"==a||"alt"==a||"meta"==a}function J(a,b,c,d){function e(b){return function(){u=b;++p[a];clearTimeout(C);C=setTimeout(t,1E3)}}function g(b){w(c,b,a);"keyup"!==d&&(y=z(b));setTimeout(t,10)}for(var f=p[a]=0;f<b.length;++f){var h=f+1===b.length?g:e(d||D(b[f+1]).action);E(b[f],h,d,a,f)}}function D(a,b){var c,
7691d,e,g=[];c="+"===a?["+"]:a.split("+");for(e=0;e<c.length;++e)d=c[e],F[d]&&(d=F[d]),b&&("keypress"!=b&&G[d])&&(d=G[d],g.push("shift")),v(d)&&g.push(d);c=d;e=b;if(!e){if(!q){q={};for(var f in k)95<f&&112>f||k.hasOwnProperty(f)&&(q[k[f]]=f)}e=q[c]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:d,modifiers:g,action:e}}function E(a,b,c,d,e){r[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?J(a,g,b,c):(c=D(a,c),m[c.key]=m[c.key]||[],B(c.key,c.modifiers,{type:c.action},
7692d,a,e),m[c.key][d?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:d,level:e,combo:a}))}for(var k={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},A={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},G={"~":"`","!":"1",
7693"@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},F={option:"alt",command:"meta","return":"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},q,m={},r={},p={},C,y=!1,H=!1,u=!1,h=1;20>h;++h)k[111+h]="f"+h;for(h=0;9>
7693=h;++h)k[h+96]=h;s(document,"keypress",x);s(document,"keydown",x);s(document,"keyup",x);var n={bind:function(a,b,c){a=a instanceof Array?a:[a];for(var d=0;d<a.length;++d)E(a[d],
7694b,c);return this},unbind:function(a,b){return n.bind(a,function(){},b)},trigger:function(a,b){if(r[a+":"+b])r[a+":"+b]({},a);return this},reset:function(){m={};r={};return this},stopCallback:function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.contentEditable&&"true"==b.contentEditable},handleKey:function(a,b,c){var d=B(a,b,c),e;b={};var g=0,f=!1;for(e=0;e<d.length;++e)d[e].seq&&(g=Math.max(g,d[e].level));for(e=0;e<
7695d.length;++e)d[e].seq?d[e].level==g&&(f=!0,b[d[e].seq]=1,w(d[e].callback,c,d[e].combo)):f||w(d[e].callback,c,d[e].combo);d="keypress"==c.type&&H;c.type!=u||(v(a)||d)||t(b);H=f&&"keydown"==c.type}};window.Mousetrap=n;"function"===typeof define&&define.amd&&define(n)})();
7696/**
7697 * jGrowl 1.2.6
7698 *
7699 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
7700 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
7701 *
7702 * Written by Stan Lemon <[email protected]>
7703 * Last updated: 2011.03.27
7704 *
7705 * jGrowl is a jQuery plugin implementing unobtrusive userland notifications.  These 
7706 * notifications function similarly to the Growl Framework available for
7707 * Mac OS X (http://growl.info).
7708 *
7709 * To Do:
7710 * - Move library settings to containers and allow them to be changed per container
7711 *
7712 * Changes in 1.2.6
7713 * - Fixed js error when a notification is opening and closing at the same time
7714 * 
7715 * Changes in 1.2.5
7716 * - Changed wrapper jGrowl's options usage to "o" instead of $.jGrowl.defaults
7717 * - Added themeState option to control 'highlight' or 'error' for jQuery UI
7718 * - Ammended some CSS to provide default positioning for nested usage.
7719 * - Changed some CSS to be prefixed with jGrowl- to prevent namespacing issues
7720 * - Added two new options - openDuration and closeDuration to allow 
7721 *   better control of notification open and close speeds, respectively 
7722 *   Patch contributed by Jesse Vincet.
7723 * - Added afterOpen callback.  Patch contributed by Russel Branca.
7724 *
7725 * Changes in 1.2.4
7726 * - Fixed IE bug with the close-all button
7727 * - Fixed IE bug with the filter CSS attribute (special thanks to gotwic)
7728 * - Update IE opacity CSS
7729 * - Changed font sizes to use "em", and only set the base style
7730 *
7731 * Changes in 1.2.3
7732 * - The callbacks no longer use the container as context, instead they use the actual notification
7733 * - The callbacks now receive the container as a parameter after the options parameter
7734 * - beforeOpen and beforeClose now check the return value, if it's false - the notification does
7735 *   not continue.  The open callback will also halt execution if it returns false.
7736 * - Fixed bug where containers would get confused
7737 * - Expanded the pause functionality to pause an entire container.
7738 *
7739 * Changes in 1.2.2
7740 * - Notification can now be theme rolled for jQuery UI, special thanks to Jeff Chan!
7741 *
7742 * Changes in 1.2.1
7743 * - Fixed instance where the interval would fire the close method multiple times.
7744 * - Added CSS to hide from print media
7745 * - Fixed issue with closer button when div { position: relative } is set
7746 * - Fixed leaking issue with multiple containers.  Special thanks to Matthew Hanlon!
7747 *
7748 * Changes in 1.2.0
7749 * - Added message pooling to limit the number of messages appearing at a given time.
7750 * - Closing a notification is now bound to the notification object and triggered by the close button.
7751 *
7752 * Changes in 1.1.2
7753 * - Added iPhone styled example
7754 * - Fixed possible IE7 bug when determining if the ie6 class shoudl be applied.
7755 * - Added template for the close button, so that it's content could be customized.
7756 *
7757 * Changes in 1.1.1
7758 * - Fixed CSS styling bug for ie6 caused by a mispelling
7759 * - Changes height restriction on default notifications to min-height
7760 * - Added skinned examples using a variety of images
7761 * - Added the ability to customize the content of the [close all] box
7762 * - Added jTweet, an example of using jGrowl + Twitter
7763 *
7764 * Changes in 1.1.0
7765 * - Multiple container and instances.
7766 * - Standard $.jGrowl() now wraps $.fn.jGrowl() by first establishing a generic jGrowl container.
7767 * - Instance methods of a jGrowl container can be called by $.fn.jGrowl(methodName)
7768 * - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container
7769 * - Added new log callback which is called before anything is done for the notification
7770 * - Corner's attribute are now applied on an individual notification basis.
7771 *
7772 * Changes in 1.0.4
7773 * - Various CSS fixes so that jGrowl renders correctly in IE6.
7774 *
7775 * Changes in 1.0.3
7776 * - Fixed bug with options persisting across notifications
7777 * - Fixed theme application bug
7778 * - Simplified some selectors and manipulations.
7779 * - Added beforeOpen and beforeClose callbacks
7780 * - Reorganized some lines of code to be more readable
7781 * - Removed unnecessary this.defaults context
7782 * - If corners plugin is present, it's now customizable.
7783 * - Customizable open animation.
7784 * - Customizable close animation.
7785 * - Customizable animation easing.
7786 * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
7787 *
7788 * Changes in 1.0.2
7789 * - All CSS styling is now external.
7790 * - Added a theme parameter which specifies a secondary class for styling, such
7791 *   that notifications can be customized in appearance on a per message basis.
7792 * - Notification life span is now customizable on a per message basis.
7793 * - Added the ability to disable the global closer, enabled by default.
7794 * - Added callbacks for when a notification is opened or closed.
7795 * - Added callback for the global closer.
7796 * - Customizable animation speed.
7797 * - jGrowl now set itself up and tears itself down.
7798 *
7799 * Changes in 1.0.1:
7800 * - Removed dependency on metadata plugin in favor of .data()
7801 * - Namespaced all events
7802 */
7803(function($) {
7804
7805	/** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/
7806	$.jGrowl = function( m , o ) {
7807		// To maintain compatibility with older version that only supported one instance we'll create the base container.
7808		if ( jQ_nxs('#jGrowl').size() == 0 ) 
7809			$('<div id="jGrowl"></div>').addClass( (o && o.position) ? o.position : $.jGrowl.defaults.position ).appendTo('body');
7810
7811		// Create a notification on the container.
7812		$('#jGrowl').jGrowl(m,o);
7813	};
7814
7815
7816	/** Raise jGrowl Notification on a jGrowl Container **/
7817	$.fn.jGrowl = function( m , o ) {
7818		if ( $.isFunction(this.each) ) {
7819			var args = arguments;
7820
7821			return this.each(function() {
7822				var self = this;
7823
7824				/** Create a jGrowl Instance on the Container if it does not exist **/
7825				if ( $(this).data('jGrowl.instance') == undefined ) {
7826					$(this).data('jGrowl.instance', $.extend( new $.fn.jGrowl(), { notifications: [], element: null, interval: null } ));
7827					$(this).data('jGrowl.instance').startup( this );
7828				}
7829
7830				/** Optionally call jGrowl instance methods, or just raise a normal notification **/
7831				if ( $.isFunction($(this).data('jGrowl.instance')[m]) ) {
7832					$(this).data('jGrowl.instance')[m].apply( $(this).data('jGrowl.instance') , $.makeArray(args).slice(1) );
7833				} else {
7834					$(this).data('jGrowl.instance').create( m , o );
7835				}
7836			});
7837		};
7838	};
7839
7840	$.extend( $.fn.jGrowl.prototype , {
7841
7842		/** Default JGrowl Settings **/
7843		defaults: {
7844			pool: 			0,
7845			header: 		'',
7846			group: 			'',
7847			sticky: 		false,
7848			position: 		'top-right',
7849			glue: 			'after',
7850			theme: 			'default',
7851			themeState: 	'highlight',
7852			corners: 		'10px',
7853			check: 			250,
7854			life: 			3000,
7855			closeDuration:  'normal',
7856			openDuration:   'normal',
7857			easing: 		'swing',
7858			closer: 		true,
7859			closeTemplate: '&times;',
7860			closerTemplate: '<div>[ close all ]</div>',
7861			log: 			function(e,m,o) {},
7862			beforeOpen: 	function(e,m,o) {},
7863			afterOpen: 		function(e,m,o) {},
7864			open: 			function(e,m,o) {},
7865			beforeClose: 	function(e,m,o) {},
7866			close: 			function(e,m,o) {},
7867			animateOpen: 	{
7868				opacity: 	'show'
7869			},
7870			animateClose: 	{
7871				opacity: 	'hide'
7872			}
7873		},
7874		
7875		notifications: [],
7876		
7877		/** jGrowl Container Node **/
7878		element: 	null,
7879	
7880		/** Interval Function **/
7881		interval:   null,
7882		
7883		/** Create a Notification **/
7884		create: 	function( message , o ) {
7885			var o = $.extend({}, this.defaults, o);
7886
7887			/* To keep backward compatibility with 1.24 and earlier, honor 'speed' if the user has set it */
7888			if (typeof o.speed !== 'undefined') {
7889				o.openDuration = o.speed;
7890				o.closeDuration = o.speed;
7891			}
7892
7893			this.notifications.push({ message: message , options: o });
7894			
7895			o.log.apply( this.element , [this.element,message,o] );
7896		},
7897		
7898		render: 		function( notification ) {
7899			var self = this;
7900			var message = notification.message;
7901			var o = notification.options;
7902
7903			// Support for jQuery theme-states, if this is not used it displays a widget header
7904			o.themeState = (o.themeState == '') ? '' : 'ui-state-' + o.themeState;
7905
7906			var notification = $(
7907				'<div class="jGrowl-notification ' + o.themeState + ' ui-corner-all' + 
7908				((o.group != undefined && o.group != '') ? ' ' + o.group : '') + '">' +
7909				'<div class="jGrowl-close">' + o.closeTemplate + '</div>' +
7910				'<div class="jGrowl-header">' + o.header + '</div>' +
7911				'<div class="jGrowl-message">' + message + '</div></div>'
7912			).data("jGrowl", o).addClass(o.theme).children('div.jGrowl-close').bind("click.jGrowl", function() {
7913				$(this).parent().trigger('jGrowl.close');
7914			}).parent();
7915
7916
7917			/** Notification Actions **/
7918			$(notification).bind("mouseover.jGrowl", function() {
7919				$('div.jGrowl-notification', self.element).data("jGrowl.pause", true);
7920			}).bind("mouseout.jGrowl", function() {
7921				$('div.jGrowl-notification', self.element).data("jGrowl.pause", false);
7922			}).bind('jGrowl.beforeOpen', function() {
7923				if ( o.beforeOpen.apply( notification , [notification,message,o,self.element] ) != false ) {
7924					$(this).trigger('jGrowl.open');
7925				}
7926			}).bind('jGrowl.open', function() {
7927				if ( o.open.apply( notification , [notification,message,o,self.element] ) != false ) {
7928					if ( o.glue == 'after' ) {
7929						$('div.jGrowl-notification:last', self.element).after(notification);
7930					} else {
7931						$('div.jGrowl-notification:first', self.element).before(notification);
7932					}
7933					
7934					$(this).animate(o.animateOpen, o.openDuration, o.easing, function() {
7935						// Fixes some anti-aliasing issues with IE filters.
7936						if ($.browser.msie && (parseInt($(this).css('opacity'), 10) === 1 || parseInt($(this).css('opacity'), 10) === 0))
7937							this.style.removeAttribute('filter');
7938
7939						if ( $(this).data("jGrowl") != null ) // Happens when a notification is closing before it's open.
7940							$(this).data("jGrowl").created = new Date();
7941						
7942						$(this).trigger('jGrowl.afterOpen');
7943					});
7944				}
7945			}).bind('jGrowl.afterOpen', function() {
7946				o.afterOpen.apply( notification , [notification,message,o,self.element] );
7947			}).bind('jGrowl.beforeClose', function() {
7948				if ( o.beforeClose.apply( notification , [notification,message,o,self.element] ) != false )
7949					$(this).trigger('jGrowl.close');
7950			}).bind('jGrowl.close', function() {
7951				// Pause the notification, lest during the course of animation another close event gets called.
7952				$(this).data('jGrowl.pause', true);
7953				$(this).animate(o.animateClose, o.closeDuration, o.easing, function() {
7954					if ( $.isFunction(o.close) ) {
7955						if ( o.close.apply( notification , [notification,message,o,self.element] ) !== false )
7956							$(this).remove();
7957					} else {
7958						$(this).remove();
7959					}
7960				});
7961			}).trigger('jGrowl.beforeOpen');
7962		
7963			/** Optional Corners Plugin **/
7964			if ( o.corners != '' && $.fn.corner != undefined ) $(notification).corner( o.corners );
7965
7966			/** Add a Global Closer if more than one notification exists **/
7967			if ( $('div.jGrowl-notification:parent', self.element).size() > 1 && 
7968				 $('div.jGrowl-closer', self.element).size() == 0 && this.defaults.closer != false ) {
7969				$(this.defaults.closerTemplate).addClass('jGrowl-closer ' + this.defaults.themeState + ' ui-corner-all').addClass(this.defaults.theme)
7970					.appendTo(self.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing)
7971					.bind("click.jGrowl", function() {
7972						$(this).siblings().trigger("jGrowl.beforeClose");
7973
7974						if ( $.isFunction( self.defaults.closer ) ) {
7975							self.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] );
7976						}
7977					});
7978			};
7979		},
7980
7981		/** Update the jGrowl Container, removing old jGrowl notifications **/
7982		update:	 function() {
7983			try 
7984			{
7985				$(this.element).find('div.jGrowl-notification:parent').each( function() {
7986					if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined && 
7987						 ($(this).data("jGrowl").created.getTime() + parseInt($(this).data("jGrowl").life))  < (new Date()).getTime() && 
7988						 $(this).data("jGrowl").sticky != true && 
7989						 ($(this).data("jGrowl.pause") == undefined || $(this).data("jGrowl.pause") != true) ) {
7990	
7991						// Pause the notification, lest during the course of animation another close event gets called.
7992						$(this).trigger('jGrowl.beforeClose');
7993					}
7994				});
7995	
7996				if ( this.notifications.length > 0 && 
7997					 (this.defaults.pool == 0 || $(this.element).find('div.jGrowl-notification:parent').size() < this.defaults.pool) )
7998					this.render( this.notifications.shift() );
7999	
8000				if ( $(this.element).find('div.jGrowl-notification:parent').size() < 2 ) {
8001					$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
8002						$(this).remove();
8003					});
8004				}
8005			} catch (err)
8006			{
8007				nxs_js_log('jgrowl err;' + err);
8008			}
8009		},
8010
8011		/** Setup the jGrowl Notification Container **/
8012		startup:	function(e) {
8013			this.element = $(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');
8014			this.interval = setInterval( function() { 
8015				$(e).data('jGrowl.instance').update(); 
8016			}, parseInt(this.defaults.check));
8017			
8018			if ($.browser.msie && parseInt($.browser.version) < 7 && !window["XMLHttpRequest"]) {
8019				$(this.element).addClass('ie6');
8020			}
8021		},
8022
8023		/** Shutdown jGrowl, removing it and clearing the interval **/
8024		shutdown:   function() {
8025			$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();
8026			clearInterval( this.interval );
8027		},
8028		
8029		close: 	function() {
8030			$(this.element).find('div.jGrowl-notification').each(function(){
8031				$(this).trigger('jGrowl.beforeClose');
8032			});
8033		}
8034	});
8035	
8036	/** Reference the Defaults Object for compatibility with older versions of jGrowl **/
8037	$.jGrowl.defaults = $.fn.jGrowl.prototype.defaults;
8038
8039})(jQuery);
8040
8041/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
8042 * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradiu
8042s-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load-cssclassprefix:nxs!m!
8043 */
8044;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)}
8044,s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" nxs-m-"+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;
8044return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" nxs-m-js nxs-m-"+v.join(" nxs-m-"):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
8045
8046/*
8047 * Thickbox 3.1 - One Box To Rule Them All.
8048 * By Cody Lindley (http://www.codylindley.com)
8049 * Copyright (c) 2007 cody lindley
8050 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
8051 * 25 Aug 2014; Tuned to "nxsbox" by Nexus Themes to prevent plugins from messing up our CSS
8052*/
8053
8054function nxsbox_init(e){jQ_nxs(e).on("click",nxsbox_click)}function nxsbox_click(){var e=this.title||this.name||null;var t=this.href||this.alt;var n=this.rel||false;nxsbox_show(e,t,n);this.blur();return false}function nxsbox_show(e,t,n){try{if(typeof document.body.style.maxHeight==="undefined"){jQ_nxs("body","html").css({height:"100%",width:"100%"});jQ_nxs("html").css("overflow","hidden");if(document.getElementById("nxsbox_HideSelect")===null){jQ_nxs("body").append("<iframe id='nxsbox_HideSelect'>"+nxsboxL10n.noiframes+"</iframe><div id='nxsbox_overlay'></div><div id='nxsbox_window'></div>");jQ_nxs("#nxsbox_overlay").click(nxsbox_remove)}}else{if(document.getElementById("nxsbox_overlay")===null){jQ_nxs("body").append("<div id='nxsbox_overlay'></div><div id='nxsbox_window'></div>");jQ_nxs("#nxsbox_overlay").click(nxsbox_remove)}}if(nxsbox_detectMacXFF()){jQ_nxs("#nxsbox_overlay").addClass("nxsbox_overlayMacFFBGHack")}else{jQ_nxs("#nxsbox_overlay").addClass("nxsbox_overlayBG")}if(e===null){e=""}jQ_nxs("body").append("<div id='nxsbox_load'><img src='"+imgLoader.src+"' /></div>");jQ_nxs("#nxsbox_load").show();var r;if(t.indexOf("?")!==-1){r=t.substr(0,t.indexOf("?"))}else{r=t}var i=/\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;var s=r.toLowerCase().match(i);if(s==".jpg"||s==".jpeg"||s==".png"||s==".gif"||s==".bmp"){nxsbox_PrevCaption="";nxsbox_PrevURL="";nxsbox_PrevHTML="";nxsbox_NextCaption="";nxsbox_NextURL="";nxsbox_NextHTML="";nxsbox_imageCount="";nxsbox_FoundURL=false;if(n){nxsbox_TempArray=jQ_nxs("a[rel="+n+"]").get();for(nxsbox_Counter=0;nxsbox_Counter<nxsbox_TempArray.length&&nxsbox_NextHTML==="";nxsbox_Counter++){var o=nxsbox_TempArray[nxsbox_Counter].href.toLowerCase().match(i);if(!(nxsbox_TempArray[nxsbox_Counter].href==t)){if(nxsbox_FoundURL){nxsbox_NextCaption=nxsbox_TempArray[nxsbox_Counter].title;nxsbox_NextURL=nxsbox_TempArray[nxsbox_Counter].href;nxsbox_NextHTML="<span id='nxsbox_next'>��<a href='#'>"+nxsboxL10n.next+"</a></span>"}else{nxsbox_PrevCaption=nxsbox_TempArray[nxsbox_Counter].title;nxsbox_PrevURL=nxsbox_TempArray[nxsbox_Counter].href;nxsbox_PrevHTML="<span id='nxsbox_prev'>��<a href='#'>"+nxsboxL10n.prev+"</a></span>"}}else{nxsbox_FoundURL=true;nxsbox_imageCount=nxsboxL10n.image+" "+(nxsbox_Counter+1)+" "+nxsboxL10n.of+" "+nxsbox_TempArray.length}}}imgPreloader=new Image;imgPreloader.onload=function(){imgPreloader.onload=null;var r=nxsbox_getPageSize();var i=r[0]-150;var s=r[1]-150;var o=imgPreloader.width;var u=imgPreloader.height;if(o>i){u=u*(i/o);o=i;if(u>s){o=o*(s/u);u=s}}else if(u>s){o=o*(s/u);u=s;if(o>i){u=u*(i/o);o=i}}nxsbox_WIDTH=o+30;nxsbox_HEIGHT=u+60;jQ_nxs("#nxsbox_window").append("<a href='' id='nxsbox_ImageOff' title='"+nxsboxL10n.close+"'><img id='nxsbox_Image' src='"+t+"' width='"+o+"' height='"+u+"' alt='"+e+"'/></a>"+"<div id='nxsbox_caption'>"+e+"<div id='nxsbox_secondLine'>"+nxsbox_imageCount+nxsbox_PrevHTML+nxsbox_NextHTML+"</div></div><div id='nxsbox_closeWindow'><a href='#' id='nxsbox_closeWindowButton' title='"+nxsboxL10n.close+"'><img src='"+nxsbox_closeImage+"' /></a></div>");jQ_nxs("#nxsbox_closeWindowButton").click(nxsbox_remove);if(!(nxsbox_PrevHTML==="")){function a(){if(jQ_nxs(document).unbind("click",a)){jQ_nxs(document).unbind("click",a)}jQ_nxs("#nxsbox_window").remove();jQ_nxs("body").append("<div id='nxsbox_window'></div>");nxsbox_show(nxsbox_PrevCaption,nxsbox_PrevURL,n);return false}jQ_nxs("#nxsbox_prev").click(a)}if(!(nxsbox_NextHTML==="")){function f(){jQ_nxs("#nxsbox_window").remove();jQ_nxs("body").append("<div id='nxsbox_window'></div>");nxsbox_show(nxsbox_NextCaption,nxsbox_NextURL,n);return false}jQ_nxs("#nxsbox_next").click(f)}jQ_nxs(document).bind("keydown.nxsbox",function(e){e.stopImmediatePropagation();if(e.which==27){if(!jQ_nxs(document).triggerHandler("wp_CloseOnEscape",[{event:e,what:"nxsbox",cb:nxsbox_remove}]))nxsbox_remove()}else if(e.which==190){if(!(nxsbox_NextHTML=="")){jQ_nxs(document).unbind("nxsbox");f()}}else if(e.which==188){if(!(nxsbox_PrevHTML=="")){jQ_nxs(document).unbind("nxsbox");a()}}return false});nxsbox_position();jQ_nxs("#nxsbox_load").remove();jQ_nxs("#nxsbox_ImageOff").click(nxsbox_remove);jQ_nxs("#nxsbox_window").css({visibility:"visible"})};imgPreloader.src=t}else{var u=t.replace(/^[^\?]+\??/,"");var a=nxsbox_parseQuery(u);nxsbox_WIDTH=a["width"]*1+30||630;nxsbox_HEIGHT=a["height"]*1+40||440;ajaxContentW=nxsbox_WIDTH-30;ajaxContentH=nxsbox_HEIGHT-45;if(t.indexOf("nxsbox_iframe")!=-1){urlNoQuery=t.split("nxsbox_");jQ_nxs("#nxsbox_iframeContent").remove();if(a["modal"]!="true"){jQ_nxs("#nxsbox_window").append("<div id='nxsbox_title'><div id='nxsbox_ajaxWindowTitle'>"+e+"</div><div id='nxsbox_closeAjaxWindow'><a href='#' id='nxsbox_closeWindowButton' title='"+nxsboxL10n.close+"'><img src='"+nxsbox_closeImage+"' /></a></div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='nxsbox_iframeContent' name='nxsbox_iframeContent"+Math.round(Math.random()*1e3)+"' onload='nxsbox_showIframe()' style='width:"+(ajaxContentW+29)+"px;height:"+(ajaxContentH+17)+"px;' >"+nxsboxL10n.noiframes+"</iframe>")}else{jQ_nxs("#nxsbox_overlay").unbind();jQ_nxs("#nxsbox_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='nxsbox_iframeContent' name='nxsbox_iframeContent"+Math.round(Math.random()*1e3)+"' onload='nxsbox_showIframe()' style='width:"+(ajaxContentW+29)+"px;height:"+(ajaxContentH+17)+"px;'>"+nxsboxL10n.noiframes+"</iframe>")}}else{if(jQ_nxs("#nxsbox_window").css("visibility")!="visible"){if(a["modal"]!="true"){jQ_nxs("#nxsbox_window").append("<div id='nxsbox_title'><div id='nxsbox_ajaxWindowTitle'>"+e+"</div><div id='nxsbox_closeAjaxWindow'><a href='#' id='nxsbox_closeWindowButton'><img src='"+nxsbox_closeImage+"' /></a></div></div><div id='nxsbox_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>")}else{jQ_nxs("#nxsbox_overlay").unbind();jQ_nxs("#nxsbox_window").append("<div id='nxsbox_ajaxContent' class='nxsbox_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>")}}else{jQ_nxs("#nxsbox_ajaxContent")[0].style.width=ajaxContentW+"px";jQ_nxs("#nxsbox_ajaxContent")[0].style.height=ajaxContentH+"px";jQ_nxs("#nxsbox_ajaxContent")[0].scrollTop=0;jQ_nxs("#nxsbox_ajaxWindowTitle").html(e)}}jQ_nxs("#nxsbox_closeWindowButton").click(nxsbox_remove);if(t.indexOf("nxsbox_inline")!=-1){jQ_nxs("#nxsbox_ajaxContent").append(jQ_nxs("#"+a["inlineId"]).children());jQ_nxs("#nxsbox_window").bind("nxsbox_unload",function(){jQ_nxs("#"+a["inlineId"]).append(jQ_nxs("#nxsbox_ajaxContent").children())});nxsbox_position();jQ_nxs("#nxsbox_load").remove();jQ_nxs("#nxsbox_window").css({visibility:"visible"})}else if(t.indexOf("nxsbox_iframe")!=-1){nxsbox_position();if(jQuery.browser.safari){jQ_nxs("#nxsbox_load").remove();jQ_nxs("#nxsbox_window").css({visibility:"visible"})}}else{jQ_nxs("#nxsbox_ajaxContent").load(t+="&random="+(new Date).getTime(),function(){nxsbox_position();jQ_nxs("#nxsbox_load").remove();nxsbox_init("#nxsbox_ajaxContent a.nxsbox");jQ_nxs("#nxsbox_window").css({visibility:"visible"})})}}if(!a["modal"]){jQ_nxs(document).bind("keyup.nxsbox",function(e){if(e.which==27){e.stopImmediatePropagation();if(!jQ_nxs(document).triggerHandler("wp_CloseOnEscape",[{event:e,what:"nxsbox",cb:nxsbox_remove}]))nxsbox_remove();return false}})}}catch(f){}}function nxsbox_showIframe(){jQ_nxs("#nxsbox_load").remove();jQ_nxs("#nxsbox_window").css({visibility:"visible"})}function nxsbox_remove(){jQ_nxs("#nxsbox_imageOff").unbind("click");jQ_nxs("#nxsbox_closeWindowButton").unbind("click");jQ_nxs("#nxsbox_window").fadeOut("fast",function(){jQ_nxs("#nxsbox_window,#nxsbox_overlay,#nxsbox_HideSelect").trigger("nxsbox_unload").unbind().remove()});jQ_nxs("#nxsbox_load").remove();
8055		if(typeof document.body.style.maxHeight=="undefined")
8056		{
8057			jQ_nxs("body","html").css({height:"auto",width:"auto"});
8058			jQ_nxs("html").css("overflow","")
8059		}
8060		jQ_nxs(document).unbind(".nxsbox");
8061		return false
8062	}
8063	function nxsbox_position()
8064	{
8065		var e=typeof document.body.style.maxHeight==="undefined";
8066		jQ_nxs("#nxsbox_window").css({marginLeft:"-"+parseInt(nxsbox_WIDTH/2,10)+"px",width:nxsbox_WIDTH+"px"});if(!e){jQ_nxs("#nxsbox_window").css({marginTop:"-"+parseInt(nxsbox_HEIGHT/2,10)+"px"})}}function nxsbox_parseQuery(e){var t={};if(!e){return t}var n=e.split(/[;&]/);for(var r=0;r<n.length;r++){var i=n[r].split("=");if(!i||i.length!=2){continue}var s=unescape(i[0]);var o=unescape(i[1]);o=o.replace(/\+/g," ");t[s]=o}return t}function nxsbox_getPageSize(){var e=document.documentElement;var t=window.innerWidth||self.innerWidth||e&&e.clientWidth||document.body.clientWidth;
8066var n=window.innerHeight||self.innerHeight||e&&e.clientHeight||document.body.clientHeight;arrayPageSize=[t,n];return arrayPageSize}function nxsbox_detectMacXFF(){var e=navigator.userAgent.toLowerCase();if(e.indexOf("mac")!=-1&&e.indexOf("firefox")!=-1){return true}}if(typeof nxsbox_pathToImage!="string"){var nxsbox_pathToImage=nxsboxL10n.loadingAnimation}if(typeof nxsbox_closeImage!="string"){var nxsbox_closeImage=nxsboxL10n.closeImage}jQ_nxs(document).ready(function(){nxsbox_init("a.nxsbox, area.nxsbox, input.nxsbox");imgLoader=new Image;/*imgLoader.src=nxsbox_pathToImage*/})
8067
8068/* jQuery forms */
8069/*!
8070 * jQuery Form Plugin
8071 * version: 3.32.0-2013.04.09
8072 * @requires jQuery v1.5 or later
8073 * Copyright (c) 2013 M. Alsup
8074 * Examples and documentation at: http://malsup.com/jquery/form/
8075 * Project repository: https://github.com/malsup/form
8076 * Dual licensed under the MIT and GPL licenses.
8077 * https://github.com/malsup/form#copyright-and-license
8078 */
8079/*global ActiveXObject */
8080;(function($) {
8081"use strict";
8082
8083/*
8084    Usage Note:
8085    -----------
8086    Do not use both ajaxSubmit and ajaxForm on the same form.  These
8087    functions are mutually exclusive.  Use ajaxSubmit if you want
8088    to bind your own submit handler to the form.  For example,
8089
8090    $(document).ready(function() {
8091        $('#myForm').on('submit', function(e) {
8092            e.preventDefault(); // <-- important
8093            $(this).ajaxSubmit({
8094                target: '#output'
8095            });
8096        });
8097    });
8098
8099    Use ajaxForm when you want the plugin to manage all the event binding
8100    for you.  For example,
8101
8102    $(document).ready(function() {
8103        $('#myForm').ajaxForm({
8104            target: '#output'
8105        });
8106    });
8107
8108    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
8109    form does not have to exist when you invoke ajaxForm:
8110
8111    $('#myForm').ajaxForm({
8112        delegation: true,
8113        target: '#output'
8114    });
8115
8116    When using ajaxForm, the ajaxSubmit function will be invoked for you
8117    at the appropriate time.
8118*/
8119
8120/**
8121 * Feature detection
8122 */
8123var feature = {};
8124feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
8125feature.formdata = window.FormData !== undefined;
8126
8127var hasProp = !!$.fn.prop;
8128
8129// attr2 uses prop when it can but checks the return type for
8130// an expected string.  this accounts for the case where a form 
8131// contains inputs with names like "action" or "method"; in those
8132// cases "prop" returns the element
8133$.fn.attr2 = function() {
8134    if ( ! hasProp )
8135        return this.attr.apply(this, arguments);
8136    var val = this.prop.apply(this, arguments);
8137    if ( ( val && val.jquery ) || typeof val === 'string' )
8138        return val;
8139    return this.attr.apply(this, arguments);
8140};
8141
8142/**
8143 * ajaxSubmit() provides a mechanism for immediately submitting
8144 * an HTML form using AJAX.
8145 */
8146$.fn.ajaxSubmit = function(options) {
8147    /*jshint scripturl:true */
8148
8149    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
8150    if (!this.length) {
8151        log('ajaxSubmit: skipping submit process - no element selected');
8152        return this;
8153    }
8154
8155    var method, action, url, $form = this;
8156
8157    if (typeof options == 'function') {
8158        options = { success: options };
8159    }
8160
8161    method = this.attr2('method');
8162    action = this.attr2('action');
8163
8164    url = (typeof action === 'string') ? $.trim(action) : '';
8165    url = url || window.location.href || '';
8166    if (url) {
8167        // clean url (don't include hash vaue)
8168        url = (url.match(/^([^#]+)/)||[])[1];
8169    }
8170
8171    options = $.extend(true, {
8172        url:  url,
8173        success: $.ajaxSettings.success,
8174        type: method || 'GET',
8175        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
8176    }, options);
8177
8178    // hook for manipulating the form data before it is extracted;
8179    // convenient for use with rich editors like tinyMCE or FCKEditor
8180    var veto = {};
8181    this.trigger('form-pre-serialize', [this, options, veto]);
8182    if (veto.veto) {
8183        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
8184        return this;
8185    }
8186
8187    // provide opportunity to alter form data before it is serialized
8188    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
8189        log('ajaxSubmit: submit aborted via beforeSerialize callback');
8190        return this;
8191    }
8192
8193    var traditional = options.traditional;
8194    if ( traditional === undefined ) {
8195        traditional = $.ajaxSettings.traditional;
8196    }
8197
8198    var elements = [];
8199    var qx, a = this.formToArray(options.semantic, elements);
8200    if (options.data) {
8201        options.extraData = options.data;
8202        qx = $.param(options.data, traditional);
8203    }
8204
8205    // give pre-submit callback an opportunity to abort the submit
8206    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
8207        log('ajaxSubmit: submit aborted via beforeSubmit callback');
8208        return this;
8209    }
8210
8211    // fire vetoable 'validate' event
8212    this.trigger('form-submit-validate', [a, this, options, veto]);
8213    if (veto.veto) {
8214        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
8215        return this;
8216    }
8217
8218    var q = $.param(a, traditional);
8219    if (qx) {
8220        q = ( q ? (q + '&' + qx) : qx );
8221    }
8222    if (options.type.toUpperCase() == 'GET') {
8223        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
8224        options.data = null;  // data is null for 'get'
8225    }
8226    else {
8227        options.data = q; // data is the query string for 'post'
8228    }
8229
8230    var callbacks = [];
8231    if (options.resetForm) {
8232        callbacks.push(function() { $form.resetForm(); });
8233    }
8234    if (options.clearForm) {
8235        callbacks.push(function() { $form.clearForm(options.includeHidden); });
8236    }
8237
8238    // perform a load on the target only if dataType is not provided
8239    if (!options.dataType && options.target) {
8240        var oldSuccess = options.success || function(){};
8241        callbacks.push(function(data) {
8242            var fn = options.replaceTarget ? 'replaceWith' : 'html';
8243            $(options.target)[fn](data).each(oldSuccess, arguments);
8244        });
8245    }
8246    else if (options.success) {
8247        callbacks.push(options.success);
8248    }
8249
8250    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
8251        var context = options.context || this ;    // jQuery 1.4+ supports scope context
8252        for (var i=0, max=callbacks.length; i < max; i++) {
8253            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
8254        }
8255    };
8256
8257    // are there files to upload?
8258
8259    // [value] (issue #113), also see comment:
8260    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
8261    var fileInputs = $('input[type=file]:enabled[value!=""]', this);
8262
8263    var hasFileInputs = fileInputs.length > 0;
8264    var mp = 'multipart/form-data';
8265    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
8266
8267    var fileAPI = feature.fileapi && feature.formdata;
8268    log("fileAPI :" + fileAPI);
8269    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
8270
8271    var jqxhr;
8272
8273    // options.iframe allows user to force iframe mode
8274    // 06-NOV-09: now defaulting to iframe mode if file input is detected
8275    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
8276        // hack to fix Safari hang (thanks to Tim Molendijk for this)
8277        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
8278        if (options.closeKeepAlive) {
8279            $.get(options.closeKeepAlive, function() {
8280                jqxhr = fileUploadIframe(a);
8281            });
8282        }
8283        else {
8284            jqxhr = fileUploadIframe(a);
8285        }
8286    }
8287    else if ((hasFileInputs || multipart) && fileAPI) {
8288        jqxhr = fileUploadXhr(a);
8289    }
8290    else {
8291        jqxhr = $.ajax(options);
8292    }
8293
8294    $form.removeData('jqxhr').data('jqxhr', jqxhr);
8295
8296    // clear element array
8297    for (var k=0; k < elements.length; k++)
8298        elements[k] = null;
8299
8300    // fire 'notify' event
8301    this.trigger('form-submit-notify', [this, options]);
8302    return this;
8303
8304    // utility fn for deep serialization
8305    function deepSerialize(extraData){
8306        var serialized = $.param(extraData).split('&');
8307        var len = serialized.length;
8308        var result = [];
8309        var i, part;
8310        for (i=0; i < len; i++) {
8311            // #252; undo param space replacement
8312            serialized[i] = serialized[i].replace(/\+/g,' ');
8313            part = serialized[i].split('=');
8314            // #278; use array instead of object storage, favoring array serializations
8315            result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
8316        }
8317        return result;
8318    }
8319
8320     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
8321    function fileUploadXhr(a) {
8322        var formdata = new FormData();
8323
8324        for (var i=0; i < a.length; i++) {
8325            formdata.append(a[i].name, a[i].value);
8326        }
8327
8328        if (options.extraData) {
8329            var serializedData = deepSerialize(options.extraData);
8330            for (i=0; i < serializedData.length; i++)
8331                if (serializedData[i])
8332                    formdata.append(serializedData[i][0], serializedData[i][1]);
8333        }
8334
8335        options.data = null;
8336
8337        var s = $.extend(true, {}, $.ajaxSettings, options, {
8338            contentType: false,
8339            processData: false,
8340            cache: false,
8341            type: method || 'POST'
8342        });
8343
8344        if (options.uploadProgress) {
8345            // workaround because jqXHR does not expose upload property
8346            s.xhr = function() {
8347                var xhr = jQ_nxs.ajaxSettings.xhr();
8348                if (xhr.upload) {
8349                    xhr.upload.addEventListener('progress', function(event) {
8350                        var percent = 0;
8351                        var position = event.loaded || event.position; /*event.position is deprecated*/
8352                        var total = event.total;
8353                        if (event.lengthComputable) {
8354                            percent = Math.ceil(position / total * 100);
8355                        }
8356                        options.uploadProgress(event, position, total, percent);
8357                    }, false);
8358                }
8359                return xhr;
8360            };
8361        }
8362
8363        s.data = null;
8364            var beforeSend = s.beforeSend;
8365            s.beforeSend = function(xhr, o) {
8366                o.data = formdata;
8367                if(beforeSend)
8368                    beforeSend.call(this, xhr, o);
8369        };
8370        return $.ajax(s);
8371    }
8372
8373    // private function for handling file uploads (hat tip to YAHOO!)
8374    function fileUploadIframe(a) {
8375        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
8376        var deferred = $.Deferred();
8377
8378        if (a) {
8379            // ensure that every serialized input is still enabled
8380            for (i=0; i < elements.length; i++) {
8381                el = $(elements[i]);
8382                if ( hasProp )
8383                    el.prop('disabled', false);
8384                else
8385                    el.removeAttr('disabled');
8386            }
8387        }
8388
8389        s = $.extend(true, {}, $.ajaxSettings, options);
8390        s.context = s.context || s;
8391        id = 'jqFormIO' + (new Date().getTime());
8392        if (s.iframeTarget) {
8393            $io = $(s.iframeTarget);
8394            n = $io.attr2('name');
8395            if (!n)
8396                 $io.attr2('name', id);
8397            else
8398                id = n;
8399        }
8400        else {
8401            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
8402            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
8403        }
8404        io = $io[0];
8405
8406
8407        xhr = { // mock object
8408            aborted: 0,
8409            responseText: null,
8410            responseXML: null,
8411            status: 0,
8412            statusText: 'n/a',
8413            getAllResponseHeaders: function() {},
8414            getResponseHeader: function() {},
8415            setRequestHeader: function() {},
8416            abort: function(status) {
8417                var e = (status === 'timeout' ? 'timeout' : 'aborted');
8418                log('aborting upload... ' + e);
8419                this.aborted = 1;
8420
8421                try { // #214, #257
8422                    if (io.contentWindow.document.execCommand) {
8423                        io.contentWindow.document.execCommand('Stop');
8424                    }
8425                }
8426                catch(ignore) {}
8427
8428                $io.attr('src', s.iframeSrc); // abort op in progress
8429                xhr.error = e;
8430                if (s.error)
8431                    s.error.call(s.context, xhr, e, status);
8432                if (g)
8433                    $.event.trigger("ajaxError", [xhr, s, e]);
8434                if (s.complete)
8435                    s.complete.call(s.context, xhr, e);
8436            }
8437        };
8438
8439        g = s.global;
8440        // trigger ajax global events so that activity/block indicators work like normal
8441        if (g && 0 === $.active++) {
8442            $.event.trigger("ajaxStart");
8443        }
8444        if (g) {
8445            $.event.trigger("ajaxSend", [xhr, s]);
8446        }
8447
8448        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
8449            if (s.global) {
8450                $.active--;
8451            }
8452            deferred.reject();
8453            return deferred;
8454        }
8455        if (xhr.aborted) {
8456            deferred.reject();
8457            return deferred;
8458        }
8459
8460        // add submitting element to data if we know it
8461        sub = form.clk;
8462        if (sub) {
8463            n = sub.name;
8464            if (n && !sub.disabled) {
8465                s.extraData = s.extraData || {};
8466                s.extraData[n] = sub.value;
8467                if (sub.type == "image") {
8468                    s.extraData[n+'.x'] = form.clk_x;
8469                    s.extraData[n+'.y'] = form.clk_y;
8470                }
8471            }
8472        }
8473
8474        var CLIENT_TIMEOUT_ABORT = 1;
8475        var SERVER_ABORT = 2;
8476                
8477        function getDoc(frame) {
8478            /* it looks like contentWindow or contentDocument do not
8479             * carry the protocol property in ie8, when running under ssl
8480             * frame.document is the only valid response document, since
8481             * the protocol is know but not on the other two objects. strange?
8482             * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
8483             */
8484            
8485            var doc = null;
8486            
8487            // IE8 cascading access check
8488            try {
8489                if (frame.contentWindow) {
8490                    doc = frame.contentWindow.document;
8491                }
8492            } catch(err) {
8493                // IE8 access denied under ssl & missing protocol
8494                log('cannot get iframe.contentWindow document: ' + err);
8495            }
8496
8497            if (doc) { // successful getting content
8498                return doc;
8499            }
8500
8501            try { // simply checking may throw in ie8 under ssl or mismatched protocol
8502                doc = frame.contentDocument ? frame.contentDocument : frame.document;
8503            } catch(err) {
8504                // last attempt
8505                log('cannot get iframe.contentDocument: ' + err);
8506                doc = frame.document;
8507            }
8508            return doc;
8509        }
8510
8511        // Rails CSRF hack (thanks to Yvan Barthelemy)
8512        var csrf_token = $('meta[name=csrf-token]').attr('content');
8513        var csrf_param = $('meta[name=csrf-param]').attr('content');
8514        if (csrf_param && csrf_token) {
8515            s.extraData = s.extraData || {};
8516            s.extraData[csrf_param] = csrf_token;
8517        }
8518
8519        // take a breath so that pending repaints get some cpu time before the upload starts
8520        function doSubmit() {
8521            // make sure form attrs are set
8522            var t = $form.attr2('target'), a = $form.attr2('action');
8523
8524            // update form attrs in IE friendly way
8525            form.setAttribute('target',id);
8526            if (!method) {
8527                form.setAttribute('method', 'POST');
8528            }
8529            if (a != s.url) {
8530                form.setAttribute('action', s.url);
8531            }
8532
8533            // ie borks in some cases when setting encoding
8534            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
8535                $form.attr({
8536                    encoding: 'multipart/form-data',
8537                    enctype:  'multipart/form-data'
8538                });
8539            }
8540
8541            // support timout
8542            if (s.timeout) {
8543                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
8544            }
8545
8546            // look for server aborts
8547            function checkState() {
8548                try {
8549                    var state = getDoc(io).readyState;
8550                    log('state = ' + state);
8551                    if (state && state.toLowerCase() == 'uninitialized')
8552                        setTimeout(checkState,50);
8553                }
8554                catch(e) {
8555                    log('Server abort: ' , e, ' (', e.name, ')');
8556                    cb(SERVER_ABORT);
8557                    if (timeoutHandle)
8558                        clearTimeout(timeoutHandle);
8559                    timeoutHandle = undefined;
8560                }
8561            }
8562
8563            // add "extra" data to form if provided in options
8564            var extraInputs = [];
8565            try {
8566                if (s.extraData) {
8567                    for (var n in s.extraData) {
8568                        if (s.extraData.hasOwnProperty(n)) {
8569                           // if using the $.param format that allows for multiple values with the same name
8570                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
8571                               extraInputs.push(
8572                               $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
8573                                   .appendTo(form)[0]);
8574                           } else {
8575                               extraInputs.push(
8576                               $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
8577                                   .appendTo(form)[0]);
8578                           }
8579                        }
8580                    }
8581                }
8582
8583                if (!s.iframeTarget) {
8584                    // add iframe to doc and submit the form
8585                    $io.appendTo('body');
8586                    if (io.attachEvent)
8587                        io.attachEvent('onload', cb);
8588                    else
8589                        io.addEventListener('load', cb, false);
8590                }
8591                setTimeout(checkState,15);
8592
8593                try {
8594                    form.submit();
8595                } catch(err) {
8596                    // just in case form has element with name/id of 'submit'
8597                    var submitFn = document.createElement('form').submit;
8598                    submitFn.apply(form);
8599                }
8600            }
8601            finally {
8602                // reset attrs and remove "extra" input elements
8603                form.setAttribute('action',a);
8604                if(t) {
8605                    form.setAttribute('target', t);
8606                } else {
8607                    $form.removeAttr('target');
8608                }
8609                $(extraInputs).remove();
8610            }
8611        }
8612
8613        if (s.forceSync) {
8614            doSubmit();
8615        }
8616        else {
8617            setTimeout(doSubmit, 10); // this lets dom updates render
8618        }
8619
8620        var data, doc, domCheckCount = 50, callbackProcessed;
8621
8622        function cb(e) {
8623            if (xhr.aborted || callbackProcessed) {
8624                return;
8625            }
8626            
8627            doc = getDoc(io);
8628            if(!doc) {
8629                log('cannot access response document');
8630                e = SERVER_ABORT;
8631            }
8632            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
8633                xhr.abort('timeout');
8634                deferred.reject(xhr, 'timeout');
8635                return;
8636            }
8637            else if (e == SERVER_ABORT && xhr) {
8638                xhr.abort('server abort');
8639                deferred.reject(xhr, 'error', 'server abort');
8640                return;
8641            }
8642
8643            if (!doc || doc.location.href == s.iframeSrc) {
8644                // response not received yet
8645                if (!timedOut)
8646                    return;
8647            }
8648            if (io.detachEvent)
8649                io.detachEvent('onload', cb);
8650            else
8651                io.removeEventListener('load', cb, false);
8652
8653            var status = 'success', errMsg;
8654            try {
8655                if (timedOut) {
8656                    throw 'timeout';
8657                }
8658
8659                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
8660                log('isXml='+isXml);
8661                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
8662                    if (--domCheckCount) {
8663                        // in some browsers (Opera) the iframe DOM is not always traversable when
8664                        // the onload callback fires, so we loop a bit to accommodate
8665                        log('requeing onLoad callback, DOM not available');
8666                        setTimeout(cb, 250);
8667                        return;
8668                    }
8669                    // let this fall through because server response could be an empty document
8670                    //log('Could not access iframe DOM after mutiple tries.');
8671                    //throw 'DOMException: not available';
8672                }
8673
8674                //log('response detected');
8675                var docRoot = doc.body ? doc.body : doc.documentElement;
8676                xhr.responseText = docRoot ? docRoot.innerHTML : null;
8677                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
8678                if (isXml)
8679                    s.dataType = 'xml';
8680                xhr.getResponseHeader = function(header){
8681                    var headers = {'content-type': s.dataType};
8682                    return headers[header];
8683                };
8684                // support for XHR 'status' & 'statusText' emulation :
8685                if (docRoot) {
8686                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
8687                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
8688                }
8689
8690                var dt = (s.dataType || '').toLowerCase();
8691                var scr = /(json|script|text)/.test(dt);
8692                if (scr || s.textarea) {
8693                    // see if user embedded response in textarea
8694                    var ta = doc.getElementsByTagName('textarea')[0];
8695                    if (ta) {
8696                        xhr.responseText = ta.value;
8697                        // support for XHR 'status' & 'statusText' emulation :
8698                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
8699                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
8700                    }
8701                    else if (scr) {
8702                        // account for browsers injecting pre around json response
8703                        var pre = doc.getElementsByTagName('pre')[0];
8704                        var b = doc.getElementsByTagName('body')[0];
8705                        if (pre) {
8706                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
8707                        }
8708                        else if (b) {
8709                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
8710                        }
8711                    }
8712                }
8713                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
8714                    xhr.responseXML = toXml(xhr.responseText);
8715                }
8716
8717                try {
8718                    data = httpData(xhr, dt, s);
8719                }
8720                catch (err) {
8721                    status = 'parsererror';
8722                    xhr.error = errMsg = (err || status);
8723                }
8724            }
8725            catch (err) {
8726                log('error caught: ',err);
8727                status = 'error';
8728                xhr.error = errMsg = (err || status);
8729            }
8730
8731            if (xhr.aborted) {
8732                log('upload aborted');
8733                status = null;
8734            }
8735
8736            if (xhr.status) { // we've set xhr.status
8737                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
8738            }
8739
8740            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
8741            if (status === 'success') {
8742                if (s.success)
8743                    s.success.call(s.context, data, 'success', xhr);
8744                deferred.resolve(xhr.responseText, 'success', xhr);
8745                if (g)
8746                    $.event.trigger("ajaxSuccess", [xhr, s]);
8747            }
8748            else if (status) {
8749                if (errMsg === undefined)
8750                    errMsg = xhr.statusText;
8751                if (s.error)
8752                    s.error.call(s.context, xhr, status, errMsg);
8753                deferred.reject(xhr, 'error', errMsg);
8754                if (g)
8755                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
8756            }
8757
8758            if (g)
8759                $.event.trigger("ajaxComplete", [xhr, s]);
8760
8761            if (g && ! --$.active) {
8762                $.event.trigger("ajaxStop");
8763            }
8764
8765            if (s.complete)
8766                s.complete.call(s.context, xhr, status);
8767
8768            callbackProcessed = true;
8769            if (s.timeout)
8770                clearTimeout(timeoutHandle);
8771
8772            // clean up
8773            setTimeout(function() {
8774                if (!s.iframeTarget)
8775                    $io.remove();
8776                xhr.responseXML = null;
8777            }, 100);
8778        }
8779
8780        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
8781            if (window.ActiveXObject) {
8782                doc = new ActiveXObject('Microsoft.XMLDOM');
8783                doc.async = 'false';
8784                doc.loadXML(s);
8785            }
8786            else {
8787                doc = (new DOMParser()).parseFromString(s, 'text/xml');
8788            }
8789            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
8790        };
8791        var parseJSON = $.parseJSON || function(s) {
8792            /*jslint evil:true */
8793            return window['eval']('(' + s + ')');
8794        };
8795
8796        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
8797
8798            var ct = xhr.getResponseHeader('content-type') || '',
8799                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
8800                data = xml ? xhr.responseXML : xhr.responseText;
8801
8802            if (xml && data.documentElement.nodeName === 'parsererror') {
8803                if ($.error)
8804                    $.error('parsererror');
8805            }
8806            if (s && s.dataFilter) {
8807                data = s.dataFilter(data, type);
8808            }
8809            if (typeof data === 'string') {
8810                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
8811                    data = parseJSON(data);
8812                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
8813                    $.globalEval(data);
8814                }
8815            }
8816            return data;
8817        };
8818
8819        return deferred;
8820    }
8821};
8822
8823/**
8824 * ajaxForm() provides a mechanism for fully automating form submission.
8825 *
8826 * The advantages of using this method instead of ajaxSubmit() are:
8827 *
8828 * 1: This method will include coordinates for <input type="image" /> elements (if the element
8829 *    is used to submit the form).
8830 * 2. This method will include the submit element's name/value data (for the element that was
8831 *    used to submit the form).
8832 * 3. This method binds the submit() method to the form for you.
8833 *
8834 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
8835 * passes the options argument along after properly binding events for submit elements and
8836 * the form itself.
8837 */
8838$.fn.ajaxForm = function(options) {
8839    options = options || {};
8840    options.delegation = options.delegation && $.isFunction($.fn.on);
8841
8842    // in jQuery 1.3+ we can fix mistakes with the ready state
8843    if (!options.delegation && this.length === 0) {
8844        var o = { s: this.selector, c: this.context };
8845        if (!$.isReady && o.s) {
8846            log('DOM not ready, queuing ajaxForm');
8847            $(function() {
8848                $(o.s,o.c).ajaxForm(options);
8849            });
8850            return this;
8851        }
8852        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
8853        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
8854        return this;
8855    }
8856
8857    if ( options.delegation ) {
8858        $(document)
8859            .off('submit.form-plugin', this.selector, doAjaxSubmit)
8860            .off('click.form-plugin', this.selector, captureSubmittingElement)
8861            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
8862            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
8863        return this;
8864    }
8865
8866    return this.ajaxFormUnbind()
8867        .bind('submit.form-plugin', options, doAjaxSubmit)
8868        .bind('click.form-plugin', options, captureSubmittingElement);
8869};
8870
8871// private event handlers
8872function doAjaxSubmit(e) {
8873    /*jshint validthis:true */
8874    var options = e.data;
8875    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
8876        e.preventDefault();
8877        $(this).ajaxSubmit(options);
8878    }
8879}
8880
8881function captureSubmittingElement(e) {
8882    /*jshint validthis:true */
8883    var target = e.target;
8884    var $el = $(target);
8885    if (!($el.is("[type=submit],[type=image]"))) {
8886        // is this a child element of the submit el?  (ex: a span within a button)
8887        var t = $el.closest('[type=submit]');
8888        if (t.length === 0) {
8889            return;
8890        }
8891        target = t[0];
8892    }
8893    var form = this;
8894    form.clk = target;
8895    if (target.type == 'image') {
8896        if (e.offsetX !== undefined) {
8897            form.clk_x = e.offsetX;
8898            form.clk_y = e.offsetY;
8899        } else if (typeof $.fn.offset == 'function') {
8900            var offset = $el.offset();
8901            form.clk_x = e.pageX - offset.left;
8902            form.clk_y = e.pageY - offset.top;
8903        } else {
8904            form.clk_x = e.pageX - target.offsetLeft;
8905            form.clk_y = e.pageY - target.offsetTop;
8906        }
8907    }
8908    // clear form vars
8909    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
8910}
8911
8912
8913// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
8914$.fn.ajaxFormUnbind = function() {
8915    return this.unbind('submit.form-plugin click.form-plugin');
8916};
8917
8918/**
8919 * formToArray() gathers form element data into an array of objects that can
8920 * be passed to any of the following ajax functions: $.get, $.post, or load.
8921 * Each object in the array has both a 'name' and 'value' property.  An example of
8922 * an array for a simple login form might be:
8923 *
8924 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
8925 *
8926 * It is this array that is passed to pre-submit callback functions provided to the
8927 * ajaxSubmit() and ajaxForm() methods.
8928 */
8929$.fn.formToArray = function(semantic, elements) {
8930    var a = [];
8931    if (this.length === 0) {
8932        return a;
8933    }
8934
8935    var form = this[0];
8936    var els = semantic ? form.getElementsByTagName('*') : form.elements;
8937    if (!els) {
8938        return a;
8939    }
8940
8941    var i,j,n,v,el,max,jmax;
8942    for(i=0, max=els.length; i < max; i++) {
8943        el = els[i];
8944        n = el.name;
8945        if (!n || el.disabled) {
8946            continue;
8947        }
8948
8949        if (semantic && form.clk && el.type == "image") {
8950            // handle image inputs on the fly when semantic == true
8951            if(form.clk == el) {
8952                a.push({name: n, value: $(el).val(), type: el.type });
8953                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
8954            }
8955            continue;
8956        }
8957
8958        v = $.fieldValue(el, true);
8959        if (v && v.constructor == Array) {
8960            if (elements)
8961                elements.push(el);
8962            for(j=0, jmax=v.length; j < jmax; j++) {
8963                a.push({name: n, value: v[j]});
8964            }
8965        }
8966        else if (feature.fileapi && el.type == 'file') {
8967            if (elements)
8968                elements.push(el);
8969            var files = el.files;
8970            if (files.length) {
8971                for (j=0; j < files.length; j++) {
8972                    a.push({name: n, value: files[j], type: el.type});
8973                }
8974            }
8975            else {
8976                // #180
8977                a.push({ name: n, value: '', type: el.type });
8978            }
8979        }
8980        else if (v !== null && typeof v != 'undefined') {
8981            if (elements)
8982                elements.push(el);
8983            a.push({name: n, value: v, type: el.type, required: el.required});
8984        }
8985    }
8986
8987    if (!semantic && form.clk) {
8988        // input type=='image' are not found in elements array! handle it here
8989        var $input = $(form.clk), input = $input[0];
8990        n = input.name;
8991        if (n && !input.disabled && input.type == 'image') {
8992            a.push({name: n, value: $input.val()});
8993            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
8994        }
8995    }
8996    return a;
8997};
8998
8999/**
9000 * Serializes form data into a 'submittable' string. This method will return a string
9001 * in the format: name1=value1&amp;name2=value2
9002 */
9003$.fn.formSerialize = function(semantic) {
9004    //hand off to jQuery.param for proper encoding
9005    return $.param(this.formToArray(semantic));
9006};
9007
9008/**
9009 * Serializes all field elements in the jQuery object into a query string.
9010 * This method will return a string in the format: name1=value1&amp;name2=value2
9011 */
9012$.fn.fieldSerialize = function(successful) {
9013    var a = [];
9014    this.each(function() {
9015        var n = this.name;
9016        if (!n) {
9017            return;
9018        }
9019        var v = $.fieldValue(this, successful);
9020        if (v && v.constructor == Array) {
9021            for (var i=0,max=v.length; i < max; i++) {
9022                a.push({name: n, value: v[i]});
9023            }
9024        }
9025        else if (v !== null && typeof v != 'undefined') {
9026            a.push({name: this.name, value: v});
9027        }
9028    });
9029    //hand off to jQuery.param for proper encoding
9030    return $.param(a);
9031};
9032
9033/**
9034 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
9035 *
9036 *  <form><fieldset>
9037 *      <input name="A" type="text" />
9038 *      <input name="A" type="text" />
9039 *      <input name="B" type="checkbox" value="B1" />
9040 *      <input name="B" type="checkbox" value="B2"/>
9041 *      <input name="C" type="radio" value="C1" />
9042 *      <input name="C" type="radio" value="C2" />
9043 *  </fieldset></form>
9044 *
9045 *  var v = $('input[type=text]').fieldValue();
9046 *  // if no values are entered into the text inputs
9047 *  v == ['','']
9048 *  // if values entered into the text inputs are 'foo' and 'bar'
9049 *  v == ['foo','bar']
9050 *
9051 *  var v = $('input[type=checkbox]').fieldValue();
9052 *  // if neither checkbox is checked
9053 *  v === undefined
9054 *  // if both checkboxes are checked
9055 *  v == ['B1', 'B2']
9056 *
9057 *  var v = $('input[type=radio]').fieldValue();
9058 *  // if neither radio is checked
9059 *  v === undefined
9060 *  // if first radio is checked
9061 *  v == ['C1']
9062 *
9063 * The successful argument controls whether or not the field element must be 'successful'
9064 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
9065 * The default value of the successful argument is true.  If this value is false the value(s)
9066 * for each element is returned.
9067 *
9068 * Note: This method *always* returns an array.  If no valid value can be determined the
9069 *    array will be empty, otherwise it will contain one or more values.
9070 */
9071$.fn.fieldValue = function(successful) {
9072    for (var val=[], i=0, max=this.length; i < max; i++) {
9073        var el = this[i];
9074        var v = $.fieldValue(el, successful);
9075        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
9076            continue;
9077        }
9078        if (v.constructor == Array)
9079            $.merge(val, v);
9080        else
9081            val.push(v);
9082    }
9083    return val;
9084};
9085
9086/**
9087 * Returns the value of the field element.
9088 */
9089$.fieldValue = function(el, successful) {
9090    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
9091    if (successful === undefined) {
9092        successful = true;
9093    }
9094
9095    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
9096        (t == 'checkbox' || t == 'radio') && !el.checked ||
9097        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
9098        tag == 'select' && el.selectedIndex == -1)) {
9099            return null;
9100    }
9101
9102    if (tag == 'select') {
9103        var index = el.selectedIndex;
9104        if (index < 0) {
9105            return null;
9106        }
9107        var a = [], ops = el.options;
9108        var one = (t == 'select-one');
9109        var max = (one ? index+1 : ops.length);
9110        for(var i=(one ? index : 0); i < max; i++) {
9111            var op = ops[i];
9112            if (op.selected) {
9113                var v = op.value;
9114                if (!v) { // extra pain for IE...
9115                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
9116                }
9117                if (one) {
9118                    return v;
9119                }
9120                a.push(v);
9121            }
9122        }
9123        return a;
9124    }
9125    return $(el).val();
9126};
9127
9128/**
9129 * Clears the form data.  Takes the following actions on the form's input fields:
9130 *  - input text fields will have their 'value' property set to the empty string
9131 *  - select elements will have their 'selectedIndex' property set to -1
9132 *  - checkbox and radio inputs will have their 'checked' property set to false
9133 *  - inputs of type submit, button, reset, and hidden will *not* be effected
9134 *  - button elements will *not* be effected
9135 */
9136$.fn.clearForm = function(includeHidden) {
9137    return this.each(function() {
9138        $('input,select,textarea', this).clearFields(includeHidden);
9139    });
9140};
9141
9142/**
9143 * Clears the selected form elements.
9144 */
9145$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
9146    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
9147    return this.each(function() {
9148        var t = this.type, tag = this.tagName.toLowerCase();
9149        if (re.test(t) || tag == 'textarea') {
9150            this.value = '';
9151        }
9152        else if (t == 'checkbox' || t == 'radio') {
9153            this.checked = false;
9154        }
9155        else if (tag == 'select') {
9156            this.selectedIndex = -1;
9157        }
9158		else if (t == "file") {
9159			if (/MSIE/.test(navigator.userAgent)) {
9160				$(this).replaceWith($(this).clone(true));
9161			} else {
9162				$(this).val('');
9163			}
9164		}
9165        else if (includeHidden) {
9166            // includeHidden can be the value true, or it can be a selector string
9167            // indicating a special test; for example:
9168            //  $('#myForm').clearForm('.special:hidden')
9169            // the above would clean hidden inputs that have the class of 'special'
9170            if ( (includeHidden === true && /hidden/.test(t)) ||
9171                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
9172                this.value = '';
9173        }
9174    });
9175};
9176
9177/**
9178 * Resets the form data.  Causes all form elements to be reset to their original value.
9179 */
9180$.fn.resetForm = function() {
9181    return this.each(function() {
9182        // guard against an input with the name of 'reset'
9183        // note that IE reports the reset function as an 'object'
9184        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
9185            this.reset();
9186        }
9187    });
9188};
9189
9190/**
9191 * Enables or disables any matching elements.
9192 */
9193$.fn.enable = function(b) {
9194    if (b === undefined) {
9195        b = true;
9196    }
9197    return this.each(function() {
9198        this.disabled = !b;
9199    });
9200};
9201
9202/**
9203 * Checks/unchecks any matching checkboxes or radio buttons and
9204 * selects/deselects and matching option elements.
9205 */
9206$.fn.selected = function(select) {
9207    if (select === undefined) {
9208        select = true;
9209    }
9210    return this.each(function() {
9211        var t = this.type;
9212        if (t == 'checkbox' || t == 'radio') {
9213            this.checked = select;
9214        }
9215        else if (this.tagName.toLowerCase() == 'option') {
9216            var $sel = $(this).parent('select');
9217            if (select && $sel[0] && $sel[0].type == 'select-one') {
9218                // deselect all other options
9219                $sel.find('option').selected(false);
9220            }
9221            this.selected = select;
9222        }
9223    });
9224};
9225
9226// expose debug var
9227$.fn.ajaxSubmit.debug = false;
9228
9229// helper fn for console logging
9230function log() {
9231    if (!$.fn.ajaxSubmit.debug)
9232        return;
9233    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
9234    if (window.console && window.console.log) {
9235        window.console.log(msg);
9236    }
9237    else if (window.opera && window.opera.postError) {
9238        window.opera.postError(msg);
9239    }
9240}
9241
9242})(jQuery);
9243
9244var colorshaken = false;
9245
9246function nxs_js_colorshake()
9247{
9248	if (colorshaken)
9249	{
9250		return;
9251	}
9252	if (!nxs_js_userhasadminpermissions()) 
9253	{
9254		// only one color shake
9255		colorshaken = true;
9256	}
9257	
9258	if (!nxs_js_inwpbackend())
9259	{
9260		nxs_js_updatecss_themecss_actualrequest(true, true);
9261		nxs_js_updatecss_manualcss_actualrequest();
9262		
9263		jQ_nxs("#nxs-load-cover").hide();
9264	}
9265}
9266
9267// kudos to https://github.com/mikesherov/jquery-idletimer/
9268
9269/*
9270 * Copyright (c) 2009 Nicholas C. Zakas
9271 *
9272 * Permission is hereby granted, free of charge, to any person obtaining a copy
9273 * of this software and associated documentation files (the "Software"), to deal
9274 * in the Software without restriction, including without limitation the rights
9275 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9276 * copies of the Software, and to permit persons to whom the Software is
9277 * furnished to do so, subject to the following conditions:
9278 *
9279 * The above copyright notice and this permission notice shall be included in
9280 * all copies or substantial portions of the Software.
9281 *
9282 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9283 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9284 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9285 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9286 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9287 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
9288 * THE SOFTWARE.
9289 */
9290
9291( function( $ ) {
9292
9293$.idleTimer = function( firstParam, elem, opts ) {
9294
9295	// defaults that are to be stored as instance props on the elem
9296	opts = $.extend( {
9297		startImmediately: true,   //starts a timeout as soon as the timer is set up
9298		idle: false,              //indicates if the user is idle
9299		enabled: true,            //indicates if the idle timer is enabled
9300		timeout: 30000,           //the amount of time (ms) before the user is considered idle
9301		events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
9302	}, opts );
9303
9304
9305	elem = elem || document;
9306
9307	var jqElem = $( elem ),
9308		obj = jqElem.data("idleTimerObj") || {},
9309
9310		/* (intentionally not documented)
9311		 * Toggles the idle state and fires an appropriate event.
9312		 * @return {void}
9313		 */
9314		toggleIdleState = function( myelem ) {
9315
9316			// curse you, mozilla setTimeout lateness bug!
9317			if ( typeof myelem === "number" ) {
9318				myelem = undefined;
9319			}
9320
9321			var obj = $.data( myelem || elem, "idleTimerObj" );
9322
9323			//toggle the state
9324			obj.idle = !obj.idle;
9325
9326			// reset timeout
9327			var elapsed = ( +new Date() ) - obj.olddate;
9328			obj.olddate = +new Date();
9329
9330			// handle Chrome always triggering idle after js alert or comfirm popup
9331			if ( obj.idle && ( elapsed < opts.timeout ) ) {
9332				obj.idle = false;
9333				clearTimeout( $.idleTimer.tId );
9334				if ( opts.enabled ) {
9335					$.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
9336				}
9337				return;
9338			}
9339
9340			// create a custom event, but first, store the new state on the element
9341			// and then append that string to a namespace
9342			var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
9343			$( elem ).trigger( event );
9344		},
9345
9346		/**
9347		 * Stops the idle timer. This removes appropriate event handlers
9348		 * and cancels any pending timeouts.
9349		 * @return {void}
9350		 * @method stop
9351		 * @static
9352		 */
9353		stop = function( jqElem ) {
9354
9355			var obj = jqElem.data("idleTimerObj") || {};
9356
9357			//set to disabled
9358			obj.enabled = false;
9359
9360			//clear any pending timeouts
9361			clearTimeout( obj.tId );
9362
9363			//detach the event handlers
9364			jqElem.off(".idleTimer");
9365		};
9366
9367	obj.olddate = obj.olddate || +new Date();
9368
9369	if ( typeof firstParam === "number" ) {
9370		opts.timeout = firstParam;
9371	} else if ( firstParam === "destroy" ) {
9372		stop( jqElem );
9373		return this;
9374	} else if ( firstParam === "getElapsedTime" ) {
9375		return ( +new Date() ) - obj.olddate;
9376	}
9377
9378
9379	/* (intentionally not documented)
9380	 * Handles a user event indicating that the user isn't idle.
9381	 * @param {Event} event A DOM2-normalized event object.
9382	 * @return {void}
9383	 */
9384	jqElem.on( $.trim( ( opts.events + " " ).split(" ").join(".idleTimer ") ), function() {
9385		var obj = $.data( this, "idleTimerObj" );
9386
9387		//clear any existing timeout
9388		clearTimeout( obj.tId );
9389
9390		//if the idle timer is enabled
9391		if ( obj.enabled ){
9392			//if it's idle, that means the user is no longer idle
9393			if ( obj.idle ){
9394				toggleIdleState( this );
9395			}
9396
9397			//set a new timeout
9398			obj.tId = setTimeout( toggleIdleState, obj.timeout );
9399		}
9400	});
9401
9402	obj.idle = opts.idle;
9403	obj.enabled = opts.enabled;
9404	obj.timeout = opts.timeout;
9405
9406	//set a timeout to toggle state. May wish to omit this in some situations
9407	if ( opts.startImmediately ) {
9408		obj.tId = setTimeout( toggleIdleState, obj.timeout );
9409	}
9410
9411	// assume the user is active for the first x seconds.
9412	jqElem.data( "idleTimer", "active" );
9413
9414	// store our instance on the object
9415	jqElem.data( "idleTimerObj", obj );
9416};
9417
9418$.fn.idleTimer = function( firstParam, opts ) {
9419	// Allow omission of opts for backward compatibility
9420	if ( !opts ) {
9421		opts = {};
9422	}
9423
9424	if ( this[0] ){
9425		$.idleTimer( firstParam, this[0], opts );
9426	}
9427
9428	return this;
9429};
9430
9431})( jQuery );
9432
9433//nxs_js_popupsession_startnewcontext();
9434var nxsfrontendscriptloaded = true;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.