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
Related
i have a structure like this :
// App.js
var APP = {
viewIndex: function(){
EVT.doSomething();
},
// Another function below
}
// Event.js
var EVT = {
doSomething: function(){
deleteField();
function deleteField(){
$("body").on("click", "#btn", function(){
console.log("Clicked");
})
}
}
}
my project is SPA wannabe, so when i want to change the page, it must execute some function inside App.js, but my problem is, when i call APP.viewIndex() (when i go to Index, go back, and go to index again(without refreshing page) ), the function inside EVT -> doSomething() is execute twice, so i have no idea how to prevent it,
in my console i got this :
Clicked
Clicked
*sorry if my explanation is a bit complicated
hope you guys can help me out of this problem :D
thanks
Use a property to remember if you already called deleteField().
var EVT = {
didSomething: false,
doSomething: function(){
if (!this.didSomething) {
deleteField();
this.didSomething = true;
}
function deleteField(){
$("body").on("click", "#btn", function(){
console.log("Clicked");
})
}
}
}
I am currently in the process of working on the app which is through modular pattern.
The problem i am currently getting is that once the Ajax is complete, i want to be able to fire a function within the object. The object i can see but when i specify a function, it fails and comes back as Undefined.
JS
var TestCase = {
settings: {
cu: $('.select'),
},
init: function() {
se = this.settings;
},
windowsReady: function() {
TestCase.init();
if ($.fn.selectBox) {
TestCase.selectBind();
}
},
ajaxComp: function() {
TestCase.init();
TestCase.selectBind();
},
selectBind: function(){
se.cu.selectBox();
},
};
JS Fire - The selectBind works fine when its loaded through the ready call. However as mentioned before, the ajaxcomplete keeps coming back as Undefined for TestCase.ajaxComp(); or a direct call for TestCase.selectBind(); Please note that when i console.log(TestCase) it lists all the objects.
$(document).ready(function () {
TestCase.windowsReady();
});
$(document).ajaxSuccess(function() {
console.log(TestCase);
TestCase.ajaxComp();
console.log('completed');
});
This is happenning because of this line:
se = this.settings;
The this in the scope of your $(document).ajaxSuccess(...) method will be the jQuery object, not TestCase object.
Try changing it to se = TestCase.settings;
I am making two different app's with Meteor. In first app, witch you can see here, I am using ... template.текст.set( true ); ... and everything is working fine. Now in second app I got error
ReferenceError: template is not defined
So, what is the problem? I Checked, packages are same.
Here is the code of second app:
Template.body.onCreated(function bodyOnCreated() {
this.TrenutniKorisnik = new ReactiveVar(true);
});
Template.PrijavaKorisnika.events({
'submit .Prijava': function(event) {
event.preventDefault();
var korisnik = event.target.КорисничкоИме.value;
var šifra = event.target.Лозинка.value;
if (Korisnici.findOne({КорисничкоИме: korisnik, Шифра: šifra})) { template.TrenutniKorisnik.set( false )};
event.target.КорисничкоИме.value = "";
event.target.Лозинка.value = "";
}
});
Template.body.helpers({
TrenutniKorisnik: function() {
return Template.instance().TrenutniKorisnik.get();
},
});
The template instance is the second parameter in an event handler. Simply change this:
'submit .Prijava': function(event) {
to this:
'submit .Prijava': function(event, template) {
so template will be defined in the function body.
Once you solve that, however you'll find that TrenutniKorisnik isn't defined because it's on the body template and not the current template. One way to solve that is to use a file-scoped variable rather than a template one. Here's an example:
var TrenutniKorisnik = new ReactiveVar(true);
Template.PrijavaKorisnika.events({
'submit .Prijava': function (event) {
...
if (Korisnici.findOne({ КорисничкоИме: korisnik, Шифра: šifra })) {
TrenutniKorisnik.set(false);
}
...
},
});
Template.body.helpers({
TrenutniKorisnik: function () {
return TrenutniKorisnik.get();
},
});
I have a panel widget with a button. Clicking the button should execute some global actions related to all such widgets and after that execute some local actions related to this widget instance only. Global actions are binded in a separate javascript file by CSS class like this:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
jQuery(document).ready(function()
{
App.init();
});
And in the html file local script is like this:
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
Currently local script is executed first and global only after while I want it to be the opposite. I tried to wrap local one also with document.ready and have it run after global but that doesn't seem to change the execution order. Is there any decent way to arrange global and local jQuery bindings to the same element?
The problem you're having comes from using jQuery's .ready() function to initialize App, while you seem to have no such wrapper in your local code. Try the following instead:
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
$(function()
{
App.init();
});
Then in your local JS:
$(function() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
});
Note that $(function(){}) can be used as shorthand for $(document).ready(function(){});. Also, make sure your JS file is located before your local JS, as javascript runs sequentially.
Alternatively, you can use setTimeout() to ensure everything's loaded properly:
(function executeOnReady() {
setTimeout(function() {
// Set App.isInitialized = true in your App.init() function
if (App.isInitialized) runLocalJs();
// App.init() hasn't been called yet, so re-run this function
else executeOnReady();
}, 500);
})();
function runLocalJs() {
$("#widgetBtn1234").click(function (e)
{
// do smth local
});
};
How about this instead:
var widget = $("#widgetBtn1234").get(0);//get the vanilla dom element
var globalHandler = widget.onclick; //save old click handler
// clobber the old handler with a new handler, that calls the old handler when it's done
widget.onclick = function(e){
//do smth global by calling stored handler
globalHandler(e);
//afterward do smth local
};
There might be a more jqueryish way to write this, but I hope the concept works for you.
-------VVVV----keeping old answer for posterity----VVVV--------
Why not something like this?
var App = function ()
{
var handleWidgetButton = function ()
{
$('.widgetBtn').on('click', function (e)
{
// do smth global
if(this.id === 'widgetBtn1234'){
//do specific things for this one
}
});
return {
init: function ()
{
handleWidgetButton();
}
};
}
}();
Please excuse any syntax errors I might have made as I haven't actually tested this code.
Check out my simple JQ extension I created on jsbin.
http://jsbin.com/telofesevo/edit?js,console,output
It allows to call consequentially all defined personal click handlers after a global one, handle missed handlers case if necessary and easily reset all personal handlers.
I'm using require.js with backbone.js to structure my app. In one of my views:
define(['backbone', 'models/message', 'text!templates/message-send.html'], function (Backbone, Message, messageSendTemplate) {
var MessageSendView = Backbone.View.extend({
el: $('#send-message'),
template: _.template(messageSendTemplate),
events: {
"click #send": "sendMessage",
"keypress #field": "sendMessageOnEnter",
},
initialize: function () {
_.bindAll(this,'render', 'sendMessage', 'sendMessageOnEnter');
this.render();
},
render: function () {
this.$el.html(this.template);
this.delegateEvents();
return this;
},
sendMessage: function () {
var Message = Message.extend({
noIoBind: true
});
var attrs = {
message: this.$('#field').val(),
username: this.$('#username').text()
};
var message = new Message(attrs);
message.save();
/*
socket.emit('message:create', {
message: this.$('#field').val(),
username: this.$('#username').text()
});
*/
this.$('#field').val("");
},
sendMessageOnEnter: function (e) {
if (e.keyCode == 13) {
this.sendMessage();
}
}
});
return MessageSendView;
});
When keypress event is triggered by jquery and sendMessage function is called - for some reason Message model is undefined, although when this view is first loaded by require.js it is available. Any hints?
Thanks
Please see my inline comments:
sendMessage: function () {
// first you declare a Message object, default to undefined
// then you refrence to a Message variable from the function scope, which will in turn reference to your Message variable defined in step 1
// then you call extend method of this referenced Message variable which is currently undefined, so you see the point
var Message = Message.extend({
noIoBind: true
});
// to correct, you can rename Message to other name, e.g.
var MessageNoIOBind = Message.extend ...
...
},
My guess is that you've bound sendMessageOnEnter as a keypress event handler somewhere else in your code. By doing this, you will change the context of this upon the bound event handler's function being called. Basically, when you call this.sendMessage(), this is no longer your MessageSendView object, it's more than likely the jQuery element you've bound the keypress event to. Since you're using jQuery, you could more than likely solve this by using $.proxy to bind your sendMessageOnEnter function to the correct context. Something like: (note - this was not tested at all)
var view = new MessageSendView();
$('input').keypress(function() {
$.proxy(view.sendMessageOnEnter, view);
});
I hope this helps, here is a bit more reading for you. Happy coding!
Binding Scopes in JavaScript
$.proxy