Getting another element through a method thats related to the current operation - javascript

Sorry for the bad title, simple couldn't figure out how to explain my problem.
Let's say i have 4 of these fields, and not just one. I want to increment or decrement each input field. Each input field has a "+" and "-" that does incremental and decremental tasks.
I have setup a method that register the v-on click even to a method. But how do i get what input field it was incremented on, cause 'this' would return the buttons of +/-
normally i would just use jquery with .parent().find('.input-number'); but i feel like this is dirty, and excessive for such a small thing. most be a better approach?
This is my markup
<div class="form-group">
<span class="input-number-decrement" v-on:click="decrement()">–</span>
<input class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="increment()">+</span>
</div>
and looks like this
example of the field
any help would great, since i'm stuck at this part :)

I have created one javascript function for increment and decrement value by 1.
HTML
<div class="form-group">
<span class="input-number-decrement" v-on:click="inc_dec('dec')">-</span>
<input class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="inc_dec('inc')">+</span>
</div>
Javascript
<script type="text/javascript">
function inc_dec(flag){
var pack1 = document.getElementById('pack1');
var inc_dec_by = 1;
if(flag=='inc'){
pack1.value = parseInt(pack1.value)+inc_dec_by;
}
if(flag=='dec'){
pack1.value = parseInt(pack1.value)-inc_dec_by;
}
}
</script>

I am assuming above code is a vue component.
<div class="form-group">
<span class="input-number-decrement" v-on:click="decrement()">–</span>
<inputn v-model="value" class="input-number form-control" name="pack1" id="pack1" type="text" value="0" min="0">
<span class="input-number-increment" v-on:click="increment()">+</span>
</div>
In the script define a variable to hold the value.Then manipulate values using defined methods
<script>
export default{
data: {
value
},
methods: {
decrement: function (event) {
},
increment: function (event) {
}
}
}
</script>

Related

jQuery, get text from neighbouring input within a div

I have a component on my page which looks like this:
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>
A component list can have multiple component pairs nested within it. When performing a search a query cannot be made for a serial number if a part number is not present, therefore when performing a keyup event on the .serial field I need to get the text from the part number field. I would store this in a data model, but by referencing the current serial field I should be able to traverse to the part number field.
Here is what I have tried, when my page loads I bind a keyup event on the serial field, I pass this as the selector so I have reference to the (sender) current field in getData():
$(document).on("keyup", '.serial', function() { getData(this, "SERIAL") });
Then in getData I want to be able to traverse up my DOM structure to the current componentPair group and then traverse into the left div and get the value from Part Number input field.
Here is what I tried:
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log(elem.closest('input[class^="part"]'))
serial = elem.value
}
... Other erroneous code to perform the search
}
As you can see, here I use console.log(elem.closest('input[class^="part"]')) to find the closest component with the class of part, after reading jQuery documentation I believe this should work, but I get an undefined function error. I then tried to use the parent() selector and parentsUntil() selector but each of them threw an undefined function error.
If I console log, elem I get:
<input type="text" class="serial" placeholder="SERIAL NUMBER">
Which is what I would expect, so I don't see why I can't use elem.parent().parent() to traverse to componentPair and then dive into the tree structure to pull the information out.
I am using jQuery 1.11.3, any help would be greatly appreciated.
The issue is because .part is not a parent of .serial. You need to use closest() to find a common parent, then find() to get the element you require. Try this:
var serial = $(elem).closest('.componentPair').find('.part').val();
The reason you get undefined function error is that elem is not a jQuery object, it's a HTMLElement, so wrap it in $().
Then .closest() won't work the way you think, it will only search through itself and its parents.
Try this:
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log($(elem).parent().siblings().find('input[class^="part"]'));
serial = elem.value
}
}
$(document).on("keyup", '.serial', function() {getData(this, "SERIAL") });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>
You have issue with elem.closest('input[class^="part"]'), this should be $(elem).closest('input[class^="part"]') . Because elem is the input's object itself. so you can not directly call closest()
Here is the working code :
$(document).on("keyup", '.serial', function() { getData(this, "SERIAL") });
function getData(elem, type) {
var code = ""
var serial = ""
if(type === "SERIAL") {
console.log($(elem).parent().parent().find('.part'));
serial = $(elem).parent().parent().find('.part').val();
alert(serial);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="componentList">
<div class="componentPair">
<div class="left">
<input type="text" class="part" placeholder="PART NUMBER">
</div>
<div class="right">
<input type="text" class="serial" placeholder="SERIAL NUMBER">
</div>
</div>
</div>

Wait to perform function until new data is reflected within the browser

I have Answer objects with an Id property which is also used for the Id tag within the HTML markup inside an ng-repeat.
<div ng-repeat="answer in question.Answers">
<div class="input-group">
<div class="input-group-addon">
<input type="number" style="width:40px" ng-model="answer.AnswerOrder"/>
</div>
<input type="text" class="form-control" id="answer-{{answer.Id}}"placeholder="Question Text" ng-model="answer.AnswerText"/>
</div>
</div>
<div class="input-group">
<div class="input-group-addon"><input type="number" style="width:40px" ng-model="answer.AnswerOrder" disabled/></div>
<input type="text" class="form-control" placeholder="Click to add answer" ng-click="addAnswerToQuestion(question)"/>
</div>
When the user clicks the input "Click to add answer" it runs the method addAnswerToQuestion(question) which is the following within my controller:
var newQuestionCounter = 0;
$scope.addAnswerToQuestion = function (question) {
newQuestionCounter++;
question.Answers.push({
Id: ('n'+newQuestionCounter),
AnswerText: '',
IsCorrect: false,
AnswerOrder: 0,
QuestionId: question.Id
});
document.getElementById('answer-n' + newQuestionCounter).focus();
}
The idea is to give the illusion that you are still on the same element but in reality the "Click to add answer" element is not being modified and your focus is just silently switching to the new Answer.
The issue is that the document.getElementById is getting called before the data-binding and the ng-repeat is updated. So the document.getElementById is not finding the element.
How do I wait for all the 2-way data binding to complete or is there a better way to accomplish what I am trying to do?
Personally, I would rethink the UX before I would do anything like this, but you can accomplish this with the $timeout service. A rule of thumb is that $timeout will always come after a complete $digest() cycle.
$timeout(function() {
document.getElementById('answer-n' + newQuestionCounter).focus();
}, 1);
http://plnkr.co/edit/0LnMBv6DqUjFrcmqd0v3

How to display number in input field's to currency format in bootstrap addon?

I'm working on small web form where I need to display number in the text field's as currency format in bootstrap appended addon.
I'm able to achieve for a single field using jQuery selectors (I'm new to Javascript world), I wanted to do the same thing for aroung 10 fields.
I think there must be elegant solution rather than writing the same for every field.
Kindly help me.
My HTML Code:
<div class="control-group">
<label class="control-label">Loan Amount 1</label>
<div class="controls">
<div class="input-append">
<input class="span2" id="loanAmount1" type="text">
<span class="add-on" id="loanAmount1Cur">$</span>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">Loan Amount 2</label>
<div class="controls">
<div class="input-append">
<input class="span2" name="loanAmount2" type="text">
<span class="add-on" name="LoanAmount2Cur">$</span>
</div>
</div>
</div>
My JS Code:
$(document).ready(function () {
$("#loanAmount1").on("keyup", null, function () {
var input = $("#loanAmount1").val();
var num = parseFloat(input).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') + " $";
$("#loanAmount1Cur").html(num);
});
});
My JSFiddle: http://jsfiddle.net/kiranm516/me52djL8/24/
I copied the above code from (thanks to them): Add comma to numbers every three digits
Assign a class to your inputs, and then bind the keyup event to your class, rather than to an ID.
Forked your JSFiddle: http://jsfiddle.net/zmbh4o2u/
JS:
$(document).ready(function () {
$(".loan-input").on("keyup", null, function () {
var $input = $(this),
value = $input.val(),
num = parseFloat(value).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
$input.siblings('.add-on').text('$' + num);
});
});
Helpful tips:
In the handler function for your keyup event, you can access the element that fired the event with this. Since you'll need that element a couple of times, it's customary to cache a jQuery object in a local var, hence var $input = $(this).
When declaring multiple variables in JavaScript, it's best practice to chain them in a single var statement. You can comma separate your declarations, and use line breaks for legibility.

Traversing with jQuery: cycle over children

Hi all I have an html structure like this:
<tr>
<td>
<div class="sigle-sz">
<span class="label-sz">36</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
<td>
<div class="sigle-sz">
<span class="label-sz">38</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
<td>
<div class="sigle-sz">
<span class="label-sz">40</span> <input class="" type="tel" value="" name="">
<div class="available yes">
<i aria-hidden="true" class="availablespot"></i>
</div>
</div> <!-- /sigle-sz -->
</td>
</tr>
I created a jQuery function like this:
<script>
function pippo() {
//code here
}
$( document ).ready(function() {
$( ".sigle-sz" ).on('change', function() {
pippo();
});
});
</script>
I would, into the function "pippo()", cycle the <td> elements in the <tr> tag and save the input value in a variable.
If this is the $( ".sigle-sz" ) element, how I can do this cycle?
I put here my current code: https://jsfiddle.net/ydrunbzz/
You can use $.each() jQuery function:
var values; // define global var to use everywhere
function pippo(myClass) {
$.each(("." + myClass), function (index, value) {
values += value;
});
}
Tonnes of ways to solve this with an .each() loop. I think it's important to have a very readable loop if you are new, or else you'll lose track fast.
1) global variable
2) first make sure that the data is gathered when someone writes something in the inputs!
3) the pippo function will clear the global variable "arrSigle" (short for Array Sigle), and make sure it's only filled with the current numbers written down
$(document).ready(function () {
//1
var arrSigle= [];
//2
$( ".sigle-sz" ).find("input").on("change", function(){
pippo();
//just FYI, the "change" only fires when an input has a new value, and lose focus
// by any means. If it annoys you to have to click out of the box for pippo()
//to run, you might want to use "onkeyup" instead of "change".
//it will fire every time someone lets go of a key while inside the input
})
//3
function pippo(){
arrSigle.length = 0; //this clears the variable
$( ".sigle-sz" ).find("input").each(function(){
arrSigle.push($(this).val());
//this itterates over all the inputs and pushes them into the
//global variable.
})
//If you want some function to run right after all the
//numbers has been gathered, put it right under this comment.
}
});
We can all discuss how "efficient" this is, but considering how small your page probably is, i think it's more than justifiable to make it this simple

Undefined - Trying to pass a value from a form to a JS function using jQuery and getting it very wrong

I'm trying to learn how to use JS in order to create a unit converter for a site I'm working on.
I did have intentions of trying to accomplish it using PHP but someone pointed out how inefficient it would be and so I'm now trying to learn JS to carry out the same tasks.
I've written a very small test function to add two numbers, it worked fine. I then adjusted it slightly to take in a few more params and to check a couple of conditions, again that worked fine - I created a new object and passed the variables in directly.
I now need to pass the values from the form that I have into this function in order to compute the sum and output the result. I keep getting an error of 'undefined'. I've googled and read but can't seem to find a solution.
so far I have:
<script type="text/javascript">
function Convert(from, to, units){
this.from = $("#from").val();
this.to = $("#to").val();
this.units = $("#units").val();
}
Convert.prototype.convertThem = function(){
if(this.from == "degC"){
if(this.to == "degF"){
return this.units * 347956757524;
}
}
}
calcTempTest = new Convert(this.from, this.to, this.units);
alert(calcTempTest.convertThem());
console.log(calcTempTest);
</script>
Could anyone tell me what I'm doing wrong please? The 'to','from' and 'units' are the id's from the form.
The Form:
<div class="form">
<label for="units">Units:</label>
<input type="text" name="units" id="units" class="required digits" />
</div>
<div class="form">
<label for="from">Convert From:</label>
<select name="from" id="from">
<option value="from">-Select an Option-</option>
</select>
</div>
<div class="form">
<label for="to">Convert Into:</label>
<select name="to" id="to">
<option value="to">-Select an Option-</option>
</select>
</div>
<div class="form">
<label> </label>
<input type="submit" name="submit" value="Convert!" />
</div>
many thanks.
Explanation
Your select selected option value onLoad both are "from" and "to". Since these are not equal to "degF" and "degC", your assignments won't go on, the resulting variable will be undefined since no value will be asssigned to it.
Solution
Add several option to your select or change their default value. I also added a default value to the input.
HTML
<input type="text" name="units" id="units" value="12" class="required digits" />
<option value="degC">-Select an Option-</option>
<option value="degF">-Select an Option-</option>
EDIT
I have added a JSFiddle here which executes the script on the button click with the following modifications to JavaScript:
NOTE: I also added the real formula.
JavaScript/jQuery
$('input[name="submit"]').click(function () {
var c = new Convert();
alert(c.convertThem());
});
function Convert() {
this.from = $("#from").val();
this.to = $("#to").val();
this.units = $("#units").val();
}
Convert.prototype.convertThem = function () {
if (this.from == "degC") {
if (this.to == "degF") {
return this.units * 1.8 + 32;
}
}
}
I think when you create the convert object you're trying to pass variables that don't exist:
calcTempTest = new Convert(this.from, this.to, this.units);
I'm pretty sure this stands for window at that point and windw.from is undefined. You don't seem to be doing anything with these values anyway so you could change it to:
calcTempTest = new Convert();
Maybe the following answer could help you out with what this stands for in JS: Prototypical inheritance - writing up
Here is some minimally working code:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script type="text/javascript" src="jquery-1.10.1.js"></script>
</head>
<body>
<div class="form">
<label for="units">Units:</label>
<input type="text" name="units" id="units" class="required digits" />
</div>
<div class="form">
<label for="from">Convert From:</label>
<select name="from" id="from">
<option value="degC">degC</option>
</select>
</div>
<div class="form">
<label for="to">Convert Into:</label>
<select name="to" id="to">
<option value="degF">degG</option>
</select>
</div>
<div class="form">
<label for="output">Output:</label>
<input type="text" id="output" />
</div>
<div class="form">
<label> </label>
<input type="submit" id="subm" name="submit" value="Convert!" />
</div>
<script type="text/javascript">
(function () {
function Convert(from, to, units) {
// when convert is created set a reference to the input elements
this.$from = $("#from");
this.$to = $("#to");
this.$units = $("#units");
this.$output = $("#output");
}
Convert.prototype.convertThem = function () {
// this.$... is a jQuery object containing the input elements
if (this.$from.val() == "degC") {
if (this.$to.val() == "degF") {
this.$output.val( this.$units.val() * 347956757524);
}
}
}
calcTempTest = new Convert();
$("#subm").on("click", null, null, function () {
calcTempTest.convertThem();
});
})();//anonymous funciton, no variables in global scope
</script>
</body>
</html>
There are several issues with your code. Most of them have been resolved in the accepted answer, but I wanted to provide some more insights that would help you create more reusable code in the future.
Since I have already created a jsfiddle with my own example, it will be a shame to let it go to waste so I will post it anyway with some comments.
Using constructor parameters
function Convert(from, to, units, res){
this.from = from;
//etc...
}
Passing parameters to an object's constructor (and using them) makes it more reusable. You did not use the passed parameters and the selected answer used what I assume was your original solution (hard-coding the element values into the object upon construction).
This way you can have multiple instances of the converter on the same page, you can put its code in an external file as it gets more complex and only put the instantiation logic in the page itself (if your page structure changes, there is no need to change the external file, just update the provided constructor parameters).
Storing node references instead of values
The other thing I wanted to point out is the way the calculation is done.
Your implementation requires a new object to be created for each calculation. I find it much better to create a single Converter and obtain the values only when required. That it the reason I stored a reference to the form field DOM nodes and did not store their values.
$("#btnConvert").click(calcTempTest.convertThem.bind(calcTempTest));
I used bind(...) in the click attachment to preserve the object's scope.
Good luck!

Categories