Sort Divs by inline "style" attribute - javascript

Is it possibile to sort divs by an inline width attribute (highest first)?
For example that are my divs:
<div style="width: 30.8px"></div>
<div style="width: 10.45px"></div>
<div style="width: 20px"></div>
I was looking for something like this, but it only works with div content ;(
$('.list li').sort(sortDescending).appendTo('.list');
function sortDescending(a, b) {
var date1 = $(a).find("div").text()
var date2 = $(b).find("div").text();
return $(b).find("div").text() - $(a).find("div").text();
};

It would be easier to just sort by the width of the element itself. This has two benefits; firstly you don't have to dissect the string to get the width value and secondly (and more importantly) you can then set the width property in an external stylesheet and the logic will still work. Try this:
$('div').sort(function(a, b) {
return $(a).width() > $(b).width() ? -1 : $(a).width() < $(b).width() ? 1 : 0;
}).appendTo('.list');
div div {
border: 1px solid #C00;
margin: 5px;
height: 5px;
}
#foo {
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div style="width: 30.8px"></div>
<div style="width: 10.45px"></div>
<div style="width: 20px"></div>
<div id="foo"></div>
</div>
Note that your selector is aiming for li elements yet your sample is using div elements. I'm just presuming this is just an oversight when writing the question.

Related

Limit selectable divs in a parent div

I'd like to create a product feature selection page where the user needs to select 3 features out of 6. Now, I got to a point where I can limit the number of selectable elements so if 3 elements are selected, the user wont be able to select a 4th one.
I need to modify this so when the user is attempting to select the 4th element, the 1st element they selected becomes unselected and the 4th element becomes selected. I hope it makes sense.
$('div').click(function(e) {
var $et = $(e.target);
if ($et.hasClass('fill')) {
$et.removeClass('fill');
} else {
if ($('.fill').length < 2) {
$et.addClass('fill');
}
}
});
div {
border: 1px solid blue;
height: 25px;
margin-bottom: 5px;
}
.fill {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<div id="1">one</div>
<div id="2">two</div>
<div id="3">three</div>
<div id="4">four</div>
This fiddle shows where I'm at with my code: http://jsfiddle.net/MarKP/32/
This fiddle is not mine, but this is exactly what I have right now in my project.
I'm trying to get this done using jQuery or plain JavaScript.
Thank you in advance!
To achieve this you can maintain an array which holds the order in which the elements were clicked. Then, when the limit is hit, you can remove the class from the element which was selected first. Try this:
var selections = [];
var $div = $('div').click(function(e) {
selections.push(this.id);
if (selections.length > 3)
selections.shift(); // remove first item
setState();
});
function setState() {
$div.removeClass('fill');
$div.filter(`#${selections.join(',#')}`).addClass('fill');
}
div {
border: 1px solid blue;
height: 25px;
margin-bottom: 5px;
}
.fill {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="1">one</div>
<div id="2">two</div>
<div id="3">three</div>
<div id="4">four</div>
<div id="5">five</div>
<div id="6">six</div>
Finally, note that jQuery 1.4.4 is massively outdated; nearly 10 years in fact. You need to update it.

Reset Border style

I have a image that is currently being styled with Jquery once it's clicked. I eventually hide it in Javascript. I want to reshow it, but I want it to have the border removed.
Here is HTML:
<div id="playOptionsWager" style="display: none">
<h4>Choose your move to beat the computer!</h4>
<img id="clickedRockWager" src="img/rock.jpg" onclick="playWagerRock()" />
<img id="clickedPaperWager" src="img/paper.jpg" onclick="playWagerPaper()"/>
<img id="clickedScissorsWager" src="img/scissors.jpg" onclick="playWagerScissors()" />
</div>
Jquery:
$(function () {
$("img").on("click",function() {
$(this).siblings().css('border','0px')
$(this).css('border', "solid 2px red");
});
});
Here is what I was trying in Javascript:
function autobet() {
coinBalance -= currentBet*2;
alert(getBalance());
document.getElementsByTagName("IMG").style.border="";
}
However when it reshows the div it has the border on it still.
Thanks for the help!
Your issue is that document.getElementsByTagName("IMG") returns a collection of elements, so simply applying .style.border on this collection won't work. Instead, you need to loop over this collection, and set every image within it to have no border using .style.border = 0;:
See working example (with div) below:
function removeBorder() {
[...document.getElementsByTagName("div")].forEach(elem => {
elem.style.border = 0;
});
}
.box {
height: 100px;
width: 100px;
background: black;
display: inline-block;
}
.active {
border: 3px solid red;
}
<div class="box"></div>
<div class="box active"></div>
<div class="box"></div>
<br />
<button onclick="removeBorder()">Remove border</button>
Also note that [...document.getElementsByTagName("IMG")] is a way of converting the collection of elements into an array of elements, which thus allows us to use the .forEach method to loop over it.
You started with jQuery, let's continue with jQuery.
function autobet() {
coinBalance -= currentBet*2;
alert(getBalance());
$("img").css("border","");
}
The problem is that getElementsByTagName() returns a collection not one element.
First you need to iterate over the collection of html elements you have - when using getElementsByTagName you get back an array of elements.
Second you need to give the elements a style of zero.
const divElements = document.getElementsByTagName("IMG");
for (let i=0; i < divElements.length; i++) {
divElements[i].style.border = 0;
}
You can see the code on stackbliz -
https://stackblitz.com/edit/border-issue?file=index.js

appending complete html of one dive into new div

I am using JQuery for this:
Taking complete html and appending into a new div
My JQuery code:
$(document).ready(function(){
$("#addNew").click(function(){
var maindiv = document.getElementById('nestedFeilds').html();
$("#showhere").append('maindiv');
});
});
The HTML is pretty complex and lengthy so take just reference
<div class= "row" id="mainContainer">
<label for="Education" style="margin-left: 30px ; float:left;">Education</label>
<div class="col-xs-4 inner"></div>
<div class="col-xs-8 verticalLine" id="nestedFeilds" style=" margin-left: 10px ;float:left; display: none;">
In the last div, it is actually a form and I need its complete html to be shown with different name attribute when ever I click button
I am calling my function like this
<div id= "showhere"></div>
<div style="margin-left: 133px;float:left;">
<a id="addNew"> Add Education</a>
</div>
If you want to get innerHTML, you should use element.innerHTML, and if you want to append previously saved inner HTML, you can use element.append(variableWithPreviousInnerHTML). Here is the working example:
$(document).ready(function() {
$("#addNew").click(function() {
var maindiv = document.getElementById('nestedFeilds').innerHTML;
$("#showhere").append(maindiv);
});
});
div {
width: 100px;
height: 100px;
border: 1px gray solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nestedFeilds">Content from #nestedFeilds</div>
<div id="showhere"></div>
<button id="addNew">Click</button>
If anything isn't clear, feel free to ask.

CSS nth-child doesn't work on dynamically hidden element [AngularJS]

I'm trying to implement CSS nth-child on every number of elements. If a certain number is reached I want to hide the first element and make it reappear if the number reduces again.
The problem is that somehow the nth-child still counts the hidden element and thus wrongly implements the styling. Is this a bug or am I doing it wrong?
NOTE: The same thing also happens if I use jQuery
http://jsfiddle.net/bedex78/uZ5wn/23/
The View:
<div ng-app>
<div ng-controller="TheCtrl">
<p>Amount to add: <input type="text" ng-model="amount" ng-init="amount=1"></p>
<div class='holder'>
<div ng-class='elements.length < 6 ? "inside" : ""'
ng-hide="elements.length >= 6">
<button class='button' ng-click="add(amount)">Add more</button>
</div>
<div class='inside' ng-repeat="(k,v) in elements">
{{ $index }} Remove
</div>
</div>
</div>
</div>
The JS (AngularJS):
function TheCtrl($scope) {
$scope.elements = [{id:1},{id:2}]
$scope.add = function(amount) {
for (i=0; i < amount; i++){
$scope.elements.push({id:$scope.elements.length+1});
}
};
$scope.remove = function(index) {
$scope.elements.splice(index, 1);
};
}
The CSS:
.holder {
width: 300px;
height: 400px;
border: 1px solid black;
}
.inside {
height: 30px;
border: 1px solid black;
}
.inside:nth-child(3n+1) {
background-color: yellow;
}
.inside a {
float: right;
}
It happens because hidden element is still in DOM. So it is count as a child and styles applied accordingly.
You can try to use ng-if instead of ng-hide. It will make div disappear from DOM and styles will work fine.
Example

jQuery :has selector filter trouble

I have some containers with ids="container1", "container2", "container3"...
They can have one of two types of tags inside: tables or canvas.
I want to hide one of them depending on the device orientation.
I have tried with this
$('[id^=container]:has(canvas)').hide();
or
$('[id^=container]:has(table)').hide();
but both hide all the containers, don't filtering their inside tags.
You can do
var x = $('[id^=container]').find("table").length;
// Will be 0 if no table inside it
if(x==0) { .. }
else { .. }
You can use classes on your containers instead of ids. Here's a JSFiddle demo.
For better performance in modern browsers, use $( "your-pure-css-selector" ).has( selector/DOMElement ) instead.
Source: https://api.jquery.com/has-selector/
Basically I made a 3 containers. One with a table, one with a canvas and one with nothing.
<div class="container green">
<table></table>
</div>
<div class="container blue">
<canvas></canvas>
</div>
<div class="container red"></div>
And a quick CSS to have the divs visible.
div.container{
display: inline-block;
height: 50px;
margin: 10px;
width: 50px;
}
div.green{
background-color: green;
}
div.blue{
background-color: blue;
}
div.red{
background-color: red;
}
And to complete it, a jQuery that executes when the document is ready.
$(document).ready(function(){
$('div.container').has('canvas').hide();
});
If you know the element by which you want to grab the container is not nested within additional tags, you can use the parentNode property of an HTML element to climb up the DOM tree and hide the parent.
document.querySelector("[id^=container] > table").parentNode.style.display= "none";
Example that demos the concept:
document.getElementById("input").addEventListener("change", function() {
document.getElementById("container1").style.display = "block";
document.getElementById("container2").style.display = "block";
document.querySelector("[id^=container] > " + this.value).parentNode.style.display = "none";
});
#container1 {
border: 1px solid red;
}
#container2 {
border: 1px solid blue;
}
<select id="input">
<options>
<option value="table">Hide the table</option>
<option value="canvas">Hide the canvas</option>
</options>
</select>
<div id="container1">Table
<table></table>
</div>
<div id="container2">Canvas
<canvas></canvas>
</div>
I didn't realized I had a global container with id= "container*".
What a silly mistake. Sorry for stealing your time, and thank you everyone!

Categories