I'm trying to code my first non-hacked up jQuery plug-in and I'm struggling to create a basic object with a constructor, public variables, private variables, and functions.
http://jqueryboilerplate.com/ has a great guide for creating objects that extend jQuery, but I don't think this is the right way to go for a generic object not attached to a DOM element.
Does anyone have a boilerplate template for creating a basic reusable object? i.e.
var calc = new CustomCalculator({'starting_value': 42});
calc.add(3);
calc.multiplyBy(2);
alert(calc.total); // Alerts (42 + 3) * 2 = 90
From your code sample it seems you just need a basic way of creating a JS object.
This would do the trick (but there are lots of other ways to do it):
function CustomCalculator(options){
var self = this;
self.total = options.starting_value;
self.add = function(term){
self.total += term;
};
self.multiplyBy = function(term){
self.total = self.total * term;
};
}
var calc = new CustomCalculator({'starting_value': 42});
calc.add(3);
calc.multiplyBy(2);
alert(calc.total); // Alerts 90
You'd still have to implement the string concatenation, but I'll leave that up to you
If you want private variables you should use closures.
I recently wrote an article about namespaces and modules in JavaScript which could help you: http://www.kenneth-truyers.net/2013/04/27/javascript-namespaces-and-modules/
And here's another one specifically about private variables: http://www.kenneth-truyers.net/2012/04/22/private-variables-in-javascript/
Related
I use a lot of the following expressions in my code:
document.
.getElementsBy...
.querySelector...
I need to save characters without using any libraries. That can be done by
var d = document;
Then, instead of document. I can write d. now.
I am wondering if there is a simple way to do the same thing for methods
.getElementsBy... and .querySelector....
Since these have a variable term, I cannot put the entire thing into a
variable, like var q = .querySelector(".class"), because the .class
changes almost every time.
You can create functions to avoid adding properties to the document object as shortcut if you don't want to.
function gEBI(d,id)
{
return d.getElementById(id);
}
function qS(d,s)
{
return d.querySelector(s);
}
var d = document;
var ele1 = gEBI(d,"yourID");
var ele2 = qS(d,".class");
You can make your own shortcut functions-references manually.
document.gEBI = document.getElementById;
document.gEBI(id);
But it's not a good practice to make such shortcuts.
I am struggling with what I know is a very basic question related to variable declaration. I've read everything I can find on variables but I don't know if my problem is related to 1) how I am declaring variables or 2) how I am setting the scope of the variables.
To start, my understanding of variables in Meteor is that if I use var, then I am setting file-scope, which would make that variable available to every helper for that particular template. If I do not use var, it will be global and therefore available to the helpers in every template. Is that correct?
The following block of code works fine, returning the correct value in the client:
Template.CompanyFinancials.helpers({
priceEarningsFy1: function () {
var compTicker = this.ticker
var price = Companies.findOne({ticker: compTicker}).capTable.lastClose;
var epsFy1 = Companies.findOne({ticker: compTicker}).fy1.eps;
return (price / epsFy1).toFixed(1)
});
I have dozens of similar calculations throughout this app and many which rely on more variables than this example, so I have been trying to factor out the variables and reuse them in the template, like so:
var compTicker = function() {
return this.ticker;
};
console.log(compTicker);
var price = function(compTicker) {
Companies.findOne({ticker: compTicker}).capTable.lastClose;
};
console.log(price);
var epsFy1 = function(compTicker) {
Companies.findOne({ticker: compTicker}).fy1.eps;
};
console.log(epsFy1);
Template.CompanyFinancials.helpers({
priceEarningsFy1: function (price, epsFy1) {
return (price / epsFy1).toFixed(1)
}
});
With this code, console.log() actually returns the text within each function (e.g., return this.ticker) for each variable, not the value. If I declare the variables without functions, like I’ve done within the helper, it returns undefined for compTicker.
I tried to follow this answer which explains reusable code, but not clear if same use case applies. My variables point to specific fields in the database, not necessarily calculations.
Can anyone help me repair my syntax? I'm writing multiples more code than I need to with my current understanding. Thank you.
EDIT
I also tried declaring the variables the same way they are declared in the helper, but these return undefined.
var compTicker = this.ticker;
console.log(compTicker);
var price = CompaniesFeed.findOne({ticker: this.ticker}).capTable.lastClose;
console.log(price);
var epsFy1 = CompaniesFeed.findOne({ticker: this.ticker}).fy1.eps;
console.log(epsFy1);
RESOLUTION:
Using global helpers and returning multiple values, then using dot notation to access in the template HTML:
Template.registerHelper('priceEarnings',function(){
var ticker = this.ticker;
var company = CompaniesFeed.findOne({ticker: ticker});
return {
peFy1: (company.capTable.lastClose / company.financial.fy1.eps).toFixed(1),
peFy2: (company.capTable.lastClose / company.financial.fy2.eps).toFixed(1)
};
});
<td>{{priceEarnings.peFy1}}x</td>
You might be looking for global helpers. These are helpers which can be reused across all templates.
For your priceEarningsFy1 function for example:
Template.registerHelper('priceEarningsFy1',ticker => {
const company = Companies.findOne({ticker: ticker});
return ( company.capTable.lastClose / company.fy1.eps ).toFixed(1);
});
In this case I've specified that ticker is to be provided as an argument. From a blaze template you would use {{priceEarningsFy1 this.ticker}} for example. To refer to this function from js code use UI._globalHelpers.priceEarningsFy1(ticker)
Note that any local functions you define inside a given file are available to any other functions inside the same file. My pattern is to put all my global helpers in one file sorted by name and then at the bottom add various utility functions for use by the global helpers. This keeps things relatively dehydrated.
I've got some issues wrapping an application, developed through netbeans 8 in html5 and javascript, into PhoneGap to make it playable also on iOS devices.
So (since it's anyway a matter i want to learn) I'm trying a port to the iOS native Objective-C language in Xcode.
I could already re-write some Javascript functions, but as I came in need to store some of my Box2D objects and structs into arrays or dictionaries I started to feel lost.
my situation is like this:
in Javascript i can make arrays to store all the objects and fixtures i need to create in this way:
function createBoxStart(){
//create three objects when game starts
for (i = 0; i < '...number of objects i need'; i++) {
var start = {x: '...some operation to get my x',
y: '...some operation to get my y'};
var fixDefContainer = new Array();
fixDefContainer['fixDef'+prodNum] = new box2d.b2FixtureDef;
fixDefContainer['fixDef'+prodNum].density = 10;
fixDefContainer['fixDef'+prodNum].friction = 10 ;
fixDefContainer['fixDef'+prodNum].restitution = myBox[prodNum].reflection;
var bodyDefContainer = new Array();
bodyDefContainer['bodyDef'+prodNum] = new box2d.b2BodyDef();
bodyDefContainer['bodyDef'+prodNum].type = box2d.b2Body.b2_dynamicBody;
bodyDefContainer['bodyDef'+prodNum].position.x = start.x /scale;
bodyDefContainer['bodyDef'+prodNum].position.y = start.y /scale;
bodyDefContainer['bodyDef'+prodNum].gravityScale = myBox[prodNum].g;
bodyDefContainer['bodyDef'+prodNum].linearDamping = myBox[prodNum].lDamp;
bodyDefContainer['bodyDef'+prodNum].angularDamping = myBox[prodNum].angDamp;
bodyDefContainer['bodyDef'+prodNum].userData = coinBox[prodNum].userName ;
fixDefContainer['fixDef'+prodNum].shape = new box2d.b2CircleShape(coinBox[prodNum].size/scale);
myBody[prodNum] = bodyDefContainer['bodyDef'+prodNum];
myBody.id = myBody[prodNum].userData;
myObj[prodNum] = world.CreateBody(bodyDefContainer['bodyDef'+prodNum]);
myObj[prodNum].CreateFixture(fixDefContainer['fixDef'+prodNum]);
prodNum++;
.....
..... }...}
However in Xcode I've to create a "NSArray* myArray" object, and also, as long I've made it, I found out I cannot store any C++ objects into it without wrapping them before.
I'm still trying to make it work using the NSValue class as i saw in some tutorials, but also i totally don't know yet how to store the fixtures, since they're neither initialized with a pointer.
Here is how i create the "myFixDef" object, and since it has not a "*" i cannot wrap it into the NSVAlue class.
b2FixtureDef myFixDef;
Thanks in advance for any help and suggestion
A b2FixtureDef is really just a collection of properties like friction, restitution, density etc. You can store that in an Obj-C structure if it's easier, and then just set the properties in a b2FixtureDef when you need to create a fixture.
I have an array of data. I have put this data on my site in different places over different attributes, how innerHTML value placeholder etc.
Is it possible to link this values with the array from where I can take data? So that when I change the data in array, it going automatic changed on the site?
Also I try to show how I did it mean:
var test = Array();
test['place1'] = 'NY';
var myspan = document.createElement('span');
myspan.innerHTML = test['place1'];
On some event the value of test['place1'] is changed to 'LA', and at the same moment the value of myspan.innerHTML must be changed too.
Native JS only please.
This needs to be manually managed. A simple solution would be something like this:
function Place(container, initVal) {
this.container = container ? container : {};
this.set(initVal);
}
Place.prototype.place = "";
Place.prototype.get = function() {
return this.place;
}
Place.prototype.set = function(val) {
this.place = val;
this.container.innerHTML = val;
}
var test = {}; // object
test['place1'] = new Place(document.createElement('span'), "NY")
test['place1'].set('New Value');
This is not a full-feature solution, but gives you an idea of the coordination that needs to take place.
If you're only supporting modern browsers, then the syntax can be cleaned up a bit by using getters/setters.
In the future, you'll be able to use Proxy, which will make it even easier and cleaner.
There is no native way to bind an attribute of an HTML element to the values of an array, but you aren't actually using an array; you're using an object, and it is a simple matter to define special features on an object. For example:
First, define your object:
function boundArray(){
this._bindings = {};
this.setBinding = function(key,element){
this._bindings[key] = element;
};
this.setValue = function(key,value){
this[key] = value;
if(this._bindings[key]){
this._bindings[key].innerHTML = value;
}
}
}
Then use it in your code:
// create a new instance of the boundArray
var test = new boundArray();
// create the HTML element to use, and add it to the DOM
var myspan = document.createElement('span');
document.body.appendChild(myspan);
// bind the HTML element to the required key in the boundArray
test.setBinding('place1',myspan);
// Now every time you set that key on the boundArray (using setValue), it will also change the innerHTML field on the element
test.setValue('place1','NY');
// You can access your information from the boundArray in the usual ways:
var somevar = test.place1;
var anothervar = test['place1'];
What you are talking about is an MVVM solution. Most MVVM JavaScript solutions uses some object that represents an observable, which is a field within the object. When the value in the object changes, the observable lets the framework know to update the DOM. It also listens to the DOM for change events, and updates the object in reverse. For arrays, it's a similar process: it listens for adds or removes of the array, and updates the UI accordingly.
As #MCL points out in the comments on this post below, there is a way to watch changes to an object, and it isn't overly difficult to generically attach to an element on the DOM. However, There are a lot of good frameworks out there that make this REALLY easy, so that may be something to consider.
I am trying something new and I am having issues with my current idea. I am still new and trying to grasp the basics of using objects so I might be completely off base with this but I thought I might ask you all if what I am doing has any chance of working.
// first we can make the instructor
function Rabbit(adjective) {
this.adjective = adjective;
this.describeMyself = function() {
console.log("I am a " + this.adjective + " rabbit");
};
}
// now we can easily make all of our rabbits
var rabbit1 = new Rabbit("fluffy");
var rabbit2 = new Rabbit("happy");
var rabbit3 = new Rabbit("sleepy");
for (i=1;i<=3;i++){
//console.log("rabbit"+i);
var tempRabbit = "rabbit"+i;
console.log(tempRabbit.adjective);
}
I want to use the for loop to add the number to each rabbit object i created and then print out the adjective it has passed into it.
Most people store rabbits in arrays. This makes it much easier to manage the growing population of these marvelous creatures.
Here's an example:
var rabbitArray = [
new Rabbit("fluffy"),
new Rabbit("happy"),
new Rabbit("sleepy")
];
for (var i=0;i<rabbitArray.length;i++) {
console.log(rabbitArray[i].adjective);
}
You can also push new rabbits into the array you've got. There's special method for that:
rabbitArray.push(new Rabbit("stubborn"));
If you need more information on how to use arrays to simplify the management of your stock, refer to this documentation: Javascript Arrays
In your code:
> for (i=1;i<=3;i++){
> //console.log("rabbit"+i);
> var tempRabbit = "rabbit"+i;
> console.log(tempRabbit.adjective);
> }
the value of tempRabbit is a string, and strings don't have an adjective method. Since your Rabbit objects are assigned to global variables, you can access them as named properties of the global object. In browsers, the window object is essentially the global object so you could use square bracket notation:
console.log(window[tempRabbit].adjective);
However, probably better to put your Rabbits in an array and access them as members (per other answers).
You can use eval with:
eval('var tempRabbit = rabbit'+i+';');
This will create and evaluate the string.
You have to know that some people find eval awful.
You can use an array, and then access it by index.
var rabbits=[];
rabbits[0]= new Rabbit("fluffy");
rabbits[1] = new Rabbit("happy");
rabbits[2] = new Rabbit("sleepy");