I'm trying to insert reference to the Javascript file in the header by using drupal_add_js(). I placed this line inside the template preprocess function in template.php. The result that the code is not working at all: There is no script link in output as it should be. Can anyone tell me what am I doing wrong?
function phptemplate_preprocess_page(&$vars) {
$url = drupal_get_path("theme","mysite");
drupal_add_js($url."/jquery.js");
drupal_add_js($url."/drupal.js");
.....
Even easier, Javascript that needs to be loaded on all pages can be added in the theme's .info file. See http://drupal.org/node/171205#scripts.
drupal_add_js(path_to_theme().'/js/jquery.cycle.all.js');
$vars['scripts'] = drupal_get_js();
If you place the javascript file in the theme directory, you can just add the following to the themes .info file
scripts[] = myJavaScriptFile.js
After you add this file you need to deactivate your theme and then reactive it.
As pointed by other, simply using drupal_add_js() from a hook_preprocess_page() implementation doesn't work. The references to JavaScript files collected through the multiple calls to drupal_add_js() are used to generate the corresponding markup into the $scripts variables from template_preprocess_page(). But a theme's implementation of hook_preprocess_page() is always called after template_preprocess_page(). So in order to have the files added through drupal_add_js() in your .tpl.php file(s), you need to override the already set $scripts variables:
function THEME_preprocess_page(&$variables)
drupal_add_js(...);
$variables['scripts'] = drupal_get_js();
}
But, you shouldn't have to add jquery.js and drupal.js yourself, it should already be done automatically by Drupal core. If you need to do it yourself, then something is broken on your site. You can (re-)add the files as a quick fix, but you better find the root cause of the issue as it is most likely creating other issues you haven't yet identified (or worked around without realizing it).
drupal_add_js() works, but you are putting it deep into the page rendering process. I suggest you put it in the template.php like you are doing, but in the beginning, outside any function. This is what we did on a few of our projects.
Related
Okay so I have a meteor app and I am trying to make templates that have THREEjs animations in them so I can load a specific animation by loading a specific template. I wanted to de-clutter my HTML file by taking out the script tags and moving them to a separate JavaScript file but that wasn't working. I ended up just putting the JavaScript into my HTML and it worked. I was going to just keep doing that and live with the cluttered code but now I have run into a problem.
For some odd reason even if a for loop is inside the script tags, the computer will see the < sign and expect a html tag. At first I thought I had forgotten a closing tag or something but I checked and I haven't. If I delete the for loop (only create one particle) everything works perfectly again. I could fix this by just using escape character for the < sign (<) but I think I should find a solution to the overarching problem so I don't run into similar problems in the future.
I want to put the least amount of JavaScript in my HTML file as possible. (Meteor doesn't like it and neiter do I.)
If I try to just copy and paste my JavaScript into a separate file, it won't find the min.three.js file (it tells me THREE isn't defined)
I would prefer not to use another framework like require.js mainly because I'm not sure how but I will as a last resort if that's the only way to do it
All the examples for THREEjs put the code directly in the HTML file but how can I put it into a separate javascript file and make sure the javascript file finds min.three.js?
This is an overview of what the template looks like. I used jQuery to find actualAnimation2 and appended the container to that. You can also find all the code here
<template name = "animation2">
<div id = "animation2" class = "centered">
<div class = "line"></div>
<h1>Animation 2</h1>
<div class = "line"></div>
{{> animationButtons}}
<!--Put in a threejs animation here -->
<div id = "actualAnimation2" class = "animation">
<script src="client/three.min.js"></script>
<script>
//THREEjs stuff here
//This is what I want to move
</script>
</div>
</div>
</template>
tl;dr: How can I make THREEjs play nice with Meteor?
Any suggestions are welcome and let me know if I can clarify anything. Thank you for your help!
Quoting http://docs.meteor.com/ :
Some JavaScript libraries only work when placed in the
client/compatibility subdirectory. Files in this directory are
executed without being wrapped in a new variable scope. This means
that each top-level var defines a global variable. In addition, these
files are executed before other client-side JavaScript files.
This is exactly what needs to be done with three.min.js because the beggining of the file looks like :
// threejs.org/license
'use strict';var THREE={REVISION:"68"};
So you need to put three.min.js inside cient/compatibility/.
But you are probably better off using a package, choose carefully the one who is more likely to upgrade to revision 69 quickly in a few weeks or so.
If I try to just copy and paste my JavaScript into a separate file, it won't find the min.three.js file (it tells me THREE isn't defined)
It sounds like you're running into an issue where your JS files are loaded before min.three.js. You might be able to fix that by taking advantage of Meteor's JS load order - files in directories called lib are loaded first, so if you put your min.three.js file inside /client/lib it will load before source files outside that directory.
Another option would be to use a package - for example, meteor add aralun:three.
I'm looking for some advice on the best way to hold my JavaScript (jQuery) functions.
I am developing in MVC/razor and therefore have a layout page. I include my jQuery library and an external JavaScript file in here so it's available in every single page.
This is working well, but I am now becoming very aware of the fact that I am adding almost 300 lines of JS to EVERY page, where maybe half of that is used in any one of these pages.
One function is not in the external file and instead sits inside the HTML because I need to use variables set in my razor code.
I have a couple of questions around this arrangement:
Is placing JS inside the HTML generally acceptable when variables set using razor are used? There does not appear to be a clean way of passing a variable into an external js file
Should I split my functions down in to individual JS files and just include what is needed for each page in the site?
If I were to split them into multiple files, how would that work with jQuery's (document).ready ? Do I need to use that if all the JavaScript I am including is to be used?
I'm sure this will more a matter of opinion than a black and white answer, but I want to consider all my options before moving on. Even though it works fine as is, I can't help but feel there is a better/cleaner way.
Remember once a user lands on your homepage and loads the javascript file it will be cached in their browser so subsequent pages will not download the Javascript again.
I would definitely keep the js separate, you could have a snippet on each page that initialise the JS that that particurlar view needs. Put something like the below in the views that need to run JS
$(document).ready(function() {
mysite.mypage();
});
Then the function mysite.mypage() can be defined in the external JS file.
300 lines isnt the end of the world, I would say its probably too early to be worryign about optimisation.
You could always look at minifying that JS file to decrease the size. A quick and easy way to do this is here:
http://www.minifyjavascript.com/
Have you ever heard of require.js? http://requirejs.org/ I find it really useful.
It's a module loader so you are able to split all of your JS code into individual files and load only the ones you need on each page.
I don't know about passing a variable to an external JS file, I don't think its possible / the 'right' way.
You can make each external JS file into a function that accepts and returns parameters. Then in the page you need to use it:
- include the file dependancy
- call the function
Thats what I do, seems like your 2nd suggestion.
for the $(document.ready) question its really up to you. You don't have to use it but its useful for some things , check out this overview:
http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
So two part question here. Basically, what is the proper practise for javascript function locations? I assumed it would be to have several MyScriptFile.js files, each with a few functions instead of one huge AllMyScripts.js file, as not every page needs every function.
However I'm not sure how to reference another function from outside of this file...
My situation: I'm using an AJAX request in many of my pages. Each request response is different (drawn from different files, etc) and is very hard to make dynamic (one-script-fits-all would be difficult). However, I do have my MakeAJAXRequest() function which creates the request object, which is standard to all DoSomethingWithRequest() functions.
How do I include MakeAJAXRequest() in the other files which contain the DoSomethingWithRequest() functions? It seems as though I should have been able to find this.. but I havn't come across it.
tl;dr I have MakeObject.js and UseObject.js. How does UseObject() reference MakeObject()?
EDIT: Found that if you include MakeObject BEFORE UseObject in your HTML <script> tags, UseObject will be able to reference MakeObject. Seems a little dirty still, as anybody who wants to use the UseObject script will have to be aware of the MakeObject dependency...
If you want to ensure your dependencies are loaded, you could use a function such as this: http://phpjs.org/functions/include:433 There is also include_once(), require(), and require_once()
I moved the jQuery in my project over to Microsoft's CDN yesterday so finally have jQuery intellisense back. Yay! However, I apparently need to include the following in all my .js files:
//These references should enable intellisense within this file
///<reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.4.js" />
///<reference path="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js" />
I would prefer to have a single js file which contains the above references such that I have a single, unchanging reference in all my js files like so:
//These references should enable intellisense within this file
///<reference path="/shared/js/stdafx.js" />
The idea is that stdafx.js would be the file containing the jQuery references. Then I have only one place to update the versions or add additional references. I gave it a quick go, but it didn't seem to work. Can anyone figure out a way to make this happen?
Actually the above common reference did work in the end. I didn't realize how quirky VS was in regards to js intellisense. Funny enough it kicked in after compiling the project.
I did try Ctrl-Shift-J which refreshes the JavaScript as well. It takes a few seconds for it to kick in so give it a chance. Another tip I read was dragging the common.js file into the editor of the .js file I wanted to add the common reference to. This sanity check ensured I had the correct path (it did). It added a relative path (../shared/stdafx.js) but I was able to use an absolute path (/shared/js/stdafx.js) which means I can modify the VS .js template for new js files.
So I would suggest anyone who comes across this question to persevere, refresh the JavaScript, compile, even close and reopen VS as it will hopefully kick in for you eventually.
For anyone still wanting jQuery intellisense in their .js files (and why wouldn't you) you need to 'reference' the correct jQuery VSDOC file, that MS created for Visual Studio intellisense:
///<reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2-vsdoc.js" />
To test it, type:
$(
You should see full intellisense with PARAMETERS, as well as members. If you only see a single list of members, it's not working.
I'm currently on a project that is a big site that uses the Prototype library, and there is already a humongous amount of Javascript code.
We're now working on a piece of code that will get "injected" into other people's sites (picture people adding a <script> tag in their sites) which will then run our code and add a bunch of DOM elements and functionality to their site. This will have new pieces of code, and will also reuse a lot of the code that we use on our main site.
The problem I have is that it's of course not cool to just add a <script> that will include Prototype in people's pages. If we do that in a page that's already using ANY framework, we're guaranteed to screw everything up.
jQuery gives us the option to "rename" the $ object, so it could handle this situation decently, except obviously for the fact that we're not using jQuery, so we'd have to migrate everything.
Right now i'm contemplating a number of ugly choices, and I'm not sure what's best...
Rewrite everything to use jQuery, with a renamed $ object everywhere.
Creating a "new" Prototype library with only the subset we'd be using in "injected" code, and renaming $ to something else. Then again I'd have to adapt the parts of my code that would be shared somehow.
Not using a library at all in injected code, to keep it as clean as possible, and rewriting the shared code to use no library at all. This would obviously degenerate into us creating our own frankenstein of a library, which is probably the worst case scenario ever.
I'm wondering what you guys think I could do, and also whether there's some magic option that would solve all my problems...
For example, do you think I could use something like Caja / Cajita to sandbox my own code and isolate it from the rest of the site, and have Prototype inside of there? Or am I completely missing the point with that?
I also read once about a technique for bookmarklets, were you add your code like this:
(function() { /* your code */ })();
And then your code is all inside your anonymous function and you haven't touched the global namespace at all.
Do you think I could make one file containing:
(function() {
/* Full Code of the Prototype file here */
/* All my code that will run in the "other" site */
InitializeStuff_CreateDOMElements_AttachEventHandlers();
})();
Would that work? Would it accomplish the objective of not cluttering the global namespace, and not killing the functionality on a site that uses jQuery, for example?
Or is Prototype too complex somehow to isolate it like that?
(NOTE: I think I know that that would create closures everywhere and that's slower, but I don't care too much about performance, my code is not doing anything that complex)
If you're injecting your code into other sites, either require that they also include prototype, or don't use a library at all.
Any other option is, in my opinion, far too intrusive.
Daniel,
I am running into the same issue for some of the same reasons. Thanksfully, I am able to use jquery. What I want to do is create a single js file that will load up an instance of jquery and any dependent libraries I need. Then I want to load up css in the same way.
I found a script that will load these files into the DOM, but they don't seem to work. Here is what I am using:
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
I can see in firebug that the css is loaded, but the contents of my css file are not coming through. I had hoped that I could dynamically load the libraries I needed based on the tools that this WIDGET used. So I would like to do some programmatic logic that would determine which libraries and css files should be "imported".
Not sure if this line of thinking plays into your efforts, but I would love to get your thoughts, or see where you end up going with this.