I have created a function named “show_alphabet” and assign to a variable named “str”, a string of the letters of the alphabet in uppercase.
I have used the prototype property of the String object to add a method named “sendArray” and assign this (sendArray) a function which returns the split() method. The split() method will split the alphabet string.
I also have a variable named “arr” and I have assigned it the sendArray() method for “str”.
I have a button that when clicked will run the show_alphabet function.
The function is supposed to display the alphabet letters in the “str” as an array with period colon followed by each letter and placing each letter on a separate line.
For example:
A:
B:
C:
…
However, whenever I click on the button, nothing is displayed.
Here is my code:
<form>
<button type = "submit" value = "submit" onclick = "show_alphabet()">submit </button>
</form>
<script type="text/javascript">
function show_alphabet() {
var str = new String("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
String.prototype.sendArray() = function() {
return this.split("");
}
for (i=0; i<str.length-1; i++) {
var arr = str.sendArray(":" + "<br />");
document.write(arr[i]);
}
}
</script>
I couldn't stand these horrible answers, so I felt compelled to offer a correct one.
<button type="button" value="submit" onclick="show_alphabet()">submit</button>
<div id="dynamic"></div>
<script type="text/javascript">
function show_alphabet() {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
document.querySelector('#dynamic').innerHtml = str.split('').join(':<br/>');
}
</script>
To recap some of the issues:
You can't document.write after the DOM has loaded. Doing so will generally only cause you frustration. Instead, as above, tweak the innerHtml or use a dozen other ways to change the DOM.
Set the button as type="button" instead of type="submit". Doing so will preclude either an actual form, or an implied one, from executing.
Your sendArray function didn't make any sense... but neither did most of the answers. Just make the string and set it somewhere, and iteration just isn't necessary here.
Ok I didn't expect to see so many incomplete answers. So let's summarize
The definition of the sendArray prototype function must not have parentheses
Above all, you don't need any sendArray prototype function (unless it is explicitly required by the Homework exercise)
You are passing a parameter to sendArray which you don't use inside the function
The action submit on the button will submit the form and hence refresh the page, so you won't see any other results of your code
You'll have to understand that pushing the button will use document.write, which will (after DOM loaded) always erase the previous document, including your script
Try it like this
<button type="button" onclick="show_alphabet()">Show alphabet</button>
<div id="output"></div>
<script type="text/javascript">
function show_alphabet() {
var str = new String("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
var arr = str.split("");
document.getElementById("output").innerHTML = arr.join(":<br/>");
}
</script>
sendArray = function() instead of sendArray() = function()
Related
I have a simple array loop, runs perfect in jsFiddle showing all items, see https://jsfiddle.net/8odoros/b27ocs4d/1/
What's strange is that putting the same script here as a snippet runs by letter, showing the first string letter by letter. I feel stupid, am I missing something? Check it out:
var name = ['Helen','Jim','Thomas','Luke','Theodore'];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = name[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
<div id="cards"></div>
Word name is a reserved word (as #prasad answered) in javascript that why your code was not working as expected.
See below code, after changing name with names. Its seems working as was working in jsfiddle.
var names = ['Helen','Jim','Thomas','Luke','Theodore'];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = names[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
<div id="cards"></div>
Note: name can only be used as local variable inside a function or iife and can not used as global varibale.
Try any one of the function its working. name is reserved word of javascript.But applied with in function .Its not act as a reserved word.This is one of the way preventing the action.
(function () {
var name = ["Helen","Jim","Thomas","Luke","Theodore"];
var div = document.getElementById('cards');
for(var i=0;i<5;i++){
var newHtml = name[i]+' '+i+'</br>';
div.innerHTML = div.innerHTML + newHtml;
}
})()
<div id="cards"></div>
Apparently name is a property of window and it has a setter which converts the input value to a string. Your code is trying to assign an array to that property which is magically converted to a string:
var name = ["foo", "bar"];
console.log(name); // array converted to "foo,bar"
So why does it work on jsFiddle? The answer is that, by default, jsFiddle wraps your code inside a function, something like this:
<script>
window.onload = function() {
var name = ["foo", "bar"];
console.log(name); // ["foo", "bar"]
}
</script>
This creates a closure where var name creates a new variable instead of referring to window.name. If you change your jsFiddle settings (JavaScript tab > Load type > No wrap - in body) then you get the same result as the StackSnippet like this:
<script>
var name = ["foo", "bar"];
console.log(name); // "foo,bar"
</script>
The solution is not to pollute the global namespace in the first place. That way you do not have to lookup the list of "words not to use as JavaScript variables".
name AKA window.name
Well name is most definitely not a reserved word in javascript.
name AKA window.name is the name of the window. Its value is set by a setter function and as the window name should be a string. So when you set it with name=["foo","bar"] it is converted to a string.
It is unfortunate that Javascript must share the global name space with every man and his dog and this illustrates another reason to avoid the global scope whenever possible.
il8n = {
'en-us':{
hello:"Hello Everyone",
goodbye:"See ya later",
welcome:"Hello how are you?",
design:"Kandi Designs"
}
};
function translate(){
var userLang = navigator.language || navigator.userLanguage;
var body = document.body || document.getElementsByTagName('body')[0];
var html = body.innerHTML;
body.innerHTML = body.innerHTML.replace(/({T_(.*?)})/g, il8n[userLang.toLowerCase()][$1.replace(/{T_|},'').toLowerCase()]);
}
translate();
Basically what I want to do is get rid of {T_Hello} to Hello Everyone but since I suck at regex my capture groups and using $1 I can't get this correctly. Can anyone assist in this a wee bit?
You have the right idea. $1, however, is not a variable where you use it. Change the second argument to replace to this:
function (match, $1) {
return il8n[userLang.toLowerCase()][$1.toLowerCase()];
}
replace can take a function as an argument. Then, shorten the capture group in the regex to this:
/{T_(.*?)}/g
This saves you some unnecessary string processing inside the replace function. On an unrelated note, regarding performance, you might want the server to send the appropriate il8n object based on the Accept-Language header, or, even better, do the insertions itself instead of relying on flaky and slow client-side code (making it cacheable).
Based on your il8n object keys you could do this to check for T_ followed by any uppercase letters.
/T_([A-Z]+)/
You could add lowercase or numbers to it too:
/T_([A-Za-z0-9]+)/
This should work:
body.innerHTML = body.innerHTML.replace(
/({T_(.*?)})/g,
function (s) { return il8n [userLang.toLowerCase()] [s.replace(/{T_|}/g,'').toLowerCase()]; }
);
The second argument of replace() can be a string or a function that takes so many arguments as there are ()-groups in the regular expression, which in your case is one.
Indeed, if you write
s.replace (/a/g, 'b')
then, obviously, replace() receives two strings. However, if you write
s.replace (/a/g, f(x))
then again, replace() receives two strings, the second being the string returned from f(x), so if f(x) returns 'b', then the two expressions above are equivalent. Since f(x) is executed before replace() has a chance to see it, it cannot use the special variables like $1, since at the point of call they are not defined.
If you want the code to be executed by replace(), then it should be executable code:
replace (/a/g, function (x) { return ' [' + x + '] found! '; } )
so that at the point of call, the function object is formed and this function is called inside replace with the argument $1 each time (note the global modifier g in the regex).
Note that your code will only work if placed below the text or called onload(), not above the text:
<body>
{T_hello} reader!
<script>
your code
</script>
<body>
works, but
<body>
<script>
your code
</script>
{T_hello} reader!
<body>
doesn't, because when it is executed, there is nothing still in <body>. The best place to call it is in <body onload='translate()'>.
I also corrected a typo in your code: s.replace(/{T_|} should be s.replace(/{T_|}/.
And another error in your code is: s.replace(/{T_|}/ should be s.replace(/{T_|}/g, because it is supposed to make two replacements, not one.
Let's say I have an object with this markup:
var obj = {
cat: function(string, bool, NEEDTHIS) {
console.log(string, bool, NEEDTHIS);
}
}
Lets say I have the function, with it's variables as an attribute on a button which I have NO control over how it's generated. Example:
<button type="button" onclick="obj.cat('foo', true, 'dog');">PRINT</button>
I need to run this function on the button, but remove the attribute so that I can parse my own attribute.
So I'd strip the attribute 'onclick', store it in a string like so:
var function = "obj.cat('foo', true);";
surely there's a way to just add in another argument without literally altering the string.
I'm also stuck on how I could run the function as it is from the string.
is this possible?
use eval
var function = "obj.cat('foo', true);";
eval(function);
i have a string objects of books which i have got from a JSON objects. This Book object has three Key value pairs, Title,Author and URL. I use a for loop to read each object and just put the title of the object as a button on the html page. But when the button is clicked i want the URL of the book to be alerted. As i read the objects i make Books objects and push it into an array for later use. but i am not able to Use .Click() method the URL is not right. Please see the code for better understanding. :-)
for (i = 0; i < 6; i++) //I know that there is only 65 Books..jsonString.books.lenght is not working.
{
var title = jsonString.books[i].title;
var classname = title.replace(/\s/g, "");
var author = jsonString.books[i].author;
var URL = jsonString.books[i].url;
var htmlString = '<div class="' + classname + '"><input type="button" value="' + title + '"></div>';
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
OneBook = new Book(author, title, URL);
arr.push(OneBook);
}
attachpoint is a reference in the html file that i got from
var attachpoint=document.querySelector('.buttonAttachPoint');
So in the above code the URL that i get on clicking is always the last object in the jsonString. this is happening coz of the for loop. So is there a way i can get to class name of the Div that has onclick or the title of the button so that i can get the URL from the array of objects i created? Or is there an easier way. Also could any one point out why "jsonString.books.lenght" is not working? Thanks in advance.:-) all the help much appreciated. :-)
Creating a closure using an immediately invoked function expression should do the trick. Just replace this:
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
with this:
(function(URL) {
$(htmlString).appendTo(attachPoint).click(function () {
loadBook(URL);
});
})(URL);
URL inside the scope of that anonymous function will have the value passed to it, which will be the correct value for that iteration of the for loop.
In ECMAScript, variables are scoped to their function, rather than any block.
The functions you are binding to click have a closure over URL in the context of the loop as a whole, not over URL in the context of the loop iteration.
This means that whenever any of the functions are invoked, URL will have the last value that the loop sets it to.
You need to freeze the value of URL for each loop. One way to do this is to have a function elsewhere that takes URL as an argument, and returns a function that closes over it, thus:
function getBookLoader(url) {
return function (){
loadBook(url);
};
}
You can then replace your ... .click line with the following:
$(htmlString).appendTo(attachPoint).click(getBookLoader(URL))
To answer the question in the title, the target property of an event contains the object to which the event was dispatched, and the currentTarget property contains the object whose listeners are currently being evaluated. currentTargetshould be the div in question.
Ok noobablicious question. But has had me sumped.
Im declaring the value of a hidden form field with a Js script with in a function.
e.g. These are just examples not the real script.
function myFunction(){
var text = "hello world";
var number = 12345;
document.getElementById('text').value= text;
document.getElementById('number').value= number;
}
Then I want to be able to use the value of the form value as a variable in another script. I realize that there is the option to declare these variables globally. However I have heard that it is not as secure. Or a streamlined as I am going for.
Second Script example...
var autoText = document.getElementById('text').value;
var autoNumber = document.getElementById('number').value;
...do stuff with variables.
However this is not working and returns undefined. Is this the correct DOM path to access the value of my form fields or do I need to find an attribute and its child??
What other options are available to me??
Thanks for your time. HTML is...
<form action="http://mysite/mypath" method="post">
<input type="text" name="text" id="text" value="">
<input type="text" name="text" id="number" value="">
<input type= "submit" name="go" value="go" allign="middle"/>
</form>
That should be fine, assuming that you have the correct ID's set to the elements you want. Remember, that ID's are required to be unique, or unpredictable issues will arise.
Make sure that you are running your code, after the DOM is loaded. Otherwise the element might not yet exist in the DOM, and so the document.getElementById method will fail to find it..
Or, you could just store that data in a closure so that both functions have access to the variable, but it's not stored in the global scope. Like so:
(function(){
var text = "blah blah",
number = 12345;
function insertValues() {
document.getElementById('text').value= text;
document.getElementById('number').value= number;
}
function otherStuffWithValues() {
alert(text);
alert(number);
}
insertValues();
otherStuffWithValues();
}())
Additionally, You could also declare the variables inside the first function, and then pass the variables onto the second function as a parameter like so:
function insertValues() {
var text = "blah blah",
number = 12345;
document.getElementById('text').value= text;
document.getElementById('number').value= number;
otherstuff(text,number)
}
function otherstuff(sometext,somenumber) {
alert(sometext);
alert(somenumber);
}
insertValues()
I think that you haven't set starting script when page load. If so, you can use this simple event handler:
window.onload = myFunction;
With myFunction will be function with yours above code.