I'm working on a project for school, and I'm trying to make some sort of store where you can buy fireworks.
I've managed to load in several items from a JSON file, and now I'm trying to make the shopping cart work. For this shopping cart, I want a function that can add the selected product's variables to a string and paste them in the cart.
For starters, I want to print the pressed data to the console, but it isn't working and I don't know what to do, as I'm getting S.fn.init {} in the console.
As you can see in the image, I would like the product's name and price and add it to the cart eventually.
This is the HTML I'm using for the cards you can see.
function addToCart() {
var productInfo = $(this.dataset);
console.log($(productInfo.name))
};
//toggle function
function toggle() {
$('.keyboardViewSection').toggle();
$('.touchViewSection').toggle();
var x = document.getElementById("toggleBtn");
if (x.innerHTML === "Keyboard View") {
x.innerHTML = "Touch View";
} else {
x.innerHTML = "Keyboard View";
}
}
$(document).ready(function() {
//Touchview productCard output
$(function() {
$.getJSON("assets/products/sample_products.json", function(response) {
$.each(response.data, function(i, el) {
let card = $($('#productCard-template').html());
card.find('#cardName').html(el.name);
card.find('#cardPrice').html('€' + el.price);
card.find('.productItem').attr('data-price', el.price)
.attr('data-article-number', el.article_number)
.attr('data-id', el.id)
.attr('data-name', el.name)
.attr('data-stock', el.stock)
.attr('data-categorie', el.categorie);
$('#touchViewProducts').append(card);
});
});
});
//KeyboardView Datatable output
$('[data-selected]')
$('#data-table').DataTable({
"paging": false,
"ajax": "assets/products/sample_products.json",
"columns": [{
"data": "article_number"
},
{
"data": "name"
},
{
"data": "stock"
},
{
"data": "price",
render: $.fn.dataTable.render.number(',', '.', 2, '€ ')
},
{
"defaultContent": "<button class='addToCart'>Add to Cart</button><button class='addFree'>Add Free</button>"
}
]
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-3 productCard" id="productCard">
<a href="#" class="productItem" onclick="addToCart()">
<div class="card">
<img src="assets/images/Firecracker.jpg" alt="Avatar" style="width: 100%; height: 8vh;">
<div class="container">
<div class="row" style="height: 6vh; max-width: 20ch;">
<p id="cardName"> </p>
</div>
<div class="row" style="height: 50%">
<b><p id="cardPrice"></p></b>
</div>
</div>
</div>
</a>
</div>
There's a few issues:
You need to remove this onclick="addToCart()" and add it here:
.attr('data-categorie', el.categorie).on('click',addToCard);
Then change function addToCart(){ to function addToCart(event){
and finally, instead of using $(this.dataset) try using $(this).data().
You could also use $(event.target).data().
You might also want the test if the <a> tag or <img> tag was the event.target. If it was the image, then you can use $(event.target).parent().data().
Related
I want to sort my JSON by date, and if there are multiple entries for a specific date, group all of them into the specific date.
This is my JSON:
[
{
"id":"3",
"time":"20:00",
"hometeam":"AC Milan",
"awayteam":"Juventus",
"prediction":"Under 2.5",
"odds":"1.75",
"competition":"Serie A",
"status":"lost",
"date":"01-11-2019"
},
{
"id":"4",
"time":"21:00",
"hometeam":"FCSB",
"awayteam":"Dinamo",
"prediction":"Draw",
"odds":"1.12",
"competition":"Liga 1",
"status":"",
"date":"01-11-2019"
},
{
"id":"1",
"time":"16:00",
"hometeam":"Chelsea",
"awayteam":"Arsenal",
"prediction":"Over 2.5",
"odds":"1.32",
"competition":"Premier League",
"status":"won",
"date":"31-10-2019"
},
{
"id":"2",
"time":"18:00",
"hometeam":"Manchester United",
"awayteam":"Liverpool",
"prediction":"1x2",
"odds":"1.45",
"competition":"Premier League",
"status":"won",
"date":"31-10-2019"
}
]
I want to order my JSON by date, and then have every match grouped by specific date and display them in HTML. So far, I'm displaying these 4 games, but I'm adding the date to every game; I would like to have the date, then the 2 games from 01-11-2019, again the date, 31-10-2019, then the rest of the 2 matches.
Here's the AJAX and HTML:
function updateList() {
jQuery.ajax({
type: "GET",
url: url
dataType: 'json',
timeout: 5000,
crossDomain: true,
cache: false,
success: function(data) {
console.log(JSON.stringify(data));
var groupedData = _.groupBy(data, function(d){return d.date});
//console.log(groupedData);
var htmlText = data.map(function(o){
return `
<div class="norm"><i class="icon-hourglass-time"></i>${o.date}</div>
<ul class="stage clearfix">
<li class="scene">
<!-- <div class="trigger"></div> -->
<div class="face" ontouchend="return true">
<a class="calendar-hour poster tasklist-gray">
<div class="max-constrain">
<div class="first-20">
<div class="cal-from"><strong>${o.time} <small>GMT</small></strong>
</div>
</div>
<div class="second-45">
<div class="teams">${o.hometeam}
<br><small>vs</small>
<br>${o.awayteam}</div><em><i class="fa fa-map-marker"></i>${o.competition}</em>
</div>
<div class="third-35 last-column">
<div class="over-under">
<div class="over-under-icon">
<div class="over-under-text-over uppercase">
<div class="over-under-number">${o.prediction}</div>
<div class="odd-number">
${o.odds}
</div>
</div>
<div class="touch-section uppercase"><span class="statusValue">${o.status}</span></div>
</div>
</div>
</div>
</div>
</a>
<div class="info">
<div class="result-top-unch uppercase"><i class="fa fa-pause"></i>…</div>
</div>
</div>
</li>
</ul>
`;
});
jQuery('.container-fullscreen').append(htmlText);
},
error: function(data) {
console.log(JSON.stringify(data));
}
});
}
Thanks for the help!
Actually what you want to do has to be done in two steps.
First, group your objects by date, you can do this with lodash, since it's already in your code.
With an ES6 approach, you could do this by defining the following function:
function groupBy(list, keyGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
return map;
}
It takes two arguments: your array and the function that'll be used to verify on which property it should group your data.
matchMap = groupBy(foo, match => match.date)
You have plenty example avalaible on SO, i checked this post
Then you just have to sort the array by dates:
let matchArray = Array.from(matchMap )
const sortedArray = matchArray.sort( (a, b) => {
const dateArrayA = a[1][0].date.split('-');
const dateArrayB = b[1][0].date.split('-');
return new Date(dateArrayA[2], dateArrayA[1]-1, dateArrayA[0]) > new Date(dateArrayB[2], dateArrayB[1]-1, dateArrayB[0])
})
since the date property is not a valid date but a string, you have to reconstruct it when comparing the different entries.
Then the result will be a dictionary with the date as key and ordered by it.
EDIT
Fetching data:
for(i=0;i<matchArray.length;i++)
{
for(j=0;j<matchArray[i][1].length;j++){
const currentMatch = matchArray[i][1][j];
//Your display logic
}
}
Hope it helps !
I am making an AngularJs survey application.
I want to show tasks one by one. And every task can have one or multiple questions with radio button answers. And I want to save question+answer pair in the new array.
If I want to show only one question per task than I was able to get answer values from radio buttons and push then into answer array. But as I have multiple questions and multiple radio button groups per page, I can't find a way to get the selected radio buttons values and push them into the answers array. I have read that ng-model can solve this, but I couldn't figure how.
This is what I have so far: https://jsfiddle.net/8qfom9th
<div ng-app="surveyApp" ng-controller="surveyCtrl">
<div ng-repeat="questionSet in questionSet">
<div ng-if="question_index == $index">
<div ng-repeat="onePageQuestions in questionSet.onePageQuestions">
<div ng-repeat="question in onePageQuestions.question">
{{question.description}}
<form action="">
<div ng-repeat="options in question.options">
<input type="radio" name="gender" ng-model="question.random" ng-value="options.answer"> {{options.answer}}
</div>
</form>
</div>
</div>
</div>
</div>
<hr>
<button ng-click="next(); submitAnswers()">Next</button>
It's actually pretty simple buddy.
You can get the value of the selected button by using the checked property. Since only one radio button can be selected from a group, you would be able to get the value of the selected one easily using this property in an if loop within the javascript.
Since you have given the options of the radio buttons a name already, i.e., gender. You can simply get all the options elements, using the following:
var options = document.getElementsByName('gender');
var option_value; //to get the selected value
The next step is to loop through all the buttons and check which of those is selected.. To loop through them use a for loop as follows: for (var i = 0; i < options.length; i++) {...}
To check if it is selected or not, use the checked attribute as follows:
if (options[i].checked) {
option_value = options[i].value;
}
I'm not sure what you intend to do with those values, hence I have assumed that you need to display those and to do that just create another element, like a <div> and give it an ID. And then just add the selected option value to that element. Should be something like this:
HTML: <div id="selected">The selected options are:</div>
JS:document.getElementById('selected').innerHTML += "<br>" + option_value;
Updated your fiddle.
Or if you want to check it right here,
here is the updated code:
var app = angular.module('surveyApp', []);
app.controller('surveyCtrl', function($scope) {
$scope.questionSet = [{
onePageQuestions: [{
question: [{
description: 'question#1?',
options: [{
answer: 'answer#1'
}, {
answer: 'answer#2'
}, {
answer: 'answer#3'
}]
},
{
description: 'question#2?',
options: [{
answer: 'answer#4'
}, {
answer: 'answer#5'
}, {
answer: 'answer#6'
}]
}
]
}]
},
{
onePageQuestions: [{
question: [{
description: 'question#3?',
options: [{
answer: 'answer#7'
}, {
answer: 'answer#8'
}, {
answer: 'answer#9'
}]
}]
}]
}
];
$scope.question_index = 0;
$scope.next = function() {
if ($scope.question_index >= $scope.questionSet.length - 1) {
$scope.question_index = 0;
} else {
$scope.question_index++;
}
};
$scope.submitAnswers = function() {
var options = document.getElementsByName('gender');
var option_value;
for (var i = 0; i < options.length; i++) {
if (options[i].checked) {
option_value = options[i].value;
document.getElementById('selected').innerHTML += "<br>" + option_value;
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="surveyApp" ng-controller="surveyCtrl">
<div ng-repeat="questionSet in questionSet">
<div ng-if="question_index == $index">
<div ng-repeat="onePageQuestions in questionSet.onePageQuestions">
<div ng-repeat="question in onePageQuestions.question">
{{question.description}}
<form action="">
<div ng-repeat="options in question.options">
<input type="radio" name="gender" ng-model="question.random" ng-value="options.answer"> {{options.answer}}
</div>
</form>
</div>
</div>
</div>
</div>
<hr>
<button ng-click="next(); submitAnswers()">Next</button>
<hr>
<div id="selected">The selected options are:
</div>
</div>
Use parent.answer for ng-model for dynamic radio button.
And for your use case I have added one saveAnswers functions to manipulate and save users answers.
Below is the code for your use case demo, run it and see updated questionSet in console.
var app = angular.module('surveyApp', []);
app.controller('surveyCtrl', function($scope) {
$scope.answer = '';
$scope.saveAnswers = function(description, options) {
$scope.questionSet.map(function(value, key) {
value.onePageQuestions.map(function(item, index) {
item.question.map(function(question, count) {
if (question.description === description.description) {
question.answer = options;
}
})
})
})
}
$scope.questionSet = [{
onePageQuestions: [{
question: [{
description: 'question#1?',
answer: '',
options: [{
answer: 'answer#1'
}, {
answer: 'answer#2'
}, {
answer: 'answer#3'
}]
},
{
description: 'question#2?',
answer: '',
options: [{
answer: 'answer#4'
}, {
answer: 'answer#5'
}, {
answer: 'answer#6'
}]
}
]
}]
},
{
onePageQuestions: [{
question: [{
description: 'question#3?',
answer: '',
options: [{
answer: 'answer#7'
}, {
answer: 'answer#8'
}, {
answer: 'answer#9'
}]
}]
}]
}
];
$scope.question_index = 0;
$scope.next = function() {
if ($scope.question_index >= $scope.questionSet.length - 1) {
$scope.question_index = 0;
} else {
$scope.question_index++;
}
};
$scope.submitAnswers = function() {
console.log($scope.questionSet)
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="surveyApp" ng-controller="surveyCtrl">
<div ng-repeat="questionSet in questionSet">
<div ng-if="question_index == $index">
<div ng-repeat="onePageQuestions in questionSet.onePageQuestions">
<div ng-repeat="question in onePageQuestions.question">
{{question.description}}
<form action="">
<div ng-repeat="options in question.options">
<input ng-change="saveAnswers(question,options.answer)" type="radio" name="gender" ng-model="$parent.answer" ng-value="options.answer"> {{options.answer}}
</div>
</form>
</div>
</div>
</div>
</div>
<hr>
<button ng-click="next()">Next</button>
<button ng-click="submitAnswers()"> Submit</button>
Hope this will help you!
I have a main page and there are items on the page. When I click "Order Now" on an item, an HTML page slides in over a portion of the page to show the item's details. I am having trouble linking the item clicked with an item inside an array of objects containing the details for each item so I can show the details on the page that slides over.
Here's the main page:
<div class="col-md-4 col-sm-6">
<div class="shop-item">
<div class="shop-thumbnail">
<img src="img/originalImage.jpg" alt="">
</div>
<div class="shop-item-footer">
<div class="shop-item-details">
<h3 class="shop-item-title">Original Title</h3>
<span class="shop-item-price">
$50.00
</span>
</div>
<div class="shop-item-order-btn">
Order Now
</div>
</div>
</div>
</div>
The page slides over fine, but I can't seem to get the image to change. The html file that has the info that slides out onto the screen is all encompassed into an article tag. Here's the top snippet of the HTML with the image that I can't seem to get to change.
<article class="order-details">
<div class="order-totals">
<div class="product-image">
<!-- ID for image -->
<img id="pageOrder" src="../img/Image1.jpg" alt="">
</div>
</div>
</article>
This is my JS so far that's not working.
var items = [{ name: 'Black', cost: '$10.00', id: '001', src: '../img/Black.jpg' }, { name: 'Something', cost: '$10.00', id: '002', src: '../img/image2.jpg' },
function changeImage() {
for (var i = 0; i >= items.count; i++) {
if (i = items.count) {
document.getElementById('pageOrder').src = items.src;
}
}
};
If I understand you correctly, when you click the order button, you can find the item by id in items by reading the data-id property on the order button that was clicked and then access the properties from that item like so:
To get this working with your specific scenario, you will have to modify some functions that you did not include in your original question, but I dug up from the link you provided in the comments. The code would look like the following:
var items = [{
name: 'Black',
cost: '50.00',
id: '001',
src: 'img/Black2.jpg'
}, {
name: 'Red',
cost: '50.00',
id: '002',
src: 'img/BloodRed2.jpg'
}, {
name: 'Desert Fox',
cost: '50.00',
id: '003',
src: 'img/DesertFox.jpg'
}];
// Single Post via Ajax
//------------------------------------------------------------------------------
var ajaxLoadLink = $('.ajax-load-link'),
orderBackdrop = $('.order-content-backdrop'),
orderContainer = $('.order-content-wrap'),
orderContentWrap = $('.order-content-wrap .inner'),
orderContent = $('.order-content-wrap .inner .order-content'),
closeBtn = $('.order-content-wrap .close-btn'),
orderPreloader = $('.order-content-wrap .preloader');
// Open Order
function openOrder(itemDetails) {
$('body').addClass('order-content-open');
orderBackdrop.addClass('active');
orderContainer.addClass('open');
orderPreloader.addClass('active');
orderContentWrap.addClass("loaded");
setTimeout(function() {
orderPreloader.removeClass('active');
// insert data from itemDetails into their respective places on the form
$(".order-content-wrap .order-details .product-image img").attr("src", itemDetails.src);
$(".order-content-wrap .order-details .product-image img").attr("alt", itemDetails.name);
$(".order-content-wrap .product-title").text(itemDetails.name);
$(".order-content-wrap .price i").text(itemDetails.cost);
$(".order-content-wrap .total-cost i").text(itemDetails.cost);
}, 900);
}
// Close Order
function closeOrder() {
$('body').removeClass('order-content-open');
orderBackdrop.removeClass('active');
orderContainer.removeClass('open');
orderContentWrap.removeClass('loaded');
}
ajaxLoadLink.on('click', function(e) {
var itemDetails = items.find(item => item.id === $(this).attr('data-id'));
openOrder(itemDetails);
e.preventDefault();
});
Working Demo
Code is too long to put in a stack snippet
Make sure to press "Run with JS" when you load the jsbin
I am trying to dynamically create a list of applicants in my HTML. I have a list of applicant saved in JSON format that I am reading in. I have an HTML template of the applicant "tile" that I read in, populate and then append to the page for each applicant.
My template:
<div>
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
My JSON data:
{
"applicants" : [
{
"name" : "John Smith",
"email" : "email#gmail.com",
"gender" : "Male",
"age" : "22"
}
]
}
My jQuery:
$.get("applicants.json", function(json) {
json.applicants.forEach(function(applicant) {
var newApplicant = $(templates).find("#applicant").html();
$(newApplicant).find(".name").append(applicant.name);
$(newApplicant).find(".email").append(applicant.email);
$(newApplicant).find(".gender").append(applicant.gender);
$(newApplicant).find(".age").append(applicant.age);
$(newApplicant).appendTo(".applicant-list");
});
});
After running this code, I am just getting the template back without the JSON information.
I have tried placing a console.log() after appending applicant.name but there is still no change to newApplicant.
Something else I tried was console.log($(newApplicant).find(".name").append(applicant.name).html()); which showed me that the .name is being populated but those changes are not persisting.
Can anyone see what I am doing wrong?
Thanks.
I am not sure if forEach would be a right one. You can use jQuery's $.each function to loop in an array with this being referred as the current iterated object:
$.each(json.applicants, function () {
var newApplicant = $("body").find("#applicant > div").clone();
newApplicant.find(".name").append(this.name);
newApplicant.find(".email").append(this.email);
newApplicant.find(".gender").append(this.gender);
newApplicant.find(".age").append(this.age);
$(newApplicant).appendTo(".applicant-list");
});
Snippet
$(function () {
json = {
"applicants" : [
{
"name" : "Nicholas Robinson",
"email" : "ntrpilot#gmail.com",
"gender" : "Male",
"age" : "22"
}
]
};
$.each(json.applicants, function () {
var newApplicant = $("body").find("#applicant > div").clone();
newApplicant.find(".name").append(this.name);
newApplicant.find(".email").append(this.email);
newApplicant.find(".gender").append(this.gender);
newApplicant.find(".age").append(this.age);
$(newApplicant).appendTo(".applicant-list");
});
});
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<div id="applicant">
<div>
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
</div>
<div class="applicant-list"></div>
In the question you omitted two HTML elements that instead you mention in the jQuery code, so according to the latter, and correct me if I'm wrong, the HTML should look like that
<div class="applicant-list">
<div class="applicant">
<div class="name"></div>
<div class="age"></div>
<div class="gender"></div>
<div class="email"><i class="fa fa-envelope"></i></div>
</div>
</div>
Then, in the jQuery you should either use your $.get() function and then parse or use instead $.getJSON()
$.getJSON("applicants.json", function(json) {
json.applicants.forEach(function(applicant) {
var newApplicant = $('body').find(".applicant").clone();
$(newApplicant).find(".name").append(applicant.name);
$(newApplicant).find(".email").append(applicant.email);
$(newApplicant).find(".gender").append(applicant.gender);
$(newApplicant).find(".age").append(applicant.age);
$(newApplicant).appendTo(".applicant-list");
});
});
I have a dojo combobox which when the options are changed i need to populate a related second combo box
which is co dependent on the value of the first combo box. How can i achieve this. The code i have tried so far is below
html code:
<div class="gis_SearchDijit">
<div class="formContainer">
<div data-dojo-type="dijit.form.Form" data-dojo-attach-point="searchFormDijit">
<table cellspacing="5" style="width:100%; height: 49px;">
<tr>
<td>
<label for="Customer">Customer:</label>
<div data-dojo-type="dijit.form.ComboBox" id="Customer"></div> <br />
<label for="Attributes">Search Attribute:</label>
<div data-dojo-type="dijit.form.ComboBox" id="Attributes"></div>
<br />
Enter Attribute Value:<input id="searchText" type="text" data-dojo-type="dijit.form.ValidationTextBox" data-dojo-props="name:'searchText',trim:true,required:true,style:'width:100%;'"
/>
</td>
</tr>
</table>
</div>
</div>
<div class="buttonActionBar">
<div data-dojo-type="dijit.form.Button" data-dojo-props="busyLabel:'searching',iconClass:'searchIcon'" data-dojo-attach-event="click:search">
Search
</div>
</div>
postCreate: function () {
this.inherited(arguments);
this.populateCmbCustomer(Memory);
var comboBoxDigit = registry.byId("Customer");
comboBoxDigit.on('change', function (evt) {
alert('on change'); //This alert is triggerd
this.populateCmbCustomerAttribute(Memory);
});
populateCmbCustomer: function (Memory) {
var stateStore = new Memory({
data: [
{ name: "Cust Data", id: "CUST" },
{ name: "Owner Data", id: "Owner" },
{ name: "Applicant", id: "Applicant" }
]
});
var comboBoxDigit = registry.byId("Customer");
//console.log("COMBO: ", comboBoxDigit);
comboBoxDigit.set("store", stateStore);
},
populateCmbCustomerAttribute: function (Memory) {
var custAttribute = new Memory({
data: [
{ name: "Custid", id: "Cust" },
{ name: "Applicant Id", id: "Applicant" },
{ name: "Owner_Id", id: "Owner" }
]
});
var CmbCustomerAttribute = registry.byId("Attributes");
CmbCustomerAttribute.set("store", custAttribute);
},
Note: the above is just part of the code of my widjet.js.
I am able to load the first combobox with the options. So now when i chose 'Cust Data' in my first combobox then custid should be the only option in second combo box. In the same way Owner Data in first then Owner_id in second...But so far i am not able to populate the second combo-box.. Can some one please guide me
Than You in advance
you should use the query property of the second combo it should look something like this
comboBoxDigit.on('change', function (evt) {
var CmbCustomerAttribute = registry.byId("Attributes");
CmbCustomerAttribute.set("query", {filteringProperty: this.get('value')}); //if you dont understand this check out the stores tutorials
});
EDIT: tutorials referenced in above code snippet helps clear up the ambiguity of "filteringProperty" quite a bit.
I would also recomend to populate your sencond combo from the beggining with something like this
var CmbCustomerAttribute = registry.byId("Attributes");
CmbCustomerAttribute.set("store", store);
CmbCustomerAttribute.set("query", {id:'nonExistantId'}); //so nothing shows in the combo
I think somthing like this is what you are seraching for, any doubts just ask. as cant say mucho more whitout a fiddle or actual code