I am trying to write a script for a dynamic drop down menu as a way to learn OOP javascript and jQuery. You can see the dummy site at www.industrialMerchants.com/industrialMerchants. The script can be found at www.industrialMerchants.com/industrialMerchants/javascript/horizontalDropMenu2.js
The script first defines a number of objects, after which I have a $(document).ready() with a closure designed to initiate the process of wrapping relevant jQuery objects and DOM elements into my object model.
The problem is, when I load the static html document serving as a dummy website, Firebug gives me the following error:
"TypeError: jqObject is undefined."
The error points to the fifth line of the following function.
function Menu(jqObject) {
self = this;
this.self = jqObject;
this.submenus = (function(){
jqObject.children().children("ul").each(function() { <<--- Error
submenu = new Submenu($(this), self);
submenus.push(submenu);
return submenus;
});
}());
}
The lines that call the function are here:
$(document).ready(function(){
menus = new Array();
$("ul.horizontalDropMenu").each(function(){
menu = new Menu($(this));
menus.push(menu);
});
});
As you can see, the call to the Menu() object constructor includes as an argument a reference to a jQuery object, so that jqObject clearly IS defined. So what gives?
When I insert breakpoints into the code starting at the $(document).ready() declaration, the execution completely skips it altogether, and starts at the function declaration itself. It's as if the browser is trying to execute the function declarations before any explicit call to them is made.
Setting a breakpoint and going up the call stack gives me this line (outside .ready - but that doesn't matter):
Submenu.prototype = new Menu();
You're creating a menu instance without a jQuery object but with undefined instead.
Related
I am new in HTML5 & trying to learn drag & drop feature.I have a JavaScript function for creating div element & attaching dragstart event to it.
var taskDefination = document.createElement("div");
taskDefination.className = "defaultButtonHolder";
taskDefination.setAttribute("draggable","true");
document.getElementById("toDo").getElementsByClassName('columnContent')[0].appendChild(taskDefination);
taskDefination.addEventListener('dragstart', dragStart, false);
}
Now I have a drop zone created as
<span class="columnWidth">
<div class ="columnHeader">Progress</div>
<div class ="columnContent" ondragenter ="dragDrop.dragEnter(event)"></div>
</span>
where the dragEnter function belongs to an external javascript file where it has been designed as a closure.I have checked network tab and this javascript file is perfectly loading.
var dragDrop = function(){
var _dragEnter = function(){
console.log("Dragged dropped");
}
return{
dragEnter:_dragEnter
}
}
Now the issue is whenever i am trying to drop the element in dropzone it is throwing an undefined not a function error. But ondropeneter event , if calling a function written in same HTML page it is perfectly executing.Why does it throwing an undefined not an function error though it is working fine function written in same HTML page?
Your closure isn't properly formed. As it stands, dragDrop is a function object returned from the function expression and as such doesn't have the code you want attached to it. Have a quick read of function expressions here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
It looks like you're trying to use a closure to implement a module pattern. To do this, you need to rebuild your code like this:
var dragDrop = (function() {
var _dragEnter = function(){
console.log("Dragged dropped");
}
return {
dragEnter:_dragEnter
}
})();
The first set of brackets around the (function {}) make it a closure. The second set of brackets afterwards (function {})() execute it immediately. This means your module is returned to the var dragDrop and then you will be able to successfully call dragDrop.dragEnter.
I have a problem when calling a function from a button in HTML that gives me the: "Uncaught TypeError: undefined is not a function" error. I don't think there's anything wrong here.. Or there is something that I haven't taken into account. Thanks in advance for answering!
I have a lot of JS files, this is because this is a school assignment and we're now learning the Model, View, Controller (MVC) method.
I have this button:
<button onClick="ControllerBKE.reageerOpKlik()">Ok!</button>
I then have this Javascript code that creates an object of ^ "ControllerBKE":
"use strict"
window.onload = reageerOpStart();
function reageerOpStart()
{
var controllerBKE = new ControllerBKE();
}
Here is the line of code that is in the "ControllerBKE" that should, but is not reacting to the button:
function ControllerBKE(){
this.reageerOpKlik = reageerOpKlik;
function reageerOpKlik(){
alert('hoi');
}
}
This is just a small portion of a big code. But I get the error message when I click on the button instead of getting an alert with 'hoi'.
reageerOpKlik is an instance method. You have to use it from an instance. The simplest solution (not the best) is to create a global controller instance. There are many ways you could get rid of that global variable, but it's beyond the scope of the question.
function reageerOpStart()
{
window.controllerBKE = new ControllerBKE();
}
<button onClick="window.controllerBKE.reageerOpKlik()">Ok!</button>
The problem is that your code
<button onClick="ControllerBKE.reageerOpKlik()">Ok!</button>
is trying to call reageerOpKlik on your prototype object ControllerBKE.
What you probably mean is
<button onClick="controllerBKE.reageerOpKlik()">Ok!</button>
where controllerBKE is an instance of your prototype.
However, you have another problem. The function:
function reageerOpStart()
{
var controllerBKE = new ControllerBKE();
}
Creates controllerBKE in the scope of the reageerOpStart function, meaning that it's not avaiable in the global scope, which is where your button click handler would expect it.
You might want to consider:
<button onClick="APP.controllerBKE.reageerOpKlik()">Ok!</button>
APP = {}
function reageerOpStart()
{
APP.controllerBKE = new ControllerBKE();
}
Or, better still:
<button id="myButton">Ok!</button>
function reageerOpStart()
{
var controllerBKE = new ControllerBKE();
document.getElementById("myButton").addEventListener("click", function() {
controllerBKE.reageerOpKlik();
});
}
What you have is referred to as a closure. Your function has a limited scope. That is, it can only be called inside of ControllerBKE() where it is defined, not from outside the function.
What you have effectively done though is expose that closure via a property on your instance of ControllerBKE. While this works, it would fit more with the prototypal structure of JavaScript to add it to ControllerBKE.prototype.
It's important to remember that JavaScript is Prototypal not Object Oriented. While this may act similar to object oriented encapsulation, the two have different concepts and uses.
Look at the following example:
HTML:
<button onclick="controllerBKE.reageerOpKlik()">Ok!</button>
JavaScript:
"use strict";
window.controllerBKE = new ControllerBKE();
function ControllerBKE () { }
ControllerBKE.prototype.reageerOpKlik = function () {
alert('hoi');
}
I've simplified some of your code and refactored it to support the prototype object that JavaScript provides us with.
The first line is adding the controllerBKE variable to the window object. This gives it a global scope across the page, allowing your onclick function to have access to it.
The next line is a simple function wrapper. This will create an instance of ControllerBKE of type object.
The function you're trying to call is now attached to the prototype of ControllerBKE. This means that any instances of ControllerBKE created with the new keyword will have access to this function.
Check out the full functionality in the fiddle below:
FIDDLE
References:
Object.prototype
Object Oriented JavaScript
I found the following definition
$.fn.flex = function ( options ) {
var p = this.data("flex"),
opts = options || {};
if (p) return p;
this.each(function () {
p = new Flex( this, opts );
$(this).data("flex", p);
});
return opts.api ? p : this;
};
which defines function flex() in original code.
Unfortunately, it stops defining this function in my environment, i.e. function call causes an error that flex is not a function.
What is critical here for flex being a function?
UPDATE
Sorry, actually I didn't modify anything. I just put this javascript https://github.com/jasonenglish/jquery-flex/ into my environment (Liferay) and the code to run script
<script type="text/javascript">
$(function() {
$(".flex").flex();
});
</script>
caused an error. So I replaced $ to jQuery everywhere as I did before and it is still not working.
UPDATE 2
Hmmm. Error occurs in widget.js from Twitter. Says
TypeError: jQuery(...).flex is not a function
If I rename flex to flex1 everywhere, it says "flex1" is not a function.
Sorry, actually I didn't modify anything. I just put this javascript ... into my environment (Liferay) and the code to run script
Because that's a jQuery plug-in, you need to make sure you include that script after jQuery on the page. So
<script src="/path/to/jquery.js"></script>
<script src="/path/to/the-plugin.js"></script>
If you put them in the other order, the first script will fail because it will try to take the value of the jQuery symbol, which doesn't exist yet, throwing a ReferenceError (in both loose and strict mode).
First of all in $.fn.flex $ and fn are jQuery variables. they are not native to JavaScript. $.fn provided by jQuery to attach method/property to jquery object
For some reason, the player_controller instance variable created on the asterisked line cannot be called in the update function below. When I run this code, the second asterisked line (the console.log) will recognize and print the specified variable from player_controller to the console. However, when I try to use player_controller in the update function below (the double asterisked line), I get the error: "TypeError: this.player_controller is undefined."
Also note that if the bold line is commented out, the other lines (which have similarly created variables) run without errors.
Can anyone tell me what's going on here?
function Engine(){
var GRAVITY = 0.3;
this.map_loader = new MapLoader();
*this.player_controller = new PlayerController();*
this.map = this.map_loader.load_next_map();
*console.log(this.player_controller.keys_down.A);*
this.update = function(){
**this.player_controller.handle_input(this.map.player);**
gravity(this.map.player);
this.map.player.x += this.map.player.dx;
this.map.player.y += this.map.player.dy;
...
...
edit: Didn't realize I couldn't do formatting in code blocks.
Here is a link to the app, if you view the web console while on this page you'll see the error I'm talking about piling up. http://lukescode.net/senior_project_game/main.html
Possibly you create engine as
var engine = Engine();
instead of
var engine = new Engine();
The problem ended up being that I was making the call to Engine.update with setInterval(engine.update, 1000/60) which, as bfavaretto mentioned in a comment, changes 'this' to be something other than the engine in the update function. The solution was to call the function like this:
setInterval(function(){return engine.update();}, 1000/60)
which causes 'this' to properly refer to the object the update function belongs to instead of the window. Thanks to bfavaretto for pointing me in the right direction.
I have a pretty specific question. I am trying to implement an onclick and cross domain tracking within a block of text, but it looks like it may need to be put directly into a .js document. I don't have a lot of JS experience. Basically, the current code looks like:
// JavaScript Document
function popup_no_status(loc)
{
var windowW=1000
var windowH=700
s = "width="+windowW+",height="+windowH+",status=yes, resizable=yes, scrollbars=yes";
mywin = window.open(loc ,'CBE', s);
mywin.focus();
}
What I want to add to this is:
onclick="pageTracker._trackEvent('Button', 'Click', 'QuickSearchWidget'); pageTracker._link(this.href); return false;
Can I just add it to the end of the document before the closing bracket? Any Ideas?
Much appreciated!
As long as the object pageTracker is defined and instantiated, you can call its methods like any other function:
function popup_no_status(loc) {
var s = "width=700,height=1000,status=yes, resizable=yes, scrollbars=yes";
var mywin = window.open(loc ,'CBE', s);
mywin.focus();
pageTracker._trackEvent('Button', 'Click', 'QuickSearchWidget');
pageTracker._link(this.href);
}
Also, the variables windowW and windowH are pointless in your example code - there is no need to store the string values in a variable if all you're going to do is concatenate them into another string. Further, unless you intend the mywin and s variables to be global, you should use the var keyword before defining them - that restricts the variables to the function scope instead of the global scope (all variables declared in a function without the var keyword are considered global).
If the code above gives an error like ReferenceError: pageTracker is not defined, that means that the code in which the pageTracker object is defined is either not included on the page, or it has not been instantiated.
Now... as for onClick, I am not clear what you're after here. Do you want this function to run when someone clicks the document? That would get pretty annoying!