diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 19cef72be..8b8b78b16 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -202,8 +202,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay $sParams .= $sName.'='.urlencode($value).'&'; // Always add a trailing & } $sUrl = utils::GetAbsoluteUrlAppRoot().'pages/'.$oObj->GetUIPage().'?'.$sParams.'class='.get_class($oObj).'&id='.$oObj->getKey().'&'.$oAppContext->GetForLink().'&a=1'; - $oPage->add_script( - <<add_early_script(<<Reload(); diff --git a/js/forms-json-utils.js b/js/forms-json-utils.js index d3e06f436..23b897689 100644 --- a/js/forms-json-utils.js +++ b/js/forms-json-utils.js @@ -115,11 +115,10 @@ function OnUnload(sTransactionId, sObjClass, iObjKey, sToken) // IMPORTANT: the ajax request MUST BE synchronous to be executed in this context $.ajax({ url: GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', - async: true, + async: false, method: 'POST', data: {operation: 'on_form_cancel', transaction_id: sTransactionId, obj_class: sObjClass, obj_key: iObjKey, token: sToken } }); - CombodoGlobalToolbox.Pause(1000); } } diff --git a/sources/application/WebPage/WebPage.php b/sources/application/WebPage/WebPage.php index 5fd30879a..563d7f7f7 100644 --- a/sources/application/WebPage/WebPage.php +++ b/sources/application/WebPage/WebPage.php @@ -74,7 +74,13 @@ class WebPage implements Page protected $s_title; protected $s_content; protected $s_deferred_content; - /** @var array Scripts to be put in the page's header */ + /** + * @var array Scripts to be put in the page's header, therefore executed first, BEFORE the DOM interpretation. + * /!\ Keep in mind that no external JS files (eg. jQuery) will be loaded yet. + * @since 3.0.0 + */ + protected $a_early_scripts; + /** @var array Scripts to be executed immediately without waiting for the DOM to be ready */ protected $a_scripts; /** @var array Scripts to be executed when the DOM is ready (typical JQuery use), right before "ready scripts" */ protected $a_init_scripts; @@ -127,6 +133,7 @@ class WebPage implements Page $this->s_title = $s_title; $this->s_content = ""; $this->s_deferred_content = ''; + $this->InitializeEarlyScripts(); $this->InitializeScripts(); $this->InitializeInitScripts(); $this->InitializeReadyScripts(); @@ -433,6 +440,45 @@ class WebPage implements Page /** * Empty all base JS in the page's header * + * @uses \WebPage::$a_a_early_scripts + * @return void + * @since 3.0.0 + */ + protected function EmptyEarlyScripts(): void + { + $this->a_early_scripts = []; + } + + /** + * Initialize base JS in the page's header + * + * @uses \WebPage::$a_scripts + * @return void + * @since 3.0.0 + */ + protected function InitializeEarlyScripts(): void + { + $this->EmptyEarlyScripts(); + } + + /** + * Add some Javascript to the header of the page, therefore executed first, BEFORE the DOM interpretation. + * /!\ Keep in mind that no external JS files (eg. jQuery) will be loaded yet. + * + * @uses \WebPage::$a_a_early_scripts + * @param string $s_script + * @since 3.0.0 + */ + public function add_early_script($s_script) + { + if (!empty(trim($s_script))) { + $this->a_early_scripts[] = $s_script; + } + } + + /** + * Empty all base JS + * * @uses \WebPage::$a_scripts * @return void * @since 3.0.0 @@ -443,7 +489,7 @@ class WebPage implements Page } /** - * Initialize base JS in the page's header + * Initialize base JS * * @uses \WebPage::$a_scripts * @return void @@ -455,7 +501,7 @@ class WebPage implements Page } /** - * Add some Javascript to the header of the page + * Add some Javascript to be executed immediately without waiting for the DOM to be ready * * @uses \WebPage::$a_scripts * @param string $s_script @@ -1123,6 +1169,7 @@ JS; ], 'aCssFiles' => $this->a_linked_stylesheets, 'aCssInline' => $this->a_styles, + 'aJsInlineEarly' => $this->a_early_scripts, 'aJsFiles' => $this->a_linked_scripts, 'aJsInlineLive' => $this->a_scripts, 'aJsInlineOnDomReady' => $this->GetReadyScripts(), diff --git a/sources/application/WebPage/iTopWebPage.php b/sources/application/WebPage/iTopWebPage.php index 0e6046063..79f9fa106 100644 --- a/sources/application/WebPage/iTopWebPage.php +++ b/sources/application/WebPage/iTopWebPage.php @@ -861,6 +861,7 @@ HTML; [ 'aCssFiles' => $this->a_linked_stylesheets, 'aCssInline' => $this->a_styles, + 'aJsInlineEarly' => $this->a_early_scripts, 'aJsFiles' => $this->a_linked_scripts, 'aJsInlineOnInit' => $this->a_init_scripts, 'aJsInlineOnDomReady' => $this->GetReadyScripts(), diff --git a/templates/pages/backoffice/ajaxpage/layout.html.twig b/templates/pages/backoffice/ajaxpage/layout.html.twig index f01b4f11a..a53834012 100644 --- a/templates/pages/backoffice/ajaxpage/layout.html.twig +++ b/templates/pages/backoffice/ajaxpage/layout.html.twig @@ -7,6 +7,15 @@ {{ render_block(oLayout, {aPage: aPage}) }} {% endif %} + {% block iboPageJsInlineEarly %} + {% for sJsInline in aPage.aJsInlineEarly %} + {# We put each scripts in a dedicated script tag to prevent massive failure if 1 script is broken (eg. missing semi-colon or non closed multi-line comment) #} + + {% endfor %} + {% endblock %} + {% block iboPageJsInlineLive %} {% for sJsInline in aPage.aJsInlineLive %} {# We put each scripts in a dedicated script tag to prevent massive failure if 1 script is broken (eg. missing semi-colon or non closed multi-line comment) #} diff --git a/templates/pages/backoffice/webpage/layout.html.twig b/templates/pages/backoffice/webpage/layout.html.twig index 3e8e5c14f..adb480360 100644 --- a/templates/pages/backoffice/webpage/layout.html.twig +++ b/templates/pages/backoffice/webpage/layout.html.twig @@ -35,6 +35,15 @@ {% endfor %} {% endblock %} + + {% block iboPageJsInlineEarly %} + {% for sJsInline in aPage.aJsInlineEarly %} + {# We put each scripts in a dedicated script tag to prevent massive failure if 1 script is broken (eg. missing semi-colon or non closed multi-line comment) #} + + {% endfor %} + {% endblock %} {% block iboPageBodyHtml %}