Is there a way load class names as variables? new window[a] does not seem to work. I'm getting an error of TypeError: window[a] is not a constructor.
require([
'myController'
], function (myController) {
// this is working fine
// new myController().init();
$(function() {
var a = $('.test').attr('class'); // this returns myController
new window[a]; // error here
});
});
To do what you want you would need to use eval like this:
eval("new " + window[a] + "()");
Working example: https://jsfiddle.net/ybjo4pn9/
NOTE: Use eval with caution.
Related
im an javascript newbie and google didnt helps:
I tryed to load ByteBuffer.js in an require.js module:
define(['js/ByteBufferAB'], function (ByteBufferAB) {
var MessageBase = function () {
this._version = 0; // unsinged int 16 bits
this._dataType = "";
};
MessageBase.prototype.toBytes = function () {
//console.log( new ByteBufferAB(58));
var headerBytes = new ByteBufferAB(58); // <-- here comes the error
headerBytes.clear();
return headerBytes;
};
return MessageBase;
});
with the same syntax math.js is properly loaded.
But with ByteBufferAB.js the following error comes:
Uncaught TypeError: undefined is not a function
What am I doing wrong?
Thank you for your help
In your define call you refer to the module as js/ByteBufferAB so RequireJS looks for a module named js/ByteBufferAB. However, the module defines itself as ByteBuffer:
/* AMD */ else if (typeof define === 'function' && define["amd"])
define("ByteBuffer", ["Long"], function(Long) { return loadByteBuffer(Long); });
Because the module name is hardcoded, you need to have a mapping like this in your paths in the configuration you give to RequireJS:
ByteBuffer: "js/ByteBufferAB"
and you need to refer to the module as ByteBuffer in your define call.
None of this would be required if the developers for this library had not hardcoded a name but they have, and so here we are.
I am trying to add a functionality to a web page that uses a jquery library which doesn't seem to have any documentation. (unknown origin) my problem is mainly due to the lack of understanding on jquery plugin model and/or inner workings of javascript.
1. the plugin is initiated as follows
jQuery('div.carousel').scrollGallery({
mask: 'div.mask',
slider: 'div.slideset',
slides: 'div.slide', ............ });
2. the plugin is defined in jquery as follows
;(function($){
function ScrollGallery(options) {
this.options = $.extend({
mask: 'div.mask', ...... }, options);
this.init();
3. in the Object.prototype declaration i see the following function numSlide defined.
ScrollGallery.prototype = {
....................
numSlide: function(c) {
if(this.currentStep != c) {
this.currentStep = c;
this.switchSlide();
}
},
.......... };
Question.
How do i reference numSlide(int) function externally?.
I tried the following methods and it did not work.
myx = jQuery('div.carousel').scrollGallery({ // var myx was added in the global scope
myx.numSlide(1); //error undefined is not a function
i tried adding return this; at the end of myx = jQuery('div.carousel').scrollGallery({ but it still returns the jQuery object.
i also tried
jQuery.scrollGallery().numSlide(2); //error undefined is not a function
jQuery.scrollGallery.numSlide(2); //same error
Do i need to add LIGHT BULB
// jquery plugin
$.fn.scrollGallery = function(opt){
return this.each(function(){
$(this).data('ScrollGallery', new ScrollGallery($.extend(opt,{holder:this})));
});
};
}(jQuery));
ANSWER (I think)
it looks like the ScrollGalary object is stored in a data for the selector. So i believe i can do the following jQuery('selector').data('ScrollGallery').numSlide(2);
I decided to post this anyway in-case if anyone in the future had a similar gullible situation.
One way of doing this will be to initiate ScrollGallery object first and then use it.
var test = new ScrollGallery();
test.numSlide();
if you want to extend jQuery and use the function you can assign it as follows
$.fn.scrollGallery = new ScrollGallery();
and use it
$("window").scrollGallery.numSlide();
I am trying to stub a method using sinon.js but I get the following error:
Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function
I also went to this question (Stubbing and/or mocking a class in sinon.js?) and copied and pasted the code but I get the same error.
Here is my code:
Sensor = (function() {
// A simple Sensor class
// Constructor
function Sensor(pressure) {
this.pressure = pressure;
}
Sensor.prototype.sample_pressure = function() {
return this.pressure;
};
return Sensor;
})();
// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure").returns(0);
// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure", function() {return 0});
// Never gets this far
console.log(stub_sens.sample_pressure());
Here is the jsFiddle (http://jsfiddle.net/pebreo/wyg5f/5/) for the above code, and the jsFiddle for the SO question that I mentioned (http://jsfiddle.net/pebreo/9mK5d/1/).
I made sure to include sinon in the External Resources in jsFiddle and even jQuery 1.9. What am I doing wrong?
Your code is attempting to stub a function on Sensor, but you have defined the function on Sensor.prototype.
sinon.stub(Sensor, "sample_pressure", function() {return 0})
is essentially the same as this:
Sensor["sample_pressure"] = function() {return 0};
but it is smart enough to see that Sensor["sample_pressure"] doesn't exist.
So what you would want to do is something like these:
// Stub the prototype's function so that there is a spy on any new instance
// of Sensor that is created. Kind of overkill.
sinon.stub(Sensor.prototype, "sample_pressure").returns(0);
var sensor = new Sensor();
console.log(sensor.sample_pressure());
or
// Stub the function on a single instance of 'Sensor'.
var sensor = new Sensor();
sinon.stub(sensor, "sample_pressure").returns(0);
console.log(sensor.sample_pressure());
or
// Create a whole fake instance of 'Sensor' with none of the class's logic.
var sensor = sinon.createStubInstance(Sensor);
console.log(sensor.sample_pressure());
The top answer is deprecated. You should now use:
sinon.stub(YourClass.prototype, 'myMethod').callsFake(() => {
return {}
})
Or for static methods:
sinon.stub(YourClass, 'myStaticMethod').callsFake(() => {
return {}
})
Or for simple cases just use returns:
sinon.stub(YourClass.prototype, 'myMethod').returns({})
sinon.stub(YourClass, 'myStaticMethod').returns({})
Or if you want to stub a method for an instance:
const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
I ran into the same error trying to mock a method of a CoffeeScript class using Sinon.
Given a class like this:
class MyClass
myMethod: ->
# do stuff ...
You can replace its method with a spy this way:
mySpy = sinon.spy(MyClass.prototype, "myMethod")
# ...
assert.ok(mySpy.called)
Just replace spy with stub or mock as needed.
Note that you'll need to replace assert.ok with whatever assertion your testing framework has.
Thanks to #loganfsmyth for the tip. I was able to get the stub to work on an Ember class method like this:
sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
I am creating a typing game which I have "app.js" as a main and loading "words.js" by requirejs.
I need to use > 2 words but I am still naive with javascript and not sure this is right to do in AMD. Anyone could point me out. I would really appreciate it.
I think it would be like following code but it doesn't work and give me error
"Uncaught TypeError: object is not a function"
[app.js]
require(['jquery','app/canvas','app/words'], function($,game_screen,words){
var words1 = new words();
var words2 = new words();
.
.
});
[words.js]
define(['app/canvas'],function(canvas){
var word_list=[{"word1"},{"word2"},...];
return {
addWord: function(new_word){
.
.
});
Right now you're returning an object from your words module: { addWord: function() {} ... }. So in app.js, when you set words to be equal to the object returned from the words module, you would invoke the functions by doing words.addWord().
If instead you want to use the new words() syntax in app.js, you would have to change your words module to return a function instead of an object (hence the error):
define(['app/canvas'],function(canvas) {
var word_list=[{"word1"},{"word2"},...]; // not sure how this is used
function words() {
// some code
}
words.prototype.addWords = function() {
// some code
}
return words;
}
I have the following code to test using sinon:
var req = new MultiPartUpload({
client: client,
objectName: "/" + obj.func.destPath(),
stream: obj.outStream,
headers: headers
}, function (err, body) {
obj.debug('uploaded' + body);
});
I have to test the creation of this object. How can I do it? I have tried with:
var MultiPartUpload = require('knox-mpu');
var stub = sinon.createStubInstance(MultiPartUpload);
instance(obj, function () {
expect(stub).to.have.been.called;
done();
});
But it doesn't work as expected. Any suggestion? Thank you :)
EDIT:
instance is the istance of the object that creates the MultiPartUpload object. The problem is that the instance signature cannot be changed and that the MultiPartUpload library is required in the file where instance is created.
In short: I have to spy the MultiPartUpload library, and the problem is that is not possible to communicate in any way with istance, where the library is used.
From the docs:
Creates a new object with the given function as the protoype and stubs
all implemented functions. The given constructor function is not
invoked
This mean that sinon.createStubInstance(MultiPartUpload); will return a new stub with all prototype functions as stubs. I think you looking for a way to spy if the MultiPartUpload function was called, so one way could be to overwrite MultiPartUpload with the stub:
var MultiPartUpload = require('knox-mpu');
var stub = sinon.stub().returns(sinon.createStubInstance(MultiPartUpload));
MultiPartUpload = stub;
instance(obj, function () {
expect(stub).to.have.been.called;
done();
});
The only way to make it work that I found was this: instead of having:
var MultiPartUpload = require('knox-mpu');
In the instance code. I changed it to:
MultiPartUpload = require('know-mpu');
Then in the test-case I simply put:
MultiPartUpload = sinon.spy();
instance(obj, function () {
expect(MultiPartUpload).to.have.been.called;
done();
});
Any way to do it better than this? (I don't like global vars). Thanks :)
Have you looked into something like https://github.com/felixge/node-sandboxed-module ? When you require the instance module, you could use SandboxedModule to substitute a spy for knox-mpu.
Edit: I can't give a complete working example, because you haven't given us all your code. But sandboxed-module works something like this:
var SandboxedModule = require('sandboxed-module')
, MultiPartUploadSpy = sinon.spy()
, expect = chai.expect
, YourInstanceModule = SandboxedModule.require('your-instance-module', {
requires: {'knox-mpu': MultiPartUploadSpy}
})
instance(obj, function () {
expect(MultiPartUploadSpy).to.have.been.called;
done();
});