How to overwrite code in app.js?
Our support Team complain that if they press Home in our Portal the default search area is set to service catalog and not to work item. We tried to overwrite this by custom.js code but that did not work because the following code in app.js overwrites the code of our custom.js. As a Workaround we overwrote this code in app.js. Does anybody know how to fix this with a custom file and not an original source code file? Regards Margret
headerSearchSetType: function () {
var currentURL = window.location.href;
var searchParam = $("input[name=search_param]"); //the hidden field which holds the search type id
var searchConcept = $("span[id=search_concept]"); //the span field which displays the search type value
var searchInput = $("input[name=searchText]");
//service catalog
if ((currentURL.indexOf("ServiceCatalog") > -1) ||
(currentURL.indexOf("94ecd540-714b-49dc-82d1-0b34bf11888f") > -1) ||
(currentURL.indexOf("02efdc70-55c7-4ba8-9804-ca01631c1a54") > -1)) {
searchParam.val("ServiceCatalog");
searchConcept.html(localization.ServiceCatalog);
searchInput.attr('placeholder', localization.SearchServiceCatalog);
}
//knowledge base
else if ((currentURL.indexOf("KnowledgeBase") > -1) || (currentURL.indexOf("0aef4765-0efa-4a65-84c1-324b09231223") > -1)) {
searchParam.val("KnowledgeBase");
searchConcept.html(localization.KnowledgeBase);
searchInput.attr('placeholder', localization.SearchKnowledgeBase);
}
//default to work item if analyst
else if (session.user.Analyst) {
searchParam.val("WorkItem");
searchConcept.html(localization.WorkItem);
searchInput.attr('placeholder', localization.SearchWorkItem);
}
//default to Service Catalog if not an analyst and we are down here
else {
searchParam.val("ServiceCatalog");
searchConcept.html(localization.ServiceCatalog);
searchInput.attr('placeholder', localization.SearchServiceCatalog);
}
},
Best Answer
-
Ryan_Lane Cireson Support Advanced IT Monkey ✭✭✭Hello there,
There aren't a ton of options for a simple fix thanks to app.js using val() to update the input which does not trigger the change event. Looking over the loading and function calls the order of operations overall looks like this:- custom.js loaded
- app.js loaded
- app.js registers anonymous function on document.ready event
- document.ready event triggered
- (app.js) anonymous function calls app.headerSeachInit() > app.headerSearchSetType()
- custom.js loaded
- custom.js registers anonymous function on document.ready event
- app.js loaded
- app.js registers anonymous function on document.ready event
- document.ready event triggered
- (custom.js) anonymous function registers inner anonymous function on document.ready event. This adds it to the end of the jQuery's readyList.
- (app.js) anonymous function calls app.headerSeachInit() > app.headerSearchSetType()
- (custom.js) inner anonymous function calls custom headerSearchSetType()
<div>if ( (window.location.href.indexOf('ServiceCatalog') > -1) || (window.location.href.indexOf('94ecd540-714b-49dc-82d1-0b34bf11888f') > -1) || (window.location.href.indexOf('02efdc70-55c7-4ba8-9804-ca01631c1a54') > -1) ) { $(function () { 'use strict'; $(function () { function headerSearchSetType(searchParamVal, searchConceptHTML, searchInputPlaceholder) { searchParamVal = searchParamVal || 'WorkItem'; searchConceptHTML = searchConceptHTML || localization.WorkItems; searchInputPlaceholder = searchInputPlaceholder || localization.SearchWorkItem; var searchParam = $('input#search_param'), searchConcept = $('span#search_concept'), searchInput = $('input[name="searchText"]'); searchParam.val(searchParamVal); searchConcept.html(searchConceptHTML); searchInput.attr('placeholder', searchInputPlaceholder); } headerSearchSetType(); }); }); }<br></div>
EDIT: There's some ambiguity between localization.WorkItem and localization.WorkItems for the dropdown label. The initial app.headerSearchSetType function uses localization.WorkItem but the actual implementation dropdown labels use localization.WorkItems. I've adjusted my answer to use localization.WorkItems to be more consistent in my opinion.
2nd EDIT: I read up on how jQuery's ready function works and my initial list was not accurate. Calling document.ready within a document.ready will only add it to the end of the private array readyList so it is going to be executed as soon as any previous ready callbacks are processed. In the end, that inner anonymous function will still be executed after the app.js functions due to the FIFO processing of readyList. Updated my "timeline" to clarify.7
Answers
The Cireson portal is designed to allow customers to extend or modify the Javascript as needed, but rather than editing the code directly in the files, which we will replace each time we do an upgrade, we provide a folder called CustomSpace where you can load a file called Custom.js that will run last in the load of the page and therefore overwrite any code that is already loaded.
If you took your code and placed it in Custom.js in the CustomSpace folder, you should be good to go.
I hope this makes sense.
Brett
You cannot 'override' the built in code. As @Brett_Moffett says, we can use custom.js to add our own code but this code is always executed last, so will probably run too late even if we could redefine the above function. The default search area might well already be set by the default code before custom.js gets run and therefore editing the method to determine what search to use on page load is useless.
However, we can use custom.js to do anything we like on the page, once it has run all the out of box code. This could include resetting the default search if certain criteria are met. Eg user is an Analyst and Current Page is the Homepage.
This is what you need to run. It will check the conditions are right and then force the default search to be WorkItem. Its not tested it fully, timing might be tricky but see how you get on.
As always with custom JavaScript, its best to place this code in its own JS file, in your CustomSpace folder (good practice is within another sub-folder to stay organised). Then you need to call that file from within custom.js file. The recommended way is with the scriptloader function. Do you know what that is?
Geoff
//service catalog
if ((currentURL.indexOf("ServiceCatalog") > -1) ||
(currentURL.indexOf("94ecd540-714b-49dc-82d1-0b34bf11888f") > -1) ||
(currentURL.indexOf("02efdc70-55c7-4ba8-9804-ca01631c1a54") > -1)) {
searchParam.val("ServiceCatalog");
searchConcept.html(localization.ServiceCatalog);
searchInput.attr('placeholder', localization.SearchServiceCatalog);
}
In the debugging mode I see that first my changes in custom.js are run and afterwards the above mentioned code in app.js.
There aren't a ton of options for a simple fix thanks to app.js using val() to update the input which does not trigger the change event. Looking over the loading and function calls the order of operations overall looks like this:
- custom.js loaded
- app.js loaded
- app.js registers anonymous function on document.ready event
- document.ready event triggered
- (app.js) anonymous function calls app.headerSeachInit() > app.headerSearchSetType()
If we make use of the document.ready event and queuing we can setup our custom code to be processed after the app.js functions are completed thanks to first-in, first-out (FIFO) nature of jQuery's document.ready function:EDIT: There's some ambiguity between localization.WorkItem and localization.WorkItems for the dropdown label. The initial app.headerSearchSetType function uses localization.WorkItem but the actual implementation dropdown labels use localization.WorkItems. I've adjusted my answer to use localization.WorkItems to be more consistent in my opinion.
2nd EDIT: I read up on how jQuery's ready function works and my initial list was not accurate. Calling document.ready within a document.ready will only add it to the end of the private array readyList so it is going to be executed as soon as any previous ready callbacks are processed. In the end, that inner anonymous function will still be executed after the app.js functions due to the FIFO processing of readyList. Updated my "timeline" to clarify.
Nice one Ryan for getting into this.
Margarete, my code was only intended as a snippet to do the actual work. You always need to consider timing with custom JavaScript with regards to the actual elements on the page and other JavaScript still to execute at the time of the custom code running.
On a side note, I have updated the description for my answer to reflect how jQuery's document.ready executes its private readyList vs. my previous, incorrect understanding. No changes in the script, just the actual reason why it works.