I'm a beginner with JS.
I am working with some JavaScript on a site, and I just want to use only 1 file of JS for determine the actions off the pages. Something like this:
function registerEvents(){
NameOfHTMLDocument = //?? Get the name of the document that called registerEvents function.
switch(NameOfHTMLDocument)
{
case:"homepage":
hmp_btn = document.getElementById("hmp_btn");
hmp_btn.onclick=otherFunction;
break;
case:"otherPage":
elem = document.getElementById("elemID");
elem.onclick=fooFunction;
break;
//etc...
}
}
This function is called with a <body onload="registerEvents()"> that is "inherited" by all the pages.
The question is, How can I get the "NameOfHTMLDocument"?. Because I don't want that JS begin doing weird things when trying to get elements that don't exist.
I found that I can get the URL of the DOM and then play a little with it to get the string that i want, but i'm not sure if this is the better way of doing it.
It Would be nice if you have a better suggestion.
Firstly I would really suggest that you create separate script tags in html documents for functionality that is used only on that page and common functionality in separate file for several reasons:
No code pollution
Ease of change
Smaller download
Secondly, you can use switch on window.location.pathname DOM variable which is everything after domain
instead of homepage, etc..
i.e.
url = vader.samplesite.com/light/saber/
window.location.pathname = /light/saber/
(look at http://www.developertutorials.com/questions/question/q-242.php )
window.location.pathname
All you need to do is some parsing, but I'm sure you'll figure that out :) If not, leave a comment.
In your <body onload="registerEvents()"> pass the object this (the BODY in the DOM) through your event function such as : <body onload="registerEvents( THIS )">.
In your function itself, call the object you passed like object.ownerDocument.URL to get the URL including the HMTL document name or object.ownerDocument.title to get the page title.
Related
I made a page I need to have in different instances. In short it is used to fill in different parts of a script and then display said script on the page for the user to copy it.
This script below handles the main part of the job, getting a field from HTML and then i can call the result in html to be displayed.
var urlField = document.getElementById('urlField').value;
var resultUrl = document.getElementById('resultUrl');
resultUrl.textContent = urlField;
Problem: there are different fields, eg. url, startdate, enddate, adschedule, etc. so I would like to have a reusable script that just says get the respective field and result the value which is assigned to it in html.
Can I do this somehow? I was researching the function "this" in javascript, but it is too complicated for my current knowledge. Bear in mind that I am in only a very basic level.
You can find the whole codepen to understand the issue better here: https://codepen.io/kmb5/pen/GxZbZq
Add parameters to your re-usable function and then call it whenever you need to use it. Use javascript to get the required data and pass it in as parameters.
reusable.js:
function myFuncWithParameters(parm1, parm2, parm3){
}
Alternatively:
function myFuncWithParameters(myObject){
//access properties from the object: myObject.parm1, myObject.parm2, myObject.parm3
}
Using the object route might make it easier since the order of the properties will not matter like parameters. Regardless of either method you will have to validate the input.
In your html pages, you will need some More JavaScript and HTML to bring in the JS and call it.
<html>
<head>
<title>my page</title>
<script scr="path to reusable js"></script>
<script src="path to this path's js"></script>
</head>
<body>
my page
</body>
</html>
If you look at the script tags, by importing the reusable js you can use it in javascript that was written / imported further down into the page.
In order to ensure you have access to an imported function, you can check if the function you need is defined:
if(typeof(myFuncWithParameters) !== 'undefined' && typeof(myFuncWithParameters) == typeof(Function){
//myFuncWithParameters will definitely be defined and is a function, if we get in here
}else{
//myFuncWithParameters is not defined and/or is not a function
}
In your html page to call the re-usable function...
var parm1 = value;
var parm2 = value;
var parm3 = value;
myFuncWithParameters(parm1, parm2, parm3);
In you decide to use the object:
var myObject = {
'parm1' : 4,
'parm2' : 6
}
//myObject.parm1 == 4
myFuncWithParameters(myObject);
I am learning about writing custom JavaScript for my Odoo 10 addons.
I've written the following piece of code:
odoo.define('ioio.io', function(require) {
'use strict'
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
})
The code is well loaded and I can see my testing string in the console.
However when this code is being loaded before the target div, so e empty/not yet filled and thus its content is not removed.
Doing it manually from the console works.
My question is what is the right way to do that? And how to know exactly when the code gets executed?
You can
put your html code before the script tag in your file
use jQuery $(document).ready(...);
Place your script at the bottom of the <body> tag to make sure the DOM renders before trying to manipulate it.
This is an Odoo specific question, so you should use the Odoo standard way, which is via its base JS class. That class contains a ready() method which does exactly what you need.
In your case, to use that function, you need to require the class first. Then you can use ready().
Updating your code, it should look like this:
odoo.define('ioio.io', function(require) {
'use strict'
// require base class
var base = require('web_editor.base');
//use its ready method
base.ready().done(function () {
// put all the code you want to get loaded
// once the DOM is loaded within this block
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
});
})
While your accepted answer leads to the same outcome, you might want to update it to this one since this is the Odoo way. It's generally advised to work within the Odoo framework as much as possible and customise only if really needed. (Though it can be tough to learn what features Odoo already provides because of its poor documentation.)
I need to do something seemingly quite simple.
In the same way that I can, from my scala.html file, create a link to another url, /entry, I need to do that from a javascript file.
i.e., from the scala.html:
<div class="footer">
<a href='#routes.Application.index()'>Home</a>
</div>
from my javascript event:
function() myEvent {
window.location="#routes.Application.entry()"; // DOESN'T WORK!
}
For routing from javascript, I've already had to setup my javascript routes for some ajax work I've already had to do.
My ajax work was calling a method 'findPersons()' so in my Application.java file, I had already:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons()));
}
Because I want to be able to redirect to my GET entry() method, I modified it to look like this:
public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter( "appRoutes",
routes.javascript.Application.findPersons(),
routes.javascript.Application.entry()));
}
Additionally I have these in my routes file:
GET /entry controllers.Application.entry()
POST /findPersons controllers.Application.findPersons()
When I am invoking my findPersons method, it is really nice and simple.
It looks like this:
appRoutes.controllers.Application.findPersons().ajax({
data: {
personIdentifier : personIdentifier,
surname : surname,
givenNames : givenNames
},
success : processDBQuery
});
For my simple redirect, I would like to be able to maintain the same loose coupling between my html/javascript code and the urls, as I can the ajax call above.
My redirect needs to occur on an event. Therefore, the easiest and quickest solution would have been simple to write:
function() myEvent {
window.location="/entry";
}
However, then I would be hard-coding the URL (which I have managed to avoid for my ajax call above), no longer maintaining that loose coupling I would so much like to have.
However, I see no examples in the documentation, and from what I have in the generated javascript (for my routes) there is no chance.
Is there any way to achieve what I am after?
thanks for reading!
p.s., I should add; I guess I have also thought of the possibility of using the ajax call that is generated, I guess I can probably fetch the page I want... and there is probably a means of replacing the current document with the entire content of the fetched page. but that just sounds bad.... wrong...
or not?
I was rather hoping for a substitution, as is done in my html
i.e, my link as shown above is generated to look like this:
<div class="footer">
<a href='/'>Home</a>
</div>
In the same way, I hoped there was some means of substitution in the javascript, so that the event function above ends up in being massaged into looking like this:
function() myEvent {
window.location="/entry";
}
Jacques, from the above comments, helped me to realize a work-around.
From within my "assets located" javascript file, I can still refer to page/template located javascript.
Own-file/assets located javascript doesn't seem to be transformed how I expected.
However, Page/template located javascript is transformed exactly how I require.
I can refer to a template located javascript function from my assets located javascript.
This means, I have a little work-around of one extra little function inside the template which does the redirection for me.
i.e.,
myJavascript.js:
function personResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.alert("hello! " + fpersonId);
affectRedirect();
};
}
myTemplate.scala.html
#main("person lookup") {
<script type="text/javascript">
function affectRedirect(){
window.location="#routes.Application.entry()";
} // Need this here so it will be transformed.
// asset located javascript doesn't seem to get transformed like javascript here in template! :(...
</script>
Another possibility is the fact that the Javascript object retrieved by calling:
appRoutes.controllers.Application.entry()
contains a url member. This url member is exactly what I can use to assign to window.location. However, it looks a bit unofficial.. in terms of
1. the member not being documented
2. not sure if the url member will exist in the future
3. the generated javascript is constructing an object dealing with ajax... and i'm just grabbing the URL member from it... it just feels... like a hack.
But i've tested this, and it works. See code below:
function patientResultsListClickHandler(personId) {
var fpersonId = personId;
return function() {
window.location=appRoutes.controllers.Application.entry(personId).url;
// window.location="/entry/" + fpersonId; // the sort of hard-coding of URL that
}; // I wanted to avoid, but don't seem able to.
}
Does anyone else have a better solution?
I am making use of constructors (classes) extensively and would like each constructor to be in a separate file (something like Java). Suppose I have constructors say Class1, Class2, ... Class10 and I only want to use Class1 and Class5 I need to use script tags to include Class1.js and Class2.js into the HTML page. Later if I also need to use Class3 and Class6 I again need to go to the HTML page and add script tags for them. Maintenance with this approach is too poor.
Is there something in JavaScript similar to include directive of C? If not, is there a way to emulate this behavior?
You can use jQuery.getScript:
http://api.jquery.com/jQuery.getScript
Or any of the many javascript loaders like YUI, JSLoader, etc. See comparison here:
https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ
You can use something like this:
jsimport = function(url) {
var _head = document.getElementsByTagName("head")[0];
var _script = document.createElement('script');
_script.type = 'text/javascript';
_script.src = url;
_head.appendChild(_script);
}
then use it in your code like:
jsimport("example.class.js");
Be careful to use this when the head is already in the DOM, else it won't work.
Yes: You can create script tags from JavaScript and load required classes on demand.
See here for a couple of solutions: http://ntt.cc/2008/02/10/4-ways-to-dynamically-load-external-javascriptwith-source.html
With careful use of id attributes or a global variable that contains "already loaded" scripts, it should be possible to develop a dependency resolution framework for JavaScript like Maven or OSGi for Java.
When we are talking about JavaScript, I feel it is better to include one file that includes everything you need instead of requesting a new file every time you need something that you don't currently have access to.
Each time you send out for another file, the browser will do many things. It checks if the requested file can in fact be found by sending an HTTPRequest, and if the browser has already seen this, is it cached and unchanged?
What you are wanting to do is not in the spirit of JavaScript. Doing what you are explaining will produce addition load times, and you wouldn't be able to do anything until the file has completely loaded, which creates wait times.
It would be better to use one file for this, include at the inner end of the </body tag (which won't cause the browser to wait until the script is done to load the page), then create one simple function that will execute when the page is completely loaded.
For example:
<html>
<head></head>
<body>
<!-- HTML code here... -->
<script src="javascript.js"></script>
<script>
(function r(f) {
/in/.test(document.readyState) ? setTimeout('r(' + f + ')', 9) : f()
})(function() {
// When the page has completey loaded
alert("DOM has loaded and is ready!");
});
</script>
</body>
</html>
you can include one js file into another js file by doing something like this in the begginig of your js file:
document.write("<script type='text/javascript' src='another.js'></script>");
The best approach in your situation is using of compiler of some kind. The greatest one is Google Closure Compiler. This is part of Google Closure Libraty which has structure similar to what you described.
I have a CDHTMLDialog, with which I have 2 HTML pages and a .js file with a few fairly simple functions.
I would like to be able to call one of the JS functions from my program with a simple data type passed with it. e.g. MyFunc(int). Nothing needs to be returned.
I would appreciate any guidance on how I go about this,
thanks.
Edit: Thanks to CR for his answer, and everyone else who submitted there ideas too.
Something a little like this worked in the end (stripped a little error handling from it for clarity):
void callJavaScriptFunc(int Fruit)
{
HRESULT hRes;
CString FuncStr;
CString LangStr = "javascript";
VARIANT vEmpty = {0};
CComPtr<IHTMLDocument2> HTML2Doc;
CComPtr<IHTMLWindow2> HTML2Wind;
hRes = GetDHtmlDocument(&HTML2Doc);
hRes = HTML2Doc->get_parentWindow(&HTML2Wind);
if( Fruit > 0 )
{
FuncStr = "myFunc(808)"; // Javascript parameters can be used
hRes = HTML2Wind->execScript(FuncStr.AllocSysString(), LangStr.AllocSysString(), &vEmpty);
}
}
Easiest approach would be to use the execScript() method in the IHTMLWindow2 interface.
So you could get the IHTMLDocument2 interface from your CDHTMLDialog by calling GetDHtmlDocument, then get the parentWindow from IHTMLDocument2. The parent window will have the IHTMLWindow2 interface that supports execScript().
There might be an easier way to get the IHTMLWindow2 interface from your CDHTMLDialog but I'm used to working at a lower level.
the SpiderMonkey library can "Call a JavaScript function from C++", please refer to
http://egachine.berlios.de/embedding-sm-best-practice/ar01s02.html#id2464522
but in your case, maybe this is not the answer.
To give you a hint - javascript injection in server-side-technologies is usually performed through bulk-load at startup (GWT) or injected when the HTML is generated and served each post-back (ASP.NET).
The important point of both approaches is that they inject the javascript calls somewhere in the page (or in a separated .js file linked in the HTML in case of GWT) when generating the HTML page.
Even if you're on win development (looks like it since you're on MFCs) it might be the case that you have to insert your js method call in the HTML and then load (or reload if you wish to interact with the html from your MFC app) the HTML file in your CHTMLDialog.
I don't see any other way of achieving this (maybe I am just not aware of some suitable out-of-the-box functionality) other than editing your HTML and (re)loading it - which is pretty convenient and workable if you have to call your js method once off or just inject some kind of event-handling logic.
Might be a bit of a pain if you have to interact with the page from your MFC app. In this case you have to re-generate your HTML and reload it in your CHTMLDialog.
Either way you can simply have some kind of placeholder in your HTML file, look for that and replace with your javascript code, then load the page in your CHTMLDialog:
onclick="__my_Javascript_Call_HERE__"