I'm bulding small filtering feature for items listed in div elements. These div elements are in a slider placed next to each other.
So each column contains a number of items. The filtering is working but i can't find a way to group the filtered items one under another so they would be in a first colum, not in their oryginal column:
<input id="filter" name="filter" size="40"/>
<div class="filtered">
<div class="archive-col-1 column">
<div class="name"><div class="element">Alchemy</div></div>
<div class="name"><div class="element">Balboa</div></div>
<div class="name"><div class="element">Nebula</div></div>
<div class="name"><div class="element">Radio</div></div>
</div>
<div class="archive-col-2 column">
<div class="name"><div class="element">Mathematics</div></div>
<div class="name"><div class="element">Disco</div></div>
<div class="name"><div class="element">Antwon</div></div>
<div class="name"><div class="element">Barracuda</div></div>
</div>
<div class="archive-col-3 column">
<div class="name"><div class="element">English</div></div>
<div class="name"><div class="element">France</div></div>
<div class="name"><div class="element">Nairobi</div></div>
<div class="name"><div class="element">Crazy</div></div>
</div>
</div>
function filter(element) {
$("#filter").keyup(function () {
var filter = $(this).val();
count = 0;
$(".column .element").each(function () {
var parent = $(this).parent();
var length = $(this).text().length > 0;
if (length && $(this).text().search(new RegExp(filter, "i")) < 0) {
parent.hide();
} else {
parent.show();
//appendTo.closest('.colums');
count++;
}
});
});
}
$('input').on('keyup change', function () {
filter(this);
});
example: http://jsfiddle.net/pw7k2/
In my another example filtering works fine but I don't know how to limit rows and move other filtered items to the next column, now they go to first column only:
http://jsfiddle.net/yQD7X/
Did anyone have similar problem?
http://jsfiddle.net/pw7k2/2/
function dispatchElements() {
var $elements = $('.column .element:visible').remove();
var $column = $('.column:first');
$elements.each(function(index, value) {
var height = $column.height();
var $childrens = $column.children(':visible');
var childrenHeight = 0;
$childrens.each(function(){
childrenHeight += $(this).outerHeight();
});
childrenHeight += childrenHeight/$childrens.length;
if (childrenHeight > height) {
$column = $column.next();
}
$(this).appendTo($column);
});
}
This method removes all visible elements and dispatch them after checking if there's available space in the current column, if not it takes the next one.
Related
I would like the .box elements to show/hide based on the words the user searches for, so for example if a user types in 'Title2 Title1' because those words exists inside box one and two they will remain visible with the renaming .box elements hiding. All the text within the .box elements needs to be searchable not just that in the .title element.
Below is how far I've got. It's almost there but it's not quite working as hoped.
Any help would be great.
Many thanks.
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">
Box title one content
</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">
Box title two content
</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">
Box title three content
</div>
</div>
<script>
$("#search").on("input", function () {
var search = $(this).val();
if (search !== "") {
var searchArray = search.split(" ");
searchArray.forEach(function(searchWord) {
$(".box").each(function () {
if($(this).is(':contains('+ searchWord +')')) {
$(this).show();
} else {
$(this).hide();
}
});
});
} else {
$(".box").show();
}
});
</script>
You need to use a different search method. :contains does not work as you expect. Consider the following example.
$(function() {
function filter(e) {
var term = $(e.target).val();
if (term.length < 3) {
$(".box").show();
return;
}
$(".box").each(function(i, el) {
if ($(".content", el).text().indexOf(term) >= 0) {
$(el).show();
} else {
$(el).hide();
}
});
}
$("#search").keyup(filter);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">Box title one content</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">Box title two content</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">Box title three content</div>
</div>
So for example if on is entered, no filtering is performed. If one is entered, the script will look inside the content class of each box and if one is found in the text, it will be shown otherwise, it is hidden. If the User clears their search out, all items are shown.
Hide all box before iterate, then only show when match any words:
$("#search").on("input", function () {
var search = $(this).val();
if (search !== "") {
var searchArray = search.split(" ");
// Hide all .box
$(".box").each(function () {
$(this).hide();
})
searchArray.forEach(function(searchWord) {
$(".box").each(function () {
if($(this).is(':contains('+ searchWord +')') ) {
$(this).show();
}
});
});
} else {
$(".box").show();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input placeholder="Search" id="search" type="text" />
<div class="box">
<div class="title">Box Title1</div>
<div class="content">
Box title one content
</div>
</div>
<div class="box">
<div class="title">Box Title2</div>
<div class="content">
Box title two content
</div>
</div>
<div class="box">
<div class="title">Box Title3</div>
<div class="content">
Box title three content
</div>
</div>
Loop through all .boxs and using regex pattern matching, check either the title or content matches the search query. Show all matched boxes and hide all others
I have also fiddled it here
$("#search").on("input", function () {
var searchables=$('.box');
console.log(searchables)
var query=$(this).val();
searchables.each(function(i,item){
var title=$(item).find('.title').text();
var content=$(item).find('.content').text();
var rgx=new RegExp(query,'gi');
if(rgx.test(title) || rgx.test(content))
{
$(item).show();
}
else
{
$(item).hide();
}
})
})
I need to have a function that would add an existing div with a class (along with its underlying elements) to a particular div using for loop. It looks like this:
<div class="left-col">
<div class="list-row">
<div class="list-row2">
<span>Hello</span>
</div>
</div>
</div>
I need to loop through a function that will produce or duplicate "list-row" twice.
$(function() {
var leftcol = document.getElementsByClassName('left-col');
for (var i = 0; i < 2; i++) {
var listrow = document.querySelector('.list-row');
leftcol.appendChild(listrow[i]);
}
})
It should look like this:
<div class="left-col">
<div class="list-row">
<div class="list-row2">
<span>Hello</span>
</div>
</div>
<div class="list-row">
<div class="list-row2">
<span>Hello</span>
</div>
</div>
<div class="list-row">
<div class="list-row2">
<span>Hello</span>
</div>
</div>
</div>
You can try the following way:
$(function() {
var leftcol = document.querySelector('.left-col');
for (let i = 0; i < 2; i++) {
var listrow = document.querySelector('.list-row').cloneNode();
listrow.textContent = i + 1 + listrow.textContent;
leftcol.appendChild(listrow);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="left-col">
<div class="list-row">0</div>
</div>
You could use cloneNode and set the deep property to true. This will clone the node and all of its descendants.
For example:
function cloneNode(copies = 1) {
for (let i = 0; i < copies; i++) {
let leftcol = document.getElementsByClassName('left-col')[0];
let nodeToClone = document.querySelector(".list-row");
let clonedNode = nodeToClone.cloneNode(true);
leftcol.appendChild(clonedNode);
}
}
clone.addEventListener("click", function() {
cloneNode();
});
<button id="clone" type="button">Clone Node</button>
<div class="left-col">
<div class="list-row">Test</div>
</div>
If you wanted to insert more than one copy, you could pass a different value to the cloneNode function.
You can use jQuery's .clone() method to copy the entire content of an element to another element. The boolean argument passed to the clone function determines whether the events associated with the cloned element has to be copied or not. true indicates all the events associated with that div has to be copied.
$(function() {
$('.list-row').each(function(){
$(".left-col").append($(this).clone(true));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="left-col">
<div class="list-row"><h1>This is original row</h1></div>
</div>
$(function() {
var leftcol = document.getElementsByClassName('left-col');
var listrow = document.querySelector('.list-row');
for (var i = 0; i < 2; i++) {
leftcol.appendChild(listrow.clone(true));
}
})
I would like to sort a few divs in ascending order based on their data-id. How can I do that?
<div class="container" data-id="1000">
<div id="H1"></div>
<div id="sub">sub 1</div>
<div id="sub">sub 2</div>
</div>
<div class="container" data-id="3000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>
<div class="container" data-id="2000">
<div id="H1"></div>
<div id="sub"></div>
<div id="sub"></div>
</div>
I've found the solution to my problem a while ago:
function sortOut() {
// get the classname chapcontainer
var classname = document.getElementsByClassName('container');
// create a variable and put the classes it into an array.
var divs = [];
for (var i = 0; i < classname.length; ++i) {
divs.push(classname[i]);
}
// Sort the divs based on data-id.
divs.sort(function(a, b) {
return +a.getAttribute("data-id") - +b.getAttribute("data-id");
});
};
divs.sort does the trick. More info about this function can be found here:
https://www.w3schools.com/jsref/jsref_sort.asp
This is my first post on stackoverflow. So far I could always find an answer here, but this time I couldn't.
Here is my DOM structure:
<div id="elementA">
<div id="elementB"></div>
<div id="elementC">
<div id="elementD"></div>
</div>
<div id="elementE"></div>
</div>
How can I wrap 2 or more selected "random" elements into a wrapper container? This should also work if the selected elements are on different level and if there are other elements in between. The DOM structure of all other elements shouldn't be effected.
Following a few examples:
Example 1:
I though of something like this:
var element1 = $('#elementB');
var element2 = $('#elementE');
??? $(element1, element2).myWrap(".wrapper"); ???
Result should look like this:
<div id="elementA">
<div class="wrapper">
<div id="elementB"></div>
<div id="elementC">
<div id="elementD"></div>
</div>
<div id="elementE"></div>
</div>
</div>
2 Example:
Elements are in different levels.
var element1 = $('#elementD');
var element2 = $('#elementE');
??? $(element1, element2).myWrap(".wrapper"); ???
Result:
<div id="elementA">
<div id="elementB"></div>
<div class="wrapper">
<div id="elementC">
<div id="elementD"></div>
</div>
<div id="elementE"></div>
</div>
</div>
Example 3: More than 2 elements:
var element1 = $('#elementD');
var element2 = $('#elementC');
var element3 = $('#elementA');
??? $(element1, element2, element3).myWrap(".wrapper"); ???
<div class="wrapper">
<div id="elementA">
<div id="elementB"></div>
<div id="elementC">
<div id="elementD"></div>
</div>
<div id="elementE"></div>
</div>
</div>
Example 4: Different trees:
var element1 = $('#elementD');
var element2 = $('#elementF');
??? $(element1, element2).myWrap(".wrapper"); ???
<div id="elementA">
<div id="elementB"></div>
<div class="wrapper">
<div id="elementC">
<div id="elementD"></div>
</div>
<div id="elementE">
<div id="elementF"></div>
</div>
</div>
</div>
As was pointed out in the comments above, the first example is different to the others in that when the specified children are all direct decendants, then all children in the common parent should be wrapped.
Using this logic, the following solution works.
jQuery.fn.myWrap = function(options) {
var e = this;
// find most nested
var max = null;
var $mostNested = null;
$(e).each(function(i, elem) {
var parents = $(elem).parents().length;
if (parents > max || max == null) {
max = parents;
$mostNested = $(elem);
}
})
// find common parent
var found = false;
$parent = $mostNested.parent();
while($parent != null && !found) {
if ($parent.find(e).length == e.length) {
// Right Level
found = true;
var toWrap = [];
var numDirect = 0;
$.each($parent.children(), function(i, item) {
var direct = $(e).index(item) >= 0;
var sibling = $(item).find(e).length > 0;
if (direct) numDirect++;
if (direct || sibling) toWrap.push(item);
})
if (numDirect == e.length) {
// All direct! (Example 1)
$parent.children().wrapAll("<div class='wrapper'></div>");
} else {
// Other Examples
$(toWrap).wrapAll("<div class='wrapper'></div>");
}
}
$parent = $parent.parent();
}
};
$(document).ready(function() {
// Example 1
$('#elementB, #elementE').myWrap();
// Example 2
//$('#elementD, #elementE').myWrap();
// Example 3
//$('#elementD, #elementC, #elementA').myWrap();
// Example 4
//$('#elementD, #elementF').myWrap();
})
See my fiddle.
I have the following list of divs and I'd like to be able to sort them using Javascript / JQuery.
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
I'd like to be able to sort the items by their Genre/Name/Location alphabetically.
Example: If Sort by Genre was clicked, it would sort the items in 0-9 A-Z by Genre.
If any of you have any tips it would greatly be appreciated.
Cheers :)
You have to make a little change to html like following:
<div id="container">
<div class="item">
<div class="genre">Classical</div>
<div class="name">Alpha</div>
<div class="location">London</div>
</div>
<div class="item">
<div class="genre">Blues</div>
<div class="name">Bravo</div>
<div class="location">New York</div>
</div>
<div class="item">
<div class="genre">Pop</div>
<div class="name">Charlie</div>
<div class="location">Paris</div>
</div>
</div>
<div class="buttons">
Sort by Genre
Sort by Name
Sort by Location
</div>
jQuery
function sorting(tag) {
var items = $('div.item').sort(function(a, b) {
var txt1 = $.trim($('div.' + tag, a).text()),
txt2 = $.trim($('div.' + tag, b).text());
if (txt1 > txt2) return 1;
else return -1;
});
return items;
}
$('.buttons a').on('click', function(e) {
e.preventDefault();
$('div#container').html(sorting(this.id));
});
Working Sample
Ok, this would be my pure JS solution.
First, we should wrap your <div>s into a larger container.
<div id = "wrapper">
<div id = "item">...</div>
<div id = "item">...</div>
<div id = "item">...</div>
</div>
Now, let's define a constant - which property do you want to sort it by? (this will probably be a function parameter later in your code).
var propName = "genre";
Let's get all the <div>s and put them in an array.
var items = document.getElementsByClassName("item");
var itemsArray = new Array();
Let us sort them lexicographically according to the text of the selected property.
for (var i = 0; i < items.length; i++)
itemsArray.push(items[i]);
itemsArray.sort(function(a, b) {
var aProp = a.getElementsByClassName(propName)[0].firstChild.nodeValue;
var bProp = b.getElementsByClassName(propName)[0] .firstChild.nodeValue;
if (aProp < bProp)
return -1;
else if (aProp > bProp)
return 1;
else
return 0;
});
Let us construct a document fragment consisting of the sorted <div>s.
var fragment = document.createDocumentFragment();
for (var i = 0; i < itemsArray.length; i++)
fragment.appendChild(itemsArray[i].clone());
Finally, let us clear the contents of the <div id = "wrapper"> and replace it with the document fragment.
document.getElementById('wrapper').innerHTML = '';
document.getElementById('wrapper').appendChild(fragment);
Also, note that document.getElementsByClassName does not work in IE<9, but I was now really lazy to cope with that issue.
A fiddle: http://jsfiddle.net/nNXr4/
Check this beast:
function sortByCreatedOnAsc(a,b){
return $(a).find('.created_on').text() > $(b).find('.created_on').text();
}
function sortByCreatedOnDesc(a,b){
return $(a).find('.created_on').text() < $(b).find('.created_on').text();
}
function reorderEl(el){
var container = $('#tasks');
container.html('');
el.each(function(){
$(this).appendTo(container);
});
}
$('#created_on').click(function(){
if($(this).hasClass("asc")){
reorderEl($('.task').sort(sortByCreatedOnDesc));
$(this).removeClass("asc");
$(this).addClass("desc");
} else {
reorderEl($('.task').sort(sortByCreatedOnAsc));
$(this).removeClass("desc");
$(this).addClass("asc");
}
return false;
});
jsfiddle: http://jsfiddle.net/jKJc3/116/