+ Start a Discussion
Savvy AdminSavvy Admin 

Make included JavaScript file work with jQuery

I have included jQuery as Static Resource and it is working with the Visualforce page when I include my own JavaScript code in <script type="text/javascript"> tag.

However, if I copy/paste the code into a .js file and upload it on static resource and include the file as apex:includeScript value, the JavaScript code never worked.

On the Visualforce page, I wrote jQuery.noConflict(); and use jQuery instead of '$' to make it work.

Later when I copied the original code into a .js file, I did not change anything. It did not work. Then I tried to use something like var j$ = jQuery.noConflict(); and replace all jQuery by j$. Not working. I also tried to delete the noConflict line and all using '$' as selector. Not working. Another try is to add (function($) {  }) (jQuery); to wrap the original code. Still not working.

Is there anything that I am mising to make the external js file which references jQuery working with the visualforce page?
Best Answer chosen by Savvy Admin
matt.ian.thomasmatt.ian.thomas
Okay, there are a few different possible causes you could look into as to why it isn't working. First, you probably are getting an error, and that would most likely be provided in your browser's console. In Chrome, for example, the next time you open the page right click anywhere on the page and click "Inspect" from the dropdown. This will open the console for Chrome, which will report clues that may point you in the right direction in cases like this. Make sure in the resulting section that opens at the bottom of the page that you are on the "Console" tab.

1. So, I'll start by saying that one possible reason this is working when it's on your page and not when it's in a resource is that merge field you have on line 6 when you declare 
var loanDetails = document.getElementById("{!$Component.OppApplication:AppForm:App:LoanDetails}"); 
This will properly resolve when on the Visualforce page but not in the resource. To use something like this, throw a script at the top of your page like this:
window.__VARS_FROM_MERGE_FIELDS__ = {
   "loan_details" : "{!$Component.OppApplication:AppForm:App:LoanDetails}"
};
Now you have an object literal populated with the actual values of your merge fields that can be used in your resource file. So now, within your .resource, you'd say
var loanDetails = document.getElementById(window.__VARS_FROM_MERGE_FIELDS__.loan_details);
2. What is the component that "loanDetails" is the id attribute for? If it's a visualforce component, such as <apex:outputPanel id="loanDetails" layout="block">, the id is not loanDetails at runtime. So in this case, $("#loanDetails") is actually returning null, and not the jQuery object that you are expecting it to. As in the above, use console to explore this type of scenario, by directly executing $("#loanDetails") in the console. It will print out the DOM element, if any, that it finds for you so you can see what it's actually doing.

If you've found that neither of these reasons are the solution to the issue you're seeing, then post your markup and we can dig deeper.

 

All Answers

matt.ian.thomasmatt.ian.thomas
Include your script or the error that you're getting and it would be easier to help you identify the issue.
Savvy AdminSavvy Admin
Thank you for reminding me this.
I actually received nothing about errors. Just the JavaScript code does not make effects on the page.

For the script, nothing special. I have included the changes I made for the two situations. I can give a chunk of the script for the original code I wrote in  <script type="text/javascript"> tag. Later, I only included all the code in .js file and put it on static resources and it did not work.

Example of my script:

<script type="text/javascript">
        jQuery.noConflict();
        jQuery(document).ready(function() {
        
            <!-- Step 1 Loan Details -->
            var loanDetails = document.getElementById("{!$Component.OppApplication:AppForm:App:LoanDetails}"); 
            
            jQuery("#loanDetails").addClass('active');
            
            jQuery("#loanDetails").click(function () {
                if (jQuery(this).hasClass('active')) {
                    jQuery(loanDetails.childNodes[2]).slideUp ();
                    jQuery(loanDetails.childNodes[3]).slideUp ();
                    jQuery(this).removeClass('active');
                    jQuery(this).addClass('unactive');
                } else {
                    jQuery(loanDetails.childNodes[2]).slideDown ();
                    jQuery(loanDetails.childNodes[3]).slideDown ();
                    jQuery(this).removeClass('unactive');
                    jQuery(this).addClass('active');
                }
            });
 
       });
        
    </script>
matt.ian.thomasmatt.ian.thomas
Okay, there are a few different possible causes you could look into as to why it isn't working. First, you probably are getting an error, and that would most likely be provided in your browser's console. In Chrome, for example, the next time you open the page right click anywhere on the page and click "Inspect" from the dropdown. This will open the console for Chrome, which will report clues that may point you in the right direction in cases like this. Make sure in the resulting section that opens at the bottom of the page that you are on the "Console" tab.

1. So, I'll start by saying that one possible reason this is working when it's on your page and not when it's in a resource is that merge field you have on line 6 when you declare 
var loanDetails = document.getElementById("{!$Component.OppApplication:AppForm:App:LoanDetails}"); 
This will properly resolve when on the Visualforce page but not in the resource. To use something like this, throw a script at the top of your page like this:
window.__VARS_FROM_MERGE_FIELDS__ = {
   "loan_details" : "{!$Component.OppApplication:AppForm:App:LoanDetails}"
};
Now you have an object literal populated with the actual values of your merge fields that can be used in your resource file. So now, within your .resource, you'd say
var loanDetails = document.getElementById(window.__VARS_FROM_MERGE_FIELDS__.loan_details);
2. What is the component that "loanDetails" is the id attribute for? If it's a visualforce component, such as <apex:outputPanel id="loanDetails" layout="block">, the id is not loanDetails at runtime. So in this case, $("#loanDetails") is actually returning null, and not the jQuery object that you are expecting it to. As in the above, use console to explore this type of scenario, by directly executing $("#loanDetails") in the console. It will print out the DOM element, if any, that it finds for you so you can see what it's actually doing.

If you've found that neither of these reasons are the solution to the issue you're seeing, then post your markup and we can dig deeper.

 
This was selected as the best answer
matt.ian.thomasmatt.ian.thomas
I would also add that the following line (and all others like it) is problematic.
jQuery(loanDetails.childNodes[2]).slideUp();

To access children, you must do something like either of the following:

1. Use .children(): https://api.jquery.com/children/
$("#id").children();

The above line returns a collection of jQuery elements which are children of the element returned by $("#id"). You can subsequently do something like:
$("#id").children().each(function(child) {
   //Do whatever you need to do to each child of $("#id") here...
});

2. Use .find(): https://api.jquery.com/find/
$("#id").find(some_other_selector)

The above line will return descendants of $("#id") that match the given selector. For example, let's say you wanted to retrieve all of the <tr> elements within a <table>:
$("#table_id").find("tr")

We can then subsequently do something similar as in the above when we followed up with .each().
Savvy AdminSavvy Admin
Thank you very much Matt for your so prompt answers.

Now I am working on other projects. When I have time, I will make testings on this part and get back to you about this issue ASAP.
Savvy AdminSavvy Admin
Sorry, I really did not work on this too much. However, I can see the errors in console. It is probably caused by

var loanDetails = document.getElementById("{!$Component.OppApplication:AppForm:App:LoanDetails}");&nbsp;

and need to be fixed by the method Matt provided

window.__VARS_FROM_MERGE_FIELDS__ = {
   "loan_details" : "{!$Component.OppApplication:AppForm:App:LoanDetails}"
};

Later, when I have time, I will get back to have a try.