Weird behavior of CSS nth-child after editing dom - javascript

I have four div container in the following order:
Every container has CSS class "chart multi-mode" with style:
.chart.multi-mode {
width: 300px;
height: 200px;
margin: 0 15px 15px 0;
}
Every second div should have no right margin, so I use:
.chart.multi-mode:nth-child(2n) {
margin-right: 0px;
}
This is working fine until I use jQuery sortable()
When dragging one div and holding, jQuery adds an placeholder, which I also gave the classes "chart multi-mode" and the original object becomes absolute and I remove the class "multi-mode".
But nth-Child doesn't care about removing the class "multi-mode" and still counts the absolute div and so the margins are set wrong, see here:
Any solution?

To select the second element with the class, after the changes, there's not much you could do. The only kind of selector I can think of is to set the hierarchy starting from the element that does not contain the class, and follow using immediate forward sibling selector +, to target the second one:
Untested
li:not(.chart.multi-mode) + .chart.multi-mode + .chart.multi-mode {
}

I solved it with Javascript:
this.$chartList.sortable({
placeholder : "chart chart-placeholder " + chartTypeClass,
handle : ".opt-drag",
start : function(event, ui) {
ui.item.addClass('drag-state');
$('.multi-mode:not(.drag-state):odd').addClass('odd');
$('.multi-mode:not(.drag-state):even').addClass('even');
},
change : function(event, ui ) {
$('.multi-mode').removeClass('odd');
$('.multi-mode').removeClass('even');
$('.multi-mode:not(.drag-state):odd').addClass('odd');
$('.multi-mode:not(.drag-state):even').addClass('even');
},
stop : function(event, ui) {
ui.item.removeClass('drag-state');
$('.multi-mode').removeClass('odd');
$('.multi-mode').removeClass('even');
},
update : function() {
uiBehavior.startSpinner();
var newUuidOrder = [];
$('.chart').each(function() {
newUuidOrder.push($(this).attr('uuid'));
});
_this.restSetChartsOrder(newUuidOrder, function() {
uiBehavior.stopSpinner();
});
}
});
On start Draggin or when list change I count elements and add class odd or even.
CSS looks like this:
.chart.multi-mode.odd {
margin-right: 0px !important;
}
.chart.multi-mode.even {
margin-right: 15px !important;
}
Thanks to all!

I knocked something workable up that uses a different approach laying out the boxes (see my comment Weird behavior of CSS nth-child after editing dom):
Basically is a non-responsive light version of a Bootstrap grid:
* { box-sizing: border-box; }
body {
padding: 50px;
}
#chartlist {
list-style: none;
margin: 0 -8px;
padding: 0;
width: 600px;
}
#chartlist::after {
content:"";
display:table;
clear:both;
}
.chart.multi-mode {
float: left;
width: 300px;
height: 200px;
margin-bottom: 16px;
padding: 0 8px;
position: relative;
}
.chart-holder {
border: 1px solid #333;
background: #999;
height: 100%;
}
.chart.placeholder {
background: rgba(255, 0, 0, 0.5);
position: absolute;
right: -20px;
top: 20px;
}
<ul id="chartlist">
<li class="chart multi-mode">
<div class="chart-holder">Chart #1</div>
</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #2</div>
</li>
<li class="chart multi-mode placeholder">Chart Placeholder</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #3</div>
</li>
<li class="chart multi-mode">
<div class="chart-holder">Chart #4</div>
</li>
</ul>
(Or http://jsfiddle.net/maryisdead/vfm5d3au/)

negate the placeholder using this
.chart.multi-mode:not(.chart-placeholder):nth-child(2n)

Related

expand div on click Polymer js without jquery

I'm using Polymer but I'm having some trouble with events and the such. I want to create an expanding search bar, similar to
My current code looks something like the following:
Code:
// This is where things are a little unclear for me. So far, I have tried the following:
expand: function() {
var divToStretch = this.$.stretchMe;
if ( /*search bar is open*/ ) {
//remove "stretched" css from "stretch" div
} else {
//add "stretched" css to "stretch" div
}
}
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
.stretched {
width: 500px;
}
<div class="stretch" id="stretchMe">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
May I suggest a pure CSS alternative? You can make your search bar receive focus, by adding tabIndex="0". This way you can provide a style for div.stretch:focus, allowing you to dynamically change its size when the user clicks or focuses on the element and making it small again when the user focuses on something else.
It's really simple, elegant, does not need a lot of code and does what you need. Give it a try!
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
div.stretch:focus {
width: 500px;
}
<div class="stretch" id="stretchMe" tabIndex="0">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
Alternatively, you can make it do the same thing on :hover, if that's what you are after, simply by changing the selector. Or combine both, if you prefer. Below is a :hover example.
div.stretch {
border: 1px solid black;
width: 25px;
height: 25px;
border-radius: 25px;
transition: width 1s;
}
div.stretch:hover {
width: 500px;
}
<div class="stretch" id="stretchMe">
<iron-icon class="search" icon="search" on-click="expand"></iron-icon>
</div>
You can use the toggle method of the classList for this:
expand : function() {
this.$.stretchMe.classList.toggle('stretched');
}
The classic way would be as following:
if (/*search bar is open*/) {
divToStretch.style.width = "auto";
} else {
divToStretch.style.width = "500px";
}
But I highly recommend using this.$.stretchMe.classList.toggle('stretched');
Read more here

Filtering with jQuery Isotope leads to jerky animation

I'm using Isotope on a project, but have run into an issue when using the filter method.
Filtering the list hides the undesired elements fine, but the transitioning animations aren't as smooth as the demos have me believe they should be.
The following code should illustrate my point; the filters apply and the elements do animate, but there are noticeable, visual jumps:
var config = {
itemSelector: '.grid_item',
percentPosition: true,
layoutMode: 'fitRows',
fitRows: {
gutter: '.grid_gutter'
}
}
$('.grid').isotope(config);
$('.filter').on('click', function(){
var type = $(this).attr('id');
$('.grid').isotope({
filter : '.' + type
});
});
$('#clear').on('click', function(){
$('.grid').isotope({
filter : '*'
});
});
html, body {
margin: 0;
padding: 0;
}
.grid {
list-style: none;
margin: 1em;
padding: 0;
text-indent: 0;
}
.grid_item {
background: gray;
margin: 0 0 1%;
padding-top: 40%;
position: relative;
width: 49.5%;
}
.grid_text {
color: #fff;
position: absolute;
top: 50%; left: 0; right: 0; bottom: 0;
text-align: center;
}
.grid_gutter {
width: 1%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/2.2.1/isotope.pkgd.js"></script>
<button class="filter" id="exit">Exit</button>
<button class="filter" id="creation">Creation</button>
<button id="clear">Clear</button>
<ul class="grid">
<div class="grid_gutter"></div>
<li class="grid_item exit">
<span class="grid_text">Exit</span>
</li>
<li class="grid_item creation">
<span class="grid_text">Creation</span>
</li>
<li class="grid_item creation">
<span class="grid_text">Creation</span>
</li>
</ul>
I assume that it's something in my CSS that's causing the issue, but I can't weed it out.
Also, see this fiddle.
For me the issue was that I had a transition applied to the elements which was causing it to be jerky. Setting the transition to 0s fixed it for me.
I don't know if this is a problem with Isotope or if we were both doing the same wrong thing, but I had the same issue and resolved it by not using percentPosition at all. The Isotope documentation says using percentPosition "reduce[s] adjustment transitions on window resize", so I guess not using it may cause performance problems.

Resizing one element using jQuery UI changing the position of another

I am trying to make resizible and draggable lines out of labels using jQuery UI.
The problem is, if I add two labels and try to resize the first label, it changes the position of the second label (but if I resize the second label it does not change the position of the first label).
How to prevent labels from changing other label's position while resizing..?
HTML:
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
JS:
function makeline() {
$t = $(".dra", "#line").clone(true).draggable().resizable({
handles: "s, n"
});
$("#main").append($t);
}
$("#s").click(function () {
makeline();
});
CSS:
.dra {
display: block;
background-color:red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width:500px;
height: 300px;
}
UPDATE: Full code in JSFiddle
This is happening because the jQuery UI widgets set the position of element to relative by default, leaving it in the normal flow of the document. You can work around this issue by applying position:absolute for the elements like:
.ui-resizable {
position:absolute !important;
}
This will cause them to stack on top of each other rather than one below another since they aren't in the normal flow anymore. You can easily fix this using the jQuery ui position() utility method as shown below:
$("#s").click(function() {
$t = $("#line .dra").clone(true).draggable().resizable({
handles: "s, n"
})
if ($("#main").find(".dra").length) {
$t.position({
at: "left bottom",
of: "#main .dra:last"
})
};
$("#main").append($t);
});
.dra {
display: block;
background-color: red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width: 500px;
height: 300px;
}
.ui-resizable {
position: absolute !important;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<div class="form-group">
<label>ADD two line and RESIZE THE FIRST LINE it will scroll down the line added after it. NOW add a 3rd line and resize the second line it will scroll down the 3rd line and if you resize the very first line you added it will scroll down the other lines</label>
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
You can adjust the positioning however you want.
If your label is:
<div class="label">Lorem ipsum</div>
add this CSS:
.label {
white-space: nowrap;
}

100% width (of page) drop down/drawer menu with JQuery?

I've been stuck trying to figure out how to code a menu much like what you see on the Playstation website: http://us.playstation.com/
EDIT: Fiddle: http://jsfiddle.net/jjcarlson/7q64A/
So far I have a number of issues. The first is that I have been unable to create the 100% width, because, I am assuming, of the parent/child relationship.
The second issue I have is that my Timeout works on all class elements rather than only the currently hovered element. In other words, if all elements have slid down and one is hovered over, they all will remain open until none of them have been hovered for 1.5 seconds. I admit that my inability to come up with a solution may be due to my limited experience with the language. Below is the CSS:
.accordion-container {
width: 90%;
padding-bottom: 5px;
margin: 20px 0 0 20px;
}
.accordion {
width: 40%;
padding: 20px;
margin: 0 15px 35px;
position: relative;
float: left;
display: inline-block;
}
.accordion-question {
margin: 0;
padding: 0 0 5px 20px;
display: inline-block;
color: #06F;
background-color: #9F0;
cursor: pointer;
}
.accordion-answer-container {
padding: 0 20px;
overflow: hidden;
color: #999;
background: #F00;
}
.accordion-answer {
margin: 0;
padding: 0;
color: #0C0;
}
Then, the JQuery:
$(document).ready(function () {
var menu = $('.accordion-answer')
var timeout = 0;
var hovering = false;
menu.hide();
$('.accordion-question').hover(function () {
hovering = true;
// Open the menu
$(this).closest('.accordion').find('.accordion-answer')
.stop(true, true)
.delay(400).slideDown(600);
if (timeout > 0) {
clearTimeout(timeout);
}
})
.on("mouseleave", function () {
resetHover();
});
$('.accordion-answer').hover(function () {
hovering = true;
startTimeout();
})
.on("mouseleave", function () {
resetHover();
});
function startTimeout() {
timeout = setTimeout(function () {
closeMenu();
}, 1500);
};
function closeMenu() {
if (!hovering) {
$('.accordion-answer').stop(true, true).slideUp(400);
}
};
function resetHover() {
hovering = false;
startTimeout();
};
});
And finally, the HTML:
<div class="accordion-container">
<div class="accordion">
<div class="accordion-question">
<h2>Is this a question?</h2>
</div>
<div class="accordion-answer-container">
<div class="accordion-answer">
<p>To be honest, I am not sure</p>
<ul>
<li>List item one</li>
<li>List item two</li>
</ul>
<p>That is all.</p>
</div>
</div>
</div><!-- /accordion -->
<div class="accordion" id="testanchor">
<div class="accordion-question">
<h2>What would be a good second question?</h2>
</div>
<div class="accordion-answer-container">
<div class="accordion-answer">
<p>I don’t know, man!</p>
<p>That is all.</p>
</div>
</div>
</div><!-- /accordion -->
</div>
Styling is minimal right now (sorry) as I'm just trying to get this figured out. Thank you for any help you can provide.
To get a width of 100% you should not display them as inline-block and set the width of .accordion to 100%.
In the hover-event you set hovering to true. If the next hover-event occurs prior to the call of closeMenu, then the if clause will already be false.
You should be able to accomplish the 100% width of your dropdown by altering the css of your .according-answer-container to a fixed position along with setting left and right to 0:
.accordion-answer-container {
padding: 0 20px;
overflow: hidden;
color: #999;
background: #F00;
position: fixed;
left: 0;
right: 0;
}
An update to your fiddle shows this working

Vertical Tabs with JQuery?

I want tabs along the left side of the page instead of across the top. I'm already loading jQuery for other reasons (effects), so I prefer using jQuery to another UI framework. Searches on "vertical tabs jquery" yield links to works-in-progress.
Is getting Vertical Tabs to work across browsers fraught, or is it so trivial that, once you have a solution, it doesn't seem worthwhile to post example code?
Have a look at the jQuery UI vertical Tabs Docu.
I try out it, it worked fine.
<style type="text/css">
/* Vertical Tabs
----------------------------------*/
.ui-tabs-vertical { width: 55em; }
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}
</style>
<script>
$(document).ready(function() {
$("#tabs").tabs().addClass('ui-tabs-vertical ui-helper-clearfix');
$("#tabs li").removeClass('ui-corner-top').addClass('ui-corner-left');
});
</script>
Try here:
http://www.sunsean.com/idTabs/
A look at the Freedom tab might have what you need.
Let me know if you find something you like. I worked on the exact same problem a few months ago and decided to implement myself. I like what I did, but it might have been nice to use a standard library.
I've created a vertical menu and tabs changing in the middle of the page. I changed two words on the code source and I set apart two different divs
menu:
<div class="arrowgreen">
<ul class="tabNavigation">
<li> Tab 1</li>
<li> Tab 2</li>
</ul>
</div>
content:
<div class="pages">
<div id="first">
CONTENT 1
</div>
<div id="secund">
CONTENT 2
</div>
</div>
the code works with the div apart
$(function () {
var tabContainers = $('div.pages > div');
$('div.arrowgreen ul.tabNavigation a').click(function () {
tabContainers.hide().filter(this.hash).show();
$('div.arrowgreen ul.tabNavigation a').removeClass('selected');
$(this).addClass('selected');
return false;
}).filter(':first').click();
});
//o_O\\ (Poker Face) i know its late
just add beloww css style
<style type="text/css">
/* Vertical Tabs ----------------------------------*/
.ui-tabs-vertical { width: 55em; }
.ui-tabs-vertical .ui-tabs-nav { padding: .2em .1em .2em .2em; float: left; width: 12em; }
.ui-tabs-vertical .ui-tabs-nav li { clear: left; width: 100%; border-bottom-width: 1px !important; border-right-width: 0 !important; margin: 0 -1px .2em 0; }
.ui-tabs-vertical .ui-tabs-nav li a { display:block; }
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 0; padding-right: .1em; border-right-width: 1px; border-right-width: 1px; }
.ui-tabs-vertical .ui-tabs-panel { padding: 1em; float: right; width: 40em;}
</style>
UPDATED ! http://jqueryui.com/tabs/#vertical
I wouldn't expect vertical tabs to need different Javascript from horizontal tabs. The only thing that would be different is the CSS for presenting the tabs and content on the page. JS for tabs generally does no more than show/hide/maybe load content.
Another options is Matteo Bicocchi's jQuery mb.extruder tabs plug-in:
http://pupunzi.open-lab.com/mb-jquery-components/jquery-mb-extruder/
Have a look at Listamatic. Tabs are semantically just a list of items styled in a particular way. You don't even necessarily need javascript to make vertical tabs work as the various examples at Listamatic show.
super simple function that will allow you to create your own tab / accordion structure here: http://jsfiddle.net/nabeezy/v36DF/
bindSets = function (tabClass, tabClassActive, contentClass, contentClassHidden) {
//Dependent on jQuery
//PARAMETERS
//tabClass: 'the class name of the DOM elements that will be clicked',
//tabClassActive: 'the class name that will be applied to the active tabClass element when clicked (must write your own css)',
//contentClass: 'the class name of the DOM elements that will be modified when the corresponding tab is clicked',
//contentClassHidden: 'the class name that will be applied to all contentClass elements except the active one (must write your own css)',
//MUST call bindSets() after dom has rendered
var tabs = $('.' + tabClass);
var tabContent = $('.' + contentClass);
if(tabs.length !== tabContent.length){console.log('JS bindSets: sets contain a different number of elements')};
tabs.each(function (index) {
this.matchedElement = tabContent[index];
$(this).click(function () {
tabs.each(function () {
this.classList.remove(tabClassActive);
});
tabContent.each(function () {
this.classList.add(contentClassHidden);
});
this.classList.add(tabClassActive);
this.matchedElement.classList.remove(contentClassHidden);
});
})
tabContent.each(function () {
this.classList.add(contentClassHidden);
});
//tabs[0].click();
}
bindSets('tabs','active','content','hidden');

Categories