calculator in angular js using directives - javascript

I'm new to Angular js and trying to build a calculator. My requirement is that I need two separate directives each for textbox (to display) and for buttons.
The problem is that I'm getting the result, but the text box is not getting updated.
Below is the code that I have written.
Script File :
var app = angular.module("app",[]);
app.service('sharedProperties', function () {
var showInput = '0';
return {
getProperty: function () {
return showInput;
},
setProperty: function(value) {
showInput = value;
}
};
});
app.controller('myCtrl', function($scope,sharedProperties) {
$scope.count = ['0','1','2','3','4','5','6','7','8','9','+','-','*','/','=','C']; $scope.showInput2 = sharedProperties.getProperty();
}); app.directive("textdir",function() { return { restrict : 'E', template : "<input type ='text' value='{{showInput2}}' id='txt'><br/>" }; });
app.directive('counter',
function() {
return {
restrict: 'EAC',
template: '<div>'+
'<button ng-repeat="i in internalCount" ng-click="kick(i)">{{i}}</button>'+
'</div>',
scope: {
internalCount: '=model'
}, controller : function($scope,sharedProperties) {
$scope.op1="";
$scope.op2="";
$scope.tempStr="";
$scope.isContinue = true;
$scope.showInput1 = sharedProperties.getProperty();
$scope.kick = function(clickvalue)
{
switch(clickvalue)
{
case "=":
if ($scope.tempStr != "" && $scope.op1!= "")
{
if($scope.op2=="")
{
$scope.showInput1 = $scope.clac($scope.tempStr, $scope.showInput1, $scope.op1);
}
if(($scope.op1=="*"||$scope.op1=="/") && $scope.op2=="-")
{
$scope.showInput1 = -$scope.showInput1;
$scope.showInput1 = $scope.clac($scope.tempStr, $scope.showInput1, $scope.op1);
}
if($scope.op1=="-" && ($scope.op2=="*"||$scope.op2=="/"))
{
$scope.tempStr = -$scope.tempStr;
$scope.showInput1 = $scope.clac($scope.tempStr, $scope.showInput1, $scope.op2);
}
alert($scope.showInput1);
$scope.op1="";
$scope.op2="";
}
break;
case "+":
case "-":
case "*":
case "/":
if($scope.op1=="")
{
$scope.tempStr = $scope.showInput1;
$scope.isClear=true;
$scope.op1=clickvalue;
}
else
{
$scope.tempStr = $scope.showInput1;
$scope.isClear=true;
$scope.op2=clickvalue;
}
break;
case "C":
$scope.showInput1 = "0";
$scope.isClear = false;
$scope.tempStr = "";
$scope.clacType = "";
break;
default :
$scope.showInput1 = $scope.showInput1 == "0" ? "" : $scope.showInput1;
$scope.isContinue = false;
if ($scope.isClear)
{
$scope.showInput1 = "";
$scope.showInput1 += clickvalue;
$scope.isClear = false;
}
else
{
$scope.showInput1 += clickvalue;
}
//alert($scope.showInput);
break;
}
}
$scope.clac = function(num1,num2,type) {
switch (type)
{
case "+":
return parseFloat(num1) + parseFloat(num2);
case "-":
return parseFloat(num1) - parseFloat(num2);
case "*":
return parseFloat(num1) * parseFloat(num2);
case "/":
return parseFloat(num1) / parseFloat(num2);
default:
return "lkl";
break;
} } }
};
});
HTML File :
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<script src = "AngularCalci.js"></script>
</head>
<body>
<div ng-app="app">
<div ng-controller="myCtrl">
<div>
<textdir/>
</div>
<counter model="count"></counter>
</div>
</div>
</body>
</html>

Every time you see 0 and it is not changing at all. The reason is it has been initialized to 0 and its value was never set to other value after that.
You need to call the set function. You have missed to add this code.
sharedProperties.setProperty(value);
UPDATE:
I have observed one more problem with the way you are setting the value back to the textbox.
If you see this line in the controller, it executes only at the beginning. But your data may change anytime during the execution. So also need take care of this scenario.
$scope.showInput2 = sharedProperties.getProperty();
You may need to dig more about events($broadcast, $emit, $on) and watchers($watch) to solve this issue.

Related

Photoshop ScriptUI Slider Indicator

The script writes the slider indicator position value to the xml file. But it fails to read and set the xml value.
The alert box in the save/read xml functions lists the xml variables. I am expecting the slider indicator to match the numerical vlaue in the xml variable.
I have a feeling the issue is with the switch statements in the read/write xml functions. Are these lines correct?
Read function:
case 'slider': myXML[a] = o[a].value; break;
Write function:
case 'slider': o[a].value = myXML[a] != '' ? (myXML[a] == 'true' ? 1 : 0) : o[a].value; break;
Reference screenshots. The slider indicator is at 0 instead of 63.
var w = new Window("dialog","test",undefined,{closeButton: true});
var group1 = w.add("group");
mySlider = group1.add("slider");
mySlider.minvalue = 0;
mySlider.maxvalue = 100;
//mySlider.value = 0;
mySlider.preferredSize.length = 195;
mySlider.preferredSize.height = 15;
mySliderEtxt = group1.add("edittext",undefined,"0");
mySliderEtxt.preferredSize=[50,20];
mySlider.onChanging = function(){
mySliderEtxt.text = mySlider.value;
}
mySliderEtxt.onChanging = function(){
mySlider.value = mySliderEtxt.text;
}
ok = group1.add("button", undefined, "Set", { name: "set" })
cancel = group1.add("button", undefined, "Close", { name: "close" })
settingsSlider1 = { sliderOne: mySlider, textItemOne: mySliderEtxt}
ok.onClick = function () {
w.close()
saveToXML(settingsSlider1, 'Simple Sider')
}
cancel.onClick = function () {
w.close()
}
w.onShow = function () {
readFromXML(settingsSlider1, 'Simple Sider')
}
w.show();
function saveToXML(o, xmlName) {
var f = new File(Folder.desktop + '/' + xmlName + '.xml'),
myXML = new XML('<variables></variables>');
for (var a in o) {
switch (o[a].type) {
case 'edittext': myXML[a] = o[a].text; break;
case 'checkbox': myXML[a] = o[a].value; break;
case 'radiobutton': myXML[a] = o[a].value; break;
case 'dropdownlist': myXML[a] = o[a].selection ? o[a].selection.text : ''; break;
case 'slider': myXML[a] = o[a].value; break;
}
}
alert('Save XML \n'+myXML);
f.encoding = "UTF8"
f.open('w');
f.write(myXML.toXMLString())
f.close();
}
function readFromXML(o, xmlName) {
var f = new File(Folder.desktop + '/' + xmlName + '.xml');
f.encoding = "UTF8";
f.open('r');
var myXML = new XML(f.read());
f.close();
for (var a in o) {
switch (o[a].type) {
case 'edittext': o[a].text = myXML[a] != '' ? myXML[a] : o[a].text; break;
case 'checkbox': o[a].value = myXML[a] != '' ? (myXML[a] == 'true' ? 1 : 0) : o[a].value; break;
case 'radiobutton': o[a].value = myXML[a] != '' ? (myXML[a] == 'true' ? 1 : 0) : o[a].value; break;
case 'dropdownlist': o[a].selection = myXML[a] != '' ? o[a].find(myXML[a]) : 0; break;
case 'slider': o[a].value = myXML[a] != '' ? (myXML[a] == 'true' ? 1 : 0) : o[a].value; break;
}
}
alert('Read XML \n'+myXML);
f.encoding = "UTF8"
f.open('w');
f.write(myXML.toXMLString())
f.close();
}
You have to add one line:
w.onShow = function () {
readFromXML(settingsSlider1, 'Simple Sider');
mySlider.value = mySliderEtxt.text; // <-------------- HERE
}

JavaScript mocked function returning undefined in tests

I'm trying to test some JavaScript functions that are part of a larger React app. They make heavy use of the module pattern, which I suspect may be what I'm not understanding correctly. Here is the script I'm testing (nearly identical to the one actually used in the real app except that GetFeedData.getFeedData in the real one makes a call to an external API):
const GetFeedData = (function () {
let feed, feedId;
return {
getFeedId: function (sub) {
switch (sub) {
case '1': case '2': case '3': case '4': case '5': case '6': case 'S':
feedId = 1;
break;
case 'A': case 'C': case 'E':
feedId = 26;
break;
case 'N': case 'Q': case 'R': case 'W':
feedId = 16;
break;
case 'B': case 'D': case 'F': case 'M':
feedId = 21;
break;
case 'L':
feedId = 2;
break;
case 'G':
feedId = 31;
break;
}
},
getFeedData: function () {
if (feedId === 2) {
feed = require('./MockData');
}
},
feed: feed
};
})();
const ReverseStop = (function () {
let stopIdN, stopIdS;
const stopData = require('../utils/stops');
return {
reverseStop: function (sub, stop) {
var invalidEntries = 0;
function filterByName (item) {
if (item.stop_name == stop && typeof item.stop_id === 'string' && item.stop_id.charAt(0) == sub) {
return true;
}
invalidEntries ++;
return false;
}
var stopObjs = stopData.filter(filterByName);
for (var i = 0; i < stopObjs.length; i++) {
if (stopObjs[i].stop_id.charAt(stopObjs[i].stop_id.length - 1) == 'N') {
stopIdN = stopObjs[i].stop_id;
} else if (stopObjs[i].stop_id.charAt(stopObjs[i].stop_id.length - 1) == 'S') {
stopIdS = stopObjs[i].stop_id;
}
}
},
stopIdN: stopIdN,
stopIdS: stopIdS
};
})();
export const IsDelayN = (function () {
let noDelay, yesDelay, nextArrival, delay;
return {
isDelay: function (sub, stop) {
GetFeedData.getFeedId(sub);
GetFeedData.getFeedData();
ReverseStop.reverseStop(sub, stop);
var arrivals = [];
var delays = [];
function dataFilter () {
var invalidEntries = 0;
var feedObjs = GetFeedData.feed.filter(function (feedObj) {
if (feedObj.entity.trip_update.stop_time_update.stop_id == ReverseStop.stopIdN) {
return feedObj.entity.trip_update.stop_time_update;
}
});
for (var i = 0; i < feedObjs.length; i++) {
arrivals.push(feedObjs.arrival.time.low);
delays.push(feedObjs.arrival.delay);
}
}
nextArrival = Math.min(...arrivals);
var delayIndex = arrivals.indexOf(nextArrival);
delay = delays.delayIndex;
if (delay === null || Math.ceil(delay / 60) <= 5) {
noDelay = Math.ceil((nextArrival - GetFeedData.feed.header.timestamp.low) / 60);
} else {
yesDelay = Math.ceil(delay / 60);
}
},
noDelay: noDelay,
yesDelay: yesDelay,
nextArrival: nextArrival
};
})();
export const IsDelayS = (function () {
let noDelay, yesDelay, nextArrival, delay;
return {
isDelay: function (sub, stop) {
GetFeedData.getFeedId(sub);
GetFeedData.getFeedData();
ReverseStop.reverseStop(sub, stop);
var arrivals = [];
var delays = [];
function dataFilter () {
var invalidEntries = 0;
var feedObjs = GetFeedData.feed.filter(function (feedObj) {
if (feedObj.entity.trip_update.stop_time_update.stop_id == ReverseStop.stopIdS) {
return feedObj.entity.trip_update.stop_time_update;
}
});
for (var i = 0; i < feedObjs; i++) {
arrivals.push(feedObjs.arrival.time.low);
delays.push(feedObjs.arrival.delay);
}
}
nextArrival = Math.min(...arrivals);
var delayIndex = arrivals.indexOf(nextArrival);
delay = delays.delayIndex;
if (delay === null || Math.ceil(delay / 60) <= 5) {
noDelay = Math.ceil((nextArrival - GetFeedData.feed.header.timestamp.low) / 60);
} else {
yesDelay = Math.ceil(delay / 60);
}
},
noDelay: noDelay,
yesDelay: yesDelay,
nextArrival: nextArrival
};
})();
What I'm attempting to do is separate out my functions so I have several shorter ones I can call in the exported functions, rather than one or two extremely long functions. Because I need to call a couple variables - GetFeedData.feed, ReverseStop.stopIdN, and ReverseStop.stopIdS in the exported functions, I am assuming that the module pattern is a better way to go than using callbacks. I could totally be wrong.
In my tests, I try log noDelay, nextArrival, and delay to the console to see if they are defined. I'm using Jest, if that information is helpful. I'll omit the other parts of my test for now because they don't seem relevant (please correct me if that's wrong), but here is that section:
it('correctly takes input at beginning of api logic and outputs expected values at end', () => {
IsDelayN.isDelay('L', 'Lorimer St');
IsDelayS.isDelay('L', 'Lorimer St');
expect(IsDelayN.noDelay).toBeTruthy();
expect(IsDelayN.yesDelay).toBeFalsy();
expect(IsDelayS.noDelay).toBeTruthy();
expect(IsDelayS.yesDelay).toBeFalsy();
console.log('IsDelayN noDelay: ' + IsDelayN.noDelay);
console.log('IsDelayN nextArrival: ' + IsDelayN.nextArrival);
console.log('IsDelayN delay: ' + IsDelayN.delay);
console.log('IsDelayS noDelay: ' + IsDelayS.noDelay);
console.log('IsDelayS nextArrival: ' + IsDelayS.nextArrival);
console.log('IsDelayS delay: ' + IsDelayS.delay);
});
The tests prior to my console.log()s are all passing, but every console.log() is turning up undefined. Also, the script that's actually being called by my React components is coming up with the same results. I have my component set to render null if these variables aren't defined, and that's exactly what's happening.
Any help with understanding this is greatly appreciated.
You do not set the modules correctly, when setting a member value you should mutate the object, now you just set a variable value.
The following should work for you:
var module = (function(){
const ret = {
mutateSomething:function(value){
//set otherValue on the object returned (mutate ret)
ret.otherValue = value;
}
,otherValue:undefined
};//create the object first
return ret;//then return the object
}())//IIFE
console.log("before mutate:",module.otherValue);
module.mutateSomething("Hello World");
console.log("after mutate:",module.otherValue);

How do I run function inside a class. Javascript

I am having hard time calling a function inside a class. When I started working on this, I had it running, but after making revisions, I cant get it working :((
You can ignore my alerts because I just put them in there to check to see if the function gets called or not.
I have function "Unit" which is a class for me. then I call it by below.
From below code, that new Unit(args) does not get completed. It stops at this.direction=this.setDirection();
and this.setDirection() is not called for some reason. Can anyone take a look and tell me what went wrong?
Thanks!
var teamBlack = [];
var bking = new Unit("black", "king", new Coords(3,1, false));
teamBlack.push(bking);
function Unit(team, type, coords) {
alert("Unit started " + count);
this.team = team;
this.type = type;
this.position = coords;
this.highlight = false;
alert("before setdirection");
this.direction = this.setDirection();
alert("this " + this.type);
this.setDirection = function () {
alert("setDirection Started ");
alert(this.type);
var tempDir = [];
switch (this.type) {
case "king" :
alert("this is king");
tempDir = [this.N(), this.NW(), this.W(), this.SW(), this.S(), this.SE(), this.E(), this.NE()];
break;
case "bishop" :
tempDir = [this.NW(), this.SW(), this.SE(), this.NE()];
break;
case "rook" :
tempDir = [this.N(), this.S(), this.W(), this.E()];
break;
case "pawn" :
{
if (this.team == "white") {
tempDir = [this.S()];
} else {
tempDir = [this.N()];
}
break;
}
case "queen" :
{
if (this.team == "white") {
tempDir = [this.N(), this.W(), this.SW(), this.S(), this.SE(), this.E()];
} else {
tempDir = [this.N(), this.NW(), this.W(), this.S(), this.E(), this.NE()];
}
break;
}
}
tempDir = tempDir.filter(function (dir) {
return dir.x > -1 && dir.x < 3 && dir.y > -1 && dir.y < 4 && dir.c == false;
});
return tempDir;
}
}
This code is wrong because you try call function that is not exist yet in your class. I recommend you to move this function in prototype. For example:
function Unit() {
//this is your constructor
}
Unit.prototype.setDirection = function() {
//your code of setDirection function
}
Make sure variables are defined, then put this.setDirecton = function()... before calling this.setDirection().
See JSFiddle.
You need to use the setDirection function as a prototype of your Unit class.
Unit.prototype.setDirection = function() {
//setDirection functionality
}
Within the prototype you have access to your class properties via this.
Check this jsFiddle: https://jsfiddle.net/urtr3quc/
I would improve your code by separating the responsibilities:
//create the class Unit
function Unit(team, type, coords) {
alert("Unit started " + count);
this.team = team;
this.type = type;
this.position = coords;
this.highlight = false;
}
Then you specify new method for your class:
Unit.prototype.setDirection = function () {
alert("setDirection Started ");
alert(this.type);
var tempDir = [];
switch (this.type) {
case "king" :
alert("this is king");
tempDir = [this.N(), this.NW(), this.W(), this.SW(), this.S(), this.SE(), this.E(), this.NE()];
break;
case "bishop" :
tempDir = [this.NW(), this.SW(), this.SE(), this.NE()];
break;
case "rook" :
tempDir = [this.N(), this.S(), this.W(), this.E()];
break;
case "pawn" :
{
if (this.team == "white") {
tempDir = [this.S()];
} else {
tempDir = [this.N()];
}
break;
}
case "queen" :
{
if (this.team == "white") {
tempDir = [this.N(), this.W(), this.SW(), this.S(), this.SE(), this.E()];
} else {
tempDir = [this.N(), this.NW(), this.W(), this.S(), this.E(), this.NE()];
}
break;
}
}
tempDir = tempDir.filter(function (dir) {
return dir.x > -1 && dir.x < 3 && dir.y > -1 && dir.y < 4 && dir.c == false;
});
alert("before setdirection");
this.direction = tempDir;//setMethod doesn't return thing but set something somewhere
alert("this " + this.type);
};
and now you invoke your class instance:
var teamBlack = [];
var bking = new Unit("black", "king", new Coords(3,1, false));
bking.setDirection();
teamBlack.push(bking);
I suggest you to take a look on this link

Find object that corresponds - getting a comment system to work?

This is how everything should work when the iFrameOn function runs:
Turn the designMode of all iFrames on
Find the three "buttons" ('a' link elements) - that when clicked affect its corresponding iFrame - depending on its className
Put those "buttons" into a multidimensional array/object i.e target.rtfID.x
Whenever a "button" is clicked, find its corresponding iFrame through the object and send the iFrame's id as an argument for another function.
Currently, however, whenever any of the buttons are clicked they all affect the same iFrame. I realize this is likely due to my usage of the loops, but I can't figure out how to make it all work. There are no errors in the console.
function iFrameOn() {
var rtfContainer, rtContainer, richTxt, richTxtId,
rtf = document.querySelectorAll('div > form > iframe'), //Rich Text Field
newPost = document.getElementById('richTextField').contentDocument.body,
target = {}, rtfIndex = 0;
//Turn iFrames On
while (rtfIndex < rtf.length) {
rtfID = rtf[rtfIndex].id;
if (rtf[rtfIndex].contentDocument.designMode != 'On') {
rtf[rtfIndex].contentDocument.designMode = 'On';
}
newPost.innerHTML = "<i style=\"color:#DDDDDD;\">What's up?</i>";
newPost.addEventListener('blur', function() {
if (newPost.innerHTML == '') {
newPost.innerHTML = "<i style=\"color:#DDDDDD;\">What's up?</i>";
}
}, false);
document.getElementById('richTextField').contentWindow.addEventListener(
'focus',
function() {
if (newPost.innerHTML == "<i style=\"color:#DDDDDD;\">What's up?</i>") {
newPost.innerHTML = '';
}
},
false
);
rtContainer = rtf[rtfIndex].nextElementSibling; //Next Element Sibling should be a div
console.log('rtContainer is: '+rtContainer);
richTxt = rtContainer.childNodes;
console.log('richTxt is: '+richTxt);
for (var i = 0; i < richTxt.length; i++) {
if (richTxt[i].nodeType != 1 ||
(richTxt[i].nodeType == 1 &&
(richTxt[i].className == 'submit_button sbmtPost'
|| richTxt[i].className == "")
)
) {
continue;
}
richTxtId = richTxt[i].id;
target.rtfID = {};
switch (richTxt[i].className) {
case 'richText bold':
if (target.rtfID.bold != richTxtId) {
target.rtfID.bold = richTxtId;
console.log(target.rtfID.bold+' is associated with: '+rtfID);
}
break;
case 'richText underline':
if (target.rtfID.underline != richTxtId) {
target.rtfID.underline = richTxtId;
console.log(target.rtfID.underline+' is associated with: '+rtfID);
}
break;
case 'richText italic':
if (target.rtfID.italic != richTxtId) {
target.rtfID.italic = richTxtId;
console.log(target.rtfID.italic+' is associated with: '+rtfID);
}
break;
default:
console.log('Error with commenting system!');
break;
}
}
var obj = target.rtfID;
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log("prop: " + prop + " value: " + obj[prop]);
switch(prop) {
case 'bold':
document.getElementById(obj[prop]).addEventListener(
'click',
function() {
bold(obj[prop]);
},
false
);
break;
case 'underline':
document.getElementById(obj[prop]).addEventListener(
'click',
function() {
Underline(obj[prop]);
},
false
);
break;
case 'italic':
document.getElementById(obj[prop]).addEventListener(
'click',
function() {
Italic(obj[prop]);
},
false
);
break;
default:
console.log('Error in for...in loop');
}
} else {console.log('error');}
}
rtfIndex++;
}
}
You can do things like this:
function createBolder (val) {
return function () {
bold(val);
};
}
document.getElementById(obj[prop]).addEventListener(
'click',
createBolder(obj[prop]),
false
);
or if you really want to keep things inline:
document.getElementById(obj[prop]).addEventListener(
'click',
(function (val) {
return function () {
bold(val);
};
}(obj[prop])), // This function call executes immediately (i.e., while still
// going through the loop, so the current value of obj[prop]
// will be stored inside this function with its own local copy
// rather than using the value of obj and prop by the time
// the function is executed (probably the completion of the loop))
false
);

JavaScript & jQuery Function Error

I am making a generic text validation function with jQuery. I made the function text and I pass the id,requirement,expression,offset,limit into the function. The way I have made it is to help me run the function easily on single input change and on the submit of the whole form. I have made the function but I can't get it to run.
var Val = {
'text' : function(event, ident,req,regexp,offset,limit) {
var ele = $(document.getElementById(ident));
if(req == 1 && ele.val().length < 1) {
Val.errors = true;
$("#"+ident+"Error").html("Please enter your " + ele.attr("title"));
$("#"+ident+"Error").show("fast");
} else if(ele.val().length <= offset || ele.val().length > limit) {
Val.errors = true;
$("#"+ident+"Error").html(ele.attr("title") + " should be between " +offset+ " & " +limit+ " charecters long");
$("#"+ident+"Error").show("fast");
} else if(regexp != null) {
switch (regexp) {
case 'text':
var regEx = /^([a-zA-Z]+)$/; break;
case 'number':
var regEx = /^([0-9]+)$/; break;
case 'email':
var regEx = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/; break;
case 'date':
var regEx = /^([123]0|[012][1-9]|31)-(0[1-9]|1[012])-(19[0-9]{2}|2[0-9]{3})$/; break;
case 'alphanum':
var regEx = /^([a-zA-Z0-9._-]+)$/; break;
default:
var regEx = /^([a-zA-Z0-9._-]+)$/; break;
}
if(!regEx.test(ele.val())) {
Val.errors = true;
$("#"+ident+"Error").html(ele.attr("title") + " is not valid");
$("#"+ident+"Error").show("fast");
}
}
},
'send' : function (){
if(!Val.errors) {
$('#form').submit();
}
}
}
The calling code of the function:
$(document).ready(function(){
$('#send').click(function(){
Val.text('test', 1, 'email', 10, 50);
Val.send();
});
$('#test').bind('change', Val.text);
$('#test').trigger('change', ['test', 1, 'email', 10, 50]);
});
I know I haven't yet used the expressions but I will once I see it working.
Appreciate all the help...
Thanks!
I made it work. Once the script worked properly no trigger was required. I was able to just call simply inside the change event.
$('#emailID').change(function(){
Val.text('emailID', 1, 'email', 10, 100);
});
Thanks everyone for the help anyway.

Categories

Resources