I have this code:
collection = (function() {
function collection(removeLinkTitle){
this.removeLinkTitle = removeLinkTitle || 'delete';
}
collection.prototype = {
removeLinkTitle: this.removeLinkTitle,
init:function(){
...some code...
this.deleteCollectionForm();
},
deleteCollectionForm:function(){
var removeFormA = $(''+this.removeLinkTitle+'');
linkLi.append( removeFormA );
removeFormA.on('click', function(e) {
e.preventDefault();
linkLi.remove();
var index = collectionHolder.data( 'index' );
collectionHolder.data( 'index', index - 1 );
});
}
};
return collection;
})();
The thing is that the var removeForm returns its value only the frst time it loads, the following times it returns undefined.
I don't want to pass the variable as an argument so, is it there any other way to do this?
Thanks !!
i think this is not really the problem, the one thing that is undefined is the, removeLinkTitle, try this:
return new collection;
so you hit your constructor, or set some other value with:
return new collection("delete item");
Related
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.
I have problem with below code. I have prices factory which returns object containing prices received from server by websocket. Prices are sent after button Create is clicked. Problem is that main.prices variable is not updated at all. I can check everything by Check button, which confirms this. Prices.data is updated, but this.prices is not, but it refers the same object, so I thought it should be updated as well. Do you have any ideas why below does not work as expected?
angular.module('myApp', ['ngWebSocket'])
.factory('ws', ['$websocket', function($websocket){
var url = 'ws://localhost/websocket';
var ws = $websocket(url);
return ws;
}])
.factory('prices', ['ws', function(ws){
var prices = {
data: [],
clear: function(){
this.data = [];
},
create: function(){
ws.send('send')
}
}
ws.onMessage(function(message){
message = JSON.parse(message.data);
var type = message.type;
if (type == 'new prices'){
prices.data = message.data;
}
});
return prices;
}])
.controller('main', ['prices', function(prices){
this.prices = prices.data;
this.check = function(){
console.log('works ', prices.data);
console.log('not works ', this.prices);
};
this.create = function(){
prices.create();
};
this.stop = function(){
prices.clear();
};
}]);
<div ng-controller="main as main">
{{ main.prices }}
<button ng-click="main.create()">Create</button>
<button ng-click="main.stop()">Stop</button>
<button ng-click="main.check()">Check</button>
</div>
There are a lot of issues with the code you posted (working on a fiddle so i can help rework it) ...
First change :
if (type == 'new prices'){
prices.data = message.data;
}
To:
if (type == 'new prices'){
prices.data.length = 0;
prices.data.push.apply(prices.data,message.data) ;//copy all items to the array.
}
From a readability / maintainability point of view you should just use this.prices vs this.prices.data. It's confusing to map them to other variables, when you can just use prices. Also note that I updated it to use "that" constantly to avoid any type of context this issues.
.controller('main', ['prices', function(prices){
var that = this;
that.prices = prices;
that.check = check;
that.create = create;
that.stop = stop;
function check(){
console.log('works ', that.prices.data);
console.log('not works ', that.prices);
}
function create(){
that.prices.create();
}
function stop(){
that.prices.clear();
}
}]);
To add to the previous response, you also have an issue on the clear():
var prices = {
...
clear: function(){
this.data = [];
},
...
}
when you do the clear with this.data = [] you are actually creating a new empty array an storing that in the this.data prop, and since this is a NEW array, the reference on main controller -> this.prices = prices.data; is still pointing to the old one. If you need to delete elements on the array just use this.data.length = 0 as Nix pointed out for the other method. that will keep all references in sync since you are re using the original array
Ok, so I'm a complete newbie to OOP in Javascript, apparently. I thought I understood it, but it appears I only know a small portion. Anyway, what I'm trying to do is setup an object to store and return data from an XML input by using a fairly simple string to retrieve data. I'd like to retrieve the data with a string similar to reader.getItem().getSubItem() or something like that.
Below is an example of what I attempted, but I get the error anonymous is not a function each time I try to do a call to fr.getType().isTexture() so obviously, I need to change something.
//Create the object by passing an XML element containing sub-elements
var fr = new FeatureReader(test.child(i));
alert(fr.getName()); //returns the object's name
alert(fr.getType().isTexture()); //"anonymous is not a function" error
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = new function() {
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
this.isModel = new function() {
if (feat.type.model == "yes") {
return true;
}
return false;
};
};
}
Now, obviously I could just remove the surrounding this.getType = function() {} around the this.isTexture and this.isModel to get my data, but for the sake of learning something, I'd like to see how it is recommended that I set this object up to get the returned values using a string similar to what I mentioned in the first and second paragraphs.
When you do this:
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
you're setting the "isTexture" property to the object constructed, not to that function. If you drop the new keyword from the statement, you'll be setting "isTexture" to be a function.
An expression of the form new <some-function> evaluates to an object, in other words.
edit — your "getType" property will also be an object, for the same reason. However, I think this would work:
alert( fr.getType.isTexture() );
Also note that your if statement can be simplified:
return feat.type.texture == "yes";
What you can do is simply assign an object instead of using new:
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = {
isTexture: function() {
return feat.type.texture == "yes";
},
isModel: function() {
return feat.type.model == "yes";
}
};
}
Then use the method like:
instance.getType.isTexture()
Note that you don't need to return true or false, as returning an expression that evaluates to boolean like a == b
returns a boolean value.
I get undefined whenever I get the value of a property of an object.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report.id, // i get undefined
reportPath: report.path // i get undefined
};
...
}
services.js
angular.module('project.services').factory('services', function(){
var reports = [
{
....
},
{
....
}
];
function getReportInfo(id){
var report = reports.filter(function(element){
return element.id === id;
});
};
return{
getReportInfo: getReportInfo
};
}
Whenever I put breakpoint on my var report = services.getReportInfo(id) it could contains the correct values for each property of the my report object. However, when I get the report.id or report.path, I get undefined value.
--Edited--
Oh, I know now where I got wrong.
The getReportInfo function returns an array and I'm accessing the properties without telling from what index should it get the values for the said properties.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report[0].id,
reportPath: report[0].path
};
...
}
I placed static index 0, since I know that the array will always have a length of 1.
You are not returning anything from the .factory method and the getReportInfo is also not returning anything. For what you are trying to do, try to use .service method:
angular.module('project.services').service('services', function(){
var reports = [
{
....
},
{
....
}
];
this.getReportInfo = function (id){
var report = reports.filter(function(element){
return element.id === id;
});
return report;
}
}
Here is a good explanation on how to use .factory and .service:
Confused about Service vs Factory
Two immediate issues with the code I can see:
1) Your factory function needs to return a value or constructor function. Right now your code is not initializing the factory to any value.
2) Your getReportInfo function also doesn't return a value, yet you are assigning the function result to a variable.
Read more here: http://docs.angularjs.org/guide/dev_guide.services.creating_services
I have written some javascript that I would to encapsulate in a closure so I can use it elsewhere. I would like do do this similar to the way jQuery has done it. I would like to be able to pass in an id to my closure and invoke some functions on it, while setting some options. Similar to this:
<script type="text/javascript">
_snr("#canvas").draw({
imageSrc : someImage.png
});
</script>
I have read a lot of different posts on how to use a closure to do this but am still struggling with the concept. Here is where I left off:
_snr = {};
(function (_snr) {
function merge(root){
for ( var i = 1; i < arguments.length; i++ )
for ( var key in arguments[i] )
root[key] = arguments[i][key];
return root;
}
_snr.draw = function (options) {
var defaults = {
canvasId : 'canvas',
imageSrc : 'images/someimage.png'
}
var options = merge(defaults, options)
return this.each(function() {
//More functions here
});
};
_snr.erase = function () {};
})(_snr);
When ever I try to call the draw function like the first code section above, I get the following error, '_snr is not a function'. Where am I going wrong here?
EDIT
Here is what I ended up doing:
function _snr(id) {
// About object is returned if there is no 'id' parameter
var about = {
Version: 0.2,
Author: "ferics2",
Created: "Summer 2011",
Updated: "3 September 2012"
};
if (id) {
if (window === this) {
return new _snr(id);
}
this.e = document.getElementById(id);
return this;
} else {
// No 'id' parameter was given, return the 'about' object
return about;
}
};
_snr.prototype = (function(){
var merge = function(root) {
for ( var i = 1; i < arguments.length; i++) {
for ( var key in arguments[i] ) {
root[key] = arguments[i][key];
}
}
return root;
};
return {
draw: function(options) {
var defaults = {
canvasId : 'canvas',
imageSrc : 'images/someimage.png'
};
options = merge(defaults, options);
return this;
},
erase: function() {
return this;
}
};
})();
I can now call:
<script type="text/javascript">
_snr("#canvas").draw({
imageSrc : someImage.png
});
</script>
Because you declared _snr as an object and not a function. Functions can have properties and methods, so there's various ways to achieve what you want, for example one of them would be say...
_snr = function(tag) {
this.tag = tag;
}
_snr.foo = function() {
//Code goes here
}
You can also pass the outer context into a closure to hide your variables from accidentally polluting the global namespace, so like...
(function(global) {
var _snr = function(tag) {
this.tag = tag;
}
_snr.foo = function() {
//Code goes here
}
//export the function to the window context:
global._snr = _snr;
})(window);
window._snr('#tag').foo('wat');
Happy coding.
Because your _snr is an object, not a function. You have to call it like this:
_snr.draw({
canvasId: '#canvas',
imageSrc: 'someImage.png'
});
When you do _snr('#canvas') that is a function call which is why you're getting that error. _snr is an object with some methods attached to it such as draw() and erase(). The reason jQuery is able to pass arguments into the $ is because they return the $ as a function object which is why we're able to pass it various selectors as arguments.
You are going wrong at the first line _snr = {}
It needs to be
_snr = function(){
selector = arguments[0]||false;
//snr init on dom object code
return _snrChild;
}
Im on a mobile phone but when im on a pc I will maybe fix the whole code c:
Here you have a snr object and that has erase and draw methods. What you intend to do is to write a _snr function which will get an id and return a wrapper object. That returned object should have erase and draw methods. so you can do
var returnedObject = _snr("my_id");
returnedObject.draw("image.png");