What Im trying to do is to get the content of a specific textarea tag in a specific clicks of a button, so I think a loop will solve this problem. The while loop on PHP does the role of making the name of textarea different and button's onclick trigger. But the loop in javascript wont work. Please anyone help what is the right one to complete my task?? Sorry for bad english...Thanks in advance
<html>
<head>
<script>
var i = 0;
while(i < 2000)
{
i++;
function feedbacks+i()
{
var feed = document.getElementsByName("feedback"+i)[0].value;
alert(feed);
}
}
</script>
</head>
<body>
<?php
while($i < 2000)
$i++;
echo "<textarea name='feedback$i' >you post</textarea>";
echo "<button onclick='feedbacks$i()' >send feedback</button>";
?>
</body>
</html>
I'm not sure if i get your question right, but why don't you write one single javascript function and pass the index as a parameter?
like:
function feedbacks(index) {
var feed = document.getElementsByName("feedback"+index)[0].value;
alert(feed);
}
and
onclick='feedbacks($i)'
Your code is incorrect, Since you have tagged your question with Jquery, I would like to suggest the following solution,
$(document).ready(function(){
$(document).on('click','button',function(){
alert($(this).prev('textarea').val())
});
});
You are creating those elements textarea and the button in runtime, So you have to use delegation inorder to register the click event for those buttons. Additionally you have to wrap your code inside .ready() function, Which means you have to manipulate the DOM only after it got ready.
Please see here for references,
.on (for delegation)
.ready()
.prev()
You have two major problems here.
Naming your function
When you name a function, you can't use variables, only a single identifier.
You could use a function expression and then assign the result somewhat that you can identify with a variable. e.g.
an_array_i_created_earlier[i] = function () {
// etc etc
}
Closures
You are trying to use i inside the function you are creating, but you are changing it outside that function before that function runs.
You can get around this by creating a new closure.
function createFunction(i) {
return function () {
// can use i sanely here because it was passed into a local variable belonging to `createFunction`
};
}
an_array_i_created_earlier[i] = createFunction(i);
This is all very messy though. You can forget about having to deal with i entirely, and throw out the horribly intrinsic event attributes while you are at it. Instead, navigate through the DOM to find the element:
addEventListener('click', function (evt) {
var textarea, t = evt.target;
if (t.classList.contains('feedback')) {
textarea = t.previousElementSibling;
alert(textarea.value);
}
});
Note that this uses some fairly recent additions to browser DOM. If you want compatibility with older browsers (in particular IE9 and earlier) then you will probably want to rewrite it to add some support for legacy approaches. A library like YUI or jQuery can help with that.
There's some error in your JavaScript code:
You tried to define a sequence of functions in a loop, and the function became local function to that loop. You cannot get access to these functions outside the loop. In order to make this work, you should define the function on window object, with the syntax window["feedbacks1"] = function () {}.
function feedbacks+i() is invalid syntax, use window['feedbacks' + i], as pointed in (1).
Functions defined in loop will share some local variable (closure). The variable in the function feedbacks#{i} will all share the same i. After the loop, i became 2001 and all the functions defined will try to get textarea with name feedbacks2001, which of course will not work. You will need the (function (i) { /* the code using i */ })(i); trick to make a local copy of the shared variable.
I made a demo on jsFiddle which correct the mistakes. I showed only 2 textareas. The following javascript should work for you 2000 textareas case.
for (var i = 0; i <= 2; ++i) {
window["feedbacks" + i] = (function (i) {
return function (e) {
var feed = document.getElementsByName("feedback"+i)[0].value;
alert(feed);
};
})(i);
}
Related
The question may not be clear, so I will clear that here. I am using require.js to import a script in script. Here is a piece of code :
var vr = {};
vr.example = function(func) {
return require(["https://example.com"], func);
};
So, now I am able to call it by :
vr.example( function() { .... });
But, I am thinking about not writing the function everytime I have to call it. I would like to write something like this :
vr.example({ ... });
And the result should be same. But I can't understand how to do it. So please help
Thanks in advance.
The thing you want can't be done in JavaScript ! But there is a way to do, by making an interpreter. Here is a basic example. I don't really recommend it, well I am showing you just a possibility ;)
window.InterpretData = function() {
var el = document.querySelectorAll("script[type='text/test']") // You can change it anyway !
for(var i = 0; i < el.length; ++i) { // You can use i++ instead of ++i, but ++i is much optimised for this function, watch out their differences in the internet.
var val = el[i].innerHTML
var crt = document.createElement("script")
crt.id = "InterpretedScript"
document.getElementsByTagName("body")[0].appendChild(crt) // Creating a new script element
val = val.replace(/\.example\(\{([\S\s]*?)\}\)/gm, function(_, a) { // Wish you are familiar with regular expressions
a = ".example( function() {" + a + "})"
document.getElementById("InterpretedScript").innerHTML += a;
}
}
}
Now you can do :
<!DOCTYPE html>
<body>
<script type="text/test">
// Defining
var vr = {};
vr.example = function(func) {
return require(["https://example.com"], func);
};
// Calling
var.example({ ... })
<script>
<script>
new InterpretData()
</script>
</body>
</html>
Output :
vr.example({ ... }) converts to vr.example( function() { ... })
Well, remember this example is just to give you an idea about a possibility to solve your problem. It's not the perfect solution though you can't again declare the "example()" to any other constant / variables, that contain different parameters ! So, the only way lies to either use ES6's fat arrows (=>) or just declare the function earlier and go on reusing it ! If you have to support old browsers than go with reusing technique shown by #mbojko, or just go with ES6's fat arrows, said earlier by #deceze. So, want do you think ?
So, you want to pass a block of code not wrapped with a function? Short answer: you can't do that in JavaScript. And require.js does expect a callback function at any rate.
If the callback function is reusable, you can declare it once and reuse it like:
function myReusableCallback(args) {
//...
}
vr.example(myReusableCallback);
And that's pretty much it.
Because the require() function returned from the vr.example() takes a callback function and since this callback function is usually provided by the invocation of vr.example, it, therefore, means you can't necessarily call it with and object as you want to. So you can only use an object if there is no callback expected by the require() an or if you have a static function that you want to be executed all the time then you can implement the function inside of the vr.example and then just pass the object which you need to use inside the function.
It's not possible because {} is not a function, it's an object.
You can try it out yourself using typeof({}) and compare it to typeof(() => {}) or typeof(function() {})
So, I've got my app to work. But I don't want to use a global variable.
Here's what I'm trying to do:
var AMLid;
$(".commentButton").on('click', function () {
AMLid = $(this).closest('tr').siblings().find('p.important').text();
alert("id is:" + AMLid);
});
$(".saveButton").on("click", function () {
$(".modal-body #txtAddComment").val(AMLid);
});
I want to get an ID from a selected table row, and pass the ID to the modal dialog, so I then can use the ID as a parameter when clicking a button in the modal dialog.
How do I do the exact same thing, without using a global variable? is it possible?
And what are the cons of using a global variable like this? Does it crash or target the wrong ID's if many people use it simultaneously?
Any help is appreciated.
You can wrap the whole thing in a function
(function(){
var AMLid;
$(".commentButton").on('click', function () {
AMLid = $(this).closest('tr').siblings().find('p.important').text();
alert("id is:" + AMLid);
});
$(".saveButton").on("click", function () {
$(".modal-body #txtAddComment").val(AMLid);
});
})();
You can avoid the use of a global variable by using an Immediately-Invoked Functon Expression, which would look like this:
(function() {
var AMLid;
$(".commentButton").on('click', function () {
AMLid = $(this).closest('tr').siblings().find('p.important').text();
alert("id is:" + AMLid);
});
$(".saveButton").on("click", function () {
$(".modal-body #txtAddComment").val(AMLid);
});
})();
This works because the AMLid is now private to the function; when the function is executed it creates a new execution context which includes that variable, which is then accessible to statements made in the function, but not outside it. And because this creates a closure the variable continues to be accessible by the callbacks attached to those functions. Moreover, as the function is anonymous it itself doesn't have a name polluting the namespace.
The term Immediately-Invoked Functon Expression comes from Ben Alman, and you can read his original blog post discussing the concept here: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
Some cons of using a global include: hard to keep track of variables, other scripts might mess with its value (when they probably shouldn't have access to it), harder to maintain, less clean code. Your worry about it being overwritten if multiple people use it won't be an issue because it's client-side and so there will be one instance per page loaded in any given browser.
Javascript is client-side so actually I can't get the point in your "many people use it simultaneously". One browser for user, so you don't have to worry about multiple client. Each one use his own set of global variable.
If your executions are not linked in any way (they are "onclick") you can just wrap them in a function so you're actually setting a "local/global" variable.
Every function that'll need that AMLid has to be declared inside that function scope.
The only way to keep variables out of the global scope is by wrapping them in a function. If this is all the code you're using in this particular module, it doesn't really make a difference.
cshtml code
<div class="span3">
#for (var i = 0; i < Model.GroupNames.Count; i++)
{
<ul>
<li>
#{
var item = Model.GroupTypeNames[i];
var selected = i == 0 ? " class=\"selected\"" : "";
}
<a onclick="getGroupType(#item.Id);" data-option-value="*"#Html.Raw(selected)>#item.TypeName</a>
</li>
</ul>
}
</div>
jquery code
function getGroupType(id) {
debugger;
$.getJSON( "Groups/Get" + id, function (data) {
$(".span9").html($("#GroupTemplate").removeData());
$.each(data, function (index, value) {
if (value.Id != undefined) {
$("#GroupTemplate").tmpl(value).appendTo(".span9");
}
});
$('#circle').css("opacity", "0.5");
});
}
Unable to get call here
but when I try to use onclick="alert('Hello');" it is working perfectly
what wrong with onclick="getGroupType(#item.Id);"
As you commented:
my function is in ready
so i think here is a scoping issue, because your onclick handler is not in the ready function so your function getGroupType(#item.Id); is not available for it, instead you can put it outside in the gloabal scope.
getGroupType(id){
// all the stuff
}
$(function(){
// all other stuff
});
I would expect you get the error:
ReferenceError: getGroupType is not defined
Because I suspect that your JavaScript code appears later in the file than your onclick attribute.
When using attributes, make sure the function is defined before the attributes... usually in the <head>. Having said this, normal practice is to include scripts later and attach the events in the script, rather than using attributes.
Also, make sure your function isn't wrapped inside another function. JavaScript is functionally scoped, and a function wrapped in another function won't be callable from global scope.
This all assumes id is actually a number. If the id is a string, remember to wrap it in quotes too. GUIDs must be treated like strings in JavaScript...
onclick="getGroupType('#item.Id');"
You will need to wrap the parameter with Single Quotes.
onclick="getGroupType('#item.Id');"
What I want in html code:
<a onclick="DeleteImage('javascript:this.id', <?=$_SESSION['UserID']?>)"></a>
which passes the var userid from $_session to the javascript function:
function DeleteImage(aid,userid){}
This worked when i didnt had to pass the $_session variable and only had this function
function DeleteImage(aid){}
Then i could create the a element in javascript like this:
cross = document.createElement('a');
cross.onclick = function() { DeleteImage(this.id) };
How can I create the a element so it generates the html code i want?
I want something like:
cross.onclick = function() { DeleteImage(this.id, "<?=$_SESSION['UserID']?>") };
which obviously does not work. Any help appreaciated :)
I think you should change the way you retrieve an information like $_SESSION['UserID']. An interesting option would be creating a data attribute, for example in the <html> tag itself:
<html data-user-id="<?=$_SESSION['UserID']?>">
Then all you have to do is to retrieve that value in the DeleteImage function itself:
function DeleteImage(aid) {
var userId = document.documentElement.getAttribute("data-user-id");
...
}
And you're done, you can call DeleteImage with the old way. (Note: you can also use document.documentElement.dataset.userId in Chrome, Firefox and Opera. There are partial polyfills for IE, but I guess they're not worth the effort in your case.)
You can even save some extra cycles retrieving the value at the beginning of the script and storing it in a scoped variable:
var userId = document.documentElement("data-user-id");
function DeleteImage(aid) {
...
}
Slightly off topic, may I suggest to using some more modern way to attach event listeners? And maybe considering some kind of event delegation?
Why is logfunc "not defined"?
var logfunc = function(obj) {
return function() {
console.log(obj)
}
}
t += '<a onclick="logfunc(this)"><</a>'
Reference to longfunc would not be accessible if it is declared outside of global scope, fiddle
I'm not advocating declaring variables directly in the global scope by omitting var but it makes a good example:
function setupStuff() {
var logfunc = function(obj) { //defined within setupStuff scope
/*...*/
}
t += '<a onclick="logfunc(this)"><</a>';
}
function setupStuffDifferently() {
logfuncB = function(obj) { //defined in the global scope
/*...*/
}
t += '<a onclick="logfuncB(this)"><</a>';
}
I would much rather see the function declared separately like
t += '<a onclick="logfunc(this)"><</a>';
function logfunc(obj) { //this would work when assigned through `onclick`
/*...*/
}
If the option is available to you, I'd suggest using a library like jQuery which offers more flexibility in assigning and handling click events.
You're getting a "logfunc is not defined" error because your logfunc is not in the global (i.e. window) scope and functions that are bound using HTML element attributes must be global.
You can get around that by saying:
window.logfunc = function(obj) {
return function() {
console.log(obj)
}
};
But that still won't do what you think it does since logfunc just returns a function that calls console.log and the <a> won't know that it is supposed to call the function() { console.log(obj) } function, it will just see it as a true value. I think you want:
window.logfunc = function(obj) {
console.log(obj)
};
if you want clicking the link to produce a console message.
As far as the "what are differences between onclick and via the DOM" goes:
Functions attached through attributes must be global and that quickly leads to a big tangled mess.
You can only attach one function per element using onclick but you can call addEventListener as often as you want. You can get around this limitation if you want to paste JavaScript snippets together as strings but that's nasty.
Similarly, you can easily undo an addEventListener call using removeEventListener; removing an event handler from an onclick attribute involves even nastier string wrangling than adding one does.
Using onclick unnecessarily entangles your HTML and JavaScript and that leads to a maintenance nightmare.