javascript_library.naml

<macro name="javascript_library" requires="servlet">
	<n.uncache_for/>
	<n.javascript_response/>
	<n.compress.>
		<n.js_basic_nabble_functions/>
		<n.js_basic_embedding_code/>
		<n.js_basic_site_functions/>
		<n.js_date_functions/>
		<n.js_header_functions/>
		<n.js_delete_functions/>
		<n.js_topic_and_post_functions/>
		<n.js_search_functions/>
	</n.compress.>
</macro>

<macro name="javascript_library_path">
	<n.encode_url.>
		/template/NamlServlet.jtp?macro=javascript_library&v=<n.javascript_version/>
	</n.encode_url.>
</macro>

<macro name="js_basic_embedding_code">
	var host = "<n.get_request_header name="host"/>";
	<![CDATA[
	Nabble.embeddingUrl = null;
	Nabble.embedForumID = 0;
	Nabble.isEmbedded = false;
	Nabble.clientID = '';

	try {
		var info = Nabble.getParent().nabbleinfo.location.search.substring(6);
		info = decodeURIComponent(info);
		var pos = info.indexOf('&');
		Nabble.embedForumID = info.substring(0, pos);
		Nabble.clientID = info.substring(pos+5, info.indexOf('&cookies'));
		var hash = Nabble.getParent().nabbleinfo.location.hash.substring(1).split('|');
		Nabble.embeddingUrl = hash[0];
		Nabble.isEmbedded = true;
	} catch(err) {}

	Nabble.getClientID = function(c) {
		if (Nabble.getParent().nabbleinfo && !Nabble.getParent().nabbleinfo.cookiesEnabled)
			return (c?c:'&') + 'cid=' + Nabble.getParent().nabbleinfo.clientID;
		return '';
	};

	Nabble.embeddedTarget = function(defaultTarget) {
		return Nabble.isEmbedded? ' target="nabbleiframe" ' : ' target="' + defaultTarget + '" ';
	};

	Nabble.height = function() {
		if( typeof( window.innerHeight ) == 'number' ) {
			return window.innerHeight;
		} else if( document.documentElement && document.documentElement.clientHeight ) {
			return document.documentElement.clientHeight;
		} else if( document.body && document.body.clientHeight ) {
			return document.body.clientHeight;
		}
	};

	Nabble.knowsHeight = navigator.userAgent.toLowerCase().indexOf('safari') == -1;

	Nabble.canScroll = function() {
		try{
			return Nabble.getParent().nabbleinfo.canScroll();
		} catch(er) {}
		return true;
	};

	Nabble.hash = function() {
		var _hash = location.hash;
		if (Nabble.getParent().nabbleinfo && Nabble.getParent().nabbleinfo.hash) {
			if (!_hash)
				_hash = '#' + Nabble.getParent().nabbleinfo.hash;
			Nabble.getParent().nabbleinfo.hash = null;
		}
		return _hash;
	};

	Nabble.fixCookieClientID = function() {
		Nabble.fixLinkClientID();
		Nabble.fixFormClientID();
		Nabble.fixImageClientID();
	};

	Nabble.fixLinkClientID = function(p) {
		if (Nabble.getParent().nabbleinfo && !Nabble.getParent().nabbleinfo.cookiesEnabled) {
			var $links = p? $('a,li',p) : $('a,li');
			$links.each(function() {
				var href = $(this).attr('href');
				if (href) {
					var isAnotherDomain = href.indexOf('https://') == 0 || href.indexOf('http://') == 0 && href.indexOf('http://'+host) == -1;
					var isJs = href.indexOf('javascript:') == 0;
					var isMailto = href.indexOf('mailto:') == 0;
					if (isAnotherDomain || isJs || isMailto || href.charAt(0) == '#')
						return;
					$(this).attr('href', Nabble.appendClientID(href));
				}
			});
		}
	};

	Nabble.appendClientID = function(url) {
		var hash = '';
		var hashPos = url.indexOf('#');
		if (hashPos > 0) {
			hash = url.substring(hashPos);
			url = url.substring(0, hashPos);
		}
		var c = url.lastIndexOf('?') == -1? (url.indexOf('.jtp') > 0? '?':';') : '&';
		return url + c + 'cid=' + Nabble.getParent().nabbleinfo.clientID + hash;
	};

	Nabble.fixFormClientID = function() {
		if (Nabble.getParent().nabbleinfo && !Nabble.getParent().nabbleinfo.cookiesEnabled) {
			$('form').each(function() {
				var $this = $(this);
				if ($this.attr('rel') == 'external')
					return;
				if ($this.attr('enctype') == 'multipart/form-data') {
					var a = $this.attr('action');
					$this.attr('action', a + '?cid=' + Nabble.getParent().nabbleinfo.clientID);
				} else {
					var i = document.createElement("input");
					$(i).attr('type','hidden');
					$(i).attr('name','cid');
					$(i).attr('value',Nabble.getParent().nabbleinfo.clientID);
					$this.prepend($(i));
				}
			});
		}
	};

	Nabble.fixImageClientID = function() {
		if (Nabble.getParent().nabbleinfo && !Nabble.getParent().nabbleinfo.cookiesEnabled) {
			$('img[src*="/file/"]').each(function() {
				var src = $(this).attr('src');
				if (src && src.indexOf(';cid=') == -1) {
					$(this).attr('src', Nabble.appendClientID(src));
				}
			});
		}
	};

	Nabble.setTop = function(url) {
		if (Nabble.isEmbedded) Nabble.getParent().nabbleiframe.location=url;
		else top.location=url;
	};

	Nabble.getMyHeight = function() {
		try {
			return $(document.body).outerHeight();
		} catch(err) {}
		return 500;
	};

	Nabble.evalInTop = function(key, js) {
		var p = '';
		for (var i = 0; i < js.length; i++) {
			p += 'v=' + key[i] + '|' + encodeURIComponent(js[i]) + '&';
		}
		if (p.length > 0) {
			var url = "/util/SessionService$Attributes.jtp?action=set&" + p + "cid=" + Nabble.clientID + "&_=" + new Date().getTime();
			$.get(url, function() {
				Nabble.getParent().nabbleresize.location = "/util/Empty.jtp";
			});
		}
	};

	Nabble.quote = function(s) {
		return '"' + s.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/"/g,'\\"') + '"';
	};

	Nabble.heightLimit = 32767;
	Nabble.resizeCount = 0;

	Nabble.isValidHeight = function(height) {
		var isBadBrowser = $.browser.mozilla || $.browser.opera;
		var exceeded = height > Nabble.heightLimit && isBadBrowser;
		return !exceeded;
	};

	Nabble.resizeFrames = function(h, scroll) {
		if (Nabble.getParent().nabbleresize) {
			var height = h && typeof h == 'number'? h : Math.max(Nabble.getMyHeight() + 25, 600);
			var validHeight = Nabble.isValidHeight(height);
			height = validHeight? height : Nabble.heightLimit;
			var js = [], key = [];
			if (scroll) {
				js.push("Nabble.scroll(" + scroll + ");");
				key.push("scrolljs");
			}
			if (height != $(window).height() || Nabble.resizeCount++ == 0) {
				js.push("Nabble.resizeFrames(" + height + "," + Nabble.quote(document.title) + "," + validHeight + ");");
				key.push("resizejs");
			}
			if (js.length > 0)
				Nabble.evalInTop(key, js);
		}
	};

	Nabble.restartEmbedding = function(nodeId, baseUrl) {
		if (Nabble.getParent().nabbleresize) {
			var js = ['Nabble.restart(' + nodeId + ',"' + baseUrl + '");'];
			Nabble.evalInTop(['others'], js);
		}
	};

	$(document).ready(function(){
		if (Nabble.isEmbedded) {
			Nabble.resizeFrames('', 1);
			$(window).resize(Nabble.resizeFrames);
			$(window).load(function() {
			   Nabble.resizeFrames();
			});
		}
	});
	]]>
</macro>

<macro name="js_basic_site_functions" requires="servlet">
	<![CDATA[
	Nabble.online = function(id) {
		$('img.online'+id).show();
	};

	Nabble.openMsg = function(id) {
		return Nabble.getCookie(id) == null;
	};

	Nabble.toggleMsg = function(id, hide) {
		if (hide)
			Nabble.setPersistentCookie(id, 'closed');
		else
			Nabble.deleteCookie(id);
	};
	]]>
</macro>

<macro name="js_date_functions" requires="servlet">
	Nabble.months = ["<t>Jan</t>","<t>Feb</t>","<t>Mar</t>","<t>Apr</t>","<t>May</t>","<t>Jun</t>","<t>Jul</t>","<t>Aug</t>","<t>Sep</t>","<t>Oct</t>","<t>Nov</t>","<t>Dec</t>"];
	<![CDATA[
	Nabble.now = new Date();
	Nabble.fmt2 = function(i) { return i <= 9? '0'+i:i; };

	Nabble.isToday = function(date) {
		return date.toDateString() == this.now.toDateString();
	};

	Nabble.isThisYear = function(date) {
		return date.getYear() == this.now.getYear();
	};

	Nabble.dateFormatters = {
		us: new (function(){
			this.formatTime = function(date) {
				var hours = date.getHours();
				if (hours < 12) {
					var xm = "am";
					if (hours==0)
						hours = 12;
				} else {
					var xm = "pm";
					if (hours > 12)
						hours -= 12;
				}
				return hours + ":" + Nabble.fmt2(date.getMinutes()) + xm;
			};
			this.formatDateOnly = function(date) {
				return Nabble.months[date.getMonth()] + " " + Nabble.fmt2(date.getDate()) + ", " + date.getFullYear();
			};
			this.formatDateLong = function(date) {
				return this.formatDateOnly(date) + "; " + this.formatTime(date);
			};
			this.formatDateShort = function(date) {
				if( Nabble.isToday(date) )
					return this.formatTime(date);
				if( Nabble.isThisYear(date) )
					return Nabble.months[date.getMonth()] + " " + Nabble.fmt2(date.getDate());
				return this.formatDateOnly(date);
			};
		})()
		,
		euro: new (function(){
			this.formatTime = function(date) {
				return Nabble.fmt2(date.getHours()) + ":" + Nabble.fmt2(date.getMinutes());
			};
			this.formatDateOnly = function(date) {
				return Nabble.fmt2(date.getDate()) + "." + Nabble.months[date.getMonth()] + "." + date.getFullYear();
			};
			this.formatDateLong = function(date) {
				return this.formatTime(date) + ", " + this.formatDateOnly(date);
			};
			this.formatDateShort = function(date) {
				if( Nabble.isToday(date) )
					return this.formatTime(date);
				if( Nabble.isThisYear(date) )
					return Nabble.fmt2(date.getDate()) + "." + Nabble.months[date.getMonth()];
				return this.formatDateOnly(date);
			};
		})()
		,
		tech: new (function(){
			this.formatTime = function(date) {
				return Nabble.fmt2(date.getHours()) + ":" + Nabble.fmt2(date.getMinutes());
			};
			this.formatDateOnly = function(date) {
				return "" + date.getFullYear() + "-" + Nabble.fmt2(date.getMonth()+1) + "-" + Nabble.fmt2(date.getDate())
			};
			this.formatDateLong = function(date) {
				return this.formatDateOnly(date) + " " + this.formatTime(date);
			};
			this.formatDateShort = function(date) {
				if( Nabble.isToday(date) )
					return this.formatTime(date);
				if( Nabble.isThisYear(date) )
					return Nabble.fmt2(date.getMonth()+1) + "-" + Nabble.fmt2(date.getDate());
				return this.formatDateOnly(date);
			};
		})()
	};

	Nabble.getDateFmt = function() {
		var dateFmt = Nabble.getCookie("date_fmt");
		return dateFmt==null ? "us" : dateFmt;
	};

	Nabble.formatDateOnly = function(date) {
		return Nabble.dateFormatters[Nabble.getDateFmt()].formatDateOnly(date);
	};

	Nabble.formatTimeOnly = function(date) {
		return Nabble.dateFormatters[Nabble.getDateFmt()].formatTime(date);
	};

	Nabble.formatDateLong = function(date) {
		return Nabble.dateFormatters[Nabble.getDateFmt()].formatDateLong(date);
	};

	Nabble.formatDateShort = function(date) {
		var fmt = Nabble.dateFormatters[Nabble.getDateFmt()];
		return '<span title="' + fmt.formatDateLong(date) + '">'
			+ fmt.formatDateShort(date) + '</span>';
	};
	]]>
</macro>

<macro name="js_topic_and_post_functions" requires="servlet">
	<![CDATA[
	Nabble.messageTextWidth = function() {
		var maxWidth = Nabble.getCookie("max_width");
		if( maxWidth==null )
			return;
		document.write("<style type='text/css'>.nabble .message-text {max-width: "+maxWidth+";}</style>");
	};

	Nabble.setFontSize = function() {
		var fontSize = Nabble.getCookie("font_size");
		if (fontSize)
			document.write("<style type='text/css'>body, table .nabble {font-size: "+fontSize+";}</style>");
	};

	Nabble.fixTopicLinks = function() {
		if (Nabble.tview == "classic")
			return;
		var a = Nabble.get("nabble").getElementsByTagName("a");
		for (var i=0; i<a.length; i++) {
			var tag = a[i];
			var threadHref = tag.getAttribute("threaded_href");
			var listHref = tag.getAttribute("list_href");
			if (threadHref && Nabble.tview == "threaded") {
				tag.href = threadHref;
			} else if (listHref && Nabble.tview == "list") {
				tag.href = listHref;
			}
		}
	};

	Nabble.hideQuotes = function(context) {
		$('div.shrinkable-quote,blockquote',context).each(function() {
			var $this = $(this);
			if ($this.outerHeight() > 300) {
				$this.after("<div class='shrink-quote'><span></span> [<a href='javascript:void(0)'></a>]</div>");
			}
		});
		$('div.shrink-quote a', context)
			.click(function(){
				var $this = $(this);
				var v = parseInt($this.attr('collapsed') || 1) % 2;
				if (v == 0) {
					$this.prev().html( "&#171;&nbsp;" );
					$this.html( "hide part of quote" );
					var $text = $this.parent().prev();
					$text.css( 'height', 'auto' );
					$text.css( 'overflowY', 'auto' );
				} else {
					$this.prev().html( "..." );
					$this.html( "show rest of quote" );
					var $text = $this.parent().prev();
					$text.css('height', '300px');
					$text.css('overflowY', 'hidden' );
				}
				$this.attr('collapsed', v+1);
				Nabble.resizeFrames();
			})
			.click()
		;
	};
	]]>
</macro>

<macro name="js_header_functions" requires="servlet">
	var t_login = "<t>Login</t>";
	var t_register = "<t>Register</t>";
	var t_logout = "<t>Log out</t>";
	var t_my_posts = "<t>My posts</t>";
	var t_account_settings = "<t>Account settings</t>";
	var t_show_nabble_notice = "<t>Show Nabble notice</t>";
	var t_permalink = "<t>Permalink</t>";
	var t_refresh = "<t>Refresh</t>";
	var login_path = "<n.login_path/>";
	var logout_path = "<n.logout_path/>";
	var register_path = "<n.register_path/>";
	var user_profile_path = "<n.user_profile_path/>";
	<![CDATA[
	Nabble.userId = Nabble.getCookie("userId");
	var encodedUsername = Nabble.getCookie("username");
	if (encodedUsername) {
		Nabble.username = decodeURIComponent(encodedUsername)
			.replace(new RegExp('\\+','g'),' ');
	}

	if (!Nabble.userId) {
		Nabble.anonymousId = Nabble.getCookie("anonymousId");
		var encodedName = Nabble.getCookie("anonymousName");
		if (encodedName) {
			Nabble.anonymousName = decodeURIComponent(encodedName)
				.replace(new RegExp('\\+','g'),' ')
				.replace(new RegExp('<','g'),'&lt;')
				.replace(new RegExp('>','g'),'&gt;');
		}
	}

	Nabble.embedPermalink = function(url) {
		if (!Nabble.isEmbedded)
			return url;
		return url.replace(/(;|&)cid=(\d|\-)+/g, '').replace(/\?cid=(\d|\-)+(&)?/g, '?');
	};

	Nabble.getPermalink = function() {
		return Nabble.embedPermalink(
			Nabble.overridePermalink? Nabble.overridePermalink : Nabble.getParent().nabbleiframe.location.href);
	};

	Nabble.permalinkLabel = function() {
		if (!Nabble.isEmbedded)
			return '';
		var p = "<script>function openPermalink() { prompt('Copy this:', Nabble.getPermalink()); };</script>";
		p += "<a href='javascript: void openPermalink();'>"+t_permalink+"</a>&nbsp;&nbsp;";
		return p;
	};

	Nabble.refreshLabel = function() {
		if (Nabble.isEmbedded)
			return "<a href='javascript: location.reload(true);'>"+t_refresh+"</a>&nbsp;&nbsp;";
		return '';
	};

	Nabble.siteHeader = function() {
		var s = Nabble.refreshLabel();
		s += Nabble.permalinkLabel();
		if (!Nabble.userId) {
			var nextUrl = typeof loginNextUrl == 'undefined'? window.location.href : loginNextUrl;
			s += '<a href="'+login_path+'&nextUrl='+encodeURIComponent(nextUrl)+'">'+t_login+'</a>';
			s += '&nbsp;&nbsp;';
			s += '<a href="'+register_path+'&nextUrl='+encodeURIComponent(nextUrl)+'">'+t_register+'</a>';
			if (Nabble.anonymousId && Nabble.anonymousName) {
				s += '&nbsp;&nbsp;';
				s += '<a href="/template/NamlServlet.jtp?macro=user_nodes&user=' + Nabble.anonymousId + '~' + Nabble.anonymousName + '">';
				s += Nabble.anonymousName;
				s += '</a>';
			}
		} else
			s += '<span id="user-dd"></span>';
		return s;
	};

	Nabble.userDropdown = function() {
		var $t = $('#user-dd');
		if ($t.size() == 0)
			return;
		$t.empty();
		var dropdown = new NabbleDropdown('usrdd', Nabble.escapeHTML(Nabble.username));
		dropdown.add('myPosts','<a href="/template/NamlServlet.jtp?macro=user_nodes&user='+Nabble.userId + '">'+t_my_posts+'</a>');
		dropdown.add('personalSettings','<a href="'+user_profile_path+'">'+t_account_settings+'</a>');
		dropdown.add('adminNotice','<a href="javascript: void Nabble.showAdminNotice()">'+t_show_nabble_notice+'</a>','display:none');
		dropdown.add('logout','<a href="javascript: void Nabble.logout()">'+t_logout+'</a>');
		$t.html(dropdown.getHtml());
		dropdownInit('usrdd');
	};

	Nabble.addUserHeaderListener(function() {
		Nabble.userDropdown();
	});

	Nabble.showAdminNotice = function() {
		Nabble.deleteCookie('admin-notice');
		window.location.reload();
	};

	Nabble.logout = function() {
		window.location = '/template/NamlServlet.jtp?macro=logout_page' + Nabble.getClientID();
	};
	]]>
</macro>

<macro name="js_delete_functions" requires="servlet">
	var t_confirm_delete_post = "<t>Do you really want to delete this post?</t>";
	var t_confirm_delete_post_recursively = "<t>Do you really want to permanently delete this message and all replies?</t>";
	var t_caution_cannot_revert = "<t>CAUTION: this action cannot be reverted.</t>";
	<![CDATA[
	Nabble.deletePost = function(postId) {
		if (!confirm(t_confirm_delete_post))
			return;
		var newLocation = "/template/NamlServlet.jtp?macro=delete_post&node="+postId+Nabble.getClientID();
		Nabble.setTop(newLocation);
	};

	Nabble.deleteFromSite = function(nodeId) {
		if( !confirm(t_confirm_delete_post_recursively+"\n\n"+t_caution_cannot_revert) )
			return;
		var newLocation = "/template/NamlServlet.jtp?macro=delete_from_site&node="+nodeId+Nabble.getClientID();
		Nabble.setTop(newLocation);
	};
	]]>
</macro>

<macro name="js_search_functions" requires="servlet">
	<![CDATA[
	Nabble.highlightSearchTerms = function(searchterms, elem) {
		if (elem.childNodes && elem.childNodes.length > 0) {
			for (var i=0; i<elem.childNodes.length; i++) {
				this.highlightSearchTerms(searchterms, elem.childNodes[i]);
			}
		} else if (elem.nodeType) {
			if (elem.nodeType == document.TEXT_NODE || elem.nodeType == 3) {
				var txt = elem.nodeValue;
				var rgx = new RegExp("\\b("+searchterms+")\\w*\\b", "gi");
				var result;
				var start = 0;
				var newFragment = document.createElement("span");
				while ((result = rgx.exec(txt)) != null) {
					var end = result.index;
					var textNode = document.createTextNode(txt.slice(start, end));
					newFragment.appendChild(textNode);
					var hlNode = document.createElement("span");
					hlNode.className = "bold highlight search-highlight";
					hlNode.appendChild(document.createTextNode(result[0]));
					newFragment.appendChild(hlNode);
					start = end + result[0].length;
					Nabble.hasHighlightedTerms = true;
				}
				newFragment.appendChild(document.createTextNode(txt.slice(start)));
				elem.parentNode.replaceChild(newFragment, elem);
			}
		}
	};

	Nabble.getSearchTerms = function() {
		var searchterms = this.getCookie("searchterms");
		if (document.referrer) {
			var result = Nabble.getSearchTerms2(document.referrer);
			if (result!=null) {
				var query = decodeURIComponent(result);
				searchterms = query.replace(/\W+/g,"|").replace(/^\|/,"").replace(/\|$/,"");
				this.setCookie("searchterms", searchterms);
				Nabble.gquery = query.replace(/\+/g," ");
			}
		}
		return searchterms;
	};

	/* Logic from _uOrg() in urchin.js */
	Nabble.getSearchTerms2 = function(referrer) {
		if (typeof(_uOsr)=="undefined" || typeof(_uOkw)=="undefined")
			return null;
		var searchEngines = _uOsr;  /* from urchin */
		var searchQueries = _uOkw;  /* from urchin */
		var i;
		if (referrer==null || (i=referrer.indexOf("://")) < 0)
			return null;
		var h = referrer.substring(i+3);
		var p = h.indexOf("/");
		if (p > -1)
			h = h.substring(0,p);
		for (var j=0; j<searchEngines.length; j++) {
			var engine = searchEngines[j];
			var query = searchQueries[j];
			if (h.toLowerCase().indexOf(engine.toLowerCase()) > -1) {
				if ((i=referrer.indexOf("?"+query+"=")) > -1 || (i=referrer.indexOf("&"+query+"=")) > -1) {
					var k = referrer.substring(i+query.length+2,referrer.length);
					if ((i=k.indexOf("&")) > -1)
						k = k.substring(0,i);
					return k;
				}
			}
		}
		return null;
	};
	]]>
</macro>