function nuInitJSOptions() { if (window.nuAdminButtons === undefined) { window.nuAdminButtons = { 'nuDebug': true, 'nuPHP': true, 'nuRefresh': true, 'nuObjects': true, 'nuProperties': true }; } if (window.nuUXOptions === undefined) { window.nuUXOptions = { 'nuEnableBrowserBackButton': true, // Enable the browser's Back button 'nuPreventButtonDblClick': true, // Disable a button for 1 5 s to prevent a double click 'nuShowPropertiesOnMiddleClick': true, // Show the Object Properties on middle mouse click 'nuAutosizeBrowseColumns': true, // Autosize columns to fit the document width 'nuShowBackButton': false, // Show a Back Button 'nuMobileView': false, // Optimise view for mobile devices 'nuBrowsePaginationInfo': 'default', // Default Format is: '{StartRow} - {EndRow} ' + nuTranslate('of') + ' ' + '{TotalRows}' 'nuShowNuBuilderLink': true, // Show the link to nubuilder com 'nuShowLoggedInUser': false, // Show the logged in User 'nuShowBrowserTabTitle': true, // Show the Form Title in the Browser Tab 'nuDebugMode': true, // Debug Mode 'nuBrowserTabTitlePrefix': 'nuBuilder', // Prefix in the Browser Tab 'nuCalendarStartOfWeek': 'Sunday', // nuCalendar: Start of Week: Sunday (default) or Monday 'nuSelect2Theme': 'default', // select2 theme (default, classic) Default: default 'nuEditCloseAfterSave': 'None', // Close forms after saving. Values: None, All, User, System 'nuShowJSErrors' : 'None' // Show JS errors in alert message }; } } nuInitJSOptions(); function nuBuildForm(formObj) { window.nuOnSetSelect2Options = null; // can be overwritten by nuAddJavaScript() window.nuSERVERRESPONSE = formObj; if (formObj.record_id != '-2') { nuAddJavaScript(formObj.javascript_bc); } $('#nubody').off('.nuresizecolumn').css('transform', 'scale(1)'); $('html,body').scrollTop(0).scrollLeft(0); if (nuNeedToLoginAgain(formObj)) return; const formType = nuFormType(); nuSetDefaultWindowProperties(formObj, formType); nuInitShowJSErrors(); nuFORM.edited = false; if (nuEditDoCloseAfterSave(formObj)) { return; } nuFORM.scroll = []; nuSetSuffix(1000); nuSetBody(formObj); nuRedefineNuSelectBrowse(); nuFORM.tableSchema = formObj.tableSchema; nuFORM.formSchema = formObj.formSchema; window.nuLANGUAGE = formObj.translation; nuSetProperty('refreshed', nuGetProperty('refreshed') + 1); nuAddedByLookup(formObj); var currentForm = nuSetFormProperties(formObj); nuAddHolder('nuBreadcrumbHolder'); nuAddHomeLogout(); nuAddHolder('nuActionHolder'); if (formType == 'edit') { nuAddHolder('nuTabHolder'); } // const nuRecordDiv = nuAddHolder('nuRECORD') .attr('data-nu-table', formObj.table) .attr('data-nu-primary-key-name', formObj.primary_key); // DEV: nuWrapWithForm(nuRecordDiv[0], '#', ''); nuAddBreadcrumbs(); nuAddEditTabs('', formObj); if (typeof window.nuBeforeAddActionButtons === 'function') { nuBeforeAddActionButtons(); } nuAddActionButtons(formObj); nuRecordProperties(formObj, ''); let obj0 = null; if (formType == 'edit') { nuOptions(formObj.form_id, '', 'form', formObj.global_access); nuBuildEditObjects(formObj, '', '', formObj); nuResizeFormDialogCoordinates(); nuCalculateForm(false); obj0 = nuGetFirstObject(formObj.objects, -1); } nuGetStartingTab(); if (formType == 'edit' && nuIsNewRecord() && (obj0 !== null)) { obj0.nuFocusWithoutScrolling(); } if (formObj.record_id == '-2') { // Arrange Objects nuCreateDragOptionsBox(formObj); } else { nuAddJavaScript(formObj.javascript); } nuDragTitleEvents(); nuAddHome(); nuShowLastUpdatedMessage(); if (window.nuOnEditorLoad) { nuOnEditorLoad(); } else { $('.nuEditor').each((index, element) => { nuInitTinyMCE(element.id); }); } nuEvaluateOnLoadEvents(); if (window.nuLoadEditGlobal && formType == 'edit') { nuLoadEditGlobal(formObj.form_id, formObj.form_code); } if (window.nuLoadBrowseGlobal && formType == 'browse') { nuLoadBrowseGlobal(formObj.form_id, formObj.form_code); } if (window.nuOnLoad) { nuOnLoad(formObj.form_id, formObj.form_code); } if (formType == 'edit') { window.nuRESPONSIVE.getStartPositions(); } else { if (currentForm.browse_autoresize_columns !== '0' || nuDocumentID !== parent.nuDocumentID) { if (nuUXOptions.nuAutosizeBrowseColumns || currentForm.browse_autoresize_columns === '1' || nuDocumentID !== parent.nuDocumentID) { nuResizeBrowseColumns(true); } } } if (nuUXOptions.nuShowBrowserTabTitle) { nuSetBrowserTabTitle(nuUXOptions.nuBrowserTabTitlePrefix); } else { document.title = nuUXOptions.nuBrowserTabTitlePrefix; } if (Object.keys(window.nuAdminButtons).length) { nuAddAdminButtons(); } if (nuUXOptions.nuEnableBrowserBackButton) { nuEnableBrowserBackButton(); } if (nuUXOptions.nuPreventButtonDblClick) { nuPreventButtonDblClick(); } if (nuUXOptions.nuShowBackButton) { nuAddBackButton(); } if (nuUXOptions.nuShowPropertiesOnMiddleClick) { document.addEventListener("mousedown", nuOpenPropertiesOnMiddleClick, { passive: true }); } if ((nuUXOptions.nuBrowsePaginationInfo) !== '') { nuShowBrowsePaginationInfo((nuUXOptions.nuBrowsePaginationInfo)); } if (nuUXOptions.nuShowLoggedInUser) { nuDisplayLoggedInUser(); } else if (!nuUXOptions.nuShowNuBuilderLink) { $('.nuBuilderLink').remove(); } nuInitSetBrowseWidthHelper(); if (window.nuMESSAGES.length > 0) { let msgDiv = nuMessage(window.nuMESSAGES); if (window.nuOnMessage) { nuOnMessage(msgDiv, window.nuMESSAGES); } window.nuMESSAGES = []; } nuProcessAfterSave(); nuAddFormStyle(formObj.style); const globalAccess = nuGlobalAccess(); if (globalAccess) { nuContextMenuUpdate(); } nuSetSaved(true); nuCursor('default'); window.nuPORTRAITSCREEN = false; if (!nuIsMobile()) { $('#nuSearchField').trigger("focus"); } else { nuMobileView(currentForm.mobile_view); } nuWindowPosition(); nuFormModification(); nuRestoreScrollPositions(); if ((nuSERVERRESPONSE.user_a11y || globalAccess) && window.nuSetAccessibility) { nuSetAccessibility(formType, globalAccess); } } function nuProcessAfterSave() { if (window.nuTimesSaved > 0) { if (window.nuAfterSaveGlobal) nuAfterSaveGlobal(); if (window.nuAfterSave) nuAfterSave(); } } function nuSetFormProperties(formObj) { const properties = ['form_id', 'record_id', 'session_id', 'user_id', 'redirect_form_id', 'redirect_other_form_id', 'title', 'row_height', 'rows', 'browse_columns', 'browse_sql', 'browse_rows', 'browse_table_id', 'browse_filtered_rows', 'browse_title_multiline', 'browse_autoresize_columns', 'mobile_view', 'pages', 'form_code', 'form_description', 'form_group', 'form_type', 'run_code', 'run_description', 'data_mode' ]; var currentForm = window.nuFORM.getCurrent(); properties.forEach(prop => { currentForm[prop] = formObj[prop]; }); return currentForm; } function nuEditDoCloseAfterSave(formObj) { if (nuHasBeenSaved() < 1 || nuGetProperty('nuEditCloseAfterSave') == '0') { return false; } const closeAfterSave = window.nuUXOptions.nuEditCloseAfterSave.toLowerCase() const isUserForm = !formObj.form_id.startsWith('nu'); const shouldCloseAllForms = closeAfterSave === 'allforms'; const shouldCloseUserForms = closeAfterSave === 'userforms' && isUserForm; const shouldCloseSystemForms = closeAfterSave === 'systemforms' && !isUserForm; if (shouldCloseAllForms || shouldCloseUserForms || shouldCloseSystemForms) { return nuCloseAfterSave(); } return false; } function nuInitShowJSErrors() { if (window.nuUXOptions.nuShowJSErrors) { const nuShowJSErrors = window.nuUXOptions.nuShowJSErrors; let enableShowJSErrors = false; switch (nuShowJSErrors.toLowerCase()) { case "globeadmin": enableShowJSErrors = nuGlobalAccess() break; case "everyone": enableShowJSErrors = true; break; } if (enableShowJSErrors) { nuConsoleErrorsToMessage(); } } } function nuAddHome() { if (window.nuLoginH != '') { let breadCrumb = $('#nuBreadcrumb0').length > 0 ? $('#nuBreadcrumb0') : $('#nuHomeGap'); breadCrumb .html('') .attr('title', nuTranslate('Home')) .attr('onclick', '') .attr('onclick', 'nuForm("' + window.nuLoginH + '", -1, "", "", 1);') .css('cursor', 'pointer'); window.nuLoginH = ''; } } function nuNeedToLoginAgain(f) { let result = f.tableSchema === null; if (result) { $('body').addClass('nuBrowseBody').removeClass('nuEditBody'); sessionStorage.logout = 'true'; window.top.location.reload(); nuCursor('default'); } return result; } function nuSetDefaultWindowProperties(f, formType) { if (formType == 'edit' && nuCurrentProperties().form_type !== 'launch') { window.nuTimesSaved ++; if (window.nuLastForm != f.form_id || (window.nuLastRecordId != f.record_id && window.nuLastRecordId !== "-1")) { window.nuTimesSaved = 0; } } else { window.nuTimesSaved = -1; } window.nuLastForm = f.form_id; window.nuLastRecordId = f.record_id; window.nuSubformRow = -1; window.nuBrowseNoData = false; window.nuBrowseNoSearchResults = false; window.nuBeforeSave = null; window.nuAfterSave = null; window.nuBeforeDelete = null; window.nuAfterDelete = null; window.nuOnSearchAction = null; window.nuOnClone = null; window.nuOnEditorLoad = null; window.nuOnBeforeGetBreadcrumb = null; window.nuOnSetSaved = null; window.nuOnTabSelected = null; window.nuOnSelectTab = null; window.nuOnAddAction = false; window.onSubformTitleClick = null; window.nuOnMessage = null; window.nuFormatValueCleared = null; window.nuDisplayObjectRefreshed = null; window.nuOnSetCalendarOptions = null; window.nuOnLookupPopulated = null; window.nuCalculated = null; window.nuOnPropertySet = null; window.nuEnableCalculation = null; window.nuPortraitScreenShowTabTitles = true; window.nuBrowseFunction = window.nuDefaultBrowseFunction; window.nuCLONE = false; window.nuSERVERRESPONSELU = []; window.nuSESSION = f.session_id; window.nuSUBFORMROW = []; window.nuHASH = []; //-- remove any hash variables previously set. window.nuTABHELP = []; window.nuFORMHELP = []; window.nuLOOKUPSTATE = []; window.nuBROWSEROW = -1; window.nuBROWSECLICKED = false; window.nuUniqueID = 'c' + String(Date.now()); window.global_access = f.global_access == '1'; window.nuVerticalTabs = false; } function nuFormModification() { if (nuFormType() == 'browse') { if (!nuIsIframe()) { $record = $('#nuRECORD'); $record.css({ 'width': '99.7vw', 'height': '80vh', 'overflow-x': 'auto', 'overflow-y': 'auto' }); $('#nuActionHolder').css({ 'width': '100vw' }); $('.nuBrowseTitle, .nuBrowseTitleMultiline').wrapAll('
'); nuBrowseStickyColumns($record); document.body.style.overflow = 'hidden'; } } else { document.body.style.overflow = 'visible'; } } function nuCloseAfterSave() { if (window.nuCloseAfterSaveGlobal) { if (!window.nuCloseAfterSaveGlobal(doClose)) { return false; } } nuDelay(100).then(() => { nuHasNotBeenEdited(); if (nuIsIframe()) { nuClosePopup(); } else { if (! nuOpenPreviousBreadcrumb()) { window.close(); } } }) return true; } function nuBrowseStickyColumns($record) { $record.on("scroll", function () { const scrollLeft = $record.scrollLeft(); const scrollTop = $record.scrollTop(); if (scrollTop >= 0 && scrollLeft >= 0) { $('#btitle').css({ 'z-index': '95', 'position': 'fixed', 'left': 5 - scrollLeft + 'px' }); $('.nuBrowseTitle').css({ 'top': '0', 'height': '28px' }); $('.nuBrowseTitleMultiline').css({ 'top': '0', 'height': '48px' }); } else { $('#btitle').css({ 'z-index': '0', 'position': 'absolute' }); $('.nuBrowseTitle,.nuBrowseTitleMultiline ').css({ 'top': '3px' }); } }); } function nuBrowseRowsPerPageFilter(rowsPerPageOptions) { if (nuFormType() !== 'browse') return; const selectId = 'nuBrowseRowsPerPage'; const hashCookie = 'ROWS_PER_PAGE'; const selectStyle = 'margin-left: 20px; width: 50px; height: 22px; text-align: left'; const selectElement = $(``); selectElement.attr('title', nuTranslate('Number of Rows')); selectElement.append($(``)); rowsPerPageOptions = rowsPerPageOptions || [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200]; for (let optionValue of rowsPerPageOptions) { $(``).appendTo(selectElement); } selectElement.insertBefore('#nuSearchField'); selectElement.on("change", function() { nuSetProperty('page_number', 0); nuSetProperty(hashCookie, this.value); nuSearchAction(); }); selectElement.val(nuGetProperty(hashCookie) ?? ''); } function nuPrintIncludeColumns($arr) { nuSetProperty('nuPrintincludedColumns', nuEncode($arr)); } function nuRestoreScrollPositions() { $(function () { $('textarea').each(function () { const position = window['nuScrollTop_' + this.id] || 0; $(this).scrollTop(position); }); }); } function nuSaveScrollPositions() { $('textarea:visible').each(function () { window['nuScrollTop_' + this.id] = $(this).scrollTop(); }); } function nuEvaluateOnLoadEvents() { const serverResponse = JSON.parse(JSON.stringify(nuSERVERRESPONSE)); for (const obj of serverResponse.objects) { if (obj.js.length > 0) { for (const jsEvent of obj.js) { if (jsEvent.event === 'onnuload') { let modifiedJS = jsEvent.js .replaceAll('(this)', `("#${obj.id}")`) .replaceAll('this.', `${obj.id}.`); eval(modifiedJS); } } } } } function nuDisplayLoggedInUser() { let u = nuGlobalAccess() ? nuCurrentProperties().user_id : nuUserName(); $('.nuBuilderLink').html(u).attr('href', '').css({ 'cursor': 'pointer', 'pointer-events': 'none' }); } function nuAddHomeLogout() { if (nuMainForm()) { if (window.nuFORM.breadcrumbs.length > 1) { const div = nuCreateElementWithId('div', 'nuBreadcrumb0', 'nuBreadcrumbHolder'); $(div) .addClass('nuBreadcrumb') .css('cursor', "pointer") .css('font-size', '16px') .attr('onclick', "nuGetBreadcrumb(0)") .html('') .attr('title', nuTranslate('Home')); } if (!nuIsMobile() || $('.nuBreadcrumb').length == 0) { $('#nuBreadcrumbHolder').append('nuBuilder'); nuAddIconToBreadCrumb('nuLogout', 'Log out', 16, 'nuAskLogout()', 'fas fa-sign-out-alt'); } } } function nuAddIconToBreadCrumb(id, title, right, handler, iconClass) { const div = nuCreateElementWithId('div', id, 'nuBreadcrumbHolder'); $(div) .addClass('nuBreadcrumbIcon') .attr('onclick', handler) .css('right', right) .html(``) .attr('title', nuTranslate(title)); } function nuAddedByLookup(f) { const isEdit = nuFormType() == 'edit'; const isNewRecord = window.nuLASTRECORD == '-1'; const isLookup = window.nuTARGET != ''; if (isEdit && isNewRecord && isLookup) { window.parent.nuGetLookupId(nuRecordId(), window.nuTARGET); //-- called from parent window } } function nuSetBody(f) { let $body = $('body'); $body.html(''); $body.removeClass('nuBrowseBody nuEditBody'); if (nuFormType() == 'browse') { $body.addClass('nuBrowseBody'); } else { var height = f.dimensions === null ? 0 : f.dimensions.edit.height; $body.addClass('nuEditBody') .css('width', window.innerWidth - 1) .css('height', height); } } function nuCSSPropertySum(id, arr) { let elem = document.getElementById(id); if (!elem) { return 0; } let sum = 0; arr.forEach(function(property) { sum += parseInt(getComputedStyle(elem).getPropertyValue(property), 10); }); return sum; } function nuDialogHeadersHeight() { let height = 0; const arr = [ "nuBreadcrumbHolder", "nuActionHolder", "nuTabHolder", "nuBrowseTitle0", "nuBrowseFooter", ]; arr.forEach(function(elem) { height += nuTotalHeight(elem); }); return height; } function nuTotalHeight(id) { const arrProperties = [ "height", "padding-top", "padding-bottom", "border-top-width", "border-bottom-width", "margin-top", "margin-bottom", ]; return nuCSSPropertySum(id, arrProperties); } function nuTotalWidth(id) { const arrProperties = [ "width", "padding-left", "padding-right", "border-left-width", "border-right-width", "margin-left", "margin-right", ]; return nuCSSPropertySum(id, arrProperties); } function nuTotalHolderWidth(id) { const arrProperties = [ "padding-left", "padding-right", "border-left-width", "border-right-width", "margin-left", "margin-right", ]; return nuCSSPropertySum(id, arrProperties); } function nuDefine(v, defaultValue = '') { if (v === undefined) { v = defaultValue; } return v; } function nuSearchFieldSetSearchType(isMobile) { $("#nuSearchField") .prop("type", "search") .attr('autocomplete', 'off') .on('search', function () { nuSearchAction(); }); } function nuAddActionButtons(form) { let draggable = 0; const r = nuRecordId(); if (r == '-2') { draggable = 1; } var button = form.buttons; if (nuFormType() == 'browse') { var s = nuDefine(nuFORM.getProperty('search')); var f = nuDefine(nuFORM.getProperty('filter')); const isMobile = nuIsMobile(); $('#nuActionHolder').append("") .append(""); const searchCaption = isMobile ? "" : " " + nuTranslate('Search'); const printCaption = isMobile ? "" : nuTranslate('Print'); const addCaption = isMobile ? "" : nuTranslate('Add'); nuAddActionButton("Search", "" + searchCaption, 'nuSearchAction()'); if (button.Add == 1) { nuAddActionButton('Add', addCaption, 'nuAddAction()'); } if (button.Print == 1 && nuFORM.getCurrent().browse_rows.length > 0) { nuAddActionButton('Print', printCaption, 'nuPrintAction()'); } nuSearchFieldSetSearchType(isMobile); } else { if (!draggable) { if (button.Save == 1 && form.form_type != 'launch') { if ((nuIsNewRecord() && form.data_mode == 0) || form.data_mode != 0) { nuAddActionButton('Save'); } } if (r != -1) { if (button.Delete == 1) { nuAddActionButton('Delete'); } if (button.Clone == 1) { nuAddActionButton('Clone'); } } if (button.RunHidden != '') { nuAddActionButton('runhidden', 'Run', button.RunHidden); } if (button.Run != '') { nuAddActionButton('run', 'Run', button.Run); } } } } function nuAddActionButton(id, value, func, text, e) { if (arguments.length == 1) { value = id; func = 'nu' + id + 'Action()'; } if (typeof(value) == 'object') { value = nuUXOptions.nuMobileView ? value.valueMobile : nuTranslate(nuDefine('value')); } else { value = nuTranslate(nuDefine(value)); } text = nuTranslate(nuDefine(text)); let nuClass = "nuActionButton"; if (id == 'Save' || id == 'Add' || id == 'Clone' || id == 'Delete') { nuClass += " " + "nu" + id + "Button"; } id = "nu" + id + "Button"; let html = `"; if (e) { $(html).insertAfter('#' + e); } else { $('#nuActionHolder').append(html); } return $('#' + id); } function nuAddActionButtonSaveClose(caption) { nuAddActionButton('SaveClose', nuTranslate(caption === undefined ? 'Save & Close' : caption), "nuSaveAction(true)", '', 'nuSaveButton'); $('#nuSaveCloseButton').addClass('nuSaveButton'); } function nuIsDraggable() { return nuRecordId() == '-2'; } function nuBuildEditObjects(formObj, p, o, prop) { if (typeof (formObj.objects) != 'object') { return; } var left = 3; const isDraggable = nuIsDraggable(); for (let objIndex = 0; objIndex < formObj.objects.length; objIndex++) { if (isDraggable) { $("body").css("overflow", "hidden"); left = left + nuDRAG(formObj, objIndex, left, p, prop); } else { var obj = prop.objects[objIndex]; var t = obj.type; formObj.objects[objIndex].parent_type = o == '' ? '' : o.subform_type; const typeFunctionMap = { 'input': nuINPUT, 'display': nuINPUT, 'lookup': nuINPUT, 'textarea': nuINPUT, 'calc': nuINPUT, 'run': nuRUN, 'html': nuHTML, 'contentbox': nuCONTENTBOX, 'editor': nuEDITOR, 'image': nuIMAGE, 'select': nuSELECT, 'subform': nuSUBFORM, 'word': nuWORD }; // Execute the function based on the type if (typeFunctionMap[t] && (t !== 'subform' || p === '')) { left += typeFunctionMap[t](formObj, objIndex, left, p, prop); } if (obj.labelOnTop) { $('#' + obj.id).nuLabelOnTop(); } const tableColumn = formObj.objects[objIndex].table_column; $('#' + p + obj.id).attr('data-nu-table-column', tableColumn); if (obj.visible === false) { nuHide(obj.id); } nuAddAttributes(p + obj.id, obj.attributes); left = left + 2; } } } function nuAddJSObjectEvents(id, events) { const element = document.getElementById(id); for (let eventObj of events) { let code = element.getAttribute(eventObj.event) || ''; let ev = eventObj.event; if (['beforeinsertrow', 'afterinsertrow', 'clickdelete'].includes(ev)) { ev = 'data-nu-' + ev; } else if (element.classList.contains('nuLookupCode') && ev === 'onclick') { continue; } else if (element.classList.contains('nuLookupButton') && ev !== 'onclick') { continue; } code += ';' + eventObj.js; element.setAttribute(ev, code); } if (element.tagName === "BUTTON") { let ele = $(element); var existingOnclick = ele.attr('onclick'); if (existingOnclick) { const newOnclick = `if (nuIsDisabled(this.id)) return; ${existingOnclick}`; ele.attr('onclick', newOnclick); } } } function nuRecordProperties(w, p, l) { var del = p + 'nuDelete'; var sf = p.substr(0, p.length - 3); const chk = nuCreateElementWithId('input', del); chk.setAttribute('title', nuTranslate('Delete This Row When Saved')); chk.setAttribute('type', w.deletable == '0' ? 'text' : 'checkbox'); chk.setAttribute('onclick', 'nuChange(event)'); $('#' + p + 'nuRECORD') .append(chk) .addClass('nuSection') .attr('data-nu-form-id', w.id) .attr('data-nu-table', w.table) .attr('data-nu-primary-key', w.record_id) .attr('data-nu-foreign-key', w.foreign_key) .attr('data-nu-foreign-field', p == '' ? '' : w.foreign_key_name); var objDel = $('#' + del); objDel .attr('data-nu-data', '') .addClass('nuSubformCheckbox') .addClass(w.table); if (arguments.length == 3) { objDel .prop('checked', w.record_id == -1) .attr('data-nu-checkbox', w.deletable == '0' ? '' : sf) .css({ 'top': 3, 'left': Number(l) + 2, 'position': 'absolute', 'visibility': 'visible' }); if (w.deletable == '0') { objDel.css({ 'width': 0, 'height': 0, 'left': -10, 'top': 10, 'tabindex': '-1' }); //-- allows tabbing when there is no checkbox. } } else { objDel.css('visibility', 'hidden') .prop('checked', false) .attr('data-nu-checkbox', sf); } } function nuDRAG(w, i, l, p, prop) { const obj = prop.objects[i]; const id = p + obj.id; const nuObjectType = p + obj.type; let tagType = 'div'; if (nuObjectType == 'textarea' || nuObjectType == 'input') { tagType = nuObjectType; } const drgDiv = nuCreateElementWithId(tagType, id, p + 'nuRECORD'); let $id = $(drgDiv); nuSetObjectBounds(drgDiv, obj.top, obj.left, obj.width, obj.height) .css({ 'text-align': obj.align, 'overflow': 'hidden', 'display': 'flex', 'align-items': 'center', 'padding-left': '4px', 'cursor': 'pointer', 'caret-color' : 'transparent' }).addClass('nu_' + nuObjectType); if (obj.read == '2') { // hidden $id.addClass('nuDragHidden').css('visibility', 'hidden') } $id.attr('data-drag', 1) .attr('data-nu-object-id', obj.object_id); if (tagType == 'div') { $id.text(id); } else { $id.val(id).attr('spellcheck','false').prop('readonly', true); } if (obj.input == 'button' || nuObjectType == 'run') { $id.attr('data-drag-button-label', obj.label); } if (obj.input != 'button' && nuObjectType != 'run' && nuObjectType != 'contentbox' && prop.title !== 'Insert-Snippet') { //-- Input Object let lab = nuLabel(w, i, p, prop); $(lab).addClass('nuDragLabel').css('visibility', 'hidden'); } nuAddDataTab(id, obj.tab, p); return Number(obj.width); } function nuGetDBColumnLengh(tableName, id) { const tableSchema = nuSERVERRESPONSE?.tableSchema; if (!tableSchema || !tableName || !tableSchema[tableName]) return 0; const columnIndex = tableSchema[tableName].names.indexOf(id); if (columnIndex === -1) return 0; const dataType = tableSchema[tableName].types[columnIndex].toUpperCase(); switch (dataType) { case "TINYTEXT": return 255; case "TEXT": return 65535; case "MEDIUMTEXT": return 16777215; default: if (dataType.includes('CHAR')) { return parseInt(dataType.match(/\d+/), 10) || 0; } return 0; } } function nuINPUTfileDatabase($formId, obj, id, p) { const newElement = nuCreateElementWithId('textarea', id); $formId.append(newElement); const $id = $(newElement); $id .css('visibility', 'hidden') .attr('data-nu-field', id) .attr('data-nu-prefix', p) .attr('data-nu-data', '') .attr('onchange', 'this.className = "nuEdited"'); if (!nuIsNewRecord()) { $id.val(obj.value); } return id + '_file'; } function nuINPUTfileFileSystem($formId, w, i, l, p, prop, id) { var obj = prop.objects[i]; id = id !== undefined ? id : p + obj.id; nuCreateElementWithId('div', 'nuBreadcrumb0', p + 'nuRECORD'); obj = nuLabelOrPosition(obj, w, i, l, p, prop); nuAddDataTab(id, obj.tab, p); let html = w.objects[i].html; html = html.replaceAll('#uppy_div#', id + '_uppy_div'); html = html.replaceAll('#this_object_id#', id); html = html.replaceAll('nuInitUppy()','nuInitUppy' + '_' + id + '()'); html = html.replaceAll('.cssNumber(','.nuCSSNumber('); html = html.replaceAll('new Uppy.Core()','new Uppy.Uppy()'); nuSetObjectBounds($('#' + id), obj.top, obj.left, obj.width, obj.height) .addClass('nuFileUppy').html(html); nuSetAccess(id, obj.read); nuAddStyle(id, obj); return Number(obj.width); } function nuINPUTInput(inp, inputType, obj, objectType) { inp.setAttribute('type', inputType); const className = objectType == 'lookup' ? 'nuHiddenLookup' : 'input_' + inputType; inp.classList.add(className); if (obj.datalist !== null && obj.datalist !== '' && typeof obj.datalist !== "undefined") { let dl = obj.datalist; if (!Array.isArray(dl)) dl = JSON.parse(dl); if (!Array.isArray(dl)) dl = eval(dl); nuAddDatalist(inp.id, dl); } } function nuINPUTnuScroll($id, thisObj) { const inputJS = 'nuFORM.scrollList(event, ' + thisObj.scroll + ')'; $id.addClass('nuScroll') .attr('onkeydown', inputJS) .attr("title", nuTranslate('Use the keyboard up and down arrows to scroll through the list or add text that is not in the list.')); } function nuINPUTnuDate($id, thisObj) { $id.addClass('nuDate') .attr('data-nu-format', thisObj.format) .attr('autocomplete', 'off'); } function nuINPUTnuNumber($id, thisObj) { $id.addClass('nuNumber') .attr('data-nu-format', thisObj.format); } function nuINPUTCheckbox($id, thisObj, obj) { document.getElementById($id.attr('id')).checked = (thisObj.value == '1'); if (obj.parent_type == 'g') { $id.css('margin-top', '1px'); } } function nuINPUTDisplay($id) { nuDisable($id.attr('id')); } function nuINPUTLookup(id, objId, thisObj, obj, $formId, p, vis) { let $id = $('#' + id); $id.hide(); $id.attr('data-nu-lookup-id', ''); const luv = thisObj.values[0][1]; if (!nuIsNewRecord() || luv !== '') { $('#' + id).val(luv); } const target = id; id = target + 'code'; const inp = nuCreateElementWithId('input', id); $formId.append(inp); nuAddDataTab(id, obj.tab, p); $id = $('#' + id); nuSetObjectBounds($id, obj.top, obj.left, obj.width, obj.height) .attr('data-nu-form-id', thisObj.form_id) .attr('data-nu-object-id', thisObj.object_id) .attr("data-nu-prefix", p) .attr('data-nu-target', target) .attr('data-nu-type', 'lookup') .attr('data-nu-subform-sort', 1) .attr('onchange', 'nuGetLookupCode(event)') .attr('onfocus', 'nuLookupFocus(event)') .css('visibility', vis) .addClass('nuLookupCode'); nuAddJSObjectEvents(id, obj.js); if (Number(obj.width) == 0) nuHide(id); $id.nuEnterKey(function () { if ($(this).val().length == 0) { let element = $('#' + target + 'button')[0]; nuBuildLookup(element, ""); } }); thisObj.values[0][0] = p + obj.id; thisObj.values[1][0] = p + obj.id + 'code'; thisObj.values[2][0] = p + obj.id + 'description'; id = target + 'button'; const div = nuCreateElementWithId('div', id); $formId.append(div); nuAddDataTab(id, obj.tab, p); var luClass = obj.label === 'Insert-Snippet' ? 'fa fa-code' : 'fa fa-search'; nuSetObjectBounds(div, obj.top, Number(obj.left) + Number(obj.width) + 6, 15, Number(obj.height - 2)) .attr('type', 'button') .attr("data-nu-prefix", p) .attr('data-nu-form-id', thisObj.form_id) .attr('data-nu-object-id', thisObj.object_id) .attr('data-nu-target', target) .attr('data-nu-subform-sort', 1) .attr('onfocus', 'nuLookupFocus(event)') .attr('onclick', 'nuBuildLookup(this,"")') .addClass('nuLookupButton') .html('') .css('visibility', vis); if (obj.label === 'Insert-Snippet') $('#' + id).css('font-size', '18px'); nuAddJSObjectEvents(id, obj.js); id = p + obj.id + 'description'; const desc = nuCreateElementWithId('input', id); $formId.append(desc); $formId.append(desc); nuAddDataTab(id, obj.tab, p); $('#' + id).css({ 'top': obj.mobile ? Number(obj.top) + Number(obj.height) + 5 : Number(obj.top), 'left': obj.mobile ? Number(obj.left) : Number(obj.left) + Number(obj.width) + 25, 'width': obj.mobile ? Number(obj.width) : obj.description_width, 'visibility': obj.description_width == 0 || obj.display == 0 ? 'hidden' : 'visible', 'height': Number(obj.height) }) .attr("data-nu-prefix", p) .addClass('nuLookupDescription') .nuDisable(); nuPopulateLookup3(thisObj.values, p); nuSetAccess(objId, obj.read); nuAddStyle(id, obj); return Number(obj.width) + Number(obj.description_width) + 30; } function nuINPUTnuAutoNumber($id, obj) { nuDisable($id.attr('id')); if (!nuIsNewRecord()) { $id.val(obj.counter); } } function nuINPUTCalc($id, thisObj, p) { const formula = String(thisObj.formula).nuReplaceAll("al('", "al('" + p); $id.addClass('nuCalculator') .attr('data-nu-format', thisObj.format) .attr('data-nu-calc-order', thisObj.calc_order) .attr('data-nu-formula', formula) .nuDisable(); if (p != '') { $id.addClass('nuSubformObject'); } } function nuINPUTSetValue($id, thisObj, inputType) { if (inputType == 'button') { $id.html(nuTranslate(thisObj.value)); $id.attr("data-nu-org-label", thisObj.value); } else { if (inputType == 'datetime-local') { //-- replace ' ' between date and time with 'T' thisObj.value = thisObj.value === null ? null : thisObj.value.replace(' ', 'T'); } if (!nuIsNewRecord() || thisObj.value !== '') { $id.val(nuFORM.addFormatting(thisObj.value, thisObj.format)); } } } function nuIPUTNuChangeEvent(obj, inputType, objectType) { let change = 'nuChange(event)'; if (inputType == 'file' && obj.file_target == '1') { change = ''; } else if (inputType == 'file') { change = 'nuChangeFile(event)'; } else if (objectType == 'lookup') { change = 'nuGetLookupId(this.value, this.id)'; } return change; } function nuINPUTSetProperties($id, obj, inputType, objectType, thisObj, p) { const leftInc = inputType == 'button' && p != '' ? 3 : 0; $id.css({ 'top': Number(obj.top), 'left': Number(obj.left) + leftInc, 'width': Number(obj.width), 'height': Number(obj.height), 'text-align': obj.align, 'position': 'absolute' }) .attr('onchange', nuIPUTNuChangeEvent(obj, inputType, objectType)) .attr('data-nu-field', inputType == 'button' || inputType == 'file' ? null : obj.id) .attr('data-nu-object-id', thisObj.object_id) .attr('data-nu-format', '') .attr('data-nu-prefix', p) .attr('data-nu-type', objectType) .attr('data-nu-subform-sort', 1) .attr('data-nu-label', thisObj.label) .attr('onfocus', 'nuLookupFocus(event)'); if (inputType != 'button') { $id.attr('data-nu-data', ''); } else { $id.addClass('nuButton'); } if (thisObj.value != '' && nuRecordId() == '-1') { //== check for Cannot be left blank $id.addClass('nuEdited'); } } function nuINPUTSetMaxLength($id, inputType, objectType, w) { const types = ['text', 'url', 'telephone', 'search', 'password', 'month', 'email', 'color', 'nuScroll'].indexOf(inputType) !== -1; if ((types && objectType == 'input') || objectType == 'textarea') { const field = $id.attr('data-nu-field'); const len = nuGetDBColumnLengh(w.table, field); if (len !== 0) $id.attr('maxlength', len); } } function nuINPUT(formObj, index, layer, prefix, properties) { var obj = properties.objects[index]; const thisObj = formObj.objects[index]; const objectId = prefix + obj.id; const formId = $('#' + prefix + 'nuRECORD'); let inputElementType = obj.type !== 'textarea' ? 'input' : 'textarea'; const visibility = obj.display === 0 ? 'hidden' : 'visible'; const inputType = obj.input; let objType = obj.type; const isFileInputWithTarget = inputType === 'file' && obj.file_target === '1'; if (inputElementType === 'input' && isFileInputWithTarget) { inputElementType = 'div'; } obj = nuLabelOrPosition(obj, formObj, index, layer, prefix, properties); let elementId = objectId; if (inputElementType === 'input' && inputType === 'file' && !isFileInputWithTarget) { elementId = nuINPUTfileDatabase(formId, obj, objectId, prefix); } const htmlElementType = inputType === 'button' && objType === 'input' ? 'button' : inputElementType; const element = nuCreateElementWithId(htmlElementType, elementId, formId.attr('id')); const $id = $(element); nuAddDataTab(elementId, obj.tab, prefix); nuINPUTSetProperties($id, obj, inputType, objType, thisObj, prefix); if (inputElementType === 'input' && !isFileInputWithTarget) { nuINPUTInput(element, inputType, obj, objType); } if (isFileInputWithTarget) { nuINPUTfileFileSystem(formId, formObj, index, layer, prefix, properties, elementId); } nuApplyInputTypeSpecificBehaviors($id, inputType, objType, thisObj, obj, prefix); if (objType !== 'lookup') { nuINPUTSetMaxLength($id, inputType, objType, formObj); nuAddJSObjectEvents(elementId, obj.js); nuSetAccess(objectId, obj.read); nuAddStyle(elementId, obj); return Number(obj.width) + (obj.read === 2 ? -2 : 4); } else { return nuINPUTLookup(elementId, objectId, thisObj, obj, formId, prefix, visibility); } } function nuApplyInputTypeSpecificBehaviors($id, inputType, objType, thisObj, obj, prefix) { switch (inputType) { case 'nuScroll': nuINPUTnuScroll($id, thisObj); break; case 'nuDate': nuINPUTnuDate($id, thisObj); $id.attr('onclick', 'nuPopupCalendar(this);'); break; case 'nuNumber': nuINPUTnuNumber($id, thisObj); break; case 'checkbox': nuINPUTCheckbox($id, thisObj, obj); break; case 'text': if (objType === 'display') { nuINPUTDisplay($id); } break; default: // ... break; } if (objType === 'calc') { nuINPUTCalc($id, thisObj, prefix); } if (inputType !== 'file') { nuINPUTSetValue($id, thisObj, inputType); } if (thisObj.input === 'nuAutoNumber') { nuINPUTnuAutoNumber($id, thisObj); } if (inputType == 'button' && objType == 'input') { nuAddInputIcon($id.attr('id'), thisObj.input_icon); } } function nuAddAttributes(id, attr) { if (attr !== undefined && attr !== null && attr !== '') { attr.trim().replace(/\"/g, "").split(",").forEach(attr => { const arr = attr.split('='); let key; let value; if (arr.length == 2) { [key, value] = arr; } else if (arr.length == 1) { key = attr; value = ''; } if (arr.length == 1 || arr.length == 2) { if (key.trim() === 'nu-label-position' && value === 'top') { $('#' + id).nuLabelOnTop(); } else { $('#' + id)[0].setAttribute(key.trim(), value); } } }); } } function nuAddInputIcon(id, icon) { function addIcon(idIcon, string, after) { if (string.startsWith('fa')) { nuAttachFontAwesome(idIcon, string, 'normal', after); } else { nuAttachHTML(idIcon, string, after); } } if (icon !== undefined && icon !== null && icon !== '' && !nuUserA11Y()) { if (!icon.includes('|')) { addIcon(id, icon, false); } else { let icons = icon.split('|'); if (icons[0].trim() !== '') addIcon(id, icons[0], false); if (icons[1].trim() !== '') addIcon(id, icons[1], true); } } } function nuAddStyleFromArray(id, obj) { var arr = JSON.parse(obj.style); for (let key in arr) { if (Object.prototype.hasOwnProperty.call(arr, key)) { let obj2; if (key == 'label') { obj2 = $('#' + 'label' + '_' + id); } else { obj2 = $('#' + id + ' .' + key); if (obj2.length === 0) { obj2 = $('#' + id); } } if (obj.style_type == 'CSS') { let css = obj2[0].getAttribute("style"); css = css === null ? arr[key] : css += ';' + arr[key]; obj2[0].setAttribute("style", css); } else if (obj.style_type == 'Class') { obj2.addClass(arr[key]); } } } } function nuAddStyle(id, obj) { const $id = $('#' + id); if (obj.style_type !== '' && obj.style !== '') { if (obj.style_type == 'CSS') { if (obj.style.startsWith('{')) { nuAddStyleFromArray(id, obj); } else { let css = $('#' + id)[0].getAttribute("style"); css = css === null ? obj.style : css += obj.style; $id[0].setAttribute("style", css); } } else if (obj.style_type == 'Class') { if (obj.style.startsWith('{')) { nuAddStyleFromArray(id, obj); } else { $id.addClass(obj.style); } } } } function nuLookupFocus(e) { const objT = $(e.target); const p = objT.attr('data-nu-prefix'); const t = objT.attr('data-nu-type'); window.nuSubformRow = Number(p.substr(p.length - 3)); if (t != 'textarea') { objT.trigger( "select" ); } } function nuCurrentRow() { return window.nuSubformRow; } function nuSetAccess(id, r) { if (r == 2 || r == 3 || r == 4) { // hidden const o = [id, id + 'code', id + 'button', id + 'description', 'label_' + id]; for (let c = 0; c < o.length; c++) { if (r == 2 || ((r == 3 || r == 4) && !nuGlobalAccess())) { $('#' + o[c]) .attr('data-nu-tab', 'x') .hide(); } else if ((r == 3 || r == 4) && !(o[c].startsWith('label_') || o[c].endsWith('button'))) { $('#' + o[c]).addClass('nuAccessHiddenUser'); } } } if (r == 1 || r == 4) { nuDisable(id); } $('#' + id).attr('data-nu-access', r); } function nuLabelOrPosition(obj, w, i, l, p, prop) { if (obj.parent_type == 'g') { obj.left = l; obj.top = 3; } else { if (obj.input != 'button' && prop.title !== 'Insert-Snippet') { //-- Input Object nuLabel(w, i, p, prop); } } return obj; } function nuSetObjectBounds(obj, top = null, left = null, width = null, height = null, absolute = null) { obj = obj.jquery ? obj[0]: obj; if (top !== null) obj.style.top = top + 'px'; if (left !== null) obj.style.left = left + 'px'; if (height !== null) obj.style.height = height + 'px'; if (width !== null) obj.style.width = width + 'px'; if (absolute || absolute === null) obj.style.position = 'absolute'; return $(obj); } function nuHTML(w, i, l, p, prop, id) { let obj = prop.objects[i]; id = id !== undefined ? id : p + obj.id; const div = nuCreateElementWithId('div', id, p + 'nuRECORD'); obj = nuLabelOrPosition(obj, w, i, l, p, prop); nuAddDataTab(id, obj.tab, p); nuSetObjectBounds(div, obj.top, obj.left, obj.width, obj.height) .addClass('nuHtml').html(w.objects[i].html); nuSetAccess(id, obj.read); nuAddStyle(id, obj); return Number(obj.width); } function nuEDITOR(w, i, l, p, prop) { const obj = prop.objects[i]; prop.objects[i].type = 'textarea'; nuINPUT(w, i, l, p, prop); $('#' + obj.id).addClass('nuEditor'); const id = obj.id + '_parent_container'; nuHTML(w, i, l, p, prop, id); $('#' + id).html('
'); nuAddStyle(id, obj); return Number(obj.width); } function nuCONTENTBOX(w, i, l, p, prop) { const obj = prop.objects[i]; const id = p + obj.id; const div = nuCreateElementWithId('div', id, p + 'nuRECORD'); nuAddDataTab(id, obj.tab, p); nuSetObjectBounds(div, obj.top, obj.left, obj.width, obj.height).css('z-index', '-1') .attr('data-nu-object-id', w.objects[i].object_id) .attr('data-nu-prefix', p) .addClass('nuContentBoxContainer').html(w.objects[i].html); if (nuGlobalAccess()) { $('#label_' + id).attr('ondblclick', 'nuOptionsListAction("nuobject", "' + obj.object_id + '")'); } nuSetAccess(id, obj.read); nuAddStyle(id, obj); return Number($(div).width()); } function nuIMAGE(w, i, l, p, prop) { let obj = prop.objects[i]; const id = p + obj.id; const img = nuCreateElementWithId('img', id, p + 'nuRECORD'); obj = nuLabelOrPosition(obj, w, i, l, p, prop); nuAddDataTab(id, obj.tab, p); let $img = $(img); nuSetObjectBounds(img, obj.top, obj.left, obj.width).addClass('nuImage'); if (obj.height !== "-1" && obj.width !== "-1") { nuSetObjectBounds($img, null, null, obj.width, obj.height) } $img.attr('src', atob(w.objects[i].src)); nuSetAccess(id, obj.read); nuAddJSObjectEvents(id, obj.js); nuAddStyle(id, obj); return Number($img.width()); } function nuWORD(w, i, l, p, prop) { const obj = prop.objects[i]; const id = p + obj.id; const div = nuCreateElementWithId('div', id, p + 'nuRECORD'); nuAddDataTab(id, obj.tab, p); let t = w.objects[i].word; const r = /(.*?)<\/n>/g.exec(t); t = r === null ? t : r[1]; let $div = $(div); nuSetObjectBounds(div, obj.top, obj.left, obj.width, obj.height) .css('text-align', obj.align) .addClass('nuWord') .html(nuTranslate(t)); if (nuGlobalAccess()) { $div.attr('ondblclick', 'nuOptionsListAction("nuobject", "' + obj.object_id + '")'); } if (r !== null) { $div.css('font-weight', 'normal'); } nuAddInputIcon(id, obj.input_icon); nuSetAccess(id, obj.read); nuAddStyle(id, obj); return Number(obj.width); } function nuRUNGetOnClickEvent(obj) { let result = ''; const runTarget = obj.run_target || '0'; const stopClick = runTarget == '0' ? 'nuStopClick(event);' : ''; const jsPopup = `nuPopup('${obj.form_id}','${obj.record_id}','${obj.filter}')`; const jsForm = `nuForm('${obj.form_id}','${obj.record_id}','${obj.filter}', '','${runTarget}')`; const runAction = runTarget == '3' ? jsPopup : jsForm; const runType = obj.run_type; if (runType == 'F') { result = stopClick + runAction; } else if (runType == 'R') { result = "nuRunReport('" + obj.record_id + "')"; } else if (runType == 'P') { result = obj.run_hidden ? `nuRunPHPHidden('${obj.record_id}')` : `nuRunPHP('${obj.record_id}')`; } return result; } function nuRUN(w, i, l, p, prop) { let obj = prop.objects[i]; let id = p + obj.id; let tagName = 'button'; if (obj.parent_type == 'g') { obj.left = l; obj.top = 3; } if (obj.run_method != 'b') { tagName = 'iframe'; if (obj.parent_type !== 'g') { nuLabel(w, i, p, prop); } } const div = nuCreateElementWithId(tagName, id, p + 'nuRECORD'); const $div = $(div); nuAddDataTab(id, obj.tab, p); nuSetObjectBounds(div, obj.top, obj.left, obj.width, obj.height).css('text-align', obj.align) .attr('data-nu-object-id', w.objects[i].object_id) .attr('data-nu-prefix', p); if (obj.run_method == 'b') { $div.attr({ 'type': 'button', 'value': nuTranslate(obj.label), 'onclick': nuRUNGetOnClickEvent(obj) }) .html(nuTranslate(obj.label)) .addClass('nuButton'); $('#' + id).attr("data-nu-org-label", obj.label); nuAddInputIcon(id, obj.input_icon); } else { window.nuOPENER.push(new nuOpener(obj.run_type, obj.form_id, obj.record_id, obj.filter, obj.parameters)); const open = window.nuOPENER[window.nuOPENER.length - 1]; const url = window.location.pathname + '?i=2&opener=' + open.id; $div.attr('src', url).removeClass('').addClass('nuIframe'); } nuAddJSObjectEvents(id, obj.js); nuSetAccess(id, obj.read); nuAddStyle(id, obj); return Number(obj.width); } function nuSELECT(w, i, l, p, prop) { let obj = prop.objects[i]; const id = p + obj.id; obj = nuLabelOrPosition(obj, w, i, l, p, prop); const sel = nuCreateElementWithId('select', id, p + 'nuRECORD'); let $sel = $(sel); if (w.objects[i].value != '' && nuRecordId() == '-1') { $sel.addClass('nuEdited'); } nuAddDataTab(id, obj.tab, p); if (obj.multiple == 1) { $sel.attr('multiple', 'multiple'); } if (obj.select2 == 1) { let select2Id = nuSetSelect2(id, obj); nuAddDataTab(select2Id, obj.tab, p); }; $sel.css({ 'top': Number(obj.top), 'left': Number(obj.left), 'width': Number(obj.width), 'position': 'absolute' }) .attr('onfocus', 'nuLookupFocus(event)') .attr('onchange', 'nuChange(event)') .attr('data-nu-field', obj.id) .attr('data-nu-object-id', w.objects[i].object_id) .attr('data-nu-format', '') .attr('data-nu-subform-sort', 1) .attr('data-nu-data', '') .attr('data-nu-label', w.objects[i].label) .attr('data-nu-prefix', p); $sel.css('height', Number(obj.height)); var s = String(w.objects[i].value); var a = []; if (w.objects[i].multiple == 0 || w.objects[i].multiple === null) { a = [s]; } // Check if the string starts and ends with '[]' if (/^\[.*\]$/.test(s)) { eval('a = ' + s); } $sel.append(''); let hasSelected = false; if (obj.options !== null) { for (let n = 0; n < obj.options.length; n++) { const opt = String(obj.options[n][1]); // .replaceAll(' ', ' '); if (a.indexOf(String(obj.options[n][0])) == -1) { $sel.append(''); } else { $sel.append(''); hasSelected = true; } } } nuAddJSObjectEvents(id, obj.js); nuSetAccess(id, obj.read); if (obj.read == 1) { nuDisable(id); } nuAddStyle(id, obj); return Number(obj.width); } function nuSUBFORMAddCSS(id, SF) { nuSetObjectBounds($('#' + id), SF.top, SF.left, SF.width, Number(SF.height) + 2) .css({ 'overflow-x': 'hidden', 'overflow-y': 'hidden' }) .attr('data-nu-object-id', SF.object_id) .attr('data-nu-foreign-key-name', SF.foreign_key_name) .attr('data-nu-primary-key-name', SF.primary_key_name) .attr('data-nu-subform', 'true') .attr('data-nu-add', SF.add) .attr('data-nu-delete', SF.delete) .addClass('nuSubform'); } function nuSUBFORMScrollDivAddCSS(id, SF, scrId, rowTop, rowWidth) { nuSetObjectBounds($('#' + scrId), rowTop, 0, Number(rowWidth) + 1, Number(SF.height) - rowTop + 1) .css({ 'border-width': 10, 'overflow-x': 'hidden', 'overflow-y': 'scroll', 'position': 'absolute' }); if (rowWidth > Number(SF.width)) { $('#' + id).css('overflow-x', 'scroll'); $('#' + scrId).css('height', SF.height - rowTop - 25); } } function nuSUBFORMnuTabHolderAddCSS(tabId, rowTop, rowWidth) { nuSetObjectBounds($('#' + tabId), 0, 0, rowWidth, rowTop) .css({ 'overflow-x': 'hidden', 'overflow-y': 'hidden', 'position': 'absolute', 'padding': '12px 0px 0px 0px' }) .addClass('nuTabHolder') .attr('data-nu-subform', tabId) .prepend('   '); } function nuSUBFORMnuRECORDAddCSS(frmId, rowTop, rowWidth, rowHeight, even) { nuSetObjectBounds($('#' + frmId), rowTop, 0, rowWidth, rowHeight) .addClass('nuSubform' + even); } function nuCreateElementWithId(tagName, id, parentElement) { const newElement = document.createElement(tagName); newElement.setAttribute('id', id); if (parentElement !== undefined) { document.getElementById(parentElement).appendChild(newElement); } return newElement; } function nuGetSubformDimensions(SF) { let sfTypeGrid = SF.subform_type == 'g'; let sfType = sfTypeGrid ? 'grid' : 'edit'; let rowHeight = Number(SF.dimensions[sfType].height + (sfTypeGrid ? 0 : 10)); let rowWidth = Number(SF.dimensions[sfType].width + (sfTypeGrid ? 55 : 10)); rowWidth = SF.delete == '1' ? rowWidth - 3 : rowWidth - 25; rowTop = sfTypeGrid ? 52 : 33; return { rowHeight, rowWidth, rowTop }; } function nuSUBFORM(w, i, l, p, prop) { var SF = prop.objects[i]; //-- First row var subformRows = w.objects[i]; //-- All rows let id = p + SF.id; nuCreateElementWithId('div', id, p + 'nuRECORD'); //-- Edit Form Id nuLabelOrPosition(SF, w, i, l, p, prop) nuAddDataTab(id, SF.tab, p); nuSUBFORMAddCSS(id, SF); nuAddJSObjectEvents(id, SF.js); if (SF.forms[0] !== undefined) { nuGetSubformRowSize(SF.forms[0].objects, SF, id); } let sfDimensions = nuGetSubformDimensions(SF); let rowHeight = sfDimensions.rowHeight; let rowWidth = sfDimensions.rowWidth; let rowTop = sfDimensions.rowTop; var tabId = id + 'nuTabHolder'; var tabDiv = document.createElement('div'); tabDiv.setAttribute('id', tabId); $('#' + id).prepend(tabDiv); nuSUBFORMnuTabHolderAddCSS(tabId, rowTop, rowWidth); if (SF.subform_type == 'f') { nuAddEditTabs(id, SF.forms[0]); } else { if (subformRows.forms.length > 0) { let tab0 = subformRows.forms[0].tabs[0]; nuTABHELP[tab0.id] = tab0.help; nuFORMHELP[SF.id] = tab0.help; } } nuOptions(SF.sf_form_id, id, 'subform', w.global_access); var scrId = id + 'scrollDiv'; let scrDiv = nuCreateElementWithId('div', scrId, id); scrDiv.setAttribute('class', 'nuSubformScrollDiv'); nuSUBFORMScrollDivAddCSS(id, SF, scrId, rowTop, rowWidth); rowTop = 0; let prefix; for (var c = 0; c < subformRows.forms.length; c++) { prefix = id + nuPad3(c); const frmId = prefix + 'nuRECORD'; nuCreateElementWithId('div', frmId, scrId); nuSUBFORMnuRECORDAddCSS(frmId, rowTop, rowWidth, rowHeight, c%2 == 0 ? '1' : '0'); nuBuildEditObjects(subformRows.forms[c], prefix, SF, SF.forms[0]); SF.forms[c].deletable = SF.delete == '1' ? '1' : '0'; nuRecordProperties(SF.forms[c], prefix, rowWidth - 40); rowTop = Number(rowTop) + Number(rowHeight); } if (prefix != '') { if (SF.add == 1) { nuNewRowObject(String(prefix)); } else { $('#' + prefix + 'nuRECORD').hide(); } } nuSetAccess(id, SF.read); nuAddStyle(id, SF); return Number(SF.width); } // DEV: function nuWrapWithForm(element, formAction, formMethod) { // 1. Create the form element const form = document.createElement('form'); // form.onsubmit = function() { return false; }; // Add the onsubmit handler form.setAttribute('onsubmit', 'return false'); // Add onsubmit attribute form.id = 'myForm'; // Set the desired ID // form.action = formAction; // form.method = formMethod; // 2. Get the element's parent (to insert the form before it) const parent = element.parentNode; // 3. Insert the form before the original element parent.insertBefore(form, element); // 4. Move the original element inside the form form.appendChild(element); } function nuNewRowObject(p) { const sf = p.substr(0, p.length - 3); if ($('#' + p + 'nuRECORD').length == 0) { return; } let html = document.getElementById(p + 'nuRECORD').outerHTML; window.nuSUBFORMROW[sf] = String(html.nuReplaceAll(p, '#nuSubformRowNumber#', true)); $("[id^='" + p + "']").addClass('nuEdit'); } function nuSubformObject(id) { return nuFORM.subform(id); } function nuSubformRowId(t) { return $(t).parent().attr('data-nu-primary-key'); } function nuSubformRowNumber(id) { return $('#' + id).attr('data-nu-prefix').slice(-3); } function nuSubformRowObject(id, column) { const formCode = $('#' + id).attr('data-nu-form'); return $('#' + formCode + nuSubformRowNumber(id) + column); } function nuSubformValue(t, id) { const p = $(t).attr('data-nu-prefix'); return $('#' + p + id).val(); } function nuSubformColumnArray(id, column, includeDeleted = false) { var a = []; const sf = nuSubformObject(id); const c = Number.isInteger(column) ? column : sf.fields.indexOf(column); for (let i = 0; i < sf.rows.length; i++) { if (sf.deleted[i] == 0 || includeDeleted) { var rv = sf.rows[i][c]; a.push(rv); } } return a; } function nuSubformDisable(sf, ob) { if (ob === undefined || ob === '') { $("[data-nu-form='" + sf + "']").nuDisable(); return; } for (let i = 0; i < nuSubformObject(sf).rows.length; i++) { nuDisable(sf + nuPad3(i) + ob); } } function nuSubformEnable(sf, ob, enable) { if (ob === undefined || ob === '') { $("[data-nu-form='" + sf + "']").nuEnable(enable); return; } for (let i = 0; i < nuSubformObject(sf).rows.length; i++) { nuEnable(sf + nuPad3(i) + ob, enable); } } function nuSubformHide(sf, ob) { if (ob === undefined || ob === '') { $("[data-nu-form='" + sf + "']").nuHide(); return; } for (let i = 0; i < nuSubformObject(sf).rows.length; i++) { nuHide(sf + nuPad3(i) + ob); } } function nuSubformShow(sf, ob, show) { if (ob === undefined || ob === '') { $("[data-nu-form='" + sf + "']").nuShow(true, false); return; } for (let i = 0; i < nuSubformObject(sf).rows.length; i++) { nuShow(sf + nuPad3(i) + ob, show, false); } } function nuSubformHideHeader(id) { const scrollDiv = $('#' + id + 'scrollDiv'); scrollDiv.css({top: 0, height: $('#' + id).nuCSSNumber('height')}); } function nuSubformLastRow(t) { const i = String($('#' + t.id).parent().attr('id')); const p = i.substr(0, i.length - 17); const s2 = parseInt(i.substring(11, 14), 10) + 1; const n = $('#' + p + nuPad3(s) + 'nuRECORD').length; return n == 0; } function nuSubformFocusLastRow(id, f) { const sf = nuSubformObject(id); const c = f === undefined ? sf.fields[1] : sf.fields.indexOf(f); const r = sf.rows.length - 1; $('#' + id + nuPad3(r) + c).trigger("focus"); } function nuSubformSetHeight(i, height, minHeight, maxHeight) { let div = $('#' + i + 'scrollDiv'); let sf = $('#' + i); let h = sf.data('nu-org-height'); if (h === undefined || h === null) { div.data('nu-org-height', div.height()); sf.data('nu-org-height', sf.height()); sf.data('nu-org-z-index', sf.css('z-index')); if (height === undefined || height === null) { h = window.innerHeight - sf.nuCSSNumber('Top') - nuDialogHeadersHeight() - 50; } else { h = height; } if (maxHeight !== undefined && h > maxHeight) h = maxHeight; if (minHeight !== undefined && h < minHeight) h = minHeight; sf.height(h); let hh = $('#' + i + 'nuTabHolder').height() + 1; div.height(h - hh); sf.css('z-index', 1); } else { sf.height(h); div.height(div.data('nu-org-height')); sf.data('nu-org-height', null); sf.css('z-index', div.data('nu-org-z-index')); } } function nuSubformRearrangeColumns(sf, fields, row, maintainWidth) { function obj(p) { return $("[id$='" + p + "']"); } let width = 3; let totalwidth = $('#' + sf).nuCSSNumber('width'); if (row !== '') row = nuPad3(row); nuHide(sf); for (let i = 1; i < fields.length; i++) { let p = row + fields[i][0]; let p0 = '000' + fields[i][0]; if (fields[i][1] == '0') { let h0 = obj(p0); if (!h0.is('[nu-subform-column-hidden]')) { h0.attr('nu-subform-column-hidden', ''); let h = obj(p); totalwidth -= h.nuCSSNumber('width'); h.nuHide(); } } else { if (obj(p0).attr('data-nu-type') == 'lookup') { obj(p + 'code').css('left', width); width = obj('code').nuCSSNumber('width') + width + 6; obj(p + 'button').css('left', width); width += 19; obj(p + 'description').css('left', width); width = obj('description').nuCSSNumber('width') + width + 6; } else { obj(p).css('left', width); width = obj(p0).nuCSSNumber('width') + width + 6; } } } if (maintainWidth !== false) { $('#' + sf + 'scrollDiv').css('width', totalwidth - 1); $('#' + sf).css('width', totalwidth); } nuShow(sf); } function nuSubformHideColumns(sfId, columns, maintainWidth) { let fields = []; nuSubformObject(sfId).fields.forEach(function (col) { fields.push([col, columns.indexOf(col) !== -1 ? '0' : '1']); }); nuSubformRearrangeColumns(sfId, fields, '', maintainWidth); } function nuSubformColumnUnique(id, column, label) { let arr = nuSubformColumnArray(id, column); if (arr.includes('') || !nuArrayIsUnique(arr)) { return nuTranslate(label) + ' ' + nuTranslate('must be both unique and not blank'); } return true; } function nuSubformTitleArray(sfName) { $arr = $('#' + sfName).children().filter('.nuSubformTitle').map(function() { return this.getAttribute("data-nu-field"); }).get(); return $arr; } function nuSubformMoveFocus(activeElement, d) { let row = activeElement.attr('data-nu-prefix').slice(-3); let nextRow = $('#' + activeElement.attr('data-nu-form') + nuPad3(Number(row) + d) + activeElement.attr('id').substr(activeElement.attr('data-nu-form').length + 3)); if (nextRow.length == 1 && !nextRow.prop('disabled')) nextRow.trigger("focus"); return true; } function nuSubformHandleArrowKeyEvent(e) { let activeElement = $(document.activeElement); let nuScroll = activeElement.hasClass('nuScroll'); var result; switch (e.key) { case 'ArrowUp': result = !nuScroll && nuSubformMoveFocus(activeElement, -1); break; case 'Enter': result = nuSubformMoveFocus(activeElement, 1); break; case 'ArrowDown': result = !nuScroll && nuSubformMoveFocus(activeElement, 1); break; default: result = false; } return result; } // Subform filtering function nuSubformAddFilter(filter) { for (const sfName in filter) { if (Object.prototype.hasOwnProperty.call(filter, sfName)) { nuSubformFiltersAdd(sfName, filter[sfName]); } } function nuSubformFilterId(sfName, columnId) { return sfName + columnId + '_filter'; } function nuSubformFilterValue(sfName, columnId, type) { let filterId = nuSubformFilterId(sfName, columnId); return nuGetValue(filterId, type === 'select' ? 'text' : 'value'); } function nuSubformFilterOptionAll(sfName, columnId) { let filterId = nuSubformFilterId(sfName, columnId); return $("#" + filterId + " option:selected").attr('data-nu-all') === 'true'; } function nuSubformFilterArray(sfName, arrColumns) { let arr = {}; let isArray = Array.isArray(arrColumns); for (let columnId in arrColumns) { if (isArray) columnId = arrColumns[columnId]; arr[columnId] = {}; arr[columnId].type = isArray ? 'select' : arrColumns[columnId].type; arr[columnId].value = nuSubformFilterValue(sfName, columnId, arr[columnId].type); arr[columnId].all = nuSubformFilterOptionAll(sfName, columnId); } return arr; } function nuSubformFilterSortOptions(sfName, columnId) { let filterId = nuSubformFilterId(sfName, columnId); $(filterId).html($(filterId + " option:not('[data-nu-persistent]')").sort(function (a, b) { return a.text == b.text ? 0 : a.text < b.text ? -1 : 1; })); } function nuSubformFiltersAdd(sfName, arrColumns) { let isArray = Array.isArray(arrColumns); for (let columnId in arrColumns) { if (Object.prototype.hasOwnProperty.call(arrColumns, columnId)) { if (isArray) columnId = arrColumns[columnId]; const prop = arrColumns[columnId]; const float = prop === undefined || prop.float === undefined ? 'center' : prop.float; let width = $('#' + sfName + '000' + columnId).width() - 3; width = prop === undefined || prop.width === undefined ? width : prop.width; let style = { 'width': width + 'px', 'float': float }; const columnTitle = '#title_' + sfName + columnId; const filterId = nuSubformFilterId(sfName, columnId); const type = prop === undefined || prop.type === undefined ? 'select' : prop.type; let obj = nuSubformFilterAddObject(type, sfName, columnId, filterId, prop); $(columnTitle).append("
"); obj.appendTo(columnTitle).css(style); if (prop !== undefined && prop.placeholder) obj.nuSetPlaceholder(prop.placeholder); } } } function nuSubformFilterAddObject(type, sfName, columnId, filterId, prop) { var obj; if (type == 'select') { obj = nuSubformFilterAddSelect(sfName, columnId, filterId, prop); } else if (type === 'search') { obj = nuSubformFilterAddSearch(sfName, columnId, filterId, prop); } return obj; } function nuSubformFilterAddSelect(sfName, columnId, filterId, prop) { let propAll = prop === undefined || prop.all === undefined ? '(' + nuTranslate('All') + ')' : prop.all; let optionAll = []; if (propAll !== false) optionAll = nuSubformFilterCreateSelectOption('', propAll, true, true, true); let propBlank = prop === undefined || prop.blank === undefined ? true : prop.blank; let optionBlank = []; if (propBlank !== false) optionBlank = nuSubformFilterCreateSelectOption('', '', true, false, false); return $('", { type: "search", class: "nuSubformFilter", on: { input: function () { nuSubformFilterRows(sfName, nuSubformFilterArray(sfName, filter[sfName])); }, focus: function () { if (propDatalist === true) nuSubformFilterAddValues(sfName, 'search', columnId); }, }, id: filterId }); } function nuSubformFilterCreateSelectOption(_value, _text, persistent, all, _selected) { return $('