/* Created by SA * User settings and page state management functions * ENV-815 */ var C_PREFERENCES_GET_URL = "/User/GetPreferences"; var C_PREFERENCES_GET_URL_ASYNC = "/User/GetPagePreferences"; var C_PREFERENCES_SAVE_URL = "/User/SavePreferences"; var C_QUICKLINK_LOAD_URL = "/UserQuickLink/GetPreferences"; var pagePreferencesCache = {}; function getPageUrl() { return window.location.pathname; } // get data-section attr value for the specified element function getDataSection(element) { var foundSection = ''; var sections = $(element).parents("*[data-section]"); if (sections && (sections.length > 0)) foundSection = $(sections).first().attr("data-section"); return foundSection; } // gather all values from elements with data-key attr for the element with the specified data-section attr value function collectPreferences(dataSection) { var items = []; var dataSectionElement = $(document).find("*[data-section='" + dataSection + "']"); if (!dataSectionElement || (dataSectionElement.length < 1)) dataSectionElement = $(document); var controlsToStore = $(dataSectionElement).find('*[data-key]'); for (var index = 0; index < controlsToStore.length; index++) { var currentControl = controlsToStore[index]; var tagName = currentControl.tagName.toLowerCase(); if (tagName == 'input') { var inputType = $(currentControl).attr('type'); tagName = tagName + '#' + inputType; } var dataKey = $(currentControl).attr('data-key'); var value = ''; switch (tagName) { case 'input#checkbox': case 'input#radio': value = $(currentControl).prop('checked'); break; case 'input#text': case 'input#search': case 'input#hidden': value = $(currentControl).val(); break; case 'select': value = $(currentControl).val(); if ($(currentControl).attr('multiple') === 'multiple' && !!value && $.isArray(value)) value = value.join(','); break; }; items.push({ Key: dataKey, Value: value }); } return items; } // save specified page preferences (data) to the database function saveUserPagePreferences(data, dataSection, customPageUrl, callback) { var pageUrl = customPageUrl; if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); var postData = {}; postData.data = JSON.stringify(data); postData.url = pageUrl; postData.section = dataSection; $.post(C_PREFERENCES_SAVE_URL, postData, function (data) { if(callback) callback(); }).error(function (h, e) { console.log("Save preferences error. h = " + h + ", e = " + e); }); } // Obsolete - use only Async version, ask AK for details // load page preferences from quick link if there is a linkId param in QS // otherwise (linkId not set or returned data is empty) loads page preferences for the specified (or current) page url function loadUserPagePreferences(dataSection, customPageUrl) { var pageUrl = customPageUrl; if (typeof quickLinkData === 'undefined' && URI().query(true).linkId) { $.ajax(C_QUICKLINK_LOAD_URL, { async: false, data: { linkId: URI().query(true).linkId }, method: "POST", success: function (response, textStatus, jqXHR) { if (response && response.Status === "OK" && response.Data) { quickLinkData = JSON.parse(response.Data); if (quickLinkData[dataSection] && quickLinkData[dataSection].length != 0) {// return quickLinkData[dataSection]; } else { if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); var prefs = []; if (typeof quickLinkData !== 'undefined' && quickLinkData[dataSection]) // return quickLinkData[dataSection]; if (!dataSection || (dataSection.length < 1)) prefs; $.ajax(C_PREFERENCES_GET_URL, { async: false, data: { url: pageUrl, section: dataSection }, method: "POST", success: function (response, textStatus, jqXHR) { if (response && response.Status === "OK" && response.Data) { prefs = JSON.parse(response.Data); } } }); return prefs; } } } }); return quickLinkData[dataSection]; } else { if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); var prefs = []; if (typeof quickLinkData !== 'undefined' && quickLinkData[dataSection]) { return quickLinkData[dataSection]; } if (!dataSection || (dataSection.length < 1)) prefs; $.ajax(C_PREFERENCES_GET_URL, { async: false, data: { url: pageUrl, section: dataSection }, method: "POST", success: function (response, textStatus, jqXHR) { if (response && response.Status === "OK" && response.Data) { prefs = JSON.parse(response.Data); } } }); return prefs; } } // loads page preferences for the specified (or current) page url function loadUserPreferences(dataSection, customPageUrl) { var pageUrl = customPageUrl; if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); var prefs = []; $.ajax(C_PREFERENCES_GET_URL, { async: false, data: { url: pageUrl, section: dataSection }, method: "POST", success: function (response, textStatus, jqXHR) { if (response && response.Status === "OK" && response.Data) { prefs = JSON.parse(response.Data); } } }); return prefs; } function restorePreferences(dataSection, data) { if (!dataSection || (dataSection.length < 1) || typeof data === 'undefined') return; var dataSectionElement = $(document).find("*[data-section='" + dataSection + "']"); if (!dataSectionElement || (dataSectionElement.length < 1)) dataSectionElement = $(document); for (var index = 0; index < data.length; index++) { var currentRec = data[index]; var dataKey = currentRec.Key; var value = currentRec.Value; var prefsReceiver = $(dataSectionElement).find('*[data-key="' + dataKey + '"]'); if (prefsReceiver && (prefsReceiver.length > 0)) { var tagName = prefsReceiver.get(0).tagName.toLowerCase(); if (tagName == 'input') { var inputType = $(prefsReceiver).attr('type'); tagName = tagName + '#' + inputType; } switch (tagName) { case 'input#checkbox': case 'input#radio': $(prefsReceiver).prop('checked', value); break; case 'input#text': case 'input#hidden': $(prefsReceiver).val(value); break; case 'select': if ($(prefsReceiver).attr('multiple') === 'multiple' && !!value && !$.isArray(value)) value = value.split(','); if (!!$(prefsReceiver).data("select2")) { $(prefsReceiver).select2('val', value); } else { $(prefsReceiver).val(value); } break; default: }; } } } function generalizeUrl(url) { var components = url.split("/"); var result = ""; for (var index = 1; index < (components.length - 1) ; index++) { result += ("/" + components[index]); } return result; } function saveLastPageVisited(pageUrl) { if (USER_PREFERENCE_LASTPAGE_URL == null || USER_PREFERENCE_LASTPAGE_URL == "") { console.log("USER_PREFERENCE_LASTPAGE_URL constant is not registered in the main _Layout.cshtml"); return; } if (USER_PREFERENCE_LASTPAGE_SECTION == null || USER_PREFERENCE_LASTPAGE_SECTION == "") { console.log("USER_PREFERENCE_LASTPAGE_SECTION constant is not registered in the main _Layout.cshtml"); return; } if (USER_PREFERENCE_LASTPAGE_KEY == null || USER_PREFERENCE_LASTPAGE_KEY == "") { console.log("USER_PREFERENCE_LASTPAGE_KEY constant is not registered in the main _Layout.cshtml"); return; } var prefs = []; prefs.push({ Key: USER_PREFERENCE_LASTPAGE_KEY, Value: pageUrl }); saveUserPagePreferences(prefs, USER_PREFERENCE_LASTPAGE_SECTION, USER_PREFERENCE_LASTPAGE_URL); } /* Page Preferences methods v. 2.0 * Updates: * 1) introduced async data loading * 2) introduced caching of loaded data * 3) data modification function(s) update(s) cached data and then save new value to database * 4) avoid collecting of data from DOM before saving but use cached data instead * To-Do: * 5) split loadUserPagePreferencesAsync to loadAsync and getDataSection (which only return cached data without any loading) * 6) Implement it as a widget to simplify usage * 7) assign change event handlers for all DOM nodes with data-key attributes to handle data update automatically * 8) consider replacing data attributes with css classes. Maybe not necessary */ // load page preferences from quick link if there is a linkId param in QS // otherwise (linkId not set or returned data is empty) loads page preferences for the specified (or current) page url function getDataSectionOptions(dataSection) { if (Object.keys(pagePreferencesCache).length == 0 || pagePreferencesCache[dataSection] == null) return null; return pagePreferencesCache[dataSection]; } function loadUserPagePreferencesAsync(dataSection, customPageUrl, force) { // to-do: move callbacks to functions and reuse page callback in different places //console.log('1'); var pageUrl = customPageUrl; if (force) { pagePreferencesCache = {}; } if (Object.keys(pagePreferencesCache).length == 0 && URI().query(true).linkId) { // load quick link page preferences if there is a linkId QS param var linkPromise = $.ajax(C_QUICKLINK_LOAD_URL, { data: { linkId: URI().query(true).linkId }, method: "POST" }).then(function (response) { // success quick link callback //console.log('1.2'); if (response && response.Status === "OK" && response.Data) { //console.log('1.3'); pagePreferencesCache = JSON.parse(response.Data); } //console.log('1.4'); //console.log(pagePreferencesCache); // return page preferences for the specified dataSection if (pagePreferencesCache[dataSection] && pagePreferencesCache[dataSection].length != 0) {// //console.log('4'); var deferrer = $.Deferred(); deferrer.resolve(pagePreferencesCache[dataSection] || []); return deferrer.promise(); } else { //console.log('5'); if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); // return page preferences for the specified dataSection if (Object.keys(pagePreferencesCache).length != 0 && pagePreferencesCache[dataSection]) // { var deferrer = $.Deferred(); deferrer.resolve(pagePreferencesCache[dataSection] || []); return deferrer.promise(); } //console.log('6'); // return entire page preferences object if dataSection was not specified if (!dataSection || (dataSection.length < 1)) { var deferrer = $.Deferred(); deferrer.resolve(pagePreferencesCache); return deferrer.promise(); } //console.log('7'); // if there is not specified section in page preferences then load them from common page preferences // and union link preferences with page preferences var pagePromise = $.ajax(C_PREFERENCES_GET_URL_ASYNC, { data: { url: pageUrl }, method: "POST" }).then(function (response) { // success page callback //console.log('8'); //console.log(response.Data); if (response && response.Status === "OK" && response.Data) { $.each(response.Data, function (key, item) { // add only missing sections to the cache, DO NOT override link preferences // because they have higher priority than page preferences //console.log('9'); if (!pagePreferencesCache[key]) { // Fix for non-JSON values in page preferences. Set them to pagePreferencesCache as is. // We may face in 'item' with plain GUID values as well plain boolean values (true/false). // See pref-keys CreateScenarioDefaultTemplate or USR_PREF_ISHOURS and USR_PREF_AVG. // tryParseJson defined in pixel-admin.js, line 26135 pagePreferencesCache[key] = $(window).editableutils.tryParseJson(item, false); } }); } //console.log('10'); return pagePreferencesCache[dataSection] || []; }, function (response) { // fail page callback throw 'An error occurred while loading page preferences missing in link options'; }); //console.log('7.1'); // console.log(pagePromise); return pagePromise; } }, function (response) { // fail quick link callback throw 'An error occurred while loading quick link page preferences'; }); return linkPromise; } else { //console.log('11'); if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); if (typeof Object.keys(pagePreferencesCache).length != 0 && pagePreferencesCache[dataSection]) { //console.log('12'); var deferrer = $.Deferred(); deferrer.resolve(pagePreferencesCache[dataSection]); return deferrer.promise(); } if (!dataSection || (dataSection.length < 1)) { //console.log('13'); var deferrer = $.Deferred(); deferrer.resolve(pagePreferencesCache); return deferrer.promise(); } var promise = $.ajax(C_PREFERENCES_GET_URL_ASYNC, { data: { url: pageUrl }, method: "POST" }).then(function (response) { if (response && response.Status === "OK" && response.Data) { $.each(response.Data, function (key, item) { // add only missing sections to the cache, DO NOT override existing data because it could be from quick link if (!pagePreferencesCache[key]) { // Fix for non-JSON values in page preferences. Set them to pagePreferencesCache as is. // We may face in 'item' with plain GUID values as well plain boolean values (true/false). // See pref-keys CreateScenarioDefaultTemplate or USR_PREF_ISHOURS and USR_PREF_AVG. // tryParseJson defined in pixel-admin.js, line 26135 pagePreferencesCache[key] = $(window).editableutils.tryParseJson(item, false); } }); } return pagePreferencesCache[dataSection] || []; }, function (response) { throw 'An error occurred while loading page preferences'; }); //console.log('15'); return promise; } } // save specified page preferences (data) to the database function updatePagePreferenceValueAsync(customPageUrl, dataSection, key, newValue) { if (!dataSection) { throw "Required dataSection arg is not set. Save page state cannot be performed."; } // use current page URL if customPageUrl is not specified var pageUrl = customPageUrl; if (!customPageUrl || (customPageUrl.length < 1)) pageUrl = getPageUrl(); // set new value in cached data var section = pagePreferencesCache[dataSection]; if (!section) { pagePreferencesCache[dataSection] = []; section = pagePreferencesCache[dataSection]; } var elem = null; var i = 0; for (i = 0; i < section.length; i++) { if (section[i].Key === key) { elem = section[i]; break; } } if (!elem) { elem = { Key: key, Value: newValue }; section.push(elem); } else { elem.Value = newValue; section[i] = elem; } //console.log(pagePreferencesCache); var postData = {}; postData.data = JSON.stringify(section); postData.url = pageUrl; postData.section = dataSection; var promise = $.ajax(C_PREFERENCES_SAVE_URL, { data: postData, method: "POST" }); return promise; }