Javascript OOP, a simple calculator that will not function - javascript

I'm building a simple calculator to incorporate it in a simple web based POS system. I do not have much experience with JS but i have programmed in C, C++ & Java extensively.
In the firefox debugger I get an exception TypeError: "this.getValue is not a function." when it is called in the method updateDisplay().
It this kind of structure not supported in JS? Calling object methods in a method of an object?
http://jsfiddle.net/uPaLS/33/
function KeyPad(divReference) {
this.divDisplay = divReference;
this.value = "0";
this.comma = false;
}
KeyPad.prototype.getValue = function () {
return parseFloat(this.value);
};
KeyPad.prototype.updateDisplay = function () {
$(document).ready(function () {
$(this.divDisplay).text(this.getValue());
});
};
KeyPad.prototype.keyPressed = function (valueString) {
if (valueString == '.' && this.comma === true) {
return;
}
this.value = this.value + valueString;
if (valueString == '.') {
this.comma = true;
}
this.updateDisplay();
};
KeyPad.prototype.reset = function () {
this.value = "0";
this.comma = false;
this.updateDisplay();
};
var keyPad = new KeyPad("#keypad_display");

In your function updateDisplay , this doesn't refer to your KeyPad object: it refers to $(document), because you're not in the same scope of how the function is called.
KeyPad.prototype.updateDisplay = function () {
//'this' is Keypad
$(document).ready(function () {
//'this' is $(document)
$(this.divDisplay).text(this.getValue());
});
};
I don't think (maybe i'm wrong) that using $(document).ready here, inside a function, is a good practice. This should simply fixed your error:
KeyPad.prototype.updateDisplay = function () {
$(this.divDisplay).text(this.getValue());
};
As sroes says in the comment, you should use the $(document).ready like this:
$(document).ready(function () {
var keyPad = new KeyPad("#keypad_display");
});

Related

JavaScript uncaught type error illegal invocation

var Rules = Rules || (function () {
saverule = function () {
var level = document.getElementById("level-selection");
var metrics = document.getElementById("metric-selection");
var operator = document.getElementById("operator-selection");
var value = document.getElementById("value123");
var saveAction = $("#hidden-save").val();
$.post(saveAction, { level_id: level, product_id: metrics, opp: operator, value: value }, function () {
},
'json');
};
wireLinkActions = function () {
$("a.save-ok").on("click", function(event) {
saverule();
return false;
});
};
return {
Initialize: function () {
wireLinkActions();
}
}
})();
$(document).ready(Rules.Initialize);
illegal invocation error it wont even cal the the save rule function while debugging also
Make sure your return the values and not the DOM element itself.
For example change this:
var level = document.getElementById("level-selection");
into this:
var level = document.getElementById("level-selection").value;
or, simply use jQuery such as this:
var level = $("#level-selection").val();

Error when Calling Jquery Function from Javascript

I am getting the error at the line :
validate();
When I trying to call the following jQuery function
(function ($) {
"use strict";
var methods = {
validate: function () {
if ($(this).is("form"))
return methods._validateFields(this);
else {
// field validation
var form = $(this).closest('form');
var options = form.data('jqv');
var r = methods._validateField($(this), options);
if (options.onSuccess && options.InvalidFields.length == 0)
options.onSuccess();
else if (options.onFailure && options.InvalidFields.length > 0)
options.onFailure();
return r;
}
}
}
Using the following JavaScript, I am getting the error at validation function.
<script type="text/javascript">
function dateSelectionChanged(sender, args) {
$(function () {
validate();
});
}
</script>
The function validate has been described in the above jQuery.
Try this:
var methods = {
validate: function () {
if ($(this).is("form"))
return methods._validateFields(this);
else {
// field validation
var form = $(this).closest('form');
var options = form.data('jqv');
var r = methods._validateField($(this), options);
if (options.onSuccess && options.InvalidFields.length == 0)
options.onSuccess();
else if (options.onFailure && options.InvalidFields.length > 0)
options.onFailure();
return r;
}
}
<script type="text/javascript">
function dateSelectionChanged(sender, args) {
methods.validate();
}
</script>
You need to expose methods to other functions - put it in the global scope.
So either use the global window object and do:
window.methods =
For example:
(function ($) {
"use strict";
window.methods = {
validate: function () {...
Or define it first outside of (function($){...})
For example:
var methods = {};
(function ($) {
"use strict";
methods = {
validate: function () {...
Notice no var before second methods.
Then you can call methods.validate()
Also: ensure you close (function ($) { with })(jQuery) - it's missing from the code that you posted.
I have fixed it !!
I have called jQuery("#aspnetForm").valid();
I Have created a function called valid()
Like this :
$.fn.valid = function (method) {
methods._validateFields(this);
};
Now its fine .... !

Javascript object accessing it's properties

I am trying to create an object in javascript that has an animation run which calls another method when it finishes.
function panel_manager() {
this.animating = false;
this.doAnimate = function (nPanel) {
//if we're still moving panels, do nothing
if(this.animating) return;
this.animating = true;
//enlarge new panel
$("#panel" + this.focusedPanel).animate({width:"115px"},1000, this.endAnim);
}
this.endAnim = function () { alert("called"); this.animating = false; }
}
A whole lot has been cut for brevity and this code does work when it isn't inside an object and uses global variables. The alert runs, but animating isn't changing.
variables.
function panel_manager() {
var that = this;
this.animating = false;
this.doAnimate = function (nPanel) {
if(this.animating) return;
this.animating = true;
$("#panel" + this.focusedPanel).animate({width:"115px"},1000, that.endAnim);
}
this.endAnim = function () { alert("called"); that.animating = false; }
}
Inside of this.doAnimate add a $.proxy.
var callback = $.proxy( this.endAnim, this );
$("#panel" + this.focusedPanel).animate({width:"115px"},1000, callback);
Basically the problem is you lose your this value when you assign it to a callback like this. proxy will make sure the function is called with the proper this.
Cheers!

I have no idea how to test this with Qunit?

I want to test this function:
/js/lib/front.js
var Front = function(){
this.onSignUp = function(){
if (!Form.assertInput("email")) {
$("input[name=email]").focus();
this.showHiddenMessage("Email not set.");
return false;
}
}
}
I have in:
/js/lib/form.js
function Form() {
this.assertInput = function (name, defaultValue) {
var text = $("input[name=" + name + "]").val();
if (defaultValue != null) {
if (defaultValue && text == defaultValue)
return false;
}
if(this.trim(text)) return true;
return false;
}
}
This simple test passing:
test("Front", function() {
var front = new Front()
ok(front);
});
But if I write something like this:
test("On Sign Up ", function() {
var front = new Front()
equal(front.onSignUp(),false,"passing test");
});
I have error:
Died on test #1: Form.assertInput is not a function
I don't understand, what I need test in function like this and how include function inside another function?
I've saved a working fiddle here. As a side note, you might want to check out a tutorial on using qUnit, here.One thing that you need to pay attention to is when you're declaring your functions. It's saying Form.assertInput is not a function because you can't access it like that. You need to use the this keyword, which refers to current context. The code should be something like this:
var Form = function () {
//good to have assertInput first if you're using it in a later function
this.assertInput = function (name, defaultValue) {
var text = $("input[name=" + name + "]").val();
if (defaultValue != null) {
//safer to explicitly close your if statements with {}
if (defaultValue && text == defaultValue) {
return false;
}
}
if ($.trim(text)) { return true; }
return false;
};
this.showHiddenMessage = function (message) {
alert(message);
};
this.onSignUp = function() {
//this will point to the current context, in this case it will be Form class
if (!this.assertInput("email")) {
$("input[name=email]").focus();
this.showHiddenMessage("Email not set.");
return false;
}
};
};
Also in the example code that you gave you're missing the Front class. So I created a dummy one in my fiddle like this:
var Front = function() {};
Here are the tests that were run:
$(document).ready(function() {
test("Front", function() {
var front = new Front();
ok(front);
});
test("On Sign Up ", function() {
var form = new Form();
equal(form.onSignUp(), false, "passing test");
});
});

Can I put a jquery handler in a constructor?

I'm seeing if I can make some object oriented javascript and I have the following code.
When I went to move my jquery event handler into the constructor I became confused because now I have two this variables...
Am I approaching this incorrectly or is there a way to make it work?
function Dropdown(ddlname) {
this.Value = 0;
this.Selected = false;
this.DDL = ddlname;
this.Limited = false;
this.SelectLast = function () {
$(this.DDL + ' option:last').attr('selected', 'selected');
}
$(ddlname).change(function () {
var v = $(this).val(); // <== ?
if (typeof v == 'number') {
this.Value = v; // <== ?
this.Selected = true; // <== ?
}
});
return true;
};
You need to assign "this" from the context of your constructor to a local variable to be able to reference it from within your jquery event handler.
function Dropdown(ddlname) {
this.Value = 0;
this.Selected = false;
this.DDL = ddlname;
this.Limited = false;
var hold = this;
this.SelectLast = function () {
$(hold.DDL + ' option:last').attr('selected', 'selected');
}
$(ddlname).change(function () {
var v = $(this).val(); // <== ?
if (typeof v == 'number') {
hold.Value = v; // <== ?
hold.Selected = true; // <== ?
}
});
return true;
};
One trick i learnt from Marcelo Ruiz of DataJS team from microsoft is as follows:
function Dropdown(ddlname)
{
var that = this;
//rest of your code. now there is no confusion of this since you have that :)
};
Not sure if this would help you. but just a trick i learned.
Yes you may, but you will need to call the class in the document ready function. I'm pretty sure it's bad practice.
You should consider passing the $ to the constructor or making a jQuery extension.

Categories