So I kept sketching out algorithms to see how this would work. Kept hitting my head on the keyboard because frankly, nothing seems to work. Basically the hardcoded HTML looks like this:
<div class="row">
<div class="column">
<a href="products.html#drinks"><div id="drinks">
<h2>Drinks</h2>
</div></a>
</div>
<div class="column">
<a href="products.html#preppedfood"><div id="preppedfood">
<h2>Prepped Food</h2>
</div></a>
</div>
<div class="column">
<a href="products.html#coffee"><div id="coffee">
<h2>Coffee Machines</h2>
</div></a>
</div>
<div class="column">
<a href="products.html#snacks"><div id="snacks">
<h2>Snacks</h2>
</div></a>
</div>
</div>
<div class="row">
<div class="column">
<a href="products.html#nuts"><div id="nuts">
<h2>Nuts of All Kinds</h2>
</div></a>
</div>...till the last div class="row" and it's column divs
So the HTML works fine, here's a screenshot:
This is how I want it to look!
But using VueJS so that I can "DRY out" my markup, I'm using the v-for directive like this in the Prods.vue component. Here's the template markup:
<div class="row" v-for="(data, index) in images" v-bind:key="data" v-if="data.ImageId%4 == 0">
<h1>{{index}}</h1>
<div
class="column"
v-for="data in images"
v-bind:key="data"
v-if="computedIndex(index) *4 >= index && index < (computedIndex(index)+1) / 4"
v-lazy-container="{ selector: 'data' }"
>
<a :href="'products/#'+data.Name">
<h4>{{data.H2}}</h4>
<img :src="'../../../static/products/'+data.Name+'.png'" :alt="data.Name+'.png'" />
</a>
</div>
</div>
And the script:
<script>
import Prods from '../../../other/jsons/products.json'
import VueLazyload from 'vue-lazyload'
export default {
data() {
return {images: Prods}
},
methods: {
computedIndex(index) {
return Math.trunc(index/4)
}
}
}
//v-for in row
//v-for in column
</script>
And this is what shows up instead:
enter image description here
Instead of juggling with indices, it seems more straightforward to me to compute the shape of your array to suit your DOM:
computed:
imageRows () {
return this.images.reduce((acc, n, i) => {
i % 4 ? acc[acc.length - 1].push(n) : acc.push([n])
return acc
}, [])
}
To be used something like this:
<table>
<tr v-for="(imageRow, i) in imageRows" :key="i">
<td v-for="image in imageRow" :key="image">
<foo/>
</td>
</tr>
</table>
(Your data seems tabular to me, so I'm showing this example as a <table>, but you can substitute that with <div>'s if you prefer, of course.)
Related
This is my first time using react and I am sure that code given is probably not using react's best practices but I am just playing around with it to understand it for now, my problem is that I am trying to access the divs and paragraphs inside the modal but document querySelector returns null. Any ideas? Thanks
moreInfo(movie) {
const movieModalImg = document.querySelector(".movieModalImg");
const movieModalTitle = document.querySelector(".movieModalTitle");
const movieModalRunTimeNum = document.querySelector(
".movieModalRunTimeNum"
);
}
render() {
return (
<div>
<div id="modal">
<Modal
isOpen={this.state.setIsOpen}
onRequestClose={this.closeModal.bind(this)}
contentLabel="Example Modal"
>
<a className="closeModalBtn" onClick={this.closeModal} href={"#"}>
×
</a>
<div className="modal-wrapper">
<div>
<img src={moviePoster} className="movieModalImg" alt=""></img>
</div>
<p className="movieModalTitle"></p>
<div className="movieModalRunTime">
<h4>Runtime:</h4>
<p className="movieModalRunTimeNum"></p>
<p>Minutes</p>
</div>
<div className="movieModalProductionCountry">
<h4>Production Countries:</h4>
<p className="movieModalProductionCountries"></p>
</div>
<div className="movieModalVoteCount">
<h4>Vote Count:</h4>
<p className="movieModalVoteCountNum"></p>
</div>
<div className="movieModalRevenew">
<h4>Revenew:</h4>
<p className="movieModalRevenewNum"></p>
<p>$</p>
</div>
<div className="movieModalBudget">
<h4>Budget:</h4>
<p className="movieModalBudgetNum"></p>
<p>$</p>
</div>
</div>
</Modal>
</div>
<a
href="#"
className="movieCoverMoreInfo"
onClick={this.moreInfo.bind(this)}
>
<img className="moreInfoIcon" src={info} alt=""></img>
More Info
</a>
</div>
);
}
I am making a webpage where i fetch movies using an api and i am trying to list the movie posters using the materilize css card in the same row, but it only gets listed on top of each other as a column.
app.js
class App extends React.Component {
constructor(props) {
super(props);
this.state={};
this.performSearch()
}
performSearch(){
$.ajax({
url:urlString,
success:(searchResults) =>{
console.log("Feteched succesfully");
//console.log(searchResults);
const results = searchResults.results
//console.log(results[0])
const movieRows = [];
results.forEach((movie) =>{
// console.log(movie.title);
console.log(movie.poster_path)
const movieRow = <MovieLists movie={movie}/>
movieRows.push(movieRow);
})
this.setState({rows:movieRows})
},
error:(xhr,status,err) =>{
console.error("Failed to fetch");
}
})
}
render() {
return (
<div className="App">
{this.state.rows}
</div>
);
}
}
export default App;
MovieLists.js
<div className="container">
<div className="row">
<div className="col s12">
<Movie key ={props.movie.id} image={props.movie.poster_path}
title={props.movie.title}/>
</div>
</div>
</div>
Movie.js
<div className="col s12 m6 l3">
<div className="card" >
<div className="card-image waves-effect waves-block waves-dark">
{
props.image == null ?
<img src ={'https://www.google.com/url?sa=i&url=https%3A%2F%2Fmarket.ionicframework.com%2Fstarters%2Fomdb-search&psig=AOvVaw3Beb0rUUVxt3OsEfwzu07Q&ust=1585542435018000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCJj8kIPsvugCFQAAAAAdAAAAABAD'}
alt="card image"
style={{width:"100%",height:360}}/>
:
<img src ={`http://image.tmdb.org/t/p/w185${props.image}`}
alt="card image"
style={{width:"100%",height:360}}/>
}
<div className="card-content">
<p>
</p>
</div>
</div>
</div>
</div>
The movieLists component lists the movie component on top of each other, i am trying to find the way to list them horizontally responsively.
Remember to always use the correct grid structure, which is:
.container > .row > .col
All cols MUST sit in rows to behave responsively. Adding a .row div around the movie.js output will fix your problem.
<div class="container">
<div class="row">
<div class="col">
[content goes here]
</div>
<div class="col">
[content goes here]
</div>
</div>
</div>
See this answer from yesterday:
Materialize grid s12 not working in mobile view or on Chrome's developer tools
Codepen with a single .row div to fix your problem (note I've had to chnage className to class):
https://codepen.io/doughballs/pen/eYNbwOQ
https://materializecss.com/grid.html
I got a list of Pizza, I would like to automatically import their name in a html element.
I'm wondering what is the best way to work with object or values like that. I was thinking to use Razor language (because I work on ASP.net)but I'm not sure maybe JavaScript could do the job too...?
Could you give me a short example of what my code would look like.
<div class="col-sm-6 col-lg-3">
<div class="thumbnail">
<img src="http://lorempixel.com/240/200" alt="">
<div class="caption">
**
<h3>Pizza's name</h3>
**
<p>Lorem</p>
<p>Ajouter à ma commande</p>
</div>
</div>
</div>
javascript could do the job too.
Yes, you can do that with two approaches, using razor or using java script.
If you want to use razor:
<div class="caption">
#foreach (var item in ListOfPizza)
{
<h3>#item.Name</h3>**
}
Or you can use javascript:
$(document).ready(function() {
var testData = [{
"Name": "pizza1"
}, {
"Name": "pizza2"
}];
$.each(testData, function(i, v) {
$('.caption h3').append(v.Name+'<br>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-sm-6 col-lg-3">
<div class="thumbnail">
<img src="http://lorempixel.com/240/200" alt="">
<div class="caption">
**<h3></h3>**
<p>Lorem</p>
<p>Ajouter à ma commande</p>
</div>
</div>
</div>
Note: Here i used test data, which needs to change accordingly!
I'm not sure how to ask this question so below is an visualization of what I want to achieve.
Please let me know if there is anything I can clarify!
Clarification:
At slide one, image 01 and image 02 are visible. Only when the person clicks on the images does the text and title div become visible. More importantly, the text box must be coherent with the page-wrapper. For example, if I were to set the text div to float:right, it will float on the right side of the page-wrapper.
Thank you in advance.
You need some javascript to get this behaviour i think. You can try something like this:
Everything in a little bit pseudo code.
HTML:
<img src="..." class="img1 clickImage">
<img src="..." class="img2 clickImage">
<div class="imageTitles">
<div class="img1 imgTitle">TITLETEXT</div>
<div class="img2 imgTitle">TITLETEXT</div>
</div>
<div class="imageInformations">
<div class="img1 imgInformation">INFORMATION img1</div>
<div class="img2 imgInformation">INFORMATION img2</div>
</div>
And some jQuery:
jQuery('.clickImage').on('click', function() {
var imgNumber = jQuery(this).getClass().replace('clickImage', '');
jQuery('imageTitles .imgTitle').hide(); //hide all image Titles
jQuery('imageTitles .imgTitle.' + imgNumber).show(); //show title for e.g. img1
//repeat this for imgInformation
});
Everything a little bit rough, but i hope it gives you an idea what you need to do.
EDIT:
Code now looks like this:
HTML:
<img src="http://media.tumblr.com/tumblr_mcepyv1Qfv1ru82ue.jpg" class="img1 clickImage">
<img src="http://media.tumblr.com/tumblr_mcf11pk4nj1ru82ue.jpg" class="img2 clickImage">
<div id="page-wrap">
<div class="imageTitles">
<div class="img1 imgTitle">TITLETEXT</div>
<div class="img2 imgTitle">TITLETEXT</div>
</div>
<div class="imageInformations">
<div class="img1 imgInformation">INFORMATION img1</div>
<div class="img2 imgInformation">INFORMATION img2</div>
</div>
</div>
JS:
jQuery('.imageTitles .imgTitle').hide();
jQuery('.imageInformations .imgInformation').hide();
jQuery('.clickImage').on('click', function () {
var imgNumber = jQuery(this).attr("class").replace('clickImage', '');
jQuery('.imageTitles .imgTitle').hide(); //hide all image Titles
jQuery('.imageTitles .imgTitle.' + imgNumber).show(); //show title for e.g. img1
jQuery('.imageInformations .imgInformation').hide();
jQuery('.imageInformations .imgInformation.' + imgNumber).show();
});
There are many ways to achieve this.
1) with every thing static, ie info about image is already available in the page in different div's.
ex: working
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.switch').hide();
});
function myInfo(myId)
{
$('.switch').hide();
$('#title'+myId).show();
$('#description'+myId).show();
}
</script>
<table>
<tr>
<td>
<!-- Images -->
<img onclick="return myInfo('1')" id='image1' height="60" width="60" src="http://static3.businessinsider.com/image/52cddfb169beddee2a6c2246/the-29-coolest-us-air-force-images-of-the-year.jpg" alt="Image1"><br/>
<img onclick="return myInfo('2')" id='image1' height="60" width="60" src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcR6I83EILo3XKIsqZ-0Q5JAEw38xGzsy1g_iKImqjBrMVaOHYb4Zg" alt="Image2">
</td>
<td>
<div id="title1" class="switch"> Image 1</div>
<div id="title2" class="switch"> Image 2</div>
</td>
<td>
<div id="description1" class="switch"> Information about Image 1 </div>
<div id="description2" class="switch"> Information about Image 2 </div>
</td>
</tr>
</table>
2) You can achieve this using AJAX calls for image information, in this case only 1 div for title and 1 for info is enough i you want to use else 1 div is enough. On click of image make an AJAX call to get the image info and display it in the div.
These are 2 ways and there are many more.
I am building a product grid built upon AngularJS data - where there will be images and product details (text)
The text sometimes extends to the 2nd line, causing havoc.
Here is my code:
<div class="row">
<div data-ng-repeat="s in Results">
<div class="col-xs-4">
<a href="#" class="thumbnail">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
This is what it looks like:
How do I fix it so that <div>s all have the same height?
I tried to look online for solutions, but I think I am 50% there. Please help.
Note: I Don't want to hide content.
This is what I ended up doing for anyone who stumbles on this again in the future.
Javascript
function ResizeToLargestElement(element) {
var maxHeight = -1;
if ($(element).length > 0) {
$(element).each(function () {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$(element).each(function () {
$(this).height(maxHeight);
});
}
}
Without AngularJS
For those who aren't using AngularJS, just call ResizeToLargestElement() when data changes or the window is resized using
$(window).resize(function() {
ResizeToLargestElement('.AutoResizeToLargestElement');
});`
With AngularJS
The idea is to call the ResizeToLargestElement() function whenever $scope.Results changes or when the window resizes.
To know when $scope.Results changed is easy, but to know when elements (that are bound to it) finished rendering is not easy. To do that, you need a AngularJS directive.
To know when the window re-sizes, use angular.element($window).on('resize', function () {...});
HTML
<div class="row">
<div data-ng-repeat="s in Results" data-ng-repeat-finished> <!--ADDED Directive-->
<div class="col-xs-4">
<a href="#" class="thumbnail AutoResizeToLargestElement"> <!--ADDED Class-->
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<!--REMOVED clearfix-->
</div>
</div>
MyDirectives.js
angular.module('myApp').directive('ngRepeatFinished', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
mycontroller.js
$scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
angular.element($window).on('resize', function () {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
Note: this requires you to include $window in the AngularJS dependency list.
I.E. angular.module('myApp').controller('....', ['...., '$window', ....]);
If you want to keep the height of each product dynamic, you will need to split the results into columns. And then use ng-if to put the right items in the right column. Every 3rd item will go into the same column. To set them to different columns, just reduce the $index by 1 for each extra column.
<div class="row">
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="$index%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-1)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-2)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
</div>
You can manually restrict the height of the div and use an overflow. Use something like
<div class="col-xs-4" style="height:200px; overflow: auto;">Content</div>
Or, you could always use a responsive table (<table class="table table-responsive">) for your layout.
The best solution for this problem is to add clearfix class to hidden divs for earch size of viewport. for example:
Large size: i want 6 columns (large desktops)
Medium size: i want 4 columns (Desktops)
Tablets: i want 3 coumns
phones: i want 2 columns
so i have the products list:
<?php $count=1; foreach($productList as $product) : ?>
<div class="item col-xs-6 col-sm-4 col-md-3 col-lg-2">
Picture and description
</div><!-- /item -->
<?php if( ($count%2)==0) {?><div class="clearfix visible-xs-block"></div><?php }?>
<?php if( ($count%3)==0) {?><div class="clearfix visible-sm-block"></div><?php }?>
<?php if( ($count%4)==0) {?><div class="clearfix visible-md-block"></div><?php }?>
<?php if( ($count%6)==0) {?><div class="clearfix visible-lg-block"></div><?php }?>
<?php $count++; endforeach?>