FIRSTCLASS.layout.ThreadHandler = function(obj) { this._config = obj; if (!this._config.threading.coltype) { this._config.threading.coltype = FIRSTCLASS.layout.ThreadHandler.coltypes.STRING; } this.threads = []; }; FIRSTCLASS.layout.ThreadHandler.prototype.getThread = function(row) { var threadId = this.getThreadId(row); var thread = this.threads[threadId]; var isNew = false; if ( !thread ) { if (this._config.threadDraw) { thread = new this._config.threadDraw(row, this, this._config.uniqueid); } else { thread = new FIRSTCLASS.layout.Thread(row, this, this._config.uniqueid); } isNew = true; } this.threads[threadId] = thread; return {"thread":thread, "isNew": isNew}; }; FIRSTCLASS.layout.ThreadHandler.prototype.handleEvent = function(evt, fcevent) { var rv = false, thread, uri; if (evt.type == "click") { switch (fcevent.fcid) { case "uncollapser": thread = this.threads[fcevent.fcattrs]; if (thread) { thread.unsuppressReadItems(fcevent.clickexpandall); rv = true; } break; case "collapser": thread = this.threads[fcevent.fcattrs]; if (thread) { thread.suppressReadItems(); rv = true; } break; case "collapsed": thread = this.threads[fcevent.fcattrs]; if (thread) { uri = fcevent.target.getAttribute("uri"); if (uri) { thread.unsuppressReadItem(uri); rv = true; } } break; default: } } return rv; }; FIRSTCLASS.layout.ThreadHandler.prototype.removeThread = function(thread) { for (var i in this.threads) { if (this.threads[i] == thread) { this.threads.splice(i,1); return; } } }; FIRSTCLASS.layout.ThreadHandler.prototype.doreset = function() { delete this.threads; this.threads = []; }; FIRSTCLASS.layout.ThreadHandler.prototype.handleRow = function(row) { var tid = this.getThreadId(row); var t = this.getThread(row); t.handleRow(row); }; FIRSTCLASS.layout.ThreadHandler.types = { NONE: 0, COLUMN: 1, THREAD: 2, DATE: 3 }; FIRSTCLASS.layout.ThreadHandler.coltypes = { STRING: 0, NUMBER: 1, DATE: 2, FRIENDLYDATE: 3 }; FIRSTCLASS.layout.ThreadHandler.prototype.getThreadId = function(row) { if (this._config.threading.format != FIRSTCLASS.layout.ThreadHandler.types.NONE) { var tid, dodate = false; switch (this._config.threading.format) { case FIRSTCLASS.layout.ThreadHandler.types.THREAD: return row.threadid; case FIRSTCLASS.layout.ThreadHandler.types.COLUMN: tid = row[this._config.threading.column]; if (this._config.threading.coltype != FIRSTCLASS.layout.ThreadHandler.coltypes.FRIENDLYDATE) { return tid; } dodate = true; break; default: dodate = true; } if (dodate) { if (this._config.threading.format == FIRSTCLASS.layout.ThreadHandler.types.DATE) { tid = row.lastmod; } var curDate = new Date(); curDate.setTime(Date.parse(tid)); curDate.setHours(0); curDate.setMinutes(0); curDate.setSeconds(0); curDate.setMilliseconds(0); return curDate.toLocaleString(); } } else { return ""; } }; FIRSTCLASS.layout.ThreadHandler.prototype.getThreadByElement = function(threadEl) { var id = threadEl.id; var strip = this._config.uniqueid+"Thread"; var threadId = id.slice(strip.length, id.length); var thread = this.threads[threadId]; return thread; }; FIRSTCLASS.layout.ThreadHandler.prototype.getThreadConfig = function() { return this._config.threading; }; FIRSTCLASS.layout.ThreadHandler.prototype.getRowHandler = function() { return this._config.rowHandler; }; FIRSTCLASS.layout.Thread = function(row, thandler, uniqueid) { this.rowDefs = {}; this.rowmap = []; this.threadid = thandler.getThreadId(row); this.thandler = thandler; this.tconfig = thandler.getThreadConfig(); this.rowHandler = thandler.getRowHandler(); this.uniqueid = uniqueid; this.domElement = document.createElement("DIV"); var html = ["
"); this.domElement.innerHTML = html.join(""); this.domElement = this.domElement.firstChild; this.getNewThreadHeader(row); this.domElement.appendChild(this.threadHead); this.contentsElement = document.createElement("DIV"); html = ["
"); this.contentsElement.innerHTML = html.join(""); this.contentsElement = this.contentsElement.firstChild; if (this.tconfig && this.tconfig.collapseRead) { this.suppressReadItems(); // YAHOO.util.Dom.addClass(this.contentsElement, 'suppressreaditems'); } this.domElement.appendChild(this.contentsElement); this.initRow = row; this.currentSelection = -1; var that = this; this.getListViewContainer = function() { var container = YAHOO.util.Dom.getAncestorByClassName(that.domElement, "fcListViewContainer"); that.getListViewContainer = function() { return container; }; return container; }; this.getListViewContainerParent = function() { var container = that.getListViewContainer(); that.getListViewContainerParent = function() { return container.parentNode; }; return container.parentNode; }; }; FIRSTCLASS.layout.Thread.prototype.handleClick = function(element) { if (YAHOO.util.Dom.isAncestor(this.threadHead, element)) { if (this._config.toolbarHelper) { } else { this.rowHandler.onRowClick(this._headerRow, this.threadHead); } } }; FIRSTCLASS.layout.Thread.prototype.selectNext = function() { if (this.currentSelection >= 0 && this.currentSelection < this.rowmap.length-1) { this.currentSelection++; } else if (this.currentSelection == -1) { this.currentSelection = 0; } else { this.currentSelection = -1; return false; } return this.rowDefs[this.rowmap[this.currentSelection]].domElement; }; FIRSTCLASS.layout.Thread.prototype.selectPrevious = function() { if (this.currentSelection > 0 && this.currentSelection < this.rowmap.length) { this.currentSelection--; } else if (this.currentSelection == -1) { this.currentSelection = this.rowmap.length-1; } else { this.currentSelection = -1; return false; } return this.rowDefs[this.rowmap[this.currentSelection]].domElement; }; FIRSTCLASS.layout.Thread.prototype.changeSelection = function(row) { for (var i = 0; i < this.rowmap.length; i++) { if (this.rowmap[i] == row.uid) { this.currentSelection = i; break; } } var def = this.rowDefs[this.rowmap[this.currentSelection]]; if (!def.domElement) { if (!def.domElement) { def.domElement = this.rowHandler.createRow(def.row); def.domElement.id = def.row._listViewID; } YAHOO.util.Dom.removeClass(def.domElement, 'read'); def.recentlyread = true; YAHOO.util.Dom.addClass(def.domElement, 'recentlyread'); this.contentsElement.appendChild(def.domElement); } return def.domElement; }; FIRSTCLASS.layout.Thread.prototype.getDomElement = function() { return this.domElement; }; FIRSTCLASS.layout.Thread.prototype.getNewThreadHeader = function(row) { this.threadHead = document.createElement("div"); this.threadHead.innerHTML = "
"; this.threadHead = this.threadHead.firstChild; this.updateThreadHeader(row); }; FIRSTCLASS.layout.Thread.prototype.isQuestion = function(row) { return row.subject.indexOf("?") > 0 || (row.originalformid && row.originalformid == 143)|| (row.originalformid && row.originalformid == 21001); }; FIRSTCLASS.layout.Thread.prototype.updateUncollapser = function() { if (this.tconfig.collapseRead && this._uncollapser) { var that = this, def, recentlyread, i, row, ncontributors; var nread = 0; for (i in this.rowDefs) { def = this.rowDefs[i]; if (def.domElement) { recentlyread = def.recentlyread; if (def.row.uri != that._headerRow.uri && def.row.status.unread == 0 && !recentlyread) { nread++; } } else if (def.row.uri != that._headerRow.uri && def.row.status.unread == 0) { nread++; } } if (nread > 0) { var html = ""; if (this.tconfig.displayThreadContributors) { html += "
"; ncontributors = 0; for (i in this.rowmap) { def = this.rowDefs[this.rowmap[i]]; row = def.row; recentlyread = def.recentlyread; if (row.uri != that._headerRow.uri && row.status.unread == 0 && !recentlyread) { html += " "; } } html += ""; html += ((nread > 1) ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.read, [""+nread]) : FIRSTCLASS.locale.community.feed.read1); html += "
"; html += "" + ((nread > 1) ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.hide, [""+nread]) : FIRSTCLASS.locale.community.feed.hide1) + "
"; } else { var showsummary = nread > 1 ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.mread, [""+nread]) : FIRSTCLASS.locale.community.feed.mread1; // nread + " more read item"+ ((nread==1)?"":"s"); var hidesummary = nread > 1 ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.hide, [""+nread]) : FIRSTCLASS.locale.community.feed.hide1; // "hide " + nread + " read item"+ ((nread==1)?"":"s"); if (this.tconfig.summaryMode) { if (this.tconfig.summaryMode === "summary") { var likes = 0; var hiddenreplies = 0; var replies = 0; for (i in this.rowmap) { def = this.rowDefs[this.rowmap[i]]; row = def.row; recentlyread = def.recentlyread; if (row.uri != that._headerRow.uri) { if (row.status.unread == 0 && !recentlyread) { hiddenreplies++; } replies++; } } showsummary = ""; hidesummary = ""; if (likes > 0) { showsummary += likes + " people liked this"; if (hiddenreplies > 0) { showsummary += ", "; } hidesummary = showsummary; } if (hiddenreplies > 0) { showsummary += hiddenreplies > 1 ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.mreply, [""+hiddenreplies]) : FIRSTCLASS.locale.community.feed.mreply1;// hiddenreplies + " more repl" + ((hiddenreplies > 1)?"ies":"y"); hidesummary += replies > 1 ? FIRSTCLASS.locale.doSub(FIRSTCLASS.locale.community.feed.reply, [""+replies]) : FIRSTCLASS.locale.community.feed.reply1; // replies + " replies"; } } } html = "
" + showsummary +"
" + hidesummary +"
"; } this._uncollapser.innerHTML = html; } else { this._uncollapser.innerHTML = ""; } } }; FIRSTCLASS.layout.Thread.prototype.unsuppressReadItems = function(clickexpandall) { for (var i = 1; i < this.rowmap.length; i++) { var rcfg = this.rowDefs[this.rowmap[i]]; if (!rcfg.domElement) { rcfg.domElement = this.rowHandler.createRow(rcfg.row); rcfg.domElement.id = rcfg.row._listViewID; } this.contentsElement.appendChild(rcfg.domElement); if (clickexpandall && rcfg.row.status.unread == 0) { YAHOO.util.Dom.removeClass(rcfg.domElement, 'read'); rcfg.recentlyread = true; YAHOO.util.Dom.addClass(rcfg.domElement, 'recentlyread'); } } YAHOO.util.Dom.removeClass(this.domElement, 'suppressreaditems'); YAHOO.util.Dom.removeClass(this.contentsElement, "fcListViewHiddenThreadBody"); if (clickexpandall) { this.updateUncollapser(); } }; FIRSTCLASS.layout.Thread.prototype.unsuppressReadItem = function(uri) { var i, rcfg, insertBefore, inserted; for (i = 0; i < this.rowmap.length; i++) { rcfg = this.rowDefs[this.rowmap[i]]; if (rcfg.row.uri == uri) { if (!rcfg.domElement) { rcfg.domElement = this.rowHandler.createRow(rcfg.row); rcfg.domElement.id = rcfg.row._listViewID; } insertBefore = 0; for (i = 0; i < this.rowmap.length; i++) { if (this.tconfig.sortfunc(this.rowDefs[this.rowmap[i]].row, rcfg.row) < 0) { insertBefore = i;//this.rowmap[i]; break; } } inserted = false; for (i = insertBefore; i < this.rowmap.length; i++) { if (this.rowDefs[this.rowmap[i]].domElement && this.rowDefs[this.rowmap[i]].domElement.parentNode == this.contentsElement) { this.contentsElement.insertBefore(rcfg.domElement, this.rowDefs[this.rowmap[i]].domElement); inserted = true; break; } } if (!inserted) { this.contentsElement.appendChild(rcfg.domElement); } YAHOO.util.Dom.removeClass(rcfg.domElement, 'read'); rcfg.recentlyread = true; YAHOO.util.Dom.addClass(rcfg.domElement, 'recentlyread'); break; } } this.updateUncollapser(); }; FIRSTCLASS.layout.Thread.prototype.suppressReadItems = function() { for (var i = this.rowmap.length-1; i > 0; i--) { var rcfg = this.rowDefs[this.rowmap[i]]; var recentlyread = rcfg.recentlyread; if (rcfg.row.status.unread == 0 && !recentlyread) { this.contentsElement.removeChild(rcfg.domElement); } } YAHOO.util.Dom.addClass(this.domElement, 'suppressreaditems'); if (this.tconfig.hideThreadBody) { YAHOO.util.Dom.addClass(this.contentsElement, "fcListViewHiddenThreadBody"); } }; FIRSTCLASS.layout.Thread.prototype.updateThreadHeader = function(row, div) { var that = this, i, inserted, recentlyread, retval = 1, hdr = this.threadHead; if (this.tconfig.originRowIsHeader && div) { //YAHOO.util.Event.purgeElement(hdr, true); //var d = FIRSTCLASS.ui.Dom.clearElementChildren(hdr); if (hdr.firstChild) { recentlyread = YAHOO.util.Dom.hasClass(hdr.firstChild, 'recentlyread'); if (this.tconfig && this.tconfig.collapseRead && this._headerRow.status.unread == 0 && !recentlyread) { // don't insert FIRSTCLASS.ui.Dom.clearElementChildren(hdr); } else if (this.contentsElement.firstChild) { var insertBefore = 0; for (i = 0; i < this.rowmap.length; i++) { if (this.tconfig.sortfunc(this.rowDefs[this.rowmap[i]].row, this._headerRow) < 0) { insertBefore = i;//this.rowmap[i]; break; } } inserted = false; for (i = insertBefore; i < this.rowmap.length; i++) { if (this.rowDefs[this.rowmap[i]].domElement && this.rowDefs[this.rowmap[i]].domElement.parentNode == this.contentsElement) { this.contentsElement.insertBefore(hdr.firstChild, this.rowDefs[this.rowmap[i]].domElement); inserted = true; break; } } if (!inserted) { this.contentsElement.appendChild(hdr.firstChild); } // insertBefore = this.rowDefs[this.rowmap[insertBefore]]; // this.contentsElement.insertBefore(hdr.firstChild, this.contentsElement.firstChild); } else { this.contentsElement.appendChild(hdr.firstChild); } } hdr.appendChild(div); // FIRSTCLASS.ui.Dom.reparentNode(div,hdr); if (this.isQuestion(row)) { YAHOO.util.Dom.addClass(hdr.parentNode, "fcThreadQuestion"); } else { YAHOO.util.Dom.addClass(hdr.parentNode, "fcThreadTopic"); } retval = 2; } else if (!this.tconfig.originRowIsHeader) { var html = ["
"], curDate; if (this.tconfig.formatter) { html.push(this.tconfig.formatter(row)); } else { switch (this.tconfig.format) { case FIRSTCLASS.layout.ThreadHandler.types.THREAD: html.push(row.subject); break; case FIRSTCLASS.layout.ThreadHandler.types.COLUMN: if (this.tconfig.coltype && this.tconfig.coltype == FIRSTCLASS.layout.ThreadHandler.coltypes.FRIENDLYDATE) { curDate = new Date(); curDate.setTime(Date.parse(this.threadid)); html.push(FIRSTCLASS.util.Date.getFriendlyDateString(curDate)); } else { html.push(this.threadid); } break; case FIRSTCLASS.layout.ThreadHandler.types.NONE: break; //case FIRSTCLASS.layout.ThreadHandler.types.DATE: default: curDate = new Date(); curDate.setTime(row.lastmods*1000); curDate.setHours(0); curDate.setMinutes(0); curDate.setSeconds(0); html.push(FIRSTCLASS.util.Date.getFriendlyDateString(curDate)); //hdr.date = curDate; break; } } html.push("
"); hdr.innerHTML = html.join(""); } if (this.tconfig.collapseRead && ! this._uncollapser) { this._uncollapser = document.createElement("div"); YAHOO.util.Dom.addClass(this._uncollapser, 'uncollapser'); hdr.appendChild(this._uncollapser); } else if (this.tconfig.collapseRead && this._uncollapser) { hdr.appendChild(this._uncollapser); } this._headerRow = row; this.updateUncollapser(); //YAHOO.util.Event.purgeElement(hdr, false); /*YAHOO.util.Event.addListener(hdr, "click", function(evt) { if (that._headerRow && that.rowHandler.onRowClick) { that.rowHandler.onRowClick(that._headerRow, hdr.firstChild); } });*/ return retval; }; FIRSTCLASS.layout.Thread.prototype.removeRow = function(row) { var rcfg = this.rowDefs[row.uid], i; if (rcfg) { delete this.rowDefs[row.uid]; if (rcfg.domElement) { rcfg.domElement.parentNode.removeChild(rcfg.domElement); YAHOO.util.Dom.removeClass(rcfg.domElement, 'lastthreaditem'); } YAHOO.util.Dom.addClass(this.contentsElement.lastChild, 'lastthreaditem'); if (rcfg.domElement) { YAHOO.util.Event.purgeElement(rcfg.domElement, true); } for (i = 0; i < this.rowmap.length; i++) { if (this.rowmap[i] == row.uid) { this.rowmap.splice(i,1); if (i == 0) { if (this.rowmap.length == 0) { break;// delete the thread } else { rcfg = this.rowDefs[this.rowmap[0]]; if (!rcfg.domElement) { rcfg.domElement = this.rowHandler.createRow(rcfg.row); rcfg.domElement.id = rcfg.row._listViewID; } this.updateThreadHeader(rcfg.row,rcfg.domElement); } } if (i < this.currentSelection) { this.currentSelection--; } break; } } if (this.rowmap.length == 0) { return 2; // no more elements, remove this thread } return 1; // removed the row successfully } return 0; // row wasn't in the thread }; FIRSTCLASS.layout.Thread.prototype.handleRow = function(row, div, dontsort, isNew) { if (!this._sortRow) { this._sortRow = row; } var rv = 1; // ok if (row != this._headerRow) { YAHOO.util.Dom.removeClass(this.threadHead, "fcThreadNoReplies"); } var def = this.rowDefs[row.uid]; if (def) { if (!def.recentlyread && YAHOO.util.Dom.hasClass(def.domElement, 'recentlyread')) { def.recentlyread = true; } if (!this._headerRow || this._headerRow.uri == row.uri) { this.updateThreadHeader(row, div); } } else { // adding row var rcfg = {"row":row, "domElement":div}; this.rowDefs[row.uid] = rcfg; var insertBefore = false; var i = 0; if (!dontsort) { for (i = 0; i < this.rowmap.length; i++) { if (this.tconfig.sortfunc(this.rowDefs[this.rowmap[i]].row, row) > 0) { insertBefore = this.rowmap[i]; break; } } } else { i = this.rowmap.length; } if (this.tconfig.originRowIsHeader && i == 0) { this.rowmap.splice(i, 0, row.uid); if (this.threadHead) { this.updateThreadHeader(row, div); } } else if (insertBefore) { this.rowmap.splice(i, 0, row.uid); if (this.tconfig && this.tconfig.collapseRead && row.status.unread == 0) { // don't insert } else if (this.tconfig && this.tconfig.collapseRead && row.status.unread == 1) { this.contentsElement.appendChild(div); } else { this.contentsElement.insertBefore(div, this.rowDefs[insertBefore].domElement); } if (insertBefore <= this.currentSelection) { this.currentSelection++; } } else { this.rowmap[this.rowmap.length] = row.uid; if (this.tconfig && this.tconfig.collapseRead && row.status.unread == 0 && !isNew) { // don't insert } else { if (isNew) { YAHOO.util.Dom.removeClass(div, 'read'); rcfg.recentlyread = true; YAHOO.util.Dom.addClass(div, 'recentlyread'); } this.contentsElement.appendChild(div); } } YAHOO.util.Dom.removeClass(this.contentsElement.childNodes, 'lastthreaditem'); YAHOO.util.Dom.addClass(this.contentsElement.lastChild, 'lastthreaditem'); } this.updateUncollapser(); return rv; }; FIRSTCLASS.layout.Thread.prototype.handleFullThread = function(thread) { var row, r, rcfg, isheader, i; this._sortRow = thread[0]; if (this.tconfig.sortfunc) { thread.sort(this.tconfig.sortfunc); } for (i in thread) { row = thread[i]; rcfg = {"row":row}; isheader = false; if (thread.length == 1) { isheader = true; } else { isheader = (i == 0); } if (!isheader && this.tconfig && this.tconfig.collapseRead && row.status.unread == 0) { this.rowDefs[row.uid] = rcfg; this.rowmap[this.rowmap.length] = row.uid; // don't make the row unless it's the header } else { rcfg.domElement = this.rowHandler.createRow(row); rcfg.domElement.id = row._listViewID; this.handleRow(row, rcfg.domElement, true); } } /*if (this.tconfig.sortfunc) { var that = this; var sortfunc = function(row1, row2) { return -1*that.tconfig.sortfunc(that.rowDefs[row1].row, that.rowDefs[row2].row); }; this.rowmap.sort(sortfunc); }*/ this.updateUncollapser(); if (this.tconfig.blogThreading) { for (i in this.rowmap) { r = this.rowDefs[this.rowmap[i]].row; if (r.typedef.objtype == FIRSTCLASS.objTypes.odocument || r.typedef.objtype == FIRSTCLASS.objTypes.formdoc) { // not versioned, return the formdoc this._sortRow = r; break; } } } }; FIRSTCLASS.layout.Thread.prototype.sortRow = function() { if (this._sortRow) { return this._sortRow; } var row = this.rowDefs[this.rowmap[this.rowmap.length-1]].row, r, i; if (this.tconfig.originRowIsHeader) { r = this.rowDefs[this.rowmap[0]].row; if (r.typedef.objtype == FIRSTCLASS.objTypes.fcfile || r.typedef.objtype == FIRSTCLASS.objTypes.file || r.typedef.objtype == FIRSTCLASS.objTypes.odocument) { row = r; } } if (this.tconfig.blogThreading) { for (i in this.rowmap) { r = this.rowDefs[this.rowmap[i]].row; if (r.typedef.objtype == FIRSTCLASS.objTypes.odocument || r.typedef.objtype == FIRSTCLASS.objTypes.formdoc) { // not versioned, return the formdoc return r; } } } if (this.tconfig.originRowIsSort) { row = this.rowDefs[this.rowmap[0]].row; } if (!row) { row = this.initRow; } return row; }; YAHOO.register("fcThread", FIRSTCLASS.layout.Thread, {version: "1.0.0", build: "1"});