Following is a piece of code in the Django 3 by example book we can use to bookmark in a browser and upon clicking the bookmark, the code in it will be executed.
Can anyone please help me understand this code?
(function(){ if (window.myBookmarklet !== undefined){ myBookmarklet(); } else { document.body.appendChild(document.createElement('script')).src='https://127.0.0.1:8000/static/js/bookmarklet.js?r='+Math.floor(Math.random()*99999999999999999999); } })();
Why do we need to put the function inside parenthesis? (function.....)()
How the browser executes the code. We put a javascript tag at the start of the code.
JavaScript:(function.....)()
what is this function myBookmarklet() and when if statement will be actually executed? How will the window object have myBookmarklet property?
Any relevant resources will be appreciated. Thanks a lot
It's because it's an anonymous function, it has no name. Because it has no name and needs to be executed, it has to be surrounded with parenthesis to be able to run it by calling it with () at the end.
Exactly like that. If you want to write a function that will not be needed in any other place, you can define it without a name so it's anonymous. To call it, see 1.
Before that js code, the HTML file has probably a series of <script> tags where it defines certain dependencies, in this case javascript files. One of those js files has assigned myBookmarklet to window, like this: window.myBookmarklet = //... a function definition. The code you posted is checking if window.myBookmarklet !== undefined before calling that function.
Related
I'm trying to modify/limit/prevent access to certain JS commands of my browser. For example commands like navigator.clipboard; However, I'm not sure how to approach this.
Is it possible to override these commands with user-defined javascript injected in the page, or do i have to edit the browser's javascript compiler and re-compile it from source for this?
I'm not really familiar with browsers and want to save time by knowing a general direction to follow. Thanks
First of all navigator.clipboard is not a function, but here is an example using the read function of navigator.clipboard:
navigator.clipboard.read = function (originalFunction) {
return function (yourParamsYouWantForThisFunction) {
// Do Stuff you wanna do before the real call. For example:
console.log(yourParamsYouWantForThisFunction);
// Call the original function
return originalFunction.call();
};
}(navigator.clipboard.read); // Pass the original function reference as a parameter
You may wonder, why there are two function statements:
The first one is there, so that we can pass the original function at runtime. If we would not do that, we would not be able to access the original navigator.clipboard.read function.
The second function is the actual function, that you will be using later, when you call navigator.clipboard.read().
I am working on a project that uses AJAX to download HTML, CSS and Javascript in one singe chunk of text then appends it to an element on the page. Here is the code:
_t.stage.empty();
_t.stage.html(DATA);
This works fine.
Here is the problem:
After adding the HTML to the stage, I call this function:
if(initApp != null && typeof(initApp) == "function") initApp();// Checks for initApp(). If exists, executes.
If I load a page that has this function, then load one that does NOT have this function, the function from the first page is executed. Here is some psuedo code to understand the results.
page 1:
This is a page.
<style>...</style>
<script> function initApp(){ alert("hello"); } </script>
When this page is run, an alert box with the text 'hello' is shown.
page 2: (no initApp() function)
This is page 2.
<style>...</style>
When the page is run, an alert box with the text 'hello' is shown.
Please note: These pages are loaded with AJAX and inserted into the HTML of an already loaded page.
It is not easy to tell exactly what you're trying to do, but if what you're trying to do is make it so that some other code that calls initApp() will cause nothing to happen when it calls that, then you can simply redefine the function to a do-nothing function like this:
initApp = function() {}
The most recent definition of a function takes precedence (e.g. replaces any prior definitions).
If your newly loaded code contains an implementation of initApp() that you don't want called the second time the script is loaded, then you're out of luck. You can't stop that. You will need to change the structure of your code so that the dynamically loaded code doesn't execute stuff you don't want to be executed. There are many different ways you could do that. For example, you could have a global boolean that keeps track of whether the init code has been called yet.
var initCalled = false;
function initApp() {
if (!initCalled) {
initCalled = true;
// rest of initialization code here
}
}
initApp(); // will only actually do anything the first time it's called
// even if it is loaded more than once
It appears from the comments that you seem to think that reloading a script tag with different code will somehow make code from the previous script go away. It will not. Once a function is loaded, it stays loaded unless it is redefined to mean something else or unless some code explicitly removed a property from an object. It does not matter how the code was loaded or whether it was in the core page or an external script file.
Javascript functions that no longer exist
This is a bad premise. The functions still exist, which is obvious from the fact that the second AJAX load ended up executing it. The fact that the <script> tags are replaced and no longer in the document doesn't undefine the function. It's like asking why is your TV still broken if the burglar that broke it is no longer there.
There are two basic things you can do:
a) Clear the function explicitly yourself:
if (initApp != null && typeof(initApp) == "function") {
initApp();
delete window.initApp;
}
b) Change the function name to be unique per AJAX page (or namespace the function with the same idea), probably tied to the name of the AJAX page, so you can invoke it in a more specific manner.
carts.js.coffee
$(document).ready ->
add_book: () ->
alert "hihi!!"
I have tried to invoke window.add_book(); and add_book(); in
add_to_cart.js.erb
But both can not work.
add_book();
window.add_book();
And there didn't display the error on Firebug or Webrick console
By the way, I can not understand
What is the meaning when vars or functions in
(function() {})
or when function embraced by {{ }}
({
add_book: function() {
return alert("poc123!!");
}
});
Is there any tutorial or keyword term can let me find related resources?
Thanks in advance
The reason is you can't use $(document).ready in js erb or coffee erb.
When you deliver this js erb through Ajax, document has been ready for a long time. The functions inside your erb will never get chance to be called if they are under document ready.
So the simple fix is, remove document ready, and invoke the functions directly.
I'm not sure what you expect using add_book: inside a function, but that's certainly not what you wanted. Here is the generated javascript for your code :
$(document).ready(function() {
return {
add_book: function() {
return alert("hihi!!");
}
};
});
You are returning an object containing the function, but no one can access it since it's not referenced by anyone.
What you want is a variable, able to contain a reference :
$(document).ready ->
window.add_book = () ->
alert "hihi!!"
Now, you can use it anywhere (after domready, of course), calling directly add_book().
If your use chrome, this extension may help you to spot coffeescript problems : it's a live shell that let you see the computed js and run coffeescript code.
On a side note, I would recommend against using coffeescript until you feel fluent with javascript.
Here is my question, I am using jsp script, trying to match a key word in requesting url and do something:
<script>
$url = '${pageContext.request.requestURL}';
if("${fn:contains(url, 'key')}" == true){
...
}
....
But this doest work... I am not sure where the problem is but I want it to be like when url contains this string, go in to the if condition.
Thank you
You are mixing JSP/EL and JavaScript as if they run in sync. This is wrong. JSP/EL runs in webserver and produces HTML code which get executed in webbrowser. JavaScript (JS) is part of the generated HTML code and runs in webbrowser only.
You need to do it either fully in JSP/EL, or fully in JavaScript. You can use JSP/EL to dynamically generate JS code which get later executed when the page arrives at browser. Rightclick page in browser, do View Source to see what JSP/EL has generated. You should not see any line of JSP/EL. You should only see HTML/JS code. It's exactly that JS code which get executed then.
You're using a JSP EL function to test a JS variable which isn't in the variable scope at that moment at all. This is not going to work. It can only test JSP/EL variables.
Here's how you could do it in pure JS:
<script>
var url = window.location.href;
if (url.indexOf('key') > -1) {
// ...
}
</script>
If you really insist in doing it using JSP/EL, you could do as follows:
<script>
var url = '${pageContext.request.requestURI}';
if (${fn:contains(pageContext.request.requestURI, 'key')}) {
// ...
}
</script>
This will then generate the following JS code (rightclick page in browser and View Source to see it):
<script>
var url = '/some/uri';
if (true) {
// ...
}
</script>
But this makes no sense. Whatever functional requirement you need to solve, you need to think twice about the right approach. Feel free to ask a new question about solving the concrete functional requirement the proper way.
If you want a parameter that the page was requested with, use ${param.paramName}. So in this case ${param.key}. See implicit objects in the docs. And if you just want to check it has a value try ${not empty param.key}.
I have problems with calling a JavaScript function (which is inside of an object, in it's own .js file) from an other HTML page. In the code exsample I'll just use a simple Hello World function.
//.js file
window.addEvent('domready',function(){
var Site = {
//Here I have like three other functions
//This function I want to detect the browser version. I use MooTools for this
detectBrowser : function(){
if(Browser.ie){
//Then what ever content goes here
}
}
}
//I execute the other three functions here because they need to be called on every page
Site.dropdownmenu();
Site.accordion();
Site.lightbox();
});
I'm working with MooTools so I have wraped everything inside of the domready function.
Now, I want this cetect function to execute only at one page. I have tried somethink like this:
//In the HTML file between two script tags:
Site.alert();
That does'nt work. Any ideas?
If I execute it in the .js file it works fine. But I don't want it to execute at every page.
If you declare a variable with var in a function, the variable is local to that function and inaccessible from outside that function. To make it explicitly global, declare it as a property of window:
window.addEvent('domready',function(){
window.Site = ...
This isn't necessary for the code to work, it just makes it explicit for programmers that might read your code that Site is a global.
External Javascript files just execute code; the code doesn't know where it's coming from.
As long as your code runs after the external JS file, it will work fine.