/** * Class Description * @namespace FIRSTCLASS.util * @module DataSource * @requires yahoo dom event connection logger json * @optional * @title Data Source */ /** * Constructor definition * @class DataSource * @constructor * @param {Object} config a configuration object for this DataSource * @param {string} config.containerBaseUrl (required) the url for the container to open * @param {number} config.requestGranularity (optional) the number of items to fetch by default */ FIRSTCLASS.util.DataSource = function(config) { if (!FIRSTCLASS.util.DataSource.instances) { FIRSTCLASS.util.DataSource.instances = 0; } this._instance = FIRSTCLASS.util.DataSource.instances++; /* FIRSTCLASS.util.DataSource._global.init();*/ this.writeLog({"1":"New DataSource containerBaseUrl: \"" + config.containerBaseUrl +"\"", "2": config}); var that = this; this._rowListeners = []; this._dataListeners = []; this._isFilled = false; this._isRefilling = false; this._isFetching = false; this._newDataInterval = null; this._config = { requestGranularity: 20, pollRequestGranularity: 5, temporaryPollRequestGranularity: 5, requestType:"GET", defaultRequestGranularity: 20, pluginStr: "Templates=JS&JSON=2", active: true, docbodies: false, messagebodies: false, serversort: "&Table=-0_0", itemrequest: true, pollInterval: 5000, fetchNewDelay: 100, fetchThreads: false, tackon: "" }; var i; for (i in config) { this._config[i] = config[i]; } if (config.isSameRow) { this.compareRows = config.isSameRow; } if (config.prePopulateData) { this._data = config.prePopulateData; this._config.dataPreLoaded = true; } if (config.useobjid) { this._config.useobjid = true; } if (config.paramStr) { this._config.paramStr = config.paramStr; } this._originalConfig = {}; FIRSTCLASS.lang.shallowCopyObjData(this._originalConfig, this._config); this._state = {currentDataIndex:1, requestGranularity: this._config.requestGranularity, hasMoreRows: true}; this._unreadState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity}; this._watchState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity, timeout:false, fetching: false}; this._objTypeState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity, hasMoreRows: true}; if (config.symbioticDataSource) { this._config.symbioticDataSource = config.symbioticDataSource; this._config.symbioticDataSource.dataSource.addDataListener({ onHeaderData:function(data, contents) { if (data === that._config.symbioticDataSource.key) { that.loadData(contents, that._state); } }, filter: function(dataname) { if (dataname === that._config.symbioticDataSource.key) { return true; } else { return false; } } }); } if (config.globalDataListener) { this._config.symbioticDataSource = FIRSTCLASS.util.DataSource; FIRSTCLASS.util.DataSource.registerGlobalDataListener({ onHeaderData:function(data, contents) { if (data === that._config.globalDataListener.key) { that.loadData(contents, that._watchState, false); that.parseContainerData(contents); } }, filter: function(dataname) { if (dataname === that._config.globalDataListener.key) { return true; } else { return false; } } }); } this.start(); }; FIRSTCLASS.util.DataSource.prototype.addConnReq = function(request, label) { var reqObj = { request: request, dsi: this._instance, ds: this }; if (label) { reqObj.label = label; } if (!FIRSTCLASS.util.DataSource.requests) { FIRSTCLASS.util.DataSource.requests = []; } FIRSTCLASS.util.DataSource.requests.push(reqObj); }; // remove a particular conn req FIRSTCLASS.util.DataSource.prototype.removeConnReq = function(request) { var reqIdx, req; for (reqIdx in FIRSTCLASS.util.DataSource.requests) { req = FIRSTCLASS.util.DataSource.requests[reqIdx]; if (req.request && req.request === request) { if (YAHOO.util.Connect.isCallInProgress(req.request)) { YAHOO.util.Connect.abort(req.request, null, false); this.writeLog("remove active request '" + req.label + "' from ds instance " + req.dsi + " in " + this.getContainerUrl()); } FIRSTCLASS.util.DataSource.requests.splice(reqIdx,1); break; } } }; // remove all this DS' conn reqs FIRSTCLASS.util.DataSource.prototype.killConnReqs = function() { var reqIdx, req; for (reqIdx = FIRSTCLASS.util.DataSource.requests.length - 1; reqIdx >= 0; reqIdx--) { req = FIRSTCLASS.util.DataSource.requests[reqIdx]; if (req.dsi === this._instance) { if (YAHOO.util.Connect.isCallInProgress(req.request)) { YAHOO.util.Connect.abort(req.request, null, false); this.writeLog("kill active request '" + req.label + "' from ds instance " + req.dsi + " in " + this.getContainerUrl()); } FIRSTCLASS.util.DataSource.requests.splice(reqIdx,1); } } }; FIRSTCLASS.util.DataSource.prototype.writeLog = function(message) { var obj = {}; if (typeof message == "object") { obj = message; } else { obj["1"] = message; } obj["10"] = this; obj.module = "FIRSTCLASS.util.DataSource"; FIRSTCLASS.session.debug.writeMessage(obj); }; FIRSTCLASS.util.DataSource.prototype.reset = function() { this.writeLog({"1": "resetting datasource!", "2": this._originalConfig}); this._originalConfig.filter = false; this.reconfigure(this._originalConfig); }; FIRSTCLASS.util.DataSource.prototype.reconfigure = function(cfg) { this.writeLog({"1": "reconfiguring datasource!", "2": cfg, "3": this._config}); this.deactivate(); this._state = {currentDataIndex:1, requestGranularity: this._config.requestGranularity, hasMoreRows: true}; this._unreadState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity}; this._watchState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity, timeout:false, fetching: false}; this._objTypeState = {currentDataIndex:0, requestGranularity: this._config.requestGranularity, hasMoreRows: true}; this._data = []; var i; for (i in cfg) { this._config[i] = cfg[i]; } /* if (typeof cfg.tackon == "string") { this._config.tackon = cfg.tackon; }*/ this.deactivate(); this._isFetching = false; this._config.symbioseeded = false; this.activate(); this.start(); }; /* class methods */ FIRSTCLASS.util.DataSource._global = { datalisteners: []/*, _initialized: false, init: function() { if (!FIRSTCLASS.util.DataSource._global._initialized) { FIRSTCLASS.util.DataSource.registerGlobalDataListener(FIRSTCLASS.util.DataSource._global.defaultListener); FIRSTCLASS.util.DataSource._global._initialized = true; } }, defaultListener: { onHeaderData: function(key, contents) { if (key == "session") { FIRSTCLASS.session.vkey = contents.vkey; FIRSTCLASS.session.updates.mailbox = contents.updates.mailbox; } }, filter: function(key) { switch(key) { case "session": return true; default: return false; } } }*/ }; FIRSTCLASS.util.DataSource.addListener = function(listener, array) { var i; for (i = 0; i < array.length; i++) { if (array[i] == listener) { return false; } } array[array.length] = listener; return true; }; FIRSTCLASS.util.DataSource.clearListeners = function(array) { while(array.length > 0) { array.pop(); } }; FIRSTCLASS.util.DataSource.removeListener = function(listener, array) { var i; for (i = 0; i < array.length; i++) { if (array[i] == listener) { array.splice(i,1); return; } } }; FIRSTCLASS.util.DataSource.registerGlobalDataListener = function(listener) { FIRSTCLASS.util.DataSource.addListener(listener, FIRSTCLASS.util.DataSource._global.datalisteners); }; FIRSTCLASS.util.DataSource.removeGlobalDataListener = function(listener) { FIRSTCLASS.util.DataSource.removeListener(listener, FIRSTCLASS.util.DataSource._global.datalisteners); }; FIRSTCLASS.util.DataSource.prototype.start = function() { var that = this; if (this._config.loadUnreadImmediate) { this.fetchUnreadRows(); } else if (this._config.reloadFullOnPoll) { this._config.autoLoad = true; this.refillTimeout = window.setTimeout(function() { that.reFill(); }, this._config.pollInterval); this.performFill(); } else if (this._config.loadFull) { this.performFill(); } else if (this._config.objTypePriority) { this.fetchRowsByObjType(this._config.objTypePriority, this._config.backVersionsImmediate); } else if (this._config.fetchThreadID) { this.fetchRowsByThread(this._config.fetchThreadID); } else if (!this._config.dataPreLoaded && (!this._config.symbioticDataSource || this._config.isDualDataSource)) { this.fetchRows(this._config.initialFillCallbacks); } }; FIRSTCLASS.util.DataSource.prototype.close = function() { if (!this._config.masterDS) { var baseUrl = this._config.containerBaseUrl; if (this._config.useobjid && this._data && this._data.objid) { baseUrl = FIRSTCLASS.session.baseURL + "__OBJID_" + this._data.objid + "/"; } if (baseUrl.indexOf("?") >= 0) { baseUrl += "&"; } else { baseUrl += "?"; } baseUrl += "Close=0"; var tmpConnManagerRequest = FIRSTCLASS.util.net.doAsyncGet(baseUrl); this.addConnReq(tmpConnManagerRequest, 'close'); } }; FIRSTCLASS.util.DataSource.prototype.open = function() { if (!this._config.masterDS && this._data) { this._data.objid = false; this.fetchRows(false, false, {startIndex:0,endIndex:1}); } }; FIRSTCLASS.util.DataSource.prototype.dispose = function() { this.writeLog("DataSource.dispose()"); this.deactivate(); this.clearRowListeners(); this.clearDataListeners(); this._data = null; window.clearTimeout(this.refillTimeout); }; /** * Create a "slave" dataSource from this one, set up to read data on its own, but to * perform list-level updates through the master. Config just overrides master config, * with watch and auto load functions disabled. * * If this ds is a slave itself, a new peer slave to the master DS is created. * * Live updates are handled by listening to the master DS. **/ FIRSTCLASS.util.DataSource.prototype.createSlave = function(config) { if (this._config.masterDS) { return this._config.masterDS.createSlave(config); } var newDS = null; var newCfg = {}; FIRSTCLASS.lang.deepCopyObjData(newCfg, this._config); FIRSTCLASS.lang.deepCopyObjData(newCfg, config); var newData = {}; if (this._data) { var rtmp = this._data.records; this._data.records = []; FIRSTCLASS.lang.deepCopyObjData(newData, this._data); this._data.records = rtmp; } newData.records = []; newCfg.autoLoad = false; newCfg.prePopulateData = newData; newCfg.watchForNew = false; newCfg.watchForTinkle = false; newCfg.masterDS = this; newCfg.dataPreLoaded = true; newDS = new FIRSTCLASS.util.DataSource(newCfg); newDS._rowQueue = []; newDS._rowQueueNewDel = false; if (newDS) { // listener functions newDS.onRow = function(row, isNewDelivery) { if (!this.filter || this.filter(row)) { var newRow = {}; FIRSTCLASS.lang.deepCopyObjData(newRow, row); newRow.mRow = row; // keep master-row pointer this._rowQueue.push(newRow); if (isNewDelivery) { this._rowQueueNewDel = true; } } }; newDS.onRowChanged = function(row) { if (!this.filter || this.filter(row)) { var newRow = {}; FIRSTCLASS.lang.deepCopyObjData(newRow, row); newRow.mRow = row; var rowDeltas = {}; rowDeltas.records = []; rowDeltas.records.push(newRow); this.loadData(rowDeltas, this._watchState); } }; newDS.onRowsChanged = function(rows) { var rowDeltas = { records: [] }; var row = {}, i; for (i in rows) { row = rows[i]; var newRow = {}; FIRSTCLASS.lang.deepCopyObjData(newRow, row); newRow.mRow = row; if (!this.filter || this.filter(row)) { rowDeltas.records.push(newRow); } } this.loadData(rowDeltas, this._watchState); }; newDS.onRowDeleted = function(row) { var i; if (this._data && this._data.records) { for (i = 0; i < this._data.records.length; i++) { if (this.compareRows(row, this._data.records[i])) { this._data.records[i].status.deleted = true; this.notifyRowDeleted(this._data.records[i]); } } } }; newDS.fillFinished = function() { if (this._rowQueue.length > 0) { var newData = {}; newData.records = this._rowQueue; this._rowQueue = []; this.loadData(newData, this._rowQueueNewDel ? this._watchState : this._objTypeState); this._rowQueueNewDel = false; } }; /*newDS.headerListener = { onHeaderData: function(key, fielddata) { var data = {}; data[key] = fielddata; newDS.parseContainerData(data, false) } };*/ this.addRowListener(newDS, true); //this.addDataListener(newDS.headerListener) } return newDS; }; /** * Create a "clone" dataSource from this one, that is identical in configuration * but has independent data. Passed-in config parameters augment or override the * source parameters. **/ FIRSTCLASS.util.DataSource.prototype.createCloneConfig = function(config) { var newCfg = {}; FIRSTCLASS.lang.deepCopyObjData(newCfg, this._config); FIRSTCLASS.lang.deepCopyObjData(newCfg, config); if (config.initialFillCallbacks) { newCfg.initialFillCallbacks = config.initialFillCallbacks; } return newCfg; }; FIRSTCLASS.util.DataSource.prototype.createClone = function(config) { var newCfg = this.createCloneConfig(config); var newDS = new FIRSTCLASS.util.DataSource(newCfg); return newDS; }; /** * Create a datasource that is watching the child */ FIRSTCLASS.util.DataSource.prototype.getChildDataSource = function(row, initialFillCallbacks) { var url = this.getItemUrl(row, true); var cfg = {containerBaseUrl: url, globalDataListener:false, initialFillCallbacks: initialFillCallbacks}; return this.createClone(cfg); }; /** * Public static variables definitions */ FIRSTCLASS.util.DataSource.objTypeToUrlParameter = function(objType) { switch (objType) { case FIRSTCLASS.objTypes.odocument: case FIRSTCLASS.objTypes.formdoc: return "Documents"; case FIRSTCLASS.objTypes.file: case FIRSTCLASS.objTypes.fcfile: return "Files"; case FIRSTCLASS.objTypes.message: return "Leaves"; case FIRSTCLASS.objTypes.confitem: return "Leaves"; default: return "Both"; } }; FIRSTCLASS.util.DataSource.prototype.deactivate = function() { this.writeLog("Deactivating " + this._config.name + (this._config.active?";was active":";was inactive"),1); this._config.active = false; this.suspendWatchFetching(); this.killConnReqs(); if (this._watchState.fetching) { this._watchState.connManagerRequest = null; this._watchState.fetching = false; } }; FIRSTCLASS.util.DataSource.prototype.activate = function(firstactivate) { this.writeLog("Activating " + this._config.name + (this._config.active?";was active":";was inactive"),1); if (!this._config.active) { this._watchState.fetching = false; this._config.active = true; var that = this; if (this._config.watchForNew && this._watchState.watching) { this._watchState.timeout = window.setTimeout(function() { that.fetchNewRows(); that._watchState.timeout = false; }, this._config.pollInterval); } if (this._config.watchForTinkle && this._watchState.watching) { if (!firstactivate) { this.fetchRows(false, false, false, true); } this._watchState.timeout = window.setTimeout(function() { that.watchForTinkle(false, true); that._watchState.timeout = false; }, this._config.pollInterval); } } }; FIRSTCLASS.util.DataSource.prototype.isActive = function() { return this._config.active; }; /** * generates an url to the data for the specified indices * * @Method DataSource.generateDataURL * @param {Object} config (required) an object that defines the request. * @param {int} config.startIndex (required) the first index to fetch * @param {int} config.endIndex (required) the last index to fetch * @return {string} the constructed url to the data */ FIRSTCLASS.util.DataSource.prototype.generateDataURL = function(config) { var date = new Date(), i; var pane = "0"; var param = "Both"; if (this._config.objtypefilter) { param = FIRSTCLASS.util.DataSource.objTypeToUrlParameter(config.objType); } var paramStr = ""; var paneStr = "";//"&Pane=0"; var sortStr = "&Table=-0_0"; var showStr = "&Show=12"; var doFile = false, doDoc = false; if (typeof config.backVersions != "undefined" && !config.backVersions) { showStr = ""; } if (config.baseUrl.indexOf("Search") >= 0 && !this._config.serversort) { sortStr = "&Table=0_0"; } else if (this._config.serversort === false) { sortStr = "&Table=0_0"; } else if (this._config.serversort) { sortStr = this._config.serversort; } if (config.objType) { if (typeof config.objType == "number") { param = FIRSTCLASS.util.DataSource.objTypeToUrlParameter(config.objType) + "=1"; if (config.objType == FIRSTCLASS.objTypes.odocument) { doDoc = true; } else if (config.objType == FIRSTCLASS.objTypes.file) { doFile = true; } } else if (typeof config.objType == "object") { param = ""; for (i = 0; i < config.objType.length; i++) { if (i !== 0) { param += "&"; } param += FIRSTCLASS.util.DataSource.objTypeToUrlParameter(config.objType[i]) + "=1"; if (config.objType[i] == FIRSTCLASS.objTypes.odocument) { doDoc = true; } else if (config.objType[i] == FIRSTCLASS.objTypes.file) { doFile = true; } } } } if (config.allunread) { param = "Leaves"; } var indexStr = "1"; if (config.objType) { paramStr = "&" + param + "&NS=1"; if (doDoc) { if (doFile) { paramStr += "&ColGFilter=$_0_(6)|25_(20503)"; } else { paramStr += "&ColGFilter=$_25_(20501)|0_(22)"; } } } else if (config.replyObjType) { paramStr = "&Leaves&Show=12&ColFilter=8091_(" + config.replyObjType + ")"; } else if (config.threadid) { var arr = config.threadid.split("-"); var threadid = arr[0] + "_" + arr[1]; paramStr = "&Leaves&Show=12&ColFilter=11_(" + threadid + ")"; } else if (config.loadFull) { paramStr = ""; /* if (config.notouch) { showStr = "&Show=12&Touch=1"; } else { showStr = "&Show=12&Touch=1"; }*/ showStr = "&Show=12&Touch=1"; } else if (typeof config.startIndex != "undefined" && typeof config.endIndex != "undefined") { var modifier = ""; if (this._config.fetchThreads) { modifier = "GR"; } if (config.endIndex > config.startIndex) { indexStr = modifier + config.startIndex + "-" + config.endIndex; } paramStr = "&" + param + "=" + indexStr; if (config.allunread) { paramStr += "&Filter=2" + sortStr; } else { paramStr += sortStr; } } else if (config.unread) { var lastupdate = 0; paramStr = "&Touch=1&Both&LU="; paneStr = "";//"&Pane=1"; if (false && this._watchState.lastrow) { paramStr = "&LastRow=" + this._watchState.lastrow.messageid + paramStr; } if (false && this._config.fetchThreads) { sortStr = "&Table=-3_9"; paramStr = "&Touch=1&Leaves&BFThreads&LU="; } else { sortStr = "&Table=-3_0"; } if (this._data) { lastupdate = this._data.lastupdate; } paramStr += lastupdate; if (config.uselastrowasanchor && !this._watchState.lastrow && this._data && this._data.records && this._data.records.length > 0) { this._watchState.lastrow = this._data.records[0]; } if (config.uselastrowasanchor && this._watchState.lastrow) { paramStr = "&Touch=1&Both&LMS=" + this._watchState.lastrow.lastmods; } else { paramStr += "&ColFilter=31_>(" + lastupdate + ")"; } paramStr += sortStr; pane = "1"; } else if (config.tinkle) { var lastupdate = 0; paramStr = "&Touch=1&LU="; paneStr = "";//"&Pane=1"; if (this._data) { lastupdate = this._data.lastupdate; } paramStr += lastupdate; paramStr += "&ColFilter=31_>(" + lastupdate + ")"; paramStr += sortStr; pane = "1"; } else if (config.uri) { paramStr = "&Leaves=1&ColFilter=13_(" + config.uri + ")"; } else if (config.name) { paramStr = "&Leaves=1&ColFilter=9_(" + config.name + ")"; } else if (config.cid) { if (typeof config.cid == "string" && config.cid.indexOf("CID") === 0) { config.cid = config.cid.slice(3); } paramStr = "&Leaves=1&ColFilter=20_(" + config.cid + ")"; } else if (this._config.itemrequest) { paramStr = "&" + param + "=" + indexStr + sortStr; } else { paramStr = sortStr; } if (config.nosymbiosis) { paramStr += "&NS=1"; } if (this._config.docbodies) { paramStr += "&DB=1"; } if (this._config.messagebodies) { paramStr += "&MB=1"; } var baseUrl = config.baseUrl; if (this._config.useobjid && this._data && this._data.objid) { baseUrl = FIRSTCLASS.session.baseURL + "__OBJID_" + this._data.objid + "/"; } if (baseUrl.indexOf("?") != -1) { baseUrl += "&"; } else { if (baseUrl.charAt(baseUrl.length - 1) != "/") { baseUrl = baseUrl + "/"; } baseUrl += "?"; } if (this._config.paramStr) { paramStr = this._config.paramStr + paramStr; } if (this._config.closeParam) { paramStr = paramStr + this._config.closeParam; } if (config.params) { paramStr = paramStr + config.params; } if (this._config.colfilter) { var colfilter = "&ColFilter="; var isfirst = 1; for (i in this._config.colfilter) { if (!isfirst) { colfilter += "|"; } isfirst = false; var filter = this._config.colfilter[i]; colfilter += filter.fieldid + "_(" + filter.val + ")"; } paramStr += colfilter; } /* paramStr += "&LM=" + FIRSTCLASS.session.updates.mailbox; */ if (baseUrl.indexOf("&Pulse") >= 0 || this._config.pluginStr.indexOf("&Pulse") >= 0 || this._config.tackon.indexOf("&Pulse") >= 0 || showStr.indexOf("&Pulse") >= 0 || paramStr.indexOf("&Pulse") >=0 || paneStr.indexOf("&Pulse") >= 0) { paramStr += "&LP=" + FIRSTCLASS.session.updates.pulse; } paramStr += "&Chats=1&LC=" + FIRSTCLASS.session.updates.chatfolder; paramStr += "&TS=" + date.getTime(); if (this._config.isRadForm) { var url = baseUrl + this._config.pluginStr; if (this._config.paramStr) { url += this._config.paramStr; } return url + this._config.tackon; } var panestr = "&Pane=" + pane; var url = baseUrl + this._config.pluginStr + showStr + paramStr + paneStr + this._config.tackon + panestr; if (config.forcenodeleted) { url = url.replace("&Show=12", ""); } return url; }; /** * adds a row listener to the datasource, filling it if we already have data * * @Method DataSource.addRowListener * @param {Object} listener * @param {function} listener.onRow(row) (optional) a function that's called when a new row is added to the DataSource * @param {function} listener.onRowChanged(row) (optional) a function that's called when a row is modified in the DataSource * @param {function} listener.filter (optional) a row filter that checks to see if a row is allowed to be sent to the listener's onRow and onRowChanged callbacks (returns true/false) */ FIRSTCLASS.util.DataSource.prototype.hasMoreListeners = function() { return (this._rowListeners.length > 0 || this._dataListeners.length > 0); }; FIRSTCLASS.util.DataSource.prototype.addRowListener = function(listener, suppressCatchup) { if (!FIRSTCLASS.util.DataSource.addListener(listener, this._rowListeners)) { return; } if (this._data && this._data.records && listener.onRow && !suppressCatchup) { var j; for (j = 0; j < this._data.records.length; j++) { if (!listener.filter || listener.filter(this._data.records[j])) { listener.onRow(this._data.records[j], this, true, j < this._data.records.length-1); } } } if (listener.fillFinished && !suppressCatchup) { listener.fillFinished(false, true); } }; FIRSTCLASS.util.DataSource.prototype.removeRowListener = function(listener) { FIRSTCLASS.util.DataSource.removeListener(listener, this._rowListeners); }; FIRSTCLASS.util.DataSource.prototype.clearRowListeners = function() { FIRSTCLASS.util.DataSource.clearListeners(this._rowListeners); }; /** * calls the rowListeners' onRow function on a new row * * @Method DataSource.notifyNewRow * @param {Object} row (required) the new row */ FIRSTCLASS.util.DataSource.prototype.notifyNewRow = function(row, isNewDelivery) { var i; for (i = 0; i < this._rowListeners.length; i++) { var listener = this._rowListeners[i]; if (typeof listener.onRow != "undefined" && (!listener.filter || listener.filter(row, isNewDelivery))) { listener.onRow(row, this, true, false); } if (listener.fillFinished) { listener.fillFinished(isNewDelivery); } } }; /** * calls the rowListeners' onRow function on a set of new rows * * @Method DataSource.notifyNewRows * @param {Array} rows (required) the new rows */ FIRSTCLASS.util.DataSource.prototype.notifyNewRows = function(rows, atEnd, isNewDelivery) { this.writeLog({funcname: "notifyNewRows", "1": {"nrows": rows.length, "nlisteners": this._rowListeners.length}, "4": {"rows": rows}}); var j, listener, threads, i, fRows; for (i = 0; i < this._rowListeners.length; i++) { listener = this._rowListeners[i]; if (typeof listener.onThread != "undefined") { threads = []; for (j = 0; j < rows.length; j++) { if (!listener.filter || listener.filter(rows[j], isNewDelivery)) { if (threads[rows[j].threadid]) { threads[rows[j].threadid].push(rows[j]); } else { threads[rows[j].threadid] = [rows[j]]; } } } for (j in threads) { this.writeLog({funcname: "notifyNewRows", "2":"Notifying thread: " + j, "3":{"thread": threads[j]}}); var allowed = true; var row, k; if (this._config.filter) { switch(this._config.filter) { case "MyPeople": allowed = false; for (k in threads[j]) { row = threads[j][k]; if (FIRSTCLASS.util.BuddyList.isBuddy(row.creatorcid) || row.creatorcid == FIRSTCLASS.session.user.cid) { allowed = true; break; } } break; case "Me": allowed = false; for (k in threads[j]) { row = threads[j][k]; if (row.creatorcid == FIRSTCLASS.session.user.cid) { allowed = true; break; } } break; default: } } if (allowed) { listener.onThread(threads[j], isNewDelivery); } } } else if (typeof listener.onRows !== "undefined") { fRows = []; for (j = 0; j < rows.length; j++) { if (!listener.filter || listener.filter(rows[(atEnd) ? j : rows.length - j - 1], isNewDelivery)) { fRows.push(rows[(atEnd) ? j : rows.length - j - 1]); this.writeLog({funcname: "notifyNewRows", "2": "notifying rows: " + fRows[fRows.length-1].messageid, "3":{"rows": fRows[fRows.length-1]}}); } } if (fRows.length > 0) { listener.onRows(fRows, this, atEnd, rows.length > 10); } } else if (typeof listener.onRow != "undefined") { for (j = 0; j < rows.length; j++) { if (!listener.filter || listener.filter(rows[(atEnd) ? j : rows.length - j - 1], isNewDelivery)) { this.writeLog({funcname: "notifyNewRows", "2":"notifying row", "3":{"row": rows[(atEnd) ? j : rows.length - j - 1]}}); listener.onRow(rows[(atEnd) ? j : rows.length - j - 1], this, atEnd, rows.length > 10); } } } if (listener.fillFinished) { listener.fillFinished(isNewDelivery); } this.writeLog("notifyNewRows finished"); } }; FIRSTCLASS.util.DataSource.prototype.fillPage = function(listener, pagenum, nperpage, cb) { if (this._data) { var startindex = (pagenum-1)*nperpage; var rowcount = 0, i; for (i = 0; i < this._data.records.length && rowcount < pagenum*nperpage; i++) { if (!listener.filter || listener.filter(this._data.records[i],false)) { if (rowcount >= startindex) { listener.onRow(this._data.records[i], this, true); } rowcount++; } } if (listener.fillFinished) { listener.fillFinished(); } if (cb && cb.completed) { cb.completed(); } } }; /** * calls the rowListeners' onRowChanged function on a modified row * * @Method DataSource.notifyRowChanged * @param {Array} rows (required) the modified row */ FIRSTCLASS.util.DataSource.prototype.notifyRowChanged = function(row, oldrow) { this.writeLog("notifyRowChanged called with: " + row.messageid); this.writeLog("notifyRowChanged called with: " + this._rowListeners.length + " listeners"); var i; for (i = 0; i < this._rowListeners.length; i++) { var listener = this._rowListeners[i]; if (listener.onRowChanged && (!listener.filter || listener.filter(row))) { this.writeLog("notifyRowChanged notifying listener: " + i); listener.onRowChanged(row, this, oldrow); } if (listener.fillFinished) { listener.fillFinished(); } this.writeLog("notifyRowChanged finished!"); } }; FIRSTCLASS.util.DataSource.prototype.notifyRowsChanged = function(rows, oldrows) { this.writeLog("notifyRowsChanged called with: " + rows.length + " rows"); this.writeLog("notifyRowsChanged called with: " + this._rowListeners.length); var i, j, listener; for (i = 0; i < this._rowListeners.length; i++) { listener = this._rowListeners[i]; if (listener.onRowsChanged) { var allowedrows = []; if (listener.filter) { for (j in rows) { if (listener.filter(rows[j])) { this.writeLog({"2": "notifyRowsChanged allowing: " + rows[j].messageid}); allowedrows.push(rows[j]); } } } else { allowedrows = rows; } this.writeLog("notifyRowsChanged notifying listener with: " + allowedrows.length + " rows"); listener.onRowsChanged(allowedrows, this); } else if (listener.onRowChanged) { for (j in rows) { if (listener.onRowChanged && (!listener.filter || listener.filter(rows[j]))) { this.writeLog({"2":"notifyRowsChanged notifying with row: " + rows[j].messageid}); listener.onRowChanged(rows[j], this, oldrows[j]); } } } if (listener.fillFinished) { listener.fillFinished(); } this.writeLog("notifyRowsChanged finished!"); } }; /** * calls the rowListeners' onRowDeleted function on a deleted row * * @Method DataSource.notifyRowDeleted * @param {Array} rows (required) the modified row */ FIRSTCLASS.util.DataSource.prototype.notifyRowDeleted = function(row) { var i; this.writeLog({"1":"notifyRowDeleted called with: " + row.messageid, "3":row}); this.writeLog("notifyRowsChanged called with: " + this._rowListeners.length); for (i = 0; i < this._rowListeners.length; i++) { var listener = this._rowListeners[i]; if (listener.onRowDeleted) { listener.onRowDeleted(row, this); } if (listener.fillFinished) { listener.fillFinished(); } } }; /** * adds a container data listener to the datasource, filling it if we already have data * * @Method DataSource.addDataListener * @param {Object} listener * @param {function} listener.onHeaderData(data) (optional) a function that's called when new container data is received * @param {function} listener.filter (optional) a data filter that checks to see if the listener cares about a specific piece of data (returns true/false) */ FIRSTCLASS.util.DataSource.prototype.addDataListener = function(listener) { if (FIRSTCLASS.util.DataSource.addListener(listener, this._dataListeners)) { if (listener.onHeaderData && this._data) { var key; for (key in this._data) { this.notifyHeaderData(key, this._data[key]); if (!listener.filter || listener.filter(key)) { listener.onHeaderData(this._data[key], this._data[this._data[key]]); } } } if (listener.onHeaderDataFinished) { listener.onHeaderDataFinished(); } } }; FIRSTCLASS.util.DataSource.prototype.clearDataListeners = function() { FIRSTCLASS.util.DataSource.clearListeners(this._dataListeners); }; /** * calls the rowListeners' onHeaderData function on a modified row * * @Method DataSource.notifyHeaderData * @param {Array} rows (required) the modified row */ FIRSTCLASS.util.DataSource.prototype.notifyHeaderData = function(data, contents) { var i, listener; for (i = 0; i < this._dataListeners.length; i++) { listener = this._dataListeners[i]; if (typeof listener.onHeaderData != "undefined" && (!listener.filter || listener.filter(data))) { listener.onHeaderData(data, contents, this); } if (listener.onHeaderDataFinished) { listener.onHeaderDataFinished(); } } for (i = 0; i < FIRSTCLASS.util.DataSource._global.datalisteners.length; i++) { listener = FIRSTCLASS.util.DataSource._global.datalisteners[i]; if (typeof listener.onHeaderData != "undefined" && (!listener.filter || listener.filter(data))) { listener.onHeaderData(data, contents, this); } if (listener.onHeaderDataFinished) { listener.onHeaderDataFinished(); } } }; /*FIRSTCLASS.util.DataSource.prototype.notifyChatInvites = function(invites) { var i; for (i = 0; i < invites.objids.length; i++) { this.notifyChatInvite(invites[i]); } }; FIRSTCLASS.util.DataSource.prototype.notifyChatInvite = function(invite) { var i; for (i = 0; i < this._dataListeners.length; i++) { var listener = this._dataListeners[i]; if (listener.onChatInvite) { listener.onChatInvite(invite); } } };*/ FIRSTCLASS.util.DataSource.prototype.getAcl = function() { if (this._config.masterDS) { return this._config.masterDS.getAcl(); } if (this._data && this._data.acl) { return this._data.acl; } else { return -1; } }; FIRSTCLASS.util.DataSource.prototype.getTags = function() { if (this._overrideTags) { return this._overrideTags; } else if (this._data && this._data.tags) { return this._data.tags; } else { return false; } }; FIRSTCLASS.util.DataSource.prototype.setTags = function(tags) { this.notifyHeaderData("tags", tags); this._overrideTags = tags; }; /** * fills the entire container, requestGranularity rows at a time * * @Method DataSource.performFill */ FIRSTCLASS.util.DataSource.prototype.performFill = function(granularity) { if (!granularity) { granularity = 100; } if (!this._isFilled || this._config.reloadFullOnPoll) { if (!this._config.loadFull) { this._config.autoLoad = true; this._state.requestGranularity = granularity; } this.fetchRows(); } }; FIRSTCLASS.util.DataSource.prototype.reFill = function() { this._isRefilling = true; this._state.hasMoreRows = true; if (this._config.reloadFullOnPoll) { this._state.currentDataIndex = 0; this._state.requestGranularity = 100; } else { this._state.requestGranularity = this._state.currentDataIndex; } this._state.currentDataIndex = 0; var i, listener; for (i = 0; i < this._rowListeners.length; i++) { listener = this._rowListeners[i]; if (listener.onRefill) { listener.onRefill(this); } } this.fetchRows(); var that = this; if (this._config.reloadFullOnPoll) { this.refillTimeout = window.setTimeout(function() { that.reFill(); }, this._config.pollInterval); } }; /** * fills the entire container of the selected objTypes, requestGranularity rows at a time * * @Method DataSource.performFill * @param {Array} objTypes (required) an array of objTypes to fill */ FIRSTCLASS.util.DataSource.prototype.performFillByObjType = function(objTypes) { if (!this._isFilled) { this.fetchRowsByObjType(objTypes); } }; FIRSTCLASS.util.DataSource.prototype.isLoading = function() { if (!this._connManagerRequest) { return false; } return YAHOO.util.Connect.isCallInProgress(this._connManagerRequest); }; FIRSTCLASS.util.DataSource.prototype.suspendWatchFetching = function() { if ((this._config.watchForNew || this._config.watchForTinkle) && this._watchState.fetching) { YAHOO.util.Connect.abort(this._watchState.connManagerRequest, null, false); this._watchState.connManagerRequest = null; this._watchState.wasfetching = true; } }; FIRSTCLASS.util.DataSource.prototype.resumeWatchFetching = function() { if (this._config.watchForNew && this._watchState.wasfetching) { this._watchState.wasfetching = false; this._watchState.fetching = false; this.fetchNewRows(); } else if (this._config.watchForTinkle && this._watchState.wasfetching) { this._watchState.wasfetching = false; this._watchState.fetching = false; this.watchForTinkle(); } }; /** * fetches more rows into the DataSource, as governed by this._config * * @Method DataSource.fetchRows */ FIRSTCLASS.util.DataSource.prototype.fetchRows = function(callbacks, ignorenosymbio, indices, notouch, ignoreactive, ignoredeleted) { var that = this; if (this._isFilled || (!this._config.active && !ignoreactive)) { return; } if (!this._connManagerRequest || !this.isLoading()) { this.suspendWatchFetching(); /* if ((this._config.watchForNew || this._config.watchForTinkle) && this._watchState.fetching) { YAHOO.util.Connect.abort(this._watchState.connManagerRequest, null, false); that._watchState.connManagerRequest = null; this._watchState.wasfetching = true; }*/ if (this._isFetching && !ignoreactive) { return; } else { this._isFetching = true;} this.fetchRowsIgnoreActive = ignoreactive; this.writeLog("Fetching Rows " + this._state.currentDataIndex + " to " + (this._state.currentDataIndex+this._state.requestGranularity)); var urlcfg = { baseUrl: this._config.containerBaseUrl, startIndex: this._state.currentDataIndex, forcenodeleted: ignoredeleted }; if (notouch) { urlcfg.notouch = notouch; } if (indices) { urlcfg.startIndex = indices.startIndex; urlcfg.endIndex = indices.endIndex; } else { if (!this._config.reloadFullOnPoll) { var granularity = this._config.initialRequestGranularity; if (this._state.currentDataIndex != 1 || !granularity) { granularity = this._state.requestGranularity; } urlcfg.endIndex = urlcfg.startIndex+granularity; } if (this._config.loadFull || this._config.reloadFullOnPoll) { urlcfg.loadFull = true; } } if (this._config.nosymbiomainfetch && !ignorenosymbio) { urlcfg.nosymbiosis = true; } if (callbacks) { this._state.callbacks = callbacks; } var postData = false; var url = this.generateDataURL(urlcfg); if (this._config.postForm) { YAHOO.util.Connect.resetDefaultHeaders(); var frm = this._config.postForm; /*var params = FIRSTCLASS.util.parseParameters(url); url = this._config.containerBaseUrl; var i; for (i in params) { frm.elements.push({name:i, value:params[i]}); }*/ var html = ["
"]; var i, e; for (i in frm.elements) { e = frm.elements[i]; html.push(""); } html.push("
"); var div = document.createElement("div"); div.innerHTML = html.join(""); YAHOO.util.Connect.setForm(div.firstChild, false); /* var date = new Date(); var boundaryString ='--FirstClass'+date.getTime(); postData = FIRSTCLASS.util.getPOSTData(this._config.postForm, boundaryString); YAHOO.util.Connect.resetDefaultHeaders(); YAHOO.util.Connect.setDefaultPostHeader(false); YAHOO.util.Connect.initHeader('Content-Type', 'multipart/form-data; boundary=' + boundaryString);*/ } this._connManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL(urlcfg), { success: this.fetchRowsSuccess, failure: this.fetchRowsFailure, scope: this }, postData); this.addConnReq(this._connManagerRequest,"fetchRows"); } }; FIRSTCLASS.util.DataSource.prototype.fetchRowsSuccess = function (response) { var that = this; var callbacks = this._state.callbacks; that.writeLog("DataSource received Success"); that._onSuccess(response, that._state, this.fetchRowsIgnoreActive); if (callbacks && callbacks.completed) { callbacks.completed(); } if (that._config.nosymbiomainfetch && !that._config.symbioseeded) { // perform fetch again, with symbiosis that.fetchRows({completed:function() {that._config.symbioseeded = true;}}, true); } that.writeLog("DataSource Finished Processing"); // we aborted the watch to fetch more rows, start it again this.resumeWatchFetching(); this.fetchRowsIgnoreActive = false; }; FIRSTCLASS.util.DataSource.prototype.fetchRowsFailure = function (response) { var that = this; var callbacks = this._state.callbacks; that._onFailure(response, that._state, this.fetchRowsIgnoreActive); if (callbacks && callbacks.failed) { callbacks.failed(); } this.resumeWatchFetching(); this.fetchRowsIgnoreActive = false; }; /** * fetches more rows into the DataSource, as governed by this._config * * @Method DataSource.fetchRowsByObjType */ FIRSTCLASS.util.DataSource.prototype.fetchRowsByObjType = function(objType, backVersions) { this.writeLog("DataSource.fetchRowsByObjType called"); var that = this; var objTypes = []; if (typeof objType === "string") { objTypes.push(objType); } else { objTypes = objType; } if (this._isFilled || !this._config.active) { return; } if (typeof backVersions == "undefined") { backVersions = true; } this.suspendWatchFetching(); var connReq = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, startIndex: this._objTypeState.currentDataIndex + 1, objType: objTypes, backVersions: backVersions }), { success: this.fetchRowsByObjTypeSuccess, failure: this.fetchRowsByObjTypeFailure, scope: this } ); this.addConnReq(connReq, 'fetchRowsByObjType'); }; FIRSTCLASS.util.DataSource.prototype.fetchRowsByObjTypeSuccess = function(response) { this._onSuccess(response, this._objTypeState); this.resumeWatchFetching(); }; FIRSTCLASS.util.DataSource.prototype.fetchRowsByObjTypeFailure = function(response) { this._onFailure(response, this._objTypeState); this.resumeWatchFetching(); }; FIRSTCLASS.util.DataSource.prototype.fetchRowsByThread = function(threadID, callbacks) { this.writeLog("DataSource.fetchRowsByThread called"); var that = this; if (this._isFilled || !this._config.active) { return; } var urlcfg = { baseUrl: this._config.containerBaseUrl, threadid: threadID }; this.suspendWatchFetching(); this.fetchRowsByThreadCallbacks = callbacks; var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL(urlcfg), { success:this.fetchRowsByThreadSuccess, failure:this.fetchRowsByThreadFailure, scope:this } ); this.addConnReq(tmpConnManagerRequest, 'fetchRowsByThread'); }; FIRSTCLASS.util.DataSource.prototype.fetchRowsByThreadSuccess = function(response) { var that = this; var callbacks = this.fetchRowsByThreadCallbacks;// = callbacks that._onSuccess(response, that._objTypeState); if (callbacks && callbacks.completed) { callbacks.completed(); } this.resumeWatchFetching(); }; FIRSTCLASS.util.DataSource.prototype.fetchRowsByThreadFailure = function(response) { var that = this; var callbacks = this.fetchRowsByThreadCallbacks; that._onSuccess(response, that._objTypeState); if (callbacks && callbacks.completed) { callbacks.completed(); } this.resumeWatchFetching(); }; /** * fetches more rows into the DataSource, as governed by this._config * * @Method DataSource.fetchRows */ FIRSTCLASS.util.DataSource.prototype.fetchUnreadRows = function(callbacks) { this.writeLog("DataSource.fetchUnreadRows called"); var that = this; if (this._isFilled) { return; } this.suspendWatchFetching(); this._state.fetchUnreadRowsCallbacks = callbacks; var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, allunread: true, startIndex: this._unreadState.currentDataIndex + 1, endIndex: this._unreadState.currentDataIndex+this._state.requestGranularity }), { success: this.fetchUnreadRowsSuccess, failure: this.fetchUnreadRowsFailure, scope: this } ); this.addConnReq(tmpConnManagerRequest, 'fetchUnreadRows'); }; FIRSTCLASS.util.DataSource.prototype.fetchUnreadRowsSuccess = function (response) { this.writeLog({"1": "DataSource.fetchUnreadRowsSuccess", "5":response}); var that = this; var callbacks = this._state.fetchUnreadRowsCallbacks; this._state.fetchUnreadRowsCallbacks = null; that._onSuccess(response, that._unreadState); if (callbacks && callbacks.completed) { callbacks.completed(); } this.resumeWatchFetching(); }; FIRSTCLASS.util.DataSource.prototype.fetchUnreadRowsFailure = function (response) { this.writeLog({"1": "DataSource.fetchUnreadRowsFailure", "5":response}); var that = this; var callbacks = this._state.fetchUnreadRowsCallbacks; this._state.fetchUnreadRowsCallbacks = null; that._onFailure(response, that._unreadState); if (callbacks && callbacks.failed) { callbacks.failed(); } this.resumeWatchFetching(); }; // get a row by name into the ds, and return it via callback FIRSTCLASS.util.DataSource.prototype.getRowByName = function(name, callback) { this.writeLog("DataSource.getRowByName called" + name); var that = this; this.suspendWatchFetching(); if (this._isFilled && false) { this.getRowCompleted(true, "name", name, callback); } else { var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, name: name }), { success:function (response) { that._onSuccess(response, that._objTypeState); that.getRowCompleted(true, "name", name, callback); }, failure:function (response) { that._onFailure(response, that._objTypeState); that.getRowCompleted(false, "name", name, callback); } } ); this.addConnReq(tmpConnManagerRequest, 'getRowByName'); } return; }; // get a row by sys id into the ds, and return it via callback FIRSTCLASS.util.DataSource.prototype.getRowBySysid = function(sysid, callbacks) { this.writeLog({"1": "DataSource.getRowBySysid: "+ sysid}); var that = this; this.suspendWatchFetching(); var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, uri: sysid }), { success:function (response) { that._onSuccess(response, that._objTypeState); that.getRowCompleted(true, "uri", sysid, callbacks); }, failure:function (response) { that._onFailure(response, that._objTypeState); that.getRowCompleted(false, "uri", sysid, callbacks); } } ); this.addConnReq(tmpConnManagerRequest, 'getRowBySysid'); return; }; FIRSTCLASS.util.DataSource.prototype.getRowByCID = function(cid, callbacks) { this.writeLog({"1": "DataSource.getRowByCID: "+ cid}); var that = this; this.supendWatchFetching(); var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, cid:cid }), { success:function (response) { that._onSuccess(response, that._objTypeState); that.getRowCompleted(true, "cid", cid, callbacks); }, failure:function (response) { that._onFailure(response, that._objTypeState); that.getRowCompleted(false, "cid", cid, callbacks); } } ); this.addConnReq(tmpConnManagerRequest, 'getRowByCID'); return; }; // grab the target row and call the callbacks on completion of a "getRowBy" function FIRSTCLASS.util.DataSource.prototype.getRowCompleted = function(success, column, key, callback) { this.writeLog({"1": "DataSource.getRowCompleted", "3":{success:success, column:column, key:key}}); var s = success; if (s) { if (callback && callback.success) { var rows = this.query(column, key, true); if (rows && rows.length) { callback.success(rows[0][1]); } else { s = false; } } } if (!s && callback.failure) { callback.failure(); } this.resumeWatchFetching(); return; }; FIRSTCLASS.util.DataSource.prototype.fetchItem = function(row, callbacks) { this.writeLog({"1": "DataSource.fetchItem", "3":row}); var that = this; if (typeof row == "string") { var i; for (i = 0; i < this._data.records.length; i++) { if (this._data.records[i].uri == row) { row = this._data.records[i]; break; } } } var uri = this.getItemUrl(row, true); var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: uri, backVersions: false }), { success:function (response) { // parse JSON data and append it to our current data list var newdata = []; try { newdata = response.responseJSON; if (!newdata) { throw "JSON parse Failed"; }//FIRSTCLASS.lang.JSON.parse(response.responseText); } catch(x){ ////YAHOO.log("JSON Parse Failed", "error", "DataSource.js"); return; } row.itemdata = newdata; var rows = [row]; that.processIncomingContent(rows); rows = null; that.notifyRowChanged(row); if (callbacks && callbacks.completed) { callbacks.completed(row); } }, failure:function (response) { that._onFailure(response, {"row": row}); if (callbacks && callbacks.failed) { callbacks.failed(); } } } ); this.addConnReq(tmpConnManagerRequest, 'fetchItem'); }; /** * checks for new rows at the beginning of the container * * @Method DataSource.fetchNewRows */ FIRSTCLASS.util.DataSource.prototype.fetchNewRows = function(callbacks, uselastrowasanchor) { this.writeLog("Polling " + this._config.name + (this._config.active?";active":";inactive")+ (this._watchState.fetching?";fetching":";not fetching"),1); if (this._config.masterDS) { this._config.masterDS.fetchNewRows(callbacks); return; } /* if (this._config.active && this._watchState.fetching) { YAHOO.util.Connect.abort(this._watchState.connManagerRequest); this._watchState.fetching = false; }*/ if (this._config.active && !this._watchState.fetching) { this._watchState.fetching = true; this._watchState.callbacks = callbacks; var that = this; //YAHOO.log("checking for new rows"); if (that._watchState.connManagerRequest) { if (YAHOO.util.Connect.isCallInProgress(that._watchState.connManagerRequest)) { this.writeLog("Polling while poll in progress in ds " + that._instance + "for container " + that.getContainerUrl()); } else { that.removeConnReq(that._watchState.connManagerRequest); } } that._watchState.connManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, this.generateDataURL({ baseUrl: this._config.containerBaseUrl, unread: true, uselastrowasanchor: uselastrowasanchor }), { success: this.fetchNewRowsSuccess, failure: this.fetchNewRowsFailure, abort: this.fetchNewRowsAbort, scope: this, timeout: 60000 }); that.addConnReq(that._watchState.connManagerRequest, 'fetchNewRows'); } }; FIRSTCLASS.util.DataSource.prototype.fetchNewRowsSuccess = function (response) { this.writeLog({"2": "DataSource.fetchNewRowsSuccess Called", "5": response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; // kludge alert: housekeeping to flush pulse updates from connection list if (that._config.name === "Pulse") { that.killConnReqs(); } that._onSuccess(response, that._watchState); if (callbacks && callbacks.completed) { callbacks.completed(); } }; FIRSTCLASS.util.DataSource.prototype.fetchNewRowsFailure = function (response) { this.writeLog({"2": "DataSource.fetchNewRowsFailure Called", "5": response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; if ( response.status == -1 && that._config.active ) { window.setTimeout(function() { that.fetchNewRows(); }, that._config.pollInterval); } else { that._onFailure(response, that._watchState); } if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.fetchNewRowsAbort = function (response) { this.writeLog({"2": "DataSource.fetchNewRowsAbort Called", "5": response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; // timeout probably if ( response.status == -1 && that._config.active ) { window.setTimeout(function() { that.fetchNewRows(); }, that._config.pollInterval); } if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.watchForTinkle = function(callbacks, reFetch) { this.writeLog({"1": "DataSource.watchForTinkle"}); if (this._config.active && this._watchState.fetching === false) { this._watchState.fetching = true; var that = this; //YAHOO.log("checking for new rows"); var url = this.generateDataURL({baseUrl: this._config.containerBaseUrl, tinkle: true}); if (reFetch) { url = this.generateDataURL({baseUrl: this._config.containerBaseUrl, startIndex: 1, loadFull: true}); } if (that._watchState.connManagerRequest) { if (YAHOO.util.Connect.isCallInProgress(that._watchState.connManagerRequest)) { this.writeLog("Tinkle watch while poll in progress in ds " + that._instance + "for container " + that.getContainerUrl()); } else { that.removeConnReq(that._watchState.connManagerRequest); } } that._watchState.connManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, url, { success: this.watchForTinkleSuccess, failure: this.watchForTinkleFailure, abort: this.watchForTinkleAbort, scope: this }); that.addConnReq(that._watchState.connManagerRequest, 'watchForTinkle'); } }; FIRSTCLASS.util.DataSource.prototype.watchForTinkleSuccess = function (response) { this.writeLog({"1": "DataSource.watchForTinkleSuccess", "5":response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; that._onSuccess(response, that._watchState); if (callbacks && callbacks.completed) { callbacks.completed(); } }; FIRSTCLASS.util.DataSource.prototype.watchForTinkleFailure = function (response) { this.writeLog({"1": "DataSource.watchForTinkleFailure", "5":response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; if ( response.status == -1 && that._config.active ) { window.setTimeout(function() { that.watchForTinkle(callbacks); }, that._config.pollInterval); } else { that._onFailure(response, that._watchState); } if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.watchForTinkleAbort = function (response) { this.writeLog({"1": "DataSource.watchForTinkleAbort", "5":response}); var that = this; var callbacks = that._watchState.callbacks; that._watchState.callbacks = null; that._watchState.fetching = false; // timeout probably if ( response.status == -1 && that._config.active ) { window.setTimeout(function() { that.watchForTinkle(callbacks); }, that._config.pollInterval); } if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.deleteThread = function(row, callbacks) { this.writeLog({"1": "DataSource.deleteThread Called", "3": row}); if (this._config.masterDS) { this._config.masterDS.deleteThread(row, callbacks); } else { var threadid = row.threadid.replace('-', '_'); var postData = FIRSTCLASS.lang.uesc('FieldID:1001=LONG') + '=299&' + FIRSTCLASS.lang.uesc('FieldID:1002=STRING') + '=' + FIRSTCLASS.lang.uesc('11_(' + threadid + ')'); YAHOO.util.Connect.resetDefaultHeaders(); YAHOO.util.Connect.setDefaultPostHeader(true); var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest("POST", FIRSTCLASS.lang.ensureSlashUrl(this._config.containerBaseUrl) + FIRSTCLASS.opCodes.FileOp, false, postData); this.addConnReq(tmpConnManagerRequest, 'deleteThread'); } var j; for (j in this._data.records) { if (this._data.records[j].threadid == row.threadid) { this.notifyRowDeleted(row); row.status.deleted = true; } } }; FIRSTCLASS.util.DataSource.prototype.deleteRow = function(row, callbacks) { this.writeLog({"1": "DataSource.deleteRow", "3":row}); if (row.mRow) { this._config.masterDS.deleteRow(row.mRow, callbacks); } else { var that = this; //YAHOO.log("Deleting Row"); var uri = this.getItemUrl(row, false, false); var url = FIRSTCLASS.lang.removeSlashUrl(uri); if (url.indexOf("?") >= 0) { url += "&"; } else { url += "?"; } url += this._config.pluginStr + "&Delete=1"; row.status.deleted = true; // not really but let's indicate to ui var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, url, { success:function (response) { that.notifyRowDeleted(row); row.status.deleted = true; if (callbacks && callbacks.completed) { callbacks.completed(); } }, failure:function (response) { if (callbacks && callbacks.failed) { callbacks.failed(); } } } ); this.addConnReq(tmpConnManagerRequest, 'deleteRow'); } }; FIRSTCLASS.util.DataSource.prototype.markAllAsRead = function() { this.writeLog({"1": "DataSource.markAllAsRead"}); if (this._config.masterDS) { this._config.masterDS.markAllAsRead(); } else { var url = this._config.containerBaseUrl; if (url.indexOf("__Open-Item/ThePulse") >= 0 && this._data && this._data.huri) { url = this._data.huri; } url +="?Unread=-1"; var that = this; var req = FIRSTCLASS.util.net.asyncRequest('GET',url, { success: function(evt) { var rows = []; var oldrows = [], i, row; for (i in that._data.records) { row = that._data.records[i]; if (row.status.unread) { oldrows.push(row); row.status.unread = false; rows.push(row); that._data.records[i] = row; } } that.notifyRowsChanged(rows,oldrows); rows = null; oldrows = null; } }); this.addConnReq(req, 'markAllAsRead'); } }; FIRSTCLASS.util.DataSource.prototype.toggleUnRead = function(row, newvalue, callbacks) { this.writeLog({"1": "DataSource.toggleUnRead", "3":row}); var that = this; if (row.mRow) { this._config.masterDS.toggleUnRead(row.mRow, newvalue, callbacks); } else { //YAHOO.log("Toggling Row"); var uri = this.getItemUrl(row, true, false); var setVal = row.status.unread ? 0 : 1; if (typeof newvalue == "number") { setVal = newvalue > 0 ? 1 : 0; } else if (typeof newvalue == "boolean") { setVal = newvalue ? 1 : 0; } var param = "&Unread=" + ((setVal === 0) ? "-1" : "1"); uri = FIRSTCLASS.lang.removeSlashUrl(uri); if (uri.indexOf("?") >= 0) { uri += "&"; } else { uri += "?"; } var oldkeys = { status: { unread: 1 }, onlyunread: true }; row.status.unread = setVal; that.notifyRowChanged(row, oldkeys); if (callbacks) { this._state.toggleUnreadCallbacks = callbacks; } var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, uri + this._config.pluginStr + param, { success: this.toggleUnReadSuccess, failure: this.toggleUnReadFailure, scope: this } ); this.addConnReq(tmpConnManagerRequest, 'toggleUnRead'); } }; FIRSTCLASS.util.DataSource.prototype.toggleUnReadSuccess = function(response) { var callbacks = this._state.toggleUnreadCallbacks; this._state.toggleUnreadCallbacks = null; if (callbacks && callbacks.completed) { callbacks.completed(); } }; FIRSTCLASS.util.DataSource.prototype.toggleUnReadFailure = function(response) { var callbacks = this._state.toggleUnreadCallbacks; this._state.toggleUnreadCallbacks = null; if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.toggleUnreadRows = function(rows) { var form = [], i, row, uri, idx, el; form.push("
"); form.push(""); form.push(""); form.push(""); form.push("
"); if (unreadrows === 0) { return; } el = document.createElement("div"); el.innerHTML = form.join(""); FIRSTCLASS.util.submitForm(el.firstChild, false); for (i in rows) { rows[i].status.unread = 0; this.notifyRowChanged(rows[i]); } }; FIRSTCLASS.util.DataSource.prototype.approveItem = function(row, newvalue, callbacks) { this.writeLog({"1": "DataSource.approveItem", "2":newvalue, "3":row}); var that = this; if (row.mRow) { this._config.masterDS.toggleUnRead(row.mRow, newvalue, callbacks); } else { var uri = this.getItemUrl(row, true, false); var setVal = row.status.unapproved ? 0 : 1; if (typeof newvalue == "number") { setVal = newvalue > 0 ? 1 : 0; } else if (typeof newvalue == "boolean") { setVal = newvalue ? 1 : 0; } var param = "&Approve=" + ((setVal === 0) ? "1" : "-1"); uri = FIRSTCLASS.lang.removeSlashUrl(uri); if (uri.indexOf("?") >= 0) { uri += "&"; } else { uri += "?"; } var oldkeys = { status: { unapproved: 1 } }; row.status.unapproved = setVal; that.notifyRowChanged(row, oldkeys); if (callbacks) { this._state.toggleUnreadCallbacks = callbacks; } this._toggleApprovedRow = row; var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, uri + this._config.pluginStr + param, { success: this.toggleApprovedSuccess, failure: this.toggleApprovedFailure, scope: this } ); this.addConnReq(tmpConnManagerRequest, 'approveItem'); } }; FIRSTCLASS.util.DataSource.prototype.toggleApprovedSuccess = function(response) { var callbacks = this._state.toggleApprovedCallbacks; this._state.toggleApprovedCallbacks = null; if (this._toggleApprovedRow.typedef.objtype == FIRSTCLASS.objTypes.message || this._toggleApprovedRow.typedef.objtype == FIRSTCLASS.objTypes.confitem) { this.fetchItem(this._toggleApprovedRow); } this._toggleApprovedRow = false; if (callbacks && callbacks.completed) { callbacks.completed(); } }; FIRSTCLASS.util.DataSource.prototype.toggleApprovedFailure = function(response) { var callbacks = this._state.toggleApprovedCallbacks; this._state.toggleApprovedCallbacks = null; this._toggleApprovedRow = false; if (callbacks && callbacks.failed) { callbacks.failed(); } }; FIRSTCLASS.util.DataSource.prototype.updateContainerFieldData = function(fields) { this.writeLog({"1": "DataSource._updateContainerField", "2":fields}); var form = {}; var field = {}; form.elements = []; form.action = FIRSTCLASS.lang.ensureSlashUrl(this.getContainerUrl()) + FIRSTCLASS.opCodes.FormSave; field.name = "Charset"; field.value = "UTF-8"; form.elements.push(field); // send tag var i; for (i in fields) { var info = fields[i]; field = {}; if (!info.name) { field.name = "FieldID:" + info.id + "=" + info.type; } else { field.name = info.name; } field.value = info.value; form.elements.push(field); if (info.key) { this._data[info.key] = info.value; this.notifyHeaderData(info.key, info.value); } var altkey = false; switch(info.id) { case 13083: altkey = "skin"; break; default: } if (altkey) { this._data[altkey] = info.value; this.notifyHeaderData(altkey, info.value); } } // post it FIRSTCLASS.util.submitForm(form); }; FIRSTCLASS.util.DataSource.prototype.updateFieldData = function(therow, fields) { this.writeLog({"1": "DataSource.updateFieldData", "3":therow, "2":fields}); var form = {}; var field = {}; form.elements = []; form.action = FIRSTCLASS.lang.ensureSlashUrl(this.getContainerUrl()) + FIRSTCLASS.opCodes.FormSave; var row = FIRSTCLASS.lang.removeSlashUrl(therow.uri); if (therow.typedef.objtype == FIRSTCLASS.objTypes.file) { if (row.indexOf("FCItemURL=") > 0) { row = row.slice(row.indexOf("FCItemURL=") + 10); } } if (row.indexOf("?") > 0) { row = row.slice(0, row.indexOf("?")); } field.name = "Charset"; field.value = "UTF-8"; form.elements.push(field); field.name = "Close"; field.value = "-1"; form.elements.push(field); // send tag var i; for (i in fields) { var info = fields[i]; field = {}; field.name = "LFieldID_" + info.id + "." + row + "=" + info.type; field.value = info.value; form.elements.push(field); } // post it FIRSTCLASS.util.submitForm(form); }; FIRSTCLASS.util.DataSource.prototype.watchItem = function(row, callbacks) { var that = this; if (row.mRow) { this._config.masterDS.watchItem(row.mRow, callbacks); } else { var uri = this.getItemUrl(row, false, false); var param = "&Watch=1"; var url = FIRSTCLASS.lang.removeSlashUrl(uri); if (url.indexOf("?") >= 0) { url += "&"; } else { url += "?"; } url += this._config.pluginStr + param; var tmpConnManagerRequest = FIRSTCLASS.util.net.asyncRequest(this._config.requestType, url, { success:function (response) { row.status.watched = 1; that.notifyRowChanged(row); if (callbacks && callbacks.completed) { callbacks.completed(); } }, failure:function (response) { if (callbacks && callbacks.failed) { callbacks.failed(); } } } ); this.addConnReq(tmpConnManagerRequest, 'watchItem'); } }; FIRSTCLASS.util.DataSource.prototype.getItemUrl = function(row, praw, retain, absolute) { var uri = row.uri; var raw = typeof praw != "undefined" && praw; if (row.uri.indexOf(FIRSTCLASS.session.baseURL) == -1) { if (row.uri.indexOf(".0/") > 0) { row.uri = row.uri.substr(0, row.uri.indexOf(".0")); } if (this._config.containerBaseUrl) uri = FIRSTCLASS.lang.ensureSlashUrl(FIRSTCLASS.lang.ensureSlashUrl(this._config.containerBaseUrl) + row.uri) + (raw?"":"?Show=2"); if (uri.indexOf(FIRSTCLASS.session.baseURL) == -1) { uri = FIRSTCLASS.lang.ensureSlashUrl(FIRSTCLASS.session.baseURL) + uri; } if (absolute && uri.indexOf(FIRSTCLASS.session.domain) == -1) { uri = FIRSTCLASS.lang.removeSlashUrl(FIRSTCLASS.session.domain) + uri; } } if (uri.indexOf("?FCItemURL=") > 0 && !retain) { var sp = uri.split("?FCItemURL="); var sp2 = sp[0].split("/"); sp2[sp2.length-1] = ""; uri = sp2.join("/") + sp[1]; } return uri; }; FIRSTCLASS.util.DataSource.prototype.getContainerUrl = function() { return this._config.containerBaseUrl; }; FIRSTCLASS.util.DataSource.prototype.getPermalinkContainerUrl = function() { if (this._data.cid) { return "__Open-Conf/CID" + this._data.cid; } var uri = this._config.containerBaseUrl.replace("FAV1", "FV1").replace("FOV1", "FV1").replace("FLV1", "FV1"); var idx = uri.indexOf(FIRSTCLASS.session.baseURL); if (idx >= 0 && uri.length - idx > FIRSTCLASS.session.baseURL.length) { return uri.substr(idx+FIRSTCLASS.session.baseURL.length); } return uri; }; FIRSTCLASS.util.DataSource.prototype.getPermalink = function(row) { return "#" + FIRSTCLASS.lang.ensureSlashUrl(this.getPermalinkContainerUrl()) + FIRSTCLASS.util.generateThreadContextParameter(row , true); }; FIRSTCLASS.util.DataSource.prototype.compareRows = function(row1, row2) { return row1.uri == row2.uri; }; /** * changes the granularity of requests dispatched by this datasource * * @Method DataSource.setRequestGranularity * @param {int} granularity (required) the new granularity */ FIRSTCLASS.util.DataSource.prototype.setRequestGranularity = function(granularity) { this._state.requestGranularity = granularity; }; FIRSTCLASS.util.DataSource.prototype._onSuccess = function(response, state, ignoreactive) { if (!this._config.active && !ignoreactive) { // deactivated, parsing the data could cause serious issues return; } // parse JSON data and append it to our current data list var newdata = [], i, listener; var that = this; try { //var text = response.responseText.replace(/\\\'/g,"'"); //newdata = FIRSTCLASS.lang.JSON.parse(text); newdata = response.responseJSON; if (!newdata) { throw "_onSuccess: JSON parse Failed"; }//FIRSTCLASS.lang.JSON.parse(response.responseText); that.writeLog("_onSuccess: JSON Parse Finished"); } catch(x){ that.writeLog("_onSuccess: JSON Parse Failed"); //YAHOO.log("JSON Parse Failed", "error", "DataSource.js"); if (response.responseText && response.responseText.indexOf("YUI/x138") > 0) { window.location = FIRSTCLASS.session.baseURL; // we had a logout, and are being returned the login page return; } if (state == that._watchState) { window.setTimeout(function() { if (that._config.active) { if (that._config.watchForTinkle) { that.watchForTinkle(); } else { that.fetchNewRows(); } } }, this._config.pollInterval); } if( this._config.isRadForm && response.responseText == "") { this._isFetching = false; window.setTimeout(function() { that.fetchRows(); }, this._config.pollInterval); } return; } if (typeof newdata.turi == "string" && newdata.turi.indexOf("S-138") >= 0) { window.location = FIRSTCLASS.session.baseURL; return; } if (newdata.error) { switch(newdata.error.code) { case 1010: window.location = FIRSTCLASS.session.baseURL; return; case 1030: var shouts = [ { parsedDate: new Date(), message: FIRSTCLASS.locale.errors.getErrorString(newdata.error), who: "Social Media", fontsize: "1.1em" } ]; FIRSTCLASS.ui.navBar.updateShoutBox(shouts); break; // case 1030: default: // handle more errors here var date = new Date(); newdata = { records: [ { typedef:{ objtype: FIRSTCLASS.objTypes.message, subtype: 0, isleaf: true }, status: { unread: 0, complete: true }, creatorcid: 0, name: FIRSTCLASS.locale.datasource.error.owner, subject: FIRSTCLASS.locale.datasource.error.subject, uid: 0, cid: "CID0", lastmod: date, lastmods: (date.getTime()/1000), messageid: "0", threadid: "0000-1111", icon: { id: 0 }, col8063: FIRSTCLASS.locale.errors.getErrorString(newdata.error), uri: "" } ] }; this.deactivate(); } } var hasMoreRows = this.loadData(newdata, state); //YAHOO.log("_onSuccess", "notification", "DataSource.js"); if (hasMoreRows && this._config.autoLoad) { if (this._config.autoLoadUntilRow) { for (i in newdata.records) { if (newdata.records[i].uri == this._config.autoLoadUntilRow.uri) { this._config.autoLoad = false; break; } } } if (this._config.autoLoad && this._data.numitems && false) { window.setTimeout(function(){ that.fetchRows(false,false, {startIndex:that._state.currentDataIndex+1, endIndex:that._data.numitems.total}); }, 1000); } else if (this._config.autoLoad) { window.setTimeout(function(){ that.fetchRows(); }, 1000); } } else if (!hasMoreRows && !this._isRefilling) { //YAHOO.log("Container Filled, no more records available"); state.hasMoreRows = false; for (i = 0; i < this._rowListeners.length; i++) { listener = this._rowListeners[i]; if (listener.onFillCompleted) { listener.onFillCompleted(this); } } /*if (this._config.watchForNew) { this.fetchNewRows(); }*/ } if (this._isRefilling) { this._isRefilling = false; state.requestGranularity = this._config.defaultRequestGranularity; } this._isFetching = false; this.parseContainerData(newdata); if (((state == this._state) || (state == this._objTypeState)) && this._config.watchForNew && !this._watchState.watching && !this._watchState.timeout) { this._watchState.watching = true; state.timeout = window.setTimeout(function() { if (that._config.active) { that.fetchNewRows(); state.timeout = false; } },this._config.pollInterval); } if (this._config.watchForNew && state === this._watchState && !state.timeout && !this._watchState.fetching) { if (newdata.records && newdata.records.length) { this.writeLog({"1":"updating lastrow to " + newdata.records[0].messageid, "3":newdata.records[0], "4": newdata}); this._watchState.lastrow = newdata.records[0]; } state.timeout = window.setTimeout(function() { if (that._config.active) { that.fetchNewRows(); state.timeout = false; } },this._config.pollInterval); } if (state == this._state && this._config.watchForTinkle && !this._watchState.watching && !this._watchState.timeout) { this._watchState.watching = true; state.timeout = window.setTimeout(function() { if (that._config.active) { that.watchForTinkle(); state.timeout = false; } },this._config.pollInterval); } if (this._config.watchForTinkle && state === this._watchState && !state.timeout && !this._watchState.fetching) { state.timeout = window.setTimeout(function() { if (that._config.active) { that.watchForTinkle(); state.timeout = false; } },this._config.pollInterval); } }; FIRSTCLASS.util.DataSource.prototype.getThreadFunction = function(threads, threadcb) { var that = this; return function() { if (threads.length > 0) { that.fetchRowsByThread(threads.pop(), threadcb); } threads = null; }; }; FIRSTCLASS.util.DataSource.prototype.loadData = function(newdata, state, doQuickFill) { if (typeof state == "undefined") { state = this._state; } // then for each new row, call our rowListeners var hasMoreRows = true, i, j, latestrow, nthreads, lastthread; if (newdata.records && newdata.records.length > 0) { this.processIncomingContent(newdata.records); var rowsToInsert = []; var deletedRows = []; var visitedRows = []; var changedRows = []; var oldRows = []; if (newdata.debugme) { debugger; } if (this._data && !doQuickFill) { if (!this._data.records) { this._data.records = []; } latestrow = false; for (i = 0; i < newdata.records.length; i++) { var insert = true; var row = newdata.records[i]; if (row.debugme) { debugger; } var maxversion = 0; for (j = 0; j < this._data.records.length; j++) { if (this.compareRows(this._data.records[j], newdata.records[i])) { var oldrow = this._data.records[j]; var newrow = newdata.records[i]; var uselastupdate = false; if (typeof oldrow.lastupdate != "undefined" && typeof newrow.lastupdate != "undefined") { uselastupdate = true; } var rowHasChanged = false; if (newrow.status.deleted != oldrow.status.deleted /*&& newrow.lastupdate > oldrow.lastupdate*/) { this._data.records[j] = newrow; this.notifyRowDeleted(oldrow); } else if ((uselastupdate && newrow.lastupdate != oldrow.lastupdate) || (!uselastupdate && this._config.compareRows && !this._config.compareRows(this._data.records[j], newdata.records[i])) || (!FIRSTCLASS.lang.objDataEqual(newrow, oldrow))) { rowHasChanged = true; } if (rowHasChanged) { if (oldrow.col8090 && !newrow.col8090) { newrow.col8090 = oldrow.col8090; } if (oldrow.mRow) { newrow.mRow = oldrow.mRow; } this._data.records[j] = newrow; changedRows.push(newrow); if (oldrow.itemdata && !newrow.itemdata) { newrow.itemdata = oldrow.itemdata; oldrow.itemdata = false; } oldRows.push(oldrow); } visitedRows[j] = true; insert = false; break; } if (state == this._watchState && (row.typedef.objtype == FIRSTCLASS.objTypes.fcfile || row.typedef.objtype == FIRSTCLASS.objTypes.file || row.typedef.objtype == FIRSTCLASS.objTypes.odocument) && row.status.backversion === 0) { if (this._data.records[j].threadid == row.threadid && this._data.records[j].col8090 && maxversion < this._data.records[j].col8090) { // don't count unsaved wikis if ((this._data.records[j].typedef.objtype != FIRSTCLASS.objTypes.odocument) || this._data.records[j].col8082) { maxversion = this._data.records[j].col8090; } this._data.records[j].status.backversion = 1; } } } if (maxversion > 0) { row.col8090 = maxversion + 1; } if (insert) { rowsToInsert.push(newdata.records[i]); } if (!latestrow || latestrow && latestrow.parsedDate < newdata.records[i].parsedDate) { latestrow = newdata.records[i]; } } if (changedRows.length) { this.notifyRowsChanged(changedRows, oldRows); } /*if (latestrow) { if (this._watchState.lastrow && latestrow.parsedDate > this._watchState.lastrow.parsedDate || !this._watchState.lastrow) { this._watchState.lastrow = latestrow; } }*/ if (this._config.reloadFullOnPoll || this._config.loadFull && state != this._watchState) { for (i = this._data.records.length-1; i > 0; i--) { if (!visitedRows[i]) { this.notifyRowDeleted(this._data.records[i]); this._data.records.splice(i,1); } } } if (state == this._state && this._config.fetchThreads) { nthreads = 0; lastthread = ""; for (i in rowsToInsert) { if (rowsToInsert[i].threadid != lastthread) { nthreads++; lastthread = rowsToInsert[i].threadid; } } this.writeLog("loadData received " + nthreads + " threads"); state.currentDataIndex += nthreads; } else if (state == this._watchState && this._config.fetchThreads && this._config.watchForNew) { var threads = []; for (i in rowsToInsert) { if (rowsToInsert[i].threadid != threads[threads.length-1]) { threads.push(rowsToInsert[i].threadid); this.writeLog("loadData found Thread " + rowsToInsert[i].threadid + " name " + rowsToInsert[i].subject + rowsToInsert[i].col8010); } } var that = this; var threadcb = { completed: this.getThreadFunction(threads, threadcb), scope: this }; if (threads.length > 0) { this.fetchRowsByThread(threads.pop(), threadcb); } } else { state.currentDataIndex += rowsToInsert.length; } this._data.records = this._data.records.concat(rowsToInsert); if (rowsToInsert.length > 0) { this.notifyNewRows(rowsToInsert, (state != this._watchState), (state == this._watchState)); } if (rowsToInsert.length === 0 || state == this._objTypeState) { hasMoreRows = false; } } else { latestrow = false; var row; for (i = 0; i < newdata.records.length; i++) { row = newdata.records[i]; if (row.debugme) { debugger; } for (j = i+1; j < newdata.records.length; j++) { if (this.compareRows(newdata.records[j], row)) { visitedRows[j] = true; } } if (row.status.deleted) { visitedRows[i] = true; } if ((!latestrow || latestrow && latestrow.parsedDate < row.parsedDate) && row.typedef && row.typedef.isleaf) { latestrow = row; } } if (latestrow) { this.writeLog({"1":"updating lastrow to " + latestrow.messageid, "3":latestrow}); this._watchState.lastrow = latestrow; } for (i = newdata.records.length-1; i >= 0; i--) { if (visitedRows[i]) { newdata.records.splice(i,1); } } this._data = newdata; if (state == this._state && this._config.fetchThreads) { nthreads = 0; lastthread = ""; for (i in newdata.records) { if (newdata.records[i].threadid != lastthread) { nthreads++; lastthread = newdata.records[i].threadid; } } this.writeLog("loadData received " + nthreads + " threads"); state.currentDataIndex += nthreads; //newdata.records.pop(); } else { state.currentDataIndex += newdata.records.length; } this.notifyNewRows(newdata.records, true); if (newdata.records.length === 0) { hasMoreRows = false; } } } else { hasMoreRows = false; } if (state == this._objTypeState) { hasMoreRows = false; } return hasMoreRows; }; FIRSTCLASS.util.DataSource.prototype._onFailure = function(response, data, ignoreactive) { this.writeLog({"1": "DataSource._onFailure", "3":response}); /*switch (response.status) { case -1: // aborted break; //case 0: // communications failure default: }*/ var failuredata = [], dofakerow = false; try { failuredata = response.responseJSON; if (!failuredata) { throw "JSON parse Failed"; } //FIRSTCLASS.lang.JSON.parse(response.responseText); if (!failuredata.error.loggedin) { // not logged in, redirect to login page window.location = FIRSTCLASS.session.baseURL; //alert("ERROR: " + failuredata.error.str); } else { switch(failuredata.error.code) { case 1030: var shouts = [ { parsedDate: new Date(), message: FIRSTCLASS.locale.errors.getErrorString(failuredata.error), who: "Social Media", fontsize: "1.1em" } ]; FIRSTCLASS.ui.navBar.updateShoutBox(shouts); break; case 1081: // not found if (data && data.row) { this.notifyRowDeleted(data.row); } dofakerow = true; break; default: dofakerow = true; } } if (dofakerow) { var date = new Date(); var fakedata = { records: [ { typedef:{ objtype: FIRSTCLASS.objTypes.message, subtype: 0, isleaf: true }, status: { unread: 0, complete: true }, creatorcid: 0, name: FIRSTCLASS.locale.datasource.error.owner, subject: FIRSTCLASS.locale.datasource.error.subject, uid: 0, cid: "CID0", lastmod: date, lastmods: (date.getTime()/1000), messageid: "0", threadid: "0000-1111", icon: { id: 0 }, col8063: FIRSTCLASS.locale.errors.getErrorString(failuredata.error), uri: "" } ] }; this.loadData(fakedata, this._state); this.deactivate(); } } catch(x) { //YAHOO.log("JSON Parse Failed", "error", "DataSource.js"); if (response.responseText && response.responseText.indexOf("YUI/x138") > 0 || response.status == 500) { window.location = FIRSTCLASS.session.baseURL; // we had a logout, and are being returned the login page } } var i, listener; for (i = 0; i < this._rowListeners.length; i++) { listener = this._rowListeners[i]; if (listener.onFillCompleted) { listener.onFillCompleted(this); } } this._isFetching = false; }; FIRSTCLASS.util.DataSource.prototype.processIncomingContent = function(rows) { var del = document.createElement("div"); var j, row; for (j in rows) { row = rows[j]; if (row.itemdata && row.itemdata.body) { if (!row.itemdata.expandedBody) { row.itemdata.expandedBody = this.expandContent(row,row.itemdata.body); if (typeof row.itemdata.expandedBody == "undefined") { row.itemdata.expandedBody = ""; } } } if(row.col8063 && row.col8063 != ""){ if (!row.expandedPreview && row.col8063) { row.expandedPreview = this.expandContent(row,row.col8063); del.innerHTML = row.expandedPreview; row.expandedPreview = del.innerHTML; if (typeof row.expandedPreview == "undefined") { row.expandedPreview = ""; } } } if (row.lastmods) { row.parsedDate = new Date(); row.parsedDate.setTime(row.lastmods*1000); } else if (row.lastmod) { row.parsedDate = Date.parse(row.lastmod); } } }; FIRSTCLASS.util.DataSource.prototype.expandContent = function(row,content) { var linklength = false; var maxstrlength = false; var urls = true; if (this._config.expandcfg) { if (typeof this._config.expandcfg.urls != "undefined") { urls = this._config.expandcfg.urls; } if (this._config.expandcfg.maxurl) { linklength = this._config.expandcfg.maxurl; } if (this._config.expandcfg.maxstr) { maxstrlength = this._config.expandcfg.maxstr; } } content = content.preprocess({urls: urls, maxurl:linklength, maxstr:maxstrlength}); content = FIRSTCLASS.util.url.processLinkTargets(content); content = FIRSTCLASS.util.url.expandImageUrls(this.getItemUrl(row),content); content = FIRSTCLASS.util.expandHashTags(content); return content; }; FIRSTCLASS.util.DataSource.prototype.parseContainerData = function(newdata, notify) { if (typeof notify == "undefined") { notify = true; } if (!this._data) { this._data = {}; } /* if (newdata.chat && newdata.chat.length) { if (!this._data.chat || this._data.chat.length === 0) { this._data.chat = newdata.chat; this.notifyChatInvites(this._data.chat); } else { var i, j, found; for (i = 0; i < newdata.chat.length; i++) { found = false; for (j = 0; j < this._data.chat.length; j++) { if (newdata.chat[i] == this._data.chat[j]) { found = true; break; } } if (!found) { this._data.chat.push(newdata.chat[i]); this.notifyChatInvite(newdata.chat[i]); } } } }*/ var key; for (key in newdata) { if (notify) { this.notifyHeaderData(key, newdata[key]); if (key == "broadcasts") { this.updateShout(newdata[key]); } } if (key != "records") { this._data[key] = newdata[key]; } } if (this._data && newdata.lastupdate) { this._data.lastupdate = newdata.lastupdate; } }; FIRSTCLASS.util.DataSource.prototype.query = function(column, str, caseinsensitive, compareFunc) { var rows = []; var search = str; if (caseinsensitive) { search = str.toLowerCase(); } if (this._data && this._data.records && this._data.records.length > 0) { var i, key; for (i = 0; i < this._data.records.length; i++) { key = this._data.records[i][column]; if (key) { if(caseinsensitive) { key = key.toLowerCase(); } var compare = false; if (compareFunc) { compare = compareFunc(key, search); } else if (typeof key == "string") { compare = (key.indexOf(search) >= 0); } else { compare = ((""+key) == search); } if (compare) { rows.push([this._data.records[i][column],this._data.records[i]]); } } } } return rows; }; FIRSTCLASS.util.DataSource.prototype.getYAHOOWidgetDataSource = function(column, caseinsensitive, compareFunc) { var that = this; var func = function(string) { return that.query(column, string, caseinsensitive, compareFunc); }; return {dataSource:new YAHOO.widget.DS_JSFunction(func), formatResult:function(result, query) { return result[0]; }}; }; FIRSTCLASS.util.DataSource.prototype.getYAHOOUtilDataSource = function() { var that = this; var getRecords = function(oRequest) { return that._data.records; }; var dataSource = new YAHOO.util.DataSource(getRecords,{ responseType:YAHOO.util.DataSource.TYPE_JSON, responseSchema: { fields: this.getColumns() }, maxCacheEntries: 4096 }); return dataSource; }; FIRSTCLASS.util.DataSource.prototype.getYAHOOUtilDataSourceFunc = function() { var that = this; var getRecords = function(oRequest) { return that._data.records; }; var dataSource = new YAHOO.util.DataSource(getRecords,{ responseType:YAHOO.util.DataSource.TYPE_JSON, responseSchema: { fields: this.getColumns() }, maxCacheEntries: 4096 }); return dataSource; }; FIRSTCLASS.util.DataSource.prototype.getColumns = function() { var cols = []; if (this._data && this._data.records) { var mkey; for (mkey in this._data.records[0]) { cols.push(mkey); } } return cols; }; FIRSTCLASS.util.DataSource.prototype.hasMoreRows = function() { if (this._data && this._data.records && this._data.numitems && this._data.numitems.both && !this._config.tackon) { return this._data.records.length < this._data.numitems.both; } return this._state.hasMoreRows; }; FIRSTCLASS.util.DataSource.prototype.updateShout = function(shouts) { FIRSTCLASS.ui.navBar.updateShoutBox(shouts); }; YAHOO.register("fcDataSource", FIRSTCLASS.util.DataSource, {version: "0.0.1", build: "1"});