Repurposing some Javascript for a similar DOM element - javascript

On my page I have an unordered list with some list items that serve as links to load content into a div.
The art direction requires that the list items be fully justified to the left and right. I've written some JavaScript to figure out how wide the ul is and calculate the width of the individual li elements, divide the remaining space and push the elements to the left and right respectively. It works great.
Now we want to add another ul under the first with another set of links.
How can I repurpose my code to do the same work as before?
All the list items are styled display:inline; and they need to be fluid in width in the event a font on one browser is a little bigger than another.
Here's my HTML: (It's all run together to overcome the spacing issue with inline list elements)
<div id="portfolio">
<ul class="stacked-nav-top">
<li class="project_link">
<a href="#" class="project_class planning" id="commercial-industrial" title="Commercial Industrial Projects">
Commercial & Industrial
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="government-institutional" title="Government Institutional Projects">
Government & Institutional
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="affordable-housing" title="Affordable Housing Projects">
Affordable Housing
</a>
</li>
<li class="breaker">//</li>
<li class="project_link">
<a href="#" class="project_class planning" id="multi-family-housing" title="Multi-family Housing Projects">
Multi-family Housing
</a>
</li>
</ul>
</div>
And my JavaScript:
$(function()
{
var linkwidth = 0;
$('#portfolio ul li.project_link').each(function()
{
linkwidth += $(this).outerWidth()
});
var leftover = ($('#portfolio ul').outerWidth() - linkwidth);
var breakerwidth = Math.floor((leftover / 3));
$('#portfolio ul li.breaker').css('width', breakerwidth);
});
EDIT
My CSS:
section#portfolio ul {
display:block;
width:820px;
text-align:center;
}
.stacked-nav-top {
border-top:solid 1px rgba(97,58,17,.3);
margin:0px;
background:transparent url(images/dotted_line_820.png) center 19px no-repeat;
padding:10px 0px;
}
.stacked-nav-bottom {
border-bottom:solid 1px rgba(97,58,17,.3);
padding-bottom:10px;
margin:10px 0px 15px 0px;
}
section#portfolio ul li {
display:inline;
font:lighter .65em "Tahoma", "Geneva", sans-serif;
color:rgb(145,145,145);
text-transform:uppercase;
}
section#portfolio ul li.breaker {
display:inline-block;
text-align:center;
}
I've tried wrapping all the JavaScript in a $('#portfolio ul').each(... but that doesn't seem to work. It sets the spacing according to the first ul not both individually.

I'm not really sure to understand what do you want but,
if you want to repeat the operation on each ul of your section, you have to loop on each ul, then do your calculations.
Demo here, respecting your HTML inline syntax (inline-block problem).
http://jsfiddle.net/ggX2r/2/
// Inside a document.ready scope of couse...
$('#portfolio ul').each(function () {
var linkwidth = 0,
leftover,
breakerwidth;
// *this* refers to your current <ul> child of your #portfolio.
$('li.project_link', this).each(function() {
// *this* refers now to your current <li.project_link> element
linkwidth += $(this).outerWidth();
});
leftover = ($('#portfolio ul').outerWidth() - linkwidth);
breakerwidth = Math.floor((leftover / 3));
$('li.breaker', this).css('width', breakerwidth);
});

Related

How to add an extra class (.info) containing text to my js code

.info needs to act the same way as .showBorder, meaning will move along with the border but will be placed above the box. A better way to structure this using jQuery is also welcome, all suggestions welcome!
// Get references to the two sets of boxes
var numbers = document.querySelectorAll(".click");
var letters = document.querySelectorAll(".border");
// Turn each node list into proper arrays:
numbers = Array.prototype.slice.call(numbers);
letters = Array.prototype.slice.call(letters);
// Loop through all the number boxes
numbers.forEach(function(box, index){
// Set up the click event handlers for all the number boxes
box.addEventListener("click", function(){
// Remove borders from each of the letter boxes
letters.forEach(function(box){
box.classList.remove("showBorder");
});
// Apply the border to only the one clicked element
letters[index].classList.add("showBorder");
});
});
.list-box li {display: inline;list-style-type: none;padding: 1em;background:red;}
.list-box {margin:50px auto;}
.box-sleeve li {display: inline;list-style-type: none;padding: 1em;background:red;}
.box-sleeve {margin:50px auto;}
.showBorder { border: 3px dashed black; }
.info {margin:0;padding:1em;}
<section>
<div class="container">
<ul class="list-box">
<li class="click">1</li>
<li class="click">2</li>
<li class="click">3</li>
<li class="click">4</li>
</ul>
<span class="info">paragraph</span>
<ul class="box-sleeve">
<li class="border">a</li>
<li class="border">b</li>
<li class="border">c</li>
<li class="border">d</li>
</ul>
</div>
</section>
Couldn't think of better way to do this, based on code you provided. I hope that you get the idea and can implement that in your project.
Edit
Paragraph is visible after box is checked.
// Get references to the two sets of boxes
var numbers = document.querySelectorAll(".click");
var letters = document.querySelectorAll(".border");
// Turn each node list into proper arrays:
numbers = Array.prototype.slice.call(numbers);
letters = Array.prototype.slice.call(letters);
// Loop through all the number boxes
numbers.forEach(function(box, index){
// Set up the click event handlers for all the number boxes
box.addEventListener("click", function(){
// Remove borders from each of the letter boxes
letters.forEach(function(box){
box.classList.remove("showBorder");
});
// Apply the border to only the one clicked element
var info = document.getElementsByClassName('info')[0];
info.style.left = 10+(index*45) + 'px';
info.style.display = 'inline';
letters[index].classList.add("showBorder");
});
});
.list-box li {display: inline;list-style-type: none;padding: 1em;background:red;}
.list-box {margin:50px auto;}
.box-sleeve li {display: inline;list-style-type: none;padding: 1em;background:red;}
.box-sleeve {margin:50px auto;}
.showBorder { border: 3px dashed black; }
.info {margin:0;padding:1em; position: relative; display: none;}
<section>
<div class="container">
<ul class="list-box">
<li class="click">1</li>
<li class="click">2</li>
<li class="click">3</li>
<li class="click">4</li>
</ul>
<span class="info">paragraph</span>
<ul class="box-sleeve">
<li class="border">a</li>
<li class="border">b</li>
<li class="border">c</li>
<li class="border">d</li>
</ul>
</div>
</section>

how to hide images in a specific list and make them visible in a other list

I have a question: is it possible to hide some images and make the same visible in another list? Here is the code:
<section>
<ul class="portfolio_filters">
<li>show all</li>
<li>New Logos</li>
<!--lightbox2-->
<li>Black & White</li>
<!--lightbox3-->
<li>Industrial</li>
<!--lightbox3-->
<li>Mix</li>
<!--lightbox4-->
</ul>
</section>
i want some images not to show in the "SHOW ALL" list, but if I click (for example) on the black and white list the same image needs to be visible.
thanks for the answers here is for example a linked image
<div class="new col-sm-4 col-md-4">
<div class="portfolio_item"> <a href="images/portfolio/stimson.jpg" class="lightbox"> <img src="images/portfolio/stimson.jpg" alt="Wedding photograph">
<div class="overlay">
<div class="desc">
<h4>Stimson</h4>
<span class="cross"></span> </div>
</div>
</a> </div>
</div>
how to make this visible only in the " NEW LOGOS " list and not in the "SHOW All" list?
You could try something like this:
$("img").hide();
$("li a").click(function(event){
event.preventDefault();
$("img").hide();
filter = $(this).data("filter");
if(filter=="*")
$("img:not(.black)").show();
else
$(filter).show();
});
Demo JsFiddle
Add a class like .hidefromall to the images you want to hide, and use a :not() selector:
<li>show all</li>
It's kinda hard with not all of the code. I assume that all the lists are build the same, and have the same HTML structure.
Most simple is to add a class to the specific list in which you want to hide the 'Show all', lets call that class dontShowAll. In your CSS you can then use:
.portfolio_filters.dontShowAll li:first-child { /*note that the classes a written without a space!! */
display: none;
}
If you aren't able to change the HTML structure you can use child selectors:
section:first-child ul li:first-child { /* only from the first list */
section:nth-child(odd) ul li:first-child { /* from all the odd lists */
section:nth-child(3n) ul li:first-child { /* every third */
section:nth-child(4) ul li:first-child { /* only the fourth */
section:nth-child(n + 5) ul li:first-child { /* the fifth and all that follow */

Sizing an <ul> in a table cell

I'm building an HTML view consisting of a <table>, with each cell containing only a single <ul> element, with a variable number of <li>. For readability reasons, my rows have a min-width: 100px;, but expand based on the contents of the <ul>. But in the other cells (which a lower number of <li>). I want my <ul> to use 100% of the cell's height. At the moment, they keep the 100px height and are verticaly centered.
My view can be summed up to that :
<table>
<tr>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
</tr>
<tr>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
<td>
<ul>...</ul>
</td>
</tr>
</table>
My reason for this, is that each <li> can be dragged & dropped between every <ul>, but the fact they are not resizing make dropping on an empty list kind of hazardous, because you don't "see" them, and have to guess where they are. It would be a lot easier if they were using the full cell dimensions.
I have made a lot of tries using developer tools, but could not find the right combination of CSS and Javascript.
Technicals prerequisites :
Javascript DOM manipulation is OK, I already do it to resize my table. I use ExtJS, but I'm OK with porting jQuery or pure JS code.
Compatibility with IE8 is a must (75% of final users are on IE. Gotta love the corporate world...)
Thanks for any advice !
EDIT : Here's a Fiddle that represents my code as closely as possible (NDA prevents me from sharing the original code)
For height: 100% to work as expected the container must have its height set. I have a solution below that uses JavaScript to set the height of all the ul's, it can be used as a function that runs every time it changes if needed:
function fixDimensions() {
var table = document.getElementById('table');
var trs = table.getElementsByTagName('tr');
for(var i = 0; i < trs.length; i++){
var tds = trs[i].getElementsByTagName('td');
for(var g = 0; g < tds.length; g++){
var ul = tds[g].getElementsByTagName('ul')[0];
ul.style.height = (tds[g].clientHeight - 12) + 'px';
}
}
}
The - 12 on the height is for the padding and border. JSFiddle.
You could use td themselves to draw the borders : http://jsfiddle.net/P5h8d/2/
table {
width: 100%;
background:black;
border-spacing:1px;
}
tr {
min-height: 50px;
width: 100%;
}
tbody th, tbody td {
border: 3px dotted red;
}
th, td {
width: 20%;
background:white;
}
You might not need a table if:
you use display:table instead <table> to turn <ul> visually into a cell.
DEMO
<section>
<div>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
</div>
<div>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
<ul>
<li> itelm</li>...
</ul>
</div>
</section>
CSS
section {
display:table;
border-spacing:5px;
}
section > div {
display:table-row;
}
section>div>ul {
display:table-cell;
background:red;
min-width:100px;
}
you use display:flex;
DEMO
basic CSS used :
tr {
display:flex;/* reset display:defaut*/
}
td {background:gray;
display:flex;/* here again display reset */
flex-direction:column;/* make sure we draw content from top to bottom */
margin:2px;
}
ul {
padding:0;
margin:5px;;
min-width:100px;
background:red;
flex:1;/* fills or shares whole height of its flex box*/
}
Not to pollute my first answer, added here the drag and drop js
No matter the height of the ul , li drops in !
here is a CSS way to extend area around an element to increase area where it can catch mouse events.
IE8 understands :before/:after , so we use them. and set them in absolute position on top and bottom of your ul.
DEMO
the CSS used:
td {overflow:hidden;/*keep ul:pseudos inside */}
ul {
position:relative;
}
ul:before,
ul:after {
content:'';
position:absolute;
height:200px;/* whatever you need or think it is safe */
left:0;
width:100%;
}
ul:before {
bottom:100%;
}
ul:after {
top:100%;
}
added to the demo basic HTML5 drag and drop (attributes and js) since it was missing from your fiddle.
function allowDrop(ev){ev.preventDefault();}
function drag(ev){ev.dataTransfer.setData("Text",ev.target.id);}
function drop(ev){ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));}

Bootstrap Pagination between navigation elements

I tried different plugins like bootstrap-paginator and bootstrap-pagination-js to make pagination through dynamically generated <li> elements , so that they don't exceed one line.
The wanted result : One line of dates with next and previous buttons respectively in the right and in the left .
The plugins that I've tried have not been useful to me .
My code looks like this:
<div class="row">
<div class="col-md-12 column">
<ul class="nav nav-pills center-pills text-center">
<li class="active">
<a href="#">
<span class="text-center badge pull-right span-list">1</span>
1 Mars
</a>
</li>
<li class="">2 Mars</li>
<li class="">3 Mars</li>
<li class="">4 Mars</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
<li class="">etc</li>
</ul>
</div>
</div>
The code fiddle .
Your suggestions will be very welcome .
Are you having a problem with styling? If so...
I've set the row height to fixed, and made overflow hidden, so that you get just one row of buttons.
.row{overflow:hidden;height:42px;}
I've added a prev and next button, and made them float left and right respectively. I hope this doesn't violate your pagination framework. Please let me know if you want an example of how to programmatically add these elements.
HTML
<li class="next">Next</li>
<li class="prev">Previous</li>
CSS
li.next{float:right;}
li.prev{float:left;}
I believe this gives the desired result... please let me know if I've missed your intention.
Disclaimer: I've only tested this in Opera 19.0. I don't have access to Firefox/Chrome/IE at the moment.
Example: http://jsfiddle.net/nickg1/5ELfQ/2/
Updated: Updated to remove horizontal scrollbar. - http://jsfiddle.net/nickg1/5ELfQ/3/
I have had success with Bootstrap pagination. If you are generating too many elements to fit in your desired space, you need to either figure out a way to generate less or use css to limit the size of your pagination space and "cut off" the overflowing elements.
What you can do is .prepend() a left li and .append() a right li:
$(document).ready(function () {
$('.nav').prepend('<li class="left"><a>Left</a></li>');
$('.nav').append('<li class="right"><a>Right</a></li>');
});
Although there has little browser compatibility and styling issues in this solution. But I hope this will give you an idea to start.
My CSS:
.nav.nav-pills {
width:auto;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
position: relative;
padding-right: 38px;
display: inline-block;
}
.nav-pills > li {
display: inline-block !important;
float: none !important;
}
.nav-pills > li.last {
position: absolute;
right: 0;
}
As display:inline; is applied to .nav, so for centering use text-center class in wrapping div. i.e.
<div class="col-md-12 column text-center">
Apply jQuery for previous/next buttons and resizing issues.
$(document).ready(function () {
$('.nav').prepend('<li>«</li>');
$('.nav').append('<li class="last">»</li>');
var ulWidth = $('.nav').width();
var screenWidth = document.body.clientWidth;
if (screenWidth < ulWidth ){
$('.nav').css('width', '100%');
}
$(window).resize(function(){
screenWidth = document.body.clientWidth;
screenWidth < ulWidth == true ?
$('.nav').css('width', '100%') :
$('.nav').css('width', 'auto');
});
});

Completely linkable li element

I need to make linkable an entire <li> or <tr> element, someone suggest me to use javascript, with an onclick action.
function doNav(url)
{
document.location.href = url;
}
This do the job, the problem is that, in this way is impossible for the user, understand what url is going to. How to realize my need (completly clickable elements) without changing browser behaviour?
You don't need javascript for this. Add this css
ul li a {
display: block;
padding: 10px 20px;//more or less, to suit your needs
text-decoration: none;
}
This will make the entire <li> containing an anchor clickable
<li class="block">Text</li>
That lets you see the target. And then:
.block{
display:block;
text-decoration:none; //just so it isn't underlined
}
in the CSS will take care of the "whole thing needs to be clickable" problem.
HTML
<ul class="menu">
<li class="anchors" title="click me I am a link" > link 1 </li>
<li class="anchors" title="click me I am a link" > link 1 </li>
<li class="anchors" title="click me I am a link" > link 1 </li>
<li class="anchors" title="click me I am a link" > link 1 </li>
</ul>
CSS:
ul li.anchors{
text-decoration:underline;
color:blue;
list-style-type:none;
display: inline-block;
margin:2px 4px;
padding: 2px 4px;
}
ul li.anchors:hover{
color:navy;
cursor:pointer;
}
better way may be like this: http://jsfiddle.net/iamanubhavsaini/Cv2FM/1/
here, use content property and data- attribute to tell user before hand as what they are going to click on.

Categories