Update var using .change? - javascript

I have an important question that I'm starting to face on 80% of the cases.
Lets say I have this:
var bcount = properties.count;
favicon.badge(bcount);
bcount.change(function() { favicon.badge(bcount); });
properties.count = its a number that changes depending on the user actions.
favicon.badge its a javascript that shows the action, which is working good.
I tried to use .change on the bcount var, but is giving me error as I supposed because is not an element.
Is there any way to listen a var when value changes?
The problem I'm facing is that when the count gets updated, with a new number. It only updates after refreshing the page.
Thanks!!
Edit: I'm trying to setup getter and stter:
var bcount = {
a: properties.count,
get b() {
return this.a;
},
set c(cname) {
this.a;
}
};
Is that okay? And now how i can init the call?

I think you need get and set functionality. You can put logic in those functions and they will do what you want in variable get and set.
See this: es5-getters-setter
Sample from above link:
var person = {
firstName: 'Jimmy',
lastName: 'Smith',
get fullName() {
return this.firstName + ' ' + this.lastName;
},
set fullName (name) {
var words = name.toString().split(' ');
this.firstName = words[0] || '';
this.lastName = words[1] || '';
}
}
person.fullName = 'Jack Franklin';
console.log(person.firstName); // Jack
console.log(person.lastName) // Franklin
Edit:
Every field has its get and set. If you want to make other confused when they read your code do that. but the right thing is this:
var properties = {
_count:0, // you hold count value here
get count() { // every time you get "properties.count" this function will run
// place for your code that must run on get, like "var bcount = properties.count"
return this._count;
},
set count(new_count) { // every time you want to do "properties.count = some_int" this function will run
// place for your code that must run on set, like "properties.count = some_int"
this._count = new_count;
}
};
// usage
properties.count = 10; // "properties._count" is "10" now
var bcount = properties.count; // you just got "properties._count" value

Related

Javascript Typedef Error when using parameters

What am I doing wrong, and how can one pass variables to a different function within the same wrapping variable/function.
Example:
function customFunctionWrap(){
this.myVar1 = 0;
this.getCurrentPosition = function(){
if (navigation.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){});
}
},
this.doSomething = function(){ // Works
//Do something, return
this.callWithParams(); //Works
},
//If I remove passing in 'value1',calling it elsewhere works
this.doSomethingWithParams = function(value1){
//Use value1
//Return
},
this.callWithParams = function(){
var value1 = 'xyz'; //Is a variable that changes based on some DOM element values and is a dynamic DOM element
this.doSomethingWithParams(value1); //THROWS TYPEDEF ERROR: this.doSomethingWithParams is not a function
this.getCurrentPosition();
}
};
var local = new customFunctionWrap();
local.doSomething(); //WORKS
I know there is another way to do it and then directly use customFunctionWrap.callWithParams(), but am trying to understand why the former approach is erroring out.
var customFunctionWrap = {
myVar1 : 0,
callWithParams : function(){
}
}
What JS sees:
var customFunctionWrap = (some function)()
returned function is fired, because the last (), so it has to yield/return something, otherwise, like in your code it is "returning" undefined.
So your given code does not work.
The very first fix is to delete last 2 characters from
var customFunctionWrap = (some function)()
to make it return constructor.

How to declare instance of a class within a instance of class?

I am making a simple hmtl/js game. I'd like to have all the data of the Game in DataofGame. It is like tennis, it is simpler than tennis: there is only set and match. changeinSet is called on click.
But I think i have a problem with private variable so it doesn't work.
Uncaught TypeError: Cannot read property 'WordsoftheGame' of undefined
//Added
document.getElementById('playboutton').addEventListener('click', newGame);
function newGame() {
var DataofGame = new newGameData();
}
// New game
function newGameData() {
this.pointTeam1 = 0;
this.pointTeam2 = 0;
this.WordsoftheGame = ShuffleListe();
this.ASet = new aSet();
}
//How the set is manage ********************
function aSet() {
var oneWord = DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML = oneWord[0];
DataofGame.WordsoftheGame.shift();
this.turn = true;
this.score = 0;
}
function changeinSet() {
DataofGame.ASet.score += 1;
//This is the other team's turn:
DataofGame.ASet.turn = !DataofGame.ASet.turn;
};
//shuffle liste
ListOfWords = ['Artiste', 'Appeler', 'Cheval', 'Choisir', 'Ciel', 'Croire', 'Dormir'];
function ShuffleListe() {
data = shuffle(ListOfWords);
return data;
}
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet=new aSet();
}
//How the set is manage ********************
function aSet(){
var oneWord=DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML=oneWord[0];
DataofGame.WordsoftheGame.shift(); // << DataofGame not assigned yet
this.turn=true;
this.score=0;
}
Here when you're accessing DataofGame, it's not yet assigned because you're inside the constructor when calling aSet().
What you want to achieve is not completely clear, but if it's adding an ASet method to your object, you could write something like this:
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet = function() {
// your code
};
}
NB your coding style for names is a bit messy, you should use uppercases consistently. The usage is to start constructor names with uppercases, the rest in lower cases.
You can let the function return an object with the data or just set the object.
function newGameData(){
return {
pointTeam1 : 0,
pointTeam2 : 0,
WordsoftheGame : ShuffleListe(),
ASet : new aSet()
}
}
But I would recommend to search for how to work with objects in javascript. Maybe this helps:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript

How to retrieve Firebase's child's value into global scope?

I have a Firebase database set up like this:
>>XXX
>>>>dislike: 0
>>>>like: 1
In my web application, I can retrieve their value into console by:
var fb = new Firebase('https://xxx.firebaseio.com');
fb.child('like').once('value',function(snapshot){
console.log(snapshot.val());
});
fb.child('dislike').once('value',function(snapshot){
console.log(snapshot.val());
});
Now if I want to retrieve these values into the global scope, it will return undefined when I do this:
var fb = new Firebase('https://xxx.firebaseio.com');
var like = fb.child('like').once('value',function(snapshot){
return snapshot.val();
});
var dislike = fb.child('dislike').once('value',function(snapshot){
return snapshot.val();
});
Of course I have a silly solution to this problem, by putting entire script inside these two scopes - but it would be a disasters if I have hundreds of scopes to work with, and if I like to dynamically turn them on and off. Here is my solution:
var likeRef = new Firebase('https://xxx.firebaseio.com/like');
var dislikeRef = new Firebase('https://xxx.firebaseio.com/dislike');
likeRef.once('value',function(likeObj){
dislikeRef.once('value',function(dislikeObj){
var like = likeObj.val();
var dislike = dislikeObj.val();
});
});
Here is another answer suggested by Frank van Puffelen from the source <Passing variable in parent scope to callback function>, and it didn't quite work because seem to only work for script that is adding a new object in an array. Here is my attempt:
var like = 0;
var dislike = 0;
var val = 0;
var fb = new Firebase('https://xxx.firebaseio.com/');
function fb_like() {
fb.child('like').on('value', read_val);
return val;
}
function fb_dislike() {
fb.child('dislike').on('value', read_val);
return val;
}
function read_val(snapshot) {
var val = snapshot.val();
}
fb_like();
fb_dislike();
console.log(like);
console.log(dislike);
As you might expected, the console logs 0 and 0, instead of the values in like and dislike in firabase xxx database.
In fact, I took a step further and use array instead of integer value, and it still won't work:
var like = [0];
var dislike = [0];
var val = [0];
var fb = new Firebase('https://xxx.firebaseio.com/');
function fb_like() {
fb.child('like').on('value', read_val);
console.log('fb_like: ' + val[0]);
return val;
}
function fb_dislike() {
fb.child('dislike').on('value', read_val);
console.log('fb_dislike: ' + val[0]);
return val;
}
function read_val(snapshot) {
val[0].value = snapshot.val();
}
fb_like();
fb_dislike();
console.log('Like: ' + like[0]);
console.log('Dislike: ' + dislike[0]);
The console will logs:
fb_like: 0
fb_dislike: 0
Like: 0
Dislike: 0
This means probably means only adding (pushing) new objects into an array will work on a global scope, changing the value of an object will only effect the local scope.
Then, I realized even adding (pushing) new objects into an array cannot effect the global scope. Here is my attempt:
var like = 0;
var likeObj = [];
var fb = new Firebase('https://xxx.firebaseio.com/');
function fb_like() {
fb.child('like').on('value', read_like);
console.log('fb_like: ' + likeObj[0]);
return likeObj;
}
function read_like(snapshot) {
likeObj.push(snapshot.val());
console.log('likeObj: ' + likeObj[0]);
}
fb_like();
like = likeObj[0];
console.log('Like: ' + like);
As a result, the console logs:
fb_like: undefined
Like: undefined
likeObj: 1
This probably means the read_like() isn't effecting scopes larger than itself, event with array.push command.

Method, doesn't set property value

I have the following code:
function Show() {
this.showId = $("#meta-show-id").val();
this.title = $("#meta-title").val();
this.season = $("#meta-season").val();
this.episode = $("#meta-episode").val();
this.storageId = $("#meta-show-id").val() + '-' + $("#meta-season").val() + '-' + $("#meta-episode").val();
this.torrents = [];
this.putioId = null;
this.status = null;
this.subtitle = null;
}
Show.prototype = {
constructor: Show,
checkStorage: function() {
var storage = new Storage();
storage.get(this.storageId, function(data){
if (jQuery.isEmptyObject(data)){
console.log("empty");
}
else {
this.subtitle = data.subtitle;
}
});
}
}
When I call the checkStorage() method on object, method checks in chrome.storage.sync for data, and sets object this.subtitle property.
But this doesn't seem to work, this.subtitle value doesn't change.
What am I doing wrong?
This is a normal result, and it happens because of scope changing. I don't know if Storage is has your own implementation (because it is used with getItem instead of get), but anyways, you are calling a method that I guess calls back the function you provide as a second argument, right?
And because this function is called from somewhere else, this is not the object that you want.
Here is a simple example: http://jsfiddle.net/6c2e6/1/
Check out logs, and see what this is. It's the Window, because my test function is at top level..

Is it possible to log a KO observable array?

I am new to knockoutjs and I have an uber-basic question for you:
I have been able to successfully subscribe to a user changing the on screen twitter handle AND successfully fetch the tweets and display the last recent tweet of a user using console.log(json.results[0].text); However I am not confident that my observable array is working, when I push the json.results into recent tweets: recent_tweets.push(json.results[0].text) I see an [] empty array.
What is going on? Is logging ko.observable array possible?
console.log("TwitterFeedComponent loaded")
TwitterFeedComponent = function(attributes) {
if (arguments[0] === inheriting)
return;
console.log("TwitterFeedComponent() loaded")
var component = this;
var url = 'https://twitter.com/search.json?callback=?';
this.attributes.twitter_user_handle.subscribe(function(value) {
alert("the new value of the twitter handle is " + value);
console.log("I have loaded")
var url = 'https://twitter.com/search.json?callback=?';
var twitter_parameters = {
include_entities: true,
include_rts: true,
q: 'from:' + value,
count: '3'
}
$.getJSON(url,twitter_parameters,
function(json) {
result = json.results[0].text
recent_tweets.push(json.results[0].text);
console.log(recent_tweets);
console.log(json.results[0].text);
});
});
};
To access the actual values of an observable whether it's an array or not you need include parenthesis. For example the following will work:
var recent_tweets= ko.observableArray(["hello", "hi", "how are you"]);
console.log(recent_tweets());
The same is true when assigning variables.
Here is an example of a regular scalar value:
var myObservableName = ko.observable("Luis");
myObservableName("Dany"); // changes the name to: Dany
var Name = myObservableName(); // gets the value and assigns it to the variable Name (in this case the value is "Dany")
To answer this a little differently, you could always use Knockout's subscribe() functionality. Let's assume you have the following view-model:
App.MyViewModel = function() {
var self = this;
self.TestProperty = ko.observable(null);
}
For demonstrations sake, let's assume this property is bound to a text field, as follows:
<input type="text" id="TestPropertyField" data-bind="textInput: TestProperty" />
Now let's assume that you'd like to log any time this value changes. To do this, simply update your view-model as follows:
App.MyViewModel = function() {
var self = this;
self.TestProperty = ko.observable(null);
self.TestProperty.subscribe(function(newValue){
console.log("The new value is: " + newValue);
});
}

Categories