Attach a callback function to a dinamically created button [JS] - javascript

So, I have this function:
create({
text: 'Confirm',
callback: function(){
location.reload();
}
});
function create(options){
$('div').append('<button>'+options.text+'</button>');
}
And I want that, when you click the button, that callback function I passed gets executed. How can I make that? Is it possible with the function being an anonymous function or do I have to name it? For example, I can name it and then change the line of the append code to:
$('div').append('<button onclick="'+options.callbackName+'()">'+options.text+'</button>');
and then create a function with that name and instead of passing a function, passing a string with the name, but I'd prefer the first option.

Create your jQuery element assigning it to a variable and then use the jQuery on method in order to bind your callback to the given function:
function create(options) {
let button = $(`<button>${options.text}</button>`);
button.on('click', options.callback);
$('#container').append(button);
}
function append() {
create({
text: 'Confirm',
callback: function() {
//location.reload();
alert('Hello World');
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>
<button onclick="append()">Append</button>

var btn = $("<button>"+options.text+"</button>");
$("<div>").append(btn);
btn.on("click", options.callBack);

Following your code snippet you could update it to :
create({
text: 'Confirm',
callback: function(){
location.reload();
}
});
function create(options){
var $button = $("<button>");
if ( typeof options.callback === "function" ) {
$button.on("click", options.cb);
}
if ( typeof options.text === "string" ) {
$button.text(options.text);
}
$('div').append($button);
return $button;
}
Your create function, steps by steps, now does the following :
creates a button element
if options.callback is a function then attaches it
if options.text is a string then set it as textNode inside.
returns the created button for convenience
As a side note, on your last remark : this would mean leaking references on the global scope as inline callbacks are executed within the global scope. Probably not what you want. You generally want to avoid this pattern, IMO the only use case for purposely leaking reference of your function on the global scope is JSONP, but that is an entirely different use case :)

You can wrap the callback function into an immediately invoked function expression (IIFE):
function create(options){
$('div').append('<button onclick="(' + options.callback + ')()">' + options.text + '</button>');
}
create({
text: 'Confirm',
callback: function(){
alert('Hello');
}
});
That way you are also able to pass the event object to the callback:
onclick="(function(event){console.log(event.target)})(event)"

function append(){
var btn = $('<button>Button</button>');
$(btn).click(function(){
alert('Text');
})
btn.appendTo($("#container"));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>
<button onclick="append()">Append</button>

Related

binding html events to an instance of a controller class _within_ the constructor

Sorry, probably bit of a noob JS question regarding binding handlers to instances.
I am creating a controller instance with some data that will subsequently be used to process incoming events (the actual use case is composing complex d3 handlers with varying ajax urls and into which I compose the function(s) doing the actual tree update).
RequireJS and jquery are involved, but I suspect my issue has more to do with my specific binding code. I guess I could forego the use of 'this' since I have only one controller per page which can be a global. But this feels like it should be doable, if only I knew how to.
This is how I bind the controller to its target, from within the constructor (doing it outside the constructor seems to work):
function BtnMgr(msg, tgt_id) {
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", this.handleClick);
}
What is going wrong?
When I click on the button, 'this', in the handleClick refers to the html button, not to the controller instance.
If I call the controller instance method directly, 'this' is correct.
I've tried call or creating a wrapper function, as suggested in
How can I bind an event handler to an instance in JQuery?
$(selector).click(function(e) { BtnMgr.prototype.handleClick.call(this, e); });
My button click keeps seeing 'this' as the button, not the controller:
output
global var controller:BtnMgr.I am a button
this:[object HTMLButtonElement],type:
e:[object Object],type:Object
BtnMgr.handleClick:this.msg:undefined
Simplified version:
HTML
page4.html
<!DOCTYPE html>
<html>
<head>
<title>Page 4</title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.15/require.min.js"></script>
<script type="text/javascript">
requirejs.config({
baseUrl: '.',
paths: {
"jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
}
});
var controller;
require(["main4"], function(BtnMgr) {
controller = new BtnMgr("I am a button", "btn_click");
//this simulated call works - 'this' refers to the BtnMgr instance
controller.handleClick("dummy_btn");
});
</script>
</head>
<body>
<button id="btn_click">click me!</button>
</body>
</html>
RequireJS
main4.js
define(["jquery"], function($) {
function BtnMgr(msg, tgt_id) {
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", this.handleClick);
}
BtnMgr.prototype.toString = function(){
return "BtnMgr." + this.msg;
};
BtnMgr.prototype.handleClick = function(e) {
//I want 'this' to refer to the BtnMgr instance
//and e to the html element that got clicked...
console.log("global var controller:" + controller);
console.log("this:" + this + ",type:" + this.constructor.name);
console.log("e:" + e + ",type:" + e.constructor.name);
console.log("BtnMgr.handleClick:this.msg:" + this.msg);
};
//define is returning the constructor method for the object
return BtnMgr;
});
You could achieve (nearly) what you want with :
$(selector).on("click", this.handleClick.bind(this));
this will be the instance of BtnMgr and e.target will, as always, be the button.
However, that would fly in the face of convention and confuse anyone trying to understand your code, including yourself in 6 months time. In a click handler, this should always refer to the clicked element, as is natural.
If you really must have a reference from the handler back to the instance of BtnMgr that attached the click, then I might opt for "e-augmentation" like this :
function BtnMgr(msg, tgt_id) {
var that = this;
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", function(e) {
e.clickAttacher = that;
that.handleClick(e);
});
}
BtnMgr.prototype.toString = function(){
return "BtnMgr." + this.msg;
};
BtnMgr.prototype.handleClick = function(e) {
console.log("click attacher was instance of : " + e.clickAttacher.constructor.name); // BtnMgr
console.log("button id: " + e.target.id); // xxx
console.log("msg: " + e.clickAttacher.msg); // Hello World!
};
var b = new BtnMgr('Hello World!', 'xxx');
DEMO
Having done that, you have to ask whether it's really worthwhile defining handleClick in that way. Sure, if it's a monster function then yes, define it with BtnMgr.prototype...., but if it's only small, then define it in the constructor itself and take direct advantage of that being in the scope chain (as does the augmenter function above).
Try this when you bind your onClick:
function BtnMgr(msg, tgt_id) {
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", $.proxy(this.handleClick, this));
}
That would make sure that the 'this' variable in your callback is your class and not the clickevent.
You can read more about jQuery Proxy here: http://api.jquery.com/jquery.proxy/

Binding 'this' and getting this

$('.btn-delete').on('click', this.confirm.bind(this));
Above, on click it runs:
p.confirm = function(e) {
if(!$(this).hasClass('danger')){
$(this).addClass('danger');
$(this).bind('mouseleave',function(){
$(this).removeClass('danger');
$(this).unbind('mouseleave');
});
}
else{
this.delete();
}
};
I'm having trouble with this. I need this to get the button but I also need this to access another method (this.delete). I've tried bind but it faisl to work.
Any ideas?
Assuming I'm understanding your question correctly, you want to be able to pass the clicked element as this to the p.confirm function. You should be able to do this by using call, or by using p.confirm as the handler:
// using call
$('.btn-delete').on('click', function (e) {
p.confirm.call(this, e);
});
// as handler
$('.btn-delete').on('click', p.confirm);
Assuming that this.delete is actually p.delete, just use call in the handler to pass the clicked element as this to the delete method:
p.confirm = function (e) {
var self = $(this); // cache lookup, "this" is the clicked element
if (!self.hasClass('danger')) {
self.addClass('danger');
self.bind('mouseleave', function () {
self.removeClass('danger');
self.unbind('mouseleave');
});
} else {
p.delete.call(this); // pass clicked element to use as "this" in p.delete
}
};

jQuery simulate click

I want to trigger a function when the page is loaded. There are many ways to do this.
However, when I add $('#button').click in front of my function, then the getType function is not recognized. For example:
$('#button').click(function getType(id) {
//...some code
});
error: getType is not defined
What am I doing wrong?
Just to clarify, in this case I cannot use an anonymous function. Also, it does not matter to me whether I use $(document).ready or $(window).bind("load", function(), but using these I still get the “getType is not defined” error.
You either have to make your function anonymous:
$('#button').click(function() {
//...some code
});
Or pass the function itself:
function getType() {
//...some code
}
$('#button').click(getType);
If you just want to trigger a click, call .click():
$('#button').click();
Also, your id parameter won't be the element's id. It'll be the click event object. To get the element's id, you can refer to the clicked element using this:
$('#button').click(function() {
var id = this.id;
});
I suggest you read a few JavaScript and jQuery tutorials (in that order).
You are using the inline notation so, you should use an anonymous function (no name function)
your code should be:
$('#button').click(function() {
// do your stuff here
}
);
Beside that, as the titles says, you need to simulate a click event, right ? if so you better use something like:
$('#button').on('click', function() {
alert($(this).text());
});
// somewhere when you want to simulate the click you call the trigger function
$('#button').trigger('click');
see documentation here
$('#button').click(function getType(id) {
//...some code
});
Should be:
$('#button').click(function() {
[...] code here
}
);
function() { } is a callback with what code have to do when I click some element.
If you have the getType function, you can pass it as a callback:
$('#button').click(getType);
If you want to trigger a funcion, when page load, you can do this:
$('#button').trigger('click');
Or
function getType() {
[...] code here
}
getType();
Use .trigger( event [, extraParameters ] ) on the element.
extraParameters
Type: Array or PlainObject
Additional parameters to pass along to the event handler.
The added benefit is that you can pass data to the event handler, whereas if you use .click(), you cannot assign data to the object.
$("#target").trigger('click');
If you're looking to use the extraParameters:
$( "#foo" ).on( "custom", function( event, param1, param2 ) {
alert( param1 + "\n" + param2 );
});
$( "#foo").trigger( "custom", [ "Custom", "Event" ] );
The .click() method requires a callback function. So you can do something like this instead:
//Define your function somewhere else
function getType(id) {
//...some code
}
$('#button').click(function() {
getType($(this).attr('id')); //Execute it when its clicked.
});
Try this, the id can not be passed the way you do:
$('#button').click(function() {
var id = this.id;
//...some code
});

jQuery: Call a function twice

I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});

calling Jquery function from javascript

How can i call a jQuery function from javascript?
//jquery
$(function() {
function my_fun(){
/.. some operations ../
}
});
//just js
function js_fun () {
my_fun(); //== call jquery function
}
Yes you can (this is how I understand the original question).
Here is how I did it. Just tie it into outside context.
For example:
//javascript
my_function = null;
//jquery
$(function() {
function my_fun(){
/.. some operations ../
}
my_function = my_fun;
})
//just js
function js_fun () {
my_function(); //== call jquery function - just Reference is globally defined not function itself
}
I encountered this same problem when trying to access methods of the object, that was instantiated
on DOM object ready only. Works. My example:
MyControl.prototype = {
init: function {
// init something
}
update: function () {
// something useful, like updating the list items of control or etc.
}
}
MyCtrl = null;
// create jquery plug-in
$.fn.aControl = function () {
var control = new MyControl(this);
control.init();
MyCtrl = control; // here is the trick
return control;
}
now you can use something simple like:
function() = {
MyCtrl.update(); // yes!
}
You can't.
function(){
function my_fun(){
/.. some operations ../
}
}
That is a closure. my_fun() is defined only inside of that anonymous function. You can only call my_fun() if you declare it at the correct level of scope, i.e., globally.
$(function () {/* something */}) is an IIFE, meaning it executes immediately when the DOM is ready. By declaring my_fun() inside of that anonymous function, you prevent the rest of the script from "seeing" it.
Of course, if you want to run this function when the DOM has fully loaded, you should do the following:
function my_fun(){
/* some operations */
}
$(function(){
my_fun(); //run my_fun() ondomready
});
// just js
function js_fun(){
my_fun(); //== call my_fun() again
}
var jqueryFunction;
$().ready(function(){
//jQuery function
jqueryFunction = function( _msg )
{
alert( _msg );
}
})
//javascript function
function jsFunction()
{
//Invoke jQuery Function
jqueryFunction("Call from js to jQuery");
}
http://www.designscripting.com/2012/08/call-jquery-function-from-javascript/
<script>
// Instantiate your javascript function
niceJavascriptRoutine = null;
// Begin jQuery
$(document).ready(function() {
// Your jQuery function
function niceJqueryRoutine() {
// some code
}
// Point the javascript function to the jQuery function
niceJavaScriptRoutine = niceJueryRoutine;
});
</script>
jQuery functions are called just like JavaScript functions.
For example, to dynamically add the class "red" to the document element with the id "orderedlist" using the jQuery addClass function:
$("#orderedlist").addClass("red");
As opposed to a regular line of JavaScript calling a regular function:
var x = document.getElementById("orderedlist");
addClass() is a jQuery function, getElementById() is a JavaScript function.
The dollar sign function makes the jQuery addClass function available.
The only difference is the jQuery example is calling the addclass function of the jQuery object $("#orderedlist") and the regular example is calling a function of the document object.
In your code
$(function() {
// code to execute when the DOM is ready
});
Is used to specify code to run when the DOM is ready.
It does not differentiate (as you may think) what is "jQuery code" from regular JavaScript code.
So, to answer your question, just call functions you defined as you normally would.
//create a function
function my_fun(){
// call a jQuery function:
$("#orderedlist").addClass("red");
}
//call the function you defined:
myfun();
I made it...
I just write
jQuery('#container').append(html)
instead
document.getElementById('container').innerHTML += html;
//javascript function calling an jquery function
//In javascript part
function js_show_score()
{
//we use so many javascript library, So please use 'jQuery' avoid '$'
jQuery(function(){
//Call any jquery function
show_score(); //jquery function
});(jQuery);
}
//In Jquery part
jQuery(function(){
//Jq Score function
function show_score()
{
$('#score').val("10");
}
});(jQuery);
My problem was that I was looking at it from the long angle:
function new_line() {
var html= '<div><br><input type="text" value="" id="dateP_'+ i +'"></div>';
document.getElementById("container").innerHTML += html;
$('#dateP_'+i).datepicker({
showOn: 'button',
buttonImage: 'calendar.gif',
buttonImageOnly: true
});
i++;
}
<script>
$.myjQuery = function() {
alert("jQuery");
};
$(document).ready(function() {
alert("Welcome!");
});
function display() {
$.myjQuery();
};
</script>
<input type="button" value="submit" onclick=" display();">
Hope this will work for you!

Categories