i was wondering if someone new how to keep a control with chaining in scope of the "this" key word. It breaks out of the chain when using .find(this).click does anyone know how to keep the chain from breaking
(function($) {
$.fn.mycontrol = function() {
$(window).resize(function() {
alert('resize')
}).scroll(function() {
alert('scroll')
}).find(document).bind('init', function() {
alert('scroll')
}).ready(function() {
$(this).trigger('init');
}).find(this).click(function() {
alert('click'); // $(this) loses scope here
});
})(jQuery);
$(document).ready(function() {
$('#mycontrol').mycontrol()
});
If I understand correctly what you're looking for, you should be able to just save the value of this before you start your chaining:
(function($) {
$.fn.mycontrol = function() {
var that = this;
$(window).resize(function() {
alert('resize')
}).scroll(function() {
alert('scroll')
}).find(document).bind('init', function() {
alert('scroll')
}).ready(function() {
$(that).trigger('init');
}).find(that).click(function() {
alert('click'); // $(this) loses scope here
});
})(jQuery);
Chaining creates unmaintainable code. Break it up into separate lines:
var $window = $(window);
$window.resize(function()
{
alert('resize')
});
$window.scroll(function()
{
alert('scroll')
});
// etc.
Then you can read it, you can step though it with the debugger, you can delete and remove logic with out breaking anything.
window is an object Window.
This is window.document which contains HTML objects.
So $(window).find(this) return jquery empty object as $(window).find(document) too.
$(document).find(this) works instead which is equivalent of $(window.document).
Related
The problem that when I click on .test it does not execute the do_alert(); function and gives me a error:
do_alert(); is not defined.
What's the problem? the main function helpers is already read when the page is loaded why can' get this function from logout_users function?
var setup_system = (function($) {
"use strict";
return {
init: function() {
this.logout_users();
this.helpers();
},
logout_users: function() {
$(document).on('click', '.test', function(e) {
e.preventDefault();
do_alert();
});
},
helpers: function() {
function do_alert() {
alert();
}
}
};
})(jQuery);
jQuery(document).ready(function() {
setup_system.init();
});
NOTE: I try to re-read the helpers function by adding this.helpers() inside logout_users function but nothing change.
It's because you've defined do_alert() within the scope of the helpers function.
To fix this you will need to move that function to within scope of the object you return. You could either put it at root level of the object (which would work fine, but could get messy if you have a lot of 'helper' functions) or you could nest it within your helpers property if you define that as another object. Personally, I'd use the latter to have some semblance of organisation. Try this:
var setup_system = (function($) {
"use strict";
return {
init: function() {
this.logout_users();
},
logout_users: function() {
var _obj = this;
$(document).on('click', '.test', function(e) {
e.preventDefault();
_obj.helpers.do_alert();
});
},
helpers: {
do_alert: function() {
alert('foo');
}
}
};
})(jQuery);
jQuery(function() {
setup_system.init();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">Click me</div>
Note that I cached the reference to the object as _obj outside of the click handler, as within that block this will refer to the clicked .test element.
Do_alert function exist only in helpers method, so you can't access to it.
You need to declare your function directly in the logout_user method or outside, try this :
var setup_system = (function ($) {
"use strict";
return {
init: function () {
this.logout_users();
this.helpers();
},
logout_users: function() {
function do_alert(){
alert();
}
$(document).on('click', '.test', function(e){
e.preventDefault();
do_alert();
});
},
helpers: function () {
function do_alert(){
alert();
}
}
};
})(jQuery);
jQuery(document).ready(function () {
setup_system.init();
});
When helpers is invoked by the initfunction, all that is happening is that do_alert is being declared. But function declarations are hoisted to the top of their lexical scope. The lexical scope of do_alert is the scope defined by the helpers function. Therefore, do_alert is not accessible outside of helpers function.
A couple things you could do. The first one that comes to mind is: you could have the helpers method define a method called do_alert on the object being returned rather than merely declaring a function, like so:
helpers: function() {
this.doAlert = function() {
alert();
}
}
When your doAlert() is invoked by the event handler passed to jQuery, it will not work with the above solution. Instead you will need to make sure you call that doAlert on the returned object in that event handler. This is how you can do that:
logout_users: function() {
var self = this;
$(document).on('click', '.test', function(e) {
e.preventDefault();
self.doAlert();
});
I'm learning how to use objects to help organize my code and give it some structure but I've run into a problem. I don't understand how to set the $(this) from inside of one function to the $(this) of another function.
I'm researching call and apply but I can't seem to grasp how it works in this scenario.
cloneCard and clickCard is where I'm having the problem. I want to pass the $(this) that is referenced when I click the card to the cloneCard function.
Here is my code so far (updated to reflect the answer):
var Modal = {
init: function(config) {
this.config = config;
this.clickCard();
this.removeModal();
this.clickOutside();
this.createClose();
},
clickCard: function() {
$this = this;
this.config.boardOutput.on('click', '.card', function(event) {
$this.showOverlay();
$this.cloneCard.call($(this));
$this.createClose();
});
},
cloneCard: function() {
this.clone()
.replaceWith($('<div/>').html(this.html()))
.removeClass('card')
.addClass('modal')
.css("margin-top", $(window).scrollTop())
.prependTo('body');
},
showOverlay: function() {
this.config.overlay.show();
},
removeModal: function() {
$('.modal').remove();
$('.overlay').hide();
},
clickOutside: function() {
this.config.overlay.on('click', this.removeModal);
},
createClose: function() {
$('<span class="close">X</span>')
.prependTo('.modal')
.on('click', this.removeModal);
}
};
Modal.init({
boardOutput: $('#board-output'),
overlay: $('.overlay')
});
For what you need, calling self.cloneCard.call($(this)); instead of self.cloneCard($(this));
should work. What you're doing is, calling cloneCard passing it the element in which the the clickCard event occured.
If this doesn't work, i think we'll need more information to sovle your problem.
I'm an intermediate front-end JS developer and I'm trying the Module Pattern outlined by Chris Coyyer here.
But when I store a jQuery selector in the settings, I'm unable to use it to trigger a click event. See the below code with my comments... Any help is greatly appreciated!
var s,
TestWidget = {
settings: {
testButton: $("#testing")
},
init: function() {
s = this.settings;
this.bindUIActions();
},
bindUIActions: function() {
console.log(s.testButton); // This works: [context: document, selector: "#testing", constructor: function, init: function, selector: ""…]
//This doesn't work - why?????
s.testButton.click(function() {
//Why isn't this triggered?
alert('testButton clicked');
});
/*This works, obviously:
$('#testing').click(function() {
alert('testButton clicked');
});
*/
}
};
$(document).ready(function() {
TestWidget.init();
});
The problem is that you initialize $("#testing") before the DOM is ready, so this jQuery object is empty.
A simple solution is to put all your code in the ready callback.
Another one would be to replace
settings: {
testButton: $("#testing")
},
init: function() {
s = this.settings;
this.bindUIActions();
},
with
settings: {
},
init: function() {
s = this.settings;
s.testButton = $("#testing");
this.bindUIActions();
},
But it's hard to get why you use so much code for such a simple thing. You might be overusing the pattern here and it's not really clean as you have two global variables s and TestWidget when one would already be a lot.
Here's a slight variation of your code which would be, in my opinion, cleaner, while still using modules (IIFE variant) :
TestWidget = (function(){
var settings = {};
return {
init: function() {
settings.testButton = $("#testing");
this.bindUIActions();
},
bindUIActions: function() {
console.log(settings.testButton);
settings.testButton.click(function() {
alert('testButton clicked');
});
}
}
})();
$(document).ready(function() {
TestWidget.init();
});
settings is kept in the closure and doesn't leak in the global namespace. Note that even this version doesn't make sense if you don't do more with the module.
im having some trouble with the following code:
Ext.define('...controller...', {
extend: 'Ext.app.Controller',
init: function() {
...
},
crearLoginWindow:function(){
var loginWindow = Ext.create('Proto1.view.adminbd.LoginWindowBDView', {
itemId: 'loginwindow',
autoShow: true,
modal: true
});
Ext.ComponentQuery.query('#loginwindow > button[text="Cancelar"]')[0].on('click', function(){loginWindow.close()});
//Cant call 'enviarLogin' function if its inside 'crearLoginWindow'
Ext.ComponentQuery.query('#loginwindow > button[text="Conectar"]')[0].on('click', this.enviarLogin, this);
var enviarLogin = function(){
console.log('login')
}
}
});
I want to be able to call 'enviarLogin' inside 'crearLoginWindow' function but it throws a reference error. If the function is placed outside 'crearLoginWindow' it will work.
Being these two lines the source of trouble:
Ext.ComponentQuery.query('#loginwindow > button[text="Conectar"]')[0].on('click', this.enviarLogin, this);
var enviarLogin = function(){
console.log('login')
}
I've tried different scope variants such as;
Ext.ComponentQuery.query('#loginwindow > button[text="Conectar"]')[0].on('click', this.crearLoginWindow.enviarLogin);
this.enviarLogin = function(){
console.log('login')
}
Which makes sense with what i think i understand about scope and the need to specify the place where the function resides to execute it.
Id appreciate a solution because this problem makes my code very messy!
Simply defining a function within another function doesn't attach it to any object or instance, so this.enviarLogin won't work. There are two basic options here:
Just define the inner function as you're doing (moving it up above your handler assignment), and reference it directly by name:
var enviarLogin = function(){
console.log('login')
};
Ext.ComponentQuery.query('#loginwindow > button[text="Conectar"]')[0]
.on('click', enviarLogin);
Define enviarLogin as a method, the same way you are defining crearLoginWindow:
Ext.define('...controller...', {
extend: 'Ext.app.Controller',
init: function() { ... },
crearLoginWindow: function(){
// ...
Ext.ComponentQuery.query('#loginwindow > button[text="Conectar"]')[0]
.on('click', this.enviarLogin, this);
},
enviarLogin: function(){
console.log('login')
}
});
The first version may be better if you don't need to reference enviarLogin outside of the crearLoginWindow method. The second is better if you do need to reference enviarLogin elsewhere, and it makes using this in enviarLogin clearer.
Using Mootools 1.3.2
Code is as follows:
var DNReportAbuse = new Class({
Extends: DNUserDialog,
comment_id: null,
container: null,
initialize: function(classname)
{
var bindclass = $(document.body).getElements(classname);
bindclass.each(function(el) {
el.addEvents({
click: function() {
this.reportComment();
}.bind(this)
});
});
},
reportComment: function() {
this.preventDefault();
alert('hello');
return false;
}
});
The event does bind, and when "this.reportComment();" is replaced with "alert('hello world');" it works entirely ...
... but when "this.reportComment()" is used, I instead receive an error, which Firebug explains as "function this.reportComment() is not a function".
I imagine that my issue has something to do with referring to a class function outside of its proper scope, though I'm a bit confused as to why ... or how to solve the issue. The end goal is to achieve an on-click binding of the reportComment() function to all members of a css class (up to 20 per page). The difficulty is that referencing the reportComment() function with "this.reportComment()" results in an error claiming that the function does not exist, when it clearly does exist.
Looking through similar questions on Stack Overflow did not seem to answer this issue ... so asking in hopes that someone can point me in the right direction.
You have some problems with bind and events:
initialize: function(classname)
{
var bindclass = $(document.body).getElements(classname);
var _self = this; //var to store the 'real' this you will use
bindclass.each(function(el) {
el.addEvents({
click: function(event) { //pass the event
this.reportComment(event);
}.bind(_self) //'this' is referring to the inner each function callback
});
});
},
reportComment: function(event) {
event.preventDefault(); //preventDefault on the event, not on 'this'
alert('hello');
return false;
}