How can you pass a string via proxy when binding event handlers? I want to pass a data attribute that is attached to the target handler to a method of an object. Is this possible?
function ReservationSchedulePicker(reservationType){
//Reservation Type Accepted Use: 'routine' || 'vacation'
this.reservationType = reservationType;
//DIV for Schedule Picker
this.schedulePickerDiv = $("#schedulePicker");
//Add Event Handler to Anchor
$(this.schedulePickerDiv).on( "click", "#addWalk", $.proxy(this.openAddWalkDialog, this));
}
}
ReservationSchedulePicker.prototype.openAddWalkDialog = function(event, day) {
//Trying to pass the data-day value to this function using proxy
}
//I need the data-day value inside of openAddWalkDialog Is this possible?
<a href="#" id="addWalk" data-day="monday">
Is this what you are looking for:
<script type="text/javascript">
function ReservationSchedulePicker(reservationType){
this.reservationType = reservationType;
this.schedulePickerDiv = $("#schedulePicker");
this.schedulePickerDiv.on( "click", "#addWalk", $.proxy(this.openAddWalkDialog, this));
}
ReservationSchedulePicker.prototype.openAddWalkDialog = function(event) {
event.preventDefault();
alert(this.reservationType);
}
$(document).on('ready',function(){
var x = new ReservationSchedulePicker('hello world');
});
</script>
<div id="schedulePicker">
Hello
</div>
Update 1: Based additional details provided in comments
<script type="text/javascript">
function ReservationSchedulePicker(reservationType){
this.reservationType = reservationType;
this.schedulePickerDiv = $("#schedulePicker");
this.schedulePickerDiv.on( "click", "#addWalk", $.proxy(this.openAddWalkDialog, this, $("#addWalk").attr('data-day') ));
}
ReservationSchedulePicker.prototype.openAddWalkDialog = function(attr, event) {
event.preventDefault();
alert(this.reservationType + '=>'+ attr);
}
$(document).on('ready',function(){
var x = new ReservationSchedulePicker('hello world');
});
</script>
<div id="schedulePicker">
Hello
</div>
Update 2
<script type="text/javascript">
function ReservationSchedulePicker(reservationType){
this.reservationType = reservationType;
this.schedulePickerDiv = $("#schedulePicker");
this.schedulePickerDiv.on( "click", "#addWalk", $.proxy(this.openAddWalkDialog, this ));
}
ReservationSchedulePicker.prototype.openAddWalkDialog = function( event) {
event.preventDefault();
alert(this.reservationType + '=>'+ ($(event.target).data('day'))) ;
}
$(document).on('ready',function(){
var x = new ReservationSchedulePicker('hello world');
});
</script>
<div id="schedulePicker">
Hello
</div>
What about something like reference arguments to proxy:
$(this.schedulePickerDiv).on('click', '#addWalk', $.proxy(this.openAddWalkDialog, this, { foo: bar }));
Or on the event.data object (event.data.foo):
$(this.schedulePickerDiv).on('click', '#addWalk', { foo: bar }, $.proxy(this.openAddWalkDialog, this));
This should do the trick:
var that = this;
$(this.schedulePickerDiv).on("click", "#addWalk", function(e){
that.openAddWalkDialog.call(this, e);
});
ReservationSchedulePicker.prototype.openAddWalkDialog = function(event) {
console.log(event, $(this).data('day'));
}
Related
I have button that creates a div on click. I want to return this created div when I click a button. But the following code actually returns this button.
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
})
var test = create.trigger('click')
console.log(test)
Result is:
init [div#create, context: document, selector: '#create']
Is this not possible to do this this way or am I missing something?
No, it is not possible. You can add a function which will be executed in your event handler to do something with the object you create in the listener:
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
doSomething(content)
})
create.trigger('click')
function doSomething(test) {
console.log(test)
}
There is no other way and it is because the handler function assigned with .on() method is called when the browser triggers an event (or you use .trigger() method) and the return statement is used only to force calling event.stopPropagation() and event.preventDefault() methods (you have to return false in the handler or just assign false instead of a function as an event handler - check the documentation, section The event handler and its environment) and not to return any value when you trigger an event manually.
You can also use an external variable to store the data "generated" in your event handler:
const divs = []
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
divs.push(content)
doSomething()
})
create.trigger('click')
function doSomething() {
console.dir(divs)
}
You're calling a variable ("create") which stores the event listener on the button. This is what it looks like:
var test = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
}).trigger('click')
console.log(test)
This is the solution:
jQuery
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
JavaScript
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.click();
(jQuery) Live example
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<button id="create">Create</button>
(JavaScript) Live example
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
<button id="create">Create</button>
Tell me please, why removeEvent is not working and click on body working after removeEventListener was called. I just make it more simple for good understanding
p - my object with properties and methods;
p.is_open - true/false property;
p.switcher - DOM element;
function MyClassname(){
.......
p.switcher.onclick = function(e){
if(p.is_open){
p.close();
document.body.removeEventListener('click', p.close.bind(p));
}else{
p.open();
document.body.addEventListener('click', p.close.bind(p));
};
e.stopPropagation();
};
.......
};
.......
MyClassname.prototype.close = function(){
var p = this;
p.is_open = false;
p.switcher.className = 'closed';
};
MyClassname.prototype.open = function(){
var p = this;
p.is_open = true;
p.switcher.className = 'open';
};
I can solve this task in another way, but I want to get the problem.
Thanks.
You can't remove the event listener because you have to store p.close.bind(p) in a variable.
Something like this:
function MyClassname(){
var closeHandler = p.close.bind(p);
.......
p.switcher.onclick = function(e){
if(p.is_open){
p.close();
document.body.removeEventListener('click', closeHandler);
}else{
p.open();
document.body.addEventListener('click', closeHandler);
};
e.stopPropagation();
};
.......
};
.......
MyClassname.prototype.close = function(){
var p = this;
p.is_open = false;
p.switcher.className = 'closed';
};
MyClassname.prototype.open = function(){
var p = this;
p.is_open = true;
p.switcher.className = 'open';
};
The bit p.close.bind(p) wil create a new function with the same body.
It is an entirelly new object. And comparing 2 different objects returns false.
Partially quoting MDN about the .bind() method:
The bind() method creates a new function that, when called, has its this keyword set to the provided value [...].
Here's an example:
var button = document.getElementsByTagName('button')[0];
var handler = function(){
console.log('click');
//this refers to the button
this.removeEventListener('click', handler.bind(this));
};
button.addEventListener('click', handler.bind(button));
<button>Click me</button>
As you can see, the click stays there. Here's another example:
var button = document.getElementsByTagName('button')[0];
var handler = (function(){
console.log('click');
//this refers to the button
this.removeEventListener('click', handler);
}).bind(button);
button.addEventListener('click', handler);
<button>Click me</button>
Storing the result of the .bind() inside a variable allows you to do as you wish, and you are refering to the same exact object.
I have been writing a plugin, and i really like this format
Function.prototype._onClick = function() {
// do something
}
Fuction.prototype.addListner = function() {
this.$element.on('click', this._onClick.bind(this));
}
the problem is sometimes i need the element being clicked and the main object. Doing as below i loose the dom element and not using bind looses the main object.
Fuction.prototype.addListner {
this.$element.find('.some-class').on('click', this._onClick.bind(this));
}
To achieve that i go back to ugly version
Fuction.prototype.addListner = function() {
var self = this;
this.$element.find('.some-class').on('click', function() {
self._onClick($(this));
});
}
Is there any better way to do this?
As zerkms, you can use the event.target to achieve what you want.
When using .on, the handler is :
handler
Type: Function( Event eventObject [, Anything extraParameter ] [, ...
] ) A function to execute when the event is triggered. The value false
is also allowed as a shorthand for a function that simply does return
false.
So your _onClick function will receive click event as its 1st parameter, then from event.target, you can now get the clicked item.
var Test = function(sel) {
this.$element = $(sel);
this.value = 'My value is ' + this.$element.data('val');
};
Test.prototype.addListner = function() {
this.$element.find('.some-class').on('click', this._onClick.bind(this));
}
Test.prototype._onClick = function(evt) {
// Get the target which is being clicked.
var $taget = $(evt.target);
//
console.log(this.value);
// use $target to get the clicke item.
console.log($taget.data('val'));
}
var test = new Test('#test');
test.addListner();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="test" data-val="divVal">
<button class="some-class" data-val="Button-A">btnA</button>
<button class="some-class" data-val="Button-B">btnB</button>
</div>
I need to know how is possible to get a plugin variable outside the plugin, to test it with some test framework.
So this is my simplified plugin:
(function ($) {
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
});
});
}
});
})(jQuery);
I need to the variable this.textSend outside the plugin.
I have tried in this way:
$(document).ready(function(){
var testfield = $('.txt');
testfield.myPlugin({
image:"../img/twitter.png"
});
testfield.focus();
testfield.trigger($.Event( "mouseup"));
console.log($.fn.myPlugin.textSend);
});
but the console.log return me undefined
How can i get that variable outside?
Thanks
You will want to make sure you are returning this like so:
(function($) {
$.fn.extend({
myPlugin: function(argumentOptions) {
var self = this;
self.textSend = 'something';
self.inc = 0;
self.mouseup(function(e) {
self.textSend = 'new thing #' + self.inc;
self.inc++;
});
return self;
}
});
})(jQuery);
var instantiated = $('button').myPlugin({});
$('input').val(instantiated.textSend);
$('button').click(function(e) {
$('input').val(instantiated.textSend);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<label>Current textSend:</label>
<input />
<br/>
<button>Change textSend</button>
Hopefully will get you on the right track.
Update
Try new code.
You can store it inside the closed scope you created around your plugin and expose it through another function. Of course it'll need some refactoring, but this is the general idea:
(function ($) {
var whateverNameYouWant; //here
$.fn.extend({
myPlugin: function (argumentOptions) {
var defaults = {
image: 'img/default.png',
};
this.textSend = '';
whateverNameYouWant = this.textSend; //here
var options = $.extend(defaults, argumentOptions);
var globalHere = this;
return this.each(function () {
obj.mouseup(function(e) {
globalHere.textSend = 'test';
whateverNameYouWant = this.textSend; //here
});
});
}
});
$.extend({
getWhateverNameYouWant: function() {
return whateverNameYouWant;
}
})
})(jQuery);
var value = $.getWhateverNameYouWant();
At line console.log($.fn.myPlugin.textSend);
use testfield.textSend . now it has become proprty of selector via myplugin.
I have two functions click and live. I want to pass a parameter from click to live.I tried something like below but it's not working.
jQuery(document).ready(function(){
var test = 'test' ;
jQuery('.item a').click(test);//pass an argument from here
});
jQuery('.item a').live('click',function(e,test) {
alert(test);//access argument here
});
Is this possible?
Update:
function init() {
//When you click on a link
jQuery('.item a').live('click',function(e,test) {
alert(test);
});
}
jQuery(document).ready(init);
jQuery(document).ready(function(){
var test= 'test';
jQuery('.item a').trigger('click', test);
});
I am expecting an alert.
Edit2:
jQuery(document).ready(function(){
(function($){
$('.item').each(function() {
$(this)[0].oncontextmenu = function() { return false }
});
$.fn.ctrl = function(key, callback) {
if(typeof key != 'object') key = [key];
callback = callback || function(){ return false; }
return $(this).keydown(function(e) {
var ret = true;
$.each(key,function(i,k){
if(e.keyCode == k.toUpperCase().charCodeAt(0) && e.ctrlKey) {
ret = callback(e);
}
});
return ret;
});
};
$.fn.disableSelection = function() {
$(window).ctrl(['a','s','c']);
return this.each(function() {
$(this).attr('unselectable', 'on')
.css({'-moz-user-select':'none',
'-o-user-select':'none',
'-khtml-user-select':'none',
'-webkit-user-select':'none',
'-ms-user-select':'none',
'user-select':'none'})
.each(function() {
$(this).attr('unselectable','on')
.bind('selectstart',function(){ return false; });
});
});
};
$('.item').disableSelection();
})(jQuery);
});
Thanks.
You can use trigger() instead, which allows you to pass arguments;
jQuery(document).ready(function(){
var test = 'test' ;
jQuery('.item a').trigger('click', test); //pass an argument from here
});
jQuery('.item a').live('click',function(e,test) {
alert(test);//access argument here
});
Or You can use hidden field to store params need to pass then read it in click function
jQuery(document).ready(function(){
var test = 'test' ;
jQuery('#hiddenID').val(test);
jQuery('.item a').click(test);//pass an argument from here
});
jQuery('.item a').live('click',function(e,test) {
var test = jQuery('#hiddenID').val();
alert(test);//access argument here
});
You can also try this
jQuery(document).ready(function(){
var test = 'test' ;
$('.item a').trigger({type:'click', myParam:test}); // pass the event object with param
});
$('.item a').live('click',function(e) {
alert(e.myParam); //access param here
});
Also remember live is deprecated instead use on.
Update:
jQuery(document).ready(function(){
var test= 'test';
$('.item a').trigger({type:'click', myParam:test});
});
$('.item a').live('click',function(e) {
alert(e.myParam); //access param here
});