I'm finishing my project right now and see that I've got a lot of javascript code on each page. It's not included as a ".js" file, but rather coded in the page itself. I figured it's a bad idea, so now I'm trying to put them all in one .js file and include it in each page.
The only problem I'm facing now is this: Some functions are only called on certain pages and are depending on the inclusion of jquery plugins. Not all pages needs the plugin however.
Example:
On the home page I need to chain the Country dropbox with the City dropbox, thus I need the jchained.js plugin for jquery. The code I need to use is:
$(function(){
$("#city").chained("#country");
});
When I add this function to the .js file, and I open a page where I don't need to chain the dropboxes I get logically an error:
TypeError: $("#city").chained is not a function
So if I understand this correctly, in order to use a .js file with all my different functions for different plugins, I need to include all the plugins to all the pages?
Thanks for your ideas & help.
Personally, I don't think you should worry about including alot of .js files, that's part of web development. Another option, albeit slightly more tedious, is you can make a check for the function to exist (if the plugin .js has been included) and then call it if it does:
if(typeof yourFunctionName == 'function') {
yourFunctionName();
}
It completely depends on how the code is structured or how complex the current code is.
An immediate solution will be,
Give an id to each page (may be on body tag).
Put all the code in a single external JavaScript file.
Execute the code meant for that particular page only if it has required id on that body element.
Something like :
if ( $('body').attr('id') == "home" ) {
/* Add home page JS here */
}
You can try this.
Correct me if I am wrong.
Related
I'm working on a new Acumatica screen for our company that will require some javascript code to retrieve and display a map object (from ESRI).
This code requires an external .js file that is included to the HTML by the javascript code itself. Everything works fine if I use a blank HTML page to test this.
The problem I have is that when I try using the same code from inside the Acumatica screen, it doesn't load this required external file, and therefore the code does not work properly.
I attempted to load the full .js file code along with my code, but it returned the following error:
error CS8095: Length of String constant exceeds current memory limit. Try splitting the string into multiple constants.
I haven't tried splitting this file into multiple strings (as the error message suggests), because I want to make sure there isn't a cleaner and more professional, direct/right way to do this.
Is it possible to manually import this external .js file into our Acumatica instance, so I can point to it instead? (in case it makes a difference if it's hosted in the same environment)
or, is there any way to make Acumatica able to load external files so we can keep using our current approach? (any setting that may be preventing external files from loading?)
I'm not sure i fully understand the question. What comes to mind however is you may be looking to use the PXJavaScript control. I used this link to help get my head wrapped around how to use the control. We had a need to trigger something off with Java Script and the PXJavaScript control got us to the end result we needed. Let me know if this gets you in the right direction?
Dynamically Change Button Color
In my app I have around 10 different pages, and most of them use some sort of JavaScript. Currently, I have one client-side app.js file that is included in all pages. In order to figure out what event listeners to attach on a page I basically check url location and go from there:
window.onload = function () {
let urlLocation = window.location.pathname.split('/')[1]
//Global functionality for all pages
UIctrl.toggleActiveNavbar(urlLocation)
//createTopic route
if (urlLocation === 'createTopic' || urlLocation === 'edit') {
UIctrl.createTopicTagsBasedOnCategory()
UIctrl.handleCreateOrEditTopicClick()
}
if (urlLocation === 'editPost' || urlLocation === 'createPost') {
UIctrl.handleCreateOrEditPostClick()
}
// .... and so on
}
Even though it works, I don't think it's a good way to do it. If a project becomes big enough, it's very hard to manage it.
I was not able to find an answer how to do it properly. My questions are :
Should I have separate js files for each page ? My problem with this is that I have to duplicate common code that is used on all pages.
Do you use some sort of bundlers (webpack/parcel) in your express apps that solve this issue? Maybe you could point me to a repository that shows how to set it up correctly.
How is this done in the real world production environments ?
Thank you.
Your intuition that comparing URLs to decide what initialization to run is a bad way to code is correct. That is not a good pattern and will quickly get out of control with more and more pages and maintenance over time can get to be a real pain.
Instead, you can put common code in a shared JS file that every page loads so those functions are available as needed. Then, use an inline <script> tag inside each individual page to do the page-specific initialization that sets up event listeners that are particular to that page and calls code in the shared JS file.
If for some pages, you have lots of page-specific initialization code, you could put just that page-specific code in a page-specific JS file, but in general you don't want to have an external JS file for every one of your pages if you can avoid it. Try putting most of the code in the common JS file and then just using a small bit of inline code in each specific page to do the right initialization. This puts most of your code in a common, shared JS file and keeps page-specific initialization logic in the specific page.
Should I have separate js files for each page ? My problem with this is that I have to duplicate common code that is used on all pages.
No. You don't want to duplicate lots of code in separate JS files as that is a maintenance nightmare and defeats effective browsing caching.
Basically, we have a massive core.js file with lots of jQuery calls that have no structure whatsoever. Example:
$(document).ready(function() {
$(document).on({
change: function() {
// some code specific to 1 view
}
},
"#some-id-name-that-may-exist-in-multiple-views" // like "bank-box"
});
// This code isn't even inside a closure, so it get's executed in all views but '.metadata' only exist in one, braking the whole system.
checkProgress($.parseJSON($('.metadata').text()));
Now, as the comment says, it has happened before that a whole section of the system breaks because of a JS error that usually happens due to the share of JS code. (Ironically, thanks to the sharing of said code, Continuous Integration caught it because of the only 1% of the code that's tested)
How do I justify the usage of separate JS files that holds view-specific logic, instead of a massive core.js that exist because of the "the browser would cache all of the JS on the first load" argument. Any resources or links are welcome.
On the other hand, maybe multiple files is an incorrect approach and we need to have 1 core.js file, but the code should be in a different way so that it doesn't conflict like it does right now. If this is the case, then how.
You can first check for the existence of those elements, that you are working on. You could rewrite your this code like this:
if( $(".metadata").length ){
checkProgress($.parseJSON($('.metadata').text()));
}// if $(".metadata").length
In my project I have a load of functions that are used on every page, so I have put these in a single javascript file common.js and have included it in my footer template. My questions is, what is the best way to handle page-specific javscript?
For example, on one of my pages I have a google map. If my map js code is run on a page where I don't have an element with id map_canvas, I get an error.
Method 1: I could write some PHP which echos an additional script tag requesting map.js if and only if I'm on a map page.
Method 2: I could give the <body> of my map page an id of "map_page", then I could write a conditional clause in common.js along the lines of:
if (#map_page exists){
put contents of map.js here
}
The problem with method 1 is that it increases the number of requests to the server.
The problem with method 2 is that it bloats my common javascript file.
Please can somebody explain, which, if any would be the preferred method to do this, or if neither are suitable, what I should do instead?
I have approximately 10 page-specific javascript files to deal with.
Thanks
I would say that simpler is better. On every page, just add a script tag calling map.js. Or, in your common.js, you don't need to paste all of map.js's code. You can just create a new script tag with the js and call map.js like that. I would not recommend the php method. The easiest and simplest, therefore the least likely to be buggy method, is just to add another script tag to the pages that need it. Or if that is not an option, common.js could include this:
if(need map.js){
var mapjs=document.createElement("script");
mapjs.type="text/javascript";
mapjs.src="map.js";
document.body.appendChild(mapjs);
}
When using HTML5 Boilerplate, you are given a script.js file and the jquery file are all loaded after the body.
How do I know when to call certain code for a specific page? For eg. What if on /maps I want to load google maps dynamically, how do I accomplish this without putting it on the page and using script.js file while having it not load the map for all pages?
Basically, how do I structure my code when I can't have any script in my pages? How do I know what code to call for a particular page?
Script files that are included are immediately executed, so inside the script file you could have a section check the URL of the page you're on.
For example, something like this:
if (window.location.href === "http://myapp.com/maps") {
// call the map function or whatever ...
}
But, out of curiosity, why can't you add a script file to the specific page you're on? I'd only recommend the solution above if you absolutely cannot edit the HTML of your pages.
I too have the same question. I searched and just found these two
http://paulirish.com/2009/markup-based-unobtrusive-comprehensive-dom-ready-execution/
http://www.viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution/
I am going through of this, and not yet completely reviewed. See if it is useful to you in between.