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
Related
i have this function which collect the image and display them in a gallery:
let gallery = document.getElementById("gallery");
let galleryItemsData = [
{
id: "UX",
img: "images/UX/BrandBoard.png",
title: "Brand Board",
},
{
id: "CMlogo",
img: "images/123CleanMe/mockup (12).png",
title: "123 Clean Me",
}
];
let generateGallery = () => {
return (gallery.innerHTML = galleryItemsData.map((x) => {
let { id, img, title, } = x;
return `
<div class="imgContainer" id="${id}" >
<p class="title">${title}</p>
<img class="galleryImg" id="${id}" src="${img}" alt="logo">
</div>
`
}).join(""));
};
generateGallery();
the problem.
how can I make a function that display the pictures in modal when the user clicks on it? I tried different options but doesn't seem to work.
what I'm trying to achieve:
I need a function that will collect the images from this function, and it will display in modal when the user clicks on the image.
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().
I am learning inherited/isolated scopes in angular directives and struck with some basic concepts. please see the plunker below.
Example.
Scenario1:
I have 2 directives (book and details). I am displaying two "Book Details" containers and toggling book name by sending custom attributes like this.
<book bookdetails="book" collapsed="yes" list="list"></book>
<book bookdetails="book1" collapsed="no" list="list"></book>
Question: Is this the right way to handle displaying things in 2 different containers?
Scenario 2:
I want to hide the author details section in container 1 but show in container2 on load. How to accomplish that?
When I use this line below it will hide and show both author details section but I want to keep it separate.
<details collapsed="yes"></details>
I know I am lacking basic skills using inherited/isolated scopes. Can someone educate me?
It's OK to use nested directives like you've used so you can do everything related to the details pane in the details controller like removing items from the books list.
If you wouldn't do any logic in details controller and just include some html I would just use ng-include.
Some points I've detected during improving your code:
Template markups are partial html files, so no need to add header, body etc. Just add your markup that you need in your directive.
I've created one model array books that you can iterate with ng-repeat and not two separate scope variables. That's easier to add more books.
I wouldn't pass the collapsed state to directive isolated scope. I would add it to the book model then you can have independent states of the details panes.
You could also create a collapsed array scope variable separate from your model and use it like ng-hide='collapsed[$index]' if you don't like to add it to your model.
Don't compare to the string yes. It makes things more complicated. It's better to use true or false.
The list you're passing is OK if you'd like to use one list for every details pane. But I think you need them independent from each other so add it to your book model.
For toggeling a value you can use the js shorthand: collapsed = !collapsed;. It takes the value of collapsed and inverts it and re-asigns it to collapsed.
Details directive: You don't need to pass attributes to a directive that doesn't use isolated scope. Instead you can directly use the inherited scope of the parent.
Note: I think you should have a look at angular-ui-bootstrap and use an accordion instead of your manually created panes later. But for learning directives your code is OK.
Please have a look at your updated code below or in this plunker.
If something is not clear, feel free to add a comment and I'll try to help.
angular.module('plunker', [])
.controller('MainCtrl', function($scope) {
$scope.books = [{
id: 0,
name: 'Building modern ASP.NET 5',
author: {
name: 'name1',
age: 31,
country: 'USA'
},
collapsed: false,
list: [{
id: 0,
name: 'book1'
}, {
id: 1,
name: 'book2'
}, {
id: 2,
name: 'book3'
}]
}, {
id: 1,
name: 'AngularJS',
author: {
name: 'name2',
age: 27,
country: 'USA'
},
collapsed: true,
list: [{
id: 0,
name: 'book1'
}, {
id: 1,
name: 'book2'
}, {
id: 2,
name: 'book3'
}]
}];
//$scope.list = ["book1", "book2", "book3"];
}).directive('book', function() {
return {
restrict: 'E',
templateUrl: 'book.html',
scope: {
bkdet: "=bookdetails"
//list: "="
//collapsed: "#"
},
controller: function($scope) {
$scope.toggleDetails = function() {
$scope.bkdet.collapsed = !$scope.bkdet.collapsed;
updateCaption();
};
function updateCaption() {
$scope.hypshowhide = $scope.bkdet.collapsed ? 'show details' : 'hide details';
}
// first run
updateCaption();
/*if ($scope.collapsed == 'yes')
{
$scope.dethide = true;
}
else {
$scope.dethide = false;
} */
//$scope.hypshowhide = 'show details';
}
}
})
.directive('details', function() {
return {
restrict: 'E',
templateUrl: 'details.html',
controller: function($scope) {
/*console.log($scope.bkdet.collapsed);
if (!$scope.bkdet.collapsed) { //== 'yes') {
$scope.dethide = true;
}
else {
$scope.dethide = false;
}*/
$scope.removeItem = function(index) {
$scope.bkdet.list.splice(index, 1);
}
}
}
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="plunker">
<div ng-controller="MainCtrl">
<div class="container">
<book bookdetails="book" ng-repeat="book in books"></book>
</div>
</div>
<script type="text/ng-template" id="book.html">
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h1>Book Details</h1>
</div>
<div class="panel-body">
<a class="pull-right" href="#" ng-click="toggleDetails(collapsed)">{{hypshowhide}}</a>
<div>
<!--ng-hide="dethide">-->
{{bkdet.name}}
</div>
<!--<details collapsed="no"></details>-->
<details></details>
</div>
</div>
</div>
</script>
<script type="text/ng-template" id="details.html">
<div class="container" ng-hide="bkdet.collapsed">
<div class="row">
<ul class="list-group list-unstyled">
<!--<li>
<h1>Author:</h1>
</li>
<li>
<ul>-->
<li>
<strong>Author</strong>
{{bkdet.author.name}}
</li>
<li>
<strong>Age</strong>
{{bkdet.author.age}}
</li>
<li>
<strong>Country</strong>
{{bkdet.author.country}}
</li>
<li>
<div ng-if="bkdet.list.length == 0">
<p>No books here!</p>
</div>
<div ng-repeat="c in bkdet.list">
<p>
{{c.name}}
<button class="btn btn-danger" ng-click="removeItem($index)">X</button>
</p>
</div>
</li>
<!--</ul>
</li>-->
</ul>
</div>
</div>
</script>
</div>
I would like to do the following. I would like to create a categories page that loads each category onto a picture. Then when a user clicks a category the parameter would show up on the url and it will search the database for photos based on that category. I will now demonstrate the code that I have.
Categories HTML File:
<template name="categories">
<div class="text-center light-container" id="categories-section">
<h1>Categories</h1>
<hr/>
{{#each categories}}
<div class="image-container">
<a href="{{pathFor route='categoryPage'}}">
<img class="freezeframe pics" src="images/app/sphere.jpg"/>
</a>
<h2><span>{{categories}}</span></h2>
</div>
{{/each}}
</div>
</template>
Categories JS File:
var categoryList = ['actions', 'animals', 'anime', 'art/design', 'cartoons/comics', 'celebrities',
'Emotions', 'Food/Drink', 'Games', 'History', 'Holidays', 'Memes', 'Movies', 'Music', 'Nature', 'News/Politics',
'Science', 'Sports', 'Technology', 'TV'];
Template.categories.helpers({
'categories':function(){
for(var i = 0; i < categoryList.length; i++){
console.log(categoryList[i]);
return categoryList[i];
}
}
});
Router JS File:
Router.route('/categories', {
name: 'categories',
template: 'categories',
fastRender: true
});
Router.route('/categories/:category', {
name: 'categoryPage',
template: 'categoryPage',
data: function(){
var category = this.params.category;
return GifsCollection.find({category: category});
},
fastRender: true
});
CategoryPage JS:
Template.categoryPage.helpers({
// Load 16 most recent ones
// When down arrow is click load another 16 more gifs
gifs: function() {
var category = this.params.category;
return GifsCollection.find({category: category}, {fields: {_id: 1, image: 1} });
}
});
Running the following code doesn't get me anywhere. I'm not sure which path to take. I can create a 'category' collection and load the helpers onto there or I can use sessions? but I'm leaning onto creating category collection however I'm pretty sure there is a much more efficient way.
Any feedback and code help would be greatly appreciated!!!
You have two small errors. One we already discussed in comments, regarding the helper. The other is in how you use the #each loop: inside of it you can just refer to this to get the string of your category.
Categories HTML File:
<template name="categories">
<div class="text-center light-container" id="categories-section">
<h1>Categories</h1>
<hr/>
{{#each categories}}
<div class="image-container">
<a href="/categories/{{this}}">
<img class="freezeframe pics" src="images/app/sphere.jpg"/>
</a>
<h2><span>{{this}}</span></h2>
</div>
{{/each}}
</div>
</template>
Categories JS File:
var categoryList = ['actions', 'animals', 'anime', 'art/design', 'cartoons/comics', 'celebrities',
'Emotions', 'Food/Drink', 'Games', 'History', 'Holidays', 'Memes', 'Movies', 'Music', 'Nature', 'News/Politics',
'Science', 'Sports', 'Technology', 'TV'];
Template.categories.helpers({
'categories':function(){
return categoryList;
}
});
I want to create an app that work like this : https://ionic-songhop.herokuapp.com
As you can see, when we click favorite button, the item will store in factory and we can invoke in another page (favorite page)
In my case : i use service to store the item data and create factory to store the pushed item.
Here's my code : (I store data in service)
.service('dataService',function(){
var service=this;
this.playerlist = [
{ name: 'Leonel Messi', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" },
{ name: 'Cristiano Ronaldo', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" },
{ name: 'Zlatan Ibrahimovic', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" },
{ name: 'Wayne Rooney', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" },
{ name: 'Michael Carrick', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" },
{ name: 'Phil Jones', ava:"https://pbs.twimg.com/profile_images/473469725981155329/E24vfxa3_400x400.jpeg" },
{ name: 'Angel di Maria', ava:"https://i.scdn.co/image/d1f58701179fe768cff26a77a46c56f291343d68" }
];
})
.factory('User', function() {
var play = { favorites: []}
play.addToFavorites = function(song) {
play.favorites.unshift(song);
}
play.removeFromFavorites = function(player, index) {
play.favorites.splice(index, 1);
}
return play;
})
Controller :
.controller('ChooseTabCtrl', function($scope, dataService, User) {
$scope.dataService=dataService;
$scope.addToFavorite = function (item) {
User.favorites.unshift(dataService.playerList.indexOf(), 1);
}
})
But when i click the favorite button on each item, the list dont show in favorite page.
Is it possible to do like this in Ionic app?
Here's my codepen : http://codepen.io/harked/pen/WvJQWp
There are a few issues with the code in your codepen...
In the controller you are referencing dataService.playerList.indexOf() when the player object is actually playerlist (all lowercase). Also, I assume you want to actually get the indexOf the player so that line needs to change to:
User.favorites.unshift(dataService.playerlist.indexOf(item));
// remove the `, 1` otherwise you'll be adding a `1` to the array everytime
and in your view, you need to change the following:
// wrong
ng-click="addToFavorite(item)"
// right
ng-click="addToFavorite(player)"
Next, in your ListTabCtrl change the following:
$scope.players=dataService;
// to
$scope.players=dataService.playerlist;
Then in the view:
<ion-item ng-repeat="player in favorites" class="item item-avatar" href="#">
<img ng-src="{{players[player].ava}}">
<h2>{{players[player].name}}</h2>
<p>Back off, man. I'm a scientist.</p>
<ion-option-button class="button-assertive" ng-click="removePlayer(player, $index)">
<i class="ion-minus-circled"></i>
</ion-option-button>
</ion-item>
I have posted a working example of your code on jsbin: http://jsbin.com/lukodukacu/edit?html,css,js,output