OK, let's say on main.js, I have this:
var topMenu = require('./menu.js');
console.log(topMenu.getCount()); // 1
topMenu.increment();
console.log(topMenu.getCount()); // 2
and on menu.js, I have this:
exports.currentTab = 0;
var count = 1;
exports.increment = function() { count++; };
exports.getCount = function() { return count; };
exports.showSearch = function () {
$(".about-box").removeClass("active");
$(".tele-box").removeClass("active");
$(".tuts-box").addClass("active");
$(".search-div").toggle();
if (!$(".search-div").is(":visible")) {
$(".tuts-box").removeClass("active");
}
currentTab = 1;
}
module.exports = [
exports.onKeyPressing = document.onkeypress = function(evt) {
if (evt.keyCode == 49) {
console.log("Open 1st box");
showTeles();
}
if (evt.keyCode == 50) {
console.log("Open 2nd box");
showSearch();
}
if (evt.keyCode == 51) {
console.log("Open 3rd box");
showAbout();
}
}
];
My bundle.js compiles correctly. That, I do know. However, open visiting the page, I get Uncaught TypeError: undefined is not a function on line console.log(topMenu.getCount()); // 1 in main.js (bundle.js since it compiled correctly...)
However, when I remove this and what's inside:
module.exports = [
...
];
that is found near the bottom of menu.js, then it works and I get:
1
2
as expected. What is wrong with my file and how do I fix it? Also, I'm probably defining exports.showSearch() wrong. In all, can you locate the errors I am making while making this file? Thank you.
exports is an alias to module.exports. So, when you assign an array to module.exports in this part:
module.exports = [
...
];
You are overriding (clearing) the value in module.exports and hence exports. So all of these assignments are lost:
exports.currentTab = 0;
exports.increment = function() { count++; };
exports.getCount = function() { return count; };
exports.showSearch = function () {
// ...
}
And that's why you get Uncaught TypeError: undefined is not a function. There is no such function as getCount() attached to exports (and topMenu).
Update
I don't know what you want to achieve, but removing the assignment to module.exports might solve the problem:
exports.onKeyPressing = document.onkeypress = function(evt) {
// ...
}
Again, it depends on what you want to achieve.
Related
I'm really stuck on this.. I need to send an event when both Load module and Hide module code was executed, and only then send the event. Ideas on how to achieve this?
// Load module
(
function() {
var s=document.createElement('script');
s.type='text/javascript';
s.async=true;
s.src='https://example.com/bundles.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
}
)();
// Hide module
var inverval = setInterval(hideClass, 100);
function hideClass () {
if ($(".class").hide().length > 0) clearInterval(inverval);
}
// When both happend = Send a event to Google Analytics
DigitalData.push({'event':Module, 'eventLabel':'Page'});
If this is your only option, then perhaps there's something you are going about wrongly. Anyway, let's see ... Only when both events have taken place.
var HandleTwoEvents = function (key1, key2) {
this.count = 0;
this.pack = [];
$self = this;
this.startListening = function(fn) {
fn = fn || function () {}
window.addEventListener(key1, function (ev) {
if ($self.pack.indexOf(key1) < 0) {
$self.pack.push(key1);
$self.count++;
if ($self.count == 2) {
fn();
$self.count = 0;
}
}
console.log(key1, ev);
});
window.addEventListener(key2, function (ev) {
if ($self.pack.indexOf(key2) < 0) {
$self.pack.push(key2);
$self.count++;
if ($self.count == 2) {
fn();
$self.count = 0;
}
}
console.log(key2, ev);
});
}
}
Forgive me, i always use this function to create events
function createEvent(name, obj) {
var evt = document.createEvent("Event");
evt.initEvent(name, true, true);
evt.data = obj;
dispatchEvent(evt);
}
Now, to log both events ...
var both = new HandleTwoEvents("EventKeyOne", "EventKeyTwo");
both.startListening(function () {console.log("This means that both Events have taken place")});
Now, let's test ...
createEvent("EventKeyOne", {});
//key, data are the arguments ... function defined in startListening above does not execute, and upon inspection, both.count is seen to be 1
createEvent("EventKeyTwo", {});
//Now, function executes.
//It also works if "EventKeyTwo" is raised before "EventKeyOne"
Happy Coding!
PS: I'm sure there's a better way to handle the use of the $self variable, with some function binding, i guess. I've never been able to learn it.
I'm trying to make something in JS and using browserify to use other JS files in my main code. I know I have node and browserify installed correctly because I can enter "browserify example.js -o bundle.js" in the terminal and run his code just fine.
I finally just added my function (soundoff()) to his system.js code below and tried calling it the same way he called the functions in this file in the second code snippet...
module.exports = (function (){
var _final = "",
DEFAULT_STEP = 15,
DEFAULT_TURN = Math.PI / 4;
/* Initializes an L-System using the supplied
* axiom, rules, and number of iterations
* params:
* - axiom: the starting string
* - rules: the array of rules as string -> string
* key/value pairs (i.e. ["key", "value"]
* - iterations: the number of iterations to carry out
*/
function lsystem(axiom, rules, iterations) {
_final = axiom;
for(var i = 0; i < iterations; i++) {
_final = apply(_final, rules);
}
return _final;
}
function soundoff(done) {
return done;
}
You see below here I'm calling it the same way he's calling other functions from the ls reference/function/module but I still get "Uncaught TypeError: ls.soundoff is not a function"
window.onload = function() {
var ls = require('./lsystem.js');
var wonk = ls.soundoff("wonk!");
// Set up the algae demo
var aIter = document.getElementById("algae-iterations"),
aOut = document.getElementById("algae-output");
aOut.value = ls.algae(0);
aIter.onchange = function() {
aOut.value = ls.algae(aIter.value);
}
Without calling this function it works perfectly. Those aren't the whole code files but I know everything else if fine since they work, I just can't figure out why I can't have a function I put in like that and call it...
Thanks in advance for the help! :)
That wont work. Because soundoff is a function within lsystem function, which means soundoff is not accessible as a property.
If you can change your lsystem to export an Object and do this, it will work.
module.exports = {
soundoff : function(done){
return done;
}
}
Edit :
Method 1:
file1.js
module.exports = (function func(){
return {
soundoff : function(done){
return done;
}
}
});
file2.js
var func = require('file1');
var obj = func();
obj.soundoff('wonk');
Method 2.
file1.js
module.exports = {
soundoff : function(done){
return done;
}
}
file2.js
var obj = require('file1');
obj.soundoff('wonk');
Method: 3
There are other dirty ways where you could, use the this property in conjunction with Function.prototype.call, but I would advise you not to go for it. Do not use it, like, ever. Highly volatile.
file1.js
module.exports = (function func(){
this.soundoff = function(done){
return done;
}
});
file2.js
var func = require('file1');
func.call(func);
func.soundoff('wonk');
I've been playing with jasmine recently in order to start incorporating tests in my projects.
All seemed to work fine until, I wanted to automate the workflow with karma (previously Karma).
In my src directory, I have simple Calculator Object with a couple of simple methods:
function Calculator() { };
var current = 0;
Calculator.prototype.add = function() {
if (arguments.length < 2) {
// we only have one arguments
current += arguments[0];
return current;
} else {
// more than one arguments
for( var i in arguments )
current += arguments[i];
return current;
}
};
Calculator.prototype.substract = function() {
var currentValue = arguments[0];
for ( var i = 1; i < arguments.length; i++ )
currentValue -= arguments[i];
return currentValue;
};
Calculator.prototype.reset = function() {
window.current = 0;
}
Then in my spec file, I do have the following ( all tests passes without Karma ):
var calculator = new Calculator();
describe('Calculator', function() {
beforeEach(function() {
window.current = 0;
});
describe('When adding numbers', function() {
it('should store the current value at all times', function() {
expect(window.current).toBeDefined();
});
it('should add numbers', function() {
expect(window.calculator.add(5)).toEqual(5);
expect(window.calculator.add(10)).toEqual(15);
});
it('should add any number of numbers', function() {
expect(calculator.add(1, 2, 3)).toEqual(6);
expect(calculator.add(1, 2)).toEqual(9);
})
});
describe('When substracting numbers', function() {
it('should substract any number of numbers', function() {
expect(calculator.substract(5, 3)).toEqual(2);
});
});
it('should reset the current value back to zero', function() {
window.current = 20;
calculator.reset();
expect(window.current).toEqual(0);
calculator.add(5);
calculator.add(20);
expect(window.current).toEqual(25);
calculator.reset();
expect(window.current).toEqual(0);
});
});
When I run karma start, I get the following:
Chrome 28.0 (Mac) ERROR
Uncaught ReferenceError: Calculator is not defined
at /Users/roland/learning/jasmine/jasmine-standalone-1.3.1/spec/calculator_spec.js:1
Thank you for the help!
It seems like you're not loading the file that has Calculator or perhaps it's being loaded after the spec file. In your Karma configuration file, you'll want to do something like this:
files = [
'path/to/calculator.js',
JASMINE,
JASMINE_ADAPTER,
'path/to/calculator_spec.js'
];
The problem is I need to break the function if it is first time running
is there any function available , or I have to do something like the following?
var times = 1
function abc () {
if (times == 1)
break;
else
.....
times++;
}
times = 0;
Thanks.
You can use this pattern:
function abc() {
if (!abc.flag) {
abc.flag = true;
return;
}
// .. rest of the code
}
It's based on the fact that Function is also an object in Javascript.
Basically this is a Memoization pattern. It has disadvantage that the flag property can be overwritten by another code. The advantage is that you don't need to pollute global scope with additional variables.
thg435 proposed much more elegant solution.
It appears to me that you're trying to solve the problem in the wrong place. Can you tell us the whole story?
In the meantime, something like this should do the trick:
function abc() {
abc = function() {
// ...actual work...
}
}
Details depend on how your function is defined (globally, locally, as a method).
var isFirstTime = true;
function abc () {
if (isFirstTime)
{
isFirstTime = false;
return;
}
.....
}
abc(); //returns
abc(); //runs
var firstTime= true
function abc () {
if (firstTime)
{
firstTime = false;
return;
}
else
{
.....
}
}
Try This :
var times = 1;
function abc () {
if (times == 1){}
else{
.....
times == 0;}
}
I'm trying to make a state machine but it's not working out. I've got this code so far:
function makeStateMachine() {
this.stateConstructors = new Object();
this.currState = {
update : function(e) {
// Nothing to do here
},
exit : function() {
// Nothing to declare
}
};
this.nextState = null;
var that = this;
this.update = new function(e) {
that.currState.update(e);
that.changeState();
};
this.setNextState = new function(targetState) {
that.nextState = targetState;
};
this.addState = new function(constructor, stateName) {
that.stateConstructors[stateName] = constructor;
};
this.changeState = new function() {
if (that.nextState != null) {
that.currState.exit();
that.currState = new that.stateConstructors[that.nextState]();
that.nextState = null;
}
};
}
When I try to run it firebug displays this error: "TypeError: that.changeState is not a function" at the line in the update function. When I uncomment the changeState() line it starts whining about the EaselJS library being incorrect (which I know is correct, because it works for other projects of mine). Can somebody help me out here? It probably something very simple (just like always) but I just can't spot the error. I can post the rest of the code if you guys like but I don't think it's relevant.
Thanks in advance!
You should be putting those functions in the prototype. You also should not be using = new function(...; just use = function(.... Finally, you don't need that. Try this code:
function makeStateMachine() {
this.stateConstructors = {};
this.currState = {
update : function(e) {
// Nothing to do here
},
exit : function() {
// Nothing to declare
}
};
this.nextState = null;
}
makeStateMachine.prototype.update = function(e) {
this.currState.update(e);
this.changeState();
};
makeStateMachine.prototype.setNextState = function(targetState) {
this.nextState = targetState;
};
makeStateMachine.prototype.addState = function(constructor, stateName) {
this.stateConstructors[stateName] = constructor;
};
makeStateMachine.prototype.changeState = function() {
if (this.nextState != null) {
this.currState.exit();
this.currState = new this.stateConstructors[this.nextState]();
this.nextState = null;
}
};