var tap = {tap:"tap tap tap",
trrap : function (){
alert(this.tap);
}
};
var tab = {tap:"tab tab tab",
trrab: function (){tap.trrap.bind(this);};
};
tab.trrab();
I want to pass tab object to a function in tap object,it would be like alert(tab.tap); . Both of it have tap property.
You never called the bound function. bind returns a function it does not call it.
var tap = {
tap:"tap tap tap",
trrap : function (){
alert(this.tap);
}
};
var tab = {
tap:"tab tab tab",
trrab: function (){
tap.trrap.bind(this)();
}
};
tab.trrab();
http://jsfiddle.net/hqEXs/
Also you could use call to set the context and call it immediately.
tap.trrap.call(this);
or apply
tap.trrap.apply(this);
Related
I'm trying to create a method that will copy the HTML from another part of the page and then set a click handler for the elements inside of it. Problem I'm having is that the handler is not firing when clicked.
Its funny because when I set the handler as an anonymous function, it fires when clicked, but when I set it to either self.initSizeSZ or myModule.initSizeSZ it won't fire.
// Elements are cached for performance.
var $selectSizes = $('#someSelector');
var $catalogWheels = $('#someOtherSelector');
var myModule = {
// This is the module that calls renderSizeSZ
loadWheels: function(){
if(!this.loaded){
this.renderSizesSZ();
this.loaded = true;
}
},
renderSizesSZ: function(){
var self = this;
var $clone = $selectSizes.clone(false);
var html = $selectSizes.html();
$catalogWheels
.find('#icf_catalog-sizes')
.html(html)
.find('li a')
// if this is set as an anonymous function, it will fire, but as a named function it won't
.click(self.initSizeSZ);
},
initSizeSZ: function(event){
console.log('firing')
}
}
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 want to write unit tests with QUnit and Sinon.Js. I have an application, where the user can click on a button and a modal dialog appers to handle downloading some files. The user can close the dialog and it triggers a method to run to reset some variables. My test code:
$(function() {
$.fn.copy_button = function(){};
ln_download_view = new DownloadModalView();
ln_download_view.modal = {'modal': function() {}};
var download_modal_dialog = $('.download-modal');
download_modal_dialog.modal = function(param){};
var modal_mock = sinon.mock(ln_download_view.modal);
var download_modal_dialog_mock = sinon.mock(download_modal_dialog);
//Should be inserted, because ln_download_view.modal is mocked
//The close button even handler
$('#btn_close_modal').click(function(){
download_modal_dialog.modal('hide');
});
//Dirty stuff to do after the window closes
//Basicly the click triggers this event handler
$('.download-modal').on('hide',function() {
window.clearInterval(window.periodicalTimer);
});
$('div .option-container').click(function() {
if(!$(this).hasClass("selected-option"))
{
$('div #option-presenting').toggleClass("selected-option");
$('div #option-editing-and-presenting').toggleClass("selected-option");
$('.image').toggle();
}
});
module("views");
test("Download modal dialog is displayed", function(){
var modal_triggered = modal_mock.expects("modal").once();
ln_download_view.handleDownloadClick();
ok(modal_triggered.verify());
});
test("Download modal dialog is closed",function(){
var modal_triggered = download_modal_dialog_mock.expects("modal");
$('#btn_close_modal').trigger('click');
ok(modal_triggered.verify());
});
});
What I do not understand is, how can I test/mock/stub this piece of code:
$('.download-modal').on('hide',function() {
window.clearInterval(window.periodicalTimer);
});
I do not have the deep understanding yet.
You can't mock/stub an anonymous function. But you can make a refactoring and stub/mock the named callback.
$('.download-modal').on('hide', onHide);
var onHide = function() {
window.clearInterval(window.periodicalTimer);
};
// ...
sinon.stub(onHide);
Here's my method for this:
In your before each, make a function that doesn't do anything:
var doNothing = function(){};
Then in your test, spy on that:
var spy = sinon.spy(this, 'doNothing');
Then call your method, passing in a callback that fires the doNothing method:
var self = this;
whatever.doSomethingAwesome(
{
finished: function(){
self.doNothing();
}
});
expect(spy.callCount).toEqual(1);
For some reason when I call generateTabs I get this.divRow1 is undefined.
However when I instantiate Criteria it is not undefined.
What am I doing wrong?
function Criteria() {
this.divPortfolio = $("#portfolio_div");
this.divImport = $("#lstimprt_div");
this.rolling = $('#rolling');
this.datePickers = $("#datepickers");
this.dateStart = $("#datepicker");
this.dateEnd = $("#datepicker2");
this.btnToggle = $("#toggle");
this.btnRun = $("#run_report");
this.divRow1 = $("#Row1");
this.dateChoice = $("#datechoice");
this.minDate = $(".minDate");
}
Criteria.prototype.generateToggle = function () {
/** Toggle button toggle elements chosen open/closed **/
button.click(function () {
this.divRow1.toggle("slow");
this.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
});
};
/** When page loads **/
$(document).ready(function () {
var controls = new Criteria();
var mindate = controls.minDate.html();
controls.onloadHide();
controls.generatePicker(controls.dateStart);
controls.generatePicker(controls.dateEnd);
controls.generateToggle(controls.btnToggle);
});
it is because of the execution context of the callback method is not the Criteria object, it is the clicked button.
One solution to this is to pass a custom execution context using $.proxy()
button.click($.proxy(function () {
this.divRow1.toggle("slow");
this.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
}, this));
Another solution is to use a closure variable
var that = this;
button.click(function () {
that.divRow1.toggle("slow");
that.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
});
button.click(function () {
this.divRow1.toggle("slow");
this.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
});
this has a different scope within the click event than outside of it. Specifically, jQuery will bind this to the item the event is being fired on (the button in this case). If you set a breakpoint and examine this in the dev console at this point you'll see it refers to a DOM element.
You can get around this by setting a self variable like this, and referencing that instead.
Criteria.prototype.generateToggle = function () {
var self = this;
/** Toggle button toggle elements chosen open/closed **/
button.click(function () {
self.divRow1.toggle("slow");
self.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
});
};
Criteria.prototype.generateToggle = function () {
var that = this;
/** Toggle button toggle elements chosen open/closed **/
button.click(function () {
that.divRow1.toggle("slow");
that.divImport.toggle("slow");
$("#mindate_div").toggle("slow");
$("#header_row").toggle("slow");
return false; //Stops postback
});
};
The "this" context has changed inside the button click. Try the above
I have the following code. The first attempt at binding to click event does not work. The second way does. The first shows the alert "CheckBox1" during Page_Load. The second one shows the alert "CheckBox4" during the proper time -- during clicks.
$(document).ready(function () {
$(document.getElementById(checkBox1ID)).click( SetCheckBox1State(this.checked) );
$(document.getElementById(checkBox4ID)).click(function () { SetCheckBox4State(this.checked) });
});
function SetCheckBox1State(checked) {
alert("CheckBox2");
var radNumericTextBox1 = $find(radNumericTextBox1ID);
var wrapperElement = $get(radNumericTextBox1._wrapperElementID);
var label = $(wrapperElemenet.getElementsByTagName("label")[0]);
if (checked) {
radNumericTextBox1.enable();
label.addClass("LabelEnabled");
label.removeClass("LabelDisabled");
}
else {
radNumericTextBox1.disable();
label.addClass("LabelDisabled");
label.removeClass("LabelEnabled");
}
}
function SetCheckBox4State(checked) {
alert("CheckBox4");
var radNumericTextBox2 = $find(radNumericTextBox2ID);
var wrapperElement = $get(radNumericTextBox2._wrapperElementID);
var label = $(wrapperElemenet.getElementsByTagName("label")[0]);
if (checked) {
radNumericTextBox2.enable();
label.addClass("LabelEnabled");
label.removeClass("LabelDisabled");
}
else {
radNumericTextBox2.disable();
label.addClass("LabelDisabled");
label.removeClass("LabelEnabled");
}
}
Am I doing something improper? I'd rather not use an anonymous function...but maybe this just how things work?
This code:
.click( SetCheckBox1State(this.checked) );
Assigns the .click() function to be the output of this function: SetCheckBox1State(this.checked).
You will have to get rid of the argument (make it internal) and just pass the function name:
.click( SetCheckBox1State );