Getting specific parent element using jQuery using eq() - javascript

I would like to be able to dynamically update a quantity field when I click on a '+' (Plus Button) However, depending where I click on the button, I am getting a different result for the parent element.
The HTML that is in use to call the function is below. This is HTML from my frontend developer and I am trying to connect a few things to make this work.
<div id="item-list" class="product_list_container">
<div class="bluedog-flex-container noPaddingLeftRgt payhub-well col-xs-12 col-sm-12 col-lg-12" data-id="32" style="margin-top:0;">
<div class="subtotal-div col-xs-12 col-sm-12 col-lg-12">
<div class="bluedog-inner-flex-container product_info_container col-xs-12 col-sm-12 col-lg-12">
<div class="order-overview-left noPaddingLeft alignLeft col-xs-4 col-sm-4 col-lg-4">Macbook Pro # 50.00</div>
<div class="quantity_range_div col-xs-6 col-sm-6 col-lg-6">
<div class="value-button createPage_decrease_qty decrease_value_btn" style="display:inline;" onclick="decreaseQty(event)"><i class="far fa-minus"></i></div>
<input type="number" class="itm_qty" id="number" value="1">
<div class="value-button increase_value_btn" style="display:inline;" onclick="increaseQty(event)"><i class="far fa-plus"></i></div>
</div>
<input type="hidden" name="item_price" data-qty="1" data-prod-name="Macbook Pro" data-id="32" data-tax="0" value="50.00"><a class="popup-close-btn order-overview-right close_btn_plans col-xs-2 col-sm-2 col-lg-2" onclick="removeItem(event)"> <i class="far fa-times-circle hosted_small_delete"></i></a>
</div>
</div>
</div>
</div>
What I am trying to achieve is, when I click on the Plus Button, (Screenshot attached) https://prnt.sc/oq770q the value will increase.
Originally, I was just using the following code to try and get the parent DIV id, which in this case is item-list
var master = $(e.target).parents().eq(5).attr('id'); // Name of item-list container
However, was receiving unexpected results, whereby if I tapped on the outside of the plus button, the surround grey area, it would not increase, but only if I tapped directly on the plus icon itself.
I noticed it was picking up a different element and the eq(5) was returning an undefined value. As you will see in in the script below, I have put in an if statement for a class check to see which part of the button has been pressed and this returns the expected results.
However, I dont' see this as scalable and transferable if someone was to change the FontAwesome Tag, as the class would likely be different.
function increaseQty(e) {
var clicked = e.path[0];
if ($(clicked).hasClass('fa-plus')) {
var master = $(e.target).parents().eq(5).attr('id'); // Name of item-list container
} else {
var master = $(e.target).parents().eq(4).attr('id'); // Name of item-list container
}
var input = $(e.target).parent().parent().find('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
I would like to know how, if possible, that regardless where on the container that is being clicked, the plus icon or the gray area around it, to increase the value, without having to do a dirty class check.
Many thanks,
David.

Based on you html code I am seeing like
<input type="number" class="itm_qty" id="number" value="1">
In this line you have id number so you can easily update.Based on your description your above line repeat. So you modify your increaseQty like that.
function increaseQty(e) {
var input = $(e.target).prev('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
If you see in your code increaseQty bind with div element and input itm_qty is sibling of div. So I am hoping above code works.

So to answer my own question, with some help from #Dhiren (Thank You)
I found out that I could assign FontAwesome Icon to the class of a SPAN. Therefore I have changed the Divs which contained the FontAwesome Icons to Spans, and assigned the FA Icon class to the span, removing the element.
<div class="quantity_range_div col-xs-6 col-sm-6 col-lg-6">
<span class="value-button createPage_decrease_qty decrease_value_btn far fa-minus" style="display:inline;" onclick="decreaseQty(event)"></span>
<input type="number" class="itm_qty" id="number" value="1">
<span class="value-button increase_value_btn far fa-plus" style="display:inline;" onclick="increaseQty(event)"></span>
</div>
In doing so I was able to use a single parents().eq(4) line of code, as the target will now always be a span, and not a Div element or an element.
function increaseQty(e) {
var master = $(e.target).parents().eq(4).attr('id');
var input = $(e.target).prev('input.itm_qty');
var qty = $(input).val();
var newQty = parseInt(qty) + 1;
$(input).val(newQty);
updatePrices(master);
}
Dhiren, thank you for the prev() suggestion as it has helped me better refactor not only this function, but more also! I appreciate the help and support.
David

Related

Add form items with javascript based on dropdown selection

I am building a recipe-database for myself (just to learn programming) and I've setup a base page with bootstrap, python, flask and sqlalchemy. I added the ingredients to the database and it is working fine. Now i can build recipes (another db.class) by adding these ingredients and combine them with the amount of them. I've prepared a form to setup all the required inputs.
For the ingredients i want to have a dropdown with all ingredients availabe in the db (done and working, see below). Now i want to add elements above in a container dynamically by selection of a dropdown-item. I staret by adding static elements first and it is working - when i use "onclick". This is what i have so far:
HTML of the dropdown:
<div id="container">
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Ingredient</label>
<div class="col-sm-2"><input
type="text"
class="form-control"
id="amount"
name="amount">
</div>
<label for="amount" class="col-sm-1 col-form-label">g / ml</label>
<div class="dropdown col-sm-2">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" id="Dropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" onclick="addIngredient()">
Choose Ingredient
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{% for ingredient in ingredients %}
<a class="dropdown-item" href="#">{{ ingredient.name }}</a>
{% endfor %}
</div>
</div>
</div>
This is the javascript I am calling:
function addIngredient() {
var container = document.getElementById("container");
var div_outer = document.createElement("div");
div_outer.setAttribute("class","form-group row");
container.appendChild(div_outer);
var label = document.createElement("label");
label.innerHTML = "Test";
label.setAttribute("class","col-sm-2 col-form-label");
div_outer.appendChild(label);
var div_inner = document.createElement("div");
div_inner.setAttribute("class","col-sm-2");
div_outer.appendChild(div_inner);
var input = document.createElement("input");
input.innerHTML = "Amount";
input.setAttribute("class","form-control");
div_inner.appendChild(input);
var label_unit = document.createElement("label");
label_unit.innerHTML = "g (ml)";
label_unit.setAttribute("class","col-sm-1 col-form-label");
div_outer.appendChild(label_unit);
var delete_btn = document.createElement("button");
delete_btn.setAttribute("type", "button");
delete_btn.setAttribute("class", "close");
delete_btn.setAttribute("onclick", "");
div_outer.appendChild(delete_btn)
var span = document.createElement("span");
span.setAttribute("aria-hidden", "true");
span.innerHTML = "×"
delete_btn.appendChild(span)
}
As a first step i wanted to replace the text of "label" with the selection of the Dropdown with that:
//Getting Value
var selObj = document.getElementById("Dropdown");
var selValue = selObj.options[selObj.selectedIndex].value;
//Setting Value
label.innerHTML = selValue;
Question 1: But as soon as I change the event from "onclick" to "onchange" it stops working. Why?
Question 2: How can i make the created items identifiable with a unique id, so that i can use the label-text to identify the ingredient-id and add them to the recipe-class. How can i generate that id?
Unfortunately i dont now much Java or HTML yet but i try to learn :)
Question 1:
The onchange attribute fires the moment when the value of the element is changed.
Tip: This event is similar to the oninput event. The difference is that the oninput event occurs immediately after the value of an element has changed, while onchange occurs when the element loses focus. The other difference is that the onchange event also works on elements.
So if you want the onchange to be fired you should consider creating a drop-down list using HTML <select> Tag.
Question 2:
You can easily retrieve the id stored in your db of the item and set it in an attribute by your choice.

Run js when pop over text input is loaded

Wanted to have cleave.js to format text input on the fly.
I have 2 text inputs
HTML text input and
also a pop over text input whenever search icon is clicked.
The issue is on popover text input where cleave text formating is not
working.
I believe it could be related to the element hasn't exist somehow? I have try to listen to listener but no luck so far. .on('shown.bs.popover)
My code as as per below
https://jsfiddle.net/fairul82/y3kf92oq/
Libraries used : cleave,js , bootstrap popover , jquery
HTML
<div class="container">
<h3>Bootstrap 3 Popover HTML Example</h3>
<input type="text" class="input-element"><br>
<ul class="list-unstyled">
<li><a data-placement="bottom" data-toggle="popover" data-
container="body" data-placement="left" type="button" data-html="true"
href="#" id="login"><span class="glyphicon glyphicon-search" style="margin:3px 0 0 0"></span></a></li>
<div id="popover-content" class="hide">
<form class="form-inline" role="form">
<div class="form-group">
<h1>
My Content
</h1>
<input type="text" class="input-element"><br>
</div>
</form>
</div>
//JS
$("[data-toggle=popover]").popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
$("[data-toggle=popover]").on('shown.bs.popover', function() {
// alert('called back');
const cleave = new Cleave('.input-element', {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
});
const cleave = new Cleave('.input-element', {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
Here is solution https://jsfiddle.net/ztkv8w60/19/
According to authority document https://github.com/nosir/cleave.js, it has a note .input-element here is a unique DOM element. If you want to apply Cleave for multiple elements, you need to give different css selectors and apply to each of them.
It is tricky question, because the bootstrap popover creates the same element as your specific div when the icon gets a click. Therefore there are two the same element, you have to point it out which element is in a popover.

uib-popover-template not showing

I am trying to use a uib-popover-template on a font awesome icon as a sort of settings menu but can't get the popup to show. This is in the header of the page I am using:
<h3>{{vm.title}}
<i class="fa fa-ellipsis-v pull-right"
aria-hidden="true"
uib-popover-template="'options-panel.html'"
popover-placement="left"></i>
</h3>
And i have the ellipses in the right corner kind of like a 'more options' menu. options-panel.html is just 4-5 <select> dropdowns depending on the page that looks like this:
<div class="row">
<div class="form-group col-md-12">
<label for="viwemode">View Mode</label>
<select id="viewmode"
class="form-control"
ng-model="vm.currentViewer"
ng-options="view for view in vm.views"
ng-change="vm.viewChange();"></select>
</div>
<div class="form-group col-md-12"
ng-repeat="viewOption in vm.genericOptions">
<label for="{{viewOption.label}}">{{viewOption.label}}</label>
<select id="{{viewOption.label}}"
class="form-control"
ng-model="vm.config[viewOption.label]"
ng-options="v as k for (k,v) in viewOption.values"
ng-change="vm.optionChange(viewOption.label);"></select>
</div>
<div class="form-group col-md-12"
ng-repeat="viewOption in vm.viewerOptions">
<label for="{{viewOption.label}}">{{viewOption.label}}</label>
<select id="{{viewOption.label}}"
class="form-control"
ng-model="vm.config[viewOption.label]"
ng-options="value for value in viewOption.values"
ng-change="vm.optionChange(viewOption.label);"></select>
</div>
</div>
And lastly in the controller for the class I just have this object which has the template url in it:
vm.popover = {
template: '<a href uib-popover-template="\'options-panel.html\'" popover-placement="left"></a>'
};
I am not sure what I am missing but not even a popover will show let alone the one with my template in it. If I just do the ellipses (fa-icon) with uib-popover="test" the popover will show with 'test' in it so I do have the uib dependency correctly installed.
Consider this uib-popover-template plunker
I don't know your data structure but should work.
You don't need anymore
vm.popover = {
template: '<a href uib-popover-template="\'options-panel.html\'" popover-placement="left"></a>'
};
This line
uib-popover-template="'options-panel.html'"
Should be
uib-popover-template="options-panel.html"
Notice I removed the single quotes, uib-popover-template accepts an expression that will evaluate to the template location on your $scope. by passing your template path in single quotes you are only passing a plain string as an expression.
From the Docs
uib-popover-template - A URL representing the location of a template to use for the popover body

how to use javascript event handler

I have a 2 col layout, on the left i have a button that says show code and on the right i have some html.
The above is repeat numerous time so i have a list of buttons that i want related to the "widget" next to it.
If i click on each button, i would like to show the innerHTML of the element to the right in an alert box.
My right column html widgets are a class called "mywidgets", and my buttons to the left have a class called "showcode"
how would I go about showing the code of the related box to the right on click of button to the left in javascript or jquery?
if I do something like:
var showthem = document.getElementsByClassName('mywidgets');
for (var i=0; i < widgetBits.length; i++) {
};
but I get confused on how to count each button and each class in the seperate area, then show the code on click.
I was also thinking about something similar to below but again I get confused on how to utilize "this"/each item clicked.
$(document).ready(function(){
$("button").click(function(){
$("mywidgets").clone().appendTo("myareofchoce");
});
});
HTML:
left area :
<div class="container marginBTM10">
<div class="row">
<div class="col-lg-offset-2 col-md-offset-2 col-lg-10 col-md-10 bgColor_FFF padding10">
<h2>Widget 1</h2>
<div class="highlight">
<button class="btn btn-primary btn-sm " onclick="widgets()">get code</button>
right hand area :
<div class="col-lg-4 col-md-4">
<!-- widget 1 starts-->
<div class="sortable bgColor_FFF mywidgets">
<div class="padding10">
stuff
</div>
</div>
<!-- widget 1 ends-->
</div>
</div>
http://jsfiddle.net/wne6rnda/1/
to connect buttons and widgets must be used in a single tag.
in this case: widget has id and corresponding button has data-id with same value
HTML:
buttons:
<button class="btn btn-primary btn-sm get_class" data-id="#mywidgets1">
...
<button class="btn btn-primary btn-sm get_class" data-id="#mywidgets2">
...
widgets:
div class="sortable bgColor_FFF mywidgets" id="mywidgets1">
...
div class="sortable bgColor_FFF mywidgets" id="mywidgets2">
...
JQ
$('.get_class').click(function () {
//get id of selected widget
var id = $(this).data('id');
//get selected widget
var $widget = $(id);
//clon and add selected widget
$widget.clone().appendTo(".myareofchoce");
})
UPDATE: 2
http://jsfiddle.net/wne6rnda/9/
$('.get_class').click(function () {
var id = $(this).data('id');
var $widget = $(id);
var html=$widget.html();
//solution 1 - output to the textarea
var txt=$(".myareofchoce2").val();
$(".myareofchoce2").val(txt+"\r\n"+html);
//solution 2 - use <xmp> tag
html='<xmp >'+html+'</xmp >';
$(".myareofchoce").append(html);
})

how to change values in a hidden chunk of html code

I have this hidden block of code that i want to call based on the values that are received from server:
<div id="hiddenChart" style="display:none;">
<li style="height:auto;">
<div class="col-sm-4" id="chart_0_0">
<div class="panel panel-success" style="width:550px; height:auto;" id="accordion_0_0">
<div class="panel-heading">
<div class="btn-group" style="float:right;">
<i class="glyphicon glyphicon-minus" id="minimize_0_0"></i>
<i class="glyphicon glyphicon-remove" id="close_0_0"></i>
</div>
<h3 class="panel-title">title</h3>
</div>
<div class="panel-body" style="height:400px;">
<nvd3-multi-bar-chart data="Sec1Graf1Data" id="dataChart_0_0" height="400" showXAxis="true" reduceXTicks="true" showYAxis="true" showLegend="true" showControls="true" tooltips="true">
<svg></svg>
</nvd3-multi-bar-chart>
</div>
</div>
</div>
</li>
</div>
but i need to change some values: ids, tags, data variables.
I know how to show the code using "$('ul').append($('div').html());" but i have to change it before doing it.
How can i do it?
How do i define in which fields i have to insert the string i'me receiving?
Thk
UPDATE:
I was able put it to work, here is the fiddle with it fiddle.
When i inspect the element, the ids that i want to change, instead of #1, it returns chart_0_0.
Thank you all for your posts and help
You can get a reference to your div like this:
var $div = $('#hiddenChart');
To clone it,
var $clonedDiv = $div.clone();
Then, in the $cloneDiv object, you make the changes:
$clonedDiv.find(--selector of a node--).attr(atributeName, atributeValue); //change/add attribute
$clonedDiv.find(--selector of a node--).removeAttr(atributeName); //remove attribute
And so on. I won't explain how jQuery works, Lekhnath gave you a link.
Finally you insert the $clonedDiv with .appendTo() wherever you want. The original div remains untouched so you can clone it again and again.
Jquery Change text/html from a hidden div content :
Simple
maintain a copy of the hidden content
replace the content based on the element class/id selector with the server response
then paste the html into another div
replace the content of the hidden back to original (optional)
http://jsfiddle.net/austinnoronha/ZJ3Nt/
$(document).ready(function(){
var serverRes = {
title: "New Title In Header",
body: "New body text from server <\/br><nvd3-multi-bar-chart data=\"Sec1Graf1Data\" id=\"dataChart_0_0\" height=\"400\" showXAxis=\"true\" reduceXTicks=\"true\" showYAxis=\"true\" showLegend=\"true\" showControls=\"true\" tooltips=\"true\"><svg><\/svg><\/nvd3-multi-bar-chart>"
};
var tmpOldCont = $("#hiddenChart").html();
var counter = 1;
$(".serverres").click(function(){
$("#hiddenChart").find(".panel-body").html(counter + " = " + serverRes.body);
$("#hiddenChart").find(".panel-title").text(serverRes.title + " " + counter);
counter++;
$(".box-container").html($("#hiddenChart").html());
$("#hiddenChart").html(tmpOldCont);
});
});

Categories

Resources