(function () { var externalModules = {}; // local variable to be enclosed in global function STC STC = function () // this is global variable { // // this function defines stc utilities library // // usage: // var stc = STC(); // var rand = stc.utils.randomizer() // var stc = {}; //////////////////////////////////////////// // // define stc.utils // (function () { var utils = {}; utils.randomizer = function () { return Math.floor(Math.random() * 1000000); } utils.getNewId = function () { bOk = false; while (!bOk) { var id = "_CDOMID_" + Math.floor(Math.random() * 1000000); bOk = (0 == $("#" + id).size()); } return id; } var eMailPattern = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/gi; // останній флаг /gi означає global case insensitive, УВАГА! В інших regex середовищах (відмінних від JavaScript) можуть бути інші варіанти з case insensitive utils.extractEMail = function (str, exctractSeveral) { var mail = str.match(eMailPattern); if (mail && !exctractSeveral) { return mail[0]; // повертаємо лише першу адресу } else { return mail; } } utils.validateEMail = function (str) { // чомусь валідація, на відміну від екстракції працює через раз - розібратись return eMailPattern.test(str); } utils.validateRealNumber = function (str) { var hasSign = false; var hasIntPart = false; var hasSeparator = false; var hasFractionalPart = false; var i = 0; if (i < str.length && str[i] == '-') { hasSign = true; i += 1; } while (i < str.length && str[i] >= '0' && str[i] <= '9') { hasIntPart = true; i += 1; } if (str.length == i && hasIntPart) { return true; } if (str[i] == '.' || str[i] == ',') { hasSeparator = true; i += 1; } else { return false; } while (i < str.length && str[i] >= '0' && str[i] <= '9') { hasFractionalPart = true; i += 1; } return str.length == i && hasFractionalPart; } stc.utils = utils; })(); // // end of stc.utils // //////////////////////////////////////////// //////////////////////////////////////////// // // define stc.http // (function () { var http = { dummy: null }; http.detemplate = function (urlTemplate, values) { values = values || {}; var url = urlTemplate.replace("{randomizer}", stc.utils.randomizer()); for (e in values) { url = url.replace("{" + e + "}", values[e]); } return url; } http.completeUrl = function (url) { url = (url) ? url.toString() : ""; if (url == "") { return "/"; } else { if (url[url.len - 1] == "/") { return url; } else { return url + "/"; } } } http.stripUrlL = function (url) { url = (url) ? url.toString() : ""; while (url.length > 0 && "/" == url[0]) { url = url.substring(1, url.length - 1); } return url; } http.stripUrlR = function (url) { url = (url) ? url.toString() : ""; while (url.length > 0 && "/" == url[url.length - 1]) { url = url.substring(0, url.length - 1); } return url; } http.composeUrl = function (arr) { if (arguments.length == 0) { return ""; } else if (arguments.length == 1) { if (((arr.length && (typeof arr.length) === 'number') || arr.length === 0) && !arr.substring) // this is to check that arr parameter is an array { var url = ""; for (var i = 0; i < arr.length; i++) { url += (url == "" ? http.stripUrl(arr[i]) : "/" + http.stripUrl(arr[i])); } return url; } else { return http.stripUrl(arr.toString()); } } else { return http.composeUrl(arguments); } } http.stripUrl = function (url) { return http.stripUrlL(http.stripUrlR(url)); } http.protocol = function () { return "http://"; } http.host = function () { return document.location.host; } http.siteUrl = function () { return http.protocol() + http.host(); } http.url = function (relativeUrl) { if (!relativeUrl) { return http.siteUrl(); } relativeUrl = relativeUrl ? relativeUrl.toString() : ""; if ("" == relativeUrl) { return http.siteUrl(); } else { //return http.stripUrl(http.siteUrl()) + (relativeUrl[0] == "/" ? relativeUrl : "/" + relativeUrl); return http.composeUrl([http.siteUrl(), relativeUrl]); } } http.createDefaultErrorHandler = function (continuation) { // створює jquery callback для обробки помилок у ajax-сценаріях // цей callback відображатиме errorBox після закриття якого можливе виконання continuation-методу return function (xhr, textStatus, errorThrown) { var msg = ""; if (400 == xhr.status || 403 == xhr.status || 404 == xhr.status) { msg += ""; } else { msg += "Код помилки " + xhr.status + "
"; } // знімаємо url повідомлення про помилку з спеціального http header var xHeader = xhr.getResponseHeader("x-stc-ajaxErrorMessageUrl"); // ім'я заголовку має бути параметором ініціалізації модуля... if (xHeader && "" != xHeader) { var messagePaneId = stc.utils.getNewId(); msg += '
'; // це div - контейнер для інформації про помилку msg += '
'; // це внутрішній div - центруючий контейнер для img msg += '
Завантажується детальна інформація про помилку

'; msg += '
' // img src винести в константу, уніфікувати з waitBox і вантажити з власного сервера msg += '
'; // внутрішній контейнер msg += '
'; // зовнішній контейнер stc.messages.errorBox(msg, continuation); // отримуємо повідомлення про помилку і включаємо його в тіло еррор-боксу var url = stc.http.protocol() + xHeader; stc.http.get(url, function (strResult) { // onSuccess $("#" + messagePaneId).html(strResult); } , function () { // onError $("#" + messagePaneId).html("Не вдалося завантажити детальну інформацію про помилку"); } ); } else { msg += xhr.responseText; stc.messages.errorBox(msg, continuation); } } } http.defaultErrorHandler = http.createDefaultErrorHandler(); // створюється функція, яка просто відображає errorBox без всякого продовження // така функція підходить для більшості аякс-сценаріїв function _ajaxInternal(method, url, data, onSuccess, onError) { var options = { type: method , url: url , success: function (xhr) { var strResult = xhr.responseText || xhr; onSuccess && onSuccess(strResult); } , error: onError || http.defaultErrorHandler } if ('POST' == method || 'PUT' == method) { options.data = data; } $.ajax(options); } http.get = function (url, onSuccess, onError) { _ajaxInternal("GET", url, null, onSuccess, onError); } http.post = function (url, data, onSuccess, onError) { debugger; _ajaxInternal("POST", url, data, onSuccess, onError); } http.put = function (url, data, onSuccess, onError) { _ajaxInternal("PUT", url, data, onSuccess, onError); } http.deleteResource = function (url, onSuccess, onError) { _ajaxInternal("DELETE", url, null, onSuccess, onError); } http.getBooleanValue = function (url, onTrue, onFalse, onError) { http.get(url , function (strResult) { strResult = strResult.toLowerCase(); if (false) { } else if ("true" == strResult) { onTrue(); } else if ("false" == strResult) { onFalse(); } else { throw "boolean value expected"; } } , onError ); } stc.http = http; })(); // // end of stc.http // //////////////////////////////////////////// //////////////////////////////////////////// // // define stc.msg // (function () { var messages = {}; var genericMessage = function (body, options) { body = body || ""; options = options || {}; // first create DOM element to be base for our message box var newId = stc.utils.getNewId(); var newIdSelector = "#" + newId; var newElement = $("
").attr("id", newId); $("body").append(newElement); var removeBaseElement = function () // this is utility function to be executed on message box closing { $(newIdSelector).remove(); } // now set default options options.modal = true; options.resizable = (options.resizable === undefined) || options.resizable; options.closeOnEscape = (options.closeOnEscape === undefined) || options.closeOnEscape; options.minHeight = options.minHeight || 140; options.maxHeight = options.maxHeight || 280; options.minWidth = options.minWidth || 320; options.width = options.width || options.minWidth options.height = options.height || "auto"; options.close = (!options.close) ? removeBaseElement : function (e) { removeBaseElement(); options.close(e); } // create dialog with given options var dlg = $(newIdSelector).dialog(options); // set dialogs body dlg.html(body); return dlg; } messages.okBox = function (title, body, continuation) { return genericMessage(body , { title: title, buttons: [ { text: "Ok", click: function () { $(this).dialog("close"); if (continuation) { continuation(); }; } } ] } ); } messages.errorBox = function (body, continuation) { return stc.messages.okBox("Помилка!", body, continuation) } messages.warningBox = function (body, continuation) { return stc.messages.okBox("Увага!", body, continuation) } messages.okCancelBox = function (title, body, buttonCaptions, okAction, options) { title = title || "Підтвердіть продовження операції"; body = body || "Продовжити?"; buttonCaptions = buttonCaptions || {}; buttonCaptions.ok = buttonCaptions.ok || "Ok"; buttonCaptions.cancel = buttonCaptions.cancel || "Відмовитись"; options = options || {}; options.title = title; options.buttons = [ { text: buttonCaptions.ok, click: function () { $(this).dialog("close"); if (okAction) { okAction(); }; } } , { text: buttonCaptions.cancel, click: function () { $(this).dialog("close"); } } ]; return genericMessage(body, options); } messages.yesNoBox = function (title, body, yesAction, options) { return messages.okCancelBox(title, body, { ok: "Так", cancel: "Ні" }, yesAction, options); } messages.waitBox = function (title, body) { var wb = genericMessage( body || '

' , { title: title || "Зачекайте" , closeOnEscape: false , resizable: false , height: "auto" } ); $(wb).parent().find(".ui-dialog-titlebar-close").hide(); // сховаємо closebutton у правому кутку wb.close = function () { $(wb).dialog("close"); } return wb; } stc.messages = messages; })(); // // end of stc.msg // //////////////////////////////////////////// //////////////////////////////////////////// // define stc.dlg // (function () { var dialogs = {}; var genericDialog = function (title, body, options) { body = body || ""; options = options || {}; // first create DOM element to be base for our dialog var newId = stc.utils.getNewId(); var newIdSelector = "#" + newId; //var newElement = $("
").attr("id", newId); var newElement = $("
").attr("id", newId); $("body").append(newElement); var removeBaseElement = function () // this is utility function to be executed on dialog closing { $(newIdSelector).remove(); } // now set default options options.title = title; options.modal = true; options.resizable = (options.resizable === undefined) || options.resizable; options.closeOnEscape = false || (options.closeOnEscape === true); // default is false options.minHeight = options.minHeight || 280; options.maxHeight = options.maxHeight || 560; options.minWidth = options.minWidth || 320; options.height = options.height || "auto"; options.close = (!options.close) ? removeBaseElement : function (e) { removeBaseElement(); options.close(e); } // create dialog with given options var dlg = $(newIdSelector).dialog(options); // set dialogs body dlg.html(body); //alert($(newElement).find(".ui-dialog-buttonpane").size()); var buttonPane = $(newElement).parent().find(".ui-dialog-buttonpane"); buttonPane.addClass("stc-dialog"); return dlg; } dialogs.okCancelDialog = function (title, body, okAction, buttonCaptions, options) { options = options || {}; okAction = okAction || function () { $(dlg).dialog("close"); }; buttonCaptions = buttonCaptions || {}; buttonCaptions.ok = buttonCaptions.ok || "Ok"; buttonCaptions.cancel = buttonCaptions.cancel || "Відмовитись"; // if any buttons defined in options parameter thay will be overriden options.buttons = [ { text: buttonCaptions.ok, click: okAction } , { text: buttonCaptions.cancel, click: function () { $(this).dialog("close"); } } ] options.minWidth = options.minWidth || 560; options.minHeight = options.minHeight || 560; options.height = options.height || 560; var dlg = genericDialog(title, body, options); return dlg; } dialogs.submitDialog = function (title, fieldSetUrl, onFieldSetLoaded, httpMethod, submitUrl, onSuccess, onError, buttonCaptions, options) { // options parameter beyond standart dialog optios could have additional boolean property "closeOnSuccess" (default is true) buttonCaptions = buttonCaptions || { ok: "Зберегти", cancel: "Відмовитись" }; options = options || {}; var customBeforeCloseHandler = options.beforeClose; options.beforeClose = function () { customBeforeCloseHandler && customBeforeCloseHandler(); $(frameIdSelector).remove(); } onSuccess = onSuccess || function (xhr) { }; var closeOnSuccess = (options.closeOnSuccess === undefined) || (options.closeOnSuccess === 'undefined') || options.closeOnSuccess; var internalSuccessHandler = function (dlg, xhr) { if (closeOnSuccess) { $(dlg).dialog("close"); } onSuccess && onSuccess(xhr.responseText ? xhr.responseText : xhr); } // prepare dom element for fieldset var formContainer = $("
"); var frameId = stc.utils.getNewId(); var frameIdSelector = "#" + frameId; var iframe = $("