How to access jquery library variable from public function? - javascript

I'm creating simple jquery library, actually I just learn about creating my own library with jQuery, I need to access variable inside lib function from outside main function. Here short code, I want to access variable page and loading from $.fn.beyondScroll.reset function. How I accomplish this task? I have tried to access via $.fn.beyondScroll.page; but it return undefinded. Thanks.
(function ($) {
$.fn.beyondScroll = function (options) {
var settings = $.extend({}, $.fn.beyondScroll.defaults, options);
var complete = false; // need access this variable
var page = 1;
return this.each(function () {
var loading = false; // and this variable
});
};
$.fn.beyondScroll.reset = function(){
// access those variables from here
var currentPage = $.fn.beyondScroll.page; // return undefined
}
}(jQuery));

Related

Javascript - web application structure

I'm having issues managing data between the parts of my Javascript application. I'm trying to stick with a "MVC" pattern, so speaking in MVC terms, i can't make some of my "C" (controller) functions access the data given by "M" (model). Specifically i can't make event functions to reach the data without making the data global (which i want to try to avoid).
A made up situation just to show you what i mean:
HTML:
<body>
<div onclick="func()"></div>
</body>
JS:
var Data = function(num) {
this.num = num;
}
window.onreadystatechange = function() {
var data = new Data(5);
}
function func() {
//How do i access the object "data" from here?
}
The question is: how do i make the event handlers access the data?
var Data = function(num) {
this.num = num;
}
var data;
window.onreadystatechange = function() {
data = new Data(5);
}
function func() {
//data.num
}
You have to declare data in a scope accessible to func
If you are worried about global variables you could do this
var service = {};
(function(service) {
var Data = function(num) {
this.num = num;
}
var data;
window.onreadystatechange = function() {
data = new Data(5);
}
service.func = function func() {
//data.num
}
})(service);
//call the function
service.func();
This will call it in a self executing closure that will prevent the variables from entering global scope. You can pass in a service instance and attach the func method to it to be able to call it. Jquery plugins typically follow this pattern.

Accessing Grandparent's variable

I have an Object with the variable "parentVar", and I want to write the response of an ajax-request into it.
Sounds easy, but I'm not able to do this, due to some namespace-troubles.
I wrote a very minimalistic example, which shows the problem.
The ajax-request will be started, when I call the Object's init-Function:
var parentObj = new Parent();
//Do some work (I need some functionality from the object before it can be fully initialized)
alert("Old Value = " + parentObj.parentVar);
parentObj.init(function(){
alert("New Value = " + parentObj.parentVar);
});
The init-Function calls the Function "load" which performs an Ajax-Request, and returns the received data (in another callback-Function).
function Parent(){
this.parentVar = "old"; //this value should be replaced
this.init = function(initCallBack){
this.load(function(newData){ //load the content of the file
this.parentVar = newData; //write the content into the variable
initCallBack(); //I'm done!
});
}
this.load = function(callbackFunc){
//load the new value from a file via ajax (asyncron).
//When finished: call callbackFunc
callbackFunc("newValue");
}
}
I already tried passing the scope to the loader-function, and getting it back in the callBack-Function. But it didn't work.
I also tried "var parentscope = this;" in the init-Function,
and "parentscope.parentVar = newData;" - it didn't work either.
Is it possible to achieve this with parentVar being private? (I mean "var parentVar = 'old';" instead of "this.parentVar = 'old';").
The callback function passed to load() doesn't have the value of this that you want. The way you call that function this will be window. You can bind the value of this as follows:
this.load(function(newData){ //load the content of the file
this.parentVar = newData; //write the content into the variable
initCallBack(); //I'm done!
}.bind(this));
...and then it will work: http://jsfiddle.net/v9Hvb/
Is it possible to achieve this with parentVar being private? (I mean var parentVar = 'old'; instead of this.parentVar = 'old';).
You can use a private variable inside the Parent() constructor and it will be accessible within all of the methods defined inside the constructor. But it won't be accessible outside with parentObj.parentVar so you'd have to add a getter method.
It would be easier to use a private var self = this; variable inside the Parent() constructor and then use self instead of this in the methods:
function Parent(){
var self = this;
self.parentVar = "old"; //this value should be replaced
self.init = function(initCallBack){
self.load(function(newData){ //load the content of the file
self.parentVar = newData; //write the content into the variable
initCallBack(); //I'm done!
});
}
self.load = function(callbackFunc){
//load the new value from a file via ajax (asyncron).
//When finished: call callbackFunc
callbackFunc("newValue");
}
}
Demo: http://jsfiddle.net/v9Hvb/1/
Further reading: MDN's this article
The problem is that the this within the callback passed to the load within the init function doesn't refer to the Parent object but the window object. There is a well known hack for this: save the reference to the Parent's this in _this. Other variable names commonly used are that and self and all these prefixed with more underscores. Here is a code that works:
function Parent(){
this.parentVar = "old"; //this value should be replaced
var _this = this;
this.init = function(initCallBack){
this.load(function(newData){ //load the content of the file
_this.parentVar = newData; //write the content into the variable
initCallBack(); //I'm done!
});
}
this.load = function(callbackFunc){
//load the new value from a file via ajax (asyncron).
//When finished: call callbackFunc
callbackFunc("newValue");
}
}

calling class function in another class function in javascript

I want to call posts() in refresh function.
Here is my code.
var TIMELINE = TIMELINE || (function (){
/*** private ***/
var _args = {};
var self = this;
return {
init : function(Args){
_args = Args;
}, // init
posts : function(data) {
alert('posts called');
}, // posts
unsetMarkers : function() {
alert('unsetMarkers called');
}, // unsetMarkers
refresh : function(){
self.posts;
}
};
}());
the problem is at this line self.posts;
I also tried self.posts({'data':'success','another':'thing'});
How I can use posts in refresh?
There are two problems in your code:
self doesn't refer to the object with the property posts, i.e. not to the object you are returning from the function. You have var self = this; and this refers to window (assuming non-strict mode).
You are not even trying to call the function.
Instead of returning the object immediately, assign it to self:
// instead of `var self = this;`
var self = {
// function definitions
};
return self;
and then you can call the method with
self.posts(); // note the parenthesis after the function name
If you are certain that the refresh function is always called as TIMELINE.refresh() (i.e. as a method of the TIMELINE object) , then you can also call the posts method with
this.posts();
and forget about self.
Further reading material:
MDN - this: Learn which value this has in different contexts.
Eloquent JavaScript - Functions: Learn how functions work.
refresh : function(){
this.posts();
}
JSFIDDLE

Make a global JS variable change value inside a Drupal.behaviors and call it in another function

I've created 2 variables as global and I would like to change their value inside my Drupal.behaviors so I can use it from another function, How can I do that ?
pointLayer is not working in my dragPoint function without puting pointLayer as an argument
(function ($) {
var map;
var pointLayer;
Drupal.behaviors.OL_lat_long = {
attach: function (context, settings) {
// setTimeout(function(){
map = $('#openlayers-map').data('openlayers').openlayers;
pointLayer= map.layers[1];
and call it in this one without any argument:
Drupal.OL_lat_long.dragPoint = function(){
var drag = new OpenLayers.Control.DragFeature(pointLayer);
Thanks
If you have global variables in JS, you can change them at any place like this:
var var_name;
window.var_name = new_value

Best way to privately scope Javascript?

I am currently writing all javascript functionality of a certain page in JQuery's document.ready handler:
$(document).ready(function() {
var one, two, three;
function f1(par1) {}
function f2() {}
...
});
I feel that this isn't optimal or according to Javascript best practices. What I need is a private scope for the page's functionality, nothing needs to be called externally.
I've seen a number of different ways:
jQuery source
(function(window) {
var anObj = {};
...
window.functionality = anObj;
}(window));
A function that is self-invoked with the window as parameter, then setting the functionality object of your application on it.
Codemirror source
window.functionality = (function() {
var functionality = {};
...
return functionality;
}());
Very similar to what jQuery does, but setting the functionality object indirectly on window by making a self-invoking function return something first.
This question
var functionality = {};
(function(obj) { obj.f1 = ... }(functionality));
Creating a local variable (instead of on window), and setting its content inside a self-invoked function (why?)
How do I declare a namespace in JavaScript?
var functionality = {
f1: function(){},
f2: function(){}
}
Pretty much the same as the previous thing but setting the contents without a self-invoking function (again why use or not use the self invoking function?).
So... which way is best?
I would suggest the module pattern for this, where a page is treated as a module. There is a lot of information about the javascript module pattern on the web. Have a look at http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html.
I've used an example from the link and modified it a bit:
var MyApp = MyApp || {};
MyApp.PageX = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
What is happening here, is that a set of properties and methods is defined and namespaced to MyApp.PageX, MyApp being the global. So this will work:
MyApp.PageX.moduleProperty; // 1
MyApp.PageX.moduleMethod();

Categories