',
postMixInProperties: function(){
this.nlsBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Shelf");
this.closeText = this.nlsBundle["shelf_closeDialog"];
this.cancelText = this.nlsBundle["add_content_cancel"];
if(this.cssStateNodes) {
delete this.cssStateNodes.closeButtonNode;
}
this.inherited(arguments);
},
onSubmit: function(){
},
submit: function(){
this.onSubmit();
},
hide: function(){
if(this.domNode) {
// internal hide doesn't check for domNode's existence, which in some cases may be null
// if hide is called after the widget is destroyed (ex. asynchronously)
return this.inherited(arguments);
}
},
cancel: function(){
if(!this._destroyingOnClose) {
this.hide();
if (this.destroyOnClose) {
this._destroyingOnClose = true; // protect from potential recursive loops
this.destroy();
}
}
},
setContent: function(content, title, okText, submitFcn){
dojo.empty(this.contentNode);
if (dojo.isString(content))
content = document.createTextNode(content);
this.contentNode.appendChild(content);
this.titleNode.innerHTML = title || this.titleText;
this.submitNode.value = okText || this.okText;
this.onSubmit = submitFcn || function(){};
this.show();
this.onLoad(); // we reuse the same dialog instance for daisy-chained dialogs, so reload the dialog to reposition and refocus in case it was already open, in which case the show does not do this for us
}
});
}
if(!dojo._hasResource["com.ibm.pb.customize.LotusWaitingDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.customize.LotusWaitingDialog"] = true;
dojo.provide("com.ibm.pb.customize.LotusWaitingDialog");
dojo.declare("com.ibm.pb.customize.LotusWaitingDialog", [com.ibm.pb.customize.LotusDialog], {
spinner: "",
message: "",
destroyOnClose: true,
templateString: '
' +
'
' +
/* the closeButtonNode is needed as an attach point because the base dijit.Dialog requires it */
''+
'
' +
'' +
'${message}' +
'
' +
'
' +
'
',
postMixInProperties: function(){
this.nlsBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Shelf");
this.loadingText = this.nlsBundle["shelf_loading"];
this.message = " " + this.message;
this.inherited(arguments);
},
show: function(){
if (!this.domNode)
return;
var me = this;
// setTimeout(function(){
// if (me.open)
// dijit._underlay.show();
// }, this.duration + 200); // make sure underlay is visible
//cause memory leak (defect 19322), since this is a quick disappear dialog, remove it.
this.inherited(arguments);
}
});
}
if(!dojo._hasResource["com.ibm.pb.extension.contextmenu.ContextMenuAcOperation"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.extension.contextmenu.ContextMenuAcOperation"] = true;
dojo.provide("com.ibm.pb.extension.contextmenu.ContextMenuAcOperation");
dojo.declare("com.ibm.pb.extension.contextmenu.ContextMenuAcOperation", [com.ibm.mashups.enabler.ac.operation.Operation], {
id: "none",
url: "",
sync: true,
roleCheck: "",
finished: null,
allowed: false,
constructor: function(id, url, sync, roleCheck, finished){
if(!com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations) com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations = {};
this.id = id;
this.url = url;
this.sync = sync;
this.roleCheck = roleCheck;
this.finished = finished || function(){};
this._checkForFeed();
},
_checkForFeed: function(){
if(com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations[this.id]) {
if(com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations[this.id][this.roleCheck]) { this.allowed = true; }
else { this.allowed = false; }
this.finished(this);
} else {
this._getXml();
}
},
_getXml: function(){
var me = this,
useString = dojo.isIE || dojo.isOpera || dojo.isFF < 3.5;
dojo.xhrGet ({
url: this.url,
handleAs: (useString) ? "text" : "xml",
sync: this.sync,
load: function(data){
var xml = data;
com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations[me.id] = {};
if(useString){
var menuItems = xml.match(/label="(\w+)"/g);
for(var i in menuItems){
if((typeof menuItems[i]) == "string") {
var label = menuItems[i].substring(7,menuItems[i].length-1);
com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations[me.id][label] = true;
}
}
} else {
var menuItems = xml.querySelectorAll("menuitem");
for(var i in menuItems){
if(menuItems[i].getAttribute){
var label = menuItems[i].getAttribute("label");
com.ibm.pb.extension.contextmenu.ContextMenuAcOperation.allowedOperations[me.id][label] = true;
}
}
}
me._checkForFeed();
}
});
},
isAllowed: function(context){
return this.allowed;
}
});
}
if(!dojo._hasResource['com.ibm.widgets.ResourceSelector']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource['com.ibm.widgets.ResourceSelector'] = true;
dojo.provide('com.ibm.widgets.ResourceSelector');
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dijit.Tooltip");
dojo.require("dojo.i18n");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.TextBox");
dojo.declare('com.ibm.widgets.ResourceSelector',
[dijit._Widget, dijit._Templated],
{
shelfBundle: null,
dialogBundle: null,
blankImg: dojo.moduleUrl("dojo", "resources/blank.gif").toString(),
autofocus: false,
baseUrl: null, // defaults to content handler uri
feedQueryUrl: null, // gets added to baseUrl to produce the full url for feed requests
feedQueryUrlTemplate: null, // only used, if the feed supports search. Before running the xhr request for getting entries,
// will be converted by replacing ${feedSearchParam} in this string
// with the actual search term
feedSupportsSearch: false, // defaults to false, which means the feed url does not have a search term placeholder
feedSearchParam: "", // if set (needs to be a string), defines the search parameter in feedQueryUrl
atomFeed: true, // if false then process a json feed
resourceData: null,
filteredResourceData: null,
selectedResourceId: null,
selectedRow1: null,
selectedRow2: null,
sortResultMult: 1,
entryStartIndex:0, // can be used by subclasses if we need to skip to a certain entry from the feed to start
value: {},
searchResults: null,
wasLastKeyEnter: false,
outerDivClass: "lotusDialog",
showTruncationMessage: false, // if true and nlsTruncationMsg is set, the picker will show a truncation message, if not all results are displayed
connections: [],
_lastUsedFeedQueryUrl: null, // is either feedQueryUrl or a copy of feedQueryUrlTemplate with the template param replaced
templateString: '',
constructor: function() {
this.shelfBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Shelf");
this.dialogBundle = dojo.i18n.getLocalization("com.ibm.bundles", "PageCreatorDialog");
this.nlsSubmitSearch= this.shelfBundle["shelf_submitSearch"];
this.nlsSortLabel = this.dialogBundle["template_dialog_sort_by"];
this.nlsClickToSort = this.dialogBundle["template_dialog_click_to_sort"];
this.nlsClickToSelect = this.dialogBundle["template_dialog_click_to_select"];
this.nlsPersonLabel = this.dialogBundle["resource_selector_updated_by"];
this.nlsNoUser = "";
this.nlsTitle = this.dialogBundle["title"];
this.nlsResourceTableSummary = this.dialogBundle["resource_selector_table_summary"];
this.nlsNoResources = this.dialogBundle["resource_selector_no_resources"];
this.nlsLoading = this.shelfBundle["shelf_loading"];
this.nlsSearchResourcesLabel = this.dialogBundle["resource_selector_search_resources"];
this.nlsSearchNoMatches = this.dialogBundle["template_dialog_search_no_matches"];
this.baseUrl = location.protocol+"//"+location.host + ibmPortalConfig.contentHandlerURI;
},
postCreate: function() {
this.inherited(arguments);
// by default, we use the feedQueryUrl
this._lastUsedFeedQueryUrl = this.feedQueryUrl;
if (this.feedSupportsSearch === true) {
// if we run this method with an empty string, it returns everything (unfiltered result set)
this._loadSearchResults("");
this._populateSearchSelect();
this._initializeSearchIcon();
} else {
this._loadResourceData();
this._populateSearchSelect();
}
},
getAvailableResourcesCount: function(/*Object*/ resData) {
return 0;
},
getMaxResourcesCount: function(/*Object*/ resData) {
return 0;
},
_buildFeedQueryUrlFromSearchTerm: function(/*String*/ searchTerm) {
if (searchTerm === null) {
searchTerm = ""; // ensure type-safety, so we convert null to an empty string
}
if (searchTerm !== "") {
if ((typeof this.feedQueryUrlTemplate == 'string') &&
(this.feedQueryUrlTemplate !== '')) {
if ((typeof this.feedSearchParam == 'string') &&
(this.feedSearchParam !== '')) {
var substJSON = {};
substJSON[this.feedSearchParam] = searchTerm;
this._lastUsedFeedQueryUrl = dojo.string.substitute(this.feedQueryUrlTemplate, substJSON);
} else {
// template URL given, however, no searchParam, so we treat the template URL as a regular URL
this._lastUsedFeedQueryUrl = this.feedQueryUrlTemplate;
}
} else {
// else, use feedQueryUrl
this._lastUsedFeedQueryUrl = this.feedQueryUrl;
}
} else {
// no searchTerm used, load all resources
this._lastUsedFeedQueryUrl = this.feedQueryUrl;
}
},
_hideLoadingDiv: function() {
// summary:
// Adds the 'lotusHidden' class to the progressDIV and as a result hides the loading animation.
// Should be called right after data fetch calls have completed.
//
dojo.addClass(this.progressDIV, 'lotusHidden');
},
_hideTruncationMsgDiv: function() {
// summary:
// Adds the 'lotusHidden' class to the truncationMsgDiv and as a result hides the warning message.
// Should be called right after data fetch calls have completed and no truncation occurred.
//
dojo.addClass(this.truncationMsgDIV, 'lotusHidden');
},
_initializeSearchIcon: function() {
// show the searchIcon right to the search text input field
dojo.removeClass(this.searchIconCell, "lotusHidden");
// attach events to the icon
this.connections.push(dojo.connect(this.searchIconInput, "onclick", this, "_runSearch"));
this.connections.push(dojo.connect(this.searchIconAltLink, "onclick", this, "_runSearch"));
},
_escapeHTML: function (str) {
return str.replace(/&/g,"&").replace(/>/g,">").replace(/ 0) {
this.isViewFiltered = true;
this.filteredResourceData = filteredArray;
this._displayChoices(filteredArray);
}
}
// no id and input box empty means we want to clear the filter
else if (this.isViewFiltered && dojo.byId(this.searchSelect.id).value.length === 0) {
this.isViewFiltered = false;
this.filteredResourceData = null;
this._displayChoices(resData);
this.searchResults = null;
}
}
},
_search_isValid: function() {
// only return false after the user has pressed Enter and there are no matches
// this should result in the no match tooltip being displayed
var rv = true;
if (this.wasLastKeyEnter && this.searchResults && this.searchResults.length === 0) {
rv = false;
}
return rv;
},
_search_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
// capture the results that the search drop down finds from the user entry
this.searchResults = results;
//console.log("_search_openResultList, results size: " + results.length);
},
_search_onKeypress: function(e){
// summary:
// Watch for enter key indicating that search is being submitted.
// The search results should already be captured and it will be used
// to build the filtered array to display
if(e && e.type && e.keyCode && e.keyCode === dojo.keys.ENTER) {
if (this.feedSupportsSearch) {
this._runSearch();
} else {
if (this.searchResults && this.searchResults.length > 0 && this.resourceData !== null){
this._updateSelectedId();
var resData = this.resourceData;
var dropDownResults = this.searchResults;
var filteredArray = [];
var ctr = 0;
dojo.forEach(dropDownResults, function(item) {
var idToMatch = item.value;
var matchArray = dojo.filter(resData, function(resource) {
return (resource.id === idToMatch);
});
if (matchArray && matchArray.length > 0) {
filteredArray[ctr++] = matchArray[0];
}
});
// if we end up with the same array as the original resource data,
// then there is no filtering
if (filteredArray.length === resData.length) {
this.isViewFiltered = false;
this.filteredResourceData = null;
this._displayChoices();
} else if (filteredArray.length > 0) {
this.isViewFiltered = true;
this.filteredResourceData = filteredArray;
this._displayChoices(filteredArray);
}
}
// Test if this was an Enter keypress.
// If it was, then force the search combo box to validate itself
// so that the no match error message is displayed if there are indeed no matches
// (normally validate gets called before this routine which is bad for us).
this.wasLastKeyEnter = false;
if(e && e.type && e.keyCode && e.keyCode === dojo.keys.ENTER ){
this.wasLastKeyEnter = true;
var searchWidget = dijit.byId(this.searchSelect.id);
searchWidget.validate(true);
}
}
}
},
_search_handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
// Override the default to take care of the case where multiple search results are being
// displyed and then the user chooses the empty item in the search drop down. We will
// force things to go back to showing all resources.
this.inherited(arguments);
if (dojo.byId(this.searchSelect.id).value === "" && this.isViewFiltered) {
this._search_onChange(null);
}
},
// bug fix for ComboBox doHighlight, this should be removed when we move beyond dojo 1.4.3
/*
_doHighlight: function(label, find){
// summary:
// Highlights the string entered by the user in the menu. By default this
// highlights the first occurence found. Override this method
// to implement your custom highlighing.
// tags:
// protected
// Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true
var modifiers = modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""), i = this.queryExpr.indexOf("${0}");
var escapedLabel = this._escapeHtml(label);
find = dojo.regexp.escapeString(find); // escape regexp special chars
return this._escapeHtml(label).replace( new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers),'$1');
},
*/
_showLoadingDiv: function() {
// summary:
// Removes 'lotusHidden' class from the progressDIV and as a result shows the loading animation.
// Should be called right before data fetch calls are triggered.
//
dojo.removeClass(this.progressDIV, 'lotusHidden');
// also set the table body which will show any results to aria-live and aria-busy
dijit.setWaiState(this.resourceTableBody, "live", "polite");
dijit.setWaiState(this.resourceTableBody, "busy", "true");
},
_showTruncationMsgDiv: function(/*Integer*/ availableResults, /*Integer*/ maxResults) {
// summary:
// Removes 'lotusHidden' class from the truncationMsgDIV and as a result shows the warning message.
// Should be called right before data fetch calls completed and a truncation of the displayed
// results occurred.
//
// only show truncation msg, if NLS string for the message is available
if (this.nlsTruncationMsg && (this.showTruncationMessage === true)) {
// regenerate truncation message based on the given values
var msg = dojo.string.substitute(this.nlsTruncationMsg, [availableResults, maxResults]);
dojo.attr(this.truncationMsgText, 'innerHTML', this._escapeHTML(msg));
if (this.warningIconClass) {
dojo.addClass(this.truncationMsgIcon, this.warningIconClass);
}
// then show it
dojo.removeClass(this.truncationMsgDIV, 'lotusHidden');
}
},
_loadResourceData: function (/*function*/callback, /*array*/resourceData, /*String*/selectedResourceId) {
// summary:
// Subclasses should override this function to populate the resourceData array
// with the entry information using the following format:
//
// {id:_id, title:_title, description:_description, user:_user, selected:_selected}
// id - unique id of the resource
// title - localized title of the resource
// description - localized description of the resource
// user - any user information associated with the resource (owner, last modifier, etc).
// This gets used with the nlsPersonLabel string in the table row UI for the resource
// selected - a boolean to mark which resource should be currently selected in the UI
//
// When the subclass method is done populating the resourceData array, _loadComplete should be invoked.
//
// The selectedResourceId param may be null or will have the last value set by the user. This
// should be used by the override method to correctly set the selected object in the resourceData array.
//
if (this.resourceData === null) {
// load data for content template page nodes
this.resourceData = [];
// we use synchronous AJAX calls, thus we can put the show/hide code in here
// no need to put it in some callback functions
this._showLoadingDiv();
this._hideTruncationMsgDiv();
// need to fix the query if the baseUrl already contains query parameters
var baseUrlWithoutQuery = this.baseUrl;
var query = "";
var idx = this.baseUrl.indexOf("?");
if (idx > -1){
query = this.baseUrl.substring(idx + 1, this.baseUrl.length);
baseUrlWithoutQuery = this.baseUrl.substring(0, idx);
}
var feedUrl = baseUrlWithoutQuery + this._lastUsedFeedQueryUrl;
if (query.length > 0){
if (feedUrl.indexOf("?") > -1){
feedUrl = feedUrl + "&" + query;
} else {
feedUrl = feedUrl + "?" + query;
}
}
if (this.atomFeed) {
this._getEntriesFromAtomFeed(feedUrl);
}
else {
this._getEntriesFromJsonFeed(feedUrl);
}
// we use synchronous AJAX calls, thus we can put the show/hide code in here
// no need to put it in some callback or deferred functions
this._hideLoadingDiv();
this._loadComplete();
}
},
_loadSearchResults: function(/* String */ searchTerm) {
// summary:
// Runs a get request against the given feed url template and fills in the given searchTerm
// before firing the request to limit results returned.
// searchTerm: String
// The search term. It might depend on the feed, which search terms (wildcard support, etc.) are
// allowed. This method uses it as-is transparently.
this._buildFeedQueryUrlFromSearchTerm(searchTerm);
this._clearResultList(this.resourceTableBody);
this._clearResourceData();
// now we can run regular code, as feedQueryUrl contains the readily built feed URL (including the
// search term)
this._loadResourceData();
// no need to recreate the select in case we have remote search event
//this._populateSearchSelect();
},
// used to examine the links for an atom entry to find the href that matches
_getHref: function(entry, linkSchema, relAttr) {
var rv = null;
if(entry.links !== null && entry.links.length > 0){
var _rel = "related";
if (relAttr) {
_rel = relAttr;
}
for(var x in entry.links){
var _link = entry.links[x];
if(_link.rel && _link.rel == _rel && _link.href && _link.href.indexOf(linkSchema) > -1){
rv = _link.href; //string
break;
}
}
}
return rv;
},
//
_getUserDataForEntry: function(atomIO, entry) {
// summary:
// Used to find the user data associated with an atom entry (like the owner
// of a resource for example).
//
// Subclasses should override this function to return a user dn formatted string
//
return null;
},
_getEntriesFromAtomFeed: function(feedUrl) {
// summary:
// Queries the atom feed and then examines the entries returned to gather the
// title, description, id for a resource. This function will also make a call
// to _getUserDataForEntry on each entry found to determine if there is any
// associated user data. Finally a call is made to _processEntryResultsBeforeStoring
// for subclassess to manipulate the entry before storing the data.
// Subclasses can override these functions to perform specific functions needed
// to handle the atom entries for a particular resource type.
var dataArray = this.resourceData;
var me = this;
var entryStartIndex = this.entryStartIndex;
var atomIO = new dojox.atom.io.Connection(true, true); // sync, preventCache
atomIO.getFeed(feedUrl, function(feed) {
var entries = feed.entries;
// build resourceData with nav model entries
if (entries){
var ctr = 0;
var hasSelectionBeenSet = false;
for (var i = entryStartIndex; i < entries.length; i++){
var entry = entries[i];
//console.log("Located resource: " + entry);
// get title and description
var _title = entry.title.value;
var _description = "";
if (entry.summary) {
_description = entry.summary.value;
}
// get id and test if this entry should be selected in the UI
var _id = entry.id;
var selectedId = this.selectedResourceId;
var _selected = false;
// has a prior selection been made at all?
if (selectedId && selectedId.length > 0 ) {
_selected = (selectedId === _id);
if (_selected) {
hasSelectionBeenSet = true;
}
}
var getUserData = dojo.hitch(me, me._getUserDataForEntry);
var _owner = getUserData(atomIO, entry);
// build data object, give subclasses a chance to modify
var data = {id:_id, title:_title, description:_description, user:_owner, selected:_selected};
var processEntryData = dojo.hitch(me, me._processEntryResultsBeforeStoring);
data = processEntryData(data);
// test if subclass has made the selection
if (!hasSelectionBeenSet && data.selected) {
hasSelectionBeenSet = true;
}
// store the results for this entry
dataArray[ctr++] = data;
}
// if no item was selected, then just default to the first as being selected
if (!hasSelectionBeenSet && dataArray.length > 0) {
dataArray[0].selected = true;
}
}
},
function(error,json){
if(json.xhr.responseText.indexOf("EJQHL0004E") >=0) {
// the current project has expired
alert(me.shelfBundle["project_expired"] || "The current project is no longer available. Click OK to be redirected.");
top.location.reload();
}
});
},
_getEntriesFromJsonFeed: function(feedUrl) {
// summary:
// Queries the JSON feed and then examines the entries returned to gather the
// title, description, id for a resource.
// A call is made to _processEntryResultsBeforeStoring
// for subclassess to manipulate the entry before storing the data.
// Subclasses can override these functions to perform specific functions needed
// to handle the atom entries for a particular resource type.
var dataArray = this.resourceData;
var me = this;
var resourceList = null;
var getResourceHandler = dojo.xhrGet( {
url: feedUrl,
sync: true,
handleAs: "json",
preventCache: true,
load: function(data){
//console.info("Data returned: ",data);
resourceList = data;
},
error: function(error){
console.debug("ResourceSelector _getEntriesFromJsonFeed ERROR");
console.debug(error);
}
});
// resourceList contains the data returned by the server, now we pass that along
// to the getNumXxx methods to figure out whether a truncation of results has
// occurred
var availableResults = this.getAvailableResourcesCount(resourceList);
var maxResults = this.getMaxResourcesCount(resourceList);
if (maxResults > availableResults) {
this._showTruncationMsgDiv(availableResults, maxResults);
} else {
this._hideTruncationMsgDiv();
}
if (resourceList && resourceList.feed) {
var rData = this.resourceData;
var selectedId = this.selectedResourceId;
dojo.forEach (this._getEntriesAsJSON(resourceList.feed), function(entry) {
//console.info("entry: " + entry);
var ctr = dataArray.length;
var _id = entry.id;
var _selected = false;
// has a prior selection been made at all?
if (selectedId && selectedId.length > 0 ) {
_selected = (selectedId === _id);
}
// no, then just default to the first child as being selected
else if (ctr === 0) {
_selected = true;
}
var _title = entry.title.value;
var _description = "";
if (entry.summary) {
_description = entry.summary.value;
}
// get author dn, should be only one in the array from the feed
var dn = null;
dojo.forEach(entry.author, function(author) {
if (author.distinguishedName) {
dn = author.distinguishedName;
}
});
var _type = entry.type;
var data = {id:_id, title:_title, description:_description, user:dn, selected:_selected, type:_type};
var processEntryData = dojo.hitch(me, me._processEntryResultsBeforeStoring);
data = processEntryData(data);
dataArray[ctr] = data;
});
}
},
_getEntriesAsJSON: function(/*Object*/ jsonFeed) {
// summary:
// Subclasses should override this function to
// access each entry in a particular feed's data
// structure
//
// Default format is:
//
// jsonFeed = {
// feed: {
// entry: [array of entries]
//
// }
//
// }
return jsonFeed.entry;
},
_processEntryResultsBeforeStoring: function(data){
// summary:
// Subclasses should override this function if further processing
// is needed on any of the data items for the entry before storing
// in the resourceData array
//
// data - represents one entry found that will be displayed
return data;
},
_stripOffPrefix: function(str, prefix){
// summary:
// Utility function to strip off a prefix on a string like a schema
//
var rv = str;
if (str && prefix) {
var pos = str.indexOf(prefix);
if (pos > -1) {
rv = str.substring(pos + prefix.length);
}
}
return rv;
},
_clearResourceData: function() {
// summary:
// Removes all entries from the resourceData array to allow it being filled with new
// data from a subsequent request
// tags:
// private
this.resourceData = null;
},
_clearResultList: function(/*DomNode*/ parent) {
// summary:
// Removes table rows from the result list, in case there are any
// tags:
// private
// clear out old rows if there
while ( parent.hasChildNodes() ) {
parent.removeChild(parent.firstChild);
}
// hide no resources message div
dojo.addClass(this.noResourcesDIV, "lotusHidden");
},
_createRadioButton: function(attrs, refNode){
// bug fix for dojo - radio buttons must be created with the name attr for IE7
if (dojo.isIE && dojo.isIE < 8) {
var doc = dojo.doc;
if(refNode){
refNode = dojo.byId(refNode);
doc = refNode.ownerDocument;
}
tag = doc.createElement("");
if(attrs){ dojo.attr(tag, attrs); }
if(refNode){ dojo.place(tag, refNode); }
return tag; // DomNode
}
// all other browsers use dojo create
else {
return dojo.create("input", attrs, refNode);
}
},
_loadComplete: function(){
// summary:
// Subclasses should override this function if further processing
// is needed after the resource data has been loaded
//
this._displayChoices();
},
_displayChoices: function(filteredData){
// summary:
// Render the table rows to display each resource.
//
// filteredData - if specified this data array will be used
// for rendering, otherwise the function will
// default to using the resourceData array to
// display all resources
// check if we are in RTL mode
var isRTL = ibmCfg.themeConfig.isRTL;
var resData,
radiobuttons;
if (filteredData) {
resData = filteredData;
}
else {
resData = this.resourceData;
}
if (resData === null || resData.length === 0) {
if (this.feedSupportsSearch === true) {
// if no results were returned at all by the search, display noResults msg.
// this is not necessary in filter-mode, as there, results are only loaded once
// and if nothing is returned, the default 'No results... ' message is still
// shown
// also set the table body which will show any results to aria-live and aria-busy
dijit.removeWaiState(this.resourceTableBody, "live");
dijit.removeWaiState(this.resourceTableBody, "busy");
dojo.removeClass(this.noResourcesDIV, "lotusHidden");
}
return;
}
var parent = this.resourceTableBody;
this._clearResultList(parent);
// sort the resource data by title
var ltRV = -1 * this.sortResultMult;
var gtRV = this.sortResultMult;
resData.sort(function(a, b){
var nameA=a.title.toLowerCase(), nameB=b.title.toLowerCase();
if (nameA < nameB) {//sort string ascending or descending
return ltRV;
}
if (nameA > nameB) {
return gtRV;
}
return 0; //default return value (no sorting)
});
var strClickToSelect = this.nlsClickToSelect;
var strPersonLabel = this.nlsPersonLabel;
var strNoOwner = this.nlsNoUser;
var needLiveTextParsing = false;
var setSelectedRowBackgroundColor = dojo.hitch(this, "_setSelectedRowBackgroundColor");
var hasUserMadeASelection = this.selectedResourceId && this.selectedRow1;
var selectedId = this.selectedResourceId;
var createRadioButton = this._createRadioButton;
var arrTypeLabels = this.nlsTypeLabels;
var tabIdx = 10;
var tr_headers = dojo.create("tr", { style: {display:"none"} }, parent);
var th1 = dojo.create("th", {innerHTML: this.nlsClickToSelect, scope: "col" }, tr_headers);
var th2 = dojo.create("th", {innerHTML: " ", scope: "col"}, tr_headers);
var th3 = dojo.create("th", {innerHTML: this.nlsTitle, scope: "col"}, tr_headers);
// add table rows for each resource found
var _this = this;
dojo.forEach(resData, function(entry, i) {
var div;
var id = entry.id;
var nlsText = entry.title;
var owner = entry.user;
var tr1 = dojo.create("tr", null, parent);
var td1 = dojo.create("td", {className: "lotusFirstCell", style: {width:"16px", paddingLeft:"2px"} }, tr1);
var radio = createRadioButton({type:"radio", title: strClickToSelect, name:"resourceValue", value:id, id:id+"_resource_"+i, className:"lotusCheckbox"}, td1);
_this.connections.push(dojo.connect(radio, "onclick", _this, function(evt) { setSelectedRowBackgroundColor(tr1); })); // add onclick function to each radio button to set the row background color
var td2 = dojo.create("td", {style: {width:"1px", paddingLeft:"0px", paddingRight:"0px", innerHTML:" "} }, tr1);
var td3 = dojo.create("td", null, tr1);
var label = dojo.create("label", {style: {margin:"1px"} }, td3);
dojo.attr(label, "for", id+"_resource_" + i);
var h4 = dojo.create("h4", {"id": id + "_header"}, label);
dojo.create("span", {
dir: isRTL ? "RTL" : "LTR",
innerHTML: _this._escapeHTML(nlsText)
}, h4);
if (entry.type && arrTypeLabels && arrTypeLabels[entry.type]) {
var pos = isRTL ? "first": "last";
dojo.create("span", {
className: "lotusType",
innerHTML: _this._escapeHTML(arrTypeLabels[entry.type])
}, h4, pos);
}
if (owner) {
div = dojo.create("div", {className: "lotusMeta", innerHTML: _this._escapeHTML(strPersonLabel) + " "}, td3);
var strOwner = "";
var strOwnerId = "";
var strOwnerDn = "";
// is owner info just the dn string
if (dojo.isString(owner)) {
strOwner = owner;
if (owner.indexOf("uid=")===0) {
var stopIndex = owner.indexOf(",");
if (stopIndex > 4) {
strOwner = owner.substring(4,stopIndex);
}
}
strOwnerDn = owner;
strOwnerId = entry.ownerId ? entry.ownerId : "";
}
// or is it the full atom entry
else if (dojo.isObject(owner) && owner.getDisplayName) {
strOwner = owner.getDisplayName();
strOwnerId = owner.getID();
strOwnerDn = owner.dn;
}
var personSpan = dojo.create("span", {className: "vcard X-sametime-resolve"}, div);
var personLink = dojo.create("a", {className: "fn lotusPerson hasHover", innerHTML: _this._escapeHTML(strOwner), onClick:"javascript:SemTagMenu.a11y(event);", href:"javascript:void(0);"}, personSpan);
personLink.onmouseover = dojo.hitch(personLink, function(event){
if (!event) {
event = window.event; // IE8 doesn't pass the event as a parameter
}
var target = event.target ? event.target : event.srcElement;
if (target) {
var rect = target.getBoundingClientRect();
var height = rect.height ? rect.height : rect.bottom - rect.top; // IE8 doesn't have a rect height
var offset = window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop;
this._ts_y = Math.floor(rect.top + height + offset); // set a y position based on the event since we are in a scrollable pane
}
});
personLink.onfocus = personLink.onmouseover;
var uoidSpan = dojo.create("span", {className: "userObjectId", style: {display: "none"}, innerHTML: _this._escapeHTML(strOwnerId)}, personSpan);
var uidSpan = dojo.create("span", {className: "uid", style: {display: "none"}, innerHTML: _this._escapeHTML(strOwnerDn)}, personSpan);
needLiveTextParsing = true;
}
else {
div = dojo.create("div", {className: "lotusMeta", innerHTML: _this._escapeHTML(strNoOwner)}, td3);
}
var description = entry.description;
if (description && description !== "") {
dojo.style(td3, "paddingBottom", "0px");
var tr2 = dojo.create("tr", {className: "lotusDetails"}, parent);
var td4 = dojo.create("td", {className: "lotusFirstCell", innerHTML:" " }, tr2);
var td5 = dojo.create("td", {innerHTML:" " }, tr2);
var td6 = dojo.create("td", {className: "lotusLastCell", colSpan:"2", headers: id + "_header" }, tr2);
var descrip = dojo.create("p", {innerHTML:_this._escapeHTML(description) }, td6);
}
// use the selection from the load results
var isThisSelectedRow = entry.selected;
// unless the user has selected something already and we are just repainting after a sort or filter
if (hasUserMadeASelection) {
if (selectedId === entry.id) {
isThisSelectedRow = true;
}
else {
isThisSelectedRow = false;
}
}
if (isThisSelectedRow) {
if (dojo.isIE==7){ // bug in ie7 where "checked" will not persist once added to page or if display:none
dojo.attr(radio, "defaultChecked", "true");
}
dojo.attr(radio, "checked", "true");
// the background color call has to be made here after the description row gets added
setSelectedRowBackgroundColor(tr1);
}
});
// init any person cards that will be displayed
if (needLiveTextParsing) {
var livetextService = com.ibm.mashups.services.ServiceManager.getService(com.ibm.mashups.livetext.ServiceModel.SERVICE_NAME);
dojo.publish(livetextService.tagChanged, [parent]);
// replace findPosition with an update that checks for y position set on our person card
if (typeof SemTagSvcPortal != 'undefined' && SemTagSvcPortal && !SemTagSvcPortal.oldFindPosition) {
SemTagSvcPortal.oldFindPosition = SemTagSvcPortal.findPosition;
SemTagSvcPortal.findPosition = function(obj, rightedge) {
var pos = SemTagSvcPortal.oldFindPosition(obj, rightedge);
if (obj._ts_y) {
pos[1] = obj._ts_y;
}
return pos;
};
}
}
// also set the table body which will show any results to aria-live and aria-busy
dijit.removeWaiState(this.resourceTableBody, "busy");
},
_toggleSort: function() {
var classNames = this.sortLink.className.split(" ");
// change from ascending to descending
if (this.sortResultMult > 0) {
this.sortResultMult = -1;
dojo.html.set(this.sortLinkIndicator, "↓");
classNames[1] = "lotusDescending";
}
else {
this.sortResultMult = 1;
dojo.html.set(this.sortLinkIndicator, "↑");
classNames[1] = "lotusAscending";
}
this.sortLink.className = classNames[0] + " " + classNames[1];
this._updateSelectedId();
var data = null;
if (this.isViewFiltered) {
data = this.filteredResourceData;
}
this._displayChoices(data);
},
_updateSelectedId: function() {
// update currently selected id
if (this.resourceData) {
var selectedId = dojo.formToObject(this.resourceSelectForm).resourceValue;
if (selectedId) {
this.selectedResourceId = selectedId;
}
}
},
_setSelectedRowBackgroundColor: function(newRow) {
// clear the background color on old selected rows
if (this.selectedRow1) {
dojo.style(this.selectedRow1, "backgroundColor", "transparent");
}
if (this.selectedRow2) {
dojo.style(this.selectedRow2, "backgroundColor", "transparent");
}
// set the background on the new selection
dojo.style(newRow, "backgroundColor", com.ibm.widgets.ResourceSelector.SELECTED_ROW_COLOR);
this.selectedRow1 = newRow;
var descriptionTableRow = newRow.nextSibling;
if (descriptionTableRow && dojo.attr(descriptionTableRow, "class") === "lotusDetails") {
dojo.style(descriptionTableRow, "backgroundColor", com.ibm.widgets.ResourceSelector.SELECTED_ROW_COLOR);
this.selectedRow2 = descriptionTableRow;
}
else {
this.selectedRow2 = null;
}
},
submit: function(){
dojo.attr(this.submitDialog, "disabled", "disabled");
this.hide();
this.beforeSubmit();
this.onSubmit();
},
cancel: function(){
this.hide();
},
onChange: function(/*Object*/arg){
},
onComplete: function(){
},
beforeSubmit: function(){
},
getSelection: function() {
// When the user presses the Submit button.
this.value = dojo.formToObject(this.resourceSelectForm);
// lookup the name matching the selected id
var selectedResourceName = "";
var selectedResourceDescription = "";
var selectedResourceType = "";
var selectedId = this.value.resourceValue;
if (this.resourceData && selectedId) {
dojo.forEach(this.resourceData, function(entry, i) {
if (entry.id === selectedId) {
if (entry.title) {
selectedResourceName = entry.title;
}
if (entry.description) {
selectedResourceDescription = entry.description;
}
if (entry.type) {
selectedResourceType = entry.type;
}
}
});
}
this.value.resourceName = selectedResourceName;
this.value.resourceDescription = selectedResourceDescription;
this.value.type = selectedResourceType;
return this.value;
},
layout: function() {
if(this.domNode.style.display != "none") {
/*
* Calling internal API to fix a bug where resizing the viewport
* does not resize the dialog, but simply calls "layout" and should
* also call "_size"
*/
this._size();
}
return this.inherited(arguments);
},
focus: function(){
var searchWidget,
focusNode = null;
// put focus on selected radio input
dojo.query("input", this.domNode).forEach(function(node, index, arr){
if (node.checked) {
focusNode = node;
}
});
// if no selection, then default focus to the close button
if (!focusNode) {
searchWidget = dijit.byId(this.searchSelect.id);
if (searchWidget) {
if (searchWidget.focusNode) {
focusNode = searchWidget.focusNode;
}
}
}
if (focusNode) {
dijit.focus(focusNode);
}
},
destroy: function () {
this.resourceData = null;
dojo.forEach(this.connections, dojo.disconnect);
this.inherited(arguments);
}
}
);
com.ibm.widgets.ResourceSelector.SELECTED_ROW_COLOR = "#f2f9ff";
}
if(!dojo._hasResource['com.ibm.widgets.ResourceSelectDialog']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource['com.ibm.widgets.ResourceSelectDialog'] = true;
dojo.provide('com.ibm.widgets.ResourceSelectDialog');
dojo.require('dijit.Dialog');
dojo.require("dojo.i18n");
dojo.declare('com.ibm.widgets.ResourceSelectDialog',
[dijit.Dialog],
{
// lotusui_id: String
// The ID for the global dijitDialog lotusui related wrapper DIV
// The container needs to be specific to the ResourceSelectDialog, as the labelledby
// aria attribute is specific to this dialog.
lotusui_id: "dijitDialog_lotusui30_ResSlctDlg_container",
// lotusui_class: String
// The lotusui class to assign to the wrapper DIV, if it gets created
lotusui_class: "lotusui30",
shelfBundle: null,
dialogBundle: null,
blankImg: "",
autofocus: false,
resourceData: null,
selectedResourceId: null,
sortResultMult: 1,
value: {},
cancelHandler: null,
templateString: '
',
postMixInProperties: function() {
this.shelfBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Shelf");
this.dialogBundle = dojo.i18n.getLocalization("com.ibm.bundles", "PageCreatorDialog");
this.cancelText = this.shelfBundle["add_content_cancel"];
this.closeText = this.shelfBundle["add_content_close"];
this.okText = this.dialogBundle["resource_select_dialog_select"] || "Select";
this.nlsTitleError = this.shelfBundle["new_feed_enterTitle"];
this.nlsResourceSelectTitle = this.dialogBundle["resource_select_dialog_title"];
},
postCreate: function() {
this.inherited(arguments);
this._populateResourceSelector();
// create lotusui surrounding DIV for this dialog and place this.domNode into it
dojo.place(this.domNode, this._findOrCreateLotusUIDIV(), "last");
var timer = window.setTimeout(dojo.hitch(this, function()
{
if (this.domNode && this.domNode.style.display != "none") {
this.layout();
}
window.clearTimeout(timer);
}), this.duration + 50);
},
_findOrCreateLotusUIDIV: function() {
// summary:
// Tries to find an existing dijit.Dialog lotusui30 container DIV in the current page
// and if it doesn't find one, creates it.
//
// Used to avoid flooding the DomTree with lotusui30 related wrapper DIVs, if dialogs
// are opened and closed many times.
// returns:
// The domNode reference of the found or created dijit.Dialog lotusui30 container DIV
// tags:
// private
var lotusui_div = dojo.byId(this.lotusui_id);
if (!lotusui_div) {
lotusui_div = dojo.create("div", { "id": this.lotusui_id,
"class": this.lotusui_class,
"wairole": "region",
"role": "region"
}, dojo.body());
}
// set wai state in any case (whether we re-use an existing or newly created
// wrapping div) to not break Accessibility
dijit.setWaiState(lotusui_div, "labelledby", this.id + "ResourceSelectDialogTitleSpan_id");
return lotusui_div;
},
_populateResourceSelector: function () {
var aNode = this.resourceSelector;
this.selectorWidget = new com.ibm.widgets.ResourceSelector({
feedQueryUrl: this.feedQueryUrl
},aNode);
},
submit: function(){
dojo.attr(this.submitDialog, "disabled", "disabled");
this.hide();
this.beforeSubmit();
this.onSubmit();
},
setCancelHandler: function(/*function()*/handler) {
this.cancelHandler = handler;
},
cancel: function(){
if(this.cancelHandler && this.cancelHandler != null) {
this.cancelHandler();
}
this.hide();
},
onChange: function(/*Object*/arg){
},
onComplete: function(){
},
beforeSubmit: function(){
},
onSubmit: function() {
this.value = this.selectorWidget.getSelection();
this.onChange(this.value);
},
layout: function() {
if(this.domNode.style.display != "none") {
/*
* Calling internal API to fix a bug where resizing the viewport
* does not resize the dialog, but simply calls "layout" and should
* also call "_size"
*/
this._size();
}
return this.inherited(arguments);
},
focus: function(){
this.resourceSelectError.style.display="none";
this.submitDialog.removeAttribute("disabled");
this.show();
/*
// put focus on selected radio input
var focusNode = null;
dojo.query("input").forEach(function(node, index, arr){
if (node.checked) {
focusNode = node;
}
});
// if no selection, then default focus to the close button
if (!focusNode) {
focusNode = this.closeButtonNode;
}
if (focusNode) {
focusNode.focus();
} */
},
// @OVERRIDE dijit.Dialog.show()
show: function() {
this.inherited(arguments);
// focus first element in the contained selectorWidget after a short delay
setTimeout(dojo.hitch(this.selectorWidget, "focus"), 30);
},
destroy: function () {
this.inherited(arguments);
},
// @OVERRIDE dijit._DialogMixin._getFocusItems()
// Need to fix the buggy method, which does not take passed in domNode into account
// although dijit.Dialog relies on this method to take a domNode as an argument
_getFocusItems: function(/*Node*/ p_domNode){
// summary:
// see dijit._DialogMixin
// tags:
// protected
// Fixed _getFocusItems() method.
// Would also work with a fixed dojo version, so we're forward compatible here.
// store current containerNode reference and replace it with the passed in domNode,
// as current implementation uses 'this.containerNode' as the reference domNode
var oldContainerNode = this.containerNode;
this.containerNode = p_domNode;
// call original method
this.inherited(arguments);
// restore containerNode reference
this.containerNode = oldContainerNode;
}
}
);
}
if(!dojo._hasResource['com.ibm.widgets.TemplateSelectDialog']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource['com.ibm.widgets.TemplateSelectDialog'] = true;
dojo.provide('com.ibm.widgets.TemplateSelectDialog');
dojo.require("dojo.i18n");
dojo.require("dojox.atom.io.model");
dojo.require("dojox.atom.io.Connection");
dojo.declare('com.ibm.widgets.TemplateSelectDialog',
[com.ibm.widgets.ResourceSelectDialog],
{
postMixInProperties: function() {
this.inherited(arguments);
// override the UI dialog strings
this.nlsResourceSelectTitle = this.dialogBundle["page_dialog_select_template"];
this.nlsPersonLabel = this.dialogBundle["template_dialog_owned_by"];
this.nlsNoUser = this.dialogBundle["template_dialog_no_owner"];
this.nlsResourceTableSummary = this.dialogBundle["template_dialog_table_summary"];
this.nlsSearchResourcesLabel = this.dialogBundle["template_dialog_search_templates"];
this.feedQueryUrl = "?uri=nm%3Aoid%3Awps.content.template.root&levels=100";
},
// Override to use our processing methods and strings
_populateResourceSelector: function () {
var aNode = this.resourceSelector;
this.selectorWidget = new com.ibm.widgets.ResourceSelector({
feedQueryUrl: this.feedQueryUrl,
entryStartIndex: 1, // skip over first entry as it should be parent page templates node, we want the rest
_getUserDataForEntry: this._getUserDataForEntry,
_processEntryResultsBeforeStoring: this._processEntryResultsBeforeStoring,
nlsPersonLabel: this.nlsPersonLabel,
nlsNoUser: this.nlsNoUser,
nlsResourceTableSummary: this.nlsResourceTableSummary,
nlsSearchResourcesLabel: this.nlsSearchResourcesLabel
},aNode);
},
// Override to get the owner data associated with a template atom entry
_getUserDataForEntry: function(atomIO, entry) {
var rv = null;
var getHref = this._getHref;
// to get author info, first need to get the content model for this entry
var relAttr = null;
if (dojo.isOpera) {
relAttr = "content";
}
var contentHref = getHref(entry, com.ibm.widgets.TemplateSelectDialog.CONTENT_MODEL_SCHEMA, relAttr);
if (contentHref) {
//contentHref = ibmPortalConfig.contentHandlerURI + contentHref;
// have to use getFeed call here rather than getEntry or it won't work on IE
atomIO.getFeed(contentHref, function(feed) {
var entries = feed.entries;
var contentEntry = entries[0];
// now get the ac resource url
if (dojo.isOpera) {
relAttr = "ac-resource-config";
}
var acResourceHref = getHref(contentEntry, com.ibm.widgets.TemplateSelectDialog.RESOURCE_CONFIG_SCHEMA, relAttr);
if (acResourceHref) {
atomIO.getEntry(acResourceHref, function(accessEntry) {
// see if an owner is specified
if (accessEntry && accessEntry.content && accessEntry.content.value) {
var value = accessEntry.content.value;
var startPos = value.indexOf("ac:DN=\"");
// just grab the dn of the owner
if (startPos > -1) {
startPos += 7;
var stopPos = value.indexOf("\"", startPos);
if (stopPos > startPos) {
rv = value.substring(startPos, stopPos);
}
}
}
});
}
});
}
return rv;
},
// Override to clean up the id data associated with a template atom entry
_processEntryResultsBeforeStoring: function(data){
if (data) {
// get id, strip off schema
var _id = data.id;
data.id = this._stripOffPrefix(_id, com.ibm.widgets.TemplateSelectDialog.NAVIGATION_MODEL_SCHEMA);
// set selection
var selectedId = this.selectedResourceId;
var _selected = false;
// has a prior selection been made at all?
if (selectedId && selectedId.length > 0 && (selectedId === _id)) {
data.selected = true;
}
}
return data;
}
}
);
com.ibm.widgets.TemplateSelectDialog.NAVIGATION_MODEL_SCHEMA = "nm:oid:";
com.ibm.widgets.TemplateSelectDialog.CONTENT_MODEL_SCHEMA = "cm/oid:";
com.ibm.widgets.TemplateSelectDialog.RESOURCE_CONFIG_SCHEMA = "resourceconfig:oid:";
}
if(!dojo._hasResource["com.ibm.mm.builder.systemwidget.TemplateSelectDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.mm.builder.systemwidget.TemplateSelectDialog"] = true;
dojo.provide("com.ibm.mm.builder.systemwidget.TemplateSelectDialog");
dojo.declare("com.ibm.mm.builder.systemwidget.TemplateSelectDialog", [com.ibm.pb.iwidget.iWidgetBase], {
controller: null,
onLoad: function() {
var mname = "onLoad", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.wid = "_"+this.iContext.widgetId+"_";
var attrMix = this.getItemSetValues([
"controller" , // Object
]);
this.convertMapTypes(attrMix, ["controller"], "Object");
dojo.mixin(this, attrMix);
this.model = this.controller.getTreeModel();
this.nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
this.nsm = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
lgr.exiting(mname, arguments);
},
onUnload: function() {
this._cleanupInternalWidget();
},
_cleanupInternalWidget: function() {
if(this.widget) {
if(this._changeConnection) {
dojo.disconnect(this._changeConnection);
}
this.widget.destroy();
}
},
_initInternalWidget: function() {
var me = this;
this._cleanupInternalWidget();
this.widget = new com.ibm.widgets.TemplateSelectDialog({
selectedResourceId: this._selectedTemplateId
}, this.iContext.getElementById(this.wid + "contents"));
this._changeConnection = dojo.connect(this.widget, "onChange", this, "_onChange");
this.widget.startup();
},
_onChange: function(value) {
var mname = "_onChange", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var payload = {};
payload.sourceWidget = this._sourceId;
payload.value = value;
com.ibm.mashups.services.ServiceManager.getService("eventService").fireEvent(this._sourceId, "onTemplateSelectChanged", value, null, this.iContext.widgetId);
lgr.exiting(mname, arguments);
},
onTemplateSelect: function(iEvent) {
var mname = "onTemplateSelect", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(this.widget && this.widget.open) { return; }
this._sourceId = iEvent.source;
this._selectedTemplateId = iEvent.payload;
if (!this.widget) {
this._initInternalWidget();
}
// only show the widget if a selected template id is passed in
if (iEvent.payload !== "") {
this.widget.focus(); // show the widget
}
else {
// otherwise the widget fetches the data to populate itself and
// signals back the default id is by calling _onChange
// without the dialog ever displaying
this.widget.onSubmit();
}
lgr.exiting(mname, arguments);
}
});
}
if(!dojo._hasResource['com.ibm.widgets.NewPageDialog']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource['com.ibm.widgets.NewPageDialog'] = true;
dojo.provide('com.ibm.widgets.NewPageDialog');
dojo.require('dijit.Dialog');
dojo.require("dojo.i18n");
dojo.declare('com.ibm.widgets.NewPageDialog',
[dijit.Dialog],
{
// lotusui_id: String
// The ID for the global dijitDialog lotusui related wrapper DIV
// The container needs to be specific to the ResourceSelectDialog, as the labelledby
// aria attribute is specific to this dialog.
lotusui_id: "dijitDialog_lotusui30_NewPageDlg_container",
// lotusui_class: String
// The lotusui class to assign to the wrapper DIV, if it gets created
lotusui_class: "lotusui30",
shelfBundle: null,
dialogBundle: null,
blankImg: "",
autofocus: false,
showMakePrivate: true,
showFriendlyURL: true,
showPageTemplate: false,
templateHasContentMapping: false,
value: {},
templateString: '
' +
'
' +
'' +
'
' +
'
',
postMixInProperties: function() {
// fix for Dojo 1.6 bug that attempts to add an empty content parameter that effectively
// clears the contents of our containerNode even though the template defines some
//this.showPageTemplate = false;
delete this.content;
if(this.params) {
delete this.params.content;
}
if(this.cssStateNodes) {
delete this.cssStateNodes.closeButtonNode;
}
this.shelfBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Shelf");
this.dialogBundle = dojo.i18n.getLocalization("com.ibm.bundles", "PageCreatorDialog");
this.cancelText = this.shelfBundle["add_content_cancel"];
this.closeText = this.shelfBundle["add_content_close"];
this.okText = this.dialogBundle["create"];
this.nlsPageTitle = this.dialogBundle["page_dialog_page_name"];
this.nlsTitleError = this.shelfBundle["new_feed_enterTitle"];
this.nlsFriendlyURL = this.dialogBundle["page_dialog_friendly_url_name"];
this.nlsMakePrivate = this.dialogBundle["page_dialog_make_private"];
this.titleText = this.dialogBundle["page_dialog_create_page"];
this.nlsPageTemplate = this.dialogBundle["page_dialog_page_template"];
this.nlsPageTemplateLabel = this.dialogBundle["page_dialog_page_template_label"];
this.nlsNoTemplate = this.dialogBundle["page_dialog_no_template"];
this.nlsDefault = this.dialogBundle["page_dialog_default"];
this.nlsChange = this.dialogBundle["page_dialog_change"];
this.nlsFriendlyUrlRequiredError = this.dialogBundle["page_dialog_friendly_url_required_error"];
this.nlsFriendlyUrlModifiedWarning = this.dialogBundle["page_dialog_friendly_url_modified_warning"];
this.inherited(arguments);
},
postCreate: function() {
this.inherited(arguments);
if (!this.showMakePrivate) { dojo.destroy(this.divPrivate); delete this.divPrivate; }
this.connect(this.typingNode, "onkeyup", function(){
if (this.typingNode.value != "") {
this.newPageError.style.display="none";
}
});
this.connect(this.typingNode, "onkeypress", dojo.hitch(this, function(event) {
if (event.keyCode==dojo.keys.ENTER) {
this.submit();
}
}));
if (this.showFriendlyURL){
this.connect(this.typingNode, "onkeyup", function(){
this.filterFriendlyURL(this.typingNode.value);
});
this.connect(this.typingNode, "onblur", function(){
this.filterFriendlyURL(this.typingNode.value);
});
} else {
dojo.destroy(this.divFriendlyURL);
delete this.divFriendlyURL;
}
if (this.showPageTemplate) {
this.connect(this.showHideTemplateNode, "onclick", this.fireEventToTemplateSelectDialog);
}
else {
dojo.destroy(this.divPageTemplate);
delete this.divPageTemplate;
}
// create lotusui surrounding DIV for this dialog and place this.domNode into it
dojo.place(this.domNode, this._findOrCreateLotusUIDIV(), "last");
},
_findOrCreateLotusUIDIV: function() {
// summary:
// Tries to find an existing dijit.Dialog lotusui30 container DIV in the current page
// and if it doesn't find one, creates it.
//
// Used to avoid flooding the DomTree with lotusui30 related wrapper DIVs, if dialogs
// are opened and closed many times.
// returns:
// The domNode reference of the found or created dijit.Dialog lotusui30 container DIV
// tags:
// private
var lotusui_div = dojo.byId(this.lotusui_id);
if (!lotusui_div) {
lotusui_div = dojo.create("div", { "id": this.lotusui_id,
"class": this.lotusui_class,
"wairole": "region",
"role": "region"
}, dojo.body());
}
// set wai state in any case (whether we re-use an existing or newly created
// wrapping div) to not break Accessibility
dijit.setWaiState(lotusui_div, "labelledby", this.id + "NewPageDialogTitleSpan_id");
return lotusui_div;
},
fireEventToTemplateSelectDialog: function () {
// summary:
// When the Template Select dialog is called the first time, it will initialize itself
// and fire back the value of the default template. On subsequent calls, the dialog will
// display itself and send back the id of the selected template.
if(this.showPageTemplate){
var widgetModel = com.ibm.mashups.iwidget.model.Factory.getGlobalWidgetModel();
com.ibm.mashups.services.ServiceManager.getService("eventService").fireEvent("templateSelect", "onTemplateSelect", this.templateSelect.options[0].value, null, "newPage");
}
},
_escapeHTML: function (str) {
return str.replace(/&/g,"&").replace(/>/g,">").replace(/= 256) {
return cwm.E_PAGE_UTIL_INVALID_NAME_LENGTH_0;
}
var match = ibmConfig[com.ibm.mashups.enabler.services.ConfigConstants.BUILDER_TITLE_FILTER_REGEXP];
if (match) {
if (title.match(match)) {
return cwm.E_PAGE_UTIL_INVALID_NAME_CHAR_0;
}
}
return null;
},
submit: function(){
var pagename = this.typingNode.value.replace(/<(?:\/?).+?>/g,""); // remove tags to protect against XSS
this.typingNode.value = pagename;
var titleError = this._validatePageName(pagename);
if(titleError) {
this.newPageError.innerHTML = titleError;
this.newPageError.style.display = "block";
return;
}
if (this.showFriendlyURL && this.showPageTemplate && this.templateHasContentMapping && !this.newPageFriendlyURL.value) {
this.newPageError.innerHTML = this.nlsFriendlyUrlRequiredError;
this.newPageError.style.display = "block";
this.newPageFriendlyURL.focus();
return;
}
if (this.showFriendlyURL && this.filterFriendlyURL(this.newPageFriendlyURL.value, true)) {
this.newPageError.innerHTML = this.nlsFriendlyUrlModifiedWarning;
this.newPageError.style.display = "block";
this.newPageFriendlyURL.focus();
return;
}
dojo.attr(this.submitDialog, "disabled", "disabled");
this.hide();
this.beforeSubmit();
//bug 12089, fix multi click to create page multi times.
var self = this;
setTimeout(function(){
self.onSubmit();
}, this.duration * 2); // time needed for create dialog to hide and waiting dialog to appear);
},
cancel: function(){
if(!this._beingDestroyed){
this.hide();
}
},
onChange: function(/*Object*/arg){
},
onComplete: function(){
},
beforeSubmit: function(){
},
onSubmit: function() {
if (ibmCfg.themeConfig.launchEditModeForNewPages) {
com.ibm.pb.control.RenderingController.getController().launchEditModeForNewPage = true;
}
// When the user presses the Submit button.
this.value = dojo.formToObject(this.newPageForm);
// if user does not have editor rights on parent page, they have no choice
// and are always making private pages so we need to set the parameter
if (!this.value["private"] && !this.showMakePrivate && this.canMakePrivate) {
this.value["private"]="on";
}
this.value.onComplete = this.onComplete;
this.onChange(this.value);
},
layout: function() {
if(this.domNode.style.display != "none") {
/*
* Calling internal API to fix a bug where resizing the viewport
* does not resize the dialog, but simply calls "layout" and should
* also call "_size"
*/
this._size();
}
return this.inherited(arguments);
},
focus: function(){
this.newPageError.style.display = "none";
if(this.showMakePrivate){
this.makePrivate.checked = false;
}
this.typingNode.value = "";
if(this.showFriendlyURL){
this.newPageFriendlyURL.value = "";
}
this.submitDialog.removeAttribute("disabled");
this.show();
this.focusNode.focus();
if(this.showPageTemplate){this.fireEventToTemplateSelectDialog();} // get the default template value
},
filterFriendlyURL: function(/*String*/textToFilter, /*boolean*/updateOnlyIfFilterNeeded) {
// summary: filters the given text into something more acceptable for the friendly url.
// textToFilter: text for the filter to run on.
// return true if a character had to be changed
var rv = false;
var friendly = textToFilter.replace(/[!\*\'\(\);:@&=+$,\/?%#\[\]\s]/g,'-');
if (friendly !== textToFilter) {
rv = true;
}
if (rv || !updateOnlyIfFilterNeeded) {
this.newPageFriendlyURL.value = friendly;
}
return rv;
},
destroy: function () {
this.inherited(arguments);
}
}
);
}
if(!dojo._hasResource["com.ibm.pb.customize.enabler.ChangeStyleController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.customize.enabler.ChangeStyleController"] = true;
dojo.provide("com.ibm.pb.customize.enabler.ChangeStyleController");
com.ibm.pb.customize.enabler.ChangeStyleController = {
current: "", // the style currently selected on the shelf
currentSet: "", // the style currently set on the page
url: "", // url to the current stylesheet
navModel: null, // enabler navigation model
dirty: false, // true if there are changes pending
started: false, // true if the widget is started up
refresh: false, // true if a page refresh is required to show saved changes
styleMetadataKey: "colorPalette",
urlPrefix: ibmCfg.themeConfig.themeRootURI + "/",
layoutParser: com.ibm.pb.layout.LayoutParser,
startup: function(){
// summary: sets up variables and UI
this.logger.entering("startup");
this.current = this.currentSet; // the currently selected style is one set for the page
this.started = true; // this widget is now started up
this.setupUI(); // set up the Change Style UI
if(!this.navModel) { this.navModel = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel(); }
this.logger.exiting("startup");
},
makeDirty: function(/*bool*/change){
// summary: changes the dirty attribute
// change: value to assign to the dirty attribute
this.logger.entering("makeDirty",[change]);
this.dirty = change;
this.logger.exiting("makeDirty",[change]);
},
processChange: function(/*Object*/args){
// summary: used as an event handler for when a user clicks on an item
// args: {id:id of the item clicked}
this.logger.entering("processChange",[args]);
this.apply(args);
this.logger.exiting("processChange",[args]);
},
apply: function(/*Object*/args){
// summary: applies a change associated with a selected item to the page
// args: {id:id of the item clicked}
this.logger.entering("apply",[args]);
if(args.id != this.current) { // return if no change has been made from the current selection
if(args.id == this.currentSet) { this.makeDirty(false); } // Change Style is no longer dirty if the selection is the same as on the server
else if(this.dirty === false) { this.makeDirty(true); } // else make Change Style dirty if it is not already
this.current = args.id; // set current to the given id
this.url = args.url; // set the current url
this._switchStylesheet(this.current,this.url); // change the stylesheet on the client
}
com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().setDirty(true);
this.logger.exiting("apply",[args]);
},
undo: function(){
// summary: reverts any changes made
this.logger.entering("undo");
if(this.started) { this.apply({id:this.currentSet}); }
this.logger.exiting("undo");
},
beforeSubmit: function(/*Object*/args){
// summary: Called before submit and returns a Deferred object which should be used
// to get notified when the controller is ready to be submitted. Attach a callback
// to this Deferred to call the controller's submit function instead of calling
// it directly.
this.logger.entering("beforeSubmit",[args]);
var dfd = new dojo.Deferred();
dfd.callback();
this.logger.exiting("beforeSubmit",[args]);
return dfd;
},
submit: function(/*Object*/args){
// summary: saves any pending changes
// args: {onComplete:function to call when submission is done, onError:function to call if submission fails}
this.logger.entering("submit",[args]);
if(!this.dirty) {
// if Change Style is not dirty, call the onComplete handler and return
if(args.onComplete) { args.onComplete(); }
this.logger.exiting("submit",[args]);
return;
}
var pageId = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getID();
if(pageId) {
var pageRef = this.navModel.find(pageId);
if(pageRef){
pageRef.setFinishedCallback(dojo.hitch(this, "_setMetadata"), args);
pageRef.start(false);
} else {
this.logger.severe("submit","Cannot get page node object from Navigation Model",[args]);
if(args.onError) { args.onError(); }
}
} else {
this.logger.severe("submit","Cannot get current page id",[args]);
if(args.onError) { args.onError(); }
}
this.logger.exiting("submit",[args]);
},
/***********************************************/
/* Helper functions */
/***********************************************/
_setMetadata: function(page, status, args){
// summary: receives the current page and from that sets the layout metadata
// page: current page object
// status: HTTP status returned from request to retrieve page
// args: from submit()
this.logger.entering("_setMetadata",[page,status,args]);
if(status == "200") {
var content = page.getContent().start();
if(this.url && content.confirmSetMetaData(this.styleMetadataKey,this.url)){
if(this.url) content.setMetaData(this.styleMetadataKey,this.url); // set the style metadata to the currently selected
} else if(!this.url && content.confirmRemoveMetaData(this.styleMetadataKey)){
content.removeMetaData(this.styleMetadataKey);
} else {
this.logger.severe("submit","User does not have permission to set or delete page metadata",[args]);
if(args.onError) { args.onError(); }
}
this.makeDirty(false); // make Change Style not dirty
this.currentSet = this.current; // the set style is now the same as the current
if(args.onComplete) { args.onComplete(); }
} else {
this.logger.severe("submit","Cannot find the page object for the current node",[args]);
if(args.onError) { args.onError(); }
}
this.logger.exiting("_setMetadata",[page,status,args]);
},
_switchStylesheet: function(title,url){
// summary: switch to the stylesheet with the given title
var i, currLink, found = false;
for(i = 0; (currLink = document.getElementsByTagName("link")[i]); i++) {
// if the link is a perferred stylesheet
if(currLink.getAttribute("rel").indexOf("style") >= 0 && currLink.getAttribute("title")) {
// if the chosen theme is found
if(currLink.getAttribute("title") == title) {
currLink.disabled = false;
if(dojo.isWebKit){
// workaround a WebKit bug that doesn't enable an alt stylesheet on the first try
currLink.disabled = true;
currLink.disabled = false;
}
found = true;
}
else { currLink.disabled = true; }
}
}
if(dojo.isWebKit) {
// workaround the Safari 3.1 and Chrome bug where an alternate stylesheet can never be turned on via js
// https://discussions.apple.com/thread/3215084?start=0&tstart=0
if(found) {
if(!this.webkitLink) {
this.webkitLink = dojo.create("link",{href:this.urlPrefix+url,type:"text/css",rel:"stylesheet"});
document.getElementsByTagName("head")[0].appendChild(this.webkitLink);
} else {
this.webkitLink.href = this.urlPrefix + url;
}
} else if (!url && this.webkitLink) {
document.getElementsByTagName("head")[0].removeChild(this.webkitLink);
this.webkitLink = null;
}
}
if(!found && url) {
this._loadCss(url,title,true,true);
this._switchStylesheet(title);
}
},
_loadCss: function(path, title, alternate, disabled){
if(dojo.isIE || window.ActiveXObject !== undefined){
var link = document.createElement("link");
link.setAttribute("disabled",disabled);
if(title) { link.title = title; }
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
link.setAttribute("type","text/css");
link.setAttribute("rel",(alternate)?"alternate stylesheet":"stylesheet");
link.setAttribute("href",this.urlPrefix+path);
link.setAttribute("media","screen");
} else {
var link = dojo.create("link",{type:"text/css",rel:(alternate)?"alternate stylesheet":"stylesheet",href:this.urlPrefix+path,media:"screen",disabled:disabled});
if(title) { link.title = title; }
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
}
};
}
if(!dojo._hasResource["com.ibm.pb.control.RenderingController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.control.RenderingController"] = true;
dojo.provide("com.ibm.pb.control.RenderingController");
dojo.require("dojo.io.script");
// not an iWidget, but uses the iWidget base for convenient provision of member variables
dojo.declare("com.ibm.pb.control.RenderingController", com.ibm.pb.iwidget.iWidgetBase, {
MINIMIZE_CLASS: "ibm-minimized",
MAXIMIZE_CLASS: "ibm-maximized",
HIDDEN_CONTAINER_NAME: "ibmHiddenWidgets",
PRERENDER_BUFFER_ID: "ibmPreRenderBuffer",
MAXIMIZE_BUFFER_ID: "ibmMaximizeBuffer",
MAXIMIZE_PLACEHOLDER_ID: "ibmMaximizePlaceHolder",
STYLE_METADATA: "colorPalette",
INITIAL_STYLE_ID: "initial",
PAGE_STYLE_METADATA: "pageStyle",
PAGE_STYLE_ID: "ibmPageStyleLink",
widgetAccessor: null,
navStateModel: null,
maximizeBuffer: null,
preRenderBuffer: null,
layoutContainers: null,
// ID of the DOM node containing CSS for handling window states
wStylesNodeID: "layout-wstate-styles",
wStylesTemplate: [
".component-control{",
"width: 0 !important;",
"height: 0 !important;",
"position: absolute;",
"top: -9999px;",
"z-index: -1;",
"}",
".id-${id}{",
"width: 100% !important;",
"height: 100% !important;",
"position: static;",
"top: 0px;",
"z-index: 0;",
"}",
".component-container{",
"height: 100% !important;",
"width: 100% !important;",
"margin: 0 !important;",
"padding: 0 !important;",
"}"].join(""),
activeElement: null,
layoutParser: com.ibm.pb.layout.LayoutParser,
modeWidgets: {},
constructor: function(){
var lgr = this.LOGGER, mname = "constructor";
lgr.entering(mname, arguments);
this.navStateModel = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
this.navModel = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
this.evtSvc.subscribeEvent(this.iWidgetConstants.CHANGE_WIDGETWINDOWSTATE, this, this.onWidgetWindowStateChange);
this.evtSvc.subscribeEvent("com.ibm.mashups.builder.preRenderProcess", this, this.onPreRenderProcess);
this.evtSvc.subscribeEvent("com.ibm.mashups.builder.layoutRefresh", this, this.onLayoutRefresh);
this.configService = com.ibm.mashups.services.ServiceManager.getService(com.ibm.mashups.enabler.services.ConfigService.SERVICE_NAME);
this.layoutContainers = dojo.byId("layoutContainers");
// TODO: Why are the widgets not parsed when outside lotusFrame? Issue with lotusMain usage is if client does not include it in their theme.
this.preRenderBuffer = dojo.create("div", {id: this.PRERENDER_BUFFER_ID, style:{position: "absolute", top: "-9999px"} }, dojo.byId("lotusMain"), "last");
this.layoutContainersDefaultY = parseInt(dojo.coords(this.layoutContainers).y);
this.wStylesNode = dojo.byId(this.wStylesNodeID);
this.doCheckNewPage();
lgr.exiting(mname, arguments);
},
boostrapPreRenderProcess: function(){
// summary: used at bootstrap to process window states before rendering layout
var mname="boostrapPreRenderProcess", lgr = this.LOGGER;
lgr.entering(mname, arguments);
try {
/* START test for non-content node */
var pageId = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getID();
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
var page = nm.find(pageId).start();
if(page && page.getNavigationElementType() == com.ibm.mashups.enabler.navigation.Constants.NAVIGATION_LABEL) {
var defaultLabelContent = this.configService.getValue("labelDefaultRuntimeContent");
if(defaultLabelContent) {
if(dojo.isFunction(defaultLabelContent)) {
defaultLabelContent = defaultLabelContent(pageId);
}
this.layoutContainers.innerHTML = defaultLabelContent;
this.layoutContainers.className = "ibmLayoutContainers";
lgr.exiting(mname, arguments);
return;
}
} /* END test for non-content node */
/* Normal content page handling */
this._setActiveElement();
this.processControls(this.layoutContainers,true);
dojo.removeClass(this.layoutContainers, "ibmLayoutContainersHidden");
//page.primeServerRuntimeContent(this.layoutContainers); // skip priming for now
if(this.activeElement){
this._setActiveElementFocus();
}
} catch (e) {
console.log(e)
}
lgr.exiting(mname, arguments);
},
onPreRenderProcess: function(iEvent){
// summary: used during page switches to process window states before rendering layout
var mname="onPreRenderProcess", lgr = this.LOGGER;
lgr.entering(mname, arguments);
//this._setActiveElement(); has errors and halts execution in IE
this.preRenderBuffer.innerHTML = iEvent.markup;
var pageId = this.runtimeModel.getCurrentPage().getID();
var page = this.navModel.find(pageId).start();
// ************************************************
// * THIS ACTIVATES PRIMING *
// * YOU CAN DEACTIVATE IT IN THE CONFIGURATION *
if(ibmConfig["com.ibm.mashups.priming.enabled"] &&
page.getNavigationElementType() == com.ibm.mashups.enabler.navigation.Constants.NAVIGATION_PAGE &&
!iEvent.id &&
this.runtimeModel.getCurrentPage().getPageMode() == com.ibm.mashups.enabler.model.state.PageModeAccessor.VIEW){
// Priming is enabled, the page is a regular navigation node and we are doing a full layout refresh and we are in view mode
console.info("activating Optimus Prime, savior of performance and killer of the Requesticons!");
page.primeServerRuntimeContent(this.preRenderBuffer);
}
// * END PRIMING ACTIVATION *
// *************************************************
this.processControls(this.preRenderBuffer,!iEvent.id);
if(this.activeElement){
this._setActiveElementFocus();
}
var transitionName = page.getMetaData('transition');
var transitionFn = null;
if (ibmCfg && ibmCfg.themeConfig && ibmCfg.themeConfig.transitions){
if (transitionName){
transitionFn = ibmCfg.themeConfig.transitions[transitionName];
} else {
transitionFn = ibmCfg.themeConfig.transitions[ibmCfg.themeConfig.transitions.fallback];
}
}
this.evtSvc.broadcastEvent("com.ibm.mashups.builder.preRenderComplete", { "id": iEvent.id, "markupDivId": this.PRERENDER_BUFFER_ID, "fn": transitionFn} );
this.doChangeStyle();
this.doCheckNewPage();
lgr.exiting(mname, arguments);
},
processControls: function(node,addMaxBuffer){
// summary: after markup has been set in pre-render buffer,
// the controls are processed
// node: the node that contains the layout controls,
// all OOB cases it is the pre-render buffer
// addMaxBuffer: true if the maximize buffer should be
// created inside the given node
// will be false when refreshing only a single
// container or control
var mname="processControls", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var controls = new Array();
var widgetAccessor = null;
var pid = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getID();
var layoutAccessor = com.ibm.mashups.enabler.model.state.AccessorFactory.getLayoutAccessor(this.navStateModel, pid);
var navstateTemplateUrl = layoutAccessor.getTemplateURL();
// if there is no Navstate template URL
// or if it is different from the Instance template URL
// then don't apply the widget size, they are invalid
var honorNavStateWidgetSizes = false;
if (navstateTemplateUrl) {
// get the page instance layout template url
var navNode = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel().find(pid).start(true);
var content = navNode.getContent().start(true);
var instanceTemplateUrl = content.getMetaData("com.ibm.portal.layout.template.ref");
honorNavStateWidgetSizes = (navstateTemplateUrl == instanceTemplateUrl);
}
// clean the maximizeBuffer since we're processing fresh controls
// reuse it when we refresh a single control (change skin, etc)
if(this.maximizeBuffer && addMaxBuffer) {
dojo.destroy(this.maximizeBuffer);
}
// create a new maximizeBuffer, hide it completely, and put it at the end of the container node we're processing
// that way anything that's inside the maximizeBuffer will be included in any processing by other components
// such as a live text invocation against the node we're processing
if(addMaxBuffer) {
this.maximizeBuffer = dojo.create("div", {id: this.MAXIMIZE_BUFFER_ID, style:{position: "absolute", top: "-9999px"} }, dojo.byId("lotusMain"), "last");
}
// restore the layoutContainers height if set by maximize
if (this.layoutContainers.style.height.length > 0) {
this.layoutContainers.style.height = "";
}
// disconnect the onresize event if it is connected
if (this.onBrowserResizeHandler) {
dojo.disconnect(this.onBrowserResizeHandler);
}
// gather window states of the controls
dojo.forEach(
dojo.query(".component-control", node),
function(control){
var cid = this.layoutParser.extractID(control);
var id = cid; // we can assume that window ID and control ID are always the same, even in live preview
widgetAccessor = com.ibm.mashups.enabler.model.state.AccessorFactory.getWidgetAccessor(this.navStateModel, id);
controls.push({node: control, id: id, state: widgetAccessor.getWindowState(), size: widgetAccessor.getSize()});
},
this);
// process widget size
if (honorNavStateWidgetSizes) {
dojo.forEach(
controls,
function(control){
if(control.size){
this._processWidgetSize(control.node, control.size);
}
},
this);
}
// process minimized controls
dojo.forEach(
controls,
function(control){
if(control.state == "minimize"){
this._processMinimize(control.node);
}
},
this);
// process a maximized control
dojo.forEach(
controls,
function(control){
if(control.state == "maximize"){
this._processMaximize(control.node, node);
}
},
this);
// extend the sandboxed widget height to 100%
dojo.forEach(
dojo.query(".iw-iWidget[sandbox='true']", node),
function(sandboxed){
dojo.addClass(sandboxed,"extendediwiWidget");
}
);
// #17713 memory leak for each DIV:component-control if not applied
// remove the nodes that ref to the dom node that will be removed shortly
for (var i=0, l=controls.length; i 0) {
var count = widgetIds.length,
decrFunc = function() {
if(--count <= 0) {
widgetIds.loaded = true;
cmCbk();
}
};
dojo.forEach(widgetIds, function(widgetId){
this.onLoad(widgetId, decrFunc);
}, com.ibm.pb.iwidget.control);
}
else {
cmCbk();
}
}
if ( editModeLoadedAsynchronously && !this.editModeInitialized ) {
dojo.io.script.get({
url: ibmCfg.themeConfig.editModeJSURL,
checkString: "com.ibm.pb.PB2EditModeLoadedFlag",
load: changeModeWork
});
} else {
changeModeWork();
}
}
},
onLayoutRefresh: function(iEvent){
// summary: restore any widgets so that the layout can refresh normally
// if this is not done, the page area will show the layout twice after the user restores the widget
// layout is refreshed (for example) after adding content or changing the layout of a CSA page
// iEvent: stores these values: [containerId]
if(this.widgetAccessor && this.widgetAccessor.getWindowState() == this.widgetAccessor.MAX) {
this.evtSvc.publishEvent(this.iWidgetConstants.CHANGE_WIDGETWINDOWSTATE, {id: this.widgetAccessor.wid, newWindowState: this.widgetAccessor.NORMAL, oldWindowState: this.widgetAccessor.MAX});
}
},
onWidgetWindowStateChange: function(iEvent){
// summary: process widget window state change (maximize, minimize, restore)
// iEvent: stores these values: [id, newWindowState, oldWindowState]
var mname="onWidgetWindowStateChange", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.widgetAccessor = com.ibm.mashups.enabler.model.state.AccessorFactory.getWidgetAccessor(this.navStateModel, iEvent.id);
this.currentWidget = this.layoutParser.findById(iEvent.controlId);
switch(iEvent.newWindowState){
case this.widgetAccessor.MIN:
this.doMinimize(iEvent);
break;
case this.widgetAccessor.MAX:
this.doMaximize(iEvent);
break;
default:
this.doRestore(iEvent);
}
lgr.exiting(mname, arguments);
},
doMinimize: function(widgetInfo){
var mname="doMinimize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(widgetInfo.oldWindowState == this.widgetAccessor.MAX){
// PMR 20525
// If widget is currently maximized, need to restore widget back to
// its original position prior to minimizing. Otherwise, it will
// minimize on the upper left hand corner.
// this._removeMaximize(this.currentWidget);
this.doRestore(widgetInfo);
}
// APAR #PM88591
// Set window state in proper order when coming from maximized since doRestore is called in if-statement
// NavStateModel, st=maximize, st=normal, st=minimize
this.widgetAccessor.setWindowState(this.widgetAccessor.MIN);
this._processMinimize(this.currentWidget);
// --> Defect 20532
var lc = this._getLayoutControl(this.layoutParser.extractID(this.currentWidget));
var css_style = lc.getMetadata("css-style");
if(this.isFreeform() || css_style) {
this._processMinimizeFreeform(this.currentWidget);
}
// <-- Defect 20532
this._updateNavStateModel(widgetInfo);
lgr.exiting(mname, arguments);
},
doMaximize: function(widgetInfo){
var mname="doMaximize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(widgetInfo.oldWindowState == this.widgetAccessor.MIN){
// Defect 20532
// If widget is currently minimized, need to restore widget back to
// its original position prior to maximizing.
// this._removeMinimize(this.currentWidget);
this.doRestore(widgetInfo);
}
// APAR #PM88591
// Set window state after window has been restored to normal
// then set to maximize
this.widgetAccessor.setWindowState(this.widgetAccessor.MAX);
// need the _setActiveElement/_setActiveElementFocus pair because _processMaximize
// manipulates the DOM (and potentially the focus to fix an IE bug) so that
// the focus is the same after this call
this._setActiveElement();
this._processMaximize(this.currentWidget, this.layoutContainers);
if(this.activeElement){
this._setActiveElementFocus();
}
var lc = this._getLayoutControl(this.layoutParser.extractID(this.currentWidget));
var css_style = lc.getMetadata("css-style");
if(this.isFreeform() || css_style) {
this._processMaximizeFreeform(this.currentWidget);
}
this._updateNavStateModel(widgetInfo);
lgr.exiting(mname, arguments);
},
doRestore: function(widgetInfo){
var mname="doRestore", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.widgetAccessor.setWindowState(this.widgetAccessor.NORMAL);
if(widgetInfo.oldWindowState == this.widgetAccessor.MIN){
this._removeMinimize(this.currentWidget);
}else if(widgetInfo.oldWindowState == this.widgetAccessor.MAX){
this._removeMaximize(this.currentWidget);
}
var lc = this._getLayoutControl(this.layoutParser.extractID(this.currentWidget));
var css_style_backup = lc.getMetadata("css-style-backup");
if(this.isFreeform() || css_style_backup) {
this._processRestoreFreeform(this.currentWidget);
}
this._updateNavStateModel(widgetInfo);
lgr.exiting(mname, arguments);
},
doCheckNewPage: function(){
// summary: go into edit mode automatically when switching to blank pages
var mname="doCheckNewPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(ibmCfg.themeConfig.autoEditNewPages && dojo.query(".component-control",this.layoutContainers).length == 0){
lgr.trace(mname, "Going into edit mode on a blank page");
this.changePageMode("edit");
}
else if (this.launchEditModeForNewPage) {
lgr.trace(mname, "Going into edit mode for newly created page");
this.launchEditModeForNewPage = false;
var me = this;
var currentMode = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getPageMode();
if (currentMode == "view") {
me.changePageMode("edit");
}
}
lgr.exiting(mname, arguments);
},
doChangeStyle: function(id){
// summary: changes the styles on page switched
// id: id of the page
var mname="doChangeStyle", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
var pid = id || com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getID();
var pageRef = nm.find(pid);
pageRef.setFinishedCallback(dojo.hitch(this, function(page){
this._processPageStyle(page.getMetaData(this.PAGE_STYLE_METADATA));
var contentRef = page.getContent();
contentRef.setFinishedCallback(dojo.hitch(this, function(content){
this._findAggregatedColorPalette(nm, content, page);
}));
contentRef.start(false);
}));
pageRef.start(false);
lgr.exiting(mname, arguments);
},
_processPageStyle: function(url){
// summary: changes the assigned page style
// url: url to page stylesheet
var mname="_processPageStyle", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var link = dojo.byId(this.PAGE_STYLE_ID),
head = document.getElementsByTagName("head")[0];
if(link){
head.removeChild(link);
delete link;
}
if(url){
var newLink = dojo.create("link",{type:"text/css",id:this.PAGE_STYLE_ID,rel:"stylesheet",href:url,media:"screen"});
head.appendChild(newLink);
}
lgr.exiting(mname, arguments);
},
_processColorPalette: function(url){
// summary: changes the color palette style from the shelf on the page
// url: url to color palette stylesheet
var mname="_processColorPalette", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var csc = com.ibm.pb.customize.enabler.ChangeStyleController;
var title = this.INITIAL_STYLE_ID;
if(url){
title = url.substring(url.lastIndexOf("/")+1);
}
dojo.hitch(csc, "_switchStylesheet", title, url)();
ibmCfg.portalConfig.aggregatedStyle = url;
dojo.publish("com.ibm.pb.customize.pageStyleChanged",[url]); // alert the customize shelf of the style change
lgr.exiting(mname, arguments);
},
_findAggregatedColorPalette: function(navModel, content, page){
// summary: climbs the navigation model to find the aggregated color palette page style
// navModel: the navigation model
// content: the content of the current page on which the color palette is set, or a label
// page: the page associated with the content, or a label
var style = content.getMetaData(this.STYLE_METADATA);
if(style) {
this._processColorPalette(style);
} else {
var parentDef = navModel.getParent(page);
parentDef.setFinishedCallback( dojo.hitch(this, function(parent){
if(!parent){
this._processColorPalette(null);
} else if(parent.getContent){
var contentDef = parent.getContent();
contentDef.setFinishedCallback( dojo.hitch(this,function(content){
this._findAggregatedColorPalette(navModel, content, parent);
}));
contentDef.start(false);
} else { // parent is not a page so does not have a corresponding content node
this._findAggregatedColorPalette(navModel, parent, parent);
}
}));
parentDef.start(false);
}
},
_processWidgetSize: function(node, size){
if (size.w) {
dojo.style(node, "width", size.w);
}
if (size.h) {
dojo.style(node, "height", size.h);
}
},
_processMinimize: function(currentWidget){
// summary: minimize a widget
// currentWidget: widget to minimize
var mname="_processMinimize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var widgetID = this.layoutParser.extractID(currentWidget);
var minimizeBufferDiv = dojo.byId(widgetID+"_minimizebuffer");
if (!minimizeBufferDiv) {
minimizeBufferDiv = dojo.create("div", {id: widgetID+"_minimizebuffer", style:{display: "none"} }, currentWidget, "first");
}
dojo.style(minimizeBufferDiv, "height", currentWidget.style.height);
dojo.addClass(currentWidget, this.MINIMIZE_CLASS);
dojo.style(currentWidget, "height", null);
lgr.exiting(mname, arguments);
},
_processMaximize: function(currentWidget, container){
// summary: make a widget maximized and
// store other controls in maximized buffer
// currentWidget: widget to maximize
// container: the container to place the maximized widget
var mname="_processMaximize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(this.wStylesNode) {
// using CSS to render layout with maximized portlet
// assume that only one window is maximized at a time; therefore replace node contents completely
var
markup = dojo.string.substitute(this.wStylesTemplate, {
id: this.layoutParser.extractID(currentWidget) || ""
}),
previous = this.wStylesNode;
// delete the old and replace with the new
// this ensures that if the old was generated in the head during bootstrap
// we remove it entirely and create a new one inside a div in the body
this.wStylesNode = dojo.create("div", {
id: this.wStylesNodeID,
style: {
"display":"none"
}
}, dojo.body());
this.wStylesNode.innerHTML = ["
"].join("");
dojo.destroy(previous);
}
else {
var containerHeight = dojo.contentBox(container).h;
// find the maximize buffer in the container
this.maximizeBuffer = dojo.byId(this.MAXIMIZE_BUFFER_ID);
dojo.addClass(currentWidget, this.MAXIMIZE_CLASS);
dojo.create("div", {id: this.MAXIMIZE_PLACEHOLDER_ID, style:{display: "none"} }, currentWidget, "after");
if(dojo.isIE){
// IE has a bug where moving an ancestor node of the current focused node
// causes the focus to mess up on things like text input fields such that
// even though they appear focused, the user cannot type in them.
// The fix is to focus another node before manipulating the DOM of the ancestor.
// In both doMaximize and boostrapPreRenderProcess we save the current focus
// and then set it back afterwards.
container.focus();
}
// #19446 we also need to consider the resizer
var nodes = dojo.query("> DIV", container);
for(var i=0,j=nodes.length; i 0) {
this.maxWidgetStore = {controlHeight: controlHeight+"px", bodyHeight: bodyHeight+"px"};
}
}
var maxControlHeight = containerHeight - 25;
var maxBodyHeight;
if ((bodyHeight > 0) || (!this.maxWidgetStore)) {
maxBodyHeight = maxControlHeight - (controlHeight - bodyHeight);
}
else {
maxBodyHeight = maxControlHeight - (parseInt(this.maxWidgetStore["controlHeight"]) - parseInt(this.maxWidgetStore["bodyHeight"]));
}
currentWidget.style.height = maxControlHeight + "px";
widgetBody.style.height = maxBodyHeight + "px";
var changes = {newHeight: maxBodyHeight,newWidth:bodyBox.w};
var widgetID = this.layoutParser.extractID(currentWidget);
this.evtSvc.publishEvent(com.ibm.mashups.iwidget.Constants.RESIZE_WIDGET + "." + widgetID, changes);
},
_getWindowHeight: function() {
if (dojo.isIE) {
return document.documentElement.offsetHeight || document.body.offsetHeight;
} else {
return window.innerHeight;
}
},
_removeMinimize: function(widget){
var mname="_removeMinimize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var widgetID = this.layoutParser.extractID(widget);
var minimizeBufferDiv = dojo.byId(widgetID+"_minimizebuffer");
if (minimizeBufferDiv) {
dojo.style(widget, "height", minimizeBufferDiv.style.height);
dojo.style(minimizeBufferDiv, "height", null);
}
dojo.removeClass(widget, this.MINIMIZE_CLASS);
lgr.exiting(mname, arguments);
},
_removeMaximize: function(widget){
var mname="_removeMaximize", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// APAR #PM88591
// Allows proper change of state of a maximized portlet back to normal
if (this.wStylesNode) {
previous=this.wStylesNode;
dojo.destroy(previous);
} else {
dojo.removeClass(widget, this.MAXIMIZE_CLASS);
var placeHolder = dojo.byId(this.MAXIMIZE_PLACEHOLDER_ID);
if(placeHolder){
placeHolder.parentNode.replaceChild(widget, placeHolder);
dojo.query(".component-container").forEach(
function (container) {
if (container.getAttribute("name") != this.HIDDEN_CONTAINER_NAME) {
this.layoutContainers.appendChild(container);
}
}, this
);
}
}
// APAR #PM88591
// maxWidgetStore Variable is null when Maximize -> Minimize in Portal
// In Mashups this is not null so code from #18798 is needed
if (this.maxWidgetStore) {
// #18798
this.layoutContainers.style.height = "";
widget.style.height = this.maxWidgetStore["controlHeight"];
var widgetBody = dojo.query(".lotusWidgetBody", widget)[0];
widgetBody.style.height = this.maxWidgetStore["bodyHeight"];
dojo.disconnect(this.onBrowserResizeHandler);
}
lgr.exiting(mname, arguments);
},
_setActiveElement: function(){
if(document.activeElement){
this.activeElement = document.activeElement;
}
},
_setActiveElementFocus: function(){
if (this.activeElement.nodeName == "IFRAME") {
return; // do not try to set focus on an iframe, avoid "Permission denied" errors in IE
}
this.activeElement.focus();
this.activeElement = null;
},
_updateNavStateModel: function(widgetInfo){
var mname="_updateNavStateModel", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.evtSvc.publishEvent(com.ibm.mashups.iwidget.Constants.WIDGET_WINDOWSTATECHANGED, {id: widgetInfo.id, oldWindowState: widgetInfo.oldWindowState, newWindowState: widgetInfo.newWindowState});
this.navStateModel.commit().start();
lgr.exiting(mname, arguments);
},
////////////////// For freeform /////////////////////////////////////
isFreeform: function() {
return dojo.query(".ibmFreeform", this.layoutContainers).length > 0 ? true : false;
},
_getLayoutControl: function(id) {
var pageId = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().getID();
var navModel = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
var pageNode = navModel.find(pageId).start();
var layoutModel = navModel.getLayoutModel(pageNode);
return layoutModel.find(id).start();
},
// Defect 20532
_processMinimizeFreeform: function(currentWidget) {
var mname="_processMinimizeFreeform", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// backup the original style metadata
var widgetID = this.layoutParser.extractID(currentWidget);
var lc = this._getLayoutControl(widgetID);
var css_style = lc.getMetadata("css-style");
// no wrapper-css-style in the latest build
lc.removeMetadata("css-style");
lc.setMetadata("css-style-backup", css_style);
lgr.exiting(mname, arguments);
},
_processMaximizeFreeform: function(currentWidget) {
var mname="_processMaximizeFreeform", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// backup the original style metadata
var widgetID = this.layoutParser.extractID(currentWidget);
var lc = this._getLayoutControl(widgetID);
var css_style = lc.getMetadata("css-style");
// no wrapper-css-style in the latest build
lc.removeMetadata("css-style");
lc.setMetadata("css-style-backup", css_style);
// remove the absolute positions
currentWidget.style.position = "";
currentWidget.style.left = "";
currentWidget.style.top = "";
currentWidget.style.height = "";
currentWidget.style.width = "";
lgr.exiting(mname, arguments);
},
_processRestoreFreeform: function(currentWidget) {
var mname="_processRestoreFreeform", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// restore the original style metadata
var widgetID = this.layoutParser.extractID(currentWidget);
var lc = this._getLayoutControl(widgetID);
var css_style = lc.getMetadata("css-style-backup");
lc.removeMetadata("css-style-backup");
lc.setMetadata("css-style", css_style);
if (css_style) {
// restore the original style to dom node
if(this.isFreeform())
dojo.style(currentWidget, "position", "absolute");
var left = this._extractStyle(css_style, "left");
if (left)
dojo.style(currentWidget, "left", left);
var top = this._extractStyle(css_style, "top");
if (top)
dojo.style(currentWidget, "top", top);
var height = this._extractStyle(css_style, "height");
if (height)
dojo.style(currentWidget, "height", height);
var width = this._extractStyle(css_style, "width");
if (width)
dojo.style(currentWidget, "width", width);
}
lgr.exiting(mname, arguments);
},
_extractStyle: function(styleString, styleName) {
var start = styleString.indexOf(styleName);
if(start > -1) {
var end = styleString.indexOf(";", start);
var style2 = styleString.substring(start+styleName.length+1, end); // eg. height: 123px;
return dojo.trim(style2);
} else {
return null;
}
}
////////////////// For freeform /////////////////////////////////////
});
(function(){
var controller = null;
com.ibm.pb.control.RenderingController.getController = function() {
if(!controller) {
controller = new com.ibm.pb.control.RenderingController();
}
return controller;
};
})();
}
if(!dojo._hasResource["com.ibm.lang.DeferredQueue"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.lang.DeferredQueue"] = true;
/*
* @author allenbj
*/
dojo.provide("com.ibm.lang.DeferredQueue");
dojo.declare("com.ibm.lang.DeferredQueue",
null,
{
constructor: function(/*Deferred?*/ def) {
this.curDef = def;
this.firstDef = def;
},
_addCallbacks: function(/*Deferred*/ source, /*Deferred*/ target) {
source.addCallbacks(
function(res){target.callback(res); return res;}, // callback
dojo.hitch(this, function(err){ // errback
try{
if(!err._raised) {
this.raiseError(err); // in case raiseError fails... we still guarantee all callbacks
err._raised = true;
}
}catch(err2){}
target.callback(err);
return err;
})
);
},
addBefore: function(/*Deferred*/ def) {
// summary: Inserts a Deferred into the front of the queue which will fire the
// Deferred that is currently in the front of the queue when it calls back.
// Allows preprocessing or delaying of this DeferredQueue's firing.
// Note, if the queue has already fired, this will cause an error when the
// def argument callsback.
if(!this.firstDef) this.firstDef = def;
else {
var oldFirst = this.firstDef;
this.firstDef = def;
this._addCallbacks(def, oldFirst);
}
},
add: function(/*Deferred*/ def) {
// summary: Adds a deferred to the queue which will be fired as a callback
// to the previous deferred in the queue. If this is the first deferred
// to be added to the queue, firing it will start the queue.
if(!this.firstDef) this.firstDef = def;
if(this.curDef) {
var oldCur = this.curDef;
this.curDef = def;
this._addCallbacks(oldCur, def);
}
else {
this.curDef = def;
}
return this;
},
fire: function(res) {
// summary: Starts the queue by firing the first deferred in the queue
// passing the argument to this function to the callback function of
// the first deferred.
// res: Anything
if(this.firstDef) this.firstDef.callback(res);
return this;
},
raiseError: function(err) {
// summary: Called whenever one of the Deferreds in the queue fires its errback.
// If an error is raised once by this and then a subsequent Deferred is errbacked
// with the exact same error, it will not be raised again. However, if the next
// Deferred throws or returns a new error, that will be raised only once itself.
// This allows any errors to be raised once and only once without losing any of them.
// NOOP by default, so override this or connect to it to provide implementation.
},
destroy: function() {
delete this.firstDef;
delete this.curDef;
delete this.raiseError;
}
}
);
}
if(!dojo._hasResource["com.ibm.data._NotificationHelper"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.data._NotificationHelper"] = true;
dojo.provide( "com.ibm.data._NotificationHelper" );
dojo.declare( "com.ibm.data._NotificationHelper",
null,
{
/********************************/
/** **/
/** **/
/** dojo.data.api.Notification **/
/** **/
/** **/
/********************************/
onDelete: function(/* Item */ deletedItem) {
// summary: See dojo.data.api.Notification.onDelete()
return deletedItem;
},
onNew: function(/* Item */ newItem, /* Object */ parentInfo) {
// summary: See dojo.data.api.Notification.onNew()
return {newItem: newItem, parentInfo: parentInfo};
},
onSet: function(/* Item */ item, /*String*/ attribute, /*Object | Array*/ oldValue, /*Object | Array*/ newValue) {
// summary: See dojo.data.api.Notification.onSet()
return {item: item, attribute: attribute, oldValue: oldValue, newValue: newValue};
}
}
);
}
if(!dojo._hasResource["com.ibm.data.EnablerModelStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.data.EnablerModelStore"] = true;
dojo.provide("com.ibm.data.EnablerModelStore");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.declare("com.ibm.data.EnablerModelStore",
com.ibm.data._NotificationHelper,{
// itemClass: String the class used to represent items of this store
itemClass: "com.ibm.mm.enabler.navigation.NavigationNodeImpl",
_isItemCreated: false,
_isDirty: false,
rootNode: null,
globalPage: null,
globalPageInSpace: null,
constructor: function(){
this.navigationUtil = com.ibm.mm.builder.utils.navigationUtil;
this.pageUtil = com.ibm.mm.builder.utils.pageUtil;
this.spaceUtil = com.ibm.mm.builder.utils.spaceUtil;
var root = this.getRootNode();
this.rootNode = root;
},
getRootNode: function(){
var pid = null;
var currentPage = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage();
var items = [];
if(!currentPage){
var spaceId = this.spaceUtil.getCurrentSpaceId();
pid = spaceId ? this.pageUtil.getFirstPageInSpace(spaceId) : this.pageUtil.getFirstRootPageId();
} else {
pid = currentPage.getID();
}
if(!pid) return null;
//update current page id and space id
currentPage.setID(pid);
var spaceId = this.spaceUtil.getSpaceIdByPageId(pid);
if (spaceId !== this.spaceUtil.getCurrentSpaceId()) {
this.spaceUtil.setSpaceId(spaceId);
}
//try to build model array
var navModel = this.navigationUtil.getNavigationModel();
var currentModel = navModel.find(pid).start();
var rootId = this.navigationUtil.getNavigationRootNodeId();
var currentSpaceRootId = this.navigationUtil.getNavigationRootNodeId(this.spaceUtil.getCurrentSpaceId());
//Loop to root to build the menuModelArrays array that holds all the models of the item that need to be rendered
while(currentModel && currentModel.getID() !== rootId && currentModel.getID() !== currentSpaceRootId) {
items.push(currentModel);
currentModel = navModel.getParent(currentModel.getID()).start();
}
return items[items.length - 1];
},
getFeatures: function(){
return {'dojo.data.api.Read':true, 'dojo.data.api.Write':true, 'dojo.data.api.Identity':'id', "dojo.data.api.Notification": true };
},
/********************************/
/** **/
/** **/
/** dojo.data.api.Read **/
/** **/
/** **/
/********************************/
getValue: function( /* item */ item, /* attribute-name-string */ attribute,
/* value? */ defaultValue){
var values = this.getValues(item, attribute);
return (values.length > 0)?values[0]:defaultValue;
},
getValues: function(/* item */ item, /* attribute-name-string */ attribute){
var values = null;
switch(attribute) {
case "id":
values = [item.getID()];
break;
case "title":
/* only needed in standalone mashups
if (this.rootNode == item) values = ["Content Root"];
else*/ if (item.title) values = [item.title];
else values = [this.pageUtil.getUnescapedPageTitle(item.getID())];
break;
case "description":
values = [this.pageUtil.getPageDescription(item.getID())];
break;
case "type":
values = item.type;
break;
case "parent":
if (this.globalPage && item.openPageId && item.pageLoadedSpaceId===com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceId()){
// to support global page, open the faked new item under current parent
if (dojo.cookie(com.ibm.mm.builder.constant.cookieKey_previous_pid)){
var lastNonGlobalPageId = dojo.cookie(com.ibm.mm.builder.constant.cookieKey_previous_pid);
var lastPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(lastNonGlobalPageId);
var _navModel = this.navigationUtil.getNavigationModel();
//TODO: need to update the logic here.
var parent = _navModel.getParent(lastPage.getID()).start();
values = [parent];
}else{
console.log("Error: previous_pid in cookie is missing!");
}
}else{
var _navModel = this.navigationUtil.getNavigationModel();
var parent = _navModel.getParent(item.getID()).start();
values = [parent];
}
break;
case "parentId":
var _navModel = this.navigationUtil.getNavigationModel();
var parent = _navModel.getParent(item.getID()).start();
var parentId = parent ? parent.getID() : null;
values = [parentId];
break;
case "children":
var _navModel = this.navigationUtil.getNavigationModel();
var childrenIter = _navModel.getChildren(item);
var children = [];
while (childrenIter.hasNext()) {
var child = childrenIter.next();
var isVisible = com.ibm.mm.builder.utils.pageUtil.isVisiable(child);
if(isVisible){ children.push(child); }
}
// support global page
if (this.globalPage && this.globalPageInSpace===com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceId()){
children.push(this.globalPage);
}
values = children;
break;
case "hasChildren":
if(com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceNode() == item){ return false; }
var _navModel = this.navigationUtil.getNavigationModel();
values = [_navModel.hasChildren(item)];
break;
default:
values = null;
}
values = (values && dojo.isArray(values)) ? values : [values];
return values;
},
getAttributes: function(/* item */ item){
return ["id", "title", "description", "type", "parent", "parentId", "children", "hasChildren"];
},
hasAttribute: function( /* item */ item, /* attribute-name-string */ attribute){
return !!(this.getValue(item, attribute));
},
containsValue: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ value){
return this.getValue(item, attribute) == value;
},
isItem: function(/* anything */ something){
//returns page node id if it is indeed an item
return something.declaredClass == "com.ibm.mm.enabler.navigation.NavigationNodeImpl" && something.getID();
},
isItemLoaded: function(/* Object */ something) {
// summary: All valid items in this data store are loaded all of the time as there
// is no support currently for stubs. Therefore, this is effectively the same
// as isItem.
return this.isItem(something) && something.loaded;
},
loadItem: function(/* Object */ keywordArgs){
// summary: All valid items in this data store are loaded all of the time as there
// is no support currently for stubs. Therefore, this function is a no-op.
},
getLabel: function(/* item */ item){
return this.getValue(item, "title");
},
getLabelAttributes: function(/* item */ item){
return ["title"];
},
fetch: function(/* Object */ keywordArgs){
if(!keywordArgs) keywordArgs = {};
var me = this;
keywordArgs.aborted = false;
if(!keywordArgs.scope) keywordArgs.scope = dojo.global;
var query = keywordArgs.query;
var items = [];
var _navModel = this.navigationUtil.getNavigationModel();
if(query === null) {
items.push(this.rootNode);
} else {
var spaceUtil = com.ibm.mm.builder.utils.spaceUtil;
var pid = query.uri;
if(!pid){
var spaceId = spaceUtil.getCurrentSpaceId();
pid = spaceId ? this.pageUtil.getFirstPageInSpace(spaceId) : this.pageUtil.getFirstRootPageId();
}
//if current page still is null, this means no page exists.
if(pid) {
if(com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceId() == pid){
// if navigating to a space with no pages, manually set up the selection path to the
// space root and content root, otherwise getChildren will fail
items.push(com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceNode());
items.push(this.navigationUtil.getNavigationRootNode());
}else{
var currentPage = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage();
currentPage.setID(pid);
var spaceId = spaceUtil.getSpaceIdByPageId(pid);
if (spaceId !== spaceUtil.getCurrentSpaceId()) {
spaceUtil.setSpaceId(spaceId);
}
var navModel = this.navigationUtil.getNavigationModel();
var currentModel = navModel.find(pid).start();
//Loop to root to build the menuModelArrays array that holds all the models of the item that need to be rendered
while(currentModel) {
items.push(currentModel);
currentModel = navModel.getParent(currentModel.getID()).start();
}
}
}
}
items = this.processFetchedItems(items, keywordArgs);
//TODO: implement getResultSize
if(keywordArgs.onBegin) keywordArgs.onBegin.call(keywordArgs.scope, this.getResultSize(items.root, keywordArgs, items), keywordArgs);
if(keywordArgs.onItem) {
for(var i = 0; i < items.length; i++) {
if(keywordArgs.aborted) return;
keywordArgs.onItem.call(keywordArgs.scope, items[i], keywordArgs);
}
}
if(keywordArgs.onComplete) {
// call onComplete with items array if onItem wasn't specified, otherwise
// call it with null
if(keywordArgs.aborted) return;
if(!keywordArgs.onItem) keywordArgs.onComplete.call(keywordArgs.scope, items, keywordArgs);
else keywordArgs.onComplete.call(keywordArgs.scope, null, keywordArgs);
}
},
processFetchedItems: function(items, keywordArgs){
// do nothing
return items;
},
getRootItem: function(){
return this.rootNode;
},
/********************************/
/** **/
/** **/
/** dojo.data.api.Identity **/
/** **/
/** **/
/********************************/
getIdentity: function(/* item */ item){
return this.getValue(item, "id");
},
getIdentityAttributes: function(/* item */ item){
return ["id"];
},
fetchItemByIdentity: function(/* object */ keywordArgs){
var node = this.pageUtil.getPageNode(getkeywordArgs.identify);
node = node ? node : null;
if(keywordArgs.onItem){
if(!keywordArgs.scope) keywordArgs.scope = dojo.global;
keywordArgs.onItem.call(keywordArgs.scope, node);
}
},
/********************************/
/** **/
/** **/
/** dojo.data.api.Write **/
/** **/
/** **/
/********************************/
deleteItem: function(/* item */ item){
// summary:
// Deletes an item from the store.
//
// item:
// The item to delete.
//
// exceptions:
// Throws an exception if the argument *item* is not an item
// (if store.isItem(item) returns false).
// example:
// | var success = store.deleteItem(kermit);
return false; // boolean
},
setValue: function( /* item */ item,
/* string */ attribute,
/* almost anything */ value){
// summary:
// Sets the value of an attribute on an item.
// Replaces any previous value or values.
//
// item:
// The item to modify.
// attribute:
// The attribute of the item to change represented as a string name.
// value:
// The value to assign to the item.
var lc = com.ibm.mashups.enabler.context.Factory.getLocalizedContext();
switch(attribute) {
case "id":
item.setID(value);
break;
case "title":
item.setTitle(value, lc.getLocale(item) || ibmConfig.locale);
break;
case "description":
item.setDescription(item, lc.getLocale(item) || ibmConfig.locale);
break;
case "type":
item.type = value;
break;
case "parent":
// TODO?
break;
case "parentId":
// TODO?
break;
case "children":
// TODO?
break;
case "hasChildren":
// TODO?
break;
case "position":
var _navModel = com.ibm.mm.builder.utils.navigationUtil.getNavigationModel();
_navModel.insert(item, value.newParent, value.next);
item.loaded = false;
item.created = true;
if(value.oldParent == value.newParent){
this.onSet(item, attribute, value.oldParent, value.next);
}else if(value.next){
this.onSet(item, "parent_next", value.oldParent, value.next);
}else{
this.onSet(item, "parent", value.oldParent, value.newParent);
}
break;
}
},
newItem: function(/* Object? */ keywordArgs, /*Object?*/ parentInfo){
// summary:
//
var title = keywordArgs.label;
var utils = com.ibm.mm.builder.utils;
var _navModel = utils.navigationUtil.getNavigationModel();
var newPage;
if (keywordArgs.openPageId){
// load an existing page as an new item
newPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(keywordArgs.openPageId);
newPage.loaded = false;
newPage.created = false;
newPage.openPageId = keywordArgs.openPageId;
newPage.pageLoadedSpaceId = keywordArgs.pageLoadedSpaceId;
newPage.onCreate = function(){};
this.globalPageInSpace = newPage.pageLoadedSpaceId;
this.globalPage = newPage;
}else{
newPage = _navModel.create(null);
newPage.setTitle(title, dojo.locale);
newPage.setTitle(title, ibmConfig["default.locale"]);
var themeId = utils.themeUtil.getThemeId(parentInfo.parent.getID());
if (!utils.themeUtil.getThemeModel().find(themeId).start()){
themeId = utils.themeUtil.getDefaultThemeId();
}
newPage.setTheme(themeId);
newPage.title = title;
newPage.loaded = false;
newPage.created = false;
newPage.onCreate = function(){};
_navModel.insert(newPage, parentInfo.parent, null);
// create layout
var lm = _navModel.getLayoutModel(newPage.getID());
var lmRoot = lm.create();
lm.insert(lmRoot);
// set empty fragment
lmRoot.setFragment(" ");
}
this.onNew(newPage, parentInfo);
this._isItemCreated = true;
return newPage;
},
isCreated: function(item) {
return !!item.created;
},
addOnCreate: function(item, callback) {
if(this.isCreated(item)) {
callback(item);
}
else {
if(!item.onCreateDefQueue) {
item.onCreateDefQueue = new com.ibm.lang.DeferredQueue(new dojo.Deferred());
}
item.onCreateDefQueue.add((new dojo.Deferred()).addCallback(callback));
}
},
_fireCreated: function(item) {
if(item.onCreateDefQueue) {
// TODO: open a global page twice will lead an exception.
try{
item.onCreateDefQueue.fire(item);
}catch(ex){
console.log(ex);
}
}
},
save: function(/* object */ keywordArgs){
// summary:
var utils = com.ibm.mm.builder.utils;
var _navModel = utils.navigationUtil.getNavigationModel();
this.keywordArgs = keywordArgs;
if (this.keywordArgs.openPageId){
// just open an existing page, no need to save the page node.
var newPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(this.keywordArgs.openPageId);
if(this._isItemCreated){
// create new items
this.keywordArgs = keywordArgs;
this.keywordArgs.item.onCreate();
this.keywordArgs.item.created = true;
this.keywordArgs.item.setID(newPage.getID());
this._fireCreated(this.keywordArgs.item);
this.onSaveComplete();
this._isItemCreated = false;
if(this.keywordArgs.onComplete) this.keywordArgs.onComplete(this.keywordArgs);
}
}else{
if(this._isItemCreated){
// create new items
this.keywordArgs = keywordArgs;
this.keywordArgs.item.onCreate();
var deferred = _navModel.commit();
deferred.addFinishedCallback( dojo.hitch(this, function(node){
this.keywordArgs.item.created = true;
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
es.broadcastEvent("com.ibm.mashups.builder.pageCreated", node.getID());
this.keywordArgs.item.setID(node.getID());
this._fireCreated(this.keywordArgs.item);
this.onSaveComplete();
this._isItemCreated = false;
if(this.keywordArgs.onComplete) this.keywordArgs.onComplete(this.keywordArgs);
}));
deferred.start(false);
}
if(this._isDirty){
// update dirty items
_navModel.commit().start(false);
this._isDirty = false;
if(keywordArgs.onComplete) keywordArgs.onComplete(keywordArgs);
}
}
},
revert: function(){
// summary:
// Discards any unsaved changes.
// description:
// Discards any unsaved changes.
this._isItemCreated = false;
this._isDirty = false;
return false; // boolean
},
onSaveComplete: function(args) {
// summary: Callers can attach listeners to this function to get notified when a save operation
// on this store has received its last response from the server for all write operations.
// This is called before callback handlers to the save function itself are called but after
// all the responses for the requests to the server have returned.
}
});
}
if(!dojo._hasResource["com.ibm.data.DataTreeModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.data.DataTreeModel"] = true;
dojo.provide( "com.ibm.data.DataTreeModel" );
// This module provides the API for a data model that corresponds to any data set that contains
// parent-child relationships that can be represented as a tree. It's exactly the same as the
// model API that's used by dijit.Tree with some functions already implemented for ease of use.
// As a result, any implementation of this API can be used as the model to a dijit.Tree widget
// or any other widget that uses a data model as its backend service provider. This data API
// also adds some additional constraints and extension points that implementations should support
// in addition to the model API that's used by dijit.Tree, but by no means breaks the API or
// deviates from the required functions of the dijit model API. One such addition is the
// support for additional query parameters that can be specified when instantiating a model
// that are always appended to any request to the server for data. This allows particular instances
// of a data model to include metadata information that would not otherwise be included by certain
// data services that support it.
dojo.declare( "com.ibm.data.DataTreeModel",
null,
{
// store: The dojo.data.Read/Write implementation
store: null,
// query: The query used to retrieve the root item for this model
query: null,
// root: The root item of this model
root: null,
// addQueryParams: Object additional query parameters that should be appended
// to any request for items from the back end. Is useful for getting
// additional information such as metadata for each item from a data service
// that provides it.
addQueryParams: null,
constructor: function(args) {
dojo.mixin(this, args);
if(!this.addQueryParams) this.addQueryParams = {};
},
destroy: function() {
// summary: destroys this object, releasing connections to the store
},
reset: function() {
// summary: Resets the root of this model to null.
this.root = null;
},
// =======================================================================
// Methods for traversing hierarchy
getRoot: function(onItem, onError){
// summary:
// Calls onItem with the root item for the tree, possibly a fabricated item.
// Any request for data that is sent to the server should also include
// the request parameters in addQueryParams.
// Throws exception on error.
},
mayHaveChildren: function(/*Object*/ item){
// summary:
// Tells if an item has or may have children. Implementing logic here
// avoids showing +/- expando icon for nodes that we know don't have children.
// (For efficiency reasons we may not want to check if an element actually
// has children until user clicks the expando node)
},
getChildren: function(/*Object*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
// summary:
// Calls onComplete() with array of child items of given parent item, all loaded.
// Any request for data that is sent to the server should also include
// the request parameters in addQueryParams.
// Throws exception on error.
},
// =======================================================================
// Inspecting items
getIdentity: function(/* item */ item){
// summary: returns identity for an item
return this.store.getIdentity(item);
},
getLabel: function(/*dojo.data.Item*/ item){
// summary: get the label for an item
return this.store.getLabel(item);
},
getParent: function(/*dojo.data.Item*/ item) {
// summary: returns the parent item of this item argument
},
// =======================================================================
// Write interface
newItem: function(/* Object? */ args, /*Item?*/ parent){
// summary
// Creates a new item. See dojo.data.api.Write for details on args.
},
pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Item*/ nextSibling, /*Boolean?*/ extra){
// summary:
// Move an item from one parent item to another or to another position under the same parent.
// Used in drag & drop.
// childItem: Item to move.
// oldParentItem: Previous parent of item being moved.
// newParentItem: Item that the item being moved was dropped on.
// nextSiblingItem: Item that should become is the next sibling of the dropped item. Null indicates
// dropping at the end of the list of children.
// extra: Boolean flag that can be interpretted however desired by the implementing model. Example
// usages include a copy flag to indicate if the paste operation is a copy, or a flag to indicate
// if the paste operation moves the child under the new item as a new child or next to the
// item it was dropped on as a new sibling.
},
// =======================================================================
// Callbacks
onChange: function(/*dojo.data.Item*/ item){
// summary:
// Callback whenever an item has changed, so that Tree
// can update the label, icon, etc. Note that changes
// to an item's children or parent(s) will trigger an
// onChildrenChange() so you can ignore those changes here.
},
onChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
// summary: Callback to do notifications about new, updated, or deleted items.
},
onTreeChange: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Item*/ nextSiblingItem) {
// summary: Called when the tree model is changed through one of three scenarios.
// 1) An item is moved in the tree model. This can be called
// when an item is reparented or reordered within the same parent. In both
// cases the nextSiblingItem refers to the next sibling of childItem, sharing
// its same newParentItem.
// 2) A new item is inserted into the tree at a given parent. In this case,
// the oldParentItem is null.
// 3) An item is removed from the tree at a given parent. In this case, the
// newParentItem and the nextSiblingItem is null.
// childItem: Item to move.
// oldParentItem: Item old parent of the childItem.
// newParentItem: Item new parent of the childItem. If this is the same as the
// oldParentItem, it indicates that the childItem is being reordered in
// the list of children under the parent.
// nextSiblingItem: Item that is becoming the next sibling of the moved child item.
// Null indicates moving to the end of the list of children.
},
toString: function() {
return "[TreeModel " + this.declaredClass + "]";
}
}
);
}
if(!dojo._hasResource["com.ibm.data.EnablerTreeModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.data.EnablerTreeModel"] = true;
dojo.provide( "com.ibm.data.EnablerTreeModel" );
// This module provides the API for a data model that corresponds to any data set that contains
// parent-child relationships that can be represented as a tree. It's exactly the same as the
// model API that's used by dijit.Tree with some functions already implemented for ease of use.
// As a result, any implementation of this API can be used as the model to a dijit.Tree widget
// or any other widget that uses a data model as its backend service provider. This data API
// also adds some additional constraints and extension points that implementations should support
// in addition to the model API that's used by dijit.Tree, but by no means breaks the API or
// deviates from the required functions of the dijit model API. One such addition is the
// support for additional query parameters that can be specified when instantiating a model
// that are always appended to any request to the server for data. This allows particular instances
// of a data model to include metadata information that would not otherwise be included by certain
// data services that support it.
dojo.declare( "com.ibm.data.EnablerTreeModel",
com.ibm.data.DataTreeModel,
{
// model: The Enabler TreeModel implementation
eModel: null,
// store: The dojo.data.Read/Write implementation
store: null,
// query: The query used to retrieve the root item for this model
query: null,
// root: The root item of this model
root: null,
// addQueryParams: Object additional query parameters that should be appended
// to any request for items from the back end. Is useful for getting
// additional information such as metadata for each item from a data service
// that provides it.
addQueryParams: null,
constructor: function(args) {
dojo.mixin(this, args);
if(!this.addQueryParams) this.addQueryParams = {};
this.connections = [];
if(this.store.getFeatures()["dojo.data.api.Notification"]) {
this.connections.concat([
dojo.connect(this.store, "onNew", this, "_onNew"),
dojo.connect(this.store, "onSet", this, "_onSet"),
dojo.connect(this.store, "onDelete", this, "_onDelete")
]);
}
},
destroy: function() {
// summary: destroys this object, releasing connections to the store
dojo.forEach(this.connections, dojo.disconnect);
},
reset: function() {
// summary: Resets the root of this model to null.
this.root = null;
},
getRoot: function(onItem, onError){
// summary:
// Calls onItem with the root item for the tree, possibly a fabricated item.
// Any request for data that is sent to the server should also include
// the request parameters in addQueryParams.
// Throws exception on error.
this.root = this.store.rootNode;
onItem(this.root);
},
mayHaveChildren: function(/*Object*/ item){
// summary:
// Tells if an item has or may have children. Implementing logic here
// avoids showing +/- expando icon for nodes that we know don't have children.
// (For efficiency reasons we may not want to check if an element actually
// has children until user clicks the expando node)
return this.store.getValue(item, "hasChildren");
},
getChildren: function(/*Object*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
// summary:
// Calls onComplete() with array of child items of given parent item, all loaded.
// Any request for data that is sent to the server should also include
// the request parameters in addQueryParams.
// Throws exception on error.
var store = this.store;
if(this.mayHaveChildren(parentItem)){
parentItem._children = this.store.getValues(parentItem, "children");
if(parentItem._children && parentItem._children.length > 0){
onComplete(parentItem._children);
}else{
//does not have children so return empty array
parentItem._children = null;
onComplete(parentItem._children);
}
}else {
// does not have children so return empty array
parentItem._children = null;
onComplete(parentItem._children);
}
},
// =======================================================================
// Inspecting items
getIdentity: function(/* item */ item){
// summary: returns identity for an item
return this.store.getIdentity(item);
},
getLabel: function(/*dojo.data.Item*/ item){
// summary: get the label for an item
return this.store.getLabel(item);
},
getParent: function(/*dojo.data.Item*/ item) {
// summary: returns the parent item of this item argument
return this.store.getValue(item, "parent");
},
// =======================================================================
// Write interface
newItem: function(/* Object? */ args, /*Item?*/ parent){
// summary
// Creates a new item. See dojo.data.api.Write for details on args.
if(parent.getRootNavigation)
{
parent = com.ibm.mm.builder.utils.navigationUtil.getNavigationRootNode(parent.getID());
}
var newPage = this.store.newItem(args, {parent: parent});
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
if (args.openPageId){
this.store.save({item: newPage, onComplete: args.onComplete, onError: args.onError, scope: args.scope, openPageId:args.openPageId, pageLoadedSpaceId:args.pageLoadedSpaceId});
// to do the real broadcast event thing, broadcast the event and open the global page
es.broadcastEvent("com.ibm.mashups.builder.saveCheck", dojo.hitch(this,function(){
es.broadcastEvents(args.eventsArray || [],args.lastVisitedPage,args.openPageId);
}));
}else{
this.store.save({item: newPage, onComplete: args.onComplete, onError: args.onError, scope: args.scope});
es.broadcastEvent("com.ibm.mashups.builder.saveCheck", dojo.hitch(this,function(){
es.broadcastEvent("com.ibm.mashups.builder.switchPage", this.getIdentity(newPage));
}));
}
return newPage;
},
deleteItem: function(/*Object*/args, /*item*/ item){
// This is a fake delete item method, which only will remove global page.
var parent = this.getParent(item);
// key to set the global page as null, so the parent and children info will back to normal
this.store.globalPage = null;
this._removeChildItem(parent, item, null, dojo.hitch(this, function(){
this.onTreeChange(parent, null, parent);
}));
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
if (args.openPagePayload){
// do not switch to the last visited non-global page, we will open another global page instead.
}else{
// go to last visited non-global page
es.broadcastEvent("com.ibm.mashups.builder.saveCheck", dojo.hitch(this,function(){
es.broadcastEvent("com.ibm.mashups.builder.switchPage", args.lastVisitedPage);
}));
}
},
clearGlobalPageItem:function(/*Object*/args, /*item*/ item){
var parent = this.getParent(item);
this.store.globalPage = null;
this._removeChildItem(parent, item, null, dojo.hitch(this, function(){
this.onTreeChange(parent, null, parent);
}));
},
isCreated: function(/*item*/ item) {
// summary: Indicates whether or not the item has been created on the server and
// the server-generated values were properly applied to the client-side
// object. NOTE: Any client-side modifications to the values of an item for
// which isCreated returns true can potentially modify the server-generated
// values to be out-of-sync with the server.
// Therefore, it's important to note that isCreated merely indicates whether
// or not the client-side item has a server-side resource associated with it,
// and any values that the server generated for the resource (such as a unique
return this.store.isCreated(item);
},
addOnCreate: function(/*item*/ item, /*Function*/ callback) {
// summary: Register callback to be called when the given item is created on the server.
// If the item is already created, this will call the callback immediately.
return this.store.addOnCreate(item, callback);
},
pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ copy, /*Item*/ nextSibling, /*Boolean?*/ extra){
// summary:
// Move an item from one parent item to another or to another position under the same parent.
// Used in drag & drop.
// See dojo.data.api.Write for details on args.
this.store.setValue(childItem, "position", {newParent: newParentItem,
oldParent: oldParentItem,
next: nextSibling});
this.store._isDirty = true;
this.store.save({});
this.store.onSaveComplete();
},
toString: function() {
return "[TreeModel " + this.declaredClass + "]";
},
_onNew: function(item, parentInfo){
this.newPageItem = item;
this.newPageParent = parentInfo.parent;
this._insertChildItem(this.newPageParent, this.newPageItem, null, dojo.hitch(this, function(){
this.onTreeChange(this.newPageItem, null, this.newPageParent);
}));
},
_onDelete: function(item){
},
_onSet: function(/* Item */ item, /*String*/ attribute, /*Object | Array*/ oldValue, /*Object | Array*/ newValue){
if(attribute.indexOf("parent") > -1) {
var newParent = null;
if(attribute == "parent_next"){
newParent = this.store.getValue(item, "parent");
}else{
newParent = newValue;
newValue = null;
}
this._removeChildItem(oldValue, item);
this._insertChildItem(newParent, item, newValue, dojo.hitch(this, function(){
this.onTreeChange(item, oldValue, newParent, newValue);
}));
}else if(attribute == "position"){
// if we're not reparenting, then we can only be moving
this._moveChildItem(oldValue, item, newValue, dojo.hitch(this, function(){
this.onTreeChange(item, oldValue, oldValue, newValue);
}));
}else {
this.onChange(item);
}
},
refreshItemChildren: function(/*Item*/ item, /*Function?*/ modifier) {
item._children = null;
var func = modifier ? modifier : function(items) {
this.onChildrenChange(item, items);
};
this.getChildren(item, dojo.hitch(this, func));
},
_insertChildItem: function(/*Item*/parentItem, /*Item*/ item, /*Item*/ newNextSibling, /*Function*/callbackfn) {
this.getChildren(parentItem, dojo.hitch(this, function(items) {
// refresh the item children with a function that will add the item first
if(!items){
items = [];
}
if(!newNextSibling) {
items.push(item);
} else {
var id = this.getIdentity(newNextSibling);
for(var i = 0; i < items.length; i++) {
if(this.getIdentity(items[i]) == id) {
items.splice(i, 0, item);
break;
}
}
}
if(callbackfn) callbackfn();
this.onChildrenChange(parentItem, items);
}));
},
_removeChildItem: function(/*Item*/parentItem, /*Item*/ item, /*Function*/callbackfn) {
this.getChildren(parentItem, dojo.hitch(this, function(items) {
var id = this.store.getIdentity(item);
if(items){
for(var i = 0; i < items.length; i++) {
if(this.store.getIdentity(items[i]) == id) {
items.splice(i,1); // remove the item from the array
break; // break out of the loop since we already found ourselves
}
}
}
if(callbackfn) callbackfn();
this.onChildrenChange(parentItem, items);
}));
},
_moveChildItem: function(/*Item*/parentItem, /*Item*/ item, /*String*/ newNextSibling, /*Function*/callbackfn) {
this.getChildren(parentItem, dojo.hitch(this, function(items) {
var id = this.store.getIdentity(item);
var nextIndex = items.length - 1;
for(var i = 0; i < items.length; i++) {
if(this.store.getIdentity(items[i]) == id) {
items.splice(i, 1); // remove item from index i
i--;
}
else if(newNextSibling && this.store.getIdentity(items[i]) == newNextSibling) {
// insert item at index i before the existing item at that index without deleting it
items.splice(i, 0, item);
i++;
}
}
if(!newNextSibling) {
// if this is null, append the item to the end of the list
items.push(item);
}
if(callbackfn) callbackfn();
this.onChildrenChange(parentItem, items);
}));
},
onTreeChange: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Item*/ nextSiblingItem) {
},
onChange: function(/*Item*/ item){
},
onChildrenChange: function(/*Item*/ parentItem, /*Array*/ items){
}
}
);
}
if(!dojo._hasResource["com.ibm.data.SelectionModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.data.SelectionModel"] = true;
dojo.provide("com.ibm.data.SelectionModel");
dojo.declare("com.ibm.data.SelectionModel",
null,
{
// treeModel: An instance of a DataTreeModel which backs this SelectionModel
treeModel: null,
// selectionPath: Array of items in the DataTreeModel which represent the current selection path.
// Starts at the currently selected node and goes up the tree to the root.
selectionPath: [],
constructor: function(args) {
dojo.mixin(this, args);
this.modelConnection = dojo.connect(this.treeModel, "onTreeChange", this, "onModelTreeChange");
},
atLevel: function(level, fromRoot) {
return this.selectionPath[fromRoot ? this.selectionPath.length - 1 - level : level];
},
getPath: function() {
return this.selectionPath.slice();
},
onModelTreeChange: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Item*/ nextSiblingItem) {
if(oldParentItem != newParentItem
&& dojo.some(this.selectionPath, function(item) {
return this._itemIsEqual(item, childItem);
}, this)) {
this._calculateNewPath(this.selectionPath[0]);
this.onSelectionPathChange(false);
}
},
_itemIsEqual: function(item1, item2) {
return (item1 && this.treeModel.getIdentity(item1)) == (item2 && this.treeModel.getIdentity(item2));
},
_calculateNewPath: function(lastSelected) {
// the model is built from the top-down, so the model should already have
// loaded all the ancestors of the lastSelected item so that model.getParent()
// returns loaded items
var cur = lastSelected;
this.selectionPath.splice(0, this.selectionPath.length);
while(cur) {
this.selectionPath.push(cur);
cur = this.treeModel.getParent(cur);
}
},
onSelectionPathChange: function(/*Boolean*/ selectionChanged) {
// summary: Event called when the selection path is updated. This can occur when the
// selection model changes because the tree was restructured, changing the path
// from the currently selected node to the root by reparenting some nodes, or
// by actually changing the currently selected node in the tree.
// selectionChanged: Boolean true if the currently selected node changed, false if the
// path changed but the currently selected node is the same.
},
changeSelection: function(/*item*/ newSelection) {
this._calculateNewPath(newSelection);
this.onSelectionPathChange(true);
}
}
);
}
if(!dojo._hasResource["com.ibm.mm.builder.navigationHelper"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.mm.builder.navigationHelper"] = true;
dojo.provide("com.ibm.mm.builder.navigationHelper");
dojo.declare("com.ibm.mm.builder.navigationHelper",
null,
{
loaded: false,
init: function(){
// singleton instance of data store to be used under the covers by any component using these APIs
this.store = new com.ibm.data.EnablerModelStore();
this.navigationUtil = com.ibm.mm.builder.utils.navigationUtil;
this.pageUtil = com.ibm.mm.builder.utils.pageUtil;
this.spaceUtil = com.ibm.mm.builder.utils.spaceUtil;
// TEMP for portal, does not cause issues in mashups 2.5
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
var currentPage = com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage();
var currentPageId = currentPage.getID();
if(!currentPageId) {
var spaceId = this.spaceUtil.getCurrentSpaceId();
currentPageId = spaceId ? this.pageUtil.getFirstPageInSpace(spaceId) : this.pageUtil.getFirstRootPageId();
if(!currentPageId && spaceId){
currentPageId = spaceId;
}else{
currentPageID = this.navigationUtil.getNavigationRootNode().getID();
}
}
var onComplete = dojo.hitch(this,
function(items) {
this.treeModel =
new com.ibm.data.EnablerTreeModel({
newItem: function(args) {
args.label = args.title;
return this.inherited("newItem", arguments);
},
root: items[items.length - 1],
store: this.store
});
this.selectionModel =
new com.ibm.data.SelectionModel({
treeModel: this.treeModel,
selectionPath: items
});
this.loaded = true;
} );
var args = { onComplete: onComplete,
onError: function(err) {
console.error(err);
throw err;
},
query: {uri: currentPageId }
}
if(!this.treeModel || !this.selectionModel) this.store.fetch(args);
},
getStore: function(){
return this.store;
},
getTreeModel: function(){
return this.treeModel;
},
getSelectionModel: function(){
return this.selectionModel;
}
}
);
com.ibm.mm.builder.navigationHelper = new com.ibm.mm.builder.navigationHelper();
}
if(!dojo._hasResource["com.ibm.pb.data.EnablerNavigationTreeModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.data.EnablerNavigationTreeModel"] = true;
dojo.provide( "com.ibm.pb.data.EnablerNavigationTreeModel" );
(function(){
//com.ibm.mashups.enabler.model.state.NavigationStateModelFactory
var enabler = com.ibm.mashups.enabler,
em = enabler.model,
state = em.state,
accFct = state.AccessorFactory,
spaceFct = enabler.space.Factory,
navFct = enabler.navigation.Factory,
lCtxt = enabler.context.Factory.getLocalizedContext(),
dfOpP = enabler.DeferredOperation.prototype,
opCodes = {};
dojo.forEach(["GET","CREATE","MODIFY","DELETE"], function(c){
this[c] = dfOpP["OPERATION_" + c];
}, opCodes);
// This module provides the API for a data model that corresponds to any data set that contains
// parent-child relationships that can be represented as a tree. It's exactly the same as the
// model API that's used by dijit.Tree with some functions already implemented for ease of use.
// As a result, any implementation of this API can be used as the model to a dijit.Tree widget
// or any other widget that uses a data model as its backend service provider. This data API
// also adds some additional constraints and extension points that implementations should support
// in addition to the model API that's used by dijit.Tree, but by no means breaks the API or
// deviates from the required functions of the dijit model API. One such addition is the
// support for additional query parameters that can be specified when instantiating a model
// that are always appended to any request to the server for data. This allows particular instances
// of a data model to include metadata information that would not otherwise be included by certain
// data services that support it.
dojo.declare( "com.ibm.pb.data.EnablerNavigationTreeModel", com.ibm.pb.logging.Loggable, {
SAVE_CHECK: "com.ibm.mashups.builder.saveCheck",
SWITCH_PAGE: "com.ibm.mashups.builder.switchPage",
// root: The root item of this model
root: null,
// navigation state model
nsm: null,
// navigation model
nm: null,
// space model
spm: null,
codes: {
HTTP_OK: 200
},
// global page support
globalPages: [], // the global pages that are open
globalPageInSpace: null, // the space in which the global pages were opened
constructor: function(args) {
dojo.safeMixin(this, args);
if(!this.nsm) {this.nsm = state.NavigationStateModelFactory.getNavigationStateModel();}
if(!this.nm) {this.nm = navFct.getNavigationModel();}
if(!this.spm) {this.spm = spaceFct.getSpaceModel();}
if(!this.delaySave) {this.delaySave = false;}
},
destroy: function() {
// summary: destroys this object, releasing connections to the store
},
reset: function(root) {
// summary: Resets the root of this model to the argument.
this.root = root;
},
_getRootBySpace: function(space, status, params) {
var mname = "_getRootBySpace", lgr = this.LOGGER;
lgr.entering(mname, arguments);
try {
var navDfd;
if(space) {
navDfd = this.nm.find(space.getRootNavigation());
}
else {
navDfd = this.nm.getRoot();
}
navDfd.setFinishedCallback(dojo.hitch(this, function(navNode, statusCode){
lgr.trace(mname, "Callback: ${0} ${1}", [navNode, statusCode]);
if(navNode && !(navNode instanceof Error)) {
this.root = navNode;
if(params.onItem) {
params.onItem(this.root);
}
}
else if(params.onError){
lgr.error(mname, "Error getting the root nav node in space ${0}: ${1}", [space, err]);
params.onError(navNode);
}
}));
lgr.trace(mname, "Finding root nav node in space ${0}", [space]);
node = navDfd.start(false);
} catch(err) {
lgr.error(mname, "Error starting find operation for the root nav node in space ${0}: ${1}", [space, err]);
console.error(err);
}
lgr.exiting(mname, arguments);
},
getRoot: function(onItem, onError){
// summary:
// Calls onItem with the root item for the tree
var mname = "getRoot", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var globalSpaceId = dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId);
if (globalSpaceId) {
var id = globalSpaceId;
} else {
var id = accFct.getSpaceAccessor(this.nsm).getSpaceID();
}
var params = {onItem:onItem, onError:onError};
if(id) {
var dfd = this.spm.find(id);
dfd.setFinishedCallback(dojo.hitch(this, "_getRootBySpace"), params);
dfd.start(false);
}
else {
this._getRootBySpace(null, 200, params);
}
lgr.exiting(mname, arguments);
},
mayHaveChildren: function(/*Object*/ item){
// summary:
// Tells if an item has or may have children. Implementing logic here
// avoids showing +/- expando icon for nodes that we know don't have children.
// (For efficiency reasons we may not want to check if an element actually
// has children until user clicks the expando node)
return this.nm.hasChildren(item);
},
getChildren: function(/*Object*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
// summary:
// Calls onComplete() with array of child items of given parent item, all loaded.
var mname = "getChildren", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var dfd = this.nm.getChildren(parentItem);
var children = [];
dfd.setForEachCallback(function(child){
lgr.trace(mname, "Got child ${0}", [child]);
if(child && !child.isHidden()) {
children.push(child);
}
});
dfd.setFinishedCallback(dojo.hitch(this, function(res, status, params){
lgr.trace(mname, "Finished getting children with status ${0}", [status]);
if(status == this.codes.HTTP_OK) {
// support global pages
if (this.globalPageInSpace) {
var parentItemSpace = com.ibm.mm.builder.utils.spaceUtil.getSpaceByNavigation(parentItem);
if (parentItemSpace && this.globalPageInSpace == parentItemSpace.getID()) {
for (var i in this.globalPages) {
var inChildren = false;
for (var j in children) {
if (this.globalPages[i].getID() == children[j].getID()) {
inChildren = true;
}
}
if (!inChildren) {
children.push(this.globalPages[i]);
}
}
}
}
if(onComplete) {onComplete(children);}
}
else if(onError) {
onError(res);
}
}));
dfd.start(false);
lgr.exiting(mname, arguments);
},
// =======================================================================
// Inspecting items
getIdentity: function(/* item */ item){
// summary: returns identity for an item
if(item == null){
return null;
}
return item.getID();
},
getLabel: function(/*dojo.data.Item*/ item){
// summary: get the label for an item
if(item == null){
return null;
}
return lCtxt.getTitle(item);
},
getParent: function(/*dojo.data.Item*/ item) {
// summary: returns the parent item of this item argument
var mname = "getParent", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if (this._isGlobalPage(item)) {
// to support global page, return the parent of the top level pages of the space that opened the global page
var globalSpaceId = dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId);
if (globalSpaceId) {
var parent = com.ibm.mm.builder.utils.navigationUtil.getNavigationRootNode(globalSpaceId);
} else {
console.log("Error: globaPageOpenedSpaceId in cookie is missing!");
}
}else{
var parent = this.nm.getParent(item).start();
}
lgr.exiting(mname, [parent]);
return parent;
},
// =======================================================================
// Write interface
newItem: function(args, parent) {
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
var createParams = {type: com.ibm.mashups.enabler.navigation.Constants.NAVIGATION_PAGE}
if (args["private"] == "on") {
createParams["private"] = true;
}
var isPageTemplate = args["template"] != null;
if (isPageTemplate) {
createParams.pageTemplate = args["template"];
}
var newPage = nm.create(createParams);
newPage.setTitle(args.title, dojo.locale);
newPage.setTitle(args.title, ibmCfg.enablerConfig["default.locale"]);
if (args.friendlyURL)
newPage.setMetaData("com.ibm.portal.friendly.name", args.friendlyURL);
var parentId = this.getIdentity(parent);
var parentNavNode = nm.find(parentId).start();
nm.insert(newPage, parentNavNode);
var content = newPage.getContent().start();
if(!isPageTemplate) {
content.setStaticContentURL(ibmConfig.defaultLayoutTemplateURI);
}
var dfd = nm.commit();
var fail = false;
// use verbose callback
dfd.setOperationCallback(function(ctx){
var evtSvc = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
// fetch request values
var page = ctx.resource;
var mode = ctx.mode;
var params = ctx.parameter;
if (ctx.request) {
var status = ctx.request.statusCode;
}
// 20582 - trigger navigation refresh only after the page is created (this
// callback is invoked not only for the page, but for the contents too)
if(!fail && page && page instanceof com.ibm.mashups.enabler.navigation.NavigationElement && page.getID && status < 300) {
fail = false;
evtSvc.broadcastEvent("com.ibm.mashups.builder.switchPage", page.getID());
}else if(status >= 400){
fail = true;
if (ctx.request) {
var responseText = ctx.request.responseText;
}
var bundle = dojo.i18n.getLocalization("com.ibm.bundles", "PageCreatorDialog");
var statusMessage = new com.ibm.widgets.StatusMessage("error", responseText || bundle["page_dialog_error_creating_page"], "");
dojo.publish("/message/status",[{message: statusMessage, uid: 'ibmStatusBox'}]);
}
if(args.callback) {
args.callback(page, mode, status, params);
}
}, null, true);
dfd.setFinishedCallback(function(page, status){
if(args.callback){
args.callback(page, null, status);
}
});
dfd.start(true);
return newPage;
},
// newGlobalItem adds an item but it is temporary. It doesn't exist in the enabler model. This is used for global page support.
newGlobalItem: function(args, parent){
if(parent.getRootNavigation)
{
parent = com.ibm.mm.builder.utils.navigationUtil.getNavigationRootNode(parent.getID());
}
var newPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(args.openPageId);
newPage.loaded = false;
newPage.created = false;
newPage.openPageId = args.openPageId;
newPage.pageLoadedSpaceId = args.pageLoadedSpaceId;
newPage.onCreate = function(){};
this.globalPageInSpace = newPage.pageLoadedSpaceId;
this.globalPages.push(newPage);
this.newPageItem = newPage;
this.newPageParent = parent;
// Note: onTreeChange seems appropriate here, but it causes duplicate tabs to appear for the global page
//this.onTreeChange(this.newPageItem, null, this.newPageParent);
this._isItemCreated = true;
return newPage;
},
// Note: _createItem appears to be dead code.
_createItem: function(args, parentInfo) {
// summary: Creates an item
// All model requests must be synchronous since this must return the
// created item directly.
var title = args.title;
var newPage, mix = {
loaded: false,
created: false
};
if (args.openPageId){
// load an existing page as an new item
newPage = this.nm.find(args.openPageId).start();
mix = dojo.mixin(mix, {
openPageId: args.openPageId,
pageLoadedSpaceId: args.pageLoadedSpaceId
});
this.globalPageInSpace = args.pageLoadedSpaceId;
this.globalPage = newPage;
}else{
if(!this.nm.confirmCreate(args)) {
// throw new Error("Not allowed");
return;
}
newPage = this.nm.create(args);
newPage.setTitle(title, lCtxt.getPreferredLocale());
newPage.setTitle(title, ibmCfg.enablerConfig["default.locale"]);
newPage.setTheme(parentInfo.parent.getTheme());
mix.title = title;
this.nm.insert(newPage, parentInfo.parent, args.next);
}
dojo.mixin(newPage, mix);
return newPage;
},
save: function(/* object */ keywordArgs) {
// summary: Saves the model updates
// Model requests can and should be asynchronous since this returns nothing
// is uses callbacks.
var scope = keywordArgs.scope || dojo.global;
var utils = com.ibm.mm.builder.utils;
var evtSvc = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
if (keywordArgs.openPageId){
// just open an existing page, no need to save the page node.
var newPage = this.nm.find(keywordArgs.openPageId).start();
// create new items
newPage.created = true;
newPage.setID(newPage.getID());
this._fireCreated(newPage);
if(keywordArgs.onComplete) {keywordArgs.onComplete.call(scope);}
}else{
// create new items
var dfdOp = this.nm.commit();
dfdOp.setOperationCallback( dojo.hitch(this, function(node){
node.created = true;
var es = com.ibm.mashups.services.ServiceManager.getService("eventService");
es.broadcastEvent("com.ibm.mashups.builder.pageCreated", node.getID());
node.setID(node.getID());
this._fireCreated(node);
}));
dfdOp.setFinishedCallback(function(page, status){
if(status >= 400) {
// 4xx and 5xx HTTP errors
var bundle = dojo.i18n.getLocalization("com.ibm.bundles", "Theme");
var statusMessage = new com.ibm.widgets.StatusMessage("error", bundle["dnd_move_failed"], "");
dojo.publish("/message/status",[{message: statusMessage, uid: 'ibmStatusBox'}]);
setTimeout(function(){
evtSvc.broadcastEvent("com.ibm.mashups.builder.refreshNavigation");
}, 500);
}
if(keywordArgs.onComplete) {keywordArgs.onComplete.call(scope);}
});
dfdOp.start(false);
if(this._isDirty){
// update dirty items
this.nm.commit().start(false);
this._isDirty = false;
if(keywordArgs.onComplete) {keywordArgs.onComplete(keywordArgs);}
}
}
},
_fireCreated: function(item) {
if(item.onCreateDefQueue && !item.onCreateDefQueue._fired) {
try {
item.onCreateDefQueue.fire(item);
item.onCreateDefQueue._fired = true;
} catch(ex) {
// open a global page twice will lead an exception.
console.log(ex);
}
}
},
deleteGlobalItem: function(/*Object*/args, /*item*/ item){
// This is a fake delete item method, which only will remove global page.
var parent = this.getParent(item);
for (var i in this.globalPages) {
if (this.globalPages[i].getID() == item.getID()) {
this.globalPages.splice(i, 1);
break;
}
}
this.onTreeChange(null, parent, parent);
},
isCreated: function(/*item*/ item) {
// summary: Indicates whether or not the item has been created on the server and
// the server-generated values were properly applied to the client-side
// object. NOTE: Any client-side modifications to the values of an item for
// which isCreated returns true can potentially modify the server-generated
// values to be out-of-sync with the server.
// Therefore, it's important to note that isCreated merely indicates whether
// or not the client-side item has a server-side resource associated with it,
// and any values that the server generated for the resource (such as a unique
return true;
},
addOnCreate: function(/*item*/ item, /*Function*/ callback) {
// summary: Register callback to be called when the given item is created on the server.
// If the item is already created, this will call the callback immediately.
if(this.isCreated(item)) {
if(callback) {callback(item);}
}
else {
if(!item.onCreateDefQueue) {
item.onCreateDefQueue = new com.ibm.lang.DeferredQueue(new dojo.Deferred());
}
item.onCreateDefQueue.add(new dojo.Deferred().addCallback(callback));
}
},
_updateChildren: function(parentItem) {
if(parentItem) {
this.getChildren(parentItem, dojo.hitch(this, function(children){
this.onChildrenChange(parentItem, children);
}));
}
},
pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ copy, /*Item*/ nextSibling, /*Boolean?*/ extra){
// summary:
// Move an item from one parent item to another or to another position under the same parent.
// Used in drag & drop.
// See dojo.data.api.Write for details on args.
var mname = "pasteItem", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(!this.nm.confirmInsert(childItem, newParentItem, nextSibling)) {
lgr.trace("confirmInsert returns false");
}
else {
lgr.trace("insert into the tree model");
this.nm.insert(childItem, newParentItem, nextSibling);
this.onTreeChange(childItem, oldParentItem, newParentItem, nextSibling);
this._updateChildren(oldParentItem);
this._updateChildren(newParentItem);
// When enabler correctly updates the runtime nav model,
// the tree model can start to use transactions for reordering
/*if(!this.delaySave){
this.save({});
} else {
com.ibm.mashups.builder.model.Factory.getRuntimeModel().getCurrentPage().setDirty(true);
}*/
}
lgr.exiting(mname, arguments);
},
toString: function() {
return "[TreeModel " + this.declaredClass + "]";
},
_onNew: function(item, parentInfo){
},
_onDelete: function(item){
},
_onSet: function(/* Item */ item, /*String*/ attribute, /*Object | Array*/ oldValue, /*Object | Array*/ newValue){
},
_isGlobalPage: function(item){
for (var i in this.globalPages) {
if (this.globalPages[i].getID() == item.getID()) {
return true;
}
}
return false;
},
onTreeChange: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Item*/ nextSiblingItem) {
},
onChange: function(/*Item*/ item){
},
onChildrenChange: function(/*Item*/ parentItem, /*Array*/ items){
}
});
})();
}
if(!dojo._hasResource["com.ibm.pb.tree.Traversal"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.tree.Traversal"] = true;
dojo.provide("com.ibm.pb.tree.Traversal");
dojo.declare("com.ibm.pb.tree.Traversal", com.ibm.pb.logging.Loggable, {
model: null,
constructor: function(model) {
this.model = model;
this.stopped = true;
},
isStopped: function() {
return this.stopped;
},
/**
* Finds the first node in the tree model that meets the test criteria
* and calls the callback with that single node.
*/
find: function(node, test, callback) {
var mname = "find", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.collect(node, test, function(list){
callback(list[0]);
}, function(params){
return params.list.length > 0;
});
lgr.exiting(mname, arguments);
},
/**
* Finds all the nodes in the tree model that meet the test criteria
* and calls the callback with an array of those nodes. Supports
* conditionally stopping at any point using a stop test function.
*/
collect: function(node, test, callback, stop, params) {
var mname = "collect", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.stopped = false;
if(!params) {
params = {};
}
if(!params.list) {
params.list = [];
}
params.level = 1;
this.visit(node, test, callback, stop || function(){return false;}, params);
lgr.exiting(mname, arguments);
},
/**
* Visits a particular node, performing the test condition on the
* node and conditionally adding it to the list of found nodes that
* meet the test criteria.
*/
visit: function(node, test, callback, stop, params) {
var mname = "visit", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(test(this.model, node)) {
lgr.trace(mname, "Found positive testing node ${0}", [node]);
params.list.push(node);
}
if(stop(params)) {
this.stopped = true;
lgr.trace(mname, "Hard stopping traversal and calling back with results ${0}", [params.list]);
callback(params.list);
}
else {
this.next(node, test, callback, stop, params);
}
lgr.exiting(mname, arguments);
},
/**
* Called after a node is visited in order to find and visit the next
* node in the traversal sequence so long as the traversal hasn't
* stopped. Unimplemented and requires extensions using a particular
* traversal algorithm to implement.
*/
next: function(node, test, callback, stop, params) {
}
});
}
if(!dojo._hasResource["com.ibm.pb.tree.DFSTraversal"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.tree.DFSTraversal"] = true;
dojo.provide("com.ibm.pb.tree.DFSTraversal");
dojo.declare("com.ibm.pb.tree.DFSTraversal", com.ibm.pb.tree.Traversal, {
next: function(node, test, callback, stop, params) {
// visit the next node in the tree using depth-first search
var mname = "next", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var iterator = null;
if(this.model.hasChildren(node)) {
lgr.trace(mname, "Traversing down children of ${0}", [node]);
var dfdParams = {
node: node,
test: test,
callback: callback,
stop: stop,
params: params,
list: []
}, me = this;
this.model.getChildren(node)
.setForEachCallback(function(){
me._collectChild.apply(me, arguments);
}, dfdParams)
.setFinishedCallback(function(){
me._visitChildren.apply(me, arguments);
}, dfdParams)
.start(false);
}
else {
lgr.trace(mname, "Reached end of traversal at ${0}", [node]);
if(!this.isStopped()) {
callback(params.list);
}
}
lgr.exiting(mname, arguments);
},
_collectChild: function(resource, dfdParams) {
dfdParams.list.push(resource);
},
_visitChildren: function(resource, status, dfdParams) {
var mname = "_visitChildren", lgr = this.LOGGER, me = this;
lgr.entering(mname, [resource, status, dfdParams]);
if((status !== 200) && (status != "200")) {
lgr.severe(mname, "An error occurred ${0} ${1}", [status, resource]);
lgr.exiting(mname, arguments);
return;
}
var subTreeCallback = function() {
if(!me.isStopped()) {
var currentNode = dfdParams.list.shift();
if(currentNode) {
me._visitChild(currentNode, dfdParams.test, subTreeCallback, dfdParams.stop, dojo.delegate(dfdParams.params, {level: dfdParams.params.level+1}));
}
else {
lgr.trace(mname, "Reached end of list of children of ${0}", [dfdParams.node]);
dfdParams.callback(dfdParams.params.list);
}
}
else {
lgr.trace(mname, "Stopped in the middle of the list of children of ${0}", [dfdParams.node]);
dfdParams.callback(dfdParams.params.list);
}
}
lgr.exiting(mname, arguments);
subTreeCallback();
},
_visitChild: function(node, test, callback, stop, params) {
var mname = "_visitChild", lgr = this.LOGGER, me = this;
lgr.trace(mname, "Visiting next node in list of children ${0}", [node]);
if(!this.isStopped()) {
this.visit(node, test, callback, stop, params);
}
else {
// FIXME: Stop any iterators at this point, 13729
lgr.trace(mname, "Hard stopped iterating");
}
}
});
}
if(!dojo._hasResource["com.ibm.pb.control.NavigationController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.control.NavigationController"] = true;
dojo.provide("com.ibm.pb.control.NavigationController");
dojo.require("dojo.i18n");
dojo.require("dojo.hash");
/**
* The NavigationController is meant to be a singleton object retrieved via the
* com.ibm.pb.control.NavigationController.getController API. It is responsible
* for managing global navigation state and model information by providing access
* to a dijit.tree.model implementation representing the navigation model. It
* also provides a selection model implementation that is mapped over top of the
* tree model and provides semantics as to the selection path from the currently
* selected node in the navigation model up to the navigation root node. These
* constructs provide suitable models for backing interface widgets and for managing
* public navigation selection events such as SWITCH_PAGE and PAGE_SWITCHED. This
* module provides logic for handling page switches both explicitly and via navigation
* state changes. It determines the correct context, updates the state, fires
* the appropriate internal events to its selection model and tree model, and fires
* the PAGE_SWITCHED event on successful selection changes.
*/
// not an iWidget, but uses the iWidget base for convenient provision of member variables
dojo.declare("com.ibm.pb.control.NavigationController", com.ibm.pb.iwidget.iWidgetBase, {
navigationConstants: com.ibm.mashups.enabler.navigation.Constants,
accFactory: com.ibm.mashups.enabler.model.state.AccessorFactory,
treeModel: null,
selectionModel: null,
_changingSelection:false,
currentThemeTemplate: "",
// these fields are used for global page support
lastNonGlobalPageId: null, // the last non-global page at any given time
lastSpaceId: null, // the space being shown before the most recent update to the navigation
globalPageLoadedSpaceId: null, // the space where global pages are opened
globalPagesOpened: [], // the ids of the global pages currently showing
globalPagesOpenedBy: [], // the ids of the pages that opened each of the global pages currently showing
constructor: function(){
var lgr = this.LOGGER, mname = "constructor", me = this;
lgr.entering(mname, arguments);
this.themeBundle = dojo.i18n.getLocalization("com.ibm.bundles", "Theme");
this.navWidgetBundle = dojo.i18n.getLocalization("com.ibm.bundles", "NavWidget");
this.nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
this.nsm = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
this.spm = com.ibm.mashups.enabler.space.Factory.getSpaceModel();
this.spaceAcc = this.accFactory.getSpaceAccessor(this.nsm);
this.nm.addStrategy(new com.ibm.mashups.enabler.strategy.TreeLoadAheadStrategy(10, 1)); // 10 parents up, 1 level of children
this.nm.addStrategy(new com.ibm.mashups.enabler.strategy.ListLoadAheadStrategy(50)); // 50 children at a time
this.treeModel = new com.ibm.pb.data.EnablerNavigationTreeModel({nm: this.nm, nsm: this.nsm, spm: this.spm, delaySave: true});
// Somewhat complex logic in getting the root, so keep it out of the tree model impl and just put it here
this.treeModel.getRoot = dojo.hitch(this, "getRootNavigation");
this.selectionModel = new com.ibm.data.SelectionModel({
treeModel: this.treeModel,
selectionPath: []
});
// Note: this logic was here for logging purposes but is throwing exceptions
// in the case of global pages
// var origChangeSelection = this.selectionModel.changeSelection;
// this.selectionModel.changeSelection = dojo.partial(function(node){
// lgr.trace("changeSelection", "Changing the selection model's selection ${0}", [node]);
// return origChangeSelection.apply(this, arguments);
// });
// Restore global page information for cases of full page refresh
this._restorePersistedGlobalPages();
this._changingSelection = true;
// calculate the current page asynchronously... will callback a selection model update
this.bootstrapping = true;
this._bootstrapState = false;
//this._calculateCurrentPage();
this.evtSvc.subscribeEvent(this.iWidgetConstants.NAVSTATE_UPDATED, this, function(){
var cbkName = "NavStateUpdatedHandler";
lgr.entering(cbkName, arguments);
// fetch the navigational state model again so it is not stale
this.nsm = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
this.spaceAcc = this.accFactory.getSpaceAccessor(this.nsm);
this.treeModel.nsm = this.nsm;
var cid = this.getCurrentPageId();
// Switch to the page if it is not the current page in navigation
if(!this._changingSelection && cid !== this.currentPageId) {
this.onSwitchPage(cid, {skipStateUpdate: true});
}
lgr.exiting(cbkName, arguments);
});
this.evtSvc.subscribeEvent(this.builderEvents.SWITCH_PAGE, this, "onSwitchPage");
this.evtSvc.subscribeEvent(this.builderEvents.SWITCH_SPACE, this, "onSwitchSpace");
this.evtSvc.subscribeEvent(this.builderEvents.REFRESH_NAVIGATION, this, "onRefreshNavigation");
this.evtSvc.subscribeEvent(this.builderEvents.PAGE_SWITCHED, this, "_updateSelModel");
this.evtSvc.subscribeEvent("com.ibm.mashups.builder.saveCheck", this, "dirtyPageCheck");
dojo.subscribe("/dojo/hashchange", this, this._processHashChange);
lgr.exiting(mname, arguments);
},
getSelectionModel: function() {
return this.selectionModel;
},
getTreeModel: function() {
return this.treeModel;
},
getThemeTemplate: function(node){
return node.getMetaData("com.ibm.portal.theme.template.file.name.html") || "";
},
getThemeId: function(node) {
var themeId = node.getThemeIdentifier ? node.getThemeIdentifier() : null;
while(!themeId && node) {
node = this.nm.getParent(node).start();
themeId = (node && node.getThemeIdentifier) ? node.getThemeIdentifier() : null;
}
if(!themeId) {
themeId = this.runtimeModel.getCurrentTheme();
}
return themeId.getID();
},
getThemeProfile: function(node) {
var themeProfile = node.getMetaData("resourceaggregation.profile") || null;
while(!themeProfile && node) {
node = this.nm.getParent(node).start();
if(node) {
themeProfile = node.getMetaData("resourceaggregation.profile") || null;
}
}
return themeProfile || "";
},
getRenderMode: function(node) {
var renderType = node.getMetaData("com.ibm.portal.rendertype") || null;
while(!renderType && node) {
node = this.nm.getParent(node).start();
if(node) {
renderType = node.getMetaData("com.ibm.portal.rendertype") || null;
}
}
return renderType || ibmConfig.defaultRenderingMode;
},
_visibleChildFinder: function(node){
// Find the first visible child of the node
var mname = "_visibleChildFinder";
this._findFirstVisible(node, dojo.hitch(this, function(child){
if(child && !(child instanceof Error)) {
this._setCurrentNavNode(child);
}
else {
this.LOGGER.severe(mname, "Error finding a visible child of navigation node ${0}: ${1}", [node, child]);
}
}));
},
_isNavLabel: function(model, node) {
return node.getNavigationElementType() === this.navigationConstants.NAVIGATION_LABEL;
},
/**
* Sets the current navigation node of the controller internally, and updates any models
* and state information accordingly.
*/
_setCurrentNavNode: function(node, semantics) {
// Set the current navigation node
var mname = "_setCurrentNavNode", lgr = this.LOGGER, bootstrapping = this.bootstrapping;
lgr.entering(mname, arguments);
this.currentNavNode = node;
this.currentPageId = node.getID();
if(this.bootstrapping) {
this.renderMode = this.getRenderMode(node);
this.bootstrapping = false;
}
this.currentThemeTemplate = this.getThemeTemplate(node).toLowerCase();
this.currentThemeProfile = this.getThemeProfile(node).toLowerCase();
// Walk up the tree to load the ancestors asynchronously, if not already loaded
// which will finally update the selection model at the end
this._walkUpTree(node, dojo.delegate(semantics, {bootstrapping:bootstrapping}));
this._updateNavigationState(this.currentPageId, semantics);
if(this.renderMode === "iwidget") {
// the title is set by theme markup or during initialization code;
// this is meant primarily for client-side page changes
this.setBrowserTitle(node);
}
lgr.exiting(mname, arguments);
},
_calculateCurrentPage: function() {
var mname = "_calculateCurrentPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var currentPageId = this.getCurrentPageId();
if(!currentPageId) {
this._bootstrapState = true;
currentPageId = this.runtimeModel.getCurrentPage().getID();
}
else {
this._bootstrapState = false;
lgr.trace(mname, "Got current page from the navigation state", []);
}
if(!currentPageId) {
// If we don't currently have a current page, then calculate it by loading the root
// of the current navigation, which will load the root navigation node of the current
// space we're in, or the default space if we're not in one.
lgr.trace(mname, "No runtime model of current page, getting root navigation", []);
this.treeModel.getRoot(dojo.hitch(this, "_visibleChildFinder"), dojo.hitch(this, function(err){
lgr.severe(mname, "Error getting root navigation node ${0}", [err]);
}));
}
else {
lgr.trace(mname, "Found current page id ${0}", [currentPageId]);
if (currentPageId && com.ibm.mm.builder.utils.spaceUtil.getSpaceIdByPageId(currentPageId)!=this.globalPageLoadedSpaceId
&& !this._isOpenedGlobalPage(currentPageId)){
// clear the global pages, as this initial page is in a different space from the one where the pages were opened
this.onClearGlobalPage();
}
this.nm.find(currentPageId)
.setFinishedCallback(dojo.hitch(this, function(node, status, params){
if(status == 200) {
this.refresh(node.getID());
}
else {
// defect 16786: There will be page ID in the cookie, and such page won't be found in next install.
// So in this case, we refresh the navigation with the nav root
lgr.trace(mname, "Error finding the current page with id ${0} ${1}", [currentPageId, node||""]);
var navRootID = this.nm.getRoot().start().getID();
var spaceID = com.ibm.mm.builder.utils.spaceUtil.getSpaceIdByPageId(navRootID);
com.ibm.mm.builder.utils.spaceUtil.setSpaceId(spaceID);
this.refresh(navRootID);
}
}))
.start(false);
}
lgr.exiting(mname, arguments);
},
_updateSelModel: function(){
this.selectionModel.changeSelection(this.currentNavNode);
},
_walkUpTree: function(navNode, semantics) {
// Recursively walks up the tree from the navNode until the root is reached
// Finally internally updates the selection model with the current navigation node
var mname = "_walkUpTree", lgr = this.LOGGER, me = this;
if(navNode) {
var dfd = this.nm.getParent(navNode).setFinishedCallback(function(node) {
// walk up the tree asynchronously to guarantee all the ancestors are loaded before
// firing the selection model update
me._walkUpTree(node, semantics);
});
dfd.start(false);
}
else {
lgr.trace(mname, "Updating selection to ${0}", [this.currentNavNode.getID()]);
if(semantics.bootstrapping) {
// call this immediately during bootstrap since the PAGE_SWITCHED event isn't
// guaranteed to be fired
this._updateSelModel();
}
else {
// we're listening to the PAGE_SWITCHED event and will call this._updateSelModel()
// when that is fired
}
}
},
_findFirstVisible: function(parentNode, callback) {
// Finds the first visible descendant of the given parentNode, and calls the callback
// with that child navigation node as the argument
var mname = "_findFirstVisible", lgr = this.LOGGER, me = this;
lgr.entering(mname, arguments);
var dft = new com.ibm.pb.tree.DFSTraversal(this.nm);
dft.find(parentNode, function(model, navNode){
return !me._isNavLabel(model, navNode) && !navNode.isHidden();
}, function(foundNode){
lgr.trace(mname, "Found visible non-label node ${0}, executing callback", [foundNode]);
callback(foundNode);
});
lgr.exiting(mname, arguments);
},
getCurrentSpaceId: function() {
var globalSpaceId = dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId);
if (globalSpaceId) {
return globalSpaceId;
} else {
return this.spaceAcc.getSpaceID();
}
},
getCurrentPageId: function() {
var pageAcc = this.accFactory.getPageAccessor(this.nsm, this.spaceAcc.getSpaceID());
return pageAcc.getPageID();
},
getRootNavigation: function(onItem, onError) {
var mname = "getRootNavigation", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var id = this.getCurrentSpaceId(),
params = {onItem:onItem, onError:onError};
if(id) {
var dfd = this.spm.find(id);
dfd.setFinishedCallback(dojo.hitch(this, "_getRootBySpace"), params);
dfd.start(false);
}
else {
this._getRootBySpace(null, 200, params);
}
lgr.exiting(mname, arguments);
},
_getRootBySpace: function(space, status, params) {
// This gets the root navigation node of a space, or gets the root navigation node
// of the default space if the space argument is null.
// Once retrieved, it calls the params.onItem function with the resulting node,
// or the params.onError function if an error occurs at any point along the way.
var mname = "_getRootBySpace", lgr = this.LOGGER;
lgr.entering(mname, arguments);
try {
var navDfd;
if(space) {
navDfd = this.nm.find(space.getRootNavigation().getID());
}
else {
navDfd = this.nm.getRoot();
}
navDfd.setFinishedCallback(dojo.hitch(this, function(navNode, statusCode){
var cbkMname = mname + ":callback";
lgr.entering(cbkMname, arguments);
//lgr.trace(cbkMname, "Callback: ${0} ${1}", [navNode, statusCode]);
if(navNode && !(navNode instanceof Error)) {
this.root = navNode;
if(params.onItem) {
params.onItem(navNode);
}
}
else if(params.onError){
lgr.severe(cbkMname, "Error getting the root nav node in space ${0}: ${1}", [space, navNode]);
params.onError(navNode);
}
}));
lgr.trace(mname, "Finding root nav node in space ${0}", [space]);
navDfd.start(false);
} catch(err) {
lgr.severe(mname, "Error starting find operation for the root nav node in space ${0}: ${1}", [space, err]);
}
lgr.exiting(mname, arguments);
},
/**
* Entry point for handling the SWITCH_SPACE event.
*/
onSwitchSpace: function(spaceId, semantics) {
var mname = "onSwitchSpace", lgr = this.LOGGER, me = this;
lgr.entering(mname, arguments);
this.dirtyPageCheck(function(){
me.switchSpaceHandler(spaceId, semantics);
});
lgr.exiting(mname, arguments);
},
switchSpaceHandler: function(spaceId, semantics) {
var mname = "switchSpaceHandler", lgr = this.LOGGER, me = this;
lgr.entering(mname, arguments);
if (spaceId) {
// we need to verify if the space is still in the model before we switch to it
// in cases where the space has just been deleted and an event is sent to switch a space
// or an invalid ID is used to send that event the enduser sees many JS exceptions
var spaceModel = com.ibm.mashups.enabler.space.Factory.getSpaceModel();
var spaceNode = spaceModel.find(spaceId).start(true);
if (!spaceNode) {
// this space node has been deleted
lgr.exiting(mname, arguments);
return;
}
}
// D18206
// When switching spaces, check whether the currently opened page is a global page.
// If so, need to update (fix) the pageID for the spaceID in the pageselection lookup index.
// At this point the pageselection for the current space will be referencing the global page.
// If the user comes back to this space, the global page will be the one that is re-opened
// (furthermore, the user will be taken to the space for the global page).
// This fix here, "cleans up" the pageselection to refer back to the last non-global page
// viewed in this space.
if (this._isOpenedGlobalPage(this.currentPageId)) {
this.accFactory.getPageAccessor(this.nsm, this.lastSpaceId).setPageID(this.lastNonGlobalPageId);
}
if (spaceId != this.lastSpaceId){
// clear global pages
this.onClearGlobalPage();
}
this.spaceAcc.setSpaceID(spaceId); // set the new space so all subsequent calls will use that
if (!spaceId) {
dojo.cookie("inPersonalSpace", "true");
}
else {
dojo.cookie("inPersonalSpace", null);
}
// get the current page from the nav state in the current space
var pageId = this.getCurrentPageId(),
pageNode = null;
//switch to last page or first page.
if(pageId) {
pageNode = this.nm.find(pageId).start();
// we need to update the navstate as setSpaceID will clear out the pageId from the navstate, so we have to set it back
this.accFactory.getPageAccessor(this.nsm, spaceId).setPageID(pageId);
}
// if no page node was found matching that pageId
if(!pageNode) {
this.getRootNavigation(function(navNode){ // gets the root navigation of the current space
me._findFirstVisible(navNode, function(firstVisibleNode){
if(firstVisibleNode) {
// broadcast SWITCH_PAGE to the page we've calculated
me.evtSvc.broadcastEvent(me.builderEvents.SWITCH_PAGE, firstVisibleNode.getID());
}
else {
// broadcast SWITCH_PAGE to the root page
if(!spaceId) {
com.ibm.mm.builder.utils.navigationUtil.autoAcceptPagesFromDefaultGroup();
}
me.evtSvc.broadcastEvent(me.builderEvents.SWITCH_PAGE, navNode.getID());
}
});
}, function(err){
lgr.severe(mname, "${0}", [err.message]);
});
}
else {
this.evtSvc.broadcastEvent(this.builderEvents.SWITCH_PAGE, pageId);
}
lgr.exiting(mname, arguments);
},
/**
* Entry point for handling the SWITCH_PAGE event. The controller handles this event
* globally and singularly on behalf of all components that are interested in navigation
* selection changes. This allows such logic to be consolidated and managed in one place.
* The semantics argument is optional and provides additional information which can be
* used by the controller during event handling.
*/
onSwitchPage: function(pageId, semantics){
var mname = "onSwitchPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// Mashup fix, do not refresh current page.
if (pageId == this.currentPageId && !com.ibm.mm.builder.utils.pageUtil.isRoot(pageId)) {
if (this.spaceAcc.getSpaceID()!==null && this.spaceAcc.getSpaceID()!==undefined &&
this.lastSpaceId!==null && this.lastSpaceId!==undefined) {
if (this.spaceAcc.getSpaceID()===this.lastSpaceId) {
lgr.trace(mname, "skipping switchPage handling as already the current page");
lgr.exiting(mname, arguments);
return;
}
}
else {
lgr.trace(mname, "skipping switchPage handling as already the current page");
lgr.exiting(mname, arguments);
return;
}
}
// end fix
// D18206
// When switching a page, check if the page is a global page.
// If it is not, remember it as the last non-global page opened.
// The lastNonGlobalPageId variable is used in switchSpaceHandler() to set the last non-global
// page visited in that space.
if (!this._isOpenedGlobalPage(pageId)) {
this.lastNonGlobalPageId = pageId;
}
if (pageId && com.ibm.mm.builder.utils.spaceUtil.getSpaceIdByPageId(pageId)!=this.globalPageLoadedSpaceId
&& !this._isOpenedGlobalPage(pageId)){
// clear the global pages, as we've switched to a different space from the one where the pages were opened
this.onClearGlobalPage();
}
this._changingSelection = true;
this.nm.find(pageId).setFinishedCallback(dojo.hitch(this, "switchPageHandler"), semantics).start(false);
this.lastSpaceId = this.getCurrentSpaceId();
lgr.exiting(mname, arguments);
},
/**
* Handles the SWITCH_PAGE event to normalize the selection, potentially modifying it
* before updating internal models and firing the PAGE_SWITCHED event. Takes
* the navigation node whose ID is equal to the payload of the SWITCH_PAGE event.
*/
switchPageHandler: function(pageNode, status, semantics) {
var mname = "switchPageHandler", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if (this.renderMode != "iwidget") {
// If we're in SSA mode, perform a full page refresh
lgr.trace(mname, "Current rendertype: ${0} - performing a full page refresh", [this.renderMode]);
this._reloadToPageWithConfirm(pageNode.getID());
} /*** End SSA switch check ***/
else {
/*** Begin page node is label check ***/
var isLabel = this._isNavLabel(this.nm, pageNode);
lgr.trace(mname, "Is ${0} a label? ${1}", [pageNode, isLabel]);
if(isLabel) {
this._findFirstVisible(pageNode, dojo.hitch(this, function(node){
if(node) {
this.evtSvc.broadcastEvent(this.builderEvents.SWITCH_PAGE, node.getID());
}
else {
lgr.trace(mname, "Could not find visible non-label descendant of ${0}, loading directly", [pageNode]);
return this._postLabelCheck(pageNode, semantics);
}
}));
} /*** End page node is label check ***/
else {
this._postLabelCheck(pageNode, semantics);
}
}
lgr.exiting(mname, arguments);
},
setLastNonGlobalPage: function() {
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
es.broadcastEvent("com.ibm.mashups.builder.switchPage", this.lastNonGlobalPageId);
this.onClearGlobalPage();
},
clearLoginFlag: function() {
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_login_flag, null, {expires: -1});
},
_postLabelCheck: function(pageNode, semantics) {
var mname = "_postLabelCheck", lgr = this.LOGGER;
lgr.entering(mname, arguments);
/*** Begin SSA switch check ***/
var renderType = this.getRenderMode(pageNode);
if (renderType.toLowerCase() != "iwidget") {
// If we are going into SSA mode, perform a full page refresh
lgr.trace(mname, "Switched page rendertype: ${0} - performing a full page refresh", [renderType]);
this._reloadToPageWithConfirm(pageNode.getID());
} /*** End SSA switch check ***/
else {
/*** Begin theme template check ***/
var themeTemplate = this.getThemeTemplate(pageNode).toLowerCase();
if (themeTemplate != this.currentThemeTemplate &&
!((themeTemplate === "" && this.currentThemeTemplate === "theme.html") ||
(themeTemplate === "theme.html" && this.currentThemeTemplate === ""))) {
lgr.trace(mname, "Switched theme template from ${0} to ${1}", [this.currentThemeTemplate, themeTemplate]);
this._reloadToPageWithConfirm(pageNode.getID());
} /*** End theme template check ***/
else {
/*** Begin theme profile check ***/
var themeProfile = this.getThemeProfile(pageNode).toLowerCase();
if (themeProfile != this.currentThemeProfile) {
lgr.trace(mname, "Switched theme profile from ${0} to ${1}", [this.currentThemeProfile, themeProfile]);
this._reloadToPageWithConfirm(pageNode.getID());
} /*** End theme profile check ***/
else {
this.currentThemeTemplate = themeTemplate;
this.currentThemeProfile = themeProfile;
/*** Begin global page check ***/
this._postGlobalPageCheck(pageNode, semantics);
/*** End global page check ***/
}
}
}
lgr.exiting(mname, arguments);
},
_postGlobalPageCheck: function(pageNode, semantics) {
var mname = "_postGlobalPageCheck", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var cb = dojo.hitch(this, function(){
//this.isSwitching = true;
try{
this.refresh(pageNode.getID(), true, semantics);
}catch(e){
// if an error occurs during refresh, make sure we reset our _changingSelection
// state
this._changingSelection = false;
lgr.severe(mname, "An error occured during page switching ${0}", [e]);
}
// refresh() will ensure that _changingSelection is reset appropriately when all
// processing is completed
});
this.dirtyPageCheck(cb);
lgr.exiting(mname, arguments);
},
/**
* Sets the browser title using the title of the pageNode as part of the new title.
* This is called when a SWITCH_PAGE event proceeds passed all normalization
* steps to ensure that a proper selection is chosen.
* Extensions may override this to provide custom implementations.
*/
setBrowserTitle: function(pageNode) {
var mname = "setBrowserTitle", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var pageTitle = "";
if(this.nm.getRoot().start().getID() != pageNode.getID()) {
pageTitle = this.treeModel.getLabel(pageNode);
}
var trimmedTitle = dojo.trim(pageTitle || ""),
pageContext = com.ibm.mashups.enabler.context.Factory.getPageContext();
// use the enabler API to set the HTML page title in browser
if (pageContext) {
var product = this.configSvc.getValue(this.configConstants.PRODUCT_NAME);
if(product) {
if (!pageTitle || trimmedTitle === "") {
pageContext.setBrowserTitle(product);
}
else {
pageContext.setBrowserTitle(pageTitle);
}
}
else if(pageTitle && trimmedTitle !== ""){
pageContext.setBrowserTitle(pageTitle);
}
}
lgr.exiting(mname, arguments);
},
dirtyPageCheck: function(callback, callbackNoSave, cancelcb){
var mname = "dirtyPageCheck", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if(com.ibm.pb.contextMenu.sharedActions.widgetEditModeChecker()) {
// skip the page dirty check and display another confirm dialog if there is unsaved widget
lgr.exiting(mname, arguments);
return;
}
if(this.runtimeModel.getCurrentPage().isDirty()){
lgr.trace(mname, "Page is dirty, display confirmation dialog", []);
var cws = com.ibm.mm.builder.coreWidgetsStrings;
/* Late lazy load */
dojo["require"]("com.ibm.mm.builder.dialog.PageSaveConfirmDialog");
var saveConfirmDlg = new com.ibm.mm.builder.dialog.PageSaveConfirmDialog({
contentWarning: cws.I_PAGE_SAVE_WARNING,
contentQuestion: cws.I_PAGE_SAVE_SUGGEST,
btnSaveText: cws.I_COMMON_SAVE,
btnNotSaveText: cws.I_PAGE_SAVE_NO_SAVE,
btnCancelText: cws.I_PAGE_SAVE_KEEP_EDIT,
hideNotSave: true,
callbackSave: callback,
callbackNotSave: callbackNoSave,
callbackCancel: cancelcb
});
saveConfirmDlg.show();
}else{
lgr.trace(mname, "Page is NOT dirty, callback immediately", []);
if(callback) callback();
}
lgr.exiting(mname, arguments);
},
_reloadToPageWithConfirm: function(pageId) {
var cb = dojo.hitch(this, this.reloadToPage, pageId);
this.dirtyPageCheck(cb);
},
reloadToPage: function(pageId) {
var mname = "reloadToPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var pageNode = this.nm.find(pageId).start();
if(pageNode) {
this._setCurrentNavNode(pageNode);
}
var redirectAddress = com.ibm.mashups.enabler.model.state.UrlGeneratorFactory.getUrlGenerator().getUrl(this.nsm, null, {skipState: true, pocURI: "nm:oid:"+pageId});
lgr.trace(mname, "Navigating to URL immediately ${0}", [redirectAddress]);
lgr.exiting(mname, arguments);
// set the pageID cookie
com.ibm.mm.builder.utils.navigationUtil.setPageIDCookie(pageId);
var oldAddress = top.location.href;
top.location.href = redirectAddress;
if(this._removeHash(oldAddress) == this._removeHash(redirectAddress)) {
setTimeout(function() {
// this is a special marker with which certain extensions can behavior differently. In this particular case
// it allows to write an unload extension that can differentiate from a normal browser close vs a refresh caused by mashups
window.__page_reload_marker = true;
// if we simply changed the hash, then setting the location before won't force a page refresh
// so we force it here, attempting to minimize performance hit by getting from cache if possible
top.location.reload(false);
}, 50);
}
},
_removeHash:function(s){
var hash = s.indexOf("#");
if(hash >= 0) {
s = s.substring(0,hash);
}
return s;
},
onRefreshNavigation:function(){
this.LOGGER.entering("onRefreshNavigation", arguments);
try{
this.refresh();
}catch(e){
var msg = dojo.string.substitute(com.ibm.mm.builder.coreWidgetsMessages.E_NAV_REFRESH_NAVIGATION_1,[e.message]);
this.LOGGER.severe("onRefreshNavigation",msg);
setTimeout(function(){
throw e; // the window can catch this and handle it outside our execution thread
}, 1);
}
this.LOGGER.exiting("onRefreshNavigation", arguments);
},
/**
* Refreshes the navigation selection in the controller, potentially changing it
* depending on the value of the pid parameter.
*/
refresh: function(pid, isPageSwitch, semantics){
var mname = "refresh", lgr = this.LOGGER, me = this, node, contentNode, spaceId = this.getCurrentSpaceId();
lgr.entering(mname, arguments);
if(pid) {
// check if we have bootstrapped before and have a current page set already
if(!this.bootstrapping) {
/*** begin theme change check ***/
lgr.trace(mname, "Checking for theme change");
var currentThemeID = this.runtimeModel.getCurrentTheme().getID();
var pageNode = this.nm.find(pid).start();
if (pageNode && this.getThemeId(pageNode) != currentThemeID) {
lgr.trace(mname, "Theme changed!");
var cb = dojo.hitch(this, this.reloadToPage, pid);
this.dirtyPageCheck(cb);
lgr.exiting(mname, arguments);
// don't set this._changingSelection to false because we're doing a full page refresh
// and want it to stick until the browser reloads
return;
}
/*** end theme change check ***/
}
else {
// We're actually bootstrapping, so don't act like we're switching pages from an already selected page
if(!semantics) {
semantics = {};
}
semantics.skipStateUpdate = !this._bootstrapState;
lgr.trace(mname, "Bootstrapping to current page ${0}", [pid]);
}
}
else {
pid = this.getCurrentPageId();
if(!pid){
lgr.trace(mname, "Find the first visible page from the current root");
this.getRootNavigation(function(item){
lgr.trace(mname, "Initiate page switch to ${0}", item);
me.refresh(me.treeModel.getIdentity(item), isPageSwitch);
}, function(err){
this._changingSelection = false;
lgr.severe(mname, "Error getting root navigation ${0}", err.message);
setTimeout(function(){throw err;}, 1);
});
lgr.exiting(mname, arguments);
return;
}
}
// defect 16614
// if the we are in nav root, we need to find whether there is child page visible
// this page can be added from shares or hub
var navRoot = this.nm.getRoot().start();
if(pid == navRoot.getID()) {
var interruptProcessing = false;
this._findFirstVisible(navRoot, dojo.hitch(this, function(child){
if(child && !(child instanceof Error)) {
interruptProcessing = true;
this.onSwitchPage(child.getID());
return;
}
}));
if (interruptProcessing) {
// we already found the correct page and initiated a page switch, no need to continue
lgr.exiting(mname, arguments);
return;
}
}
// the nav must be reloaded on every refresh because deleting
// a page is handled the same as switching the page. Since there
// is no way to tell whether a page has been deleted we must
// reload the nav to make sure the page is removed from the markup.
// This will be fixed once Mashups created a deletePage iEvent.
if(pid){
lgr.trace(mname, "Reloading navigation");
node = this.nm.find(pid).start();
if(node) {
// node may have been deleted
this._setCurrentNavNode(node, semantics);
}
}
this._changingSelection = false;
if(isPageSwitch) {
var nsm = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
lgr.trace(mname, "Setting timeout to fire page switched event later");
setTimeout(dojo.hitch(this, function(){
lgr.trace(mname, "Sending page switched event");
this.runtimeModel.getCurrentPage().setDirty(false);
this.evtSvc.broadcastEvent(this.builderEvents.PAGE_SWITCHED, pid);
}), 50);
}
lgr.exiting(mname, arguments);
},
/**
* The optional semantics arguments allows additional semantic information to be provided
* in paths where custom logic is required based on the context and circumstances.
*
* The skipStateUpdate property specifies whether or not the state should be updated when
* the controller sets the current nav node. The reason for this is because this function may
* be fired by listening to the SWITCH_PAGE event, in which case the navigation state
* should be updated by the controller. Alternatively, this function may be called
* on a path where the controller detects a NAVSTATE_UPDATED event separate
* from a SWITCH_PAGE event, but detects that the selection has changed as part of that
* state change. In that case, the controller should not update the state since it
* has already been updated and the controller is merely synchronizing its internal
* models to reflect the new state. If skipStateUpdate is true, then this does NOT
* update the navigation state.
*/
_updateNavigationState: function(pageId, semantics){
var mname = "_updateNavigationState", lgr = this.LOGGER;
lgr.entering(mname, arguments);
this.runtimeModel.getCurrentPage().setID(pageId);
if(!semantics || !semantics.skipStateUpdate) {
// Do not update the navigation state if semantics.skipStateUpdate is truthy
var spaceId = com.ibm.mm.builder.utils.spaceUtil.getSpaceIdByPageId(pageId);
if (spaceId !== com.ibm.mm.builder.utils.spaceUtil.getCurrentSpaceId()) {
com.ibm.mm.builder.utils.spaceUtil.setSpaceId(spaceId);
}
this.accFactory.getPageAccessor(this.nsm, spaceId).setPageID(pageId);
this.navigationStateUpdated = true; // for testing in _processHashChange, to avoid firing page switch
this.nsm.commit({addToHistory: true}).start();
}
lgr.exiting(mname, arguments);
},
onOpenPage: function(iEvent){
var mname = "onOpenPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// there are two kinds of payload format for ievent com.ibm.mashups.builder.openPage
// 1. payload is a string : the page id, just switch to the page.
// 2. payload is a JSON object : {"pid":"123456",eventsArray:{{"targetEvent": targetEvent1, "payload": payload1, "payloadType": payloadType1},{"targetEvent": targetEvent2, "payload": payload2, "payloadType": payloadType2}}}
var openPageId = null;
if (iEvent.payload.pid){
openPageId = iEvent.payload.pid;
}else{
openPageId = iEvent.payload;
}
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
es.broadcastEvent("com.ibm.mashups.builder.saveCheck", dojo.hitch(this,function(){
var mname = "onOpenPage_saveCheck", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if (this._isOpenedGlobalPage(openPageId)) {
// if the global page is already opened, switch to it and reload it.
}else{
// otherwise this is a new global page, not currently open
this.lastVisitedPage = com.ibm.mm.builder.utils.pageUtil.getCurrentPageId();
if (this.lastSpaceId) {
this.globalPageLoadedSpaceId = this.lastSpaceId;
} else {
this.globalPageLoadedSpaceId = this.getCurrentSpaceId();
}
this._addToGlobalPages(openPageId, this.lastVisitedPage);
//create new tab in the tabbed navigation, and navigate to the new tab, with event broadcast to the page.
var openPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(openPageId);
var globalSpaceRoot = com.ibm.mm.builder.utils.navigationUtil.getNavigationRootNode(this.globalPageLoadedSpaceId);
var args = {
title:openPage.getTitle(dojo.locale),
pageLoadedSpaceId:this.globalPageLoadedSpaceId,
openPageId: openPageId
};
if (iEvent.payload.pid){
args.eventsArray = iEvent.payload.eventsArray;
args.lastVisitedPage = this.lastVisitedPage;
}
this.treeModel.newGlobalItem(args, globalSpaceRoot);
lgr.trace(mname, "Broadcasting refreshNavigation event");
es.broadcastEvent("com.ibm.mashups.builder.refreshNavigation");
}
setTimeout(dojo.hitch(this, function(){
lgr.trace("onOpenPage_Timeout", "Broadcasting switch page event");
if (iEvent.payload.eventsArray) {
es.broadcastEvents(iEvent.payload.eventsArray, com.ibm.mm.builder.utils.pageUtil.getCurrentPageId(), openPageId);
} else {
es.broadcastEvent("com.ibm.mashups.builder.switchPage", openPageId);
}
}), 50);
lgr.exiting(mname, arguments);
}));
lgr.exiting(mname, arguments);
},
onClosePage: function(iEvent){
var mname = "onClosePage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
var closePageId = null;
if (iEvent.payload) {
if (iEvent.payload.closePageId) {
closePageId = iEvent.payload.closePageId;
} else if (!iEvent.payload.eventsArray) {
closePageId = iEvent.payload;
}
}
if (!closePageId) {
closePageId = com.ibm.mm.builder.utils.pageUtil.getCurrentPageId();
}
if (!this._isOpenedGlobalPage(closePageId)){
console.log("Error: you are closing a global page not opened now!");
return;
}
var es = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
es.broadcastEvent("com.ibm.mashups.builder.saveCheck", dojo.hitch(this,function(){
var mname = "onClosePage_saveCheck", lgr = this.LOGGER;
lgr.entering(mname, arguments);
// go to last visited non-global page
var openedPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(closePageId);
var args = {
"lastVisitedPage": this._getGlobalPageOpenedBy(closePageId)
};
if (iEvent.payload && iEvent.payload.openPagePayload){
args.openPagePayload = iEvent.payload.openPagePayload;
}
this._removeFromGlobalPages(closePageId);
this.treeModel.deleteGlobalItem(args,openedPage);
this.evtSvc.publishEvent(this.builderEvents.REFRESH_NAVIGATION);
setTimeout(dojo.hitch(this, function(){
lgr.trace("onClosePage_Timeout", "Broadcasting switch page event");
if (args.openPagePayload){
// do not switch to the last visited non-global page, we will open another global page instead.
es.broadcastEvent("com.ibm.mashups.builder.openPage", args.openPagePayload);
}else{
if (iEvent.payload && iEvent.payload.eventsArray) {
es.broadcastEvents(iEvent.payload.eventsArray, null, args.lastVisitedPage, this.globalPageLoadedSpaceId);
} else {
es.broadcastEvent("com.ibm.mashups.builder.switchPage", args.lastVisitedPage);
}
}
}), 50);
lgr.exiting(mname, arguments);
}));
lgr.exiting(mname, arguments);
},
onClearGlobalPage:function(){
var mname = "onClearGlobalPage", lgr = this.LOGGER;
lgr.entering(mname, arguments);
for (var i in this.globalPagesOpened) {
var openedPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(this.globalPagesOpened[i]);
var args = {"lastVisitedPage":this.lastVisitedPage};
this.treeModel.deleteGlobalItem(args,openedPage);
}
this.globalPagesOpened = [];
this.globalPagesOpenedBy = [];
this.globalPageLoadedSpaceId = null;
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageId, null, {expires: -1});
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId, null, {expires: -1});
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_previous_pid, null, {expires: -1});
lgr.exiting(mname, arguments);
},
_isOpenedGlobalPage: function(pageId){
for (var i in this.globalPagesOpened) {
if (this.globalPagesOpened[i] == pageId) {
return true;
}
}
return false;
},
_addToGlobalPages: function(pageId, openerPageId) {
// find the index of the page to be deleted
var pageIndex = -1;
for (var i in this.globalPagesOpened) {
if (this.globalPagesOpened[i] == pageId) {
pageIndex = i;
}
}
if (pageIndex >= 0) { // page already opened, just update info
this.globalPagesOpened[pageIndex] = pageId;
this.globalPagesOpenedBy[pageIndex] = openerPageId;
} else { // new global page
this.globalPagesOpened.push(pageId);
this.globalPagesOpenedBy.push(openerPageId);
}
this._persistGlobalPages();
},
_removeFromGlobalPages: function(pageId){
// find the index of the page to be deleted
var pageIndex = -1;
for (var i in this.globalPagesOpened) {
if (this.globalPagesOpened[i] == pageId) {
pageIndex = i;
}
}
if (pageIndex >= 0) {
// If there are any global pages that were opened by this global page, update
// the opened by so they would return to the opener of this (deleted) global page
for (var i in this.globalPagesOpened) {
if (this.globalPagesOpenedBy[i] == pageId) {
this.globalPagesOpenedBy[i] = this.globalPagesOpenedBy[pageIndex];
}
}
// delete the page
this.globalPagesOpened.splice(pageIndex, 1);
this.globalPagesOpenedBy.splice(pageIndex, 1);
}
this._persistGlobalPages();
},
_getGlobalPageOpenedBy: function(pageId) {
for (var i in this.globalPagesOpened) {
if (this.globalPagesOpened[i] == pageId) {
return this.globalPagesOpenedBy[i];
}
}
return null;
},
_persistGlobalPages: function(){
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageId,dojo.toJson(this.globalPagesOpened));
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_previous_pid,dojo.toJson(this.globalPagesOpenedBy));
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId,this.globalPageLoadedSpaceId);
},
_restorePersistedGlobalPages: function(){
if (dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId)) {
this.globalPagesOpened = dojo.fromJson(dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageId));
this.globalPagesOpenedBy = dojo.fromJson(dojo.cookie(com.ibm.mm.builder.constant.cookieKey_previous_pid));
this.globalPageLoadedSpaceId = dojo.cookie(com.ibm.mm.builder.constant.cookieKey_globalPageOpenedSpaceId);
for (var i in this.globalPagesOpened) {
var openedPage = com.ibm.mm.builder.utils.pageUtil.getPageNode(this.globalPagesOpened[i]);
var globalSpaceRoot = com.ibm.mm.builder.utils.navigationUtil.getNavigationRootNode(this.globalPageLoadedSpaceId);
var args = {
title:openedPage.getTitle(dojo.locale),
pageLoadedSpaceId:this.globalPageLoadedSpaceId,
openPageId: this.globalPagesOpened[i]
};
this.treeModel.newGlobalItem(args, globalSpaceRoot);
}
}
},
_processHashChange: function(/*string*/hash) {
var mname = "_processHashChange", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if (!this.navigationStateUpdated) {
var hashDec = decodeURIComponent(hash);
var hashObj = dojo.queryToObject(hashDec);
if (hashObj.pid) {
var eventService = com.ibm.mashups.services.ServiceManager.getService("eventService");
eventService.publishEvent(com.ibm.mashups.builder.iEvents.SWITCH_PAGE, hashObj.pid);
}
}
this.navigationStateUpdated = false;
lgr.exiting(mname, arguments);
},
onUnLoad: function(){
var mname = "onUnLoad", lgr = this.LOGGER;
lgr.entering(mname, arguments);
if (this.tabNavigation) {
this.tabNavigation.destroy();
this.tabNavigation = null;
}
lgr.exiting(mname, arguments);
}
});
(function(){
var controller = null;
com.ibm.pb.control.NavigationController.getController = function() {
if(!controller) {
controller = new com.ibm.pb.control.NavigationController();
}
return controller;
};
})();
}
if(!dojo._hasResource["com.ibm.pb.iwidget.PageModeWidgetHandler"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.iwidget.PageModeWidgetHandler"] = true;
dojo.provide("com.ibm.pb.iwidget.PageModeWidgetHandler");
/**
* This module is used when parsing the page at initialization time to detect
* iwidgets that are only used in certain page modes and to dynamically turn them
* into lazy-loading iwidgets by using a rendering controller like the
* com.ibm.pb.control.RenderingController with the addModeWidgets function.
* It's the RenderingController's responsibility to load those iwidgets when
* the a particular page mode is entered for the first time.
*/
dojo.declare("com.ibm.pb.iwidget.PageModeWidgetHandler", null, {
CLASS_PREFIX: "pb-pageMode-",
renderingController: null,
matchingModes: [],
constructor: function(args) {
dojo.safeMixin(this, args);
if(!this.matchingModes) {
this.matchingModes = [];
}
this.modeWidgets = {};
dojo.forEach(this.matchingModes, function(mode){
this.modeWidgets[mode] = [];
}, this);
},
preProcessCallbackFunc: function(domNode, livetextList, tagEntry) {
if(this.renderingController && this._isMatchingIWidgets(tagEntry)) {
dojo.forEach(livetextList, function(node){
for(var mode in this.modeWidgets) {
if(dojo.hasClass(node, this.CLASS_PREFIX + mode)) {
// if this inline iwidget declaration specifies
// a class name with the given CLASS_PREFIX and
// a mode we're matching, then turn it into a lazy-
// loaded iwidget for that page mode
node.setAttribute("lazyLoad", "true");
var id = node.getAttribute("id");
this.modeWidgets[mode].push(id);
this.renderingController.addModeWidgets(mode, [id]);
}
}
}, this);
}
},
postProcessCallbackFunc: function(domNode, livetextList, errors, tagEntry) {
// no-op
},
_isMatchingIWidgets: function(tagEntry) {
return tagEntry.match && tagEntry.match.indexOf(".iw-iWidget") > -1;
}
});
}
if(!dojo._hasResource["com.ibm.pb.data.NavigationPrimer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.data.NavigationPrimer"] = true;
dojo.provide("com.ibm.pb.data.NavigationPrimer");
dojo.declare("com.ibm.pb.data.NavigationPrimer", com.ibm.pb.logging.Loggable, {
LEVEL_ATTR: "data-nm-level",
PRIMED_ATTR: "data-nm-primed",
END: {},
selPath: null, // Array of selection path starting from root going down towards selected node
map: null, // Object map of priming node data with keys as node ids
constructor: function() {
this.selPath = [];
this.map = {};
},
parse: function(domNode) {
var mname = "parse", lgr = this.LOGGER;
lgr.entering(mname, [domNode]);
domNode = dojo.byId(domNode);
var level = dojo.attr(domNode, this.LEVEL_ATTR);
if(level !== null && level !== undefined) {
lgr.trace(mname, "Priming the parse root node itself");
this._prime(domNode);
}
// now look for descendants that may have the level attribute defined
var levelNodes = dojo.query("[" + this.LEVEL_ATTR + "]", domNode);
if(levelNodes.length > 0) {
levelNodes.forEach(this._prime, this);
}
else {
lgr.trace(mname, "No level nodes detected in descendant nodes");
lgr.exiting(mname, [null]);
return;
}
lgr.exiting(mname, [domNode]);
},
_prime: function(domNode) {
var mname = "_prime", lgr = this.LOGGER;
lgr.entering(mname, [domNode]);
var level = dojo.attr(domNode, this.LEVEL_ATTR);
var nodeData = this.extractData(domNode);
if(nodeData) {
this.addItem(nodeData);
if(!this.selPath[level]) {
lgr.trace(mname, "No previous selection path data at level ${0}", [level]);
}
}
else {
if(this.selPath[level]) {
nodeData = this.selPath[level];
lgr.trace(mname, "No data provided for selection path data, using previously known", []);
}
else {
lgr.trace(mname, "No data provided for selection path data, and no previous data to use", []);
lgr.exiting(mname, []);
return;
}
}
nodeData = this.byId(nodeData.id);
this.selPath[level] = nodeData;
lgr.trace(mname, "Priming selection path data at level ${0}", [level]);
var childNodes = dojo.query("[" + this.PRIMED_ATTR + "]", domNode);
if(childNodes.length > 0) {
lgr.trace(mname, "Found children of ${0}", [nodeData.id]);
if(!nodeData.children) {
nodeData.children = [];
}
childNodes.forEach(function(childDomNode){
var childData = this.extractData(childDomNode);
if(childData) {
lgr.trace(mname, "Adding child ${0} of ${1}", [childData.id, nodeData.id]);
this.addItem(childData);
childData = this.byId(childData.id);
nodeData.children.push(childData);
}
}, this);
nodeData.children.push(this.END);
}
else {
lgr.trace(mname, "Found NO children of ${0}", [nodeData.id]);
}
lgr.exiting(mname, [nodeData]);
},
addItem: function(data){
var mname = "addItem", lgr = this.LOGGER;
if(data && data.id) {
if(this.map[data.id]) {
// data already primed... mix in any additional attributes
lgr.trace(mname, "Adding properties ${0} for ${1} to existing data", [data, data.id]);
dojo.mixin(this.map[data.id], data);
}
else {
// data not primed yet
lgr.trace(mname, "Adding new data ${0} for ${1}", [data, data.id]);
this.map[data.id] = data;
}
}
},
byId: function(id) {
return this.map[id];
},
_normalizeType: function(type) {
type = type ? type.toLowerCase() : "page";
switch(type) {
case "internalurl":
case "externalurl":
type = "url";
break;
case "staticpage":
type = "page";
break;
}
return type;
},
extractData: function(domNode) {
var mname = "extractData", lgr = this.LOGGER;
var data = dojo.attr(domNode, this.PRIMED_ATTR);
if(data) {
data = dojo.fromJson(data);
data.locale = ibmConfig.locale;
data.type = this._normalizeType(data.type);
lgr.trace(mname, "Extracted data ${0}", [data]);
}
else {
data = null;
}
return data;
},
finalize: function() {
var mname = "finalize", lgr = this.LOGGER;
for(var i=this.selPath.length-1; i>=0; i--) {
if(i > 0) {
if(this.selPath[i-1]){
if(!this.selPath[i-1].children) {
this.selPath[i-1].children = [this.selPath[i]];
}
else if(this.selPath[i-1].children.length == 0) {
// pushing the END marker onto the beginning along with other nodes
// specifies that this set of children is incomplete, but that it
// doesn't start at the beginning; hence the system will get all
// children from the model if getChildren is called on this parent
this.selPath[i-1].children.push(this.END, this.selPath[i]);
}
}
}
}
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel();
if(lgr.isLoggable(com.ibm.mashups.enabler.logging.LogLevel.TRACE)) {
lgr.trace(mname, "Priming navigation model ${0}", [this]);
lgr.trace(mname, "Priming data:\n ${0}", [dojo.toJson(this.selPath[0], true)]);
}
var firstDefined;
for (var i = 0; i < this.selPath.length; i++){
if (firstDefined == null && this.selPath[i]){
firstDefined = i;
}
}
nm.setPrimingData(this.selPath[firstDefined]);
}
});
}
if(!dojo._hasResource["com.ibm.pb.themes.commonInit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["com.ibm.pb.themes.commonInit"] = true;
dojo.provide("com.ibm.pb.themes.commonInit");
dojo.require("dojo.i18n");
com.ibm.pb.themes.commonInit = function(initArgs) {
if (!initArgs) {
initArgs = {};
}
var lgr = com.ibm.mashups.enabler.logging.Logger.getLogger("com.ibm.pb.themes.commonInit"), mname = "commonInit", sharedMessages = dojo.i18n.getLocalization("com.ibm.bundles", "SharedMessages");
lgr.entering(mname);
if(ibmConfig.primeNavigation) {
lgr.trace(mname, "Priming navigation model");
var np = new com.ibm.pb.data.NavigationPrimer();
dojo.query(".wpthemeNavList, #wpthemePrimeRoot").forEach(np.parse, np);
if(np.selPath.length > 0) np.finalize();
ibmCfg.themeConfig.navigationPrimed = true;
}
var evtSvc = com.ibm.mashups.iwidget.services.ServiceManager.getService("eventService");
lgr.trace(mname, "Initializing navigation model and HiddenMetaDataLoadingStrategy");
/* Initialize the theme's HiddenMetaDataLoadingStrategy on the navigation model */
var nm = com.ibm.mashups.enabler.navigation.Factory.getNavigationModel(), hiddenMdStrategy = new com.ibm.mashups.enabler.strategy.HiddenMetaDataLoadingStrategy(ibmCfg.themeConfig.navHiddenMetadata);
nm.addStrategy(hiddenMdStrategy);
lgr.trace(mname, "Initializing navigation node to content node meta data sync strategy");
var syncStrategy = new com.ibm.mashups.enabler.strategy.SyncMetaDataStrategy();
nm.addStrategy(syncStrategy);
var currentPageId = null;
var testPage = null;
var redirect = false;
var statehash = null;
var isLogInAction = false;
if (dojo.cookie(com.ibm.mm.builder.constant.cookieKey_login_flag)) {
dojo.cookie(com.ibm.mm.builder.constant.cookieKey_login_flag, null, {expires: -1}); // Remove the cookie
isLogInAction = true;
}
// 1, get page ID from cookie, which is passed when login
// IT IS IMPORTANT THAT THIS CODE RUNS BEFORE THE NAVIGATION STATE MODEL IS FETCHED.
if(dojo.cookie("url_pid")) {
statehash = dojo.cookie("url_pid");
dojo.cookie("url_pid", null, {expires: -1, path: "/"});
// we still have JUST the pid in the cookie. For those cases we need to prefix the ID with pid=
if (statehash.indexOf("pid=")!=0) {
// there is no pid in front, so we have to add it
statehash = "pid=" + statehash;
}
window.location.hash = "#"+encodeURIComponent(statehash);
}
/* Initalize the builder API RuntimeModel using the SPIs using the current context */
lgr.trace(mname, "Initializing builder RuntimeModel");
var navStateModel = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
var pageAccessor = com.ibm.mashups.enabler.model.state.AccessorFactory.getPageAccessor(navStateModel);
var spaceAccessor = com.ibm.mashups.enabler.model.state.AccessorFactory.getSpaceAccessor(navStateModel);
// 2, get the pid from the nav state
// if statehash is definied, then the server or login form is telling us via the url_pid
// cookie where we should be directed. we also want to execute this code block
// if we need to go to the last page visited on login
var goToLastPageVisited = com.ibm.mm.builder.utils.navigationUtil.isLastPageWhenLogin();
if (statehash || goToLastPageVisited || !isLogInAction) {
currentPageId = pageAccessor.getPageID();
if (!currentPageId) {
currentPageId = ibmPortalConfig.currentPageOID;
lgr.trace(mname, "Could not retrieve selected page from navigation state, retrieving from bootstrap config: ${0}", [currentPageId]);
if ("-1" !== currentPageId) {
pageAccessor.setPageID(currentPageId);
}
}
if ("-1" !== currentPageId) {
//testPage = nm.find(currentPageId).start();
}
}
// 3, try to get the page from shared navigation
// this will take effect after you login, in this case cookie:url_pid is not exist
if(!testPage && currentPageId && goToLastPageVisited) {
if (currentPageId !== ibmPortalConfig.currentPageOID) {
var snm = com.ibm.mashups.enabler.navigation.Factory.getSharedNavigationModel();
var sharedPage = snm.find(currentPageId).start(true); // 404 if not found
if (sharedPage && !snm.isAccepted(sharedPage)) {
var sharedPageRoot = nm.findDefaultAcceptParent().start(true);
if (sharedPageRoot) {
// auto accept the page
nm.insert(sharedPage, sharedPageRoot);
nm.commit().start(true);
testPage = sharedPage;
}
}
}
}
// 4, home space - bspace case/overridden navstate preprocess
if (!testPage && (!goToLastPageVisited && isLogInAction)) {
testPage = com.ibm.mm.builder.utils.navigationUtil.gotoHomeSpace();
if (testPage) {
if ((currentPageId) && ("-1" != currentPageId)) {
// if a currentPageId has been set above it means that we could not navigate to it. therefore we will now be redirected
redirect = true;
}
currentPageId = testPage.getID();
pageAccessor.setPageID(currentPageId);
}
}
pageAccessor.setPageID(currentPageId);
navStateModel.commit({addToHistory: true}).start();
var runtimeModel = com.ibm.mashups.builder.model.Factory.getRuntimeModel();
var currentPage = runtimeModel.getCurrentPage();
currentPage.setID(currentPageId);
if(typeof ibmToolbarConfig != "undefined") {
lgr.trace(mname, "Setting page mode for current page using ibmToolbarConfig: ${0}", [ibmToolbarConfig.toolbarMode]);
currentPage.setPageMode(ibmToolbarConfig.toolbarMode != "closed" ? "edit" : "view");
} else {
var pageMode = dojo.hasClass(dojo.body(),"edit-mode") ? "edit" : "view";
lgr.trace(mname, "Setting page mode for current page using the edit-mode CSS class on the body element: ${0}", [pageMode]);
currentPage.setPageMode(pageMode);
}
runtimeModel.getCurrentTheme().setID(ibmCfg.themeConfig.themeUniqueName);
/* Initialize the theme's HiddenMetaDataLoadingStrategy on the layout model, needed to see container and control names */
var strategyService = com.ibm.mashups.services.ServiceManager.getService(com.ibm.mashups.enabler.services.StrategyService.SERVICE_NAME);
var s = new com.ibm.mashups.enabler.strategy.HiddenMetaDataLoadingStrategy(ibmCfg.themeConfig.layoutHiddenMetadata);
strategyService.setStrategy("com.ibm.mashups.enabler.layout.LayoutModel", s);
if (initArgs.setWindowTitle) {
var title = "";
var localizedContext = com.ibm.mashups.enabler.context.Factory.getLocalizedContext();
var currentPageTitle = localizedContext.getTitle(this.currentPage);
if (dojo.isString(ibmCfg.themeConfig.portletOverridePageTitle) && ibmCfg.themeConfig.portletOverridePageTitle != currentPageTitle) {
title = ibmCfg.themeConfig.portletOverridePageTitle.replace(/&/g, "&").replace(/"/g, '"').replace(/>/g, ">").replace(/</g, "<");
} else {
title = currentPageTitle;
}
com.ibm.mashups.enabler.context.Factory.getPageContext().setBrowserTitle(title);
}
if (initArgs.useNavigationController) {
/* Initialize the navigation controller */
lgr.trace(mname, "Initializing navigation controller");
ibmCfg.controllers.navigation = com.ibm.pb.control.NavigationController.getController();
}
if (initArgs.useRenderingController) {
/* Initialize the rendering controller */
lgr.trace(mname, "Initializing rendering controller");
ibmCfg.controllers.rendering = com.ibm.pb.control.RenderingController.getController();
}
if (initArgs.useDNDController && dojo.getObject("com.ibm.pb.control.DNDController")) {
lgr.trace(mname, "Initializing page layout drag-and-drop controller");
/* Initialize the drag-and-drop controller for page layout DND actions */
ibmCfg.controllers.dnd = com.ibm.pb.control.DNDController.getController();
if (currentPage.getPageMode() == "edit") {
ibmCfg.controllers.dnd.init();
}
}
if (initArgs.serverRuntimeContentPrimingNode) {
}
if (initArgs.customInit) {
initArgs.customInit();
}
if (initArgs.initLiveTextService) {
i$.addOnLoad(function(){
lgr.trace(mname, "Initializing live text service");
var liveTextInitArgs = initArgs.liveTextInitArgs || {}, livetextService = com.ibm.mashups.services.ServiceManager.getService(com.ibm.mashups.livetext.ServiceModel.SERVICE_NAME);
if (initArgs.lazyLoadModeWidgets) {
var pageModeWidgetHandler = new com.ibm.pb.iwidget.PageModeWidgetHandler({
renderingController: ibmCfg.controllers.rendering,
matchingModes: ["edit"]
});
/* The pageModeWidgetHandler picks up widgets that are flagged to work in certain modes and prepares them to be lazy loaded until that mode is entered */
liveTextInitArgs.preProcessCallbackFunc = dojo.hitch(pageModeWidgetHandler, "preProcessCallbackFunc");
liveTextInitArgs.postProcessCallbackFunc = dojo.hitch(pageModeWidgetHandler, function() {
pageModeWidgetHandler.postProcessCallbackFunc(arguments);
// #14071 display message if the page is redirected
if (redirect) {
var msgTitle = com.ibm.mm.builder.coreWidgetsStrings.I_NAVIGATION_REDIRECT_TITLE ? com.ibm.mm.builder.coreWidgetsStrings.I_NAVIGATION_REDIRECT_TITLE : "You have been redirected";
var msgBody = com.ibm.mm.builder.coreWidgetsStrings.I_NAVIGATION_REDIRECT_TITLE_MESSAGE ? com.ibm.mm.builder.coreWidgetsStrings.I_NAVIGATION_REDIRECT_TITLE_MESSAGE : "You can't visit the page, because it has been deleted or you do not have authority.";
var statusMessage = new com.ibm.widgets.StatusMessage("info", msgTitle, msgBody);
dojo.publish("/message/status",[{message: statusMessage, uid: "ibmStatusBox"}]);
}
});
}
if(i$.fromPath("SemTagSvcPortalGlobal.isPersonCardHandlerRequired") && i$.fromPath("SemTagSvcPortalGlobal.isParsingRequired")) {
// Add person card livetext entries
var configEntryVCard = new com.ibm.mashups.livetext.ConfigEntry(".vcard", false, "portallof",SemTagSvcPortalGlobal.contextUrl+"/javascript", "portallof.vcard", false, "hcard");
dojo.publish("/com/ibm/mashups/livetext/configentryadded",[configEntryVCard]);
}
if(i$.fromPath("SemTagSvcPortalGlobal.isActionHandlerRequired") && i$.fromPath("SemTagSvcPortalGlobal.isParsingRequired")) {
// add person card extension
var configEntryAction = new com.ibm.mashups.livetext.ConfigEntry(".com\\.ibm\\.portal\\.action", false, "portallof", SemTagSvcPortalGlobal.contextUrl+"/javascript", "portallof.vcard", false, "com.ibm.portal.action");
dojo.publish("/com/ibm/mashups/livetext/configentryadded",[configEntryAction]);
}
if(i$.fromPath("SemTagSvcPortalGlobal.isC2AHandlerRequired") && i$.fromPath("SemTagSvcPortalGlobal.isParsingRequired")) {
// Add c2a livetext entries
var configEntryC2aSourceTarget = new com.ibm.mashups.livetext.ConfigEntry(".c2a\\:source,.c2a\\:target", false, "portallof", SemTagSvcPortalGlobal.contextUrl+"/javascript", "portallof.vcard", false, "c2a");
dojo.publish("/com/ibm/mashups/livetext/configentryadded",[configEntryC2aSourceTarget]);
}
// for legacy themes that have been modularized
if(i$.fromPath("com.ibm.pb.decorations.DECORATION_MANAGER")) {
var decorationsEntry = new com.ibm.mashups.livetext.ConfigEntry("*.component-control", true, "com.ibm.pb.decorations", ibmConfig["com.ibm.mashups.contextroot.builder"]+"/js/com/ibm/pb/decorations","com.ibm.pb.decorations.DecorationManager", true);
dojo.publish("/com/ibm/mashups/livetext/configentryadded",[decorationsEntry]);
}
/* Initialize the live text service, which will immediately parse the page for semantic content */
livetextService.init(liveTextInitArgs);
});
}
// moving this code from pagebuilder_ui to config.jso of wp_sametime_proxy module
/****
if(typeof(stproxy) != "undefined" && !stproxy.isLoggedIn &&
typeof(ibmCfg.portalConfig) != "undefined" && typeof(ibmCfg.portalConfig.currentUser) != "undefined" && ibmCfg.portalConfig.currentUser.length > 0) {
var tempUsername = ibmCfg.portalConfig.currentUser ;
if ( i$.fromPath("SemTagSvcPortalGlobal.newSametimeCommunityServer") ) { // Community Server is post 7.5.1
tempUsername = null; // we pass null to ST proxy and it retrieves username from ltpaToken
}
lgr.trace(mname, "Logging " + tempUsername + " onto Sametime");
stproxy.login.loginByToken(tempUsername, stproxy.awareness.AVAILABLE, stproxy.i18nStrings.statusAvailable, function(){lgr.info(mname,"Login passed and isLoggedIn is:"+stproxy.isLoggedIn);}, function() {
lgr.severe(mname, "Sametime login for " + tempUsername + " failed."); });
}
*********/
}
}
i$.addOnLoad(function(){
// call commonInit
com.ibm.pb.themes.commonInit({
setWindowTitle:false,
useNavigationController: true,
useRenderingController: true,
useDNDController: true,
initLiveTextService: true,
lazyLoadModeWidgets: true
});
// create the Portal operations
var portalOp = dojo.declare("com.ibm.portal.PortalOperation", [com.ibm.mashups.enabler.ac.operation.Operation], {
allowed: false,
constructor: function(allowed, finished) {
this.allowed = allowed;
if(finished) {
finished(this);
}
},
isAllowed: function(context){
return this.allowed;
}
}),
enabler = com.ibm.mashups.enabler,
allowedOpsModel = enabler.ac.operation.AllowedOperationsModelFactory.getAllowedOperationsModel();
allowedOpsModel.setOperation(com.ibm.pb.extension.Operations.PAGE_ACTIONS, function(opName, jsonContext, sync, finished) {
var isAllowed = enabler.model.Factory.getUserModel().getAnonymousMode() != enabler.user.AnonymousMode.ANONYMOUS;
if(!isAllowed) {
if (typeof ibmPortalCPConfig != "undefined") {
var cp = ibmPortalCPConfig, node = jsonContext && jsonContext.contentNode;
isAllowed = (cp.isTaggingEnabled && cp.contextMenu.isTaggingEnabled && cp.operations.canViewTags && ((node && node.getMetaData) ?
node.getMetaData("com.ibm.portal.cp.tagging.isTaggingDisabled") !== "true" : true)) ||
(cp.isRatingEnabled && cp.contextMenu.isRatingEnabled && cp.operations.canViewRatings && ((node && node.getMetaData) ?
node.getMetaData("com.ibm.portal.cp.rating.isRatingDisabled") !== "true" : true));
}
}
new portalOp(isAllowed, finished);
});
// Subscribe the status bar to topic
dojo.subscribe("/portal/status/theme", dojo.global, function(type, message, details){
var statusMessage = new com.ibm.widgets.StatusMessage(type, message, details);
dojo.publish("/portal/status", [{message: statusMessage, uid: 'ibmStatusBox'}]);
});
// Subscribe to the refresh navigation event
com.ibm.mashups.services.ServiceManager.getService("eventService").subscribeEvent("com.ibm.mashups.builder.refreshNavigation", window, function(){
var nsm = com.ibm.mashups.enabler.model.state.NavigationStateModelFactory.getNavigationStateModel();
var redirectAddress = com.ibm.mashups.enabler.model.state.UrlGeneratorFactory.getUrlGenerator().getUrl(nsm, null, {skipState: true, pocURI: "nm:oid:"+ibmCfg.portalConfig.currentPageOID});
top.location.href = redirectAddress;
});
});