Responsive jQuery Equal Height Per Pair - html

I have this markup:
<div class="wrapper">
<article>A</article>
<article>B</article>
<article>C</article>
<article>D</article>
<article>E</article>
<article>F</article>
<article>G</article>
<article>H</article>
</div>
which is floated and forms a two-column list. Each article has a variable height due to its contents.
What I want is each pair should have the same height based on which of the two has the tallest height. I have found variations of equalHeights plugin but all of them force equal heights to all elements. I just need each pair to be the same height, not all elements. Is this possible or are there any existing plugin for this?
Note: Can't change the article markup because it's outputted by the CMS.
My expected output:
|-------|---------|
| A | B |
|-------|---------|
| | |
| C | D |
| | |
| | |
| | |
|-------|---------|
| | |
| E | F |
| | |
|-------|---------|

Here is a little bit of code that will set the height to the max height, splitting a block of articles by a column count, rather than any other structural method.
Demo: http://jsfiddle.net/bgWaw/
var articles = $('.wrapper article');
var columns = 2;
var cIndex = 0;
while (cIndex < articles.size()) {
var cMaxHeight = 0;
for (cColumn = 0; cColumn < columns; cColumn++) {
var cArticle = articles.eq(cIndex + cColumn);
if (cArticle.size() > 0) {
cMaxHeight = (cArticle.height() > cMaxHeight ? cArticle.height() : cMaxHeight);
}
}
articles.slice(cIndex, cIndex + columns).height(cMaxHeight);
cIndex += columns;
}
This could easily be turned in to a plugin if needed. Just a matter of making it a function in the $.fn object and using this rather than articles and passing in columns as a parameter to the function.
jQuery Plugin Version Demo: http://jsfiddle.net/bgWaw/2/
$.fn.maxSliceHeight = function(columns) {
var cIndex = 0;
while (cIndex < this.size()) {
var cMaxHeight = 0;
for (cColumn = 0; cColumn < columns; cColumn++) {
var cElem = this.eq(cIndex + cColumn);
if (cElem.size() > 0) {
cMaxHeight = (cElem.height() > cMaxHeight ? cElem.height() : cMaxHeight);
}
}
this.slice(cIndex, cIndex + columns).height(cMaxHeight);
cIndex += columns;
}
return this;
}
Example call:
$('.wrapper article').maxSliceHeight(2);

Contrary to my comment here is another method you can use:
Turn that markup into rows:
<div class="row">
<article>A</article>
<article>B</article>
</div>
<div class="row">
<article>C</article>
<article>D</article>
</div>
<div class="row">
<article>E</article>
<article>F</article>
</div>
Float the <article> elements again, but make sure each .row div has clear: both in the CSS.
That way every "row" will be the same height has the tallest content within it.

Separating by divs is a good solution if you really want always two columns, but I assume that you might want to change to three columns if the browser is wide enough. Have you looked at isotope? http://isotope.metafizzy.co/

I have found a solution for this without changing the markup: http://css-tricks.com/equal-height-blocks-in-rows/

Related

How to change the appearance of an anchor (text) by comparing 2 id?

I'm building a book-like pagination style for my website. It is composed of a 4 parts code: the text supposed to be displayed, the pages numbered, the "next" and "previous" buttons and the script to determine which part/page of the text is displayed.
var current = 1;
var totalPages = document.getElementById("pageContainer").childElementCount;
function showPages(id = 1) {
if (id < 1 || id > totalPages)
return;
curr_page = document.getElementById("page" + current);
curr_page.classList.add("pageHidden");
curr_page.classList.remove("pageDisplayed");
target_page = document.getElementById("page" + id);
target_page.classList.add("pageDisplayed");
target_page.classList.remove("pageHidden");
current = id;
}
.pageHidden
{
display: none;
}
.pageDisplayed
{
display: block;
}
<div id="pageContainer">
<div class="pageDisplayed" id="page1"><p>page 1 displayed</p></div>
<div class="pageHidden" id="page2"><p>That is the second page.</p></div>
<div class="pageHidden" id="page3"><p>And finally a third one.</p></div>
</div>
<h2>pages :
1
2
3
</h2>
<h2>
<span style="float: left;">
Previous
</span>
<span style="float: right;">
Next
</span>
</h2>
Now, I'd like to mark the actual page that is being displayed by changing the appearance of the link. For now it shows
"Pages: 1 2 3"
And I'd like it to become, for example:
"Pages: 1 [2] 3" (with a different color for the marked "[2]".
I've found ways to do that, but I couldn't make it works with the "next" and "previous" button, which, when triggered, didn't highlight the anchor number.
Basically, if the function showPages returns "page2", the anchor "2" with the id "2" should appear like that: [2].
I think it means that I have to compare the id from the page container, to the id from the pagination part... Anyone know how I can do that?
Same As you are hiding previous block and showing new block. create a css class with following css:
.page:before{
content: '['
}
.page:after{
content: ']'
}
this css will wrap any element with page class in brackets [].
Now add page class to selected page and remove from older one.
pageNum = document.getElementById("" + id);
pageNum.classList.add("page")
pageNum = document.getElementById("" + current);
pageNum.classList.remove("page")
Here is your working code.
var current = 1;
var totalPages = document.getElementById("pageContainer").childElementCount;
function showPages(id = 1) {
if (id < 1 || id > totalPages)
return;
curr_page = document.getElementById("page" + current);
curr_page.classList.add("pageHidden");
curr_page.classList.remove("pageDisplayed");
target_page = document.getElementById("page" + id);
target_page.classList.add("pageDisplayed");
target_page.classList.remove("pageHidden");
pageNum = document.getElementById("" + id);
pageNum.classList.add("page")
pageNum = document.getElementById("" + current);
pageNum.classList.remove("page")
current = id;
}
.pageHidden
{
display: none;
}
.pageDisplayed
{
display: block;
}
.page:before{
content: '['
}
.page:after{
content: ']'
}
<div id="pageContainer">
<div class="pageDisplayed" id="page1"><p>page 1 displayed</p></div>
<div class="pageHidden" id="page2"><p>That is the second page.</p></div>
<div class="pageHidden" id="page3"><p>And finally a third one.</p></div>
</div>
<h2>pages :
1
2
3
</h2>
<h2>
<span style="float: left;">
Previous
</span>
<span style="float: right;">
Next
</span>
</h2>
Here you go..

Preserve White Space

I want to preserve white space to keep every column align properly.
But sidebar auto remove any extra space, could someone give me some advise on this.
Google Sidebar
function Test1() {
var lineBrk = "<br />"
var aValues = "```"+lineBrk+
"BLB001| APPLE | O/B | 100.00"+lineBrk+
"AG010 | ORANGE| O/B | 125.25"+lineBrk+
"B123 | KIWI | O/B | 95.00"+lineBrk+
"```"
// Display a modal dialog box with custom HtmlService content.
var htmlOutput = HtmlService
.createHtmlOutput(aValues);
SpreadsheetApp.getUi().showSidebar(htmlOutput);
}
Sidebars are created using the Google Apps Script HTML service, that means that they use html and that is why Serge included a link to a question regarding the use of . Another alternative is to enclose the text lines on <pre> tags.
Below is an adaptation of the code that builds the html output to work on the stack snippet.
var lineBrk = "</pre><br />"
var aValues =
"<pre>BLB001| APPLE | O/B | 100.00"+lineBrk+
"<pre>AG010 | ORANGE| O/B | 125.25"+lineBrk+
"<pre>B123 | KIWI | O/B | 95.00"+lineBrk;
document.write(aValues);
If you're looking to display plaintext, Ruben's answer above would work. If you want some kind of formatting, using simple HTML layout styles will help.
You could interpret your table example as the following HTML:
<div id="table">
<div class="row">
<div class="col">BLB001</div>
<div class="col">Apple</div>
<div class="col">0/B</div>
<div class="col">100.00</div>
</div>
<div class="row">
<div class="col">AG010</div>
<div class="col">Orange</div>
<div class="col">0/B</div>
<div class="col">125.25</div>
</div>
<div class="row">
<div class="col">B123</div>
<div class="col">Kiwi</div>
<div class="col">0/B</div>
<div class="col">95.00</div>
</div>
</div>
Then, either in a style tag or a linked CSS file, set the display:
#table {
display: table;
table-layout:fixed;
width: 300px; /* This could be any width you'd like */
font-family:monospace;
}
.row { display: table-row; }
.col { display: table-cell; }
You can also set borders, if you want them. The nice thing about using this method is that you can populate any number of rows or cells using an apps script loop if your data is variable.
Here's a very simple CodePen demo showing the layout only.

Text alignment using whitespace and the pre tag

How do I align add this text properly?
my code :
data[0]=hello 123
data[1]=hellowq 345
data[2]=heloowaaa 678
for (var i = 0; i < data.length; i++) {
obj += "<pre><li>" + data[i] + "</li></pre>";
}
my actual input :
hello 123
hellowq 345
heloowaaa 678
output :
hello 123
hellowq 345
heloowaaa 678
I would like to get output like this:
hello 123
hellowq 345
heloowaaa 678
You have invalid HTML, the only valid child of either a <ul> or <ol> is an <li> element; the <pre> elements should be within the <li> elements:
for (var j = 0; j < data.length; j++) {
obj += "<li><pre>" + data[i] + "</pre></li>";
}
And the CSS for the <pre> elements set to white-space: pre-wrap (or similar), this is the usual default styling of that element, but it's possible that the defaults have been overwritten or set differently in your browser.
As I claimed in the comments, you probably add the same amount of spaces to each label/value-pair. The solution is probably in the code we don't see where you would have to subtract the length of your label+value from the number of whitespaces generated.
A better way to do this would be to layout in html/css instead. A quick and dirty example.
HTML
<ul>
<li>Domdido <span class="value">$8</span></li>
<li>Domdido123 <span class="value">$8</span></li>
</ul>
CSS:
ul{list-style:none;padding-left:0;
width:50%;
}
.value{float:right;}
http://jsfiddle.net/tqs2rvrd/

MediaWiki: Forcing new line in templates

I'm going to standardize some picture galleries at some non-public wiki using pure templates. The legacy wiki picture/thumbnail galleries are specified with a lot of boilerplate code (it renders a gallery of pictures with thumbnails underneath):
<center>
<gallery widths="120px" heights="170px" perrow="5">
Image:Pic1.jpg|<center>1</center>
Image:Pic2.jpg|<center>2</center>
Image:Pic3.jpg|<center>3</center>
Image:Pic4.jpg|<center>4</center>
Image:Pic5.jpg|<center>5</center>
Image:Pic6.jpg|<center>6</center>
Image:Pic7.jpg|<center>7</center>
</gallery>
</center>
This is scary. There is an idea of re-implementing the above code with the following template:
{{Photos
| Picture1.jpg = 1
| Picture2.jpg = 2
| Picture3.jpg = 3
| Picture4.jpg = 4
| Picture5.jpg = 5
| Picture6.jpg = 6
| Picture7.jpg = 7
|}}
The template is mostly as follows:
... var definitions, etc ...
<center>
{{#tag:gallery
| {{#forargs: | K | V |
Image:{{#var: K}} {{!}} <center>'' {{#var: V}} ''</center>
}}
| widths = {{#var:WIDTHS}}
| heights = {{#var:HEIGHTS}}
| perrow = {{#var:PERROW}}
}}
</center>
But the problem is that only the first image is rendered, and the whole rest Picture 2... Picture 7 is rendered under the first image thumbnail. And I suspect that the reason possibly is a missing new line character so the gallery tag may be rendered like this producing wrong 1-picture gallery:
<gallery widths="120px" heights="170px" perrow="5">
Image:Pic1.jpg|<center>1</center>Image:Pic2.jpg|<center>2</center>Image:Pic3.jpg|<center>3</center>...
It's only an assumption, but I guess it may have strong background. So the question is:
is there any way of forcing a new line break so the <gallery> tag could be rendered as expected?
You can force a newline by adding <nowiki />like this:
{{#tag:gallery
| {{#forargs: | K | V |<nowiki />
Image:{{#var: K}} {{!}} <center>'' {{#var: V}} ''</center>
}}
| widths = {{#var:WIDTHS}}
| heights = {{#var:HEIGHTS}}
| perrow = {{#var:PERROW}}
}}

3-column layout to 2-column layout with minimum markup changes

In an app I am maintaining, I am implementing less (the styling language) changes for iPad form factors. I've already got media queries set up to handle this, but I have a slight problem with getting my markup to behave!
Currently, in our 'normal' form factor, we have a 3-column layout:
*---*-----*---*
| A | B | C |
*---*-----*---*
<div class="lft-side-panel">
A
</div>
<div class="ctr-panel">
B
</div>
<div class="rt-side-panel">
C
</div>
.lft-side-panel {
.span4(); // 4/16 slots wide
margin-left: 0;
left: 0;
}
.ctr-panel {
.span8();
}
.rt-panel {
.span4();
}
However, due to size constraints on these smaller form factors, I am trying for a 2-column setup as such:
*---*---------*
| A | |
*---* B |
| C | |
*---*---------*
<div class="lft-side-panel">
A
</div>
<div class="ctr-panel">
B
</div>
<div class="rt-side-panel">
C
</div>
/* These appear to be where the solution lies, at least as far as Less is concerned. */
.lft-side-panel,
.rt-side-panel {
left: 0;
margin-left: 0;
.span4();
}
.ctr-panel {
span12();
}
I've tried
specifying a top and left attribute with value 0 for the C div,
specifying float: left in the media query for the rt-side-pnl class
...but it leaves me with a layout like:
*---*-----*
| A | |
*---| B |
| |
*---*-----*
| C |
*---*
Question: What am I missing to achieve a 2-column layout with A and C on top of each other, and B off to the side? I have a feeling the solution is right under my nose, but I'm just not seeing it. If possible, I must preserve the structure of the markup; if I must re-order things slightly, that can work too.
Check out this fiddle http://jsfiddle.net/s756e/3/
I set .rt-side-panel, .lft-side-panel { float:left; width=25%;} (needed to convert your 4 of 16 bootstrap to percent and added some demo colors and heights) and set .ctr-panel {float:right; width=75%;}
This seems to be, what you are looking for. Right!?