Javascript class with jQuery and JSON - javascript

i'm creating a function that i wanna use as class on javascript.
My function, will call an JSON page create with php parse json, and set the vars, but it doesen't work.
May you can give me some hints?
Here's the code, thx in advance:
function SiteParams(){
$.getJSON("parse/parametri.php",function(data){
$.each(data,function(index,value){
this.NomeSito = value.nomesito;
this.URLSito = value.urlsito;
this.EmailAutore = value.email;
this.NomeAutore = value.nomeautore;
});
});
}
var website = new SiteParams();
function ModuleBase(){
$("<div/>",{id:"title", text:website.NomeSito}).appendTo("#main");
}

This is a good place to use $.Deferred
function SiteParams(){
// create a private deferred, and expose the promise:
var d = new $.Deferred();
this.load = d.promise();
var that = this;
$.getJSON("parse/parametri.php", function(data) {
// your $.each only used one value anyway
var value = data[0];
// copy the data across
that.NomeSito = value.nomesito;
that.URLSito = value.urlsito;
that.EmailAutore = value.email;
that.NomeAutore = value.nomeautore;
// resolve the promise
d.resolve();
});
}
var s = new SiteParams();
s.load.done(function() {
$("<div/>", {id:"title", text: s.NomeSito}).appendTo("#main");
});

You have the wrong this inside the callback to $.each (and the callback to getJSON). Try that:
function SiteParams(){
var that = this;
$.getJSON("parse/parametri.php",function(data){
$.each(data,function(index,value){
that.NomeSito = value.nomesito;
that.URLSito = value.urlsito;
that.EmailAutore = value.email;
that.NomeAutore = value.nomeautore;
});
});
}
Note that it doesn't make much sense to loop with each if your response only contains a single object. And if it contained multiple objects, every object would overwrite the previous. So, if your response is really an array with a single item inside, you can simple use this:
function SiteParams(){
var that = this;
$.getJSON("parse/parametri.php",function(data){
that.NomeSito = data[0].nomesito;
that.URLSito = data[0].urlsito;
that.EmailAutore = data[0].email;
that.NomeAutore = data[0].nomeautore;
});
}

getJSON is asynchronous, so you need to pass a callback function. Try this:
function SiteParams(cb){
$.getJSON("parse/parametri.php",function(data){
$.each(data,function(index,value){
this.NomeSito = value.nomesito;
this.URLSito = value.urlsito;
this.EmailAutore = value.email;
this.NomeAutore = value.nomeautore;
cb(this);
});
});
}
new SiteParams(ModuleBase);
function ModuleBase(website){
$("<div/>",{id:"title", text:website.NomeSito}).appendTo("#main");
}

Related

Javascript: call object method using string only

This code doesn't work.
var Modal = {
init: function() {
console.log("test");
}
}
var objMethod = "Modal.init";
window[objMethod]();
I saw some answers that it can be called using this but I want to know how it can be called without using the object.
Modal["init"]();
Thank you!
To call a namespaced function, you need to use a multidimensional array. In this case it would be window['Modal']['init'](), which can also be expressed by splitting the objMethod string and using array indices:
var arr = objMethod.split(".");
window[arr[0]][arr[1]]();
var Modal = {
init: function() {
console.log("test");
}
}
var objMethod = "Modal.init";
var arr = objMethod.split(".");
window[arr[0]][arr[1]]();

Can't set scoped variable in $.post callback

I have the following type of structure:
(function(){
var objects = [];
$('button.one').on('click', function(){
fetchObjects = function(objects) {
$.post("/fetchObjects")
.done(function(data){
objects = data;
console.log(objects.length);
});
}
fetchObjects(objects)
});
$('button.two').on('click', function(){
console.log(objects.length);
});
})();
You can see I have a variable objects that is local to this function. Initially its empty. When I click button.one I wish to populate objects with the returned value from some ajax request. It appears to work, however when clicking button.two, the objects variable is still an empty array.
Why isn't objects available in the jQuery callback?
I've also tried this approach but with the same results:
function callback(data) {
facilities = data
}
$.post("/fetchObjects")
.done(function(data){
callback(data);
});
What am I missing here? Please don't tell me to make "objects" global.
I don't know why you're passing objects as parameter. The following should work fine I think. Please let me know if you're trying to achieve something else.
(function(){
var objects = [];
$('button.one').on('click', function(){
fetchObjects = function() {
$.post("/fetchObjects")
.done(function(data){
objects = data;
console.log(objects.length);
});
}
fetchObjects()
});
$('button.two').on('click', function(){
console.log(objects.length);
});
})();
Let's simplify the code a bit. You have essentially this:
var objects = [];
fetchObjects = function(innerObjects) {
var data = ['a','b'];
innerObjects = data;
console.log(innerObjects.length);
};
fetchObjects(objects);
console.log(objects);
(I've changed the other objects variable's name just for clarity; the issue is the same even if it had the same name.)
When you call the function, innerObjects contains a reference to objects so modifying it would change the original array as well. But when you do
innerObjects = data;
now instead of modifying the array you're replacing the reference with something else. innerObjects "points" to data instead of objects and the original variable remains unchanged.
To make it work you'd need to loop through the data array (assuming it'll always be an array) and assign the contents to the objects reference one by one. This way you'll keep the original reference and modify the original array.
var objects = [];
fetchObjects = function(innerObjects) {
var data = ['a','b'];
for( var i = 0; i < data.length; i++ ) {
innerObjects[i] = data[i];
}
console.log(innerObjects.length);
};
fetchObjects(objects);
console.log(objects);
Or, in your actual code:
(function(){
var objects = [];
$('button.one').on('click', function(){
fetchObjects = function(objects) {
$.post("/fetchObjects")
.done(function(data){
for( var i = 0; i < data.length; i++ ) {
objects[i] = data[i];
}
console.log(objects.length);
});
}
fetchObjects(objects)
});
$('button.two').on('click', function(){
console.log(objects.length);
});
})();

OOJS call other method

var Lines = function(startXCon, endXCon,startYCon, endYCon)
{
this.drawCurve = function()
{
}
this.changeCurve = function(e)
{
//how can I call drawCurve from this method
}
}
The comment in my code explains the problem. Is this possible or are all methods private?
Like this:
var Lines = function(startXCon, endXCon,startYCon, endYCon){
var self = this; // store this as a variable to use in nested function
this.drawCurve = function(){}
this.changeCurve = function(e){
self.drawCurve(); //now call this.drawCurve()
}
}

How to create an object who have alias for many others object's functions

I have a situation here.
Let's show an example:
function ScrewDriver(){
var data = ...;
this.driving = function(){
//Some Stuff Here
}
}
function Hammer(){
var data = ...;
this.stomp = function(){
//Some Stuff Here
}
}
function MultiTools(){
this.screwDriver = new ScrewDriver();
this.hammer = new Hammer();
}
Here is the base of our example.
Now I would like redirect the tools functions from the multiTools but dynamicaly.
Let's explain myself:
function Work(){
this.tools = new MultiTools();
this.tools.screw(); // I want to user directly the function of the proper object
this.tools.hammer.stomp(); // Not like this;
}
I was thinking of something like that:
function MultiTools(){
this.screwDriver = new ScrewDriver();
this.hammer = new Hammer();
for(var prop in this.screwDriver){
this[prop] = this.screwDriver[prop];
}
//Same for each object
}
But it's not working like I want because if I acces to the child object data in the child object function I'll get an error.
When im calling this.tools.screw(); I want in reality this.tools.screwDriver.screw();
In finally I just want a redirection.
Someone know how to do this?
Thanks in advance.
You can use .bind():
this[prop] = this.screwDriver[prop].bind(this.screwDriver);
That ensures that when the functions are called, they'll have the correct value of this.
You could write a general function for your MultiTools object:
function MultiTools() {
var multitool = this;
function promoteMethods(subobj) {
for (var prop in subobj)
if (typeof subobj[prop] == 'function')
multitool[prop] = subobj[prop].bind(subobj);
else
multitool[prop] = subobj[prop];
}
promoteMethods(this.hammer = new Hammer());
promoteMethods(this.screwDriver = new ScrewDriver());
// ...
}

how to access object's member through a method which filled by another method?

I know the title is a little bit confusion, here is the details:
Say I have a custom object defined in javascript, and there is a public member defined in it:
function Test()
{
this.testArray = [];
}
And I have two methods for this object, one is read out some xml file and filled into the array:
Test.prototype.readXML = function()
{
var self = this;
$.get('assest/xml/mydata.xml', function(d){
$(d).find("item").each(function(){
var item = new Item;
item.ID = ($(this).attr("ID"));
item.body = ($(this).find("body").text());
});
self.testArray.push(item);
});
}
And another function, which will display the content into the HTML page.
Test.prototype.appendInfo = function()
{
var i;
for (i=0; i<testArray.length;i++)
{
$('#testdisplay').append(testArray[i].ID +"<br />");
$('#testdisplay').append(testArray[i].body = "<br /");
}
}
However, the display function continue gives me error that the testArray is not defined. I'm not sure where is the problem, since I put the display function behind the reading function. I expect that the data will be stored in the array and could be accessed anytime I need them.
Hope some one will kindly help me about this! Thank you!
}
}
So I notice two problems with your code.
First when you do your ajax call you need to pass a deferred back to the user. Since ajax calls are async it may not finish right away.
So your readXML function should do this. It should return the jquery get.
Test.prototype.readXML = function() {
var self = this;
return $.get('assest/xml/mydata.xml', function(d){
$(d).find("item").each(function(){
var item = new Item;
item.ID = ($(this).attr("ID"));
item.body = ($(this).find("body").text());
});
self.testArray.push(item);
});
}
Next you your second function append was just missing some context.
Test.prototype.appendInfo = function() {
var i;
for (i=0; i<this.testArray.length;i++) {
$('#testdisplay').append(this.testArray[i].ID +"<br />");
$('#testdisplay').append(this.testArray[i].body = "<br /");
}
}
So your code should look like this.
var mytest = new Test();
mytest.readXML().done(function(){
mytest.appendInfo();
}).fail(function(){
// put some fallback code here
});
Updated:
Added additional this's.
There is no testArray in your appendInfo() function, that's why it says it's not defined. You should use this.testArray instead.
Every time you want to use a variable declared inside your scope, but outside the function you are using, you must use this.yourVariable

Categories