Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List view getListItemXmlAttributes method fails with child publication items

I have created a JS class to populate SG/Folder list view data, when items are modified. (As per Jaime's approach) Everything works great when I operate on items in the publication they're created in.

Ex: I open a component or page and the custom locked by column immediately updates and shows my user name.

However, when I go to a child publication and repeat that process, I get the window asking if I want to localize or edit the parent item. If I select to edit the parent window, the code doesn't work. I haven't quite figured it out yet with initial debugging. Chrome seems to swallow the error, Firefox gives me a cryptic:

Timestamp: 6/22/2012 3:42:54 PM

Error: uncaught exception: [Exception... "Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]" nsresult: "0x80004002 (NS_NOINTERFACE)" location: "JS frame :: chrome://browser/content/tabbrowser.xml :: :: line 545" data: no]

Does anyone have any initial ideas? I'll try to post some code later on...

Code from PageEx.js:

Type.registerNamespace("MyCompany.Tridion.RTFExtensions");  /* * Constructor */  MyCompany.Tridion.RTFExtensions.PageEx = function (id) {     Type.enableInterface(this, "MyCompany.Tridion.RTFExtensions.PageEx");     this.addInterface("Tridion.ContentManager.Page", [id]);     var p = this.properties;     p.versionNumberString = undefined;     p.modifiedBy = undefined;     p.lockedBy = undefined;     p.approvalStatus = undefined;     p.publishDate = undefined;     p.previousVersion = undefined;     p.previousApprovalStatus = undefined;     p.customModifiedDate = undefined;     p.initialModifierUserName = undefined; };  /* * sends the list xml string for the item  */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.getListItemXmlAttributes = function (customAttributes) {     var attribs = {};     $extUtils.getListItemXmlAttributes(customAttributes,this, attribs);     return this.callBase("Tridion.ContentManager.Page", "getListItemXmlAttributes", [attribs]); };   /* * This method gets called when an item is opened from list view. node parameter has the information * displayed in the list view as attributes. We are getting cutom data extender column information  * from this xml node and storing it in this class member for returning it from getListItemXmlAttributes method */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.setDataFromList = function (node, parentId, timeStamp) {     $extUtils.setDataFromList(node,parentId,timeStamp,this);     this.callBase("Tridion.ContentManager.Page", "setDataFromList", [node, parentId, timeStamp]); };  /*  * Gets item icon  */ MyCompany.Tridion.RTFExtensions.PageEx.prototype.getItemIcon = function () {     var icon = this.callBase(this.defaultBase, "getItemIcon");     return icon; }; 

Code from utils.js:

// reloads the list view for the given id (used in list view data refresh when JS cant get the required data without reloading) MyCompany.Tridion.RTFExtensions.Utilities.reloadListView = function (listTcmId) {     var registry = $models.getListsRegistry();     for(var key in registry)     {         var entry = $models.getItem(registry[key]);         if (entry && entry.getParentId() == listTcmId)         {            entry.unload();            return true;         }     }     return false; }  /* * This method gets called when an item is opened from list view. node parameter has the information * displayed in the list view as attributes. We are getting cutom data extender column information  * from this xml node and storing it in this class member for returning it from getListItemXmlAttributes method */ MyCompany.Tridion.RTFExtensions.Utilities.setDataFromList = function (node, parentId, timeStamp, itemClicked) {     var p = itemClicked.properties;      if (!timeStamp || timeStamp > itemClicked.getTimeStamp()) {         var tmp;         if (tmp = node.getAttribute('Version')) {             p.versionNumberString = tmp;             p.previousVersion = tmp;         }         if (tmp = node.getAttribute('ModifiedBy')) {             p.modifiedBy = tmp;             p.initialModifierUserName = tmp;         }         if (tmp = node.getAttribute('LockedBy')) {             p.lockedBy = tmp;         }         if (tmp = node.getAttribute('ApprovalStatus')) {             p.approvalStatus = tmp;             p.previousApprovalStatus = tmp;         }         if (tmp = node.getAttribute('PublishDate')) {             p.publishDate = tmp;         }         if (p.customModifiedDate === undefined) {             if (tmp = node.getAttribute('Modified')) {                 p.customModifiedDate = tmp;             }         }     } }  /* * sends the list xml string for the item in the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListItemXmlAttributes = function (customAttributes, listViewObject,attribs) {     var p = listViewObject.properties;     $extUtils.getListViewItemLockedByName(p,listViewObject);      if (customAttributes) {         for (var attr in customAttributes) {             attribs[attr] = customAttributes[attr];         }     }      attribs["Version"] = $extUtils.getListViewItemUpdatedVersion(p,listViewObject);     //modified name has to come after the version update...     $extUtils.getListViewItemModifiedByName(p,listViewObject);     attribs["ApprovalStatus"] = $extUtils.getListViewItemApprovalStatus(p,listViewObject);       attribs["PublishDate"] = $extUtils.getListViewItemPublishDate(p,listViewObject);      //set default values     if (p.versionNumberString != undefined) {         var iResult = p.versionNumberString.localeCompare(p.previousVersion);         if (p.previousVersion === undefined || iResult > 0) {             //it's been updated!             p.previousVersion = p.versionNumberString;             p.previousApprovalStatus = p.approvalStatus;              //also need to update modified date             p.customModifiedDate = $extUtils.getListViewItemUpdatedModifiedDate(p,listViewObject);             p.initialModifierUserName = p.modifiedBy;         }      }     attribs["Modified"] = p.customModifiedDate;     attribs["LockedBy"] = p.lockedBy;     attribs["ModifiedBy"] = p.modifiedBy;  };  /* * This method sets the property of the Revisor owner on the item in the list view. however, if it's not the current user * we have no way to look that up in JS so we have to reload the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemModifiedByName = function (p,listViewObject) {     var p = listViewObject.properties;     var xmlDoc = listViewObject.getXmlDocument();     if (xmlDoc) {         //modifier should always exist...         var modifierId = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Revisor/@xlink:title");         if (modifierId != undefined) {             var u = Tridion.UI.UserSettings.getJsonUserSettings(true);             if (modifierId == u.User.Data.Name) {                 var strDescription = u.User.Data.Description.split('(');                 p.modifiedBy = strDescription[0];                 return;             } else {                 //we're in trouble...                 //let's hope it's the initial modifier we had...                 if (p.previousVersion == p.versionNumberString) {                     //whew...                     p.modifiedBy = p.initialModifierUserName;                     return;                 }                  if (!$extUtils.reloadListView(listViewObject.getOrganizationalItemId())) {                     //hrm. something failed on the reload? not sure what else to do:                     p.modifiedBy = modifierId;                 }             }         } else {             //shouldn't ever happen.             p.modifiedBy = "";             return;         }     }  };  /* * This method sets the property of the lock owner on the item in the list view. however, if it's not the current user * we have no way to look that up in JS so we have to reload the list view. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemLockedByName = function (p,listViewObject) {     var xmlDoc = listViewObject.getXmlDocument();     if (xmlDoc) {         //this will be user id. no sense getting tcmid... can't look it up without async call         var lockedUserId = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:ItemLock/tcm:User/@xlink:title");         if (lockedUserId != undefined) {             //see if it's the current user. most likely...             var u = Tridion.UI.UserSettings.getJsonUserSettings(true);             if (lockedUserId == u.User.Data.Name) {                 var strDescription = u.User.Data.Description.split('(');                 p.lockedBy = strDescription[0];                 return;             }             //it's not the current user. no synch way to do what we want, plus the JS call doesn't get the workflow version anyway. refresh the parent view             if (!$extUtils.reloadListView(listViewObject.getOrganizationalItemId())) {                 //hrm. something failed on the reload? not sure what else to do:                 p.lockedBy = lockedUserId;             }         } else {             //clear it out since there's no lock owner             p.lockedBy = "";         }     } };  /* * Gets the ApprovalStatus from the item * This makes absolutely no sense... but for some reason the approval status gets wiped out when this method * enters. so I had to use a "previous approval status" variable to maintain it. no idea why. I don't see anything * else that should be touching it... but clearly something clears it out. */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemApprovalStatus = function (p,listViewObject) {     //check if the item has actually been modified.     if (p.versionNumberString != p.previousVersion) {         var xmlDoc = listViewObject.getXmlDocument();         if (xmlDoc) {             p.approvalStatus = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:Data/tcm:ApprovalStatus/@xlink:title");         }     } else {         p.approvalStatus = p.previousApprovalStatus;     }     if (p.approvalStatus === undefined || p.approvalStatus.toUpperCase() == 'UNAPPROVED') {         var foo = p.approvalStatus;         p.approvalStatus = 'WIP';     }     return p.approvalStatus; };   /* * Gets the PublishDate from the item list view */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemPublishDate = function (p,listViewObject) {     //modification won't alter publish date.     var p = listViewObject.properties;     return p.publishDate; };   /* *   get the modified date for the workflow version, overwrite OOB since that uses last major version */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemUpdatedModifiedDate = function (p,listViewObject) {     var xmlDoc = listViewObject.getXmlDocument();     var modDate = $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:RevisionDate");     return modDate; }   /* * Gets the updated Version information from the item */ MyCompany.Tridion.RTFExtensions.Utilities.getListViewItemUpdatedVersion = function (p,listViewObject) {     var p = listViewObject.properties;     var xmlDoc = listViewObject.getXmlDocument();     var newVersionString = undefined;     if (xmlDoc) {         newVersionString = String.format("{0}.{1}", $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Version"), $xml.getInnerText(xmlDoc, "/tcm:*/tcm:Info/tcm:VersionInfo/tcm:Revision"));     }     if (newVersionString != undefined) {         //want to ensure we're getting a LATER version than we had (because it will try to load the non-workflow version afterwards...         var iResult = newVersionString.localeCompare(p.previousVersion);         if (p.previousVersion === undefined || iResult > 0) {             p.versionNumberString = newVersionString;         } else {             p.versionNumberString = p.previousVersion;         }     } else {         p.versionNumberString = p.previousVersion;     }     return p.versionNumberString; };    function launchPopup(winURL, winName, winFeatures, winObj) {     // this will hold our opened window     var theWin;     // first check to see if the window already exists     if (winObj != null) {         // the window has already been created, but did the user close it?         // if so, then reopen it. Otherwise make it the active window.         if (!winObj.closed) {             winObj.focus();             return winObj;         }         // otherwise fall through to the code below to re-open the window     }     // if we get here, then the window hasn't been created yet, or it     // was closed by the user.     theWin = window.open(winURL, winName, winFeatures);     return theWin; }  var $extUtils = MyCompany.Tridion.RTFExtensions.Utilities; 
like image 586
Warner Soditus Avatar asked Jun 22 '12 22:06

Warner Soditus


1 Answers

[Exception... "Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsIWebProgress.DOMWindow]"

This means that there was no window assigned to the nsIWebProgress object. So it has nowhere to display data.

nsresult: "0x80004002 (NS_NOINTERFACE)" location: "JS frame :: chrome://browser/content/tabbrowser.xml :: :: line 545" data: no]

This is telling you what file is associated with that error. and what line it faulted on.

But the real key is the NS_NOINTERFACE error. Which means the interface has not been registered.

You are using Type.enableInterface(). Is that a custom method you are declaring somewhere else ? I don't see it. You might want to change that to .registerInterface()

See this link Type Class and Type.registerInterface()

like image 112
Tech Savant Avatar answered Oct 02 '22 22:10

Tech Savant