+ Start a Discussion
nil_von_9wonil_von_9wo 

Is it possible to put Object references in Static resources?

When making web pages, I prefer to separate the scripts from the markup.  As such, I'd rather put JavaScripts into Static Resources than embed them into my VisualForce pages.

 

I have the following JavaScript (from the Salesforce guide to useful scontrols):

 

 

// Create a map object var map = new YMap(document.getElementById('mapContainer')); // Display the map centered on given address map.drawZoomAndCenter("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); // Set marker at that address map.addMarker ("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3);

 

Included in the VisualForce page, it works fine.

 

I put it into a static resource "createmap_js", which I reference with  

 

 

<script type="text/javascript" src="{!$Resource.createmap_js}" >

 

 However, when I do this, the map doesn't appear and instead the space is tiled with "We're sorry, the data you have            your browser to try again."

 

I assume this means that the fields are not being rendered when the script executes.

 

Is there any way to seperate the JavaScript from the markup and have a functional VisualForce page?

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
nil_von_9wonil_von_9wo

I've got it working now... had to take the contentType out, add a missing "/" to </script>, and remove some extra parenthesis from the JavaScript. 

 

Final code:

 

 

<apex:page standardController="Account" > <script type="text/javascript"> function createmap() { // Create a map object var map = new YMap(document.getElementById('mapContainer')); // Display the map centered on given address map.drawZoomAndCenter("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); // Set marker at that address map.addMarker ("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); } function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } window.onTimeout(addLoadEvent(createmap),2000); </script></apex:page>

 

 

All Answers

DevAngelDevAngel

Hi nil_von_9wo,

 

Using a vanilla script tag is not the way to go.  You should instead use 

<apex:includeScript value="{!$Resource.myscript.js}" />

 

This will cause the script tag to be generated in the head of the page.  Using vanilla script tag will cause the tag to be rendered in the body somewhere, which may be why you are experiencing problems.

 

 

Cheers,

 

 

 

nil_von_9wonil_von_9wo

Thanks for your response.   Unfortunately, the code still doesn't work.

 

At first, the result was just a blank page.

 

Then I tried wrapping that code within a function and calling it with <body onload="createmap()">

 

This restored allocating space for the map, but again it displayed the same as with the "vanilla" script tag. 

 

 

Perhaps there is an attribute I should be adding to apex:includeScript to get it to "fill in the blanks"?

 

 

-Brian. 

DevAngelDevAngel

Will the script work when coded directly into the page?

 

Also, just setting the body.onload =  can potentially overwrite some other code that has onload dependencies.

 

A better way is to "add" the event to the onload chain rather than "set" the event.

 

Check this article here.

 

Another debugging/troubleshooting technique is to wrap your calls in a function an use window.onTimeout(function, time_in_ms) to cause a delay.  Use about 2 seconds to see if there is a dom completion issue.

Message Edited by DevAngel on 08-04-2009 09:37 AM
nil_von_9wonil_von_9wo

The JavaScript itself (if one discounts the merge fields) seems to be working fine now.

 

The problem is that the merge fields don't seem to be receiving values from the Account object when the JavaScript is in a seperate file, so the script can't pass these values to Yahoo.  

 

These merge fields worked without a problem when the JavaScript was embedded within the <body> element.

 

I've tried using both addLoadEvent() and Timeout() but neither solved this problem. 

 

 

DevAngelDevAngel

Ok, well, I understand now, didn't realize you had merge fields in the JS code (probably should have looked :-)).

 

One more approach is to create your javascript in a different page.  Set the content type of the page to "text/javascript" and use the <apex:include .../> tag to include the js page in your main page.  This is also useful for css so that you can use the ide to edit both types of content and immediately see the results after saving (as opposed to re-uploading the static resource).

 

 

Cheers

nil_von_9wonil_von_9wo

I seem to be doing this wrong because now it isn't working at all... here is all the code:

 

Yahoo_Map_API.page: 

 

<apex:page standardController="Account" tabstyle="Account" id="thePage"> <apex:styleSheet value="{!$Resource.mapcontainer_css}" /> <apex:include pageName="createmap_js" /> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Yahoo Map API</title> <script type="text/javascript" src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=salesforce.com"></script> </head> <body > <div id="mapContainer"></div> </body></html></apex:page>

 

createmap_js.page

 

<apex:page standardController="Account" tabstyle="Account" id="createMapScript"> <script type="text/javascript"> function createmap() { // Create a map object var map = new YMap(document.getElementById('mapContainer')); // Display the map centered on given address map.drawZoomAndCenter("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); // Set marker at that address map.addMarker ("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); } function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } window.onTimeout((addLoadEvent(createmap())),2000)); <script></apex:page>

 

 

 

 

 

DevAngelDevAngel

You js page should be:

 

 

<apex:page contentType="text/javascript" >
<script type="text/javascript">
function createmap() {
// Create a map object
var map = new YMap(document.getElementById('mapContainer'));
// Display the map centered on given address

map.drawZoomAndCenter("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3);
// Set marker at that address
map.addMarker ("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3);
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();

}

}

}

window.onTimeout((addLoadEvent(createmap())),2000));
<script>
</apex:page>

 

 

 

nil_von_9wonil_von_9wo

I tried making the change suggested above and it wouldn't save because it didn't recognize "{!Account."   So, I put standardController="Account" back into the line and it would save.

 

However, the result is quite strange.

 

Now the entire page doesn't render: I just see plaintext, including all the markup. 

nil_von_9wonil_von_9wo

I've got it working now... had to take the contentType out, add a missing "/" to </script>, and remove some extra parenthesis from the JavaScript. 

 

Final code:

 

 

<apex:page standardController="Account" > <script type="text/javascript"> function createmap() { // Create a map object var map = new YMap(document.getElementById('mapContainer')); // Display the map centered on given address map.drawZoomAndCenter("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); // Set marker at that address map.addMarker ("{!Account.BillingStreet}, {!Account.BillingState}, {!Account.BillingPostalCode}", 3); } function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } window.onTimeout(addLoadEvent(createmap),2000); </script></apex:page>

 

 

This was selected as the best answer
DevAngelDevAngel
Niiiice!  Sorry for taking you the round about way to get there.
nil_von_9wonil_von_9wo

Don't worry about it... round about is educational, and we got there.  :-)

 

 

Thanks again.  :-)

 

-Brian.

 

 

[8 issues solved, 13 left to go...]