1 /** 2 * @file Array 3 * 4 * @author Dominik Kocuj 5 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2 or later 6 * @copyright Copyright (c) 2016-2018 kocuj.pl 7 */ 8 9 (function() {})(); // empty function for correct minify with comments 10 //'use strict'; // for jshint uncomment this and comment line above 11 12 /* jshint strict: true */ 13 /* jshint -W034 */ 14 15 /* global document */ 16 /* global jQuery */ 17 18 /* global kocujILV12aHelper */ 19 /* global kocujILV12aDataHelper */ 20 21 /* global kocujILV12aBackendSettingsFormArrayVals */ 22 23 /** 24 * Array prototype constructor 25 * 26 * @constructs 27 * @namespace kocujILV12aCBackendSettingsFormArray 28 * @public 29 * @return {void} 30 */ 31 function kocujILV12aCBackendSettingsFormArray() { 32 'use strict'; 33 /* jshint validthis: true */ 34 // get this object 35 var self = this; 36 // initialize objects 37 self._objHelper = kocujILV12aHelper; 38 self._objDataHelper = kocujILV12aDataHelper; 39 // get current script filename 40 self._thisFilename = document.scripts[document.scripts.length-1].src; 41 // get settings 42 var vals = kocujILV12aBackendSettingsFormArrayVals; 43 if (vals.throwErrors === '1') { 44 self._valsThrowErrors = true; 45 } else { 46 self._valsThrowErrors = false; 47 } 48 self._valsHtmlIdFormatArrayContainer = vals.htmlIdFormatArrayContainer; 49 self._valsTextButtonAddNewElement = vals.textButtonAddNewElement; 50 self._valsDivElementContainer = vals.divElementContainer; 51 self._valsDivField = vals.divField; 52 self._valsDivControls = vals.divControls; 53 self._valsImageArrowDown = vals.imageArrowDown; 54 self._valsImageArrowUp = vals.imageArrowUp; 55 self._valsImageDelete = vals.imageDelete; 56 self._valsImageEmpty = vals.imageEmpty; 57 } 58 59 /** 60 * Array prototype 61 * 62 * @namespace kocujILV12aCBackendSettingsFormArray 63 * @public 64 */ 65 kocujILV12aCBackendSettingsFormArray.prototype = { 66 /** 67 * Object kocujILV12aHelper 68 * 69 * @private 70 * @type {Object} 71 */ 72 _objHelper : null, 73 74 /** 75 * Object kocujILV12aDataHelper 76 * 77 * @private 78 * @type {Object} 79 */ 80 _objDataHelper : null, 81 82 /** 83 * Current script filename 84 * 85 * @private 86 * @type {string} 87 */ 88 _thisFilename : '', 89 90 /** 91 * Projects list 92 * 93 * @private 94 * @type {Array} 95 */ 96 _prj : [], 97 98 /** 99 * Script settings - throw errors (true) or not (false) 100 * 101 * @private 102 * @type {string} 103 */ 104 _valsThrowErrors : false, 105 106 /** 107 * Script settings - HTML identifier format for array container 108 * 109 * @private 110 * @type {string} 111 */ 112 _valsHtmlIdFormatArrayContainer : '', 113 114 /** 115 * Script settings - text for button for adding new element 116 * 117 * @private 118 * @type {string} 119 */ 120 _valsTextButtonAddNewElement : '', 121 122 /** 123 * Script settings - div for element container 124 * 125 * @private 126 * @type {string} 127 */ 128 _valsDivElementContainer : '', 129 130 /** 131 * Script settings - div for element field 132 * 133 * @private 134 * @type {string} 135 */ 136 _valsDivField : '', 137 138 /** 139 * Script settings - div for element controls 140 * 141 * @private 142 * @type {string} 143 */ 144 _valsDivControls : '', 145 146 /** 147 * Script settings - image with down arrow 148 * 149 * @private 150 * @type {string} 151 */ 152 _valsImageArrowDown : '', 153 154 /** 155 * Script settings - image with up arrow 156 * 157 * @private 158 * @type {string} 159 */ 160 _valsImageArrowUp : '', 161 162 /** 163 * Script settings - image with delete button 164 * 165 * @private 166 * @type {string} 167 */ 168 _valsImageDelete : '', 169 170 /** 171 * Script settings - empty image 172 * 173 * @private 174 * @type {string} 175 */ 176 _valsImageEmpty : '', 177 178 /** 179 * Add project 180 * 181 * @public 182 * @param {string} projectId Project identifier 183 * @param {string} [projectName] Project name 184 * @return {void} 185 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.PROJECT_ALREADY_EXISTS if project identifier entered in projectId already exists 186 */ 187 addProject : function(projectId, projectName) { 188 'use strict'; 189 // parse arguments 190 var args = this._checkAddProject(projectId, projectName); 191 // add project 192 if (this._prj['prj_' + args.projectId] === undefined) { 193 this.addProjectIfNotExists(args.projectId, args.projectName); 194 } else { 195 this._throwError('PROJECT_ALREADY_EXISTS', args.projectId); 196 return; 197 } 198 }, 199 200 /** 201 * Add project if not exists 202 * 203 * @public 204 * @param {string} projectId Project identifier 205 * @param {string} [projectName] Project name 206 * @return {void} 207 */ 208 addProjectIfNotExists : function(projectId, projectName) { 209 'use strict'; 210 // parse arguments 211 var args = this._checkAddProject(projectId, projectName); 212 // add project 213 if (this._prj['prj_' + args.projectId] === undefined) { 214 this._prj['prj_' + args.projectId] = { 215 projectName : args.projectName, 216 arrays : [] 217 }; 218 } 219 }, 220 221 /** 222 * Get HTML selector for array container 223 * 224 * @public 225 * @param {string} projectId Project identifier 226 * @param {string} formId Form identifier 227 * @param {string} fieldId Field identifier 228 * @return {string} HTML selector for array container 229 */ 230 getHTMLSelectorArrayContainer : function(projectId, formId, fieldId) { 231 'use strict'; 232 // parse arguments 233 projectId = this._parseProjectId(projectId); 234 formId = this._objHelper.initString(formId); 235 fieldId = this._objHelper.initString(fieldId); 236 // exit 237 return '#' + this._getHTMLNameArrayContainer(projectId, formId, fieldId); 238 }, 239 240 /** 241 * Get HTML selector for array element container 242 * 243 * @public 244 * @param {string} projectId Project identifier 245 * @param {string} formId Form identifier 246 * @param {string} fieldId Field identifier 247 * @param {number} number Number of element in array 248 * @return {string} HTML selector for array element container 249 */ 250 getHTMLSelectorArrayElementContainer : function(projectId, formId, fieldId, number) { 251 'use strict'; 252 // parse arguments 253 projectId = this._parseProjectId(projectId); 254 formId = this._objHelper.initString(formId); 255 fieldId = this._objHelper.initString(fieldId); 256 number = this._objHelper.initNumeric(number); 257 // exit 258 return '#' + this._getHTMLNameArrayContainer(projectId, formId, fieldId) + ' div[data-type="element-container"][data-number="' + number + '"]'; 259 }, 260 261 /** 262 * Get HTML selector for array empty element container 263 * 264 * @public 265 * @param {string} projectId Project identifier 266 * @param {string} formId Form identifier 267 * @param {string} fieldId Field identifier 268 * @return {string} HTML selector for array empty element container 269 */ 270 getHTMLSelectorArrayEmptyElementContainer : function(projectId, formId, fieldId) { 271 'use strict'; 272 // parse arguments 273 projectId = this._parseProjectId(projectId); 274 formId = this._objHelper.initString(formId); 275 fieldId = this._objHelper.initString(fieldId); 276 // exit 277 return '#' + this._getHTMLNameArrayContainer(projectId, formId, fieldId) + ' div[data-type="element-container"][data-next="na"]'; 278 }, 279 280 /** 281 * Get HTML selector for array element container field div 282 * 283 * @public 284 * @param {string} projectId Project identifier 285 * @param {string} formId Form identifier 286 * @param {string} fieldId Field identifier 287 * @param {number} number Number of element in array 288 * @return {string} HTML selector for array element container field div 289 */ 290 getHTMLSelectorArrayElementContainerFieldDiv : function(projectId, formId, fieldId, number) { 291 'use strict'; 292 // parse arguments 293 projectId = this._parseProjectId(projectId); 294 formId = this._objHelper.initString(formId); 295 fieldId = this._objHelper.initString(fieldId); 296 number = this._objHelper.initNumeric(number); 297 // exit 298 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' div[data-type="field"]'; 299 }, 300 301 /** 302 * Get HTML selector for array element container field value 303 * 304 * @public 305 * @param {string} projectId Project identifier 306 * @param {string} formId Form identifier 307 * @param {string} fieldId Field identifier 308 * @param {number} number Number of element in array 309 * @return {string} HTML selector for array element container field value 310 */ 311 getHTMLSelectorArrayElementContainerFieldValue : function(projectId, formId, fieldId, number) { 312 'use strict'; 313 // parse arguments 314 projectId = this._parseProjectId(projectId); 315 formId = this._objHelper.initString(formId); 316 fieldId = this._objHelper.initString(fieldId); 317 number = this._objHelper.initNumeric(number); 318 // exit 319 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' [data-type="field-value"]'; 320 }, 321 322 /** 323 * Get HTML selector for array element container controls div 324 * 325 * @public 326 * @param {string} projectId Project identifier 327 * @param {string} formId Form identifier 328 * @param {string} fieldId Field identifier 329 * @param {number} number Number of element in array 330 * @return {string} HTML selector for array element container controls div 331 */ 332 getHTMLSelectorArrayElementContainerControlsDiv : function(projectId, formId, fieldId, number) { 333 'use strict'; 334 // parse arguments 335 projectId = this._parseProjectId(projectId); 336 formId = this._objHelper.initString(formId); 337 fieldId = this._objHelper.initString(fieldId); 338 number = this._objHelper.initNumeric(number); 339 // exit 340 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' div[data-type="controls"]'; 341 }, 342 343 /** 344 * Get HTML selector for array element down arrow 345 * 346 * @public 347 * @param {string} projectId Project identifier 348 * @param {string} formId Form identifier 349 * @param {string} fieldId Field identifier 350 * @param {number} number Number of element in array 351 * @return {string} HTML selector for array element down arrow 352 */ 353 getHTMLSelectorArrayElementArrowDown : function(projectId, formId, fieldId, number) { 354 'use strict'; 355 // parse arguments 356 projectId = this._parseProjectId(projectId); 357 formId = this._objHelper.initString(formId); 358 fieldId = this._objHelper.initString(fieldId); 359 number = this._objHelper.initNumeric(number); 360 // exit 361 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' div[data-type="controls"] a[data-type="down"]'; 362 }, 363 364 /** 365 * Get HTML selector for array element up arrow 366 * 367 * @public 368 * @param {string} projectId Project identifier 369 * @param {string} formId Form identifier 370 * @param {string} fieldId Field identifier 371 * @param {number} number Number of element in array 372 * @return {string} HTML selector for array element up arrow 373 */ 374 getHTMLSelectorArrayElementArrowUp : function(projectId, formId, fieldId, number) { 375 'use strict'; 376 // parse arguments 377 projectId = this._parseProjectId(projectId); 378 formId = this._objHelper.initString(formId); 379 fieldId = this._objHelper.initString(fieldId); 380 number = this._objHelper.initNumeric(number); 381 // exit 382 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' div[data-type="controls"] a[data-type="up"]'; 383 }, 384 385 /** 386 * Get HTML selector for array element delete 387 * 388 * @public 389 * @param {string} projectId Project identifier 390 * @param {string} formId Form identifier 391 * @param {string} fieldId Field identifier 392 * @param {number} number Number of element in array 393 * @return {string} HTML selector for array element delete 394 */ 395 getHTMLSelectorArrayElementDelete : function(projectId, formId, fieldId, number) { 396 'use strict'; 397 // parse arguments 398 projectId = this._parseProjectId(projectId); 399 formId = this._objHelper.initString(formId); 400 fieldId = this._objHelper.initString(fieldId); 401 number = this._objHelper.initNumeric(number); 402 // exit 403 return this.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number) + ' div[data-type="controls"] a[data-type="delete"]'; 404 }, 405 406 /** 407 * Process array elements 408 * 409 * @public 410 * @param {string} projectId Project identifier 411 * @param {string} formId Form identifier 412 * @param {string} fieldId Field identifier 413 * @param {string} emptyField Empty field 414 * @param {number} elementsCount Array elements count 415 * @param {Object} arraySettings Array settings 416 * @return {void} 417 */ 418 process : function(projectId, formId, fieldId, emptyField, elementsCount, arraySettings) { 419 'use strict'; 420 // get this object 421 var self = this; 422 (function($) { 423 // parse parameters 424 projectId = self._parseProjectId(projectId); 425 formId = self._objHelper.initString(formId); 426 fieldId = self._objHelper.initString(fieldId); 427 emptyField = self._objHelper.initString(emptyField); 428 elementsCount = self._objHelper.initNumeric(elementsCount); 429 arraySettings = self._objHelper.initObject(arraySettings); 430 // remember array of fields 431 var id = self._prj['prj_' + projectId].arrays.length; 432 self._prj['prj_' + projectId].arrays['arr_' + id] = { 433 formId : formId, 434 fieldId : fieldId, 435 arraySettings : arraySettings, 436 emptyField : emptyField, 437 newNumber : elementsCount 438 }; 439 self._objDataHelper.setDataInDom($(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)), 'array-id', id); 440 // update controls in fields 441 for (var z=0; z<elementsCount; z++) { 442 var prevNumber = ''; 443 if (z > 0) { 444 prevNumber = z-1; 445 } 446 var nextNumber = ''; 447 if (z < elementsCount-1) { 448 nextNumber = z+1; 449 } 450 self._updateControls(projectId, id, z, true, prevNumber, true, nextNumber); 451 } 452 // optionally add empty field 453 if (arraySettings.autoadddeleteifempty) { 454 self._addNewEmptyField(projectId, formId, fieldId); 455 } 456 // optionally add button for adding a new field 457 if (arraySettings.addnewbutton) { 458 // get selector 459 var selectorArrayContainer = $(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)); 460 // add button 461 selectorArrayContainer.append('<div data-type="add-new-button"><input type="button" class="button" value="' + self._valsTextButtonAddNewElement + '" /></div>'); 462 // add button event 463 selectorArrayContainer.find('div[data-type="add-new-button"] input').bind('click', { 464 self : self, 465 projectId : projectId, 466 formId : formId, 467 fieldId : fieldId 468 }, function(event) { 469 // disable default event 470 event.preventDefault(); 471 // add new empty field if there is none 472 if ($(event.data.self.getHTMLSelectorArrayEmptyElementContainer(event.data.projectId, event.data.formId, event.data.fieldId)).length === 0) { 473 event.data.self._addNewEmptyField(event.data.projectId, event.data.formId, event.data.fieldId); 474 $(this).insertAfter($(event.data.self.getHTMLSelectorArrayEmptyElementContainer(event.data.projectId, event.data.formId, event.data.fieldId))); 475 } 476 }); 477 } 478 }(jQuery)); 479 }, 480 481 /** 482 * Get HTML array container name 483 * 484 * @private 485 * @param {string} projectId Project identifier 486 * @param {string} formId Form identifier 487 * @param {string} fieldId Field identifier 488 * @param {number} number Number of element in array 489 * @return {string} HTML array container name 490 */ 491 _getHTMLNameArrayContainer : function(projectId, formId, fieldId) { 492 'use strict'; 493 // exit 494 return this._valsHtmlIdFormatArrayContainer.replace('####FORM_ID####', formId).replace('####FIELD_ID####', fieldId); 495 }, 496 497 /** 498 * Parse project identifier 499 * 500 * @private 501 * @param {string} projectId Project identifier 502 * @return {string} Parsed project identifier 503 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.EMPTY_PROJECT_ID if project identifier entered in projectId is empty 504 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.PROJECT_DOES_NOT_EXIST if project identifier entered in projectId does not exist 505 */ 506 _parseProjectId : function(projectId) { 507 'use strict'; 508 // parse project identifier 509 projectId = this._objHelper.initString(projectId); 510 if (projectId === '') { 511 this._throwError('EMPTY_PROJECT_ID'); 512 return; 513 } 514 // check if project exists 515 if (this._prj['prj_' + projectId] === undefined) { 516 this._throwError('PROJECT_DOES_NOT_EXIST', projectId); 517 return; 518 } 519 // exit 520 return projectId; 521 }, 522 523 /** 524 * Check arguments for adding project 525 * 526 * @private 527 * @param {string} projectId Project identifier 528 * @param {string} [projectName] Project name 529 * @return {Object} Parsed arguments for adding project 530 * @throws {kocujILV12aCException} kocujILV12aExceptionCode.EMPTY_PROJECT_ID if project identifier entered in projectId is empty 531 */ 532 _checkAddProject : function(projectId, projectName) { 533 'use strict'; 534 // parse arguments 535 projectId = this._objHelper.initString(projectId); 536 if (projectId === '') { 537 this._throwError('EMPTY_PROJECT_ID'); 538 return; 539 } 540 projectName = this._objHelper.initString(projectName); 541 // exit 542 return { 543 projectId : projectId, 544 projectName : projectName 545 }; 546 }, 547 548 /** 549 * Throw an error if debugging is enabled 550 * 551 * @private 552 * @param {string} codeString Error code in string format 553 * @param {string} [param] Parameter for error information 554 * @return {void} 555 */ 556 _throwError : function(codeString, param) { 557 'use strict'; 558 // parse arguments 559 codeString = this._objHelper.initString(codeString); 560 if (codeString === '') { 561 return; 562 } 563 param = this._objHelper.initString(param); 564 // throw an error 565 if (this._valsThrowErrors) { 566 /* jshint evil: true */ 567 eval('throw new kocujILV12aCException(kocujILV12aExceptionCode.' + codeString + ', this._thisFilename, param);'); 568 } 569 }, 570 571 /** 572 * Update controls 573 * 574 * @private 575 * @param {string} projectId Project identifier 576 * @param {number} arrayId Identifier of array of fields 577 * @param {number} number Number of element in array 578 * @param {boolean} changePrevNumber Change previous number (true) or leave it as it is (false) 579 * @param {number|string} prevNumber Previous number or empty string if there is none 580 * @param {boolean} changeNextNumber Change next number (true) or leave it as it is (false) 581 * @param {number|string} nextNumber Next number or empty string if there is none 582 * @return {void} 583 */ 584 _updateControls : function(projectId, arrayId, number, changePrevNumber, prevNumber, changeNextNumber, nextNumber) { 585 'use strict'; 586 // get this object 587 var self = this; 588 (function($) { 589 // get array data 590 var arrayData = self._prj['prj_' + projectId].arrays['arr_' + arrayId]; 591 // clear controls 592 var selectorArrayElementArrowDown = $(self.getHTMLSelectorArrayElementArrowDown(projectId, arrayData.formId, arrayData.fieldId, number)); 593 var selectorArrayElementArrowUp = $(self.getHTMLSelectorArrayElementArrowUp(projectId, arrayData.formId, arrayData.fieldId, number)); 594 var selectorArrayElementDelete = $(self.getHTMLSelectorArrayElementDelete(projectId, arrayData.formId, arrayData.fieldId, number)); 595 if (selectorArrayElementArrowDown.length > 0) { 596 selectorArrayElementArrowDown.remove(); 597 } 598 if (selectorArrayElementArrowUp.length > 0) { 599 selectorArrayElementArrowUp.remove(); 600 } 601 if (selectorArrayElementDelete.length > 0) { 602 selectorArrayElementDelete.remove(); 603 } 604 // get array settings 605 var arraySettings = arrayData.arraySettings; 606 // get array element container selector 607 var selectorArrayElementContainer = $(self.getHTMLSelectorArrayElementContainer(projectId, arrayData.formId, arrayData.fieldId, number)); 608 // get array element container controls selector 609 var selectorArrayElementContainerControls = $(self.getHTMLSelectorArrayElementContainerControlsDiv(projectId, arrayData.formId, arrayData.fieldId, number)); 610 // add data attributes to array element container for controls 611 self._objDataHelper.setDataInDom(selectorArrayElementContainer, 'number', number); 612 if (changePrevNumber) { 613 self._objDataHelper.setDataInDom(selectorArrayElementContainer, 'prev', prevNumber); 614 } 615 if (changeNextNumber) { 616 self._objDataHelper.setDataInDom(selectorArrayElementContainer, 'next', nextNumber); 617 } 618 // prepare buttons link 619 var buttonsLink = '<a href="#" data-type="####DATA_TYPE####"><img src="####IMAGE_URL####" alt="" style="float:left;border-width:0;border-style:none;" /></a>'; 620 // add down arrow 621 var selector = ''; 622 var imageUrl = self._valsImageEmpty; 623 if ((arraySettings.allowchangeorder) && (selectorArrayElementContainer.data('next') !== '')) { 624 selector = self.getHTMLSelectorArrayElementArrowDown(projectId, arrayData.formId, arrayData.fieldId, number); 625 imageUrl = self._valsImageArrowDown; 626 } 627 selectorArrayElementContainerControls.append(buttonsLink.replace('####DATA_TYPE####', 'down').replace('####IMAGE_URL####', imageUrl)); 628 if (selector !== '') { 629 $(selector).bind('click.element', { 630 self : self, 631 projectId : projectId, 632 formId : arrayData.formId, 633 fieldId : arrayData.fieldId 634 }, function(event) { 635 // disable default event 636 event.preventDefault(); 637 // change HTML contents 638 event.data.self._changeFields(event.data.projectId, event.data.formId, event.data.fieldId, parseInt($(this).parent().parent().data('number'), 10), $(this).parent().parent().data('next')); 639 }); 640 } 641 // add up arrow 642 selector = ''; 643 imageUrl = self._valsImageEmpty; 644 if ((arraySettings.allowchangeorder) && (selectorArrayElementContainer.data('prev') !== '')) { 645 selector = self.getHTMLSelectorArrayElementArrowUp(projectId, arrayData.formId, arrayData.fieldId, number); 646 imageUrl = self._valsImageArrowUp; 647 } 648 selectorArrayElementContainerControls.append(buttonsLink.replace('####DATA_TYPE####', 'up').replace('####IMAGE_URL####', imageUrl)); 649 if (selector !== '') { 650 $(selector).bind('click.element', { 651 self : self, 652 projectId : projectId, 653 formId : arrayData.formId, 654 fieldId : arrayData.fieldId 655 }, function(event) { 656 // disable default event 657 event.preventDefault(); 658 // change HTML contents 659 event.data.self._changeFields(event.data.projectId, event.data.formId, event.data.fieldId, $(this).parent().parent().data('prev'), parseInt($(this).parent().parent().data('number'), 10)); 660 }); 661 } 662 // add delete button 663 selector = ''; 664 imageUrl = self._valsImageEmpty; 665 if (arraySettings.deletebutton) { 666 selector = self.getHTMLSelectorArrayElementDelete(projectId, arrayData.formId, arrayData.fieldId, number); 667 imageUrl = self._valsImageDelete; 668 } 669 selectorArrayElementContainerControls.append(buttonsLink.replace('####DATA_TYPE####', 'delete').replace('####IMAGE_URL####', imageUrl)); 670 if (selector !== '') { 671 $(selector).bind('click.element', { 672 self : self, 673 projectId : projectId, 674 formId : arrayData.formId, 675 fieldId : arrayData.fieldId 676 }, function(event) { 677 // disable default event 678 event.preventDefault(); 679 // delete field 680 event.data.self._deleteField(event.data.projectId, event.data.formId, event.data.fieldId, parseInt($(this).parent().parent().data('number'), 10)); 681 }); 682 } 683 // add automatic adding and deleting of elements 684 if (arraySettings.autoadddeleteifempty) { 685 // add automatic deleting of element 686 $(self.getHTMLSelectorArrayElementContainerFieldValue(projectId, arrayData.formId, arrayData.fieldId, number)).bind('change.element', { 687 self : self, 688 projectId : projectId, 689 formId : arrayData.formId, 690 fieldId : arrayData.fieldId 691 }, function(event) { 692 // disable default event 693 event.preventDefault(); 694 // optionally delete field 695 if ($(this).val() === '') { 696 event.data.self._deleteField(event.data.projectId, event.data.formId, event.data.fieldId, parseInt($(this).parent().parent().data('number'), 10)); 697 } 698 }); 699 } 700 }(jQuery)); 701 }, 702 703 /** 704 * Change fields in array 705 * 706 * @private 707 * @param {string} projectId Project identifier 708 * @param {string} formId Form identifier 709 * @param {string} fieldId Field identifier 710 * @param {number} numberAbove First number of element in array 711 * @param {number} numberBelow Second number of element in array 712 * @return {void} 713 */ 714 _changeFields : function(projectId, formId, fieldId, numberAbove, numberBelow) { 715 'use strict'; 716 // get this object 717 var self = this; 718 (function($) { 719 // get array identifier 720 var arrayId = $(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)).data('array-id'); 721 // get selectors 722 var selectorArrayElementContainer1 = $(self.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, numberAbove)); 723 var selectorArrayElementContainer2 = $(self.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, numberBelow)); 724 // change positions 725 selectorArrayElementContainer1.insertAfter(selectorArrayElementContainer2); 726 // get previous and next numbers 727 var prev1 = selectorArrayElementContainer1.data('prev'); 728 var prev2 = selectorArrayElementContainer2.data('prev'); 729 var next1 = selectorArrayElementContainer1.data('next'); 730 var next2 = selectorArrayElementContainer2.data('next'); 731 // update controls for previous array element 732 if (prev1 !== '') { 733 self._updateControls(projectId, arrayId, prev1, false, '', true, numberBelow); 734 } 735 // update controls for next array element 736 if (next2 !== '') { 737 self._updateControls(projectId, arrayId, next2, true, numberAbove, false, ''); 738 } 739 // update controls 740 self._updateControls(projectId, arrayId, numberAbove, true, numberBelow, true, next2); 741 self._updateControls(projectId, arrayId, numberBelow, true, prev1, true, numberAbove); 742 }(jQuery)); 743 }, 744 745 /** 746 * Delete field in array 747 * 748 * @private 749 * @param {string} projectId Project identifier 750 * @param {string} formId Form identifier 751 * @param {string} fieldId Field identifier 752 * @param {number} number Number of element in array 753 * @return {void} 754 */ 755 _deleteField : function(projectId, formId, fieldId, number) { 756 'use strict'; 757 // get this object 758 var self = this; 759 (function($) { 760 // get array element container selector 761 var selectorArrayElementContainer = $(self.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, number)); 762 // get previous and next numbers 763 var prevNumber = selectorArrayElementContainer.data('prev'); 764 var nextNumber = selectorArrayElementContainer.data('next'); 765 // get array identifier 766 var arrayId = $(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)).data('array-id'); 767 // update previous element 768 if (prevNumber !== '') { 769 var selectorArrayElementContainerPrev = $(self.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, prevNumber)); 770 self._updateControls(projectId, arrayId, prevNumber, false, '', true, nextNumber); 771 } 772 // update next element 773 if (nextNumber !== '') { 774 var selectorArrayElementContainerNext = $(self.getHTMLSelectorArrayElementContainer(projectId, formId, fieldId, nextNumber)); 775 self._updateControls(projectId, arrayId, nextNumber, true, prevNumber, false, ''); 776 } 777 // delete element 778 selectorArrayElementContainer.remove(); 779 }(jQuery)); 780 }, 781 782 /** 783 * Add empty field 784 * 785 * @private 786 * @param {string} projectId Project identifier 787 * @param {string} formId Form identifier 788 * @param {string} fieldId Field identifier 789 * @return {void} 790 */ 791 _addNewEmptyField : function(projectId, formId, fieldId) { 792 'use strict'; 793 // get this object 794 var self = this; 795 (function($) { 796 // get array container selector 797 var selectorArrayContainer = $(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)); 798 // get array identifier 799 var arrayId = $(self.getHTMLSelectorArrayContainer(projectId, formId, fieldId)).data('array-id'); 800 // get array data 801 var arrayData = self._prj['prj_' + projectId].arrays['arr_' + arrayId]; 802 // add new empty field 803 selectorArrayContainer.append(self._valsDivElementContainer.replace('####DATA_TYPE_ELEMENT_CONTAINER####', 'element-container').replace('####DATA_ATTRS####', 'data-number="" data-prev="na" data-next="na"') + self._valsDivField.replace('####DATA_TYPE_FIELD####', 'field') + arrayData.emptyField + '</div>' + self._valsDivControls.replace('####DATA_TYPE_CONTROLS####', 'controls') + '</div><div style="clear:both;"></div></div>'); 804 // get empty array element container 805 var selectorEmptyArrayElementContainer = selectorArrayContainer.find('div[data-type="element-container"]:last'); 806 // update array element number 807 self._objDataHelper.setDataInDom(selectorEmptyArrayElementContainer, 'number', arrayData.newNumber); 808 self._prj['prj_' + projectId].arrays['arr_' + arrayId].newNumber = arrayData.newNumber+1; 809 // add adding controls to empty field after changing its value 810 selectorEmptyArrayElementContainer.find('[data-type="field-value"]').bind('change.empty', { 811 self : self, 812 projectId : projectId, 813 formId : formId, 814 fieldId : fieldId, 815 arrayId : arrayId, 816 arraySettings : arrayData.arraySettings 817 }, function(event) { 818 // disable default event 819 event.preventDefault(); 820 // optionally add new empty field 821 if ($(this).val() !== '') { 822 // update last array element 823 var previous = ''; 824 var selectorArrayElementContainer = selectorArrayContainer.find('div[data-type="element-container"][data-next=""]'); 825 if (selectorArrayElementContainer.length > 0) { 826 previous = parseInt(selectorArrayElementContainer.data('number'), 10); 827 var number = parseInt($(this).parent().parent().data('number'), 10); 828 event.data.self._updateControls(event.data.projectId, event.data.arrayId, parseInt(selectorArrayElementContainer.data('number'), 10), false, '', true, number); 829 } 830 // update controls 831 event.data.self._updateControls(event.data.projectId, event.data.arrayId, parseInt($(this).parent().parent().data('number'), 10), true, previous, true, ''); 832 // add new empty field 833 if (event.data.arraySettings.autoadddeleteifempty) { 834 event.data.self._addNewEmptyField(event.data.projectId, event.data.formId, event.data.fieldId); 835 } 836 // remove this event 837 $(this).unbind('change.empty'); 838 } 839 }); 840 }(jQuery)); 841 } 842 }; 843 844 // initialize 845 var kocujILV12aBackendSettingsFormArray = new kocujILV12aCBackendSettingsFormArray(); 846