this works on some functions and not others - javascript

Normally when writing jQuery i just use functions. This time I want to give it a little sprinkle of best practice and so I followed a tutorial. The javascript itself seems to be correct but I am having a few problems calling certain functions.
jQuery.noConflict();
(function($j) {
'use strict';
function Site(settings) {
this.windowLoaded = false;
}
Site.prototype = {
constructor: Site,
start: function() {
var me = this;
$j(window).load(function() {
me.windowLoaded = true;
});
this.attach();
},
attach: function() {
this.getPrimaLink();
this.onCloseDialog();
this.triggerDialog();
this.openLink();
},
getPrimaLink: function(){
if($j('#order-data').is(":visible")){
$j( ".content-header" ).append($j( "#findPrimaLink" ));
$j('#findPrimaLink').show();
}
},
onCloseDialog: function(){
$j('#dialog').bind('dialogclose', function(event) {
$j( ".content-header" ).append($j( "#findPrimaLink" ));
$j('#findPrimaLink').show();
});
},
triggerDialog: function(){
$j("[title='Create New Customer']").click(function(){
$j('#findPrimaLink').show();
>>>>> this.openDialog(); <<<<<<
})
},
openLink: function(){
$j('#findPrimaLink').click(function(){
>>> this.openDialog(); <<<<<
});
},
openDialog: function(){
$j( "#dialog" ).dialog({
height: 'auto',
width: 350,
modal: true,
resizable:false,
});
},
};
$j(document).ready(function($j) {
var site = new Site();
site.start();
});
})(jQuery);
Within the start and attach function I am able to call each function by placing 'this' in front of it. But when I try to call openDialog() from openLink() and triggerDialog() I get - Uncaught TypeError: undefined is not a function.
Why is this and what should I do to fix it?

For both functions you're having a problem with, you're trying to use this inside of a jQuery function, so this's scope is to the DOM element, not the Site class.
triggerDialog: function(){
var site = this;
$j("[title='Create New Customer']").click(function(){
$j('#findPrimaLink').show();
site.openDialog();
console.log(this); //remove this for production, but you can see that `this` points to a DOM element
})
},
openLink: function(){
var site = this;
$j('#findPrimaLink').click(function(){
site.openDialog();
});
},
To understand why this happens, you should read about javascript Closures. Here and here.
P.S. you have an extra comma after your openDialog function.
P.P.S. It's also worth noting that this is exactly what're you're doing inside the start method.
var me = this;
$j(window).load(function() {
me.windowLoaded = true;
});

Related

JQuery - how to get the app object from a button click function

In my javascript file, I have defined an app object that takes an initialization function which is triggered upon document ready via JQuery.
$(document).ready(function() {
console.log("JQuery ready");
app.initialize();
});
The app is defined as
var app = {
_GPS_ENABLED: false,
initialize: function() {
var self = this;
// deviceready Event Handler
$(document).on('deviceready', function() {
... ...
// BIND A CLICK EVENT TO A FUNCTION DEFINED IN A LATER STEP
$('#isGPSenabled').on("click", self.isGPSenabled);
... ...
});
},
isGPSenabled: function() {
cordova.plugins.diagnostic.isGpsLocationEnabled(function(enabled) {
// HERE I NEED TO ACCESS THE "APP" ATTRIBUTE "_GPS_ENABLED"
._GPS_ENABLED = enabled; // HOW CAN I ACCESS THE _GPS_ENABLED ATTRIBUTE ON APP
});
}
}
The HTML part has:
<button id = "isGPSenabled">IS GPS ENABLED</button>
How can I access the app's attribute from the function attached to a button?
Previously I've referenced the object by it's name within itself. I think it was a pattern I saw once which worked for my needs at the time. Haven't really thought about the positives or negatives much but it has never caused me any issues in previous work.
Here is an example to to demonstrate:
const app = {
isEnabled: null,
init: () => {
app.isEnabled = false;
},
toggleEnabled: () => {
app.isEnabled = !app.isEnabled;
},
displayEnabled: () => {
console.log('isEnabled?:', app.isEnabled);
}
}
app.displayEnabled(); // null
app.init();
app.displayEnabled(); // false
app.toggleEnabled();
app.displayEnabled(); // true

Some problems with Javascript functions and this argument

I am using colorbox to my popups and...
This works fine.
$(".show_popup").colorbox({inline:true, width:"800px", onOpen: function() {
type = $(this).attr('type);
....
}
But I want use my inner function many times so I want make it a module function.
});
(function ($,a) {
var p = {
showPopup: function (popup_type) {
...
},
bindEvents: function () {
$(".show_popup").colorbox({inline:true, width:"800px", onOpen: p.showPopup($(this).attr('type')) });
}
...
}
a.Popups = p;
})(jQuery);
But this don't work - it is problem with $(this) - and function execute only once after page loading.
(function ($,a) {
var p = {
showPopup: function (popup_type) {
...
},
bindEvents: function () {
$(".show_popup").colorbox({inline:true, width:"800px", onOpen: p.showPopup });
}
...
}
a.Popups = p;
})(jQuery);
And this don't work of course too, but execute many times. So can you help me know what is matter?
The problem with onOpen: p.showPopup($(this).attr('type)) is that it will run the p.showPopup-function at the moment that you bind it to onOpen. What you want is that it runs at the moment the onOpen-event is triggered. Use
onOpen: function() { p.showPopup($(this).attr('type')); }
instead
(edit) assuming that p.showPopup is defined, I can't see it in your code.

Implement toggle in Backbone.js events

I'd like to implement a reversible animation in Backbone, in the same way we do it in jquery :
$('a.contact').toggle(
function(){
// odd clicks
},
function(){
// even clicks
});
my question is how to do this in backbone's event syntax?
How to do I mimic the function, function setup?
events : {
'click .toggleDiv' : this.doToggle
},
doToggle : function() { ??? }
Backbone's view events delegate directly to jQuery, and give you access to all of the standard DOM event arguments through the callback method. So, you can easily call jQuery's toggle method on the element:
Backbone.View.extend({
events: {
"click a.contact": "linkClicked"
},
linkClicked: function(e){
$(e.currentTarget).toggle(
function() {
// odd clicks
},
function() {
// even clicks
}
);
}
});
I was looking for a solution to this problem and I just went about it the old fashioned way. I also wanted to be able to locate my hideText() method from other views in my app.
So now I can check the status of the 'showmeState' from any other view and run either hideText() or showText() depending on what I want to do with it. I have tried to simplify the code below by removing things like render and initialize to make the example more clear.
var View = Backbone.View.extend({
events: {
'click': 'toggleContent'
},
showmeState: true,
toggleContent: function(){
if (this.showmeState === false) {
this.showText();
} else {
this.hideText();
}
},
hideText: function() {
this.$el.find('p').hide();
this.showmeState = false;
},
showText: function() {
this.$el.find('p').show();
this.showmeState = true;
}
});
var view = new View();
Is the element you want to toggle within the view receiving the event? If so:
doToggle: function() {
this.$("a.contact").toggle()
}
I actually believe the only to do this using events is to add a trigger in order to keep the actual flow together. It seems a bit clumsy to be honest to have to use toggle in this way.
Backbone.View.extend({
events: {
"click .button": "doToggle"
},
doToggle: function(e){
var myEle = $(e.currentTarget);
$(e.currentTarget).toggle(
function() {
// odd clicks
},
function() {
// even clicks
}
);
myEle.trigger('click');
}
});
It's probably cleaner to just use
Backbone.View.extend({
el: '#el',
initalize: function() {
this.render();
},
doToggle: {
var myEle = this.$el.find('.myEle');
myEle.toggle(
function() {
// odd clicks
},
function() {
// even clicks
}
);
},
render: function(e){
//other stuff
this.doToggle();
return this;
}
});

Javascript: How to pass an argument to a method being called without parentheses

Sorry for how stupid this is going to sound. My JS vocabulary is terrible and I had absolutely no idea what to search for.
I'm using jQuery.
So I've got this code:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){example.init();)
So here's the problem: I want to pass an argument to example.open() when I click the "a" element. It doesn't seem like I can, though. In order for the example.open method to just…exist on page-load and not just run, it can't have parentheses. I think. So there's no way to pass it an argument.
So I guess my question is…how do you pass an argument to a function that can't have parentheses?
Thanks so much.
Insert another anonymous function:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function()
{
example.open($(this));
});
}
};
You can also try this version because jQuery set the function's context (this) to the DOM element:
var example = {
open: function(){
alert($(this).text());
},
init: function(){
$("button").click(example.open);
}
};
Since jQuery binds the HTML element that raised the event into the this variable, you just have to pass it as a regular parameter:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function() {
// jQuery binds "this" to the element that initiated the event
example.open(this);
});
}
}
$(document).ready(function(){example.init();)
You can pass the anchor through its own handler:
var example = {
open: function( element ){
alert(element.text());
},
init: function(){
$("a").on("click", function() {
example.open( $(this) );
});
}
};
$(document).ready(function() {
example.init();
});
I don't understand what you actually want to do;
however, I can give a try:
var example = {
open: function(event){
event.preventDefault();
alert($(event.target).text()+' : '+event.data.x);
},
init: function(){
$("a").bind('click',{x:10},example.open);
}
};
$(example.init);
demo:
http://jsfiddle.net/rahen/EM2g9/2/
Sorry, I misunderstood the question.
There are several ways to handle this:
Wrap the call in a function:
$('a').click( function(){ example.open( $(this) ) } );
Where $(this) can be replaced by your argument list
Call a different event creator function, which takes the arguments as a parameter:
$('a').bind( 'click', {yourvariable:yourvalue}, example.open );
Where open takes a parameter called event and you can access your variable through the event.data (in the above it'd be event.data.yourvariable)
Errors and Other Info
However your element.text() won't just work unless element is a jQuery object. So you can jQueryify the object before passing it to the function, or after it's received by the function:
jQuery the passed object:
function(){ example.open(this) } /* to */ function(){ example.open($(this)) }
jQuery the received object:
alert(element.text()); /* to */ alert($(element).text());
That said, when calling an object without parameters this will refer to the object in scope (that generated the event). So, really, if you don't need to pass extra parameters you can get away with something like:
var example = {
open: function(){ // no argument needed
alert($(this).text()); // this points to element being clicked
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){
example.init();
}); // your ready function was missing closing brace '}'

jQuery: UI widget definition

I have a widget defined like so:
$.widget("ui.mywidget", {
_init: function() {
this.element.bind("keyup", function(event) {
alert(this.options);
alert(this.options.timeout);
});
}
});
And trying to call it like so:
$("input.mywidget").mywidget({timeout: 5});
I also redefined the bind method using the this.element.keyup(function(event) { ... }) style: no difference.
But, in the keyup bind, this.options (and referencing it just as options) both yield undefined. I thought the UI widget framework allowed this type of abstraction; am I doing something wrong?
When inside bind(), this changes to refer to the object that the event is raised on. Try:
$.widget("ui.mywidget", {
_init: function(options) {
var opts = this.options;
this.element.bind("keyup", function(event) {
alert(opts);
alert(opts.timeout);
});
}
});
What #Dave said is right. You can also set "this" to a variable rather than using options as an argument to the init function. Here is how I see it implemented often:
$.widget("ui.mywidget", {
options: {
timeout: 100
},
_init: function() {
var self = this;
self.element.bind("keyup", function(event) {
alert(self.options);
alert(self.options.timeout);
});
}
});
Why stop there? Check out $.proxy and write better code
$.widget("ui.mywidget", {
_create: function() {
//Under this syntax, _omgAlertsRule must be a method of 'this'
this.element.bind("keyup", $.proxy( this, '_omgAlertsRule' ) );
},
_omgAlertsRule: function( event ){
alert(this.options);
alert(this.options.timeout);
}
});

Categories

Resources