I'm trying to use a toggle button with jquery appended content. The appended content uses Labelauty jQuery Plugin to load the check boxes and its working fine.
But the toggle button is not loading the relevant css properly.
Here is my html code for the panel which includes the toggle button.
<div class="col-md-6">
<div class="panel">
<div class="panel-body container-fluid">
<div id="testcases" class="accordion js-accordion">
<h4>Test<i class="fa fa-thumbs-o-down"></i> <small>CASES</small>
<div class="toggle-wrap w-checkbox">
<input class="toggle-ticker w-checkbox-input" data-ix="toggle-switch" data-name="Toggle Switch" id="Toggle-Switch" name="Toggle-Switch" type="checkbox" onclick="toggle()">
<label class="toggle-label w-form-label" for="Toggle-Switch"> </label>
<div class="toggle">
<div class="toggle-active">
<div class="active-overlay"></div>
<div class="top-line"></div>
<div class="bottom-line"></div>
</div>
</div>
</div>
</h4>
</div>
<br>
<button type="button" class="btn btn-info float-right" onclick="loadplan()">Add to Plan</button>
</div>
</div>
</div>
<!--TestPlan Panel-->
<div class="Panel">
<div class="col-md-13">
<div class="panel">
<div class="panel-body container-fluid">
<h4>Test<i class="fa fa-thumbs-o-down"></i> <small>PLAN</small></h4>
<!-- Start list -->
<ul id="testplan" class="list-group"></ul>
</div>
<!-- End list -->
</div>
</div>
</div>
Which output this
before jquery append
Here is my jquery to append content
//Load TestCase List to Accordion
var testSuiteList;
var currentTestSuite;
function loadtestcases(testSuite, testcases) {
currentTestSuite = testSuite;
var testcases = testcases.split(",");
// $("#testcases").empty();
$("#testcases div:not(:first)").remove();
var id = 0;
// $("#testcases").append("<h4>Test<i class='fa fa-thumbs-o-down'></i> <small>CASES</small></h4>")
testcases.forEach(function(entry) {
id = id + 1;
$("#testcases").append("<div class='accordion__item js-accordion-item'>" +
"<div class='accordion-header js-accordion-header'>" +
"<input type=\"checkbox\" class='to-labelauty-icon' name=\"inputLableautyNoLabeledCheckbox\" data-plugin=\"labelauty\" data-label=\"false\" id=\"labelauty-" + id + "\" value=\"" + entry + "\"> " + entry + "</div>" +
"<div class='accordion-body js-accordion-body'>" +
"<div class='accordion-body__contents'>" +
"data-table" +
"</div>" +
"</div>" +
"</div>" +
"<div class='accordion__item js-accordion-item active'>" +
"</div>")
});
//accordion js for appended div
var accordion = (function() {
var $accordion = $('.js-accordion');
var $accordion_header = $accordion.find('.js-accordion-header');
var $accordion_item = $('.js-accordion-item');
// default settings
var settings = {
// animation speed
speed: 400,
// close all other accordion items if true
oneOpen: false
};
return {
// pass configurable object literal
init: function($settings) {
$accordion_header.on('click', function() {
accordion.toggle($(this));
});
$.extend(settings, $settings);
// ensure only one accordion is active if oneOpen is true
if (settings.oneOpen && $('.js-accordion-item.active').length > 1) {
$('.js-accordion-item.active:not(:first)').removeClass('active');
}
// reveal the active accordion bodies
$('.js-accordion-item.active').find('> .js-accordion-body').show();
},
toggle: function($this) {
if (settings.oneOpen && $this[0] != $this.closest('.js-accordion').find('> .js-accordion-item.active > .js-accordion-header')[0]) {
$this.closest('.js-accordion')
.find('> .js-accordion-item')
.removeClass('active')
.find('.js-accordion-body')
.slideUp()
}
// show/hide the clicked accordion item
$this.closest('.js-accordion-item').toggleClass('active');
$this.next().stop().slideToggle(settings.speed);
}
}
})();
$(document).ready(function() {
accordion.init({
speed: 300,
oneOpen: true
});
$(":checkbox").labelauty({
label: false
});
});
}
//Load the selected testcases on TestPlan
function loadplan() {
currentTestSuite;
//Map the selected testcases to an array
var selectedtclist = [];
$('input[class="to-labelauty-icon labelauty"]:checked').each(function() {
selectedtclist.push(this.value);
});
for (var i = 0; i < selectedtclist.length; i++) {
var tc_name = selectedtclist[i];
var searchWord = currentTestSuite + " " + "|" + " " + tc_name;
// see if element(s) exists that matches by checking length
var exists = $('#testplan li:contains(' + searchWord + ')').length;
if (!exists) {
//Append selected testcases to TestPlan
$("#testplan").append("<li class='list-group-item list-group-item-info'>" + currentTestSuite + " " + "|" + " " + tc_name + "</li>");
}
};
};
which output this
after loading jquery appended content
How can I load the styles for toggle button properly?
You use append() for the selector $("#testplan"), but I cannot find that ID id="testplan" for any element in your HTML code, so therefore JS can't find it and thus cannot "appand" anything to it.
Related
I'm trying to get data from this page using cheerio js:
var html =
"<div class='clear'>" +
"<div class='time_head'>time_head content1</div>"
+ "<div class='blockfix'>blockfix1</div>"
+ "<div class='blockfix'>blockfix2</div>"
+ "<div class='time_head'>time_head content2</div>"
+ "<div class='blockfix'>blockfix3</div>"
+ "<div class='blockfix'>blockfix4</div>"
+ "<div class='blockfix'>blockfix5</div>"
+ "</div>";
this is what i tried so far:
$ = cheerio.load(html);
let devtoList = [];
$('.clear').each(function (i, elem) {
devtoList[i] = {
title: $(this).find('.time_head').text(),
game: $(this).find('.blockfix').text()
};
});
const devtoListTrimmed = devtoList.filter(n => n != undefined);
console.log(devtoListTrimmed);
the result is :
[
{ title: 'time_head content1time_head content2',
game: 'blockfix1blockfix2blockfix3blockfix4blockfix5' }
]
But i need every time_head with its blockfix's
TIME_HEAD CONTENT1
----blockfix1
----blockfix2
TIME_HEAD CONTENT2
----blockfix3
----blockfix4
please note:
1- The number of time_head's always change
2- I'm open to other solutions
Get all elements with .time_head, iterate over it, apply while loop until the next element has class blockfix.
const output = [];
$('.time_head').each(function(i) {
let next = $(this).next('.blockfix');
output.push({"title": $(this).text(), game: []});
while(next) {
output[i].game.push(next.text());
const isNext = $(next).next('.blockfix');
next = isNext.length > 0 ? $(next).next('.blockfix') : false;
}
});
console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='clear'>
<div class='time_head'>time_head content1</div>
<div class='blockfix'>blockfix1</div>
<div class='blockfix'>blockfix2</div>
<div class='time_head'>time_head content2</div>
<div class='blockfix'>blockfix3</div>
<div class='blockfix'>blockfix4</div>
<div class='blockfix'>blockfix5</div>
</div>
If user click "Twin Bed" or "King Bed", Content inside "demand-message" have to change either "high demand" or "Only ??? rooms left".
ID will be same for button because of existing logic. Now my message to display on "demand-message" is not changing if i click "King Bed". It displays correctly for "Twin Bed".
Is it possible to change message by getting ID with data-bed-type attribute to match and change the message (either high demand or No. of rooms left)?
HTML:
<div class="col-lg-4 col-md-12 col-sm-12 col-12 left-container">
<div class="demand-message--wrapper">
<div class="demand-message"></div>
</div>
<div class="left-column">
<div class="btn-group">
<button type="button" data-bed-container-id="deluxe-balcony-room" data-bed-max="190" data-bed-type="twin">Twin Bed</button>
<button type="button" data-bed-container-id="deluxe-balcony-room" data-bed-max="90" data-bed-type="king">King Bed</button>
</div>
</div>
JS:
function onToggleBed(e) {
var thisButton = $(e.currentTarget);
var bedTypeSelected = thisButton.data('bed-type');
var bedValueSelected = thisButton.data('bed-value');
var roomContianerId = thisButton.data('bed-container-id');
var buttonMaxRoom = thisButton.data('bed-max');
var message = '';
if (buttonMaxRoom < 100) {
message = 'Only ' + buttonMaxRoom + ' rooms left';
} else if (buttonMaxRoom > 100) {
message = 'In high demand';
}
if (message == '') {
$('#' + roomContianerId + ' .demand-message').hide();
} else {
$('#' + roomContianerId + ' .demand-message').show();
$('#' + roomContianerId + ' .demand-message').html(message);
}
}
As I mentioned in my comment, hypens will removed and turned into camelCase.
In this case use:
var bedTypeSelected = thisButton.data('bedType');
Let's console.log(thisButton.data()); to see your data items.
I am adding and removing <ul> and placing its plain structure with its text into a textarea. The following works yet it is not closing all the <ul>s, not adding the closing </ul> basically but it places an open <ul> instead.
Here it is a jsFiddle
This is what I am doing:
HTML
<div id="mindMap">
<ul>
<li><button class="btn btn-default ul-appending">+ Node</button> </li>
</ul>
</div>
<div id="mindMapData">
<textarea col="10" rows="10"></textarea>
</div>
The in jQuery I am creating the tool to add/remove nested list and cleaning all the unnecessary html while leaving all the plain nested list and its text:
$('body').on('click', 'button.ul-appending', function() {
$(this).parent().append(
$('<ul class="main_ul">').addClass('newul sortable').append(
$('<li><div class="input-group"><input placeholder="Add node..." class="form-control" type="text"><div class="input-group-btn"><button type="button" class="btn btn-default list">+ sub node</button><button type="button" class="btn btn-default removeThis">remove</button></div></div></li>')
)
);
});
$('body').on('click', 'button.list', function() {
var newLi = '<ul class="sub_ul"><li class="listSub"><div class="input-group"><input placeholder="+ sub node..." class="form-control" type="text"><div class="input-group-btn"><button type="button" class="btn btn-default list">+ sub node</button><button type="button" class="btn btn-default removeThis">remove</button></div></div></li></ul>';
var listEl = $(this).parent().parent().parent();
$(listEl).append(newLi);
});
$('body').on('click', 'button.removeThis', function() {
$(this).parent().parent().parent().remove();
});
function ul(indent) {
indent = indent || 4;
var node = $(this);
return node.removeAttr('class').children().map(function() {
var self = $(this);
var value = self.find('> .input-group input').val();
var sub_ul = self.find('> ul');
var ul_spaces = new Array(indent+4).join(' ');
var li_spaces = new Array(indent).join(' ');
if (sub_ul.length && ul) {
return li_spaces + '<li>' + value + '\n' + ul_spaces +
'<ul class="sortable">\n' + ul.call(sub_ul, indent+8) + '\n' + ul_spaces + '<ul>\n' +
li_spaces + '</li>';
} else {
return li_spaces + '<li>' + value + '</li>';
}
}).get().join('\n');
}
function updateTree() {
$("#mindMapData textarea").text('<ul class="sortable">\n' + $("#mindMap").clone().find('.main_ul').map(ul).get().join('\n') + '\n</ul>');
}
$("#mindMap").on("DOMSubtreeModified", updateTree);
$("#mindMap").on('keyup', 'input', updateTree);
jsFiddle
Line 30:
'<ul class="sortable">\n' + ul.call(sub_ul, indent+8) + '\n' + ul_spaces + '<ul>\n' +
Correction:
'<ul class="sortable">\n' + ul.call(sub_ul, indent+8) + '\n' + ul_spaces + '</ul>\n' +
You need a slash here: '</ul>\n'
JSfiddle
Im pulling items from a JSON file. I have a class called "showProduct" and once clicked it executes a function and shows the item information on the page. I am trying to call this same function again later in my code on the similar product. I need the page to refresh with that new items contents. Below is my code really hope someone can help me out im not sure what I am doing wrong. I did not include the JSON but i hope just by looking at the class and my code someone will know why it wont work.
function openNav() {
document.getElementById("productsSideBar").style.width = "250px";
}
function closeNav() {
document.getElementById("productsSideBar").style.width = "0";
}
'use strict';
$.ajax({
dataType: "jsonp",
url: '',
success: function(json){
//check for window hash and display appropriate product category
var currentHash = window.location.hash;
switch(currentHash)
{
case '#tomatoes':
displayTomatoes();
break;
default:
displayAll();
break;
}
//display all products function
function displayAll() {
var categoryImage = '';
$.each(json, function (i, item) {
if (item.itemBrandLetter == "C") {
categoryImage += '<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">' + '' + '<img class="img-responsive img-hover productImagesCategory" src="' + item.imageURL + '">' + '<h3>' + item.itemName + '</h3>' + '' + '</div>';
}
});
$('#imagesCategoryProducts').hide().html(categoryImage).fadeIn('slow');
//show individual product function on click
$(".showProduct").click(function(event){
//hide all current products
$('#productCategories').hide();
//get passed data from other function
var clickedItemName = '<h1>' + $(this).data('itemname') + '</h1>';
var clickedItemUPC = $(this).data('itemupc');
var clickedItemOZ = '<h2>' + $(this).data('itemoz') + '</h2>';
var clickedItemDescription = '<p>' + $(this).data('itemdescription') + '</p>';
var clickedItemImage = '<img class="img-responsive img-rounded center-block" src="' + $(this).data('itemimage') + '">';
var clickedItemGluten = $(this).data('itemgluten');
var clickedItemBPA = $(this).data('itembpa');
var clickedItemGMO = $(this).data('itemgmo');
var clickedItemPageURL = $(this).data('itempageurl');
//check if clicked data equals correct item
$.each(json, function (i, item) {
if (item.itemName === clickedItemName) {
clickedItemName
}
if (item.itemFullUPC === clickedItemUPC) {
clickedItemUPC
}
if (item.itemPackSize === clickedItemOZ) {
clickedItemOZ
}
if (item.itemDescription === clickedItemDescription) {
clickedItemDescription
}
if (item.imageURL === clickedItemImage) {
clickedItemImage
}
if (item.itemGlutenFree === clickedItemGluten) {
clickedItemGluten
}
if (item.itemBPAFree === clickedItemBPA) {
clickedItemBPA
}
if (item.itemGMOFree === clickedItemGMO) {
clickedItemGMO
}
//assign window hash to each product
if (item.itemName === clickedItemPageURL) {
event.preventDefault();
clickedItemPageURL = clickedItemPageURL.replace(/\s/g, '');
window.location.hash = clickedItemPageURL;
}
});
//remove extra characters from UPC
var originalUPC = clickedItemUPC;
var strippedUPC = '<h2>' + originalUPC.slice(1, -1); + '</h2>';
//show individual product information
$('#productSocialShare').show();
$('#individualProduct').show();
$('#relatedProducts').show();
//append product information to appropriate DIV
$('#productTitle').html(clickedItemName);
$('#productUPC').html(strippedUPC);
$('#productOZ').html(clickedItemOZ);
$('#productDescription').html(clickedItemDescription);
$('#productImage').html(clickedItemImage);
//check if gluten free is true and show image
if (clickedItemGluten == "Y") {
clickedItemGluten = '<img class="img-responsive img-rounded img-margin" src="../images/misc/gluten_free_test.jpg">';
$('#productGlutenFree').html(clickedItemGluten);
$('#productGlutenFree').show();
} else {
$('#productGlutenFree').hide();
}
//check if bpa free is true and show image
if (clickedItemBPA == "Y") {
clickedItemBPA = '<img class="img-responsive img-rounded img-margin" src="../images/misc/bpa_free_test.jpg">';
$('#productBPAFree').html(clickedItemBPA);
$('#productBPAFree').show();
} else {
$('#productBPAFree').hide();
}
//check if gmo free is true and show image
if (clickedItemGMO == "Y") {
clickedItemGMO = '<img class="img-responsive img-rounded img-margin" src="../images/misc/gmo_test.jpg">';
$('#productGMOFree').html(clickedItemGMO);
$('#productGMOFree').show();
} else {
$('#productGMOFree').hide();
}
//show random recipe for each item
var url = '';
$.getJSON(url, function(json) {
var randomRecipe = json[Math.floor(Math.random() * json.length)];
randomRecipe += '<div>' + '' + '<img class="img-responsive img-hover similarProductImagesCategory" src="' + randomRecipe.recipeImageCategoryURL + '">' + '' + '' + '<h3 class="similarProductSubCategoryImgCaption">' + randomRecipe.recipeName + '</h3>' + '' + '</div>';
$('#featuredRecipe').append(randomRecipe);
});
//show similar products
var categoryItems = [];
$.each(json, function(i, item){
if(window.location.hash.indexOf('Tomatoes') >= 0) {
if(item.itemCommodity == '1120' && item.itemBrandLetter == "C") categoryItems.push(item);
}
if(window.location.hash.indexOf('Olive') >= 0) {
if(item.itemCommodity == '2120' && item.itemBrandLetter == "C") categoryItems.push(item);
}
});
var similarProduct= '';
$.each(json, function(i,item){
similarProduct = categoryItems[Math.floor(Math.random()*categoryItems.length)];
similarProduct += '<div>' + '' + '<h3 class="similarProductSubCategoryImgCaption">' + similarProduct.itemName + '</h3>' + '' + '</div>';
});
$('#productSimilar').append(similarProduct);
});
closeNav();
}
}
});
});
<section>
<div id="productsSideBar" class="sidenav">
×
<h3>View All</h3>
Tomatoes
Sauce
Olive Oil
Red Wine Vinegar
Balsamic Vinegar
Peppers
Artichokes
Olives
Beans
Capers & Pignoli Nuts
Specialties
Spices
Fish
Broth, Stocks & Soups
Breadcrumbs
Grated Cheese
</div>
</section>
<section id="productCategories">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<br>
<span class="expandSidebar" onclick="openNav()">☰ Categories</span>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div id="imagesCategoryProducts"></div>
</div>
</div>
</div>
</section>
<!-- Product Row Start -->
<section id="individualProduct">
<div class="container topmargin">
<div class="row">
<div class="col-md-7 col-sm-6">
<!-- Product Title Div -->
<div id="productTitle"></div>
<!-- Product UPC Div -->
<div class="displayInlineBlock" id="productUPC"></div>
<span class="displayInlineBlock"><h2>•</h2></span>
<!-- Product OZ Div -->
<div class="displayInlineBlock" id="productOZ"></div>
<span class="displayInlineBlock"><h2>•</h2></span>
<!-- Where to Buy Icon -->
<div class="displayInlineBlock"><h3><span rel="popover" data-content="View Product Availability"><span class="fa-stack"><i class="fa fa-square fa-stack-2x"></i><i class="fa fa-map-marker fa-stack-1x fa-inverse"></i></span></span></h3></div>
<hr>
<!-- Product Description Div -->
<div id="productDescription"></div>
<div class="row center">
<!-- Gluten Free Div -->
<div class="displayInlineBlock" id="productGlutenFree"></div>
<!-- BPA Free Div -->
<div class="displayInlineBlock" id="productBPAFree"></div>
<!-- GMO Div -->
<div class="displayInlineBlock" id="productGMOFree"></div>
</div>
</div>
<div class="col-md-5 col-sm-6">
<!-- Product Image Div -->
<div id="productImage"></div>
</div>
</div>
</div>
</section>
<!-- Product Row End -->
<section id="relatedProducts">
<div class="container topmargin">
<div class="row">
<div class="col-md-7">
<h1 class="center">Featured Recipe</h1>
<div id="featuredRecipe"></div>
</div>
<div class="col-md-5">
<h1 class="center">Similar Product</h1>
<br>
<div id="productSimilar"></div>
</div>
</div>
</div>
</section>
Ok, there are a lot of things that are wrong in the code but I am not going to into that right now. To do what you want to achieve is rather simple, you already got all the code you need, you just need to make some adjustments to make it work.
Step one. Bind the click events to the body instead of to the element.
$("body").on('click', ".showProduct", function(event){
That way, any element on the page with the class showProduct that is clicked will trigger the function, not just the elements that were bound to when the initial function ran.
The rest is really simple, you already have the similar product's information available, you just didn't put it in the data attributes when you created the element. Now obviously there are better ways of doing this... but here is how you would do it:
similarProduct = '<div>' +
'<a href="#" class="showProduct"' +
'data-itempageurl="' + similarProduct.itemFullUPC + '"' +
'data-itemgmo="' + similarProduct.itemGMOFree + '"' +
'data-itembpa="' + similarProduct.itemBPAFree + '"' +
'data-itemgluten="' + similarProduct.itemGlutenFree + '"' +
'data-itemlowsodium="' + similarProduct.itemLowSodium + '"' +
'data-itemorganic="' + similarProduct.itemOrganic + '"' +
'data-itemimage="' + similarProduct.imageURL + '"' +
'data-itemname="' + similarProduct.itemName + '"' +
'data-itemoz="' + similarProduct.itemPackSize + '"' +
'data-itemdescription="' + similarProduct.itemDescription + '"' +
'data-itemupc="' + similarProduct.itemFullUPC + '"' + '>' +
'<img class="img-responsive img-hover similarProductImagesCategory" src="' + similarProduct.imageURL + '">' +
'<h3 class="similarProductSubCategoryImgCaption">' + similarProduct.itemName +
'</h3>' + '</a>' + '</div>';
});
That should do it... now you will notice when you click on one of the similar products it should show you the information like you wanted, however it will add the new similar product to the already existing similar product list and this will keep on growing the more you click. I am sure you can figure out how to clear the list. If not just shout.
Here is the codepen: http://codepen.io/anon/pen/oYJpve
EDIT: As a side note... normally you want to store the json data with the product id as key. Then you only save the key inside the data attribute. On click you simply use the product id (key) to access the information in your stored object.
It is really easy to do. Just create a global variable
var product_data = {};
Then you populate the object when you get the data with a function. So on success of your ajax call you could have something like this:
product_data = json;
or even better you could have a function that changes the data into the structure you want:
product_data = restructureDataFunction(json);
Then you have a nice data set which you can pull from. If you need to make updates to the dataset you can do it in one place instead of in each element.
If you want, have a look at Angular 2, it should teach you a lot and also help you with future projects. It is really strong tool especially if you have html elements representing data.
I want to add this function
function list(){
var html=" "
for(var i =0; i<movements.length;i++){
html+=("<p>" + movements[i][0]+ " " + movements[i][1] + " " + movements[i][2] + "</p>")}
document.getElementById("listSpace").innerHTML = html;
}
to the click of the collapsible and display the return of list() into the textblock:
<div data-role="collapsible-set" id="myCollapsible">
<div data-role="collapsible" data-collapsed="true" >
<h3>
10 Last movements
</h3>
<div data-controltype="textblock">
<p>
<b id="listSpace">
10 last movements
</b>
</p>
</div>
</div>
</div>
Made a few changes to your code
function list() {
var html = " ", movements = [['10', 'next', 'movements'],['10', 'next', 'movements'],['10', 'next', 'movements']];
for (var i = 0; i < movements.length; i++) {
html += ("<p>" + movements[i][0] + " " + movements[i][1] + " " + movements[i][2] + "</p>")
}
document.getElementById("listSpace").innerHTML = html;
}
$(document).ready(function () {
$('div[data-role="collapsible"]').click(list);
});
check out the fiddle