Being able to retrieve and set personalization values on the client is a new feature that DNN will support for version 4.5. Since personalization is something specific to DNN, the code will reside in the DNN specific ClientAPI files of dnncore.js and DNNClientAPI (ClientAPI.vb). The current state of the dnncore.js is such that it does not utilize namespaces. Instead it prefixes all function names with __dnn_. Module developers use these client-side functions when they are calling server-side methods like AddBodyOnloadEventHandler and EnableMinMax, but they are not intended to be used directly from the client. Since we now wish to expose client-side methods for setting and obtaining personalization values, the creation on a new namespace is in order.
The name of this namespace will be dnncore. To start out, it will only support personalization methods, but eventually the entire set of dnncore functions will be encapsulated.
Since the core is in the process of adapting the MS AJAX framework, I have decided to start following some of their naming standards, specifially, denoting a method is meant to be private by the prefixing of an _ (underscore).
The first two methods of dnncore that are not private are
dnncore.getUserProp(sNameCtr, sKey, pFunc)
dnncore.setUserProp(sNameCtr, sKey, sVal, pFunc)
sNameCtr - The concept of the naming container serves a similar function to namespaces in our js and .NET code. It enables our keys to be unique between our modules.
sKey - The key parameter should also be self explanitory. It is the property name we are setting or retrieving.
sVal - The setUserProp obviously needs to pass a value to assign.
pFunc - pointer to function to invoke with results from our async callback.
Pesonalization has existed in the DNN Framework for a long time. Therefore, most of these parameters should be easy to understand. The one exception to this is the pFunc parameter. To explain this it is important to remember is what the first A in AJAX stands for. Thats right, Asynchronous! Javascript is a single threaded environment. There is no way to do some sort of looping structure with something like DoEvents (VB) while we wait for a result. Some of you are probably saying that the XMLHTTP object that the MS and Mozilla/FireFox offer has a property that allows for async to be true or false. Additionally, the method the ClientAPI exposes has a parameter for async. What gives?
Causing javascript to execute a synchronous request to the serer is not a good idea, for it will make the browser appear to be locked up. Additonally, support for browsers that do not have their own XMLHTTP object would be impossible. Most AJAX frameworks utilize the hidden IFrame method to utilize postbacks for these browsers. As you know, the requesting of a webpage is certainly not synchronous.
So how do you obtain a value?
Code similar to this can be used.
function getUserSettings()
{
dnncore.getUserProp('MyModule', 'backgroundColor', setValue);
dnncore.getUserProp('MyModule', 'color', setValue);
}
function setValue(sNameCtr, sKey, sVal)
{
$('mytextbox').style[sKey] = sVal;
}
function setUserSettings()
{
dnncore.setUserProp('MyModule', 'backgroundColor', 'yellow');
dnncore.setUserProp('MyModule', 'color', 'blue');
}
Some of you may be asking, since this is just javascript, how can I be sure that users don't obtain any personalization value they want? Or, how can I stop them from putting a bunch of junk in these tables, thus bloating my database?
Both of these are legitimate concerns. The first, however, depends on what module developers are storing in the user's personalization. Most likely, these are simple settings the user already knows about. The second, is a bigger concern, and therefore something needs to be done to limit what values can be inserted. To address both concerns, the DNNClientAPI class now has a method that needs to be used to enable a personalization property to be both set and retrieved.
EnableClientPersonalization(ByVal strNamingContainer As String, ByVal strKey As String, ByVal objPage As Page) As Boolean
strNamingContainer - personalization naming container
strKey - personalization key
objPage - page being rendered (handles callback)
ReturnValue - Returns True when browser supports client-side personalization. If this returns false, it is your responsibility to ensure that your code still functions, most likely with postbacks.
The core has supported the EnableMinMax method for a long time now. One of the parameters going into this method is PersonaliztionType. The supported types consisted of: None, Page, and Cookie. A new type has been added to support persisting to Personalization. Support for this requires an additional overloads to be added to allow the developer to pass in the NamingContainer and Key for personalization.
In addition to module developers having another cool tool in their toolbox, the core has also utilized this feature. The newly updated control panel currently has min/max capability, that persists between page requests. This is now persisting with the new overloaded EnableMinMax.
DotNetNuke.UI.Utilities.DNNClientAPI.EnableMinMax(imgVisibility, rowControlPanel, Not IsVisible, Common.Globals.ApplicationPath & "/images/min.gif", _
Common.Globals.ApplicationPath & "/images/max.gif", DNNClientAPI.MinMaxPersistanceType.Personalization, "Usability", "ControlPanelVisible" & Me.PortalSettings.PortalId.ToString)