/soc/2015/igor.gajowiak/chatlog: 975639850201: Refactor Template...

Igor Gajowiak igor.gajowiak at gmail.com
Sat Jun 6 16:40:12 EDT 2015


Changeset: 9756398502012874940852ddb5bd78b89968969d
Author:	 Igor Gajowiak <igor.gajowiak at gmail.com>
Date:	 2015-06-06 22:39 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/975639850201

Description:

Refactor Template.html

diffstat:

 pidgin/themes/Contents/Resources/Incoming/Content.html |    1 -
 pidgin/themes/Template.html                            |  410 +++++-----------
 2 files changed, 125 insertions(+), 286 deletions(-)

diffs (truncated from 476 to 300 lines):

diff --git a/pidgin/themes/Contents/Resources/Incoming/Content.html b/pidgin/themes/Contents/Resources/Incoming/Content.html
--- a/pidgin/themes/Contents/Resources/Incoming/Content.html
+++ b/pidgin/themes/Contents/Resources/Incoming/Content.html
@@ -5,4 +5,3 @@
 	</span>
 	<span class="x-message">%message%</span>
 </div>
-<div id="insert"></div>
diff --git a/pidgin/themes/Template.html b/pidgin/themes/Template.html
--- a/pidgin/themes/Template.html
+++ b/pidgin/themes/Template.html
@@ -3,293 +3,152 @@
 <head>
 	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
 	<base href="%@">
+
 	<script type="text/javascript" defer="defer">
-		// NOTE:
-		// Any percent signs in this file must be escaped!
-		// Use two escape signs (%%) to display it, this is passed through a format call!
 
-		var PURPLE_IMAGE_STORE_PROTOCOL = 'purple-image:';
+		function DeferredInvoker(timeout, maxStackSize) {
+			var self = this;
+			this.timerID = 0;
+			this.stackSize = 0;
 
-		function appendHTML(html) {
-			var node = document.getElementById("Chat");
-			var range = document.createRange();
-			range.selectNode(node);
-			var documentFragment = range.createContextualFragment(html);
-			node.appendChild(documentFragment);
-		}
+			this.invokeDeferred = function (func) {
+				window.clearTimeout(self.timerID);
+				++self.stackSize;
 
-		// a coalesced HTML object buffers and outputs DOM objects en masse.
-		// saves A LOT of CSS recalculation time when loading many messages.
-		// (ex. a long twitter timeline)
-		function CoalescedHTML() {
-			var self = this;
-			this.fragment = document.createDocumentFragment();
-			this.timeoutID = 0;
-			this.coalesceRounds = 0;
-			this.isCoalescing = false;
-			this.isConsecutive = undefined;
-			this.shouldScroll = undefined;
-
-			var appendElement = function (elem) {
-				document.getElementById("Chat").appendChild(elem);
-			};
-
-			function outputHTML() {
-				var insert = document.getElementById("insert");
-				if(!!insert && self.isConsecutive) {
-					insert.parentNode.replaceChild(self.fragment, insert);
-				} else {
-					if(insert)
-						insert.parentNode.removeChild(insert);
-					// insert the documentFragment into the live DOM
-					appendElement(self.fragment);
-				}
-				alignChat(self.shouldScroll);
-
-				// reset state to empty/non-coalescing
-				self.shouldScroll = undefined;
-				self.isConsecutive = undefined;
-				self.isCoalescing = false;
-				self.coalesceRounds = 0;
-			}
-
-			// creates and returns a new documentFragment, containing all content nodes
-			// which can be inserted as a single node.
-			function createHTMLNode(html) {
-				var range = document.createRange();
-				range.selectNode(document.getElementById("Chat"));
-				return range.createContextualFragment(html);
-			}
-
-			// removes first insert node from the internal fragment.
-			function rmInsertNode() {
-				var insert = self.fragment.querySelector("#insert");
-				if(insert)
-					insert.parentNode.removeChild(insert);
-			}
-
-			function setShouldScroll(flag) {
-				if(flag && undefined === self.shouldScroll)
-					self.shouldScroll = flag;
-			}
-
-			// hook in a custom method to append new data
-			// to the chat.
-			this.setAppendElementMethod = function (func) {
-				if(typeof func === 'function')
-					appendElement = func;
-			}
-
-			// (re)start the coalescing timer.
-			//   we wait 25ms for a new message to come in.
-			//   If we get one, restart the timer and wait another 10ms.
-			//   If not, run outputHTML()
-			//  We do this a maximum of 400 times, for 10s max that can be spent
-			//  coalescing input, since this will block display.
-			this.coalesce = function() {
-				window.clearTimeout(self.timeoutID);
-				self.timeoutID = window.setTimeout(outputHTML, 25);
-				self.isCoalescing = true;
-				self.coalesceRounds += 1;
-				if(400 < self.coalesceRounds)
-					self.cancel();
-			}
-
-			// if we need to append content into an insertion div,
-			// we need to clear the buffer and cancel the timeout.
-			this.cancel = function() {
-				if(self.isCoalescing) {
-					window.clearTimeout(self.timeoutID);
-					outputHTML();
-				}
-			}
-
-
-			// coalased analogs to the global functions
-
-			this.append = function(html, shouldScroll) {
-				// if we started this fragment with a consecuative message,
-				// cancel and output before we continue
-				if(self.isConsecutive) {
-					self.cancel();
-				}
-				self.isConsecutive = false;
-				rmInsertNode();
-				var node = createHTMLNode(html);
-				self.fragment.appendChild(node);
-
-				node = null;
-
-				setShouldScroll(shouldScroll);
-				self.coalesce();
-			}
-
-			this.appendNext = function(html, shouldScroll) {
-				if(undefined === self.isConsecutive)
-					self.isConsecutive = true;
-				var node = createHTMLNode(html);
-				var insert = self.fragment.querySelector("#insert");
-				if(insert) {
-					insert.parentNode.replaceChild(node, insert);
-				} else {
-					self.fragment.appendChild(node);
-				}
-				node = null;
-				setShouldScroll(shouldScroll);
-				self.coalesce();
-			}
-
-			this.replaceLast = function (html, shouldScroll) {
-				rmInsertNode();
-				var node = createHTMLNode(html);
-				var lastMessage = self.fragment.lastChild;
-				lastMessage.parentNode.replaceChild(node, lastMessage);
-				node = null;
-				setShouldScroll(shouldScroll);
-			}
-		}
-		var coalescedHTML;
-
-		//Appending new content to the message view
-		function appendMessage(html) {
-			var shouldScroll;
-
-			// Only call nearBottom() if should scroll is undefined.
-			if(undefined === coalescedHTML.shouldScroll) {
-				shouldScroll = nearBottom();
-			} else {
-				shouldScroll = coalescedHTML.shouldScroll;
-			}
-			appendMessageNoScroll(html, shouldScroll);
-		}
-
-		function appendMessageNoScroll(html, shouldScroll) {
-			shouldScroll = shouldScroll || false;
-			// always try to coalesce new, non-griuped, messages
-			coalescedHTML.append(html, shouldScroll)
-		}
-
-		function appendNextMessage(html){
-			var shouldScroll;
-			if(undefined === coalescedHTML.shouldScroll) {
-				shouldScroll = nearBottom();
-			} else {
-				shouldScroll = coalescedHTML.shouldScroll;
-			}
-			appendNextMessageNoScroll(html, shouldScroll);
-		}
-
-		function appendNextMessageNoScroll(html, shouldScroll){
-			shouldScroll = shouldScroll || false;
-			// only group next messages if we're already coalescing input
-			coalescedHTML.appendNext(html, shouldScroll);
-		}
-
-		function replaceLastMessage(html){
-			var shouldScroll;
-			// only replace messages if we're already coalescing
-			if(coalescedHTML.isCoalescing){
-				if(undefined === coalescedHTML.shouldScroll) {
-					shouldScroll = nearBottom();
-				} else {
-					shouldScroll = coalescedHTML.shouldScroll;
-				}
-				coalescedHTML.replaceLast(html, shouldScroll);
-			} else {
-				shouldScroll = nearBottom();
-				//Retrieve the current insertion point, then remove it
-				//This requires that there have been an insertion point... is there a better way to retrieve the last element? -evands
-				var insert = document.getElementById("insert");
-				if(insert){
-					var parentNode = insert.parentNode;
-					parentNode.removeChild(insert);
-					var lastMessage = document.getElementById("Chat").lastChild;
-					document.getElementById("Chat").removeChild(lastMessage);
+				if (self.stackSize >= maxStackSize) {
+					func();
+					self.stackSize = 0;
+					return;
 				}
 
-				//Now append the message itself
-				appendHTML(html);
-
-				alignChat(shouldScroll);
+				self.timerID = window.setTimeout(
+					function () { func(); self.stackSize = 0; },
+					timeout);
 			}
 		}
 
-		var SCROLLMODE_UNKNOWN = 0;
-		var SCROLLMODE_WEBKIT1 = 1;
-		var SCROLLMODE_WEBKIT2 = 2;
-		var scroll_mode = SCROLLMODE_UNKNOWN;
+		function Scroller() {
+			var self = this;
+			var SCROLLMODE_UNKNOWN = 0;
+			var SCROLLMODE_WEBKIT1 = 1;
+			var SCROLLMODE_WEBKIT2 = 2;
 
-		function detectWebkitScrolling() {
-			if (scroll_mode != SCROLLMODE_UNKNOWN)
-				return scroll_mode;
-			if (document.body.scrollTop > 0)
-				scroll_mode = SCROLLMODE_WEBKIT1;
-			if (document.documentElement.scrollTop > 0)
-				scroll_mode = SCROLLMODE_WEBKIT2;
-			return scroll_mode;
-		}
-
-		var stickyscroll_just_scrolled = false;
-		var stickyscroll_just_scrolled_more = false;
-		var stickyscroll_to_bottom = true;
-		var stickyscroll_to_bottom_new = true;
-
-		function windowDidScroll(ev) {
-			if (stickyscroll_just_scrolled) {
-				stickyscroll_just_scrolled_more = true;
-				return;
+			function detectWebkitScrollingMode() {
+				if (document.body.scrollTop > 0)
+					scroll_mode = SCROLLMODE_WEBKIT1;
+				if (document.documentElement.scrollTop > 0)
+					scroll_mode = SCROLLMODE_WEBKIT2;
+				return SCROLLMODE_UNKNOWN;
 			}
 
-			stickyscroll_just_scrolled = true;
-			var update_to_bottom = function() {
-				stickyscroll_to_bottom = stickyscroll_to_bottom_new;
+			this.nearBottom = undefined;
+			this.scrollToBottom = undefined;
 
-				var mode = detectWebkitScrolling();
-				if (mode == SCROLLMODE_UNKNOWN || mode == SCROLLMODE_WEBKIT1) {
-					stickyscroll_to_bottom_new = ( document.body.scrollTop >=
+			// Initialize nearBottom and scrollToBottom
+			var mode = detectWebkitScrollingMode();
+			if (mode == SCROLLMODE_UNKNOWN || mode == SCROLLMODE_WEBKIT1) {
+				this.nearBottom = function () {
+					return ( document.body.scrollTop >=
 						( document.body.offsetHeight - (window.innerHeight + 20) ) );
-				} else { /* SCROLLMODE_WEBKIT2 */
-					stickyscroll_to_bottom_new = ( document.documentElement.scrollTop >=
+				}
+				this.scrollToBottom = function() {
+					document.body.scrollTop = document.body.offsetHeight;
+				};
+			}



More information about the Commits mailing list