define(
        getTemplates
        createSakaiDate
        convertToHumanReadableFileSize
        formatTags
        tagEntity
            deleteTags
        applyThreeDots
        replaceTemplateParameters
        constructProfilePicture
        determineEmptyContent
        notification
            show
            removeAll
            type
                INFORMATION
                ERROR
        progressIndicator
            showProgressIndicator
            hideProgressIndicator
        parseSakaiDate
        parseRFC822Date
            insertTag
            checkForTag
            js
            css
        Sorting
            naturalSort
        loadSkinsFromConfig
        setPageTitle
            convertToHierarchy
            buildNodeRecursive
        getValueForDirectoryKey
        getValueForDirectoryTag
            createActivity
            getCurrentGMTTime
        safeURL
        saneHTMLAttribute
        templateCache
        processMacros
        processLocalMacros
        TemplateRenderer
            escapeHTML
            unescapeHTML
            replaceURL
            saneHTML
                removeExpression
            send404
            send403
            sendToLogin
        renderMath
        makeSafeTag
        makeUniqueURL
        hideOnClickOut
            setup
            open
            close
            positionDialogBox
            bindDialogFocus
        extractEntity
            setup
            reset
            destroy
            setupTagAndCategoryAutosuggest
            getTagsAndCategories
            validate
            setDraggableParameters
            setupDraggable
            setIFrameFix
            removeIFrameFix
            setDroppableParameters
            setupDroppable
        replaceInObject
define(

class Util
description General utility functions which implement commonly used low level operations and unifies practices across codebase.
namespace General utility functions


getTemplates: function(callback) {

Get the world templates from the server If the worldTemplates are already fetched they will just be returned from the variable
param {Function} callback Function executed after the templates have been fetched. The templates are passed through to the function


createSakaiDate : function(date, format, offset) {

Parse a JavaScript date object to a JCR date string (2009-10-12T10:25:19) <p> Accepted values for the format [1-6]: <ol> <li>Year: YYYY (eg 1997)</li> <li>Year and month: YYYY-MM <br /> (eg 1997-07)</li> <li>Complete date: YYYY-MM-DD <br /> (eg 1997-07-16)</li> <li>Complete date plus hours and minutes: YYYY-MM-DDThh:mmTZD <br /> (eg 1997-07-16T19:20+01:00)</li> <li>Complete date plus hours, minutes and seconds: YYYY-MM-DDThh:mm:ssTZD <br /> (eg 1997-07-16T19:20:30+01:00)</li> <li>Complete date plus hours, minutes, seconds and a decimal fraction of a second YYYY-MM-DDThh:mm:ss.sTZD <br /> (eg 1997-07-16T19:20:30.45+01:00)</li> </ol> </p> <p> External links: <ul> <li><a href='http://www.w3.org/TR/NOTE-datetime'>W3C datetime documentation</a></li> <li><a href='http://delete.me.uk/2005/03/iso8601.html'>ISO8601 JavaScript function</a></li> <li><a href='http://confluence.sakaiproject.org/display/KERNDOC/KERN-643+Multiple+date+formats+in+the+back-end'>Specification</a></li> </ul> </p>
param {Date} date JavaScript date object. If not set, the current date is used.
param {Integer} format The format you want to put out
param {String} offset Optional timezone offset +HH:MM or -HH:MM, if not set Z(ulu) or UTC is used
return {String} a JCR date string


convertToHumanReadableFileSize : function(filesize) {

Convert a file's size to a human readable size example: 2301 = 2.301kB
param (Integer) filesize The file's size to convert
return (String) the file's size in human readable format


formatTags : function(inputTags) {

Formats a comma separated string of text to an array of usable tags Filters out unwanted tags (eg empty tags) Returns the array of tags, if no tags were provided or none were valid an empty array is returned Example: inputTags = 'tag1, tag2, , , tag3, , tag4' returns ['tag1','tag2','tag3','tag4']
param {String} inputTags Unformatted, comma separated, string of tags put in by a user
return {Array} Array of formatted tags


tagEntity : function(tagLocation, newTags, currentTags, callback) {

Add and delete tags from an entity The two arrays, newTags and currentTags, represent the state of tags on the entity newTags should be the tags that you want on the entity, the whole set currentTags should be the set of tags the entity had before the user modified it tagEntity will delete any tags in currentTags but not in newTags, and add any in newTags that aren't in currentTags
param (String) tagLocation the URL to the tag, ie. (~userid/public/authprofile)
param (Array) newTags The set of tags you wish to be on the entity
param (Array) currentTags The set of tags on the current entity
param (Function) callback The callback function


var deleteTags = function(tagLocation, tags, deleteTagsCallback) {

Delete tags on a given node
param (String) tagLocation the URL to the tag, ie. (~userid/public/authprofile)
param (Array) tags Array of tags to be deleted from the entity
param (Function) callback The callback function


applyThreeDots : function(body, width, params, optClass, alreadySecure) {

Truncate a string of text using the threedots plugin
param {String} body String of text to be truncated
param {int} width Width of the parent element
param {Object} params Object containing parameters, Threedots plugin specific. The row limit for widget headers should be 4 rows.
param {String} Optional class(es) to give container div. Used to give specific mark-up to the content to avoid wrong calculations. e.g. s3d-bold


replaceTemplateParameters : function(variables, replaceIn) {

Search for and replace parameters in a template (replaces both keys and properties) primarily used for making unique IDs for the group/course templates in config.js
param {Object} variables The variables to replace in the template with, ie. 'groupid'
param {Object} replaceIn The object to modify
return {Object} the template structure with replaced variables


constructProfilePicture : function(profile, type) {

Check whether there is a valid picture for the user
param {Object} profile The profile object that could contain the profile picture
param {String} type The type of profile we're getting the picture for (group or user)
return {String} The link of the profile picture Will be an empty string if there is no picture


determineEmptyContent: function(content) {

Do some checks on the content to see if it's the default Tinymce content or just empty
param {String} content Content in the form of a string
return{Boolean} True indicates that content is present, False indicates that there is no content


notification : {

class notification
description Utility functions related to notifications messages in Sakai3
namespace Notifications messages


show : function(title, text, type, sticky) {

Show notification messages
example sakai.api.Util.notification.show('Title Message', 'z2', 'z01');
param {String} title The notification title (if it is an empty string, the title isn't shown)
param {String} text The text you want to see appear in the body of the notification
param {Constant} [type] The type of the notification. If this is not supplied, we use the type 'information'
param {Boolean} sticky The sticky (if it is true, the notification doesn't disappear without using action)


removeAll : function() {

Remove all the notification messages that are currently visible to the user


type : {

class type
description Namespace that contains all the different notification types
namespace Notifications types


INFORMATION : $.extend(true, {}, sakai_conf.notification.type.INFORMATION),

Object containing settings for the information notification type


ERROR : $.extend(true, {}, sakai_conf.notification.type.ERROR)

Object containing settings for the error notification type


progressIndicator: {

Allows you to show a progress indicator on the screen. Example of where this is done are the Add Content and the Create World widgets


showProgressIndicator: function(title, body) {

Show the progress indicator on the screen
param {Object} title Title of the indicator screen
param {Object} body Additional text to be shown in the indicator


hideProgressIndicator: function() {

Hide the existing progress indicator (if there is one)


parseSakaiDate : function(dateInput) {

Parse a ISO8601 date into a JavaScript date object. <p> Supported date formats: <ul> <li>2010</li> <li>2010-02</li> <li>2010-02-18</li> <li>2010-02-18T07:44Z</li> <li>1997-07-16T19:20+01:00</li> <li>1997-07-16T19:20:30+01:00</li> <li>1269331220896</li> </ul> </p> <p> External links: <ul> <li><a href='http://www.w3.org/TR/NOTE-datetime'>W3C datetime documentation</a></li> <li><a href='http://delete.me.uk/2005/03/iso8601.html'>ISO8601 JavaScript function</a></li> <li><a href='http://confluence.sakaiproject.org/display/KERNDOC/KERN-643+Multiple+date+formats+in+the+back-end'>Specification</a></li> </ul> </p>
param {String|Integer} dateInput The date that needs to be converted to a JavaScript date object. If the format is in milliseconds, you need to provide an integer, otherwise a string
return {Date} JavaScript date object


parseRFC822Date : function(dateString) {

Parse an RFC822 date into a JavaScript date object. Examples of RFC822 dates: Wed, 02 Oct 2002 13:00:00 GMT Wed, 02 Oct 2002 13:00:00 +0200
param {String} dateString
return {Date} a Javascript date object


insertTag : function(tagname, attributes) {

Generic function that will insert an HTML tag into the head of the document. This will be used to both insert CSS and JS files
param {Object} tagname Name of the tag we want to insert. This is supposed to be 'link' or 'script'.
param {Object} attributes A JSON object that contains all of the attributes we want to attach to the tag we're inserting. The keys in this object are the attribute names, the values in the object are the attribute values


checkForTag : function(tagname, attributes) {

Check to see if the tag+attributes combination currently exists in the DOM
param {Object} tagname Name of the tag we want to insert. This is supposed to be 'link' or 'script'.
param {Object} attributes A JSON object that contains all of the attributes we want to attach to the tag we're inserting. The keys in this object are the attribute names, the values in the object are the attribute values
return {jQuery|Boolean} returns the selected objects if found, otherwise returns false


js : function(url) {

Load a JavaScript file into the document
param {String} URL of the JavaScript file relative to the parent dom.


css : function(url) {

Load a CSS file into the document
param {String} URL of the CSS file relative to the parent dom.


Sorting : {

class Sorting
description Sorting algorithms
namespace Sorting functions


naturalSort: function(a, b) {

Natural sorting algorithm, for sorting file lists etc.
example sakai.api.Util.Sorting('z1', 'z2', 'z01');
param {String|Integer|Number} a The first element you want to sort
param {String|Integer|Number} b The second element you want to sort
return {Integer} [0 | 1 | -1] <ul> <li>-1: sort a so it has a lower index than b</li> <li>0: a and b are equal</li> <li>1: sort b so it has a lower index than a</li> </ul>


loadSkinsFromConfig : function() {

loadSkins Loads in any skins defined in sakai.config.skinCSS


setPageTitle : function(title, targetLevel) {

Sets the browsers title
param {String} title The string to be added to the page title
param {String} targetLevel Change the specified component of the page title only


var convertToHierarchy = function(directory) {

Converts directory array into a node structure so that it can be rendered into the jstree.
param {Object} directory list of directories
return result the json object in the structure necessary to render in jstree


var buildNodeRecursive = function(node_id, directory, url, parent_title) {

Recursive method that create the node structure so that it can be rendered into the jstree.
param {String} node_id the unique id for each node for example firstyearcourses
param {Object} directory directory list json object for example 'collegeofengineering': { ... }
param {String} url the url of the page to render when directory node is clicked for example /directory#collegeofengineering
return node the json object in the structure necessary to render in jstree


getValueForDirectoryKey : function( key, _directory ) {

Recursive function that gets the title corresponding to an ID in the directory
param {Object} key Key to get title for
param {Object} child Object to check for children next, if not supplied start with first child


getValueForDirectoryTag: function( tag ) {

Get the string value for a directory tag directory/medicineanddentistry/clinicalmedicine => Medicine and Dentistry » Clinical Medicine
param {String} tag The directory tag
return {String} The printable tag


createActivity : function(nodeUrl, appID, templateID, extraData, callback) {

Wrapper function for creating a Nakamura activity
param nodeUrl {String} The URL of the node we would like the activity to be stored on
param appID {String} The ID of the application/functionality creating the activity
param templateID {String} The ID of the activity template
param extraData {Object} Any extra data which will be stored on the activity node
param callback {Function} Callback function executed at the end of the operation
returns void


getCurrentGMTTime : function() {

Returns the current time in GMT milliseconds from the epoch


safeURL: function(str) {

A version of encodeURIComponent that does not encode i18n characters when using utf8. The javascript global encodeURIComponent works on the ascii character set, meaning it encodes all the reserved characters for URI components, and then all characters above Char Code 127. This version uses the regular encodeURIComponent function for ascii characters, and passes through all higher char codes. At the time of writing I couldn't find a version with these symantics (which may or may not be legal according to various RFC's), but this implementation can be swapped out with one if it presents itself.
param {String} String to be encoded.
returns Encoded string.


saneHTMLAttribute: function(str) {

Convert a string into something that is safe to put into an HTML attribute. This is made available as a modifier to TrimPath templates, as we can't call the .data() function of jQuery whilst rendering a template
param {Object} str String to be transformed into a string safe for use in an attribute


templateCache : [],

A cache that will keep a copy of every template we have parsed so far. Like this, we avoid having to parse the same template over and over again.


processMacros : function(url, asyncreq) {

Process trimpath macros in html file at url, which will then be available with the macro function inside regular rendering. The optional asyncreq option allows the request to be syncronous, which would mostly be for on-demand loading (because that is happening during rendering and it needs the template to continue. )
function
param {String} url with macros to load
param {Boolean} Optional parameter to distinguish whether the loading should happen syncronously. Default is true (async)


processLocalMacros : function(templateElement) {

While the processMacros function allows a way to make macros that can be shared and discovered between widgets automatically, this function allows for a simpler use case where a widget developer may just want some macros for their specific widget. In this case they can put all their macros in a template element ( similar to regular template elements), and then get a macro set back that can be used in between the rest of the templates they have defined in their page.
param {String|jQuery} Raw String or jQuery element containing the text of the macro definitions.
return An object containing the macro functions. This can be added to the context of subsequent TemplateRenderers and called like regular trimpath macros.


TemplateRenderer : function(templateElement, templateData, outputElement, doSanitize) {

Trimpath Template Renderer: Renders the template with the given JSON object, inserts it into a certain HTML element if required, and returns the rendered HTML string
function
param {String|Object} templateElement The name of the template HTML ID or a jQuery selection object.
param {Object} templateData JSON object containing the template data
param {Object} outputElement (Optional) jQuery element in which the template needs to be rendered
param {Boolean} doSanitize (Optional) perform html sanitization. Defaults to true


escapeHTML : function(inputString) {

Encodes the HTML characters inside a string so that the HTML characters (e.g. <, >, ...) are treated as text and not as HTML entities
param {String} inputString String of which the HTML characters have to be encoded
returns {String} HTML Encoded string


unescapeHTML : function(inputString) {

Unescapes HTML entities in a string
param {String} inputString String of which the HTML characters have to be unescaped
returns {String} normal HTML string


replaceURL : function(message) {

Represent URL if any in an anchor tag.
param {Object} message Message that user has entered.


saneHTML : function(inputHTML) {

Sanitizes HTML content. All untrusted (user) content should be run through this function before putting it into the DOM
param inputHTML {String} The content string we would like to sanitize
returns {String} Escaped and sanitized string


var removeExpression = function(cssStyle) {

Remove expressions from a CSS style (only an issue in IE)
param {String} cssStyle The CSS style we want to remove expressions from
return {String} A CSS style that doesn't contain an expression


send404 : function() {

Function that can be called by pages that can't find the content they are supposed to show.


send403 : function() {

Function that can be called by pages that don't have the permission to show the content they should be showing


sendToLogin : function() {

Function that can be called by pages that require a login first


renderMath : function(element) {

Runs MathJax over an element replacing any math TeX with rendered formulas
param element {String} The element (or it's id) that should be checked for math


makeSafeTag : function(tag) {

Sling doesn't like certain characters in the tags So we escape them here /:;,[]*'"|


makeUniqueURL : function(desiredURL, secondaryURL, structure) {

Make a unique URL, given a primary and secondary desired url and a structure passed in to ensure uniqueness of the key. The first argument will be used as the primary URL, and used if possible. The second argument will be used if passed, but if none of these work, or if the second argument isn't passed and the first argument doesn't work, the first argument will be appended with '0', '1', etc until a unique key for the structure is found. That string will be returned.
param {String} desiredURL The URL (or object key) you'd like to use first
param {String} secondaryURL The URL (or orject key) that you'd like to use as a backup in case the desiredURL isn't available. Pass null here if you want to use the number-append feature
param {Object} structure The structure to test against its top-level keys for uniqueneness of the URL/key


hideOnClickOut : function(elementToHide, ignoreElements, callback) {

Sets up events to hide a dialog when the user clicks outside it
param elementToHide {String} a jquery selector, jquery object, dom element, or array thereof containing the element to be hidden, clicking this element or its children won't cause it to hide
param ignoreElements any elements that match a jquery.is(ignoreElements) will not hide the target element when clicked
param callback {function} a function to be called instead of the default jquery.hide()


setup : function(dialogContainer, options, addClose) {

Sets jqmodal options
param dialogContainer {String} a jquery selector or jquery object, that is the dialog container
param options {Object} object containing options to pass to the jqmodal plugin
param addClose {String} a jquery selector or jquery object used in the jqmAddClose function


open : function(dialogContainer, openOptions) {

Opens the dialog box
param {String} dialogContainer a jquery selector or jquery object, that is the dialog container
param {Object} openOptions optional object containing options to apply when opening the dialog: positionDialog {Boolean} true to position the dialog at the scroll position positionOffset {Integer} dialog height position offset bindKeyboardFocus {Boolean} true to trap keyboard focus inside the dialog bindKeyboardFocusIgnoreElements {String} optional jquery selector for start/end elements to be ignored bindKeyboardCloseFunction {Function} optional function to be called when the user hits the escape key


close : function(dialogContainer) {

Closes the dialog box
param {String} dialogContainer a jquery selector or jquery object, that is the dialog container


positionDialogBox : function(el, offset) {

Positions the dialog box at the users scroll position
param {String} el a jquery selector or jquery object, to position
param {Integer} offset optional numeric value to add to the dialog position offset


bindDialogFocus : function(dialogContainer, ignoreElements, closeFunction) {

Sets up events to keep keyboard focus within the dialog box and close it when the escape key is pressed
param {String} dialogContainer a jquery selector or jquery object which is the dialog container
param {String} ignoreElements an optional jquery selector for start/end elements to be ignored
param {Function} closeFunction an optional function to be called when the user hits the escape key


extractEntity : function(pathname) {

Extracts the entity ID from the URL also handles encoded URLs Example: input: '/~user1' return: 'user1' Encoded Exmaple: input: '/%7E%D8%B4%D8%B3' return: 'شس'
param {String} pathname The window.location.pathname
return {String} The entity ID


setup: function( element, options, callback, _dataFn ) {

Autosuggest for users and groups (for other data override the source parameter). setup method creates a new autosuggest on the element (a jQuery object or selector string that is passed to jQuery) and also sets a namespace .data() so autosuggest won't be created more than once, with the original element as its value. The original element is retrieved in the destroy method to replace the autosuggest.
param {String|Object} jQuery selection object or selector string.
param {Object} JavaScript object of optional parameters to extend or override defaults
param {function} optional callback to be executed after calling autosuggest plugin
returns {Object} new jQuery object with autosuggest


reset: function( $element ) {

Resets the autosuggest without destroying/creating. Use this when the autosuggest is in an element whose visibility is toggled, e.g. via a 'Cancel' button which should have the effect of clearing the autosuggest. The autosuggest plugin has no reset method, and it maintains a 'prev' variable that holds the last typed character. Clearing the input field isn't sufficient, if the same character is typed next time it will match the stored character and return false, so the keydown after clearing the input clears the var in the plugin.
param {String} $element The element (or a jQuery selector string) for the text input for the autosuggest
returns {Object} the jQuery object created from setup method


destroy: function( element, options ) {

Removes the autosuggest and replaces it with the original element stored in .data() under the 'namespace' key when the autosuggest was created. Because it stores the original element, and this isn't a jQuery plugin that iterates over all matching selectors, this method only works if a single element is passed in. In practice it's probably not likely to pass multiple elements in the selector when creating the autosuggest (if that's really needed, then modifications to the plugin are more appropriate).
param element {Object} The autosuggest element (a jQuery object); usually the returned from the setup method
param {Object} JavaScript object of optional parameters; currently only the namespace key
returns {Object} original jQuery object without autosuggest


setupTagAndCategoryAutosuggest: function($elt, options, $list_categories_button, initialSelections, callback) {

Set up the tag + category autosuggest box
param {jQuery} $elt The element to set up as the autosuggest box
param {Object} options Options to pass through to the autoSuggest setup
param {jQuery} $list_categories_button The button that should trigger the assignlocation overlay
param {Array} initialSelections The inital selections for the autosuggest, direct from the profile
param {Function} callback Function to call after setup is complete


getTagsAndCategories: function($elt, merge, longform) {

Get the tags and categories from the autosuggest box
param {jQuery} $elt The element which you passed to the autoSuggest setup method
param {Boolean} merge If the tags and categories should be merged on return
param {Boolean} longform When true, the categories returned will be the full object instead of just the path string ('directory/category/child')
return {Object} Two arrays, categories and tags - OR - one array of tags and categories if merge === true


validate: function($form, opts, insertAfterLabel) {

A wrapper for jquery.validate, so we can perform the same errorPlacement on each form, without any duplicated code
param {jQuery} $form the jQuery element of the form in question
param {Object} opts options to pass through to jquery.validate NOTE: There is one additional option you can pass in -- an error callback function When there is an error in validation detected, it will be called NOTE: Additional option 'errorsShown' can hold a function that is executed after the error labels have been displayed on screen.
param {Function} [invalidCallback] The function to call when an error is detected
param {Boolean} [insertAfterLabel] Insert the error span after the label, not before


setDraggableParameters: function(params) {

Sets and overrides default parameters for the jQuery Droppable plugin
param {Object} params Optional parameters that override defaults


setupDraggable: function(params, $container) {

Sets up draggables accross the page
param {Object} params Optional parameters that override defaults
param {Object} $container Optional container element to add draggables, defaults to $('html') if not set


setIFrameFix: function() {

When dragging elements over the screen, there are issues with iframes as they can make the drag action hang when hovering over them. Therefore, we apply an almost transparent div on top of the screen. This avoids the iframe events to be triggered and allows for smooth dragging and dropping


removeIFrameFix: function() {

Remove the transparant div that makes sure that dragging is smooth despite iFrames being present on the screen


setDroppableParameters: function() {

Sets and overrides default parameters for the jQuery Draggable plugin
param {Object} params Optional parameters that override defaults


setupDroppable: function(params, $container) {

Sets up droppables accross the page
param {Object} params Optional parameters that override defaults
param {Object} $container Optional container element to add droppables, defaults to $('html') if not set


replaceInObject: function(obj, toReplace, replacement) {

Do a deep search and replace in an object
param {Object} obj The object to replace values in
param {String} toReplace The value to search for
param {String} replacement The string to replace the value with
return {Object} The object with the string replaced in all occurrences