1var global_counter = 1; // globalny unikalny licznik; może byÄ tylko inkrementowany 2var EXPAND_BUTTONS = {}; // miejsce na dane przycisków zwijania/rozwijania 3var GENSELECT_CALLBACKS = {}; // miejsce na callbacki z funkcji genSelect 4 5function assert(cond, text){ 6 if(!cond){ 7 alert('ASSERT:\n'+text); 8 } 9} 10 11if(!Object.values){ // polyfill dla Object.values() 12 Object.values = function(obj){ 13 return Object.keys(obj).map(function(e) { 14 return obj[e]; 15 }) 16 } 17} 18 19if(!String.replaceAt){ // polyfill dla String.replaceAt() 20 String.prototype.replaceAt = function(index, str){ 21 return this.substr(0, index) + str + this.substr(index + str.length); 22 } 23} 24 25if (typeof Object.assign != 'function') { // polyfill dla Object.assign 26 // Must be writable: true, enumerable: false, configurable: true 27 Object.defineProperty(Object, "assign", { 28 value: function assign(target, varArgs) { // .length of function is 2 29 'use strict'; 30 if (target == null) { // TypeError if undefined or null 31 throw new TypeError('Cannot convert undefined or null to object'); 32 } 33 34 var to = Object(target); 35 36 for (var index = 1; index < arguments.length; index++) { 37 var nextSource = arguments[index]; 38 39 if (nextSource != null) { // Skip over if undefined or null 40 for (var nextKey in nextSource) { 41 // Avoid bugs when hasOwnProperty is shadowed 42 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 43 to[nextKey] = nextSource[nextKey]; 44 } 45 } 46 } 47 } 48 return to; 49 }, 50 writable: true, 51 configurable: true 52 }); 53} 54 55$.fn.exists = function(){ // zwraca true jeÅli selektor jQuery zawiera jakieÅ elementy. Użycie: $('#element').exists() 56 return this.length !== 0; 57} 58 59 60 61// zamienia wszystkie puste anchory na void(0), żeby nie przewijaÅo ekranu po klikniÄciu na takim guziorze lub linku 62function replaceEmptyAnchors() 63{ 64 $('a[href$="#"]').attr('href', 'javascript:void(0)'); 65} 66 67addSeparators = function(nStr, separator){ 68 separator = separator || ' '; 69 nStr += ''; 70 const x = nStr.split('.'); 71 let x1 = x[0]; 72 const x2 = x.length > 1 ? '.' + x[1] : ''; 73 var rgx = /(\d+)(\d{3})/; 74 while (rgx.test(x1)) { 75 x1 = x1.replace(rgx, '$1' + separator + '$2'); 76 } 77 return x1 + x2; 78} 79 80formatCurrency = function(num, precision = 2, separator = ' '){ // konwertuje liczbÄ na format waluty 81 if(typeof precision != 'number'){ 82 precision = 2; 83 } 84 num = isNaN(num) || num === '' || num === null ? 0.00 : num; 85 var str = parseFloat(num).toFixed(precision); 86 if(separator){ 87 str = addSeparators(str, separator); 88 } 89 return str; 90} 91waluta = formatCurrency; // alias 92 93isSet = function(v){ // zwraca true jeÅli podana zmienna jest zdefiniowana 94 return (typeof v != 'undefined')? true : false; 95} 96 97toBoolean = function(v,true_value,false_value){ // zwraca wartoÅÄ true_value dla v != 0, "0", false, null i undefined 98 if(!isSet(v) || v == 0 || v == '0' || v == false || v == null){ 99 return isSet(false_value)? false_value : false; 100 } 101 102 return isSet(true_value)? true_value : true; 103} 104 105function padNumber(num, size) { // konwertuje liczbÄ na string zajmujÄ cy size pozycji 106 var s = "000000000" + num; 107 return s.substr(s.length-size); 108} 109 110function getUnixDay(date){ // zwraca JS Unix time of beginning of the 'date' given as Date object 111 return Math.floor(date.getTime() / 86400000)*86400000; 112} 113 114data2dataWizyty = function(data, separator) // konwertuje datÄ z formatu DD.MM.YYYY na YYYY-MM-DD 115{
116 if(data == ""){ 117 return ""; 118 } 119 separator = separator || '-'; 120 return data.substr(6,4) + separator + data.substr(3,2) + separator + data.substr(0,2); 121} 122 123dataWizyty2data = function(data, separator) // konwertuje datÄ z formatu YYYY-MM-DD na DD.MM.YYYY 124{ 125 if(data == ""){ 126 return ""; 127 } 128 separator = separator || '.'; 129 return data.substr(8,2) + separator + data.substr(5,2) + separator + data.substr(0,4); 130} 131 132 133// Próbuje wyciÄ gnÄ Ä godzinÄ i minutÄ z podanego stringa; string musi mieÄ postaÄ [[h]h:][m]m 134// Funkcja przyjmuje zakres czasu od 00:00 do 23:59 135// PominiÄcie godziny powoduje przyjÄcie wartoÅci 0. JeÅli nie da siÄ wyciÄ gnÄ Ä czasu, funkcja zwraca false. 136function validateTime(t, allow_seconds = false){ 137 if(!t){ 138 return false; 139 } 140 141 t = t.trim(); 142 143 if(allow_seconds){ 144 let match = t.match(/^([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-9]|[0-5][0-9]):([0-9]|[0-5][0-9])$|^([0-9]|[0-5][0-9]):([0-9]|[0-5][0-9])$|^([0-9]|[0-5][0-9])$/i); 145 if(match){ 146 if(match[1] && match[2] && match[3]){ // hh:mm:ss 147 return padNumber(match[1], 2) + ':' + padNumber(match[2], 2) + ':' + padNumber(match[3], 2); 148 } 149 else if(match[4] && match[5]){ // mm:ss 150 return '00:' + padNumber(match[4], 2) + ':' + padNumber(match[5], 2); 151 } 152 else if(match[6]){ // ss 153 return '00:00:' + padNumber(match[6], 2); 154 } 155 return '00:00:00'; 156 } 157 } 158 else { 159 let match = t.match(/^([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-9]|[0-5][0-9])$|^([0-9]|[0-5][0-9])$/i); 160 if(match){ 161 if(match[1] && match[2]){ // hh:mm 162 return padNumber(match[1], 2) + ':' + padNumber(match[2], 2); 163 } 164 if(match[3]){ // tylko minuty 165 return '00:' + padNumber(match[3], 2); 166 } 167 } 168 } 169 return false; 170} 171 172function validateAmount(numStr){ 173 var numNum = +numStr; 174 return !isNaN(numNum); 175} 176 177// zwraca nazwÄ miesiÄ ca podanÄ jako numer miesiÄ ca z obiektu Date(), czyli styczeÅ to 0 178function getMonthName(mt, short_name = false, dopelniacz = false){ 179 180 if(dopelniacz){ 181 switch(+mt){ 182 case 1 : return 'lutego'; 183 case 2 : return 'marca'; 184 case 3 : return 'kwietnia'; 185 case 4 : return 'maja'; 186 case 5 : return 'czerwca'; 187 case 6 : return 'lipca'; 188 case 7 : return 'sierpnia'; 189 case 8 : return 'wrzeÅnia'; 190 case 9 : return 'października'; 191 case 10 : return 'listopada'; 192 case 11 : return 'grudnia'; 193 default : 194 return 'stycznia'; 195 } 196 } 197 else { 198 switch(+mt){ 199 case 1 : return short_name? 'Lut' : 'Luty'; 200 case 2 : return short_name? 'Mar' : 'Marzec'; 201 case 3 : return short_name? 'Kwi' : 'KwiecieÅ'; 202 case 4 : return short_name? 'Maj' : 'Maj'; 203 case 5 : return short_name? 'Cze' : 'Czerwiec'; 204 case 6 : return short_name? 'Lip' : 'Lipiec'; 205 case 7 : return short_name? 'Sie' : 'SierpieÅ'; 206 case 8 : return short_name? 'Wrz' : 'WrzesieÅ'; 207 case 9 : return short_name? 'Paź' : 'Październik'; 208 case 10 : return short_name? 'Lis' : 'Listopad'; 209 case 11 : return short_name? 'Gru' : 'GrudzieÅ'; 210 default : 211 return short_name? 'Sty' : 'StyczeÅ'; 212 } 213 } 214} 215 216// zwraca nazwÄ dnia tygodnia podanÄ jako numer z dat terminarza, czyli niedziela to 0, sobota to 6 217function getWeekdayName(wd, short_name = false, very_short_name = false, very_very_short_name = false){ 218 switch((+wd) % 7){
219 case 0 : return short_name? (very_short_name? (very_very_short_name? 'N' : 'Nd') : 'Nie') : 'Niedziela'; 220 case 1 : return short_name? (very_short_name? (very_very_short_name? 'P' : 'Po') : 'Pon') : 'PoniedziaÅek'; 221 case 2 : return short_name? (very_short_name? (very_very_short_name? 'W' : 'Wt') : 'Wto') : 'Wtorek'; 222 case 3 : return short_name? (very_short_name? (very_very_short_name? 'Å' : 'År') : 'Åro') : 'Åroda'; 223 case 4 : return short_name? (very_short_name? (very_very_short_name? 'C' : 'Cz') : 'Czw') : 'Czwartek'; 224 case 5 : return short_name? (very_short_name? (very_very_short_name? 'P' : 'Pt') : 'PiÄ ') : 'PiÄ tek'; 225 case 6 : return short_name? (very_short_name? (very_very_short_name? 'S' : 'So') : 'Sob') : 'Sobota'; 226 } 227 return '?weekday?'; 228} 229 230// konwertuje duÅ¼Ä wartoÅÄ na string celem unikniÄcia scientific notation 231function toFixed(x){ 232 if (Math.abs(x) < 1.0) { 233 var e = parseInt(x.toString().split('e-')[1],10); 234 if (e) { 235 x *= Math.pow(10,e-1); 236 x = '0.' + (new Array(e)).join('0') + x.toString().substring(2); 237 } 238 } else { 239 var e = parseInt(x.toString().split('+')[1],10); 240 if (e > 20) { 241 e -= 20; 242 x /= Math.pow(10,e); 243 x += (new Array(e+1)).join('0'); 244 } 245 } 246 return x; 247} 248/* 249// podobnie jak $.center(), ale zawsze na Årodku ekranu, bez wzglÄdu na przewiniÄcie 250jQuery.fn.center2 = function () { 251 this.css("position","absolute"); 252 this.css("top", Math.max(0, (($(window).height() - $(this).outerHeight()) / 2) + 253 $(window).scrollTop()) + "px"); 254 this.css("left", Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) + 255 $(window).scrollLeft()) + "px"); 256 return this; 257} 258*/ 259 260$.fn.extend({ 261 center: function () { 262 return this.each(function() { 263 var top = ($(window).height() - $(this).outerHeight()) / 2; 264 var left = ($(window).width() - $(this).outerWidth()) / 2; 265 $(this).css({position:'absolute', margin:0, top: (top > 0 ? top : 0)+'px', left: (left > 0 ? left : 0)+'px'}); 266 }); 267 }, 268 center2: function () { // podobnie jak $.center(), ale zawsze na Årodku ekranu, bez wzglÄdu na scroll dokumentu 269 var wh = $(window).height(); 270 var ww = $(window).width(); 271 var ws = $(window).scrollTop(); 272 var wl = $(window).scrollLeft(); 273 274 return this.each(function() { 275 $(this).css("position","absolute"); 276 $(this).css("top", Math.max(0, ((wh - $(this).outerHeight()) / 2) + ws) + "px"); 277 $(this).css("left", Math.max(0, ((ww - $(this).outerWidth()) / 2) + wl) + "px"); 278 }); 279 }, 280 shake : function (ampl,number) { 281 return this.each(function() { 282 ampl = ampl || 10; 283 number = number || 4; 284 $(this).css({ "position": "relative" }); 285 for (var x = 0; x < number; x++) { 286 $(this).animate({ left: -ampl }, 10).animate({ left: 0 }, 50).animate({ left: ampl }, 10).animate({ left: 0 }, 50); 287 } 288 }); 289 }, 290 setChecked : function (checked) { 291 if(typeof checked == 'string'){ 292 checked = +checked; 293 } 294 return this.each(function() { 295 $(this).prop('checked', checked? 1 : 0); 296 }); 297 }, 298 getChecked : function () { 299 return this.prop('checked')? 1 : 0; 300 }, 301 setRadioVal : function (value) { 302 return this.each(function(){ 303 $(this).prop('checked', $(this).attr('value') == value? 1 : 0); 304 }); 305 }, 306 getRadioVal : function () { 307 return this.filter(":checked").val(); 308 }, 309 // \param my Punkt odniesienia dla umieszczanego elementu; np. 'center top' lub 'left'. Jak nie ma drugiej wspóÅrzÄdnej, przyjmujemy 'center'. ObowiÄ zuje dokÅadnie jedna spacja pomiÄdzy. 310 // \param at Punkt odniesienia w docelowym elemencie. (podobnie jak parametr 'my') 311 // \param of Obiekt jQuery docelowego elementu. 312 // \param dx Dodatkowy offset [w pikselach] w poziomie; default: 0 313 // \param dy Dodatkowy offset [w pikselach] w pionie; default: 0 314 // PrzykÅad: $('#umieszczany_element').align('left top', 'right center', '#do_tego_wyrównujemy', 10, 20) 315 // To nam umieÅci element tak, że jego lewy górny róg znajdzie siÄ na Årodku prawej krawÄdzi docelowego elementu
316 align : function(my, at, $of, dx, dy){ // my,at: <horizontal> [<vertical>]; of: jQuery selektor elementu, do którego wyrównujemy 317 return this.each(function() { 318 dx = +dx || 0; 319 dy = +dy || 0; 320 321 var myi = $(this); 322 323 var my_w = myi.width(); 324 var my_h = myi.height(); 325 326 my_w += (parseInt(myi.css('padding-left') || '0',10) + parseInt(myi.css('padding-right') || '0',10)); 327 my_h += (parseInt(myi.css('padding-top') || '0',10) + parseInt(myi.css('padding-bottom') || '0',10)); 328 329 my_w += (parseInt(myi.css('border-left') || '0',10) + parseInt(myi.css('border-right') || '0',10)); 330 my_h += (parseInt(myi.css('border-top') || '0',10) + parseInt(myi.css('border-bottom') || '0',10)); 331 332// $of = $($of); 333 var of_w = $of.width() + (parseInt($of.css('padding-left') || '0',10) + parseInt($of.css('padding-right') || '0',10)); 334 var of_h = $of.height() + (parseInt($of.css('padding-top') || '0',10) + parseInt($of.css('padding-bottom') || '0',10)); 335 of_w += (parseInt($of.css('border-left') || '0',10) + parseInt($of.css('border-right') || '0',10)); 336 of_h += (parseInt($of.css('border-top') || '0',10) + parseInt($of.css('border-bottom') || '0',10)); 337 338 var of_left = $of.offset().left; 339 var of_top = $of.offset().top; 340 341 my = my.split(' '); 342 at = at.split(' '); 343 344 var my_left = my[0]; 345 var my_top = my[1]; 346 var at_left = at[0]; 347 var at_top = at[1]; 348 349 // i jeszcze wyjÄ tki dla top i bottom 350 if(my[0] == 'top'){ 351 my_left = 'center'; 352 my_top = 'top'; 353 } 354 else if(my[0] == 'bottom'){ 355 my_left = 'center'; 356 my_top = 'bottom'; 357 } 358 if(at[0] == 'top'){ 359 at_left = 'center'; 360 at_top = 'top'; 361 } 362 else if(at[0] == 'bottom'){ 363 at_left = 'center'; 364 at_top = 'bottom'; 365 } 366 367 var left = of_left; 368 var top = of_top; 369 370 // defaultowo left,top odnosi siÄ do lewego górnego rogu elementu; na podstawie parametrów przesuÅmy te pozycje 371 if(my_left == 'left'){ 372 ; // jest ok 373 } 374 else if(my_left == 'right'){ 375 left -= my_w; 376 } 377 else { 378 left -= my_w/2; 379 } 380 381 if(my_top == 'top'){ 382 ; // jest ok 383 } 384 else if(my_top == 'bottom'){ 385 top -= my_h; 386 } 387 else { 388 top -= my_h/2; 389 } 390 391 392 if(at_left == 'left'){ 393 ; // jest ok 394 } 395 else if(at_left == 'right'){ 396 left += of_w; 397 } 398 else { 399 left += of_w/2; 400 } 401 402 if(at_top == 'top'){ 403 ; // jest ok 404 } 405 else if(at_top == 'bottom'){ 406 top += of_h; 407 } 408 else { 409 top += of_h/2; 410 } 411 412 var left_px = +left + +dx; 413 var top_px = +top + +dy; 414 myi.css('left', left_px + 'px'); 415 myi.css('top', top_px + 'px'); 416 417 }); 418 419 }, 420 GoogleTranslate : function (callback) { 421 var str = $($(this).attr('from')).val(); 422 var $to = $($(this).attr('to')); 423 var lang_from = $(this).attr('lang_from'); 424 var lang_to = $(this).attr('lang_to'); 425 426 GoogleTranslate(lang_from, lang_to, str, function(localized){ 427 CResultFader3('OK', 1000, 'ok'); 428 if(typeof callback == 'function'){ 429 callback(localized); 430 } 431 else { 432 $to.val(localized); 433 } 434 }); 435 436 return this.prop('checked')? 1 : 0; 437 }, 438 439}); 440 441function GoogleTranslate(lang_from, lang_to, str, callback){ 442 443 var spinner = new CWaitSpinner(); 444 445 var url = 'https://translate.googleapis.com/translate_a/single?client=gtx&sl=' + lang_from + '&tl=' + lang_to + '&hl=' + lang_to + '&dt=t&dt=bd&dj=1&source=icon&tk=467103.467103&q=' + encodeURIComponent(str); 446 447 $.ajax({ 448 url: url, 449 type: "GET", 450// data: fd, 451 enctype: 'application/json', 452 dataType: "json", 453 processData: false, // tell jQuery not to process the data 454 contentType: false // tell jQuery not to set contentType 455 }).done(function( resp ) { 456 spinner.close(); 457 458 var localized = ''; 459 if(resp.sentences){
460 resp.sentences.forEach(function(sentence){ 461 localized += sentence.trans; 462 }); 463 } 464 else { 465 CResultFader3('Nie znaleziono tÅumaczenia.', 2000, 'error'); 466 return; 467 } 468 469 if(typeof callback === 'function'){ 470 if(localized.length && str.length && str[0].toUpperCase() === str[0]){ // 471 localized = localized.replaceAt(0, localized[0].toUpperCase()); 472 } 473 callback(localized); 474 } 475 476 477 }).fail(function( jqXHR, textStatus ){ 478 spinner.close(); 479 alert('Pobranie tÅumaczenia nie powiodÅo siÄ. OdÅwież przeglÄ darkÄ i spróbuj ponownie.\nBÅÄ d: ' + textStatus); 480 }); 481} 482 483 484(function($) { 485 $.addslashes = function (str) { 486 if(str.replace){ 487 str = str.replace(/\'/g,'\\\''); 488 str = str.replace(/\"/g,'\\"'); 489 str = str.replace(/\\/g,'\\\\'); 490 str = str.replace(/\0/g,'\\0'); 491 } 492 return str; 493 }; 494})(jQuery); 495 496function replaceAll(find, replace, str) { 497 return str.replace(new RegExp(find, 'g'), replace); 498} 499 500deepcopy = function(obj){ 501 return jQuery.extend(true, {}, obj); 502} 503 504// wyszukuje i zwraca nastÄpny indeks obiektu lub tablicy (liczÄ c od zera) 505findNextIndex = function(obj){ 506 var idx = 0; 507 for(var i in obj){ 508 if(+i >= idx){ 509 idx = +i+1; 510 } 511 } 512 return idx; 513} 514 515// bezpiecznie usuwa wskazany element zarówno z tablicy, jak i z obiektu 516deleteMember = function(object, member){ 517 if(object.constructor === Array){ 518 object.splice(member,1); 519 } 520 else { 521 delete object[member]; 522 } 523} 524 525// zwraca rozmiar zarówno tablicy, jak i obiektu 526getArraySize = function(arr) 527{ 528 var i = 0; 529 for(let a in arr){ 530 i++; 531 } 532 return i; 533} 534 535/* 536escapeHTML = function(str) 537{ 538 if(typeof str === 'undefined'){ 539 return ''; 540 } 541 try { 542 return( 543 (str+'').replace(/&/g,'&'). 544 replace(/>/g,'>'). 545 replace(/</g,'<'). 546 replace(/'/g, '''). 547 replace(/"/g,'"') 548 ); 549 } 550 catch(e){ 551 return ''; 552 } 553} 554*/ 555function _html(str){ 556//function escapeHTML(str){ 557 558 if(typeof str === 'undefined' || str === null){ 559 return ''; 560 } 561 562 const entityMap = { 563 '&': '&', 564 '<': '<', 565 '>': '>', 566 '"': '"', 567 "'": ''', 568 '/': '/', 569 '\\':'\', 570 '`': '`', 571 '=': '=', 572 '|': 'C;' 573 }; 574 575 return str.toString().replace(/[&<>"'`=\/\\|]/g, s => entityMap[s]); 576} 577 578//const _html = (str) => escapeHTML(str); 579 580 581function htmlEscape(str) { 582 var stringval=""; 583 $.each(str, function (i, element) { 584 stringval += element 585 .replace(/&/g, '&') 586 .replace(/"/g, '"') 587 .replace(/'/g, ''') 588 .replace(/</g, '<') 589 .replace(/>/g, '>') 590 .replace(' ', '-') 591 .replace('?', '-') 592 .replace(':', '-') 593 .replace('|', '-') 594 .replace('.', '-'); 595 }); 596 return String(stringval); 597} 598 599function escapeAngleBraces(str){ 600 if(typeof str === 'undefined'){ 601 return ''; 602 } 603 try { 604 return((str+'').replace(/>/g,'>').replace(/'/g, '\'').replace(/</g,'<')); 605 } 606 catch(e){ 607 return ''; 608 } 609} 610 611 612todayDate = function(format_wizyty, separator) // zwraca bieÅ¼Ä cÄ datÄ w formacie zwykÅym (DD.MM.YYYY) lub wizyty (YYYY-MM-DD) 613{ 614 var today = new Date(); 615 var dd = today.getDate(); 616 dd = (+dd < 10)? '0'+dd : dd; 617 var mm = today.getMonth()+1; //January is 0! 618 mm = (+mm < 10)? '0'+mm : mm; 619 var yyyy = today.getFullYear(); 620 if(format_wizyty){ 621 separator = separator || '-'; 622 return yyyy+separator+mm+separator+dd; 623 } 624 else { 625 separator = separator || '.'; 626 return dd+separator+mm+separator+yyyy; 627 } 628} 629 630function date2string(date, format_wizyty, separator) // zamienia obiekt daty na string YYYY.MM.DD 631{ 632 var dd = date.getDate(); 633 dd = (+dd < 10)? '0'+dd : dd; 634 var mm = date.getMonth()+1; //January is 0! 635 mm = (+mm < 10)? '0'+mm : mm; 636 var yyyy = date.getFullYear(); 637 if(format_wizyty){ 638 separator = separator || '-'; 639 return yyyy+separator+mm+separator+dd; 640 } 641 else { 642 separator = separator || '.'; 643 return dd+separator+mm+separator+yyyy; 644 } 645} 646 647// przyjmuje datÄ w formacie yyyy.[0]m.[0]d lub [0]d.[0]m.yyyy i sprawdza, czy jest poprawna. 648// JeÅli tak, zwraca datÄ, jeÅli nie, zwraca false. W zwróconej dacie jednocyfrowe dni i miesiÄ ce bÄdÄ zawieraÅy wiodÄ ce zera 649// \param date Data do sprawdzenia 650// \param format_wizyty JeÅli true, zwraca datÄ w formacie yyyy.mm.dd; jeÅli false, w formacie dd.mm.yyyy 651// \param separator Separator czÄÅci daty, defaultowo kropka 652function validateDate(date, format_wizyty = true, separator = '-'){ 653 654 separator = separator || '.'; 655 656 var value = date+''; 657 var match = value.match(/^(0?[1-9]|[12]?[0-9]|3[01])[\.\-\/_](0?[1-9]|1[012])[\.\-\/_](19[0-9]{2}|20[0-9]{2})$/); 658 if(match){ 659 value = match[1] + separator + match[2] + separator + match[3]; // przepiszmy datÄ z użyciem separatora 660 } 661 else { 662 // może wpisana odwrotnie? 663 match = value.match(/^(19[0-9]{2}|20[0-9]{2})[\.\-\/_](0?[1-9]|1[012])[\.\-\/_](0?[1-9]|[12]?[0-9]|3[01])$/); 664 if(match){ // ok, data byÅa wpisana odwrotnie, wiÄc wpiszmy poprawnie 665 value = match[3] + separator + match[2] + separator + match[1]; 666 } 667 else { 668 return false; // nie rozpoznano daty 669 } 670 } 671 672 // zamieÅmy datÄ na postaÄ dd.mm.rrrr 673 var data_ur = value.split(separator); 674 value = padNumber(data_ur[0],2) + separator + padNumber(data_ur[1],2) + separator + data_ur[2]; 675 676 if(format_wizyty){ 677 value = data2dataWizyty(value,separator); 678 } 679 680 return value; 681} 682 683// ustawia stan checkboxa (id podawane jak selektor jQuery) 684function setChecked(id, checked){ 685 $(id).prop('checked', checked? 1 : 0); 686} 687 688// zwraca stan checkboxa (id podawane jak selektor jQuery) jako numeryczne 0 lub 1 689function getChecked(id){ 690 return $(id).prop('checked')? 1 : 0; 691} 692 693// zwraca stan radia 694// \param name Atrybut name inputa radia 695function getRadioVal(name){ 696 return $('input:radio[name="'+name+'"]:checked').val(); 697} 698 699// zwraca wartoÅÄ kontrolki (id podawane jak dla selektora jQuery). Na życzenie konwertuje do liczby 700function getVal(id, as_numeric){ 701 return as_numeric? +($(id).val()) : $(id).val(); 702} 703 704// helper do sortowania i filtrowania obiektu. 705// \param obj Obiekt lub tablica z elemntami do sortowania i filtrowania 706// \param sort_fn Standardowa funkcja przekazywana do array.sort(a, b). Opcjonalna. JeÅli parametr jest typu 'string', 707// to jest używana standardowa funkcja generic_compare_desc(a[<parametr>], b[<parametr>], 0, 0). 708// JeÅli string zaczyna siÄ od minusa (-), to elementy sÄ sortowane w kolejnoÅci odwrotnej 709// JeÅli string zaczyna siÄ od plusa (+), to elementy sÄ sortowane numerycznie wg kolejnoÅci rosnÄ cej 710// Jesli parametr jest pustym stringiem, to elementy sÄ porównywane bezpoÅrednio: generic_compare_desc(a, b, 0, 0) 711// \param filter_fn JeÅli jest, to jest woÅana jako filter_fn(obj) i powinna zwr
711óciÄ true lub false. Defaultowa funkcja zwraca true. 712// \param loop_fn JeÅli jest, to jest woÅana jako loop_fn(arr[i], i, arr) dla każdego elementu w wynikowej (posortowanej) tablicy. JeÅli zwróci === false, iterowanie siÄ zakoÅczy. 713// \return Zwraca posortowanÄ i odfiltrowanÄ tablicÄ ([]) 714function filterAndSortArray(obj, sort_fn, filter_fn, loop_fn){ 715 filter_fn = filter_fn || function(obj, idx){ return true;}; 716 717 if(typeof obj == 'undefined' || obj === null){ 718 return []; 719 } 720 let arr = Object.values(obj).filter(filter_fn); 721 if(typeof(sort_fn) == 'function'){ 722 arr.sort(sort_fn); 723 } 724 else if(sort_fn === ''){ 725 arr.sort(function(a, b){ 726/* 727 if(typeof a[sort_fn] == 'undefined'){ 728 throw Error('Nie ma ID', sort_fn, a); 729 } 730 if(typeof b[sort_fn] == 'undefined'){ 731 throw Error('Nie ma ID', sort_fn, b); 732 } 733*/ 734 return generic_compare_desc(a.toString(), b.toString(), 0, 0); 735 }); 736 } 737 else if(typeof(sort_fn) == 'string'){ 738 if(sort_fn[0] == '-' && sort_fn[1] == '+'){ 739 const sort_fld = sort_fn.substring(2); 740 arr.sort(function(a, b){ 741/* 742 if(typeof a[sort_fn] == 'undefined'){ 743 throw Error('Nie ma ID', sort_fn, a); 744 } 745 if(typeof b[sort_fn] == 'undefined'){ 746 throw Error('Nie ma ID', sort_fn, b); 747 } 748*/ 749 return generic_compare(+a[sort_fld], +b[sort_fld], 0, 0, true); 750 }); 751 } 752 else if(sort_fn[0] == '-'){ 753 const sort_fld = sort_fn.substring(1); 754 arr.sort(function(a, b){ 755/* 756 if(typeof a[sort_fn] == 'undefined'){ 757 throw Error('Nie ma ID', sort_fn, a); 758 } 759 if(typeof b[sort_fn] == 'undefined'){ 760 throw Error('Nie ma ID', sort_fn, b); 761 } 762*/ 763 return generic_compare(a[sort_fld].toString(), b[sort_fld].toString(), 0, 0); 764 }); 765 } 766 else if(sort_fn[0] == '+'){ 767 const sort_fld = sort_fn.substring(1); 768 arr.sort(function(a, b){ 769/* 770 if(typeof a[sort_fn] == 'undefined'){ 771 throw Error('Nie ma ID', sort_fn, a); 772 } 773 if(typeof b[sort_fn] == 'undefined'){ 774 throw Error('Nie ma ID', sort_fn, b); 775 } 776*/ 777 return generic_compare_desc(+a[sort_fld], +b[sort_fld], 0, 0, true); 778 }); 779 } 780 else { 781 const sort_fld = sort_fn; 782 arr.sort(function(a, b){ 783/* 784 if(typeof a[sort_fn] == 'undefined'){ 785 throw Error('Nie ma ID', sort_fn, a); 786 } 787 if(typeof b[sort_fn] == 'undefined'){ 788 throw Error('Nie ma ID', sort_fn, b); 789 } 790*/ 791 return generic_compare_desc(a[sort_fld].toString(), b[sort_fld].toString(), 0, 0); 792 }); 793 } 794 } 795 796 if(typeof(loop_fn) == 'function'){ 797 for(var i = 0; i < arr.length; ++i){ 798 if(loop_fn(arr[i], i, arr) === false){ 799 break; 800 } 801 } 802 } 803 return arr; 804} 805 806// Klasa do wyÅwietlania modalnego okienka dialogowego. Okienko defaultowo ma przycisk do zamykania 807// oraz ewentualny czarny background na caÅy dokument. Daje możliwoÅÄ wypeÅnienia contentem zapodanym 808// przez użytkownika. 809// \param options Obiekt z opcjami dla okienka 810// Najważniejsze opcje to: 811// $container = null JeÅli jest, zostanie użyte jako kanwas dla dialogu. 812// id ID dialogu; na tej podstawie zostanie wygenerowane także ID ciemnego tÅa pod spodem 813// add_classes Dodatkowe klasy, które zostanÄ dodane do diva z dialogiem 814// z_index = 5 z-index dla dialogu 815// no_bkg = false Gdy true, to pod okienkiem nie bÄdzie ciemnego tÅa na caÅy dokuemt 816// dont_exit_on_bkg = 1 TRUE oznacza, że klikniÄcie na ciemnym tle nie powoduje wyjÅcia z okienka 817// dont_show_at_once = false Gdy true, konstruktor nie wywoÅuje automatycznie metody showDlg() 818// width = 'auto' SzerokoÅÄ okienka jest dopasowywana do zawartoÅci i może byÄ korygowana w css (wartoÅÄ 'auto'), ale można jÄ też okreÅliÄ na sztywno jako wartoÅÄ atrybutu width w css (wartoÅÄ inna niż auto jest brana dosÅownie jako width:<wartoÅÄ>) 819// height = 'auto' WysokoÅÄ okienka jest dopasowywana do zawartoÅci i może byÄ korygowana w css (wartoÅÄ 'auto'), ale można jÄ też okreÅliÄ na sztywno jako wartoÅÄ atrybutu height w css (wartoÅÄ inna niż auto jest brana dosÅownie jako height:<wartoÅÄ>) 820// opacity = 0.8 PrzezroczystoÅÄ tÅa
821// dlg_color = 'inherit' Kolor okna dialogu. Może byÄ podany kolor lub css - wtedy tÅo jest brane z css-a 822// dlg_class = 'modal_dlg_bkg' Klasa dialogu 823// no_reposition = false TRUE oznacza, że okno po wyÅwietleniu nie bÄdzie repozycjonowane 824// skip_despace = false TRUE oznacza, że z tekstu html dla okienka nie bÄdÄ wycinane whitespacje (bo pewnie już sÄ wyciÄte) 825// parent = 'body' Parent, do którego zostanie doÅÄ czone okienko 826// before_close_callback = false JeÅli jest, to zostanie wywoÅana tuż przed zamkniÄciem okienka na ekranie. Parametrem funkcji jest this do CModalDlg2 827// ctrl_s_callback = null JeÅli jest, to zostanie wywoÅane po wciÅniÄciu kombinacji Ctrl+S (zamiast zapisywania html-a do pliku) 828// on_exit_fn = null JeÅli jest, to zostanie wywoÅana przed anulowaniem okienka (klikniÄcie na bkg, zamkniÄcie przyciskiem, klawisz Esc) 829// \param content_fn JeÅli jest, to powinien byÄ funkcjÄ zwracajÄ cÄ tekst do wypeÅnienia contentem. Parametrem funkcji jest this do CModalDlg2 830// \param after_show_fn JeÅli jest, to zostanie wywoÅana po wyÅwietleniu okienka na ekranie (jeszcze przed wycentrowaniem). Parametrem funkcji jest this do CModalDlg2 831CModalDlg2 = function(options, content_fn, after_show_fn){ 832 if(!options.id){ 833 console.log('CModalDlg2: nie podano ID dialogu'); 834 return; 835 } 836 var self = this; 837 838 var o = options; 839 o.$container ??= null; 840 o.z_index = o.z_index || 5; 841 o.width = o.width || 'auto'; 842 o.height = o.height || 'auto'; 843 o.left = (o.left != undefined)? o.left : 'center'; 844 o.right = o.right || 0; 845 o.top = (o.top != undefined)? o.top : 'center'; 846 o.bottom = o.bottom || 0; 847 o.margin = o.margin || 0; 848 o.dont_show_at_once = o.dont_show_at_once || false; 849 o.opacity = o.opacity || 0.8; 850 o.dlg_color = o.dlg_color || ''; // '#D0E6E6'; 851 o.dlg_class = o.dlg_class || 'modal_dlg_bkg'; 852 o.no_reposition = o.no_reposition || false; 853 o.parent = o.parent || 'body'; 854 self.content_fn = content_fn || function(){return '';}; 855 self.after_show_fn = after_show_fn || function(){}; 856 o.dont_exit_on_bkg = typeof o.dont_exit_on_bkg != 'undefined'? o.dont_exit_on_bkg : true; 857 o.no_close_btn = typeof o.no_close_btn != 'undefined'? o.no_close_btn : false; 858 o.no_center_after_tab_select = typeof o.no_center_after_tab_select != 'undefined'? o.no_center_after_tab_select : false; 859 o.skip_despace = o.skip_despace || false; 860 861 if(o.dlg_color == 'from_class'){ 862 o.dlg_color = ''; 863 } 864 865 this.options = o; 866 867 let $dlg = o.$container; 868 869 if(!o.dont_show_at_once){ 870 self.showDlg(); 871 } 872 873 self.close = self.closeDlg; // alternatywna nazwa funkcji do zamykania dialogu, bo siÄ myli 874 875 this.getDlg = function(){ // zwraca obiekt jQuery dialogu jako takiego 876 return $dlg; 877 } 878 879 this.closeDlg = function(call_callback){ 880 881 if(self.already_closed || o.$container){ 882 return; 883 } 884 885 self.already_closed = true; // dziÄki temu ewentualne kolejne zamkniÄcie speÅznie na niczym 886 887 var curr_dlg = self.dlg_stack[self.dlg_stack.length-1]; 888 if(call_callback && typeof(curr_dlg.options.before_close_callback) == 'function'){ 889 curr_dlg.options.before_close_callback(curr_dlg); 890 } 891 892 self.dlg_stack.pop(); 893 894 if(typeof o.ctrl_s_callback == 'function'){ // jesli dialog obsÅugiwaÅ Ctrl+S, to odbindujmy to zdarzenie 895 if(!self.dlg_stack.length){ 896 $(window).off('keydown.modal_dlg'); 897 } 898 } 899 900 if(!o.no_bkg || o.$container){ 901 $('.'+o.id+'_dark_bkg').remove(); 902 } 903 904 if($dlg && !o.$container){ 905 $dlg.remove(); 906 } 907 // delete this; 908 } 909 910 this.center = function(){ 911 if(!o.$container){ 912 $dlg.center2(); 913 } 914 } 915 916 this.getStyle = function(){ 917 var st = $(window).scrollTop(); 918 var sl = $(window).scrollLeft(); 919 920 var txt = 'padding:5px;position:absolute;left:'+sl+'px;top:'+st+'px;z-index:'+(o.z_index+1); 921 if(o.dlg_color != 'css'){ 922 txt += ';background:'+o.dlg_color+';'; 923 } 924 return txt; 925 } 926 927 this.showDlg = function(){ 928// self.closeDlg(0); 929 930 var txt = ''; 931 932 var bkg_width = $(document).width(); 933 var bkg_height = $(document).height(); 934 935 let $dlg_int; 936 937 if(!o.$container){ 938 if(!o.no_bkg){ 939 txt += '<div class="modal_dlg_dark_bkg '+o.id+'_dark_bkg" style="z-index:'+o.z_index+';position:fixed;background:black;opacity:'+o.opacity+';width:'+(bkg_width-1)+'px;height:'+(bkg_height-1)+'px;left:0;top:0;"></div>'; 940 } 941 942 txt += '<div class="' + o.dlg_class; 943 if(o.add_classes){ 944 txt += ' ' + o.add_classes; 945 } 946 txt += '" style="' + self.getStyle() + '" id="'+o.id+'">'; 947 948 txt += '<div class="modal_dlg_int" id="'+o.id+'_int">'; 949 var tt = self.content_fn(self); 950 951 if(typeof(tt) != 'string'){ 952 tt = '<span class="color_red">Funkcja powinna zwracaÄ string z HTML-em dialogu</span>'; 953 } 954 955 if(!o.skip_despace){ 956 tt = tt.despace(); 957 } 958 959 txt += tt; 960 txt += '</div>'; 961 if(!o.no_close_btn){ 962 txt += '<div class="dlg_close_btn jeden" id="'+o.id+'_close_btn_jeden" title="Anuluj i wyjdź"></div>'; 963 txt += '<div class="dlg_close_btn dwa" id="'+o.id+'_close_btn_dwa" title="Anuluj i wyjdź"></div>'; 964 } 965 txt += '<div style="clear:both"></div>'; 966 txt += '</div>'; 967 968 $(o.parent).append(txt); 969 970 if(o.add_classes){ 971 let classes = o.add_classes.split(' ').join('.'); 972 $dlg = $('.'+classes+'#'+o.id); 973 } 974 else { 975 $dlg = $('#'+o.id); 976 } 977 978 $dlg_int = $dlg.find('#'+o.id+'_int'); 979 980 if(o.width == 'auto'){ 981 $dlg_int.css('width', 'auto'); 982 } 983 else if(o.width == 'css'){ 984 // wartoÅÄ ustawiana w css 985 } 986 else { 987 const w = o.width[o.width.length-1] == ';'? o.width.substring(0, o.width.length-1) : o.width; 988 $dlg_int.css('width', w); 989 $dlg_int.css('overflow', 'auto'); 990 } 991 992 if(o.height == 'auto'){ 993 $dlg_int.css('height', 'auto'); 994 } 995 else if(o.height == 'css'){ 996 // wartoÅÄ ustawiana w css 997 } 998 else if(o.height){ 999 const h = o.height[o.height.length-1] == ';'? o.height.substring(0, o.height.length-1) : o.height; 1000 $dlg_int.css('height', h); 1001 $dlg_int.css('overflow', 'auto'); 1002 } 1003 1004 1005 // $dlg_int.css('width', o.width+'px'); 1006 1007 $dlg.find('.dlg_close_btn').click(function(){ 1008 if(typeof o.on_exit_fn == 'function'){ 1009 o.on_exit_fn(); 1010 } 1011 self.closeDlg(1); 1012 }); 1013 1014 if(!o.dont_exit_on_bkg){ 1015 $('.'+o.id+'_dark_bkg').click(function(){ // tupniÄcie na tle wychodzi z dialogu 1016 if(typeof o.on_exit_fn == 'function'){ 1017 o.on_exit_fn(); 1018 } 1019 self.closeDlg(1); 1020 }); 1021 } 1022 } 1023 else { // stwórzmy bardzo prostÄ ramkÄ
1024 const $dlg = $('<div/>').addClass('modal_dlg_bkg').attr('id', o.id); 1025 1026 if(o.add_classes){ 1027 $dlg.addClass(o.add_classes); 1028 } 1029 1030 let txt = '<div class="modal_dlg_int" id="'+o.id+'_int">'; 1031 var tt = self.content_fn(self); 1032 1033 if(typeof(tt) != 'string'){ 1034 tt = '<span class="color_red">Funkcja powinna zwracaÄ string z HTML-em dialogu</span>'; 1035 } 1036 1037 if(!o.skip_despace){ 1038 tt = tt.despace(); 1039 } 1040 1041 txt += tt; 1042 txt += '</div>'; 1043 1044 $dlg_int = $(txt); 1045 1046 $dlg_int.appendTo($dlg); 1047 $dlg.appendTo(o.$container); 1048 } 1049 1050 self.after_show_fn(self); 1051 1052 if(typeof o.ctrl_s_callback == 'function'){ // jesli dialog chce obsÅużyÄ Ctrl+S, to zbindujmy to zdarzenie 1053// if(!self.dlg_stack.length){ 1054 $(window).off('keydown.modal_dlg').on('keydown.modal_dlg', function(evt) { 1055 var key = String.fromCharCode(evt.keyCode); 1056 1057 if(key.toLowerCase() === "s" && (evt.ctrlKey || evt.metaKey)){ //ctrl+S 1058 var curr_dlg = self.dlg_stack[self.dlg_stack.length-1]; 1059 if(typeof curr_dlg.options.ctrl_s_callback == 'function'){ 1060 curr_dlg.options.ctrl_s_callback(curr_dlg); 1061 } 1062 evt.preventDefault(true); 1063 event.stopImmediatePropagation(); 1064 return false; 1065 } 1066 return true; 1067 }); 1068// } 1069 } 1070 1071 if(!o.no_Esc_close){ // jesli dialog nie blokuje zamykania skrótem Esc, to zbindujmy to zdarzenie 1072 if(!self.dlg_stack.length){ 1073 $(window).on('keydown.modal_dlg', function(evt) { 1074 var key = String.fromCharCode(evt.keyCode); 1075 1076// if(key.toLowerCase() === "x" && evt.ctrlKey){ // Ctrl+X 1077 if(evt.key === "Escape"){ // Esc 1078 evt.preventDefault(true); 1079 1080 if(typeof o.on_exit_fn == 'function'){ 1081 o.on_exit_fn(); 1082 } 1083 1084 if(self.dlg_stack.length){ 1085 var curr_dlg = self.dlg_stack[self.dlg_stack.length-1]; 1086 1087 curr_dlg.closeDlg(true); 1088 } 1089 1090 return false; 1091 } 1092 return true; 1093 }); 1094 } 1095 } 1096 1097 self.dlg_stack.push(self); 1098 1099 $dlg_int.find('.focus').focus(); // wybierzmy pole focusa na w caÅym dialogu 1100 1101 var $dialog_header = $dlg_int.find('.dialog_header'); 1102 if($dialog_header.length && $dialog_header.find('.tab_header').length > 1){ // obsÅugujemy zakÅadki tylko jeÅli jakieÅ sÄ 1103 var tab; 1104 if(!$dialog_header.find('.tab_header.selected').length >= 1){ // jeÅli nie ma aktywnej zakÅadki, to uaktywnijmy pierwszÄ z brzegu 1105 var th = $dialog_header.find('.tab_header'); 1106 tab = th.first().attr('tab'); 1107 1108 $dialog_header.find('.tab_header[tab="'+tab+'"]').addClass('selected'); 1109 } 1110 else { 1111 tab = $dialog_header.find('.tab_header.selected').first().attr('tab'); 1112 } 1113 1114 $dlg_int.find('.dialog_tab[tab="'+tab+'"]').addClass('selected'); 1115 $dlg_int.find('.dialog_tab[tab="'+tab+'"] .focus').focus(); // wybierzmy pole focusa na domyÅlnej zakÅadce 1116 1117 if(!o.no_center_after_tab_select){ // centrujemy obiekt tylko wtedy, gdy to nie jest zakazane 1118 self.center(); 1119 } 1120 1121 if(typeof self.set_tab_callback == 'function'){ 1122 self.set_tab_callback(tab); 1123 } 1124 1125 $dialog_header.find('.tab_header').click(function(){ 1126 var tab = $(this).attr('tab'); 1127 1128 $dialog_header.find('.tab_header').removeClass('selected'); 1129 $dlg_int.find('.dialog_tab').removeClass('selected'); 1130 $dialog_header.find('.tab_header[tab="'+tab+'"]').addClass('selected'); 1131 $dlg_int.find('.dialog_tab[tab="'+tab+'"]').addClass('selected'); 1132 $dlg_int.find('.dialog_tab[tab="'+tab+'"] .focus').focus(); // wybierzmy pole focusa na wybranej zakÅadce 1133 1134 if(!o.no_center_after_tab_select){ // centrujemy obiekt tylko wtedy, gdy to nie jest zakazane 1135 self.center(); 1136 } 1137 1138 if(typeof self.set_tab_callback == 'function'){ 1139 self.set_tab_callback(tab); 1140 } 1141 }); 1142 1143 przygotujDymki($dlg); 1144 1145 1146 } 1147 1148 if(!o.no_reposition){ 1149 self.reposition(); 1150 } 1151 } 1152 1153 this.reposition = function(){ 1154 self.center(); 1155 1156 if(o.left && o.left != 'center'){ 1157 $dlg.css('left', o.left + (typeof o.left == 'number'? 'px' : '')); 1158 } 1159 if(o.top && o.top != 'center'){ 1160 $dlg.css('top', o.top + (typeof o.top == 'number'? 'px' : '')); 1161 } 1162 if(o.right && o.right != 'center'){ 1163 $dlg.css('left', 'inherit'); 1164 $dlg.css('right', o.right + (typeof o.right == 'number'? 'px' : '')); 1165 } 1166 if(o.bottom && o.bottom != 'center'){ 1167 $dlg.css('top', 'inherit'); 1168 $dlg.css('bottom', o.bottom + (typeof o.bottom == 'number'? 'px' : '')); 1169 } 1170 } 1171 1172 this.selectTab = function(tab){ 1173 var $dlg_int = $dlg.find('#'+o.id+'_int'); 1174 var $dialog_header = $dlg_int.find('.dialog_header'); 1175 if($dialog_header.length && $dialog_header.find('.tab_header').length > 1){ // obsÅugujemy zakÅadki tylko jeÅli jakieÅ sÄ 1176 $dialog_header.find('.tab_header').removeClass('selected'); 1177 $dlg_int.find('.dialog_tab').removeClass('selected'); 1178 $dialog_header.find('.tab_header[tab="'+tab+'"]').addClass('selected'); 1179 $dlg_int.find('.dialog_tab[tab="'+tab+'"]').addClass('selected'); 1180 $dlg_int.find('.dialog_tab[tab="'+tab+'"] .focus').focus(); // wybierzmy pole focusa na wybranej zakÅadce 1181 1182 if(!o.no_center_after_tab_select){ // centrujemy obiekt tylko wtedy, gdy to nie jest zakazane 1183 self.center(); 1184 } 1185 } 1186 } 1187} 1188 1189CModalDlg2.prototype.dlg_stack = []; 1190 1191// W podanym parencie (obiekcie jQuery) wyszukuje elementy z atrybutem "dymek" i dopisuje do nich html-e z treÅciami dymków 1192function przygotujDymki($parent){ 1193 1194 $parent.find('.dymek_cont').remove(); // usuÅmy poprzednie dymki 1195/* 1196 $parent.find('*[dymek]').each(function(){ 1197 var lewy = $(this).attr('lewy'); 1198 var dym_id = $(this).attr('dymek'); 1199 1200 const head = $(this).attr('dymek_head'); 1201 const light = $(this).attr('dymek_light'); 1202 1203 var txt = dymek(dym_id, lewy, null, head, light); 1204 $(this).append(txt); 1205 }); 1206*/ 1207 $parent.find('*[dymek]').each(function(){ 1208 var lewy = $(this).attr('lewy'); 1209 const dymek = $(this).attr('dymek'); 1210 1211 const head = $(this).attr('dymek_head'); 1212 const light = $(this).attr('dymek_light'); 1213 1214 var txt = dymek2(dymek, lewy, $(this).attr('dymek_id'), head, light); 1215 $(this).append(txt); 1216 }); 1217 1218} 1219 1220 1221// Klasa do wyciÄ gania informacji z PESELA 1222// Po utworzeniu konstruktora możemy z obiektu wyciÄ gnÄ Ä: 1223// error: string z bÅÄdem lub null jak poprawny 1224// rok, miesiec, dzien: skladowe daty 1225// plec: pÅeÄ ('M' lub 'K') 1226// \param s PESEL do sprawdzenia 1227CPesel = function(s){ 1228 this.error = null; 1229 1230 if (s.length != 11){ // Sprawdźmy dÅugoÅÄ, musi byÄ 11 znaków 1231 this.error = 'musi mieÄ 11 cyfr'; 1232 return; 1233 } 1234 1235 // Sprawdźmy, czy wszystkie znaki to cyfry 1236 var aInt = new Array(); 1237 for(var i = 0; i < 11; i++){ 1238 aInt[i] = parseInt(s.substring(i,i+1),10); 1239 if(isNaN(aInt[i])){ 1240 this.error = 'musi zawieraÄ wyÅÄ cznie cyfry'; 1241 return; 1242 } 1243 } 1244 1245 // Sprawdźmy sumÄ kontrolnÄ 1246 var wagi = [1,3,7,9,1,3,7,9,1,3,1]; 1247 var sum=0; 1248 for (var i = 0; i < 11; i++){ 1249 sum += wagi[i] * aInt[i]; 1250 } 1251 1252 if((sum % 10) != 0){ 1253 this.error = 'NiewÅaÅciwy PESEL'; 1254 return; 1255 } 1256 1257 // Policzmy rok z uwzglÄdnieniem XIX, XXI, XXII i XXIII wieku 1258 this.rok = 1900 + aInt[0] *10 + aInt[1]; 1259 if(aInt[2] >= 2 && aInt[2] < 8){ 1260 this.rok += Math.floor(aInt[2]/2)*100; 1261 } 1262 if(aInt[2]>=8){ 1263 this.rok -= 100; 1264 } 1265 1266 this.miesiac = ('0' + ((aInt[2] % 2) * 10 + aInt[3])).slice(-2); // zapewnijmy wiodÄ ce zero 1267 this.dzien = ('0' + (aInt[4] * 10 + aInt[5])).slice(-2); 1268 1269 //Sprawdźmy poprawnoÅÄ daty urodzenia 1270 if(!checkDate(this.dzien,this.miesiac,this.rok)){ 1271 this.error = 'Niepoprawna data urodzenia!'; 1272 return; 1273 } 1274 this.plec = ((aInt[9] % 2) == 1)? "M" : "K"; 1275 1276 function checkDate(d,m,y){ 1277 var dt = new Date(+y, +m-1, +d); 1278 return dt.getDate() == d && 1279 dt.getMonth() == m-1 && 1280 dt.getFullYear() == y; 1281 } 1282} 1283 1284// Klasa do walidacji NIP. 1285// Po utworzeniu konstruktora możemy z obiektu wyciÄ gnÄ Ä: 1286// error: string z bÅÄdem lub null jak poprawny 1287function CNIP(nip){ 1288 this.error = null; 1289 nip += ''; 1290// nip = nip.replace(/[^0-9]+/g, ''); 1291 nip = nip.replace(/[-]+/g, ''); 1292 1293 if(nip.length != 10){ 1294 this.error = 'NIP musi zawieraÄ 10 cyfr'; 1295 return; 1296 } 1297 1298 var controlSum = 0; 1299 controlSum += parseInt(nip.charAt(0),10) * 6;
1300 controlSum += parseInt(nip.charAt(1),10) * 5; 1301 controlSum += parseInt(nip.charAt(2),10) * 7; 1302 controlSum += parseInt(nip.charAt(3),10) * 2; 1303 controlSum += parseInt(nip.charAt(4),10) * 3; 1304 controlSum += parseInt(nip.charAt(5),10) * 4; 1305 controlSum += parseInt(nip.charAt(6),10) * 5; 1306 controlSum += parseInt(nip.charAt(7),10) * 6; 1307 controlSum += parseInt(nip.charAt(8),10) * 7; 1308 1309 if((controlSum % 11) != parseInt(nip.charAt(9),10)) { 1310 this.error = 'BÅÄdny numer NIP'; 1311 return; 1312 } 1313} 1314 1315// ajaxem zwraca wartoÅÄ parametru param_name z admina 1316function getParam(param_name, def_val){ 1317 try { 1318 if(PARAMETRY_AUTOMATYCZNE[param_name]){ 1319 if(+PARAMETRY_AUTOMATYCZNE[param_name].poufny){ // param jest poufny, wiÄc go nie ma w pliku parametry.js 1320 return htmlDataSync('ajax_req.php?aaction=ajax_get_param', 'param_name='+param_name); // ciÄ gniemy z bazy 1321 } 1322 return PARAMETRY_AUTOMATYCZNE[param_name].val; 1323 } 1324 else { // nieznany parametr 1325 return def_val; 1326 } 1327 } 1328 catch(e){ 1329 // to chamski hack, ale to chyba najlepszy sposób na wyÅapanie nieistniejÄ cej zmiennej globalnej PARAMETRY_AUTOMATYCZNE 1330 } 1331 1332 return htmlDataSync('ajax_req.php?aaction=ajax_get_param', 'param_name='+param_name); 1333} 1334 1335// ajaxem zwraca wartoÅÄ parametru param_name z admina, ale uwaga: ASYNCHRONICZNIE 1336function getParam2(param_name, def_val, callback){ 1337 1338 try { 1339 if(PARAMETRY_AUTOMATYCZNE[param_name]){ 1340 if(+PARAMETRY_AUTOMATYCZNE[param_name].poufny){ // param jest poufny, wiÄc go nie ma w pliku parametry.js 1341 return htmlDataSync('ajax_req.php?aaction=ajax_get_param', 'param_name='+param_name); // ciÄ gniemy z bazy 1342 } 1343 return PARAMETRY_AUTOMATYCZNE[param_name].val; 1344 } 1345 else { // nieznany parametr 1346 return def_val; 1347 } 1348 } 1349 catch(e){ 1350 // to chamski hack, ale to chyba najlepszy sposób na wyÅapanie nieistniejÄ cej zmiennej globalnej PARAMETRY_AUTOMATYCZNE 1351 } 1352 1353 JSONAsyncRequest3('ajax_get_param', 'action=get_param¶m_name='+param_name).then(dane => { 1354 if(dane?.result == 'OK'){ 1355 if(callback){ 1356 callback(dane.param); 1357 } 1358 } 1359 else { 1360 console.error('Nie powiodÅo siÄ pobranie parametru \''+param_name+'\'. BÅÄ d: ' + dane?.message); 1361 if(callback){ 1362 callback(def_val); 1363 } 1364 } 1365 }); 1366} 1367 1368// zapewnia, że podany element (jako selektor jQuery) znajdzie siÄ poniżej górnej krawÄdzi i powyżej dolnej krawÄdzi okna przeglÄ darki 1369function checkDivVisibility(elem){ 1370 var docViewTop = $(window).scrollTop(); 1371 var docViewBottom = docViewTop + $(window).height(); 1372 1373 var elemTop = $(elem).offset().top; 1374 var elemBottom = elemTop + $(elem).height(); 1375 1376 if(elemTop < docViewTop){ // przesuÅmy go tak, żeby siÄ pojawiÅ pod dolnÄ krawÄdziÄ 1377 $(elem).css("top", docViewTop + 20); 1378 } 1379} 1380 1381// sprawdza, czy podany elemnt (jako selektor jQuery) przy aktualnym przewiniÄciu jest widoczny na ekranie 1382// \param top_only TRUE sprawia, że sprawdzamy tylko, czy górna krawÄdź elementu jest widoczna 1383function isScrolledIntoView(elem, top_only){ 1384 var docViewTop = $(window).scrollTop(); 1385 var docViewBottom = docViewTop + $(window).height(); 1386 1387 var elemTop = $(elem).offset().top; 1388 1389 if(top_only){ // sprawdzamy tylko widocznoÅÄ górnej krawÄdzi 1390 return ((elemTop < docViewBottom) && (elemTop >= docViewTop)); 1391 } 1392 else { // sprawdzamy, czy caÅy element jest widoczny 1393 var elemBottom = elemTop + $(elem).height(); 1394 return ((elemBottom < docViewBottom) && (elemTop >= docViewTop)); 1395 } 1396} 1397 1398// Helper funkcja wywoÅywana co period sekund żeby sesja nie wygasÅa 1399function refreshSession() { 1400 setTimeout(refreshSession, 2*60*1000); // co dwie minuty 1401 1402 // zapytanie o parametr jest tanie, a odÅwieża sesjÄ 1403 htmlData('ajax_req.php?aaction=ajax_get_param¶m_name=PLAY_REFRESH_SOUND',function(response){ 1404 if(response == '1' || response == 'true'){ 1405 var soundHandle = document.getElementById('audiotag1'); 1406 soundHandle.src = 'money.wav'; 1407 soundHandle.play(); 1408 } 1409 }); 1410} 1411 1412// uzupeÅnienie obiektu Date o możliwoÅÄ dodawania miesiÄcy 1413// Użycie: 1414//var myDate = new Date("01/31/2012"); 1415//var result1 = myDate.addMonths(1);
1416//var myDate2 = new Date("01/31/2011"); 1417//var result2 = myDate2.addMonths(1); 1418 1419Date.isLeapYear = function (year) { 1420 return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 1421}; 1422 1423Date.getDaysInMonth = function (year, month) { 1424 return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 1425}; 1426 1427Date.prototype.isLeapYear = function () { 1428 var y = this.getFullYear(); 1429 return (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0)); 1430}; 1431 1432Date.prototype.getDaysInMonth = function () { 1433 return Date.getDaysInMonth(this.getFullYear(), this.getMonth()); 1434}; 1435 1436Date.prototype.addMonths = function (value) { 1437 var n = this.getDate(); 1438 this.setDate(1); 1439 this.setMonth(this.getMonth() + value); 1440 this.setDate(Math.min(n, this.getDaysInMonth())); 1441 return this; 1442}; 1443 1444// converts string yyyy.mm.dd into Date object 1445dateFromString = function(date, separator) { 1446 separator = separator || '.'; 1447 var from = date.split(separator); 1448 return new Date(from[0], from[1] - 1, from[2]); 1449} 1450 1451// zamienia czas hh:mm[:ss] na dzisiejszy obiekt Date z podanym czasem 1452timeFromString = function(time, separator){ 1453 separator = separator || ':'; 1454 var spl = time.split(separator); 1455 1456 var d = new Date(); 1457 d.setHours(spl[0]); 1458 d.setMinutes(spl[1]); 1459 if(spl.length > 2){ 1460 d.setSeconds(spl[2]); 1461 } 1462 else { 1463 d.setSeconds(0); 1464 } 1465 return d; 1466} 1467 1468// Zwraca tekst z wygenerowanym elementem <select>. Element otrzyma podane id, wartoÅÄ i opcje (jako pary {val : txt}) 1469// Opcjonalnie można podaÄ wartoÅci dla atrybutów value, name, class oraz style 1470// JeÅli parametr process_fn jest funkcjÄ , to zostanie ona wywoÅana jako process_fn(i, opcje) dla każdego elementu obiektu opcje. 1471// Ta funkcja dla otrzymanego elementu powinna zwróciÄ obiekt {'txt' : <tekst do taga option>, 'val' : <value do taga option>}. 1472// JeÅli zwróci także atrybut 'sel' = 1, to dany element zostanie zaznaczony na liÅcie. 1473// Po wybraniu elementu wywoÅuje callback select_fn(item) (o ile istnieje). 1474genSelect = function(id, value, opcje, readonly, name, klasa, styl, process_fn, select_fn) 1475{ 1476 id = _html(id); 1477 value = _html(value); 1478 1479 var txt = '<select id="'+id; 1480 1481 if(value){ 1482 txt += '" value="'+value+'"'; 1483 } 1484 if(name){ 1485 txt += ' name="'+_html(name)+'"'; 1486 } 1487 if(klasa){ 1488 txt += ' class="'+_html(klasa)+'"'; 1489 } 1490 if(styl){ 1491 txt += ' style="'+_html(styl)+'"'; 1492 } 1493 if(readonly){ 1494 txt += ' disabled'; 1495 } 1496 if(select_fn){ 1497 // przygotujmy callbacka na wybór elementu z listy 1498 GENSELECT_CALLBACKS[id] = function(){ 1499 var val = $('select#'+id).val(); 1500 select_fn(opcje[val]); 1501 }; 1502 1503 txt += ' onchange="GENSELECT_CALLBACKS[\''+id+'\']()"'; 1504 } 1505 txt += '>'; 1506 1507 process_fn = process_fn || function(i,o){ 1508 return { 1509 txt : o[i], 1510 val : i 1511 }; 1512 } 1513 1514 for(var i in opcje){ 1515 var dat = process_fn(i, opcje); 1516 var val = _html(dat.val); 1517 var opis = _html(dat.txt); 1518 var sel = dat.sel; 1519 txt += '<option value="'+val+'" '+((i==value || sel)? 'selected' : '')+'>'+opis+'</option>'; 1520 } 1521 txt += '</select>'; 1522 1523 return txt; 1524} 1525 1526// Helper do wybierania elementów listy. 1527// Zwraca tablicÄ z ofiltrowanymi i posortowany elementami. 1528// Do filtrowania elementów używa callbacka filter_fn(idx, items). Ta funkcja powinna zwróciÄ obiekt {'o' : <element>, 'i' : <indeks>} przeznaczony do wstawienia do tablicy lub null w przypadku pominiÄcia elementu. 1529// Do sortowania wybranych elementów używa callbacka sort_fn(item_a, item_b). 1530function filterSortArray(items, filter_fn, sort_fn){ 1531 1532 filter_fn = filter_fn || function(idx, items){ 1533 return items[idx]; // defaultowo pokazuje wszystkie elementy z listy 1534 } 1535 1536 var arr = []; 1537 for(var i in items){ 1538 var filtered = filter_fn(i, items); 1539 if(filtered){ 1540 arr.push(filtered); 1541 } 1542 } 1543 1544 if(sort_fn){ 1545 arr.sort(sort_fn); 1546 } 1547 1548 return arr; 1549} 1550 1551 1552// odpowiednik funkcji PHP date(). Timestamp podawany jako obiekt Date lub Unixowy timestamp (doba ma 86400 sekund) 1553function php_date(format, timestamp) 1554{ 1555 var that = this; 1556 var jsdate, f; 1557 // Keep this here (works, but for code commented-out below for file size reasons) 1558 // var tal= []; 1559 var txt_words = [ 1560 'Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur', 1561 'January', 'February', 'March', 'April', 'May', 'June', 1562 'July', 'August', 'September', 'October', 'November', 'December' 1563 ]; 1564 // trailing backslash -> (dropped) 1565 // a backslash followed by any character (including backslash) -> the character 1566 // empty string -> empty string 1567 var formatChr = /\\?(.?)/gi; 1568 var formatChrCb = function (t, s) { 1569 return f[t] ? f[t]() : s; 1570 }; 1571 var _pad = function (n, c) { 1572 n = String(n); 1573 while (n.length < c) { 1574 n = '0' + n; 1575 } 1576 return n; 1577 }; 1578 f = { 1579 // Day 1580 d: function () { 1581 // Day of month w/leading 0; 01..31 1582 return _pad(f.j(), 2); 1583 }, 1584 D: function () { 1585 // Shorthand day name; Mon...Sun 1586 return f.l() 1587 .slice(0, 3); 1588 }, 1589 j: function () { 1590 // Day of month; 1..31 1591 return jsdate.getDate(); 1592 }, 1593 l: function () { 1594 // Full day name; Monday...Sunday 1595 return txt_words[f.w()] + 'day'; 1596 }, 1597 N: function () { 1598 // ISO-8601 day of week; 1[Mon]..7[Sun] 1599 return f.w() || 7; 1600 }, 1601 S: function () { 1602 // Ordinal suffix for day of month; st, nd, rd, th 1603 var j = f.j(); 1604 var i = j % 10; 1605 if (i <= 3 && parseInt((j % 100) / 10, 10) == 1) { 1606 i = 0; 1607 } 1608 return ['st', 'nd', 'rd'][i - 1] || 'th'; 1609 }, 1610 w: function () { 1611 // Day of week; 0[Sun]..6[Sat] 1612 return jsdate.getDay(); 1613 }, 1614 z: function () { 1615 // Day of year; 0..365 1616 var a = new Date(f.Y(), f.n() - 1, f.j()); 1617 var b = new Date(f.Y(), 0, 1); 1618 return Math.round((a - b) / 864e5); 1619 }, 1620 1621 // Week 1622 W: function () { 1623 // ISO-8601 week number 1624 var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3); 1625 var b = new Date(a.getFullYear(), 0, 4); 1626 return _pad(1 + Math.round((a - b) / 864e5 / 7), 2); 1627 }, 1628 1629 // Month 1630 F: function () { 1631 // Full month name; January...December 1632 return txt_words[6 + f.n()]; 1633 }, 1634 m: function () { 1635 // Month w/leading 0; 01...12 1636 return _pad(f.n(), 2); 1637 }, 1638 M: function () { 1639 // Shorthand month name; Jan...Dec 1640 return f.F() 1641 .slice(0, 3); 1642 }, 1643 n: function () { 1644 // Month; 1...12 1645 return jsdate.getMonth() + 1; 1646 }, 1647 t: function () { 1648 // Days in month; 28...31 1649 return (new Date(f.Y(), f.n(), 0)) 1650 .getDate(); 1651 }, 1652 1653 // Year 1654 L: function () { 1655 // Is leap year?; 0 or 1 1656 var j = f.Y(); 1657 return j % 4 === 0 & j % 100 !== 0 | j % 400 === 0; 1658 }, 1659 o: function () { 1660 // ISO-8601 year 1661 var n = f.n(); 1662 var W = f.W(); 1663 var Y = f.Y(); 1664 return Y + (n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? -1 : 0); 1665 }, 1666 Y: function () { 1667 // Full year; e.g. 1980...2010 1668 return jsdate.getFullYear(); 1669 }, 1670 y: function () { 1671 // Last two digits of year; 00...99 1672 return f.Y() 1673 .toString() 1674 .slice(-2); 1675 }, 1676 1677 // Time 1678 a: function () { 1679 // am or pm 1680 return jsdate.getHours() > 11 ? 'pm' : 'am'; 1681 }, 1682 A: function () { 1683 // AM or PM 1684 return f.a() 1685 .toUpperCase(); 1686 }, 1687 B: function () { 1688 // Swatch Internet time; 000..999 1689 var H = jsdate.getUTCHours() * 36e2; 1690 // Hours 1691 var i = jsdate.getUTCMinutes() * 60; 1692 // Minutes 1693 // Seconds 1694 var s = jsdate.getUTCSeconds(); 1695 return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3); 1696 }, 1697 g: function () { 1698 // 12-Hours; 1..12 1699 return f.G() % 12 || 12; 1700 }, 1701 G: function () { 1702 // 24-Hours; 0..23 1703 return jsdate.getHours(); 1704 }, 1705 h: function () { 1706 // 12-Hours w/leading 0; 01..12 1707 return _pad(f.g(), 2); 1708 }, 1709 H: function () { 1710 // 24-Hours w/leading 0; 00..23 1711 return _pad(f.G(), 2); 1712 }, 1713 i: function () { 1714 // Minutes w/leading 0; 00..59 1715 return _pad(jsdate.getMinutes(), 2); 1716 }, 1717 s: function () { 1718 // Seconds w/leading 0; 00..59 1719 return _pad(jsdate.getSeconds(), 2); 1720 }, 1721 u: function () { 1722 // Microseconds; 000000-999000 1723 return _pad(jsdate.getMilliseconds() * 1000, 6); 1724 }, 1725 1726 // Timezone 1727 e: function () { 1728 // Timezone identifier; e.g. Atlantic/Azores, ... 1729 // The following works, but requires inclusion of the very large 1730 // timezone_abbreviations_list() function. 1731 /* return that.date_default_timezone_get(); 1732 */ 1733 throw 'Not supported (see source code of date() for timezone on how to add support)'; 1734 }, 1735 I: function () { 1736 // DST observed?; 0 or 1 1737 // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC. 1738 // If they are not equal, then DST is observed. 1739 var a = new Date(f.Y(), 0); 1740 // Jan 1 1741 var c = Date.UTC(f.Y(), 0); 1742 // Jan 1 UTC 1743 var b = new Date(f.Y(), 6); 1744 // Jul 1 1745 // Jul 1 UTC 1746 var d = Date.UTC(f.Y(), 6); 1747 return ((a - c) !== (b - d)) ? 1 : 0; 1748 }, 1749 O: function () { 1750 // Difference to GMT in hour format; e.g. +0200 1751 var tzo = jsdate.getTimezoneOffset(); 1752 var a = Math.abs(tzo); 1753 return (tzo > 0 ? '-' : '+') + _pad(Math.floor(a / 60) * 100 + a % 60, 4); 1754 }, 1755 P: function () { 1756 // Difference to GMT w/colon; e.g. +02:00 1757 var O = f.O(); 1758 return (O.substr(0, 3) + ':' + O.substr(3, 2)); 1759 }, 1760 T: function () { 1761 // Timezone abbreviation; e.g. EST, MDT, ... 1762 // The following works, but requires inclusion of the very 1763 // large timezone_abbreviations_list() function. 1764 /* var abbr, i, os, _default; 1765 if (!tal.length) { 1766 tal = that.timezone_abbreviations_list(); 1767 } 1768 if (that.php_js && that.php_js.default_timezone) { 1769 _default = that.php_js.default_timezone; 1770 for (abbr in tal) { 1771 for (i = 0; i < tal[abbr].length; i++) { 1772 if (tal[abbr][i].timezone_id === _default) { 1773 return abbr.toUpperCase(); 1774 } 1775 } 1776 } 1777 } 1778 for (abbr in tal) { 1779 for (i = 0; i < tal[abbr].length; i++) { 1780 os = -jsdate.getTimezoneOffset() * 60; 1781 if (tal[abbr][i].offset === os) { 1782 return abbr.toUpperCase(); 1783 } 1784 } 1785 } 1786 */ 1787 return 'UTC'; 1788 }, 1789 Z: function () { 1790 // Timezone offset in seconds (-43200...50400) 1791 return -jsdate.getTimezoneOffset() * 60; 1792 }, 1793 1794 // Full Date/Time 1795 c: function () { 1796 // ISO-8601 date. 1797 return 'Y-m-d\\TH:i:sP'.replace(formatChr, formatChrCb); 1798 }, 1799 r: function () { 1800 // RFC 2822 1801 return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb); 1802 }, 1803 U: function () { 1804 // Seconds since UNIX epoch 1805 return jsdate / 1000 | 0; 1806 } 1807 }; 1808 this.date = function (format, timestamp) { 1809 that = this; 1810 jsdate = (timestamp === undefined ? new Date() : // Not provided 1811 (timestamp instanceof Date) ? new Date(timestamp) : // JS Date() 1812 new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int) 1813 ); 1814 return format.replace(formatChr, formatChrCb); 1815 }; 1816 return this.date(format, timestamp); 1817} 1818 1819 1820 1821/** 1822 * A class to parse color values 1823 * @author Stoyan Stefanov <[email protected]> 1824 * @link http://www.phpied.com/rgb-color-parser-in-javascript/ 1825 * @license Use it if you like it 1826 */ 1827 /* Example use: 1828var color = new RGBColor('darkblue'); 1829if (color.ok) { // 'ok' is true when the parsing was a success 1830 // alert channels 1831 alert(color.r + ', ' + color.g + ', ' + color.b); 1832 // alert HEX and RGB 1833 alert(color.toHex()); 1834 alert(color.toRGB()); 1835} 1836*/ 1837function RGBColor(color_string) 1838{ 1839 this.ok = false; 1840 1841 if(!color_string || color_string == ''){ 1842 color_string = 'black'; 1843 } 1844 1845 // strip any leading # 1846 if (color_string.charAt(0) == '#') { // remove # if any 1847 color_string = color_string.substr(1,6); 1848 } 1849 1850 color_string = color_string.replace(/ /g,''); 1851 color_string = color_string.toLowerCase(); 1852 1853 // before getting into regexps, try simple matches 1854 // and overwrite the input 1855 var simple_colors = {
1856 aliceblue: 'f0f8ff', 1857 antiquewhite: 'faebd7', 1858 aqua: '00ffff', 1859 aquamarine: '7fffd4', 1860 azure: 'f0ffff', 1861 beige: 'f5f5dc', 1862 bisque: 'ffe4c4', 1863 black: '000000', 1864 blanchedalmond: 'ffebcd', 1865 blue: '0000ff', 1866 blueviolet: '8a2be2', 1867 brown: 'a52a2a', 1868 burlywood: 'deb887', 1869 cadetblue: '5f9ea0', 1870 chartreuse: '7fff00', 1871 chocolate: 'd2691e', 1872 coral: 'ff7f50', 1873 cornflowerblue: '6495ed', 1874 cornsilk: 'fff8dc', 1875 crimson: 'dc143c', 1876 cyan: '00ffff', 1877 darkblue: '00008b', 1878 darkcyan: '008b8b', 1879 darkgoldenrod: 'b8860b', 1880 darkgray: 'a9a9a9', 1881 darkgreen: '006400', 1882 darkkhaki: 'bdb76b', 1883 darkmagenta: '8b008b', 1884 darkolivegreen: '556b2f', 1885 darkorange: 'ff8c00', 1886 darkorchid: '9932cc', 1887 darkred: '8b0000', 1888 darksalmon: 'e9967a', 1889 darkseagreen: '8fbc8f', 1890 darkslateblue: '483d8b', 1891 darkslategray: '2f4f4f', 1892 darkturquoise: '00ced1', 1893 darkviolet: '9400d3', 1894 deeppink: 'ff1493', 1895 deepskyblue: '00bfff', 1896 dimgray: '696969', 1897 dodgerblue: '1e90ff', 1898 feldspar: 'd19275', 1899 firebrick: 'b22222', 1900 floralwhite: 'fffaf0', 1901 forestgreen: '228b22', 1902 fuchsia: 'ff00ff', 1903 gainsboro: 'dcdcdc', 1904 ghostwhite: 'f8f8ff', 1905 gold: 'ffd700', 1906 goldenrod: 'daa520', 1907 gray: '808080', 1908 green: '008000', 1909 greenyellow: 'adff2f', 1910 honeydew: 'f0fff0', 1911 hotpink: 'ff69b4', 1912 indianred : 'cd5c5c', 1913 indigo : '4b0082', 1914 ivory: 'fffff0', 1915 khaki: 'f0e68c', 1916 lavender: 'e6e6fa', 1917 lavenderblush: 'fff0f5', 1918 lawngreen: '7cfc00', 1919 lemonchiffon: 'fffacd', 1920 lightblue: 'add8e6', 1921 lightcoral: 'f08080', 1922 lightcyan: 'e0ffff', 1923 lightgoldenrodyellow: 'fafad2', 1924 lightgrey: 'd3d3d3', 1925 lightgreen: '90ee90', 1926 lightpink: 'ffb6c1', 1927 lightsalmon: 'ffa07a', 1928 lightseagreen: '20b2aa', 1929 lightskyblue: '87cefa', 1930 lightslateblue: '8470ff', 1931 lightslategray: '778899', 1932 lightsteelblue: 'b0c4de', 1933 lightyellow: 'ffffe0', 1934 lime: '00ff00', 1935 limegreen: '32cd32', 1936 linen: 'faf0e6', 1937 magenta: 'ff00ff', 1938 maroon: '800000', 1939 mediumaquamarine: '66cdaa', 1940 mediumblue: '0000cd', 1941 mediumorchid: 'ba55d3', 1942 mediumpurple: '9370d8', 1943 mediumseagreen: '3cb371', 1944 mediumslateblue: '7b68ee', 1945 mediumspringgreen: '00fa9a', 1946 mediumturquoise: '48d1cc', 1947 mediumvioletred: 'c71585', 1948 midnightblue: '191970', 1949 mintcream: 'f5fffa', 1950 mistyrose: 'ffe4e1', 1951 moccasin: 'ffe4b5', 1952 navajowhite: 'ffdead', 1953 navy: '000080', 1954 oldlace: 'fdf5e6', 1955 olive: '808000', 1956 olivedrab: '6b8e23', 1957 orange: 'ffa500', 1958 orangered: 'ff4500', 1959 orchid: 'da70d6', 1960 palegoldenrod: 'eee8aa', 1961 palegreen: '98fb98', 1962 paleturquoise: 'afeeee', 1963 palevioletred: 'd87093', 1964 papayawhip: 'ffefd5', 1965 peachpuff: 'ffdab9', 1966 peru: 'cd853f', 1967 pink: 'ffc0cb', 1968 plum: 'dda0dd', 1969 powderblue: 'b0e0e6', 1970 purple: '800080', 1971 red: 'ff0000', 1972 rosybrown: 'bc8f8f', 1973 royalblue: '4169e1', 1974 saddlebrown: '8b4513', 1975 salmon: 'fa8072', 1976 sandybrown: 'f4a460', 1977 seagreen: '2e8b57', 1978 seashell: 'fff5ee', 1979 sienna: 'a0522d', 1980 silver: 'c0c0c0', 1981 skyblue: '87ceeb', 1982 slateblue: '6a5acd', 1983 slategray: '708090', 1984 snow: 'fffafa', 1985 springgreen: '00ff7f', 1986 steelblue: '4682b4', 1987 tan: 'd2b48c', 1988 teal: '008080', 1989 thistle: 'd8bfd8', 1990 tomato: 'ff6347', 1991 turquoise: '40e0d0', 1992 violet: 'ee82ee', 1993 violetred: 'd02090', 1994 wheat: 'f5deb3', 1995 white: 'ffffff', 1996 whitesmoke: 'f5f5f5', 1997 yellow: 'ffff00', 1998 yellowgreen: '9acd32' 1999 }; 2000 for (var key in simple_colors) { 2001 if (color_string == key) { 2002 color_string = simple_colors[key]; 2003 } 2004 } 2005 // emd of simple type-in colors 2006 2007 // array of color definition objects 2008 var color_defs = [ 2009 { 2010 re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, 2011 example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], 2012 process: function (bits){ 2013 return [ 2014 parseInt(bits[1],10), 2015 parseInt(bits[2],10), 2016 parseInt(bits[3],10) 2017 ]; 2018 } 2019 }, 2020 { 2021 re: /^(\w{2})(\w{2})(\w{2})$/, 2022 example: ['#00ff00', '336699'], 2023 process: function (bits){ 2024 return [ 2025 parseInt(bits[1], 16), 2026 parseInt(bits[2], 16), 2027 parseInt(bits[3], 16) 2028 ]; 2029 } 2030 }, 2031 { 2032 re: /^(\w{1})(\w{1})(\w{1})$/, 2033 example: ['#fb0', 'f0f'], 2034 process: function (bits){ 2035 return [ 2036 parseInt(bits[1] + bits[1], 16), 2037 parseInt(bits[2] + bits[2], 16), 2038 parseInt(bits[3] + bits[3], 16) 2039 ]; 2040 } 2041 } 2042 ]; 2043 2044 // search through the definitions to find a match 2045 for (var i = 0; i < color_defs.length; i++) { 2046 var re = color_defs[i].re; 2047 var processor = color_defs[i].process; 2048 var bits = re.exec(color_string); 2049 if (bits) { 2050 channels = processor(bits); 2051 this.r = channels[0]; 2052 this.g = channels[1]; 2053 this.b = channels[2]; 2054 this.ok = true; 2055 } 2056 } 2057 2058 // validate/cleanup values 2059 this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); 2060 this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); 2061 this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); 2062 2063 // some getters 2064 this.toRGB = function () { 2065 return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; 2066 } 2067 this.toHex = function (skip_hex) { 2068 var r = this.r.toString(16); 2069 var g = this.g.toString(16); 2070 var b = this.b.toString(16); 2071 if (r.length == 1) r = '0' + r; 2072 if (g.length == 1) g = '0' + g; 2073 if (b.length == 1) b = '0' + b; 2074 if(skip_hex){ 2075 return r + g + b; 2076 } 2077 else { 2078 return '#' + r + g + b; 2079 } 2080 } 2081 2082 // help 2083 this.getHelpXML = function () { 2084 2085 var examples = new Array(); 2086 // add regexps 2087 for (var i = 0; i < color_defs.length; i++) { 2088 var example = color_defs[i].example; 2089 for (var j = 0; j < example.length; j++) { 2090 examples[examples.length] = example[j]; 2091 } 2092 } 2093 // add type-in colors 2094 for (var sc in simple_colors) { 2095 examples[examples.length] = sc; 2096 } 2097 2098 var xml = document.createElement('ul'); 2099 xml.setAttribute('id', 'rgbcolor-examples'); 2100 for (var i = 0; i < examples.length; i++) {
2101 try { 2102 var list_item = document.createElement('li'); 2103 var list_color = new RGBColor(examples[i]); 2104 var example_div = document.createElement('div'); 2105 example_div.style.cssText = 2106 'margin: 3px; ' 2107 + 'border: 1px solid black; ' 2108 + 'background:' + list_color.toHex() + '; ' 2109 + 'color:' + list_color.toHex(); 2110 2111 example_div.appendChild(document.createTextNode('test')); 2112 var list_item_value = document.createTextNode(' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()); 2113 list_item.appendChild(example_div); 2114 list_item.appendChild(list_item_value); 2115 xml.appendChild(list_item); 2116 2117 } catch(e){} 2118 } 2119 return xml; 2120 2121 } 2122} 2123 2124function setCookie(cname, cvalue, exseconds, domain, path){ 2125 exseconds = exseconds || 86400; 2126 var d = new Date(); 2127 d.setTime(d.getTime()+(exseconds*1000)); 2128 var expires = ";expires="+d.toGMTString(); 2129 if(domain){ 2130 domain = ';domain='+domain; 2131 } 2132 else { 2133 domain = ''; 2134 } 2135 if(path){ 2136 path = ';path='+path; 2137 } 2138 else { 2139 path = ''; 2140 } 2141 var val = cname + "=" + cvalue + expires + domain + path; 2142 document.cookie = val; 2143} 2144 2145function getCookie(cname, default_val){ 2146 2147 if(typeof default_val === 'undefined'){ 2148 default_val = ''; 2149 } 2150 2151 var name = cname + "="; 2152 var ca = document.cookie.split(';'); 2153 for(var i = 0; i < ca.length; i++){ 2154 var c = ca[i].trim(); 2155 if(c.indexOf(name) == 0){ 2156 return c.substring(name.length, c.length); 2157 } 2158 } 2159 return default_val; 2160} 2161 2162function deleteCookie(name){ 2163 document.cookie = name+'=; Max-Age=-99999999;'; 2164} 2165 2166 2167// Pomocniczy obiekt używany do wizualnego przedstawiania wyników zapytania ajax-a 2168// Zależnie od rezultatu wyÅwietla DIV-a z odpowiednim komunikatem i potem go stopniowo faduje. 2169// Jak caÅkowicie zniknie, usuwa siÄ z pamiÄci 2170CResultFader3 = function(result, duration, type, x, y){ 2171 x = (+x) || 0; 2172 y = (+y) || 0; 2173 2174 var klasa = ' ok'; 2175 var color; 2176 2177 if(type == 'ok'){ 2178 klasa = ' ok'; 2179 } 2180 else if(type == 'warning'){ 2181 klasa = ' warning'; 2182 } 2183 else if(type == 'error'){ 2184 klasa = ' error'; 2185 } 2186 else { 2187 color = ' style="color:' + color + '"'; 2188 } 2189 2190 duration = duration || 1200; 2191 2192 2193 const $fader = $('<div class="result_fader2'+klasa+'"'+color+'>'+ result+'</div>'); 2194 2195 $('body').append($fader); 2196 2197 if(x || y){ 2198 $fader.css("top", x + "px"); 2199 $fader.css("left", y + "px"); 2200 } 2201 else { 2202 $fader.center2(); 2203 } 2204 2205 $fader.fadeOut(duration, function(){ 2206 $(this).remove(); 2207 }); 2208} 2209 2210// Pomocniczy obiekt używany do wyÅwietlania spinnera podczas oczekiwania na system 2211CWaitSpinner = function(){ 2212 this.id = 'wait_spinner_'+Math.floor(Math.random()*1e6); 2213 2214 var txt = '<div class="wait_spinner" id="'+this.id+'"></div>'; 2215 2216 $('body').append(txt); 2217 2218 $('#'+this.id+'.wait_spinner').center2(); 2219} 2220 2221CWaitSpinner.prototype.close = function(){ 2222 $('#'+this.id+'.wait_spinner').remove(); 2223} 2224 2225 2226 2227// serializuje pola podanego formularza (elementu DOM) do lini zapytania do umieszczenia w URL-u (w GET-cie lub w POST-cie) 2228function serializeForm(form) { 2229// var kvpairs = []; 2230 var uri = ''; 2231 var first = true; 2232 for ( var i = 0; i < form.elements.length; i++ ) { 2233 var e = form.elements[i]; 2234// if(!e.name || !e.value){ 2235 if(!e.name){ 2236 continue; // Shortcut, may not be suitable for values = 0 (considered as false) 2237 } 2238 2239 switch (e.type){ 2240 case 'text': 2241 case 'textarea': 2242 case 'password': 2243 case 'hidden': 2244 case 'select-one': 2245// kvpairs.push(encodeURIComponent(e.name) + "=" + encodeURIComponent(e.value)); 2246 if(first){ 2247 first = false; 2248 } 2249 else { 2250 uri += '&'; 2251 } 2252 2253 uri += encodeURIComponent(e.name) + "=" + encodeURIComponent(e.value); 2254 break; 2255 case 'radio': 2256 case 'checkbox': 2257 if (e.checked){ 2258 if(first){ 2259 first = false; 2260 } 2261 else { 2262 uri += '&'; 2263 } 2264 2265// kvpairs.push(encodeURIComponent(e.name) + "=" + encodeURIComponent(e.value)); 2266 uri += encodeURIComponent(e.name) + "=" + encodeURIComponent(e.value); 2267 } 2268 break; 2269 /* To be implemented if needed: 2270 case 'select-one': 2271 ... document.forms[x].elements[y].options[0].selected ... 2272 break; 2273 case 'select-multiple': 2274 for (z = 0; z < document.forms[x].elements[y].options.length; z++) { 2275 ... document.forms[x].elements[y].options[z].selected ... 2276 } */ 2277 break; 2278 } 2279 } 2280 return uri;
2281// return kvpairs; 2282} 2283 2284// helper do wstawiania w HTML przycisku do rozwijania/zwijania wskazanego div-a. 2285// \param el_id Selektor elementu do rozwiniÄcia/zwiniÄcia [w formacie selektora jQuery] 2286// \param collapsed Flaga, czy element jest poczÄ tkowo zwiniÄty 2287// \param options Ewentualne opcje zwijania/rozwijania 2288function expandBtn(el_id, collapsed, options){ 2289 2290 function calcHeight(el_id){ 2291 var height = 0; 2292 var top = 0; 2293 var bottom = 0; 2294 $(el_id+' > *').each(function(){ 2295 var pos = $(this).offset(); 2296 pos.bottom = pos.top + $(this).height(); 2297 2298 if(!top || pos.top < top){ 2299 top = pos.top; 2300 } 2301 if(!bottom || pos.bottom > bottom){ 2302 bottom = pos.bottom; 2303 } 2304 }) 2305 height = Math.abs(top-bottom+1); 2306 return height + options.margin; 2307 } 2308 2309 options = options || {}; 2310 options.height = options.height || -1; // mniejsze lub równe zeru oznacza, że wysokoÅÄ zostanie obliczona automatycznie. JeÅli to jest funkcja, to po wywoÅaniu powinna zwróciÄ wysokoÅÄ. WartoÅÄ numeryczna oznacza ustawionÄ na sztywno wysokoÅÄ w pikselach 2311 options.callback = options.callback || function(){}; // wywoÅywane po zwiniÄciu i rozwiniÄciu 2312 options.margin = options.margin || 0; // domyÅlny dolny margines 2313 options.clas = options.clas || ''; // klasa w tworzonym divie lub atrybutach 2314 options.min_height = options.min_height || 0; // wysokoÅÄ zwiniÄtego diva 2315 options.payload = options.payload || 0; // przekazywane do callbacka zwijania/rozwijania 2316 options.from_class = options.from_class || 0; // gdy true, stan przycisku jest brany z aktualnej klasy div-a 2317 2318 var id = options.id || 'exp_btn'+Math.floor(Math.random()*1000000); 2319 2320 if(typeof(options.height) != 'function'){ 2321 if(+options.height >= 0){ // wartoÅÄ ustawiona na sztywno [w pikselach] 2322 var height = options.height; 2323 options.height = function(el_id){return height;} 2324 } 2325 else { // za każdym razem przy rozwijaniu spróbujemy obliczyÄ docelowÄ wysokoÅÄ div-a 2326 options.height = calcHeight; 2327 } 2328 } 2329 2330/* 2331 if(EXPAND_BUTTONS[el_id]){ 2332 console.log('Powtórzony identyfikator w funkcji expandBtn(): '+el_id); 2333 } 2334*/ 2335 2336 if(options.from_class){ 2337 collapsed = $(el_id).hasClass('collapsed'); 2338 } 2339 2340 var txt; 2341 if(options.attrs_only){ // nie generujemy diva a jedynie wymagane atrybuty 2342 txt = ' id="'+id+'" class="'+(collapsed? 'EB_collapsed' : 'EB_expanded')+' '+options.clas+'" onclick="expandBtn_callback(\''+el_id+'\')" '; 2343 } 2344 else { // geenrujemy caÅego diva przycisku do zwijania/rozwijania 2345 txt = '<div id="'+id+'" class="'+(collapsed? 'EB_collapsed' : 'EB_expanded')+' '+options.clas+'" onclick="expandBtn_callback(\''+el_id+'\')"></div>'; 2346 } 2347 2348 EXPAND_BUTTONS[el_id] = { 2349 id : id, 2350 options : options, 2351 collapsed : collapsed 2352 } 2353/* 2354 // i jeszcze ustawmy odpowiedniÄ klasÄ dla kontenera 2355 if(collapsed){ 2356 $(el_id).removeClass('expanded').addClass('collapsed'); 2357 } 2358 else { 2359 $(el_id).removeClass('collapsed').addClass('expanded'); 2360 } 2361*/ 2362 return txt; 2363} 2364 2365// aktualizuje wysokoÅÄ elementu do nowej wysokoÅci (jeÅli jest obliczana automatycznie) 2366function expandBtnUpdate(el_id){ 2367 expandBtn_callback(el_id, true); 2368} 2369 2370 2371// callback z funkcji expandBtn() 2372function expandBtn_callback(el_id, force_expand){ 2373 var btn = EXPAND_BUTTONS[el_id]; 2374 var id = '#'+btn.id; 2375 if(btn.collapsed || force_expand){ // rozwijamy 2376 var height = btn.options.height(el_id); 2377 $(el_id).animate({height : height }, 300, null, function(){btn.options.callback(btn.options.payload, true)}); 2378 $(el_id).removeClass('collapsed'); 2379 $(id).removeClass('EB_collapsed').addClass('EB_expanded'); 2380 btn.collapsed = false; 2381 } 2382 else { 2383// btn.options.height = $(el_id).height(); // zapamiÄtajmy aktualnÄ wysokoÅÄ div-a 2384 $(el_id).animate({height : btn.options.min_height }, 300, null, function(){btn.options.callback(btn.options.payload, false)}); 2385 $(el_id).addClass('collapsed'); 2386 $(id).removeClass('EB_expanded').addClass('EB_collapsed'); 2387 btn.collapsed = true; 2388 } 2389 2390 2391} 2392 2393// zamienia liczbÄ na rzymskÄ 2394function romanize(num){ 2395 if(!+num){ 2396 return 0; 2397 } 2398 var digits = String(+num).split(""),
2399 key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM", 2400 "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC", 2401 "","I","II","III","IV","V","VI","VII","VIII","IX"], 2402 roman = "", 2403 i = 3; 2404 while (i--){ 2405 roman = (key[+digits.pop() + (i * 10)] || "") + roman; 2406 } 2407 return Array(+digits.join("") + 1).join("M") + roman; 2408} 2409 2410var NUMERY_KIERUNKOWE = [12,13,14,15,16,17,18,22,23,24, 2411 25,29,32,33,34,41,42,43,44,46, 2412 48,52,54,55,56,58,59,61,62,63, 2413 65,67,68,71,74,75,76,77,81,82, 2414 83,84,85,86,87,89,91,94,95]; 2415 2416// helper do sprawdzania, czy mamy do czynienia z poprawnym numerem komórkowym 2417// JeÅli numer jest niepopawny, zwraca false 2418// JeÅli numer jest stacjonarny, zwraca 0 2419function validateMobilePhone(tel){ 2420 tel = tel.replace(/[^0-9]/g,''); // pozbÄ dźmy siÄ znaków innych niż cyfry 2421 2422 tel = tel.substr(-9); 2423 2424 var res = tel.match(/^\d\d\d\d\d\d\d\d\d$/); // dokÅadnie 9 cyfr 2425 2426 if(!res){ 2427 return false; // bÅÄdny numer 2428 } 2429 else { 2430 if(NUMERY_KIERUNKOWE.indexOf(+tel.substring(0,2)) >= 0){ 2431 return 0; // to jest numer stacjonarny 2432 } 2433 } 2434 2435 return tel; 2436} 2437 2438function displayPhone(tel){ // helper do Åadnego wyÅwietlania numeru 2439 tel = tel.replace(/^00/,'+'); // zamieÅmy poczÄ tkowe 00 na + 2440 tel = tel.replace(/[^0-9+]/g,''); // pozbÄ dźmy siÄ znaków innych niż cyfry i plus 2441 2442 if(tel.length == 11 && tel.substring(0,2) == '48'){ // tel. kom. lub stacjonarny z kodem kraju ale bez wiodÄ cego + 2443 tel = '+' + tel; 2444 } 2445 2446 if(tel.length == 12 && tel.substring(1,3) == '48'){ // dla polskich numerów sprawdźmy, czy to numer stacjonarny 2447 2448 if(NUMERY_KIERUNKOWE.indexOf(+tel.substring(3,5)) >= 0){ 2449 // mamy numer stacjonarny 2450 tel = '+48 ' + tel.substring(3,5) + ' ' + tel.substring(5,8) + ' ' + tel.substring(8,10) + ' ' + tel.substring(10,12); 2451 } 2452 else { // komórkowy albo specjalny 2453 tel = '+48 ' + tel.substring(3,6) + ' ' + tel.substring(6,9) + ' ' + tel.substring(9,12); 2454 } 2455 } 2456 else if(tel.length == 9){ // tel komórkowy lub stacjonarny bez kodu kraju 2457 if(NUMERY_KIERUNKOWE.indexOf(+tel.substring(0,2)) >= 0){ 2458 // mamy numer stacjonarny 2459 tel = tel.substring(0,2) + ' ' + tel.substring(2,5) + ' ' + tel.substring(5,7) + ' ' + tel.substring(7,9); 2460 } 2461 else { // komórkowy albo specjalny 2462 tel = tel.substring(0,3) + ' ' + tel.substring(3,6) + ' ' + tel.substring(6,9); 2463 } 2464 } 2465 // w przypadku innych numerów zwracamy je jak leci 2466 return tel; 2467} 2468 2469 2470 2471function generic_compare(sa, sb, ia, ib, numeric){ 2472 if(numeric){ 2473 if(+sa == +sb){ 2474 return ia - ib; 2475 } 2476 return (+sb) - (+sa); 2477 } 2478 else { 2479 try { 2480 var n = sa.localeCompare(sb); 2481 } 2482 catch(e){ 2483 var n = 0; 2484 } 2485 if(!n){ 2486 return ia - ib; 2487 } 2488 return -n; 2489 } 2490} 2491 2492function generic_compare_desc(sa,sb,ia,ib, numeric){ 2493 if(numeric){ 2494 if(+sa == +sb){ 2495 return ia - ib; 2496 } 2497 return (+sa) - (+sb); 2498 } 2499 else { 2500 try { 2501 var n = sa.localeCompare(sb); 2502 } 2503 catch(e){ 2504 var n = 0; 2505 } 2506 if(!n){ 2507 return ia - ib; 2508 } 2509 return n; 2510 } 2511} 2512 2513function LOC(param, par1, par2, par3){ 2514 2515 if(param == 'ID'){ 2516 var a = 1; 2517 } 2518 2519 try { 2520// var string = txt_translations[param]; 2521 var string = param; // w tym przypadku nie ma lokalizacji, zatem przekazujemy string 1:1 2522 2523 if(typeof string === 'undefined') { 2524 string = 'Brak tÅumaczenia JS ('+lang+') dla \'<span style="color:red">' + param + '\'</span>'; 2525 } 2526 2527 if(typeof par1 !== 'undefined'){ 2528 string = string.replace(/<<param1>>/g, par1); 2529 } 2530 if(typeof par2 !== 'undefined'){ 2531 string = string.replace(/<<param2>>/g, par2); 2532 } 2533 if(typeof par3 !== 'undefined'){ 2534 string = string.replace(/<<param3>>/g, par3); 2535 } 2536 2537 return string; 2538 } 2539 catch(e){ 2540 return '<span style="color:red">BRAK PLIKÃW LOKALIZACJI</span>'; 2541 } 2542} 2543 2544function LOCX(param, par1, par2, par3){ // ta wersja funkcji LOC powinna byÄ używana dla tyc
2544h lokalizacji, które nie majÄ automatycznie trafiaÄ do bazy 2545 return LOC(param, par1, par2, par3); 2546} 2547 2548// przygotowuje HTML kontrolki tÅumaczÄ cej 2549// \param from Selektor css kontrolki zawierajÄ cej tekst źródÅowy (input lub textarea) 2550// \param to Selektor css kontrolki docelowej (input lub textarea) 2551// \param lang_to Dwuznakowe ID jÄzyka docelowego (np. en, ru, sk itd.) 2552// \param lang_from JeÅli jest, to zawiera dwuznakowe ID jÄzyka źródÅowego. Jak nie zostanie podane, to jÄzyk źródÅowy jest brany 2553// z lang_base z conf-a. Trzeba zdefiniowaÄ w javascripcie w jakimÅ headerze najlepiej. 2554function GTRANS(from, to, lang_to, lang_from, callback){ 2555 2556 lang_from = lang_from || (window.lang_base? window.lang_base : 'pl'); // defaultowo tÅumaczymy z lang_base (a jak nie ma, to z pl) 2557 2558 callback = callback? callback : ''; 2559 2560 return '<div class="google_translate_ctrl" from="'+from+'" to="'+to+'" lang_from="'+lang_from+'" lang_to="'+lang_to+'" onclick="$(this).GoogleTranslate('+callback+')" title="Automatyczne tÅumaczenie Google Translate z '+lang_from+' na '+lang_to+'></div>'; 2561} 2562 2563//var dymki_first_time = true; 2564 2565// helper do wypisywania ikonki z dymkiem. 2566// \param id ID parametru dymka (zawsze w grupie DYMKI) 2567// \param lewy Dymek zostanie wyÅwietlony z lewej strony 2568function dymek(id, lewy, div_id, head = '', light = false){ 2569/* 2570 if(dymki_first_time && typeof(DYMKI) == 'undefined'){ 2571 dymki_first_time = false; 2572 alert('Zdefiniuj DYMKI!'); 2573 2574 return; 2575 } 2576 2577 var dymek = DYMKI[id]? (DYMKI[id].wartosc) : 'Nie ustawiono parametru <b>'+_html(id)+'</b><br />w grupie <b>DYMKI</b>'; 2578*/ 2579 2580 if(typeof JSLOC == "object"){ // byÄ może LOC jest zdefiniowane lokalnie w plikach JS 2581 var dymek = JSLOC[id]; 2582 } 2583 else if(typeof LOC == 'function'){ 2584 var dymek = LOC(id); 2585 } 2586 2587 return dymek2(dymek, lewy, div_id, head, light); 2588} 2589 2590// helper do wypisywania ikonki z dymkiem. 2591// \param dymek treÅÄ dymka 2592// \param lewy Dymek zostanie wyÅwietlony z lewej strony 2593function dymek2(dymek, lewy, div_id, head = '', light = false){ 2594 var txt = ` 2595<div class="dymek_cont"> 2596 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="${light? 'light' : ''}"> 2597 <path fill-rule="evenodd" 2598 d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" 2599 clip-rule="evenodd" /> 2600 </svg> 2601 2602 <div class="dymek_inner${lewy? ' lewy' : ''}"> 2603 <div class="dymek_inner_txt"${div_id? ' id="'+div_id+'"' : ''}>${head? `<div class="dymek_head">${head}</div>${dymek}` : dymek}</div> 2604 </div> 2605</div>`.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); 2606 return txt; 2607} 2608 2609 2610// Na podstawie otrzymanej tablicy menu itemów generuje i zwraca html z menu 2611function generateMenu(items, demo){ 2612 2613 items = items || {}; 2614 2615 var txt = ''; 2616 var cnt = 0; 2617 2618 // zbudujmy strukturÄ drzewka menu, którÄ potem przeparsujemy tworzÄ c div-y na ekranie 2619 var menu_items = {}; 2620 2621 for(var mniid in items){ 2622 var it = items[mniid]; 2623 2624 menu_items[mniid] = menu_items[mniid] || { 2625 items : {} 2626 }; 2627 menu_items[mniid].it = it; 2628 2629 var parent = it.parent; 2630 if(!menu_items[parent]){ 2631 menu_items[parent] = { 2632 items : {} 2633 }; 2634 } 2635 menu_items[parent].items[mniid] = menu_items[parent].items[mniid] || { 2636 items : {} 2637 }; 2638 menu_items[parent].items[mniid].it = it; 2639 } 2640 2641 function createMenu(mniid, depth, active, position){ 2642 var txt = ''; 2643 position = position || 1; 2644 2645 var mi = menu_items[mniid]; 2646 var aktywne = (mi.it.status == 'aktywny'); 2647 2648 if(+mniid == 0){ // dla roota nie generujemy nic poza rekurencyjnie wywoÅywanymi menu itemami gÅównego poziomu 2649 // posortujmy itemy zgodnie z priorytetem 2650 var arr = []; 2651 for(var sub_mniid in mi.items){ 2652 arr.push(mi.items[sub_mniid]); 2653 } 2654 arr.sort(function(a, b){ 2655 return +b.it.priorytet - +a.it.priorytet; 2656 }); 2657 for(var i = 0; i < arr.length; i++){ 2658 var sub_mniid = arr[i].it.mniid; 2659 txt += createMenu(sub_mniid, depth+1, aktywne); 2660 } 2661 return txt; 2662 } 2663 2664 if(!aktywne){ 2665 return ''; // pomijamy nieaktywne pozycje menu 2666 } 2667 2668 var items_no = getArraySize(mi.items); 2669 if(!items_no){ 2670 if(depth > 1){ 2671 txt += '<li>'; 2672 var cls = (position == 1? 'first' : ''); 2673 cls += (position > 1? ' next' : ''); 2674 cls += (position == items_no? ' last' : ''); 2675 2676 if(mi.it.link != ''){ 2677 txt += '<a '+(demo? 'target="_blank"' : '')+' class="" data-position="'+position+'" href="'+_html(mi.it.link)+'"><div class="'+cls+'" >'+_html(mi.it.tytul)+'</div></a>'; 2678 } 2679 else { 2680 txt += '<a '+(demo? 'target="_blank"' : '')+' class="" data-position="'+position+'" href="javascript:void(0)"><div class="'+cls+'" >'+_html(mi.it.tytul)+'</div></a>'; 2681 } 2682 txt += '</li>'; 2683 } 2684 else { 2685 txt += '<li class="position'+position+'">'; 2686 if(mi.it.link != ''){ 2687 txt += '<a '+(demo? 'target="_blank"' : '')+' href="'+_html(mi.it.link)+'" style="cursor:pointer;">'; 2688 } 2689 else { 2690 txt += '<a '+(demo? 'target="_blank"' : '')+' href="javascript:void(0)" style="cursor:pointer;">'; 2691 } 2692 txt += '<div>'; 2693 txt += '<span class="menu-mid">'+_html(mi.it.tytul)+'</span>'; 2694 txt += '</div>'; 2695 txt += '</a>'; 2696 txt += '</li>'; 2697 } 2698 } 2699 else { 2700 txt += '<li class="has-dropdown position'+position+'">'; 2701 txt += '<a '+(demo? 'target="_blank"' : '')+' style="cursor:default;">'; 2702 txt += '<div>'; 2703 txt += '<span class="menu-mid" >'+_html(mi.it.tytul)+'</span>'; 2704 txt += '</div>'; 2705 txt += '</a>'; 2706 txt += '<ul class="dropdown">'; 2707 // posortujmy itemy zgodnie z priorytetem 2708 var arr = []; 2709 for(var sub_mniid in mi.items){ 2710 arr.push(mi.items[sub_mniid]); 2711 } 2712 arr.sort(function(a, b){ 2713 return +b.it.priorytet - +a.it.priorytet; 2714 }); 2715 var pos = 1; 2716 for(var i = 0; i < arr.length; i++){ 2717 if(arr[i].it.status == 'aktywny'){ 2718 var sub_mniid = arr[i].it.mniid; 2719 txt += createMenu(sub_mniid, depth+1, aktywne, pos++); 2720 } 2721 } 2722 txt += '</ul>'; 2723 txt += '</li>'; 2724 } 2725 2726 return txt; 2727 } 2728 2729 2730 txt += '<div class="toggleMenuDiv">'; // przycisk do zwijania menu dla responsywnego 2731 txt += '<a class="toggleMenu" href="#">Menu</a>'; 2732 txt += '<div style="clear:both"></div>'; 2733 txt += '</div>'; 2734 2735 txt += '<ul class="nav">'; 2736 txt += createMenu(0, 0, 1, 1); // a teraz rekurencyjnie stwórzmy hierarchiÄ divów dla poszczególnych itemów 2737 txt += '</ul>'; 2738 2739 return txt; 2740} 2741 2742formatFileSize = function(bytes){ 2743 bytes = +bytes || 0; 2744 2745 if(bytes >= 1000000000){ 2746 return (bytes / 1000000000).toFixed(2) + ' GB'; 2747 } 2748 if(bytes >= 1000000){ 2749 return (bytes / 1000000).toFixed(2) + ' MB'; 2750 } 2751 return (bytes / 1000).toFixed(2) + ' KB'; 2752} 2753 2754// zwraca obiekt, w którym pola obiektu dst sÄ zaktualizowane polami obiektu src. Dodatkowe pola obiektu src sÄ także dopisywane do wyniku 2755merge_objects = function(dst, src){ 2756 return $.extend({}, dst, src); 2757} 2758 2759function saveTextAsFileDownload(text, filename, mime) 2760{ 2761 if(!text){ 2762 return; 2763 } 2764 2765 filename = filename || 'plik.txt'; 2766 mime = mime || 'text/plain'; 2767 2768 var textFileAsBlob = new Blob([text], {type: mime}); 2769 var downloadLink = document.createElement("a"); 2770 downloadLink.download = filename; 2771 downloadLink.innerHTML = "Download File"; 2772 2773 downloadLink.href = window.URL.createObjectURL(textFileAsBlob); 2774 downloadLink.style.display = "none"; 2775 document.body.appendChild(downloadLink); 2776 downloadLink.click(); 2777 document.body.removeChild(downloadLink); 2778} 2779 2780 2781// konwertuje php.ini values (8K, 4G itd) na liczby 2782function return_bytes(val){ 2783 2784 val = val.trim(); 2785 var last = val[val.length-1].toLowerCase(); 2786 val = parseInt(val,10); 2787 2788 switch(last) { 2789 // The 'G' modifier is available since PHP 5.1.0 2790 case 'g': 2791 val *= 1024; 2792 case 'm': 2793 val *= 1024; 2794 case 'k': 2795 val *= 1024; 2796 } 2797 2798 return val; 2799} 2800 2801function page_handler_example(type, page, of_pages, current_page){ 2802 2803 page = +page || 0; 2804 of_pages = +of_pages || 0; 2805 current_page = +current_page || 0; 2806 2807 var curr = (page == current_page)? ' current' : ''; 2808 2809 var spacer = '<div class="spacer"></div>'; 2810 var spacer_div = spacer + '</div>'; 2811 2812 if(type == '...'){ 2813 return '<div class="page ellipsis">...' + spacer_div; 2814 } 2815 else if(type == '|<'){ 2816 return '<div class="page first' + curr + '" page="' + page + '">|<<' + spacer_div; 2817 } 2818 else if(type == '<'){ 2819 return '<div class="page prev' + curr + '" page="' + page + '"><<' + spacer_div; 2820 } 2821 else if(type == '>'){ 2822 return '<div class="page next' + curr + '" page="' + page + '">>>' + spacer_div; 2823 } 2824 else if(type == '>'){ 2825 return '<div class="page next' + curr + '" page="' + page + '">>>' + spacer_div; 2826 } 2827 else if(type == '>|'){ 2828 return '<div class="page last' + curr + '" page="' + page + '">>>|</div>'; 2829 } 2830 2831 // dla zwykÅych stron (type == '#') 2832 return '<div class="page nr' + curr + '" page="' + page + '">' + (page+1) + spacer_div; 2833} 2834 2835 2836// helper do tworzenia pagera 2837// \param page_handler Opcjonalna funkcja do tworzenia linka, wywoÅywana jako page_handler(type, page, of_pages, current_page). page i curent_page liczony od 0 2838// Parametr type: '#' oznacza numer strony 2839// '...' oznacza przerwÄ w numeracji 2840// '|<' oznacza powrót na poczÄ tek 2841// '<' oznacza przejÅcie do poprzedniej strony 2842// '>' oznacza przejÅcie do nastÄpnej strony 2843// '>|' oznacza przejÅcie do ostatniej strony 2844function pager(items_no, page, options, page_handler){ 2845 2846 this.items_no = +items_no || 0; 2847 2848 if(!this.items_no){ 2849 return ''; // nie ma sensu dawaÄ pagera przy braku stron 2850 } 2851 2852 options = options || {}; 2853 2854 if(!options.per_page){ 2855 console.log('W opcjach pagera należy podaÄ iloÅÄ itemów na stronÄ. PrzyjÄto domyÅlnÄ wartoÅÄ 20 itemów na stronÄ.'); 2856 options.per_page = 20; 2857 } 2858 2859 this.page = +page || 0; 2860 this.o = options; 2861 this.o.per_page = +options.per_page; 2862 this.o.max_before = +options.max_before || 3;
2862 // domyÅlnie 3 przed bieÅ¼Ä cÄ i 3 po bieÅ¼Ä cej 2863 this.o.max_after = +options.max_after || 3; // domyÅlnie 3 przed bieÅ¼Ä cÄ i 3 po bieÅ¼Ä cej 2864 this.o.show_first = options.show_first || true; // czy pokazywaÄ powrót do poczÄ tku 2865 this.o.show_last = options.show_last || true; // czy pokazywaÄ przejÅcie na koniec 2866 this.o.show_prev = options.show_prev || true; // czy pokazywaÄ przejÅcie o jednÄ wstecz 2867 this.o.show_next = options.show_next || true; // czy pokazywaÄ przejÅcie o jednÄ do przodu 2868 this.o.show_with_one_page = options.show_with_one_page || false; // czy pokazywaÄ pager w przypadku jednej strony 2869 this.o.show_select = options.show_select || false; // czy pokazywaÄ selecta ze stronami do wybowu 2870 this.page_handler = page_handler || page_handler_example; 2871 2872 this.pages_no = Math.floor(this.items_no / this.o.per_page) + ((this.items_no % this.o.per_page)? 1 : 0); 2873 2874 if(this.pages_no < 2 && !this.o.show_with_one_page){ 2875 return ''; // nie pokazujemy pagera dla jednej strony 2876 } 2877 2878 var txt = ''; 2879 if(this.pages_no > 2 && this.page > 0){ // first 2880 if(this.o.show_first){ 2881 txt += this.page_handler('|<', 0, this.pages_no, this.page); 2882 } 2883 } 2884 2885 if(this.o.show_prev && this.page > 0){ // prev 2886 txt += this.page_handler('<', this.page-1, this.pages_no, this.page); 2887 } 2888 2889 if(this.page-this.o.max_before > 0){ // poczÄ tkowa przerwa w numeracji 2890 txt += this.page_handler('...', 0, this.pages_no, this.page); 2891 } 2892 2893 for(var p = this.page-this.o.max_before; p < this.page; ++p){ // strony przed bieÅ¼Ä cÄ 2894 if(p >= 0){ 2895 txt += this.page_handler('#', p, this.pages_no, this.page); 2896 } 2897 } 2898 2899 txt += this.page_handler('#', this.page, this.pages_no, this.page); 2900 2901 for(var p = this.page+1; p <= this.page+this.o.max_after; ++p){ // strony po bieÅ¼Ä cej 2902 if(p < this.pages_no){ 2903 txt += this.page_handler('#', p, this.pages_no, this.page); 2904 } 2905 } 2906 2907 if(this.page+this.o.max_before < this.pages_no-1){ // koÅcowa przerwa w numeracji 2908 txt += this.page_handler('...', 0, this.pages_no, this.page); 2909 } 2910 2911 if(this.o.show_next && this.page < this.pages_no-1){ // next 2912 txt += this.page_handler('>', this.page+1, this.pages_no, this.page); 2913 } 2914 2915 if(this.pages_no > 2 && this.page < this.pages_no-1){ // last 2916 if(this.o.show_last){ 2917 txt += this.page_handler('>|', this.pages_no-1, this.pages_no, this.page); 2918 } 2919 } 2920 2921 if(this.pages_no > 2 && this.o.show_select){ 2922 txt += '<select>'; 2923 txt += '<option value="-1">---</option>'; 2924 for(var p = 0; p < this.pages_no; ++p){ 2925 txt += '<option value="' + p + '">' + (p+1) + '</option>'; 2926// txt += this.page_handler('#', p, this.pages_no, this.page); 2927 } 2928 txt += '</select>'; 2929 } 2930 2931 return txt; 2932} 2933 2934 2935 2936 2937 2938 2939// Widget do pobierania odpowiedzi tak/nie. Wyrażenie await Confirm(...) zwraca true lub false zależnie od tego, czy klinkniÄto na tak, czy na nie 2940// \param o Obiekt z opcjami; dostÄpne opcje to: 2941// dlg_class = '' Dodatkowa klasa okienka dialogu 2942// dlg_style = '' Dodatkowe style okienka dialogu 2943// z_index = null JeÅli jest ustawiony, wymusza z-index dla dialogu [int] 2944// txt_yes = ' TAK ' Tekst na przycisku YES 2945// txt_no = ' NIE ' Tekst na przycisku NO 2946// no_outside_click = false TRUE powoduje, że nie reaguje na klikniÄcie poza dialogiem 2947// single_btn = false TRUE powoduje, że nie ma przycicisku NIE 2948Confirm = function(title, alert, o){ 2949 2950 return new Promise((resolve, reject) => { 2951 2952 title = title || null; 2953 alert = alert || null; 2954 o = o || {}; 2955 o.dlg_class = o.dlg_class || ''; 2956 o.dlg_style = o.dlg_style || ''; 2957 o.z_index = +o.z_index || null; 2958 o.txt_yes = o.txt_yes || ((typeof callback_no == 'function')? ' TAK ' : ' OK '); 2959 o.txt_no = o.txt_no || ' NIE '; 2960 o.no_outside_click = o.no_outside_click || false; 2961 o.single_btn = o.single_btn || false; 2962 2963 var id = 'confirmdlg_' + Math.floor(Math.random()*1e6); 2964 2965 2966 var txt = ''; 2967 2968 var bkg_width = $(document).width()-1; 2969 var bkg_height = $(document).height()-1; 2970 2971 txt += '<div class="confirmdlg_dark_bkg" id="'+id+'_dark_bkg" style="position:absolute;width:'+bkg_width+'px;height:'+bkg_height+'px;left:0;top:0;' + (+o.z_index? `z-index:${o.z_index};` : '') +'"></div>'; 2972 2973 txt += '<div class="confirmdlg '+o.dlg_class+'" id="'+id+'" style="position:absolute;' + (+o.z_index? `z-index:${o.z_index + 1};` : '') + o.dlg_style + '" >'; 2974 2975 if(title){ 2976 txt += '<div class="confirmdlg_title">' + title + '</div>'; 2977 } 2978 if(alert){ 2979 txt += '<div class="confirmdlg_alert">
2979' + alert + '</div>'; 2980 } 2981 txt += '<div class="confirmdlg_btns">'; 2982 txt += '<form onsubmit="return false">'; 2983 txt += '<div class="confirmdlg_btn" id="btn_yes">' + o.txt_yes + '</div>'; 2984 if(!o.single_btn){ 2985 txt += '<div class="confirmdlg_btn" id="btn_no">' + o.txt_no + '</div>'; 2986 } 2987 txt += '<input type="text" id="confirmdlg_target" style="width:0;height:0;outline:none !important;border:none !important;" />'; 2988 txt += '</form>'; 2989 txt += '</div>'; 2990 2991 txt += '</div>'; 2992 2993 $('body').append(txt); 2994 2995 $('.confirmdlg#'+id).center2(); 2996 2997 $('.confirmdlg#'+id + ' #btn_yes').click(function(){ 2998 closeDlg(); 2999 resolve(true); 3000 }); 3001 3002 $('.confirmdlg#'+id + ' #btn_no').click(function(){ 3003 closeDlg(); 3004 resolve(false); 3005 }); 3006 3007 3008 if(!o.no_outside_click){ // klikniÄcie poza dialogiem oznacza 'NIE' 3009 $('.confirmdlg_dark_bkg#'+id+'_dark_bkg').click(function(){ 3010 closeDlg(); 3011 resolve(false); 3012 }); 3013 } 3014 3015 $('.confirmdlg#'+id+' #confirmdlg_target').focus(); 3016 $('.confirmdlg#'+id+' #confirmdlg_target').keyup(function(e){ 3017 if(e.which == 13 || e.which == 32){ // enter i spacja 3018 closeDlg(); 3019 resolve(true); 3020 } 3021 else if(e.which == 27){ // escape 3022 closeDlg(); 3023 resolve(false); 3024 } 3025 }); 3026 3027 var closeDlg = function(){ 3028 $('.confirmdlg_dark_bkg#'+id+'_dark_bkg').remove(); 3029 $('.confirmdlg#'+id).remove(); 3030 $('body').off('keyup.ConfirmDlg'); 3031 } 3032 }); 3033} 3034/* 3035Confirm = function(title, alert, callback_yes, callback_no, o){ 3036 3037 callback_yes = callback_yes || function(){}; 3038 callback_no = callback_no || function(){}; 3039 3040 title = title || null; 3041 alert = alert || null; 3042 o = o || {}; 3043 o.dlg_class = o.dlg_class || ''; 3044 o.txt_yes = o.txt_yes || ((typeof callback_no == 'function')? ' TAK ' : ' OK '); 3045 o.txt_no = o.txt_no || ' NIE '; 3046 o.no_outside_click = o.no_outside_click || false; 3047 o.single_btn = o.single_btn || false; 3048 3049 var id = 'confirmdlg_' + Math.floor(Math.random()*1e6); 3050 3051 3052 var txt = ''; 3053 3054 var bkg_width = $(document).width()-1; 3055 var bkg_height = $(document).height()-1; 3056 3057 txt += '<div class="confirmdlg_dark_bkg '+o.dlg_class+'" id="'+id+'_dark_bkg" style="position:absolute;width:'+bkg_width+'px;height:'+bkg_height+'px;left:0;top:0;"></div>'; 3058 3059 txt += '<div class="confirmdlg" id="'+id+'" style="position:absolute;" >'; 3060 3061 if(title){ 3062 txt += '<div class="confirmdlg_title">' + title + '</div>'; 3063 } 3064 if(alert){ 3065 txt += '<div class="confirmdlg_alert">' + alert + '</div>'; 3066 } 3067 txt += '<div class="confirmdlg_btns">'; 3068 txt += '<form onsubmit="return false">'; 3069 txt += '<div class="confirmdlg_btn" id="btn_yes">' + o.txt_yes + '</div>'; 3070 if(!o.single_btn){ 3071 txt += '<div class="confirmdlg_btn" id="btn_no">' + o.txt_no + '</div>'; 3072 } 3073 txt += '<input type="text" id="confirmdlg_target" style="width:0;height:0;outline:none !important;border:none !important;" />'; 3074 txt += '</form>'; 3075 txt += '</div>'; 3076 3077 txt += '</div>'; 3078 3079 $('body').append(txt); 3080 3081 $('.confirmdlg#'+id).center2(); 3082 3083 $('.confirmdlg#'+id + ' #btn_yes').click(function(){ 3084 closeDlg(); 3085 setTimeout(callback_yes, 20); 3086 }); 3087 3088 $('.confirmdlg#'+id + ' #btn_no').click(function(){ 3089 closeDlg(); 3090 setTimeout(callback_no, 20); 3091 }); 3092 3093 3094 if(!o.no_outside_click){ // klikniÄcie poza dialogiem oznacza 'NIE' 3095 $('.confirmdlg_dark_bkg#'+id+'_dark_bkg').click(function(){ 3096 closeDlg(); 3097 setTimeout(callback_no, 20); 3098 }); 3099 } 3100 3101 $('.confirmdlg#'+id+' #confirmdlg_target').focus(); 3102 $('.confirmdlg#'+id+' #confirmdlg_target').keyup(function(e){ 3103 if(e.which == 13 || e.which == 32){ // enter i spacja 3104 closeDlg(); 3105 setTimeout(callback_yes, 20); 3106 } 3107 else if(e.which == 27){ // escape 3108 closeDlg(); 3109 setTimeout(callback_no, 20); 3110 } 3111 }); 3112 3113 var closeDlg = function(){ 3114 $('.confirmdlg_dark_bkg#'+id+'_dark_bkg').remove(); 3115 $('.confirmdlg#'+id).remove(); 3116 $('body').off('keyup.ConfirmDlg'); 3117 } 3118} 3119*/ 3120// Klasa do wyÅwietlania selecta z kategoriami i itemami w tych kategoriach 3121// \param input_id Selektor elementu, do którego odnosi siÄ picker, podawany jako selektor jQuery. To zwykle powinien byÄ input type="text" żeby wybraÄ poczÄ tkowÄ wartoÅÄ, ale może byÄ cokolwiek 3122// \param options Obiekt z opcjami dla okienka 3123// Najważniejsze opcje to: 3124// added_class Dodatkowa klasa dodawana do gÅównego diva selecta 3125// z_index = 500 z-index dla listy selecta 3126// opacity = 0.1 PrzezroczystoÅÄ tÅa 3127// position = 'left top,left bottom' PoÅożenie okienka wzglÄdem elementu input_id; '' oznacza wyÅrodkowanie na ekranie 3128// Parametr skÅada siÄ z czterech (lub szeÅciu) czÄÅci (spacja to dokÅadnie jedna spacja a przecinek musi byÄ bez spacji): 3129// <left selecta> <top selecta>,<left inputa> <top inputa>,dx,dy 3130// Select zostanie uÅożony tak, żeby jego <left selecta> <top selecta> znalazÅ siÄ w <left inputa> <top inputa> 3131// Parametry dx,dy sÄ opcjonalne i stanowiÄ dodatkowy offset w poziomie i w pionie 3132// Parmetry dostÄpne dla left to left, center, right. 3133// Parmetry dostÄpne dla top to top, center, bottom. 3134// parent = 'body' Parent, do którego zostanie doÅÄ czone okienko
3135// empty_text = '---' Tekst wypisywany w przypadku, gdy lista selecta jest pusta 3136// max_height = 0 Maksymalna dÅugoÅÄ selecta [px]. Zero oznacza, że maksymalnÄ dÅugoÅciÄ bÄdzie dolna krawÄdź ekranu 3137// width = 0 SzerokoÅÄ selecta [px]. Zero oznacza, że select bÄdzie szerokoÅci elementu inputa 3138// \param elements Tablica/obiekt zawierajÄ cy obiekty do wyÅwietlenia lub funkcja elements(input_id, <wartoÅÄ atrybutu 'picker' inputa>) zwracajÄ ca obiekt/tablicÄ z elementami selecta 3139// Na pierwszym poziomie jest lista kategorii, które zawierajÄ itemy. 3140// JeÅli kategoria nie ma nazwy (pola 'txt') lub jest ono puste, to tytuÅ tej kategorii nie jest wyÅwietlany. 3141// Lista itemów w kategorii może byÄ pusta 3142// elements = [ 3143// { txt : '<nazwa kategorii na liÅcie>', 3144// items : [ 3145// { txt : '<nazwa subitema na liÅcie'>, item : <obiekt subitema>, id : <opcjonalny unikalny id itema>, val : <opcjonalna wartoÅÄ dla selecta> }, 3146// { txt : '<nazwa subitema na liÅcie'>, item : <obiekt subitema>, id : <opcjonalny unikalny id itema>, val : <opcjonalna wartoÅÄ dla selecta> }, 3147// ... 3148// ], 3149// kat : <obiekt kategorii>, 3150// id : <opcjonalnie unikalny id kategorii - jeÅli mamy mieÄ możliwoÅÄ manipulowania zawartoÅciÄ selecta>, 3151// val : <opcjonalna wartoÅÄ dla selecta> 3152// }, 3153// { txt : '<nazwa kategorii na liÅcie>', 3154// items : [ 3155// { txt : '<nazwa subitema na liÅcie'>, item : <obiekt subitema>, id : <opcjonalny unikalny id itema>, val : <opcjonalna wartoÅÄ dla selecta> }, 3156// { txt : '<nazwa subitema na liÅcie'>, item : <obiekt subitema>, id : <opcjonalny unikalny id itema>, val : <opcjonalna wartoÅÄ dla selecta> }, 3157// ... 3158// ], 3159// kat : <obiekt kategorii>, 3160// id : <opcjonalnie unikalny id kategorii - jeÅli mamy mieÄ możliwoÅÄ manipulowania zawartoÅciÄ selecta> 3161// val : <opcjonalna wartoÅÄ dla selecta> 3162// }, 3163// ... 3164// ] 3165// \param sort_fn JeÅli jest, to powinien byÄ funkcjÄ wywoÅywanÄ jako sort(a, b, rodzaj). Parametrami a,b tej funkcji sÄ porównywane obiekty kategorii lub itemów a parametr 'rodzaj' to 0 dla itema lub 1 dla kategorii. 3166// \param on_select_fn JeÅli jest, to powinien byÄ funkcjÄ wywoÅywanÄ jako on_select_fn(<tekst wybranego itema/kategorii>, input_id, <wartoÅÄ atrybutu 'picker' inputa>, <obiekt wybranego elementu - itema lub kategorii>, <opcjonalny unikalny ID itema lub kategorii>, <rodzaj: 0 dla itema lub 1 dla kategorii>) 3167CSelectPicker = function(input_id, options, elements, sort_fn, on_select_fn){ 3168 if(!input_id){ 3169 alert('Nie wskazano elementu reagujÄ cego na selectpickera'); 3170 return; 3171 } 3172 3173 sort_fn = sort_fn || null; // defaultowo bez sortowania 3174 3175 var oryg_elements = elements || []; 3176 3177 on_select_fn = on_select_fn || function(){}; 3178 3179 var o = deepcopy(options || {}); 3180 o.id = 'selectpicker_' + Math.floor(Math.random()*1e6); 3181 o.z_index = o.z_index || 500; 3182 o.position = o.position || 'left top,left bottom'; 3183 o.parent = o.parent || 'body'; 3184 o.opacity = o.opacity || 0.1; 3185 o.max_height = +o.max_height || 0; 3186 3187 o.added_class = o.added_class || ''; 3188 o.empty_text = o.empty_text || '---'; 3189 3190 var sorted_arr = null; // tu bÄdÄ przechowywane skeszowane elementy 3191 var selected_idx = -1; // indeks wybranego elementu 3192 3193 var cnt = $(input_id).length; 3194 $(input_id).each(function(){ 3195 var input = $(this); 3196 3197 var val = input.val(); 3198 3199 // przykryjmy input naszym div-em 3200 input.css('visibility','hidden'); 3201 var io = input.offset(); 3202 var txt = '<div class="selectpicker_inp '+o.id+'" id="'+o.id+this.id+'_inp" style="position:absolute;
3202left:'+io.left+'px;top:'+io.top+'px;"></div>'; 3203 $(o.parent).append(txt); 3204 3205 var inp_target = $('.selectpicker_inp.'+o.id+'#'+o.id+this.id+'_inp'); 3206 3207 inp_target.outerWidth(input.outerWidth()); 3208 inp_target.outerHeight(input.outerHeight()); 3209 3210 // sprawdźmy, czy wartoÅÄ w input pasuje do którejÅ z wartoÅci selecta 3211 var inp_sel; 3212 for(var k in elements){ 3213 if(elements[k].val == val){ 3214 inp_sel = elements[k].txt; 3215 break; 3216 } 3217 if(elements[k].items){ 3218 for(var i in elements[k].items){ 3219 if(elements[k].items[i].val == val){ 3220 inp_sel = elements[k].items[i].txt; 3221 break; 3222 } 3223 } 3224 } 3225 } 3226 if(inp_sel){ 3227 inp_target.append(inp_sel); 3228 } 3229 3230 3231 inp_target.off('click.SelectPicker').on('click.SelectPicker', function(){ 3232 3233 var inp_id = this.id; 3234 3235 var showPicker = function(){ 3236 closePicker(); 3237 3238 if(typeof(oryg_elements) == 'function'){ // pobierzmy dynamicznie te elementy 3239 elements = oryg_elements(inp_id, input.attr('picker')); 3240 } 3241 else { 3242 elements = oryg_elements; 3243 } 3244 3245 var txt = ''; 3246 3247 var bkg_width = $(document).width(); 3248 var bkg_height = $(document).height(); 3249 3250 txt += '<div class="selectpicker_dark_bkg" id="'+o.id+'_dark_bkg" style="z-index:'+o.z_index+';position:fixed;background:black;opacity:'+o.opacity+';width:'+bkg_width+'px;height:'+bkg_height+'px;left:0;top:0;"></div>'; 3251 3252 txt += '<div class="selectpicker' + (o.added_class? (' ' + o.added_class) : '') + '" id="'+o.id+'" style="position:absolute;z-index:'+(o.z_index+1)+';" >'; 3253 txt += createPicker(inp_id); 3254 txt += '<div style="clear:both"></div>'; 3255 txt += '</div>'; 3256 3257 $(o.parent).append(txt); 3258 var my = $('#'+o.id); 3259 3260 $('#'+o.id+'_dark_bkg').click(function(){ // klikniÄcie poza selectem oznacza anulowanie 3261 closePicker(); 3262 }); 3263 3264 $('#'+o.id+' .selectpicker_item').click(function(){ // wybranie itema 3265 var idx = +this.id.substring(21); // prefix to selectpicker_item_nr_ 3266 3267 closePicker(); 3268 3269 inp_target.html(sorted_arr[idx].txt); 3270 val = sorted_arr[idx].val; // zapamiÄtajmy wybranÄ wartoÅÄ 3271 input.val(val); // ustawmy także wartoÅÄ naszego ukrytego inputa (np. jeÅli ma jechaÄ wraz z formularzem) 3272 selected_idx = idx; 3273 3274 if(on_select_fn){ 3275 on_select_fn(sorted_arr[idx].txt, inp_id, input.attr('picker'), sorted_arr[idx].obj, sorted_arr[idx].id, 0); 3276 } 3277 }); 3278 3279 $('#'+o.id+' .selectpicker_kat_title').click(function(){ // wybranie kategorii 3280 var idx = +this.id.substring(20); // prefix to selectpicker_kat_nr_ 3281 3282 closePicker(); 3283 3284 inp_target.html(sorted_arr[idx].txt); 3285 val = sorted_arr[idx].val; // zapamiÄtajmy wybranÄ wartoÅÄ 3286 input.val(val); // ustawmy także wartoÅÄ naszego ukrytego inputa (np. jeÅli ma jechaÄ wraz z formularzem) 3287 selected_idx = idx; 3288 3289 if(on_select_fn){ 3290 on_select_fn(sorted_arr[idx].txt, inp_id, input.attr('picker'), sorted_arr[idx].obj, sorted_arr[idx].id, 1); 3291 } 3292 }); 3293 3294 // uÅóżmy picker wzglÄdem inputa 3295 if(o.position == ''){ 3296 my.center2(); 3297 } 3298 else { 3299 var parts = o.position.split(','); 3300 var myc = parts[0] || ''; 3301 var at = parts[1] || ''; 3302 var dx = parts[2] || 0; 3303 var dy = parts[3] || 0; 3304 my.align(myc, at, input, dx, dy); 3305 } 3306 3307 if(o.max_height){ 3308 my.css('max-height', o.max_height + 'px'); 3309 } 3310 else { // nie możemy przekroczyÄ rozmiaru ekranu 3311 var wh = $(window).height(); 3312 my.css('max-height', (wh-input.outerHeight()-20) + 'px'); 3313 } 3314 3315 if(o.width){ 3316 my.css('width', o.width + 'px'); 3317 } 3318 else { 3319// my.css('width', input.outerWidth() + 'px'); 3320 my.outerWidth(input.outerWidth()); 3321 } 3322 3323 } 3324 3325 showPicker(); 3326 });
3327 3328 3329 var createPicker = function(inp_id){ 3330 3331 if(!sorted_arr){ // zobaczmy, czy mamy skeszowane 3332 if(!getArraySize(elements)){ 3333 return o.empty_text; 3334 } 3335 3336 sorted_arr = []; 3337 var kat_arr = []; 3338 for(var k in elements){ 3339 var kat = {kat : elements[k], items : []}; 3340 if(elements[k].items){ 3341 for(var i in elements[k].items){ 3342 kat.items.push(elements[k].items[i]); 3343 } 3344 kat.items.sort(function(a, b){ 3345 return sort_fn(a.item, b.item, 0); 3346 }); 3347 } 3348 kat_arr.push(kat); 3349 } 3350 kat_arr.sort(function(a,b){ 3351 return sort_fn(a.kat.kat, b.kat.kat, 1); 3352 }); 3353 3354 var idx; 3355 // skeszujmy to wszystko do jednej tablicy 3356 for(var k = 0; k < kat_arr.length; ++k){ 3357 if(val == kat_arr[k].kat.val){ 3358 selected_idx = sorted_arr.length; 3359 } 3360 sorted_arr.push({rodzaj : 1, txt : kat_arr[k].kat.txt, obj : kat_arr[k].kat.kat, id : kat_arr[k].kat.id, val : kat_arr[k].kat.val}); 3361 if(kat_arr[k].items){ 3362 for(var i = 0; i < kat_arr[k].items.length; ++i){ 3363 if(val == kat_arr[k].items[i].val){ 3364 selected_idx = sorted_arr.length; 3365 } 3366 sorted_arr.push({rodzaj : 0, txt : kat_arr[k].items[i].txt, obj : kat_arr[k].items[i].item, id : kat_arr[k].items[i].id, val : kat_arr[k].items[i].val}); 3367 } 3368 } 3369 sorted_arr.push({rodzaj : 2}); // rodzaj == 2 to koniec kategorii 3370 } 3371 } 3372 3373 txt = ''; 3374 var idx; 3375 for(var idx = 0; idx < sorted_arr.length; ++idx){ 3376 var ob = sorted_arr[idx]; 3377 switch(ob.rodzaj){ 3378 case 1 : // poczÄ tek kategorii 3379 txt += '<div class="selectpicker_kat" >'; 3380 if(ob.txt){ 3381 txt += '<div class="selectpicker_kat_title clickable'; 3382 if(idx == selected_idx){ 3383 txt += ' selected'; 3384 } 3385 txt += '" id="selectpicker_kat_nr_' + idx + '"'; 3386 if(isSet(ob.val)){ 3387 txt += ' val="'+_html(ob.val)+'"'; 3388 } 3389 txt += '>' + _html(ob.txt) + '</div>'; 3390 } 3391 break; 3392 case 2 : // koniec kategorii 3393 txt += '</div>'; 3394 break; 3395 case 0 : // item 3396 txt += '<div class="selectpicker_item clickable'; 3397 if(idx == selected_idx){ 3398 txt += ' selected'; 3399 } 3400 txt += '" id="selectpicker_item_nr_' + idx + '"'; 3401 if(isSet(ob.val)){ 3402 txt += ' val="'+_html(ob.val)+'"'; 3403 } 3404 txt += '>' + _html(ob.txt) + '</div>'; 3405 break; 3406 } 3407 } 3408 return txt; 3409 } 3410 3411 var closePicker = function(){ 3412 if(!o.no_bkg){ 3413 $('#'+o.id+'_dark_bkg').remove(); 3414 } 3415 $('#'+o.id).remove(); 3416 } 3417 3418 }); 3419 3420 return { 3421 disablePicker : function(item_id){ // wywoÅany z selektorem elementu, wyÅÄ cza SelectPicker dla tego elementu. WywoÅany bez parametru wyÅÄ cza caÅy picker 3422 var inp = item_id? '.selectpicker_inp.'+o.id+'#'+o.id+item_id+'_inp' : '.selectpicker_inp.'+o.id; 3423 $(inp).remove(); // nie wiadomo, czy to dziaÅa 3424 } 3425 } 3426 3427} 3428 3429 3430 3431// W podanym HTML-u zamienia adresy wzglÄdne na bezwzglÄdne. Zmienia atrybuty href i src, w razie potrzeby uzupeÅniajÄ c je przedrostkiem url_base 3432function replaceIndirectURL(url, url_base){ 3433 3434 return url.replace(/((href|src)(="?)(.*?)("|>))/gi, function(match, p1, p2, p3, p4, p5){ 3435 if(p4 && p4.substring(0, 4) == 'http'){ // mamy adres bezwzglÄdny, wiÄc zwracamy jak leci 3436 return p1; 3437 } 3438 else { // mamy adres wzglÄdny 3439 if(url_base[url_base.length-1] == '/' && p4 && p4[0] == '/'){ // pozbÄ dźmy siÄ nadmiarowego ukoÅnika 3440 p4 = p4.substring(1); 3441 } 3442 var attr = p2 + p3 + url_base + p4 + p5; 3443 return attr; 3444 } 3445 }); 3446} 3447 3448function copyTextToClipboard(text){ 3449 var textArea = document.createElement("textarea"); 3450 textArea.style.position = 'fixed'; 3451 textArea.style.top = 0; 3452 textArea.style.left = 0; 3453 textArea.style.width = '2em'; 3454 textArea.style.height = '2em'; 3455 textArea.style.padding = 0; 3456 textArea.style.border = 'none'; 3457 textArea.style.outline = 'none';
3458 textArea.style.boxShadow = 'none'; 3459 textArea.style.background = 'transparent'; 3460 textArea.value = text; 3461 document.body.appendChild(textArea); 3462 textArea.select(); 3463 try { 3464 var successful = document.execCommand('copy'); 3465 } 3466 catch (err) { 3467 } 3468 document.body.removeChild(textArea); 3469} 3470 3471// helper do parsowania zlokalizowanych nazw otrzymanych od bazy danych 3472function parseLocalizations(arr, json_field_name, field_name){ 3473 for(var id in arr){ 3474 var item = arr[id]; 3475 var loc_arr = JSON.parse(item[json_field_name]) || {}; 3476 delete item[json_field_name]; 3477 item[field_name] = {}; 3478 for(var i = 0; i < langs_arr.length; ++i){ 3479 var lng = langs_arr[i]; 3480 item[field_name][lng] = loc_arr[lng] || {strid : 0, lang : lng, object_column : field_name, text : ''}; 3481 } 3482 } 3483} 3484 3485// helper do inicjalizowania zlokalizowanego pola przed odpaleniem dialogu do edycji obiektu 3486function defaultLocaliztions(locs, field_name){ 3487 locs = locs || {}; 3488 for(var i = 0; i < langs_arr.length; ++i){ 3489 var lng = langs_arr[i]; 3490 locs[lng] = locs[lng] || {strid : 0, lang : lng, object_column : field_name, text : ''}; 3491 } 3492 return locs; 3493} 3494 3495// Zwraca true gdy wskazany element (stringowy selektor albo obiekt jQwery) jest widoczny przy bieÅ¼Ä cym przewiniÄciu strony 3496function isScrolledIntoView(elem){ 3497 var docViewTop = $(window).scrollTop(); 3498 var docViewBottom = docViewTop + $(window).height(); 3499 3500 var $elem = (typeof elem == 'string')? $(elem) : elem; 3501 3502 try { 3503 3504 var elemTop = $elem.offset().top; 3505 var elemBottom = elemTop + $elem.height(); 3506 3507 // return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); // true jak jest caÅy widoczny 3508 return ((elemBottom >= docViewTop && elemBottom < docViewBottom) || (elemTop >= docViewTop && elemTop < docViewBottom)); // true jak jest choÄ czÄÅciowo na ekranie 3509 } catch(e){ 3510 console.error('3w_tools.js:3694: isScrolledIntoView: element not found\n'+e.message); 3511 } 3512 return false; 3513} 3514 3515function getScrollBarSizes(){ // helper do odczytania gruboÅci scrollbarów 3516 var inner = document.createElement('p'); 3517 inner.style.width = "100px"; 3518 inner.style.height = "100px"; 3519 3520 var outer = document.createElement('div'); 3521 outer.style.position = "absolute"; 3522 outer.style.top = "0px"; 3523 outer.style.left = "0px"; 3524 outer.style.visibility = "hidden"; 3525 outer.style.width = "100px"; 3526 outer.style.height = "100px"; 3527 outer.style.overflow = "hidden"; 3528 outer.appendChild (inner); 3529 3530 document.body.appendChild (outer); 3531 3532 3533 var w1 = inner.offsetWidth; 3534 var h1 = inner.offsetHeight; 3535 outer.style.overflow = 'scroll'; 3536 var w2 = inner.offsetWidth; 3537 var h2 = inner.offsetHeight; 3538 3539 if(w1 == w2){ 3540 w2 = outer.clientWidth; 3541 } 3542 if(h1 == h2){ 3543 h2 = outer.clientHeight; 3544 } 3545 3546 document.body.removeChild (outer); 3547 3548 return {width : (w1 - w2), height : (h1 - h2)}; 3549}; 3550 3551// helper do zatwierdzania zlokalizowanych pól w dialogu edycji obiektu 3552// \locs Obiekt z lokalizacjami danego pola 3553// \field_id Selektor (jak CSS) kontrolek formularza. W formularzu na stronie te kontrolki majÄ jeszcze przyrostek jÄzyka, np. '_pl' 3554function zatwierdzLokalizacje(locs, field_id){ 3555 3556 for(var i = 0; i < langs_arr.length; ++i){ 3557 var lng = langs_arr[i]; 3558 locs[lng].text = $(field_id + '_' + lng).val(); 3559 } 3560} 3561 3562// klasa do keszowania obrazków 3563CCachedImage = function(url, nazwa){ 3564 var loaded = false; 3565 var img = null; 3566 var callbacks = []; 3567 this.nazwa = nazwa; 3568 3569 img = new Image(); 3570 3571 img.onload = function() { 3572 img.onload = null; 3573 loaded = true; 3574 callbacks.forEach(function(v){ 3575 v(img); 3576 }); 3577 } 3578 3579 img.src = url; 3580 3581 this.getImage = function(callback){ 3582 if(typeof(callback) == 'function'){ 3583 if(!loaded){ 3584 callbacks.push(callback); 3585 } 3586 else { 3587 callback(img); 3588 } 3589 } 3590 } 3591 3592 this.isLoaded = function(){ 3593 return loaded; 3594 } 3595 3596 this.getWidth = function(){ 3597 if(loaded){ 3598 return img.width; 3599 } 3600 return 0; 3601 } 3602 this.getHeight = function(){ 3603 if(loaded){
3604 return img.height; 3605 } 3606 return 0; 3607 } 3608} 3609/* 3610// \param outer_html TRUE oznacza, że funkcja zwraca HTML ÅÄ cznie ze wskazanym elementem; FALSE powoduje zwrócenie innerHTML 3611function getDOMTemplate(template_selector, outer_html){ // zwraca tekst reprezentujÄ cy DOM zawarty we wskazanym elemencie 3612 var template = document.querySelector(template_selector); 3613 if(!template){ 3614 console.error('Nie znaleziono szablonu: ' + template_selector); 3615 return null; 3616 } 3617 3618 if(outer_html){ 3619 return template.outerHTML.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); // pozbÄ dźmy siÄ wszystkich separatorów miÄdzy tagami 3620 } 3621 else { 3622 return template.innerHTML.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); // pozbÄ dźmy siÄ wszystkich separatorów miÄdzy tagami 3623 } 3624} 3625*/ 3626// \param outer_html TRUE oznacza, że funkcja zwraca HTML ÅÄ cznie ze wskazanym elementem; FALSE powoduje zwrócenie innerHTML 3627function getDOMTemplate(template_selector, outer_html){ // zwraca tekst reprezentujÄ cy DOM zawarty we wskazanym elemencie 3628 var $template = $(template_selector); 3629 if(!$template){ 3630 console.error('Nie znaleziono szablonu: ' + template_selector); 3631 return null; 3632 } 3633 3634 if(outer_html){ 3635 return $template[0].outerHTML.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); // pozbÄ dźmy siÄ wszystkich separatorów miÄdzy tagami 3636 } 3637 else { 3638 return $template[0].innerHTML.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); // pozbÄ dźmy siÄ wszystkich separatorów miÄdzy tagami 3639 } 3640} 3641 3642// \param $wydruk Element jQuery przeznaczony do wydruku 3643// \param before_print_callback JeÅli jest funkcjÄ , zostanie wywoÅane tuż przed wydrukiem, jako callback($head, $body); $head i $body to elementy iframe do wydruku. 3644// W tej funkcji można np, ustawiÄ dodatkowe arkusze css, np. $head.append('<link rel="stylesheet" type="text/css" href="css/admin.css">'); 3645// \param tylko_podglad JeÅli jest ustawione, to fukcja nie drukuje, tylko wyÅwietla wynikowÄ iframe z treÅciÄ wydruku 3646function drukujHTML($wydruk, tylko_podglad, callback){ 3647// tylko_podglad = true; 3648 3649 var spinner = new CWaitSpinner(); 3650 3651 var self = this; 3652 3653 function closePrint () { 3654 $iframe.remove(); 3655 } 3656 3657 var $iframe = $('<iframe id="wydruk" name="iframka"></iframe>'); 3658 $iframe.css({'position' : 'fixed', 'right' : 0, 'bottom' : 0}); 3659 3660 $('body').append($iframe); 3661 3662 if(tylko_podglad){ 3663 $iframe.css({'height': '100%', 'background': 'white', 'width': '100%', 'z-index' : 10000});
3664 $iframe.show(); 3665 } 3666 else { 3667 $iframe.hide(); 3668 } 3669 3670 $iframe.focus(); // podobno wymaga tego IE 3671 3672 function waitForIFrame(){ 3673 setTimeout(function(){ // musimy poczekaÄ co najmniej moment, bo w niektórych przeglÄ darkach nie idzie od razu 3674 var $body = $iframe.contents().find('body'); 3675 var $head = $iframe.contents().find('head'); 3676 if($body.length && $head.length){ 3677 3678 if($wydruk){ 3679 $body.append($wydruk); 3680 } 3681 if(typeof callback == 'function'){ 3682 setTimeout(function(){ // poczkajamy na zaÅadowanie siÄ doma 3683 callback($head, $body); 3684 3685 waitForImages(function(){ 3686 setTimeout(function(){ // poczekajmy na zaÅadowanie siÄ arkuszy stylów i wyrenderowanie obrazków 3687 spinner.close(); 3688 if(!tylko_podglad){ 3689 $iframe[0].contentWindow.onbeforeunload = closePrint; 3690 $iframe[0].contentWindow.onafterprint = closePrint; 3691 $iframe[0].contentWindow.print(); 3692 3693 } 3694 }, 500); 3695 }); 3696 3697 }, 500); 3698 } 3699 3700 var wait_start_time = microtime(true); 3701 // poczekajmy, aż zaÅadujÄ siÄ wszystkie obrazki 3702 function waitForImages(callback2){ 3703 setTimeout(function(){ 3704 var all = true; 3705 3706 var completed = 0; 3707 var not_completed = 0; 3708 3709 $body.find('img').each(function(){ 3710 var img = this; 3711 if(!this.complete || +this.naturalWidth == 0){ 3712 all = false; 3713console.log('waiting for: ' + this.src); 3714 return false; 3715 } 3716 else { 3717// console.log('complete: ' + $(this).prop('complete') + ', ' + this.src); 3718 } 3719 }); 3720 3721 if(all){ 3722 callback2(); 3723 } 3724 else { 3725 var now_time = microtime(true); 3726 var wait_time = now_time - wait_start_time; 3727console.log('img wait (' + wait_time + 's)'); 3728 3729 if(wait_time > 10){ // hmm, czekamy już ponad 10s, wiÄc drukujemy tak czy tak 3730console.log('wait too long'); 3731 callback2(); 3732 } 3733 else { 3734 waitForImages(callback2); 3735 } 3736 } 3737 }, 200); 3738 } 3739 3740 3741 } 3742 else { 3743console.log('iframe wait'); 3744 waitForIFrame(); 3745 } 3746 }, 200); 3747 } 3748 waitForIFrame(); 3749} 3750 3751// helper do zmiany kolejnoÅci sortowania tabelki 3752 3753// UWAGA: ta funkcja jest do dorobienia, bo nie dziaÅa 3754 3755// \param old_sort Dotychczasowa kolejnoÅÄ sortowania 3756// \param new_sort Nowa kolejnoÅÄ sortowania 3757// \param $table String zawierajÄ cy obiekt jQuery tabeli 3758// \param update_function JeÅli jest funkcjÄ to zostanie wywoÅane przed ustawieniem nowych klas nagÅówkowi tabeli 3759function changeSortOrder(old_sort, new_sort, $table, update_function){ 3760 var desc; 3761 var sort; 3762 if(old_sort == new_sort){ // jak nie desc, to desc 3763 sort = old_sort + ' desc'; 3764 desc = true; 3765 } 3766 else { 3767 sort = new_sort; 3768 desc = false; 3769 } 3770 3771 if(typeof(update_function) == 'function'){ 3772 update_function(); 3773 } 3774 3775 $table.find('th').removeClass('sort'); 3776 $table.find('th').removeClass('sort_desc'); 3777 3778 if(desc){ 3779 $table.find('th[sort="' + ord + '"]').addClass('sort_desc'); 3780 } 3781 else { 3782 $table.find('th[sort="' + ord + '"]').addClass('sort'); 3783 } 3784 3785} 3786 3787// helper do drukowania wskazanego tekstu z użyciem wskazanego pliku css-a 3788function printHelper(txt, id = 'print_wnd', css = '/back/css/print.css', head_html = null){ 3789 $('iframe#'+id).remove(); 3790 var ifr = document.createElement('iframe'); 3791 var head; 3792 3793 if(!head_html){ 3794 head = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3795<html lang="pl"> 3796<head> 3797<title>Diecezja</title> 3798<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 3799<link href="${url_base}${css}" rel="stylesheet" type="text/css" /> 3800</head>`; 3801 } 3802 else { 3803 head = head_html; 3804 } 3805 3806 ifr.src = ''; 3807 3808 ifr.id = id; 3809 ifr.onload = function () { 3810 var doc = document.getElementById(id); 3811 doc.contentDocument.head.innerHTML = head; 3812 doc.contentDocument.body.innerHTML = txt; 3813 setTimeout(function () { 3814 $('iframe#'+id).css('display', 'none'); 3815 ifr.contentWindow.print();
3816// setTimeout(function () { ifr.style.display = 'none' }, 1000); 3817 }, 50); 3818 } 3819 document.body.appendChild(ifr); 3820} 3821 3822// helper do wysyÅania wskazanego tekstu z użyciem wskazanego pliku css-a pod wskazany adres email 3823async function sendHelper(subject, body, email, css = null, with_debug_log = false, params = null){ 3824 if(!email){ 3825 throw Error('Nie podano adresu email'); 3826 } 3827 3828 var spinner = new CWaitSpinner(); 3829 3830 let css_text = ''; 3831 if(css){// pobierzmy wskazany css 3832 const response = await fetch(url_base + css); 3833 css_text = await response.text(); 3834 3835 css_text = `<style type="text/css">${css_text}</style>`; 3836 } 3837 3838 spinner.close(); 3839 3840 3841 3842 3843 head = `<!DOCTYPE html> 3844<html lang="pl"> 3845<head> 3846<title>Email</title> 3847<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 3848${css_text} 3849</head>`; 3850 3851 const payload = { 3852 subject : subject, 3853 body : body, 3854 email : email, 3855 head : head, 3856 params : params, 3857 kontakt_email : params.kontakt_email, 3858 default_mail_from : params.default_mail_from, 3859 3860 3861 mail_host : params.mail_host, 3862 mail_port : params.mail_port, 3863 mail_auth : params.mail_auth, 3864 mail_security : params.mail_security, 3865 mail_ignore_bad_certs : params.mail_ignore_bad_certs, 3866 mail_user : params.mail_user, 3867 mail_pass : params.mail_pass, 3868 mail_timeout : params.mail_timeout, 3869 3870 }; 3871 3872 const res = await JSONAsyncRequest3('ajax_3w_front_sql','action=send_email' + (with_debug_log? '&with_debug_log=1' : ''), payload); 3873 3874 return res; 3875} 3876 3877 3878CSlownik3w = function(){ 3879 var self = this; 3880 3881 let dane_zaladowane = false; 3882 3883 this.id = 0; 3884 this.txt_id = ''; 3885 this.nazwa = 'not loaded'; 3886 this.opis = 'not loaded'; 3887 3888 this.pozycje = {}; 3889 3890 this.getName = function(id, no_question_marks){ // zwraca nazwÄ wskazanej pozycji sÅownika 3891 return self.pozycje[id]? self.pozycje[id].label : (no_question_marks? '' : '???'); 3892 } 3893 3894 this.getPozycjaByID = function(id, def_val = null){ 3895 for(let _id in self.pozycje){ 3896 if(+_id == +id){ 3897 return self.pozycje[id]; 3898 } 3899 } 3900 return def_val; 3901 } 3902 3903 this.getLabelByID = function(id, default_val = null){ 3904 for(let _id in self.pozycje){ 3905 if(+_id == +id){ 3906 return self.pozycje[id].label; 3907 } 3908 } 3909 return default_val; 3910 } 3911 3912 // Åaduje dane obiektów 3913 // Po zakoÅczeniu wywoÅuje opcjonalny handler. 3914 this.ladujDane = async function(txt_id){ 3915 3916 if(dane_zaladowane){ // ok, dane już mamy zaÅadowane 3917 self.pozycje; 3918 } 3919 3920// console.log('Waiting for grupy funkcji'); 3921 let T0 = microtime(true); 3922 3923 const dane = await JSONAsyncRequest3('ajax_3w_slowniki_sql','action=load_slownik&id='+encodeURIComponent(txt_id)); 3924 if(dane?.result == 'OK'){ 3925 self.txt_id = txt_id; 3926 dane_zaladowane = true; 3927 let T1 = microtime(true); 3928 console.log('Loaded slownik ' + txt_id + ', ' + (T1 - T0)); 3929 self.id = +dane.slownik.id; 3930 self.txt_id = dane.slownik.txt_id; 3931 self.nazwa = dane.slownik.nazwa; 3932 self.opis = dane.slownik.opis; 3933 self.pozycje = dane.slownik.pozycje; 3934 3935 self.pozycje; 3936 } 3937 else if(dane?.result == 'SLOWNIK NOT FOUND'){ 3938 console.error('Nie znaleziono sÅownika ' + txt_id); 3939 throw Error('Nie znaleziono sÅownika ' + txt_id); 3940 } 3941 else { 3942 let T1 = microtime(true); 3943 console.log('Rejected slowniki ' + txt_id +', ' + (T1 - T0)); 3944 self.obiekty = {}; 3945 3946 alert('Nie powiodÅo siÄ pobranie danych. OdÅwież przeglÄ darkÄ i spróbuj ponownie.\nBÅÄ d: ' + dane?.message); 3947 throw Error('Nie powiodÅo siÄ pobranie danych. OdÅwież przeglÄ darkÄ i spróbuj ponownie.\nBÅÄ d: ' + dane?.message); 3948 } 3949 } 3950 3951 this.afterAllLoaded = function(){ 3952 } 3953 3954 // wskazany select wyeÅnia pozycjami sÅownika. 3955 // \param $select Element <select>, wskazany jako selektor css lub obiekt jQuery 3956 // \param options DostÄpne opcje: 3957 // - empty_value WartoÅÄ inna niż null powoduje, że na poczÄ tku listy zostanie umieszczony element o takiej wartoÅci 3958 // - empty_label Etykieta dla empty_value 3959 // - by_id TRUE powoduje, że pozycje sÄ wybierane wg. id pozycji a nie wg. pola val pozycji 3960 // \param pn_select_fn JeÅli jest funkcjÄ , zostanie wywoÅane jako on_select_fn(<selected_val>, this) 3961 this.createCtrl = function($select, value, options = null, on_select_fn = null){ 3962 options = options || {empty_value : null, empty_label : '', by_id : false}; 3963 $select = $($select); 3964 3965 $select.empty(); 3966 3967 let has_empty = false; 3968 3969 if(options && options.empty_value !== null && options.empty_value !== undefined){ 3970 $('<option />').val(options.empty_value).html(options.empty_label).appendTo($select); 3971 has_empty = true; 3972 } 3973 3974 filterAndSortArray(self.pozycje, (a,b) => { 3975 if(+a.prio == +b.prio){ 3976 return generic_compare_desc(a.label, b.label, +a.id, +b.id, false); 3977 } 3978 else { 3979 return b.prio - a.prio; 3980 } 3981 }, null, (v) => { 3982 $('<option />').val(options.by_id? v.id : v.label).html(v.label).appendTo($select); 3983 });
3984 3985 if((value != null && value != undefined && +value !== 0) || has_empty){ 3986 $select.val(value); 3987 } 3988 else { 3989 $select.val($select.find('option:first').val()); // zapodajmy value w selekcie 3990 } 3991 3992 if(typeof on_select_fn == 'function'){ 3993 $select.change(function(){ 3994 on_select_fn($(this).val(), self); 3995 }); 3996 } 3997 } 3998} 3999 4000CFeature3W = function(){ 4001 var self = this; 4002 4003 let dane_zaladowane = false; 4004 4005 this.id = 0; 4006 this.txt_id = ''; 4007 this.nazwa = 'not loaded'; 4008 this.opis = 'not loaded'; 4009 4010 this.opcje = {}; 4011 4012 this.getName = function(id, no_question_marks){ // zwraca nazwÄ wskazanej pozycji sÅownika 4013 return self.opcje[id]? self.opcje[id].label : (no_question_marks? '' : '???'); 4014 } 4015 4016 this.getOpcjaByID = function(id, def_val = null){ 4017 for(let _id in self.opcje){ 4018 if(+_id == +id){ 4019 return self.opcje[id]; 4020 } 4021 } 4022 return def_val; 4023 } 4024 4025 this.getLabelByID = function(id, default_val = null){ 4026 for(let _id in self.opcje){ 4027 if(+_id == +id){ 4028 return self.opcje[id].label; 4029 } 4030 } 4031 return default_val; 4032 } 4033 4034 // Åaduje dane obiektów 4035 // Po zakoÅczeniu wywoÅuje opcjonalny handler. 4036 this.ladujDane = async function(txt_id){ 4037 4038 if(dane_zaladowane){ // ok, dane już mamy zaÅadowane 4039 self.opcje; 4040 } 4041 4042// console.log('Waiting for grupy funkcji'); 4043 let T0 = microtime(true); 4044 4045 const dane = await JSONAsyncRequest3('ajax_3w_features_sql','action=load_feature&id='+encodeURIComponent(txt_id)); 4046 if(dane?.result == 'OK'){ 4047 self.txt_id = txt_id; 4048 dane_zaladowane = true; 4049 let T1 = microtime(true); 4050 console.log('Loaded features ' + txt_id + ', ' + (T1 - T0)); 4051 self.id = +dane.feature.id; 4052 self.txt_id = dane.feature.txt_id; 4053 self.nazwa = dane.feature.nazwa; 4054 self.opis = dane.feature.opis; 4055 self.opcje = dane.feature.opcje; 4056 4057 self.opcje; 4058 } 4059 else if(dane?.result == 'FEATURE NOT FOUND'){ 4060 console.error('Nie znaleziono kategorii wÅaÅciwoÅci ' + txt_id); 4061 throw Error('Nie znaleziono kategorii wÅaÅciwoÅci ' + txt_id); 4062 } 4063 else { 4064 let T1 = microtime(true); 4065 console.log('Rejected feature ' + txt_id +', ' + (T1 - T0)); 4066 self.obiekty = {}; 4067 4068 alert('Nie powiodÅo siÄ pobranie danych. OdÅwież przeglÄ darkÄ i spróbuj ponownie.\nBÅÄ d: ' + dane?.message); 4069 throw Error('Nie powiodÅo siÄ pobranie danych. OdÅwież przeglÄ darkÄ i spróbuj ponownie.\nBÅÄ d: ' + dane?.message); 4070 } 4071 } 4072 4073 this.afterAllLoaded = function(){ 4074 } 4075 4076 // wskazany select wyeÅnia pozycjami sÅownika. 4077 // \param $select Element <select>, wskazany jako selektor css lub obiekt jQuery 4078 // \param options DostÄpne opcje: 4079 // - empty_value WartoÅÄ inna niż null powoduje, że na poczÄ tku listy zostanie umieszczony element o takiej wartoÅci 4080 // - empty_label Etykieta dla empty_value 4081 // - by_id TRUE powoduje, że pozycje sÄ wybierane wg. id pozycji a nie wg. pola val pozycji 4082 // \param pn_select_fn JeÅli jest funkcjÄ , zostanie wywoÅane jako on_select_fn(<selected_val>, this) 4083 this.createCtrl = function($select, value, options = null, on_select_fn = null){ 4084 options = options || {empty_value : null, empty_label : '', by_id : false}; 4085 $select = $($select); 4086 4087 $select.empty(); 4088 4089 let has_empty = false; 4090 4091 if(options && options.empty_value !== null && options.empty_value !== undefined){ 4092 $('<option />').val(options.empty_value).html(options.empty_label).appendTo($select); 4093 has_empty = true; 4094 } 4095 4096 filterAndSortArray(self.opcje, (a,b) => { 4097 if(+a.prio == +b.prio){ 4098 return generic_compare_desc(a.label, b.label, +a.id, +b.id, false); 4099 } 4100 else { 4101 return b.prio - a.prio; 4102 } 4103 }, null, (v) => { 4104 $('<option />').val(options.by_id? v.id : v.label).html(v.label).appendTo($select); 4105 });
4106 4107 if((value != null && value != undefined && +value !== 0) || has_empty){ 4108 $select.val(value); 4109 } 4110 else { 4111 $select.val($select.find('option:first').val()); // zapodajmy value w selekcie 4112 } 4113 4114 if(typeof on_select_fn == 'function'){ 4115 $select.change(function(){ 4116 on_select_fn($(this).val(), self); 4117 }); 4118 } 4119 } 4120} 4121 4122function slownie(val){ 4123// pobrane z algorytm.org 4124 4125 let liczba = parseInt(val); 4126 4127 let jednosci = ["", " jeden", " dwa", " trzy", " cztery", " piÄÄ", " szeÅÄ", " siedem", " osiem", " dziewiÄÄ"]; 4128 let nastki = ["", " jedenaÅcie", " dwanaÅcie", " trzynaÅcie", " czternaÅcie", " piÄtnaÅcie", " szesnaÅcie", " siedemnaÅcie", " osiemnaÅcie", " dziewiÄtnaÅcie"]; 4129 let dziesiatki = ["", " dziesiÄÄ", " dwadzieÅcia", " trzydzieÅci", " czterdzieÅci", " piÄÄdziesiÄ t", " szeÅÄdziesiÄ t", " siedemdziesiÄ t", " osiemdziesiÄ t", " dziewiÄÄdziesiÄ t"]; 4130 let setki = ["", " sto", " dwieÅcie", " trzysta", " czterysta", " piÄÄset", " szeÅÄset", " siedemset", " osiemset", " dziewiÄÄset"]; 4131 let grupy = [["" ,"" ,""], 4132 [" tysiÄ c" ," tysiÄ ce" ," tysiÄcy"], 4133 [" milion" ," miliony" ," milionów"], 4134 [" miliard"," miliardy"," miliardów"], 4135 [" bilion" ," biliony" ," bilionów"], 4136 [" biliard"," biliardy"," biliardów"], 4137 [" trylion"," tryliony"," trylionów"]]; 4138 4139 if(+liczba == +val){ // dla poprawnej wartoÅci 4140 4141 let wynik = ''; 4142 let znak = ''; 4143 if(!liczba){ 4144 wynik = "zero"; 4145 } 4146 4147 if(liczba < 0) { 4148 znak = "minus"; 4149 liczba = -liczba; 4150 } 4151 4152 let g = 0; 4153 while(liczba > 0){ 4154 let s = Math.floor((liczba % 1000) / 100); 4155 let n = 0; 4156 let d = Math.floor((liczba % 100) / 10); 4157 let j = Math.floor(liczba % 10); 4158 4159 if(d == 1 && j > 0){ 4160 n = j; 4161 d = 0; 4162 j = 0; 4163 } 4164 4165 let k = 2; 4166 if(j == 1 && s+d+n == 0){ 4167 k = 0; 4168 } 4169 if(j == 2 || j == 3 || j == 4){ 4170 k = 1; 4171 } 4172 if(s + d + n + j > 0){ 4173 wynik = setki[s]+dziesiatki[d]+nastki[n]+jednosci[j]+grupy[g][k]+wynik; 4174 } 4175 4176 g++; 4177 liczba = Math.floor(liczba/1000); 4178 } 4179 return znak + wynik; 4180 } 4181 4182 4183 // nieprawidÅowa wartoÅÄ 4184 return '---'; 4185} 4186 4187function roundToPlaces(value, places){ // potrafi zaokrÄ glaÄ do 10, 100 itd. (places < 0) zÅ, a nie tylko groszy i dziesiÄ tek groszy (places > 0) 4188 if(places >= 0){ 4189 return +((+value).toFixed(places)); 4190 } 4191 let divider = parseInt(Math.pow(10, -places)); 4192 return Math.round(value/divider)*divider; 4193} 4194 4195Date.prototype.adjust = function(parts, amounts, negative = false){ // pozwala na dodawanie i odejmowanie czasu do/od daty 4196 4197 4198 var map = { 4199 years: 'FullYear', months: 'Month', weeks: 'Hours', days: 'Hours', hours: 'Hours', 4200 minutes: 'Minutes', seconds: 'Seconds', milliseconds: 'Milliseconds', 4201 utcyears: 'UTCFullYear', utcmonths: 'UTCMonth', weeks: 'UTCHours', utcdays: 'UTCHours', 4202 utchours: 'UTCHours', utcminutes: 'UTCMinutes', utcseconds: 'UTCSeconds', utcmilliseconds: 'UTCMilliseconds' 4203 }; 4204 4205 if(typeof(parts) == 'string'){ 4206 parts = [parts]; 4207 } 4208 if(typeof(amounts) == 'string' || typeof(amounts) == 'number'){ 4209 amounts = [amounts]; 4210 } 4211 4212 var self = this, i = 0; 4213 4214 parts.forEach(function(part){ 4215 part = part.toLowerCase(); 4216 4217 var amount = +amounts[i++]; 4218 4219 var mapPart = map[part]; 4220 4221 if(negative){ 4222 amount *= -1; 4223 } 4224 4225 if(part == 'weeks' || part == 'utcweeks'){ 4226 amount *= 168; 4227 } 4228 if(part == 'days' || part == 'utcdays'){ 4229 amount *= 24; 4230 } 4231 4232 self['set'+ mapPart]( self['get'+ mapPart]() + amount ); 4233 }); 4234 4235 return this; 4236} 4237 4238Date.prototype.diff = function(date2, parts){ // zwraca różnicÄ pomiÄdzy obiektem a wskazanÄ datÄ 4239 var d1 = new Date(this.getTime()), 4240 d2 = new Date(date2.getTime()), 4241 pm = d1 <= d2? 1 : -1, 4242 result = { }, 4243 factors = { weeks: (1000*60*60*24*7), days: (1000*60*60*24), hours: (1000*60*60), minutes: (1000*60), seconds: 1000, milliseconds: 1 }; 4244 4245 if(parts === undefined) 4246 parts = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds']; 4247 else if(typeof(parts) == "string") 4248 parts = [parts]; 4249 4250 for(var i=0, l=parts.length; i<l; i++){ 4251 var k = parts[i];
4252 result[k] = 0; 4253 4254 if(factors[k] === undefined){ 4255 inaWhile: while( true ){ 4256 d2.adjust(k, -1*pm); 4257 if( (pm === 1 && d1 > d2) || (pm === -1 && d1 < d2)){ 4258 d2.adjust(k, 1*pm); 4259 break inaWhile; 4260 } 4261 result[k]++; 4262 } 4263 } 4264 else{ 4265 var tmpDiff = Math.abs(d2.getTime() - d1.getTime()); 4266 result[k] = Math.floor(tmpDiff / factors[k]); 4267 d2.adjust(k, result[k]*-1*pm); 4268 } 4269 result[k] *= pm; 4270 } 4271 4272 if(parts.length == 1){ 4273 return result[parts[0]]; 4274 } 4275 return result; 4276} 4277 4278// Iterator do dat pomiÄdzy obiektem a zadanÄ datÄ ; można iterowaÄ po zadanej czÄÅci daty z okreÅlonym krokiem. 4279// Gdy callback zwroci false, iteracja jest od razu koÅczona 4280Date.prototype.each = function(endDate, parts, step, callback, bind){ 4281 var fromDate = new Date(this.getTime()), 4282 toDate = new Date(endDate.getTime()), 4283 pm = fromDate <= toDate? false:true, 4284 i = 0; 4285 4286 while( (pm === false && fromDate <= toDate) || (pm === true && fromDate >= toDate) ){ 4287 if(bind){ 4288 if(callback.call(bind, fromDate, i, this) === false){ 4289 break; 4290 } 4291 } 4292 else { 4293 if(callback(fromDate, i, this) === false){ 4294 break; 4295 } 4296 } 4297 i += step; 4298 fromDate.adjust(parts, step, pm); 4299 } 4300 return this; 4301} 4302 4303function displayPDF(link){ 4304 new CModalDlg2({ 4305 id : 'display_pdf_dlg', 4306 add_classes : 'display_pdf', 4307 z_index : 131, 4308 width: 'auto', 4309 dont_show_at_once : true, 4310 before_close_callback : null, 4311 opacity : 0.11, 4312 no_Esc_close : 0, 4313 }, 4314 function(dlg){ 4315 var txt = ` 4316<iframe src="${link}"></iframe> 4317`; 4318 txt = txt.trim().replace(/(>)([ \t\r\n]*)(<)/g,'$1$3'); 4319 return txt; 4320 }, 4321 function(dlg){ 4322 let $dlg = dlg.getDlg(); 4323 4324 $dlg.find('iframe').width($(window).width()-50).height($(window).height()-100); 4325 } 4326 ).showDlg(); 4327} 4328 4329function getGUID(separator = '-'){ 4330 var d = new Date().getTime(); 4331 var d2 = (performance && performance.now && (performance.now() * 1000)) || 0; // time in microseconds since page-load (or 0 if unsupported) 4332 return `xxxxxxxx${separator}xxxx${separator}4xxx${separator}yxxx${separator}xxxxxxxxxxxx`.replace(/[xy]/g, c => { 4333 var r = Math.random() * 16; // random number between 0 and 16 4334 if(d > 0){ // use timestamp until depleted 4335 r = (d + r) % 16 | 0; 4336 d = Math.floor(d/16); 4337 } 4338 else { // use microseconds since page-load (if supported) 4339 r = (d2 + r) % 16 | 0; 4340 d2 = Math.floor(d2 / 16); 4341 } 4342 return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); 4343 }); 4344} 4345 4346function numFormatter(num, base = 1000) { 4347 if(base == 1000){ 4348 if(num > 999 && num < 1e6){ 4349 return (num/1000).toFixed(1) + 'k'; // convert to k for number from > 1000 - 1e6 4350 } 4351 else if(num >= 1e6 && num < 1e9){ 4352 return (num/1e6).toFixed(1) + 'M'; // convert to M for number from > 1e6 - 1e9 4353 } 4354 else if(num >= 1e9){ 4355 return (num/1e9).toFixed(1) + 'G'; // convert to G for number > 1e9 4356 } 4357 else if(num < 900){ 4358 return num; // if value < 1000, nothing to do 4359 } 4360 } 4361 else { // base 1024 4362 if(num > 1023 && num < 1024*1024){ 4363 return (num/1024).toFixed(1) + 'K'; 4364 } 4365 else if(num >= 1024*1024 && num < 1024*1024*1024){ 4366 return (num/(1024*1024)).toFixed(1) + 'M'; 4367 } 4368 else if(num >= 1024*1024*1024){ 4369 return (num/(1024*1024*1024)).toFixed(1) + 'G'; 4370 } 4371 else if(num < 900){ 4372 return num; // if value < 1000, nothing to do 4373 } 4374 } 4375} 4376 4377if(!Math.imul){ 4378 Math.imul = (a, b) => {let aHi = (a >>> 16) & 0xffff;let aLo = a & 0xffff;let bHi = (b >>> 16) & 0xffff;let bLo = b & 0xffff;return ((aLo * bLo) + (((aHi * bLo + aLo * bHi) << 16) >>> 0) | 0);}; 4379} 4380 4381iHashFromString = s => {for(var i=0,h=9;i<s.length;
4381)h=Math.imul(h^s.charCodeAt(i++),9**9);return h^h>>>9}; 4382 4383/** 4384 * sends a request to the specified url from a form. this will change the window location. 4385 * @param {string} path the path to send the post request to 4386 * @param {object} params the parameters to add to the url 4387 * @param {string} [method=post] the method to use on the form 4388 */ 4389function gotoPage(path, params, method = 'post'){ 4390 4391 // The rest of this code assumes you are not using a library. 4392 // It can be made less verbose if you use one. 4393 const form = document.createElement('form'); 4394 form.method = method; 4395 form.action = path; 4396 4397 for (const key in params) { 4398 if (params.hasOwnProperty(key)) { 4399 const hiddenField = document.createElement('input'); 4400 hiddenField.type = 'hidden'; 4401 hiddenField.name = key; 4402 hiddenField.value = params[key]; 4403 4404 form.appendChild(hiddenField); 4405 } 4406 } 4407 4408 document.body.appendChild(form); 4409 form.submit(); 4410 return false; 4411} 4412 4413function csvToArray(str, _headers = 'first row', delimiter = ";", new_line = '\r\n'){ 4414 4415 let headers, rows; 4416 4417 if(_headers == 'first row'){ // nagÅówki brane z pierwszego wiersza 4418 // slice from start of text to the first \n index 4419 // use split to create an array from string by delimiter 4420 headers = str.slice(0, str.indexOf(new_line)).split(delimiter).map(h => h.trim()); 4421 4422 // slice from \n index + 1 to the end of the text 4423 // use split to create an array of each csv value row 4424 rows = str.slice(str.indexOf(new_line) + 1).split(new_line); 4425 } 4426 else { // nagÅówki zapodane w parametrze _headers 4427 headers = _headers.map(h => h.trim()); 4428 rows = str.slice(0).split(new_line); 4429 } 4430 4431 // Map the rows 4432 // split values from each row into an array 4433 // use headers.reduce to create an object 4434 // object properties derived from headers:values 4435 // the object passed as an element of the array 4436 const arr = rows.map(function (row) { 4437 const values = row.split(delimiter); 4438 const el = headers.reduce(function (object, header, index) { 4439 object[header] = values[index].trim(); 4440 return object; 4441 }, {}); 4442 return el; 4443 }); 4444 4445 // return the array 4446 return arr; 4447} 4448 4449var MD5 = function(d){var r = M(V(Y(X(d),8*d.length)));return r.toLowerCase()};function M(d){for(var _,m="0123456789ABCDEF",f="",r=0;r<d.length;
4449r++)_=d.charCodeAt(r),f+=m.charAt(_>>>4&15)+m.charAt(15&_);return f}function X(d){for(var _=Array(d.length>>2),m=0;m<_.length;m++)_[m]=0;for(m=0;m<8*d.length;m+=8)_[m>>5]|=(255&d.charCodeAt(m/8))<<m%32;return _}function V(d){for(var _="",m=0;m<32*d.length;m+=8)_+=String.fromCharCode(d[m>>5]>>>m%32&255);return _}function Y(d,_){d[_>>5]|=128<<_%32,d[14+(_+64>>>9<<4)]=_;for(var m=1732584193,f=-271733879,r=-1732584194,i=271733878,n=0;n<d.length;n+=16){var h=m,t=f,g=r,e=i;f=md5_ii(f=md5_ii(f=md5_ii(f=md5_ii(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_hh(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_gg(f=md5_ff(f=md5_ff(f=md5_ff(f=md5_ff(f,r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+0],7,-680876936),f,r,d[n+1],12,-389564586),m,f,d[n+2],17,606105819),i,m,d[n+3],22,-1044525330),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+4],7,-176418897),f,r,d[n+5],12,1200080426),m,f,d[n+6],17,-1473231341),i,m,d[n+7],22,-45705983),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+8],7,1770035416),f,r,d[n+9],12,-1958414417),m,f,d[n+10],17,-42063),i,m,d[n+11],22,-1990404162),r=md5_ff(r,i=md5_ff(i,m=md5_ff(m,f,r,i,d[n+12],7,1804603682),f,r,d[n+13],12,-40341101),m,f,d[n+14],17,-1502002290),i,m,d[n+15],22,1236535329),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+1],5,-165796510),f,r,d[n+6],9,-1069501632),m,f,d[n+11],14,643717713),i,m,d[n+0],20,-373897302),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+5],5,-701558691),f,r,d[n+10],9,38016083),m,f,d[n+15],14,-660478335),i,m,d[n+4],20,-405537848),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+9],5,568446438),f,r,d[n+14],9,-1019803690),m,f,d[n+3],14,-187363961),i,m,d[n+8],20,1163531501),r=md5_gg(r,i=md5_gg(i,m=md5_gg(m,f,r,i,d[n+13],5,-1444681467),f,r,d[n+2],9,-51403784),m,f,d[n+7],14,1735328473),i,m,d[n+12],20,-1926607734),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+5],4,-378558),f,r,d[n+8],11,-2022574463),m,f,d[n+11],16,1839030562),i,m,d[n+14],23,-35309556),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+1],4,-1530992060),f,r,d[n+4],11,1272893353),m,f,d[n+7],16,-155497632),i,m,d[n+10],23,-1094730640),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+13],4,681279174),f,r,d[n+0],11,-358537222),m,f,d[n+3],16,-722521979),i,m,d[n+6],23,76029189),r=md5_hh(r,i=md5_hh(i,m=md5_hh(m,f,r,i,d[n+9],4,-640364487),f,r,d[n+12],11,-421815835),m,f,d[n+15],16,530742520),i,m,d[n+2],23,-995338651),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+0],6,-198630844),f,r,d[n+7],10,1126891415),m,f,d[n+14],15,-1416354905),i,m,d[n+5],21,-57434055),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+12],6,1700485571),f,r,d[n+3],10,-1894986606),m,f,d[n+10],15,-1051523),i,m,d[n+1],21,-2054922799),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+8],6,1873313359),f,r,d[n+15],10,-30611744),m,f,d[n+6],15,-1560198380),i,m,d[n+13],21,1309151649),r=md5_ii(r,i=md5_ii(i,m=md5_ii(m,f,r,i,d[n+4],6,-145523070),f,r,d[n+11],10,-1120210379),m,f,d[n+2],15,718787259),i,m,d[n+9],21,-343485551),m=safe_add(m,h),f=safe_add(f,t),r=safe_add(r,g),i=safe_add(i,e)}return Array(m,f,r,i)}function md5_cmn(d,_,m,f,r,i){return safe_add(bit_rol(safe_add(safe_add(_,d),safe_add(f,i)),r),m)}function md5_ff(d,_,m,f,r,i,n){return md5_cmn(_&m|~_&f,d,_,r,i,n)}function md5_gg(d,_,m,f,r,i,n){return md5_cmn(_&f|m&~f,d,_,r,i,n)}function md5_hh(d,_,m,f,r,i,n){return md5_cmn(_^m^f,d,_,r,i,n)}function md5_ii(d,_,m,f,r,i,n){return md5_cmn(m^(_|~f),d,_,r,i,n)}function safe_add(d,_){var m=(65535&d)+(65535&_);return(d>>16)+(_>>16)+(m>>16)<<16|65535&m}function bit_rol(d,_){return d<<_|d>>>32-_} 4450 4451String.prototype.despace = function(){ 4452 return this.trim?.().replace?.(/(>)([ \t\r\n]*)(<)/g,'$1$3') ?? ''; 4453} 4454 4455String.prototype.nl2br = function(){ 4456 return this.trim?.().replace?.(/\n/g,'<br />') ?? ''; 4457} 4458 4459RegExp.escape = function(str){ 4460 return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 4461} 4462 4463// funkcja "podÅwietla" szukany fragment tekstu wstawiajac w jego miejsce <span> podanej klasy 4464function highliteFragment(txt, fragment, klasa){ 4465 txt = txt?.toString() ?? ''; 4466 if(!fragment){ 4467 return txt; 4468 } 4469 const re = new RegExp('('+RegExp.escape(fragment)+')',"gi"); 4470 txt = txt.replace(re,'<span class="'+klasa+'">$1</span>'); 4471 return txt; 4472} 4473 4474const applyErrors = ($container, errors) => { 4475 if(errors.length){ // wyÅwietlmy bÅÄdy 4476 var txt = ''; 4477 for(var i in errors){ 4478 txt += errors[i].txt + '<br />'; 4479 $container.find(errors[i].id).addClass('error'); 4480 } 4481 CResultFader3(txt, 1000, 'error'); 4482 return errors.length; 4483 } 4484 4485 return false; 4486} 4487 4488 4489/* 4490// Helper do obsÅugi multifiltra 4491class CMultiFilter { 4492 4493 // Multifilter "rozbija" podany filtr na skÅadowe i zależnie od stanu modyfikatorów tyc
4493h skÅadowych interpretuje wynik porównania każdej skÅadowej ze wszystkimi polami wskazanymi w konstruktorze. 4494 4495 defs = []; 4496 4497 // \param fields Obiekt ze spisem sprawdzanych pól obiektu. Każda skÅadowa jest parÄ o postaci <nazwa pola> : <definicja reguÅy jako funkcja lub wartoÅÄ_logiczna>. 4498 // Sprawdzanie odbywa siÄ dla wszystkich pól dla wszystkich skÅadowych filtra (ale może zakoÅczyÄ siÄ wczeÅniej, jeÅli peÅne sprawdzanie nie jest konieczne). 4499 // Dla definicji typu wartoÅÄ logiczna: 4500 // W tym przypadku znalezione elementy filtra sÄ porównywane jako ciÄ gi znaków. JeÅli wartoÅÄ logiczna definicji ewaluuje do false, wielkoÅÄ liter nie ma znaczenia. W przeciwnym razie wielkoÅÄ liter ma znaczenie. 4501 // Dla reguÅ typu function: 4502 // Dla każdego pola i każdej skÅadowej filtra jest wywoÅywana funkcja dla tego pola (jako (<subfilter>, <sprawdzany obiekt>) => {}). Funkcja powinna zwróciÄ 0 gdy szukany filtr wystÄpuje na poczÄ tku wartoÅci danego pola, > 0 gdy wystÄpuje dalej niż na poczatku i < 0 gdy nie wystÄpuje w wartoÅci tego pola. 4503 constructor(fields = {}){ 4504 4505 const findIgnoreCase = (needle, haystack) => { 4506 return haystack.toLowerCase().indexOf(needle.toLowerCase()); 4507 } 4508 4509 const findCaseMatters = (needle, haystack) => { 4510 return haystack.indexOf(needle); 4511 } 4512 4513 for(let field in fields){ 4514 if(typeof fields[field] == 'function'){ 4515 this.defs.push({field : field, func : fields[field], custom : true}); 4516 } 4517 else { 4518 this.defs.push({field : field, fields[field]? findCaseMatters : findIgnoreCase}); 4519 } 4520 } 4521 } 4522 4523 // \param filter WartoÅÄ filtra. CiÄ gi znaków rozdzielone spacjÄ sÄ traktowane jako AND. W celu uzyskania OR ciÄ gi znaków należy oddzieliÄ pionowÄ paÅkÄ (|). 4524 // Nadmiarowe spacje sÄ ignorowane. 4525 // CiÄ g poprzedzony wykrzyknikiem (!) oznacza negacjÄ. 4526 // CiÄ g poprzedzony caret (^) oznacza, że dopasowanie musi wystÄ piÄ na poczÄ tku 4527 // \param obj Sprawdzany obiekt 4528 // \return Zwraca true jeÅli obiekt ma zostaÄ przepuszczony przez sito i false w przeciwnym przypadku. 4529 filter(filter, obj){ 4530 const f1 = filter.replace( 4531 } 4532} 4533*/ 4534 4535class CKEditorUploadAdapter { 4536 constructor(loader, params, check_fn){ 4537 this.loader = loader; // The file loader instance to use during the upload. 4538 this.params = params; 4539 this.check_fn = check_fn; 4540 } 4541 4542 // Initializes the XMLHttpRequest object using the URL passed to the constructor. 4543 _initRequest() { 4544 const xhr = this.xhr = new XMLHttpRequest(); 4545 4546 // Note that your request may look different. It is up to you and your editor 4547 // integration to choose the right communication channel. This example uses 4548 // a POST request with JSON as a data structure but your configuration 4549 // could be different. 4550 4551 xhr.open( 'POST', url_base + '/ajax_req.php?aaction=' + this.params + '&sid=' + Math.random(), true ); 4552 xhr.responseType = 'json'; 4553 } 4554 4555 // Initializes XMLHttpRequest listeners. 4556 _initListeners( resolve, reject, file ) { 4557 var error = this.check_fn(); 4558 if(error){ 4559 return reject(); 4560 } 4561 4562 const xhr = this.xhr; 4563 const loader = this.loader; 4564 const genericErrorText = `Nie udaÅo siÄ wysÅaÄ pliku: ${ file.name }.`; 4565 4566 xhr.addEventListener( 'error', () => reject( genericErrorText ) ); 4567 xhr.addEventListener( 'abort', () => reject() ); 4568 xhr.addEventListener( 'load', () => { 4569 const response = xhr.response; 4570 4571 if( !response || +response.error_code){ // The reject() function must be called when the upload fails. 4572 return reject( response.message); 4573 } 4574 4575 // If the upload is successful, resolve the upload promise with an object c
4575ontaining 4576 // at least the "default" URL, pointing to the image on the server. 4577 // This URL will be used to display the image in the content. Learn more in the 4578 // UploadAdapter#upload documentation. 4579 resolve( { 4580 default: response.url 4581 } ); 4582 } ); 4583 4584 // Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded 4585 // properties which are used e.g. to display the upload progress bar in the editor user interface. 4586 if(xhr.upload){ 4587 xhr.upload.addEventListener('progress', evt => { 4588 if(evt.lengthComputable){ 4589 loader.uploadTotal = evt.total; 4590 loader.uploaded = evt.loaded; 4591 } 4592 }); 4593 } 4594 } 4595 4596 _sendRequest(file){ // Prepares the data and sends the request. 4597 const data = new FormData(); // Prepare the form data. 4598 4599 data.append('upload', file); 4600 4601 // Important note: This is the right place to implement security mechanisms 4602 // like authentication and CSRF protection. For instance, you can use 4603 // XMLHttpRequest.setRequestHeader() to set the request headers containing 4604 // the CSRF token generated earlier by your application. 4605 this.xhr.send(data); // Send the request. 4606 } 4607 4608 upload(){ // Starts the upload process. 4609 return this.loader.file 4610 .then(file => new Promise((resolve, reject) => { 4611 this._initRequest(); 4612 this._initListeners(resolve, reject, file); 4613 this._sendRequest(file); 4614 })); 4615 } 4616 4617 // Aborts the upload process. 4618 abort(){ 4619 if(this.xhr){ 4620 this.xhr.abort(); 4621 } 4622 } 4623}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.