Goal: I'm trying to create an object literal that includes all the information in three different sections so a user can order multiple of multiple items and their order can be saved in session storage and later sent to a server.
My Problem: Other than selecting the parentNode of the order button, which only selects one of the three sections, I can't figure out how to get querySelectorAll to work with a variable that includes all three sections. It always says xVariable(container in this code).querySelectorAll isn't a function, or if it returns an object all the fields are null.
const orderButtons = document.querySelectorAll(".orderButton");
orderButtons.forEach(function(button) {
button.addEventListener("click", function() {
const container = document.querySelectorAll(".merch");
let order = {
title: container.querySelectorAll(".title").innerText,
price: container.querySelectorAll(".price").innerText,
description: container.querySelectorAll(".description").innerText,
quantity: container.querySelectorAll(".orderQuantity").innerText
};
console.log(order);
});
});
<article class="merchOrderPage">
<h1>Treadhead and Tank Models, Merch, Books, and More</h1>
<p>Here you can buy tank model kits, books about tanks and armored vehicles, and merch for our website.</p>
<div class="row">
<section id="orderItem1" class="column merch small-12 medium-12 large-4">
<img src="/images/ShermanEasy8Model.jpg" alt="Model of M4A3E8 Sherman Tank">
<h2 class="title">US M4A3E8 "Easy 8" Sherman </h2>
<p class="description">A plastic model of the M4A3E8 "Easy 8" Sherman.</p>
<p class="price">$29.99</p>
<button data-minusOrder="easy8" type="button">-</button><span class="orderQuantity" id="Easy8ModelQuantity">0</span><button data-plusOrder="easy8" type="button">+</button>
<button class="orderButton">Order</button>
</section>
<section id="orderItem2" class="column merch small-12 medium-12 large-4">
<img src="/images/ShermanTanksByDennisOliver.jpg" alt="Book cover of 'Sherman Tanks: US Army, North-Western Europe, 1944 to 1945 by Dennis Oliver'">
<h2 class="title">Sherman Tanks: US Army, North-Western Europe, 1944-1945</h2>
<p class="description">This excellent book by Dennis Oliver chronicles the history and service of the Sherman in Europe from 1944-1945.</p>
<p class="price">$49.99</p>
<button data-minusOrder="shermanbookoliver" type="button">-</button><span class="orderQuantity" id="ShermanTanksDennisOliverQuantity">0</span><button data-plusOrder="shermanbookoliver" type="button">+</button>
<button class="orderButton">Order</button>
</section>
<section id="orderItem3" class="column merch small-12 medium-12 large-4">
<img src="/images/Pz.IV T-Shirt.jfif" alt="Black shirt with a white profile of a Panzer IV.">
<h2 class="title">Panzer IV T-Shirt (Black)</h2>
<p class="description">A black cotton t-shirt with a solid white outline of a Panzer IV tank on it.</p>
<p class="price">$19.99</p>
<button data-minusOrder="pzivshirt" type="button">-</button><span class="orderQuantity" id="PanzerIVShirtQuantity">0</span><button data-plusOrder="pzivshirt" type="button">+</button>
<button class="orderButton">Order</button>
</section>
</div>
</article>
querySelectorAll returns a NodeList, which you need to iterate over. Then, you need just querySelector to find the only element:
let order = Array.prototype.map.call(container, x => {
return {
title: x.querySelector(".title").innerText,
price: x.querySelector(".price").innerText,
description: x.querySelector(".description").innerText,
quantity: x.querySelector(".orderQuantity").innerText
}
})
Related
I've tried to implement the solution of this site but that didn't work, I have tried many things to try to solve my issue. In my code below that'st he closet I can get and even then it's not what I'm after.
Trying to achieve:
I'm copying html from a div and placing it inside of a textrea.
I strip the html but keep the line breaks.
However due to the html being used from a third party site, I have no control over the way the 'html' is structed. As in the extra spaces seen in the code. The following code should be nice and neat in the textarea and look like:
Textarea data should be formated to look like:
Product details:
Item Number: 000800209270
Brand: Nikon
Model Number: D3500
Colour: Black
Number of Lenses: 2
This Nikon D3500 camera body comes with
Nikon 18-55mm 1:3.5-5.6G VR Lens
Nikon 70-300mm 1:4.5-6.3G ED VR Lens
1 battery & charger.
Shutter count: 426
The camera and both lens are in perfect working order, and is showing hardly any visible wear (please see photos).
For more information on this or any other item you may have seen please feel free to send me an email and I will respond as soon as possible.
function strip() {
$("#pstad-descrptn").text($('#item-info-container').text());
setTimeout(
function() {
jQuery.fn.cleanWhitespace = function() {
this.contents().filter(
function() { return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); })
.remove();
return this;
}
$('#item-info-container').cleanWhitespace();
$('#pstad-descrptn').cleanWhitespace();
}, 200 );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="button" id="thebutton" value="strip" onclick="strip();">
<textarea id="pstad-descrptn" name="description" data-val="true" cols="78" rows="20"></textarea>
<div id="item-info-container" class="clipboard copied re-copy" data-clipboard-target="#item-info-container">
<div id="item-pre-description">
<h2 class="h5">Product details:</h2> <div class="product-details__columns"> <p class="product-details__column"> <strong>Item Number:</strong> <span id="product-unique-id">000800209270</span> </p> <p class="product-details__column"> <strong>Brand:</strong> <span>Nikon</span> </p> <p class="product-details__column"> <strong>Model Number:</strong> <span>D3500</span> </p> <p class="product-details__column"> <strong>Colour:</strong> <span>Black</span> </p> <p class="product-details__column"> <strong>Number of Lenses:</strong> <span>2</span> </p> </div> </div>
<div id="item-description">
This Nikon D3500 camera body comes with<br><br>Nikon 18-55mm 1:3.5-5.6G VR Lens<br>Nikon 70-300mm 1:4.5-6.3G ED VR Lens<br>1 battery & charger.<br><br>Shutter count: 426<br><br>The camera and both lens are in perfect working order, and is showing hardly any visible wear (please see photos).<br><br>For more information on this or any other item you may have seen please feel free to send me an email and I will respond as soon as possible.<br><br> </div>
</div>
I'm at my wits end I've tried so many 'white-space' removing techniques, javascript and css to no prevail. Please someone save me from my misery. Thanks a million!
You can simply use innerText
function strip() {
document.querySelector('#pstad-descrptn').value =
document.querySelector('#item-info-container').innerText
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="button" id="thebutton" value="strip" onclick="strip();">
<textarea id="pstad-descrptn" name="description" data-val="true" cols="78" rows="20"></textarea>
<div id="item-info-container" class="clipboard copied re-copy" data-clipboard-target="#item-info-container">
<div id="item-pre-description">
<h2 class="h5">Product details:</h2> <div class="product-details__columns"> <p class="product-details__column"> <strong>Item Number:</strong> <span id="product-unique-id">000800209270</span> </p> <p class="product-details__column"> <strong>Brand:</strong> <span>Nikon</span> </p> <p class="product-details__column"> <strong>Model Number:</strong> <span>D3500</span> </p> <p class="product-details__column"> <strong>Colour:</strong> <span>Black</span> </p> <p class="product-details__column"> <strong>Number of Lenses:</strong> <span>2</span> </p> </div> </div>
<div id="item-description">
This Nikon D3500 camera body comes with<br><br>Nikon 18-55mm 1:3.5-5.6G VR Lens<br>Nikon 70-300mm 1:4.5-6.3G ED VR Lens<br>1 battery & charger.<br><br>Shutter count: 426<br><br>The camera and both lens are in perfect working order, and is showing hardly any visible wear (please see photos).<br><br>For more information on this or any other item you may have seen please feel free to send me an email and I will respond as soon as possible.<br><br> </div>
</div>
I want the pre-description to be a block of code with no spaces only line breaks.
You then need to separate the paragraphs and combine them
(and eliminate double line ending at first paragraph)
function strip() {
let item_pre_desc = document.querySelector('#item-pre-description')
let item_desc = document.querySelector('#item-description')
let result = document.querySelector('#pstad-descrptn')
result.value =
item_pre_desc.innerText.replace(/\n+/g,'\n')
+ '\n'
+ item_desc.innerText
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="button" id="thebutton" value="strip" onclick="strip();">
<textarea id="pstad-descrptn" name="description" data-val="true" cols="78" rows="20"></textarea>
<div id="item-info-container" class="clipboard copied re-copy" data-clipboard-target="#item-info-container">
<div id="item-pre-description">
<h2 class="h5">Product details:</h2> <div class="product-details__columns"> <p class="product-details__column"> <strong>Item Number:</strong> <span id="product-unique-id">000800209270</span> </p> <p class="product-details__column"> <strong>Brand:</strong> <span>Nikon</span> </p> <p class="product-details__column"> <strong>Model Number:</strong> <span>D3500</span> </p> <p class="product-details__column"> <strong>Colour:</strong> <span>Black</span> </p> <p class="product-details__column"> <strong>Number of Lenses:</strong> <span>2</span> </p> </div> </div>
<div id="item-description">
This Nikon D3500 camera body comes with<br><br>Nikon 18-55mm 1:3.5-5.6G VR Lens<br>Nikon 70-300mm 1:4.5-6.3G ED VR Lens<br>1 battery & charger.<br><br>Shutter count: 426<br><br>The camera and both lens are in perfect working order, and is showing hardly any visible wear (please see photos).<br><br>For more information on this or any other item you may have seen please feel free to send me an email and I will respond as soon as possible.<br><br> </div>
</div>
I'm trying to filter data gotten from database with the class="data-groups".
Here is the code:
this.shuffle.filter(function(element, shuffle) {
// If there is a current filter applied, ignore elements that don't match it.
if (shuffle.group !== Shuffle.ALL_ITEMS) {
// Get the item's groups.
var groups = JSON.parse(element.getAttribute('data-groups'));
var isElementInCurrentGroup = groups.indexOf(shuffle.group) !== -1;
// Only search elements in the current group
if (!isElementInCurrentGroup) {
return false;
}
}
var titleElement = element.querySelector('.book-item_title');
var titleText = titleElement.textContent.toLowerCase().trim();
return titleText.indexOf(searchText) !== -1;
});
};
<!-- begin snippet: js hide: false console: true babel: false -->
<div class="grid-shuffle">
<ul id="grid" class="row">
#foreach($libraries as $library)
<li class="book-item small-12 medium-6 columns" data-groups='["{{$library->genre}}"]' data-date-created='{{$library->published}}' data-title='{{ $library->title }}' data-color='{{$library->color}}'>
<div class="bk-img">
<div class="bk-wrapper">
<div class="bk-book bk-bookdefault">
<div class="bk-front">
<div class="bk-cover" style="background-image: url('img/001-small.png')"></div>
</div>
<div class="bk-back"></div>
<div class="bk-left"></div>
</div>
</div>
</div>
<div class="item-details">
<h3 class="book-item_title">{{$library->title}}</h3>
<p class="author">{{$library->author}} • {{$library->published}}</p>
<p>{{$library->synopsis}}</p>
Details
</div>
<div class="overlay-details">
Close
<div class="overlay-image">
<img src="img/001.jpg" alt="Book Cover">
<div class="back-color"></div>
</div>
<div class="overlay-desc activated">
<h2 class="overlay_title">{{$library->title}}</h2>
<p class="author">by {{$library->author}}</p>
<p class="published">{{$library->published}}</p>
<p class="synopsis">{{ $library->synopsis }}</p>
Preview
</div>
<div class="overlay-preview">
Back
<h4 class="preview-title">Preview</h4>
<div class="preview-content">
<h5>Chapter 1</h5>
<p>{{$library->details}}</p>
</div>
</div>
</div>
</li>
#endforeach
</ul>
</div>
The problem is it doesn't work unless I hard code the genre like this
data-groups='["fiction"]'
Now since I'm retrieving data from a database using the foreach loop it means any book out the database is automatically given the "fiction" attribute regardless of its db assigned genre.
Any help on how to solve this will be appreciated.
Found the problem
I was Filtering with this lines of code
All Categories
Fantasy
Sci-Fi
Classics
Fairy Tale
The problem was that the data-group items are case sensitive. So for example I was filtering with "classic" while my database was providing "Classic" therefore making the filter function seem faulty.
I am trying to write a script in tampermonkey that prints/inserts a value calculating the $ per sq ft. (Price/Total Sq Ft.) of each listing in a list like this. I have no javascript experience:
Screen Shot Example
Webpage:
http://www.utahrealestate.com/search/map.search
Relevant portion of HTML (one of the listings:)
<div id="mls-inline-1420899" class="listing_container">
<div class="listing-wrapper-table">
<div class="listing-wrapper-row">
<div class="listing-container-desktop">
<div class="listing-wrapper-cell">
<img src="http://assets.utahrealestate.com/photos/280x210/1420899_6faef96a263f4613b6b300cc915a9767_710733.jpg" class="listing-img" alt="MLS #1420899 Photo">
</div>
<div class="listing-wrapper-cell aligned-top">
<div class="inline_info">
<p class="status">
<i class="icon icon-circle status-1"></i> Active </p>
<h3>$249,000</h3>
<div class="list-info-content">
135 S 300 E <br>
Provo, UT 84606 </div>
<div class="list-info-content">
5 bds •
2.00 ba •
2026 sqft<br>
Built: 1914 • MLS #: 1420899 </div>
<p class="inline_agent">Agent: Chase Leavitt</p>
<p class="inline_brokerage">RE/MAX Equity</p>
</div>
</div>
</div>
<div class="listing-container-handheld">
<img id="img_1420899" class="listing-img" src="http://assets.utahrealestate.com/photos/640x480/1420899_6faef96a263f4613b6b300cc915a9767_710733.jpg" alt="MLS #1420899 Photo">
<div class="listings-info" style="display: block;">
<div class="listings-info-left-col">
<span>$249,000</span>
<p class="listing-address">135 S 300 E</p>
<p class="listing-address-csz">Provo, UT 84606</p>
</div>
<div class="listings-info-right-col">
<div class="border"><span>5</span><br>Beds</div>
<div class="border"><span>2.00</span><br>Baths</div>
<div class="end"><span>2026</span><br>Sq.Ft.</div>
<p>#1420899</p>
</div>
<p class="inline_brokerage">RE/MAX Equity</p>
</div>
</div>
</div>
</div>
</div>
I wrote a list of things that I need to accomplish to make this happen:
Javascript to grab the value of each listing and put it in a
variable
Javascript to grab the sq footage of each listing while excluding the uneeded info in the same div
Javascript to divide those variables and store result in a $perSqFt variable
Javascript to output that new value along with the original data
Loop for all of the listings doing the same as above.
Here is what I have so far. Feel free to offer any pointers, links, or advice. I am just updating this as I go. Thank you for helping!
(#1) The value for each listing is within a h3 tag. I am thinking that I will need to use find to get the value of the h3 tag:
.find('h3')
(#4) I am thinking I can use appendChild to output the new value next to the original sq ft value. Still working on this:
document.getElementById('list-info-content').appendChild(dollarPerSqFt);
(#5) The beginnings of a loop through .list-info-content classes:
var find_class = document.getElementsByClassName('list-info-content');
for (var i = 0, i++) {
find_class[i].innerHTML = {do something to} find_class[i].innerHTML ;
}
I can't seem to separate out an event method to effect just one specific element within a larger class.
Goal: When user changes value in input box for number of nights, the total price changes (only for that specific input). Currently, all classes are being altered simultaneously. I believe .find or .closest is the trick, but am unsure how to implement. here's the .js.
//nights auto multiply price
$(".cashtotal").prepend("$");
$('.nights').on('keyup change', function() {
var nights = +$(this).val();
var dailyPrice = +$(this).closest(".tour").data("daily-price");
$(".cashtotal").text(nights * dailyPrice);
$(".nights-total").text(nights);
$(".cashtotal").prepend("$");
});
and an example from the html
<div class="col-md-4 socal tour panel panel-default" data-discount="99" data-daily-price="100">
<h2 class="title">Idlehour, Angeles National Forest</h2>
<div class="info">
<div class="description">A pleasant trail through red fir forest with access to different
lake basins and the Yosemite Creek watershed.</div>
<div class="nightsnum">
<p>
<label for="nights">Number of Nights</label>
</p>
<p>
<input type="number" value="3" class="nights">
</p>
</div>
<div class="total">
<p><span class="cashtotal">400</span><br> for <span class="nights-count">3</span> Nights</p>
</div>
</div>
//nights auto multiply price
$(".cashtotal").prepend("$");
$('.nights').on('keyup change', function() {
var $thisTour = $(this).closest(".tour");
var nights = $(this).val();
var dailyPrice = $thisTour.data("daily-price");
$(".cashtotal", $thisTour).text("$" + nights * dailyPrice);
$(".nights-total", $thisTour).text(nights);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- I can't seem to separate out an event method to effect just one specific element within a larger class.
Goal: When user changes value in input box for number of nights, the total price changes (only for that specific input). Currently, all classes are being altered simultaneously. I believe .find or .closest is the trick, but am unsure how to implement. here's the .js. -->
<div class="col-md-4 socal tour panel panel-default" data-discount="99" data-daily-price="100">
<h2 class="title">Idlehour, Angeles National Forest</h2>
<div class="info">
<div class="description">A pleasant trail through red fir forest with access to different lake basins and the Yosemite Creek watershed.</div>
<div class="nightsnum">
<p>
<label for="nights">Number of Nights</label>
</p>
<p>
<input type="number" value="1" class="nights">
</p>
</div>
<div class="total">
<p><span class="cashtotal">100</span>
<br>for <span class="nights-total">1</span> Nights</p>
</div>
</div>
</div>
<div class="col-md-4 socal tour panel panel-default" data-discount="99" data-daily-price="200">
<h2 class="title">Another forest</h2>
<div class="info">
<div class="description">another tour.</div>
<div class="nightsnum">
<p>
<label for="nights">Number of Nights</label>
</p>
<p>
<input type="number" value="1" class="nights">
</p>
</div>
<div class="total">
<p><span class="cashtotal">200</span>
<br>for <span class="nights-total">1</span> Nights</p>
</div>
</div>
</div>
The question is worded in a way where the person giving the answer needs to interpret it. This is my interpretation. I am assuming that there are multiple tours. When you change one tour it changes all the ".nights-total" and ".cashtotal" classes. What you can do to solve this issue is use a context for the selector. In this case it is the tour that is the container that is the context for each ".nights-total" and ".cashtotal" class. If I have made the wrong assumptions please update your question in a clearer meaning. Hope this helps.
I have a pagination set up that I have used many time before... works great for lists and simple paragraphs, but I am unable to get it to work with a more complex html code, which is listed below. For some reason, the js refuses to turn the below code into a set object in order to paginate.
<div class="properties-content">
<div id="paging_container8" class="container">
<div class="storybody">
<p>
<!---------- Property Start ---------->
<article class="hentry">
<div class="property-featured"> <a class="content-thumb" href="property-details.html"> <img src="images/property/property3.jpg" alt=""> </a> <span class="property-label last">Last one left</span> <span class="property-category">Single Family Home </span> </div>
<div class="property-wrap">
<h2 class="property-title"> Single Family Residential, NJ </h2>
<div class="property-excerpt">
<p>Classic 60's ranch living. House has hardwood floors and hard coat plaster walls and ceilings...</p>
<p class="property-fullwidth-excerpt">Classic 60's ranch living. House has hardwood floors and hard coat plaster walls and ceilings in good condition. Intimate backyard for private gatherings. Full basement...</p>
</div>
<div class="property-summary">
<div class="property-detail">
<div class="size"> <span>1118 sqft</span> </div>
<div class="bathrooms"> <span>2</span> </div>
<div class="bedrooms"> <span>3</span> </div>
</div>
<div class="property-info">
<div class="property-price"> <span> <span class="amount">$299,000</span> </span> </div>
<div class="property-action"> More Details </div>
</div>
<div class="property-info property-fullwidth-info">
<div class="property-price"> <span><span class="amount">$299,000</span> </span> </div>
<div class="size"><span>1118 sqft</span> </div>
<div class="bathrooms"><span>2</span> </div>
<div class="bedrooms"><span>3</span> </div>
</div>
</div>
</div>
<div class="property-action property-fullwidth-action"> More Details </div>
</article>
<!---------- Property End ---------->
<!---------- Property End ---------->
</p>
<div class="page_navigation"></div>
I need, due to how my css is, to show 2 of the above code snippet out of maybe 25. And here is my javascript that I am using:
<script>
var str= $(".storybody").html();
var substr=str.split( "<!--pagebreak-->" );
var txt="<ul class='storycontent'><li>";
var x=0;
for (x in substr)
{
if(x==0){
txt=txt+substr[x];
}
else{
txt=txt+"</li><li>"+substr[x];
}
}
var paginated=txt+"</li></ul>";
$('div.storybody').replaceWith(paginated);
$(document).ready(function(){
$('#paging_container8').pajinate({
num_page_links_to_display : 2,
items_per_page : 1 ,
item_container_id : '.storycontent'
});
});
</script>
And here is the jsfiddle: http://jsfiddle.net/moLwmyyr/1/
I have figured it out!
The following js, along with the js in the fiddle, work with my html code in my question. Instead of the original js which only worked for simple lists, tables, and paragraphs, the js listed here will work on nested html code.
(function($){
$(document).ready(function(){
$(".pagination").customPaginate({
itemsToPaginate : ".post"
});
});
})(jQuery)
http://jsfiddle.net/moLwmyyr/2/
Works perfectly with my site and css. Hope this helps others.