How do I attach a jQuery event to a object's method? - javascript

I defined an object with properties and methods. But I can't find how to attach a jQuery function to a method. What I want is : when I click on the object #myTarget change its html text.
I wrote this :
function blockTest(word){
this.word = ""+genRandInt(0, 25);
this.applyNewWord = function(){
$(document).ready(function(){
$("#myTarget").click(function(){
$("#myTarget").html(this.word);
});
});
};
}
Actually, I'm trying to

Accomplishing what you want based on the code you provided isn't the way to go. I'd first create an Object rather than using a function. Insert your attributes inside that object and handle your DOM events separately:
(function($) {
var obj = {
word: "Example Word",
applyNewWord: function() {
return this.word;
}
}
$(function() {
$("#myTarget").on("click", function() {
$(this).text(obj.applyNewWord())
});
});
}(jQuery));
div {
border: 1px solid black;
cursor: pointer;
padding: 5px;
}
<div id="myTarget">Dummy Text</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

function blockTest(word){
var self = this;
self.word = ""+genRandInt(0, 25);
self.applyNewWord = function(){
$("#myTarget").click(function(){
$(this).html(self.word);
});
};
}
make copy of this and don't keep document.ready inside function

Related

How to make the this inside of jQuery event callbacks refer to the jQuery object by default

So by default jQuery uses a HTML Dom Element as the calling object in a event callback
var el = $("#foo");
el.on("click", function()
{
// this will output a div element
console.log(this);
});
Is there a simple way to make it use the jQuery object as the calling function by default instead
so that "this" references the jQuery object and I don't have to wrap "this" in a jQuery constructor.
$("#foo").on("click", function()
{
// this will instead output the jQuery object el declared above
console.log(this);
this.addClass("fee").find(".roo").remove();
});
I want to avoid creating variable names and just use "this" to refer to the jQuery object that added the listener.
You can make your own handler which calls a function bound to the jQuery collection:
const onClick = (selector, callback) => {
const jQueryCollection = $(selector);
jQueryCollection.on('click', callback.bind(jQueryCollection));
};
onClick("#foo", function() {
this.addClass("fee").find(".roo").remove();
});
.fee {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="foo">foo
</div>
Or, extend jQuery:
$.fn.onClickWithThis = function(callback) {
const jQueryCollection = $(this);
jQueryCollection.on('click', callback.bind(jQueryCollection));
};
$("#foo").onClickWithThis(function() {
this.addClass("fee").find(".roo").remove();
});
.fee {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="foo">foo
</div>
I wanted to use a preexisting option if possible, but since there doesn't seem to be one.
I overwrote the on function instead.
Most of the credit to CertainPerformance, but this solution works best since it overwrites the callback and works with the 4 available parameters that on can take.
(function ($)
{
let originalOn = $.fn.on;
$.fn.on = function(...args)
{
for(let key in args)
{
if(typeof(args[key]) == "function")
{
let originalCallback = args[key];
args[key] = function(...args)
{
originalCallback.bind($(this))(...args);
}
}
}
originalOn.bind(this)(...args);
}
})($);

jQuery click event inside prototype extend

I have this code
;(function($, document, window) {
'use strict';
var defaults = {
el: '.na',
};
$.fn.baboy = function( options ) {
var settings = $.extend( {}, defaults, options );
this.each(function(){
var dis = $(this);
$('body').on('click', dis, function(e) {
var text = dis.text();
$( settings.el ).append('Click ' + text + '</br>' );
});
});
};
})(jQuery, document, window);
Then I wanted to use it on two elements
Button 1
<p class="duh"></p>
Button 2
<p class="duh2"></p>
using the function in two elements
$('.btn').baboy({
el: '.duh',
});
$('.btn2').baboy({
el: '.duh2',
});
However, everytime I click any of the a tag, it seems like the other one also runs.
Here the fiddle to see the issue https://jsfiddle.net/xpvt214o/100340/
The issue is because you're using a jQuery object in the selector argument of the delegated on() call. Quite why this then affects all elements not the bound one I'm not sure without digging in to the jQuery source. However I can say that your usage is incorrect; that argument should be a string.
That said, you don't need a delegated event handler at all. You don't need the each() either. You can create the click() event handler on the element(s) the plugin was instantiated on, like this:
;(function($, document, window) {
'use strict';
var defaults = {
el: '.na',
};
$.fn.baboy = function(options) {
var settings = $.extend({}, defaults, options);
return this.on('click', function() {
$(settings.el).append('Click ' + $(this).text() + '</br>');
});
};
})(jQuery, document, window);
$('.btn').baboy({
el: '.duh',
});
$('.btn2').baboy({
el: '.duh2',
});
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
color: #fff;
}
a {
display: inline-block;
background: #a3de14;
padding: 10px 30px;
font-size: 12px;
text-decoration: none;
}
.duh,
.duh2 {
background: #fff;
padding: 10px 20px;
color: #222;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Button 1
<p class="duh"></p>
Button 2
<p class="duh2"></p>
You should also note that this plugin is massive overkill, as the logic for all button instances can be distilled in to a single event handler with 3 lines of code. However I'm going to assume this is just a learning exercise.

jQuery - Combine .hide() and .remove()

I want to define a function to remove element after x milliseconds.
jQuery.fn.extend({
remove: function(x) {
this.hide(x);
//this line won't work
//setTimeout(function(){ this.remove() }, x);
}
});
$("button").click(function() {
$("p").remove(600);
});
p {
background: yellow;
margin: 6px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div>
<p>Hello</p>
how are
<p>you?</p>
</div>
<button>remove</button>
After clicking the button, html looks like this:
<div>
<p style="display: none;">Hello</p>
how are
<p style="display: none;">you?</p>
</div>
<button>remove</button>
My problem is: The line: setTimeout(function(){ this.remove() }, x); didn't work. I think the compiler didn't understand what did this mean?
Can you give me any idea to call remove() function inside setTimeout?
this inside the setTimeout refers to the window object.
Use complete callback of hide()
A function to call once the animation is complete, called once per matched element.
this.hide(x, function() {
this.remove();
});
jQuery.fn.extend({
remove: function(x) {
this.hide(x, function() {
this.remove();
});
}
});
$("button").click(function() {
$("p").remove(600);
});
p {
background: yellow;
margin: 6px 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div>
<p>Hello</p>
how are
<p>you?</p>
</div>
<button>remove</button>
Two issues, firstly this in the setTimeout() does not refer to the element which raised the click, but the window. You need to store the this reference in a variable within the function body. Secondly, inside the setTimeout you call remove() again, which creates a circular reference which only serves to create a new timeout. You need to change the name of the function so that remove() is still valid. Try this:
jQuery.fn.extend({
delayedRemove: function (x) {
var $el = this;
setTimeout(function(){
$el.remove()
}, x);
}
});
$("button").click(function () {
$("p").delayedRemove(600);
});
Example fiddle
No need to use timeout, you can remove the element in the done callback of hide.
jQuery.fn.extend({
remove: function (x) {
this.hide(x, function () {
this.remove();
});
}
});

use jquery hover from class method

I'm trying to use .hover method of jquery in a javascript class:
var test = {
init:function(){
$("#elm li").hover(test.showTitle(this), test.hideTitle());
},
showTitle:function(e){
...
},
hideTitle: function(){
...
}
};
$(document).ready(function() {
test.init();
});
but here this refers to class itself and not to eventObject.
How can I listen for events with jquery from a javascript class?
If you simply remove the parenthesis and the usage of the this keyword, jQuery will call your functions with the required variables as expected within the context of the element.
var test = {
init:function(){
$("#elm li").hover(test.showTitle, test.hideTitle);
},
showTitle:function(e){
console.log(e)
console.log(this);
},
hideTitle: function(){
}
};
$(document).ready(function() {
test.init();
});
You should be applying that to each element that is returned by your class query.
$("#elm li").each(function() {
var $self = $(this);
$self.hover(test.showTitle($self), test.hideTitle());
}
Wrap the call in an anonymous function that gives you access to e.
#("elm li").hover(function(e) {
test.showTitle(e); //or this
}, function(e) {
test.hideTitle(e); //or this
});

Simple jQuery plugin - reference error?

I'm writing simple jQuery plugin and it should search all .camp_row on the page and everywhere when it find .log.active, it should change its border.
$.fn.filtruj = function(){
$(this).on('click', function(){
var that = $(this);
$('.camp_row').each(function(){
$(this).find(that).css('border','10px solid orange');
});
})
}
$('.log.active').filtruj();
The problem is, it wor on only one result. I think that's because "that" refer to a specific .log.active' but no all .log.active.
If I understand the question, you should pass the selector in constructor, then:
$.fn.filtruj = function(selector){
$(this).on('click', function(){
var that = $(this);
$('.camp_row').each(function(){
$(this).find(selector).css('border','10px solid orange');
});
})
}
$('.log.active').filtruj('.log.active');

Categories

Resources