Highlight results when searching divs - javascript

I have a div setup like this:
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">lorem ipsum test test1 testing</div>
</div>
<div class="entry">
<div class="title">attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>
And I allow the user to search the divs with:
jQuery(document).ready(function() {
jQuery("#search").on("keyup click input", function () {
var val = jQuery(this).val();
if (val.length) {
jQuery(".entry").hide().filter(function () {
return jQuery('.title, .description',this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
}).show();
}
else {
jQuery(".entry").show();
}
});
});
Works great, try jsFiddle.
My question is, how can I highlight the search terms? For example, if the user searches for test, I want to wrap the text test into <span> tags.
EDIT: Note that I know how to search/replace text, but I can't seem to make it work properly with my search function.

Optimised solution
After all the issues discussed in comments and trying to optimise the solution so it won't have any lack for eventual bugs, I refactored the code and optimised it:
$(document).ready(function() {
$("#search").on("keyup click input", function() {
var val = jQuery(this).val();
var regExp = new RegExp(val, 'ig');
var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
if (val.length) {
$(".entry").hide().filter(function() {
var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
if (val.length > 3) {
$('.title, .description', this).each(function(k, v) {
if ($(v).text().match(regExp)) {
$(v).html($(v).text().replace(regExp, '<span class="highlight">$&</span>'));
} else {
$(v).html($(v).text().replace(reg, '$&'));
}
});
} else {
$('.title, .description', this).each(function(k, v) {
$(v).html($(v).text().replace(reg, '$&'));
});
}
return found;
}).show();
} else {
$('.title, .description').each(function(k, v) {
$(v).html($(v).text().replace(reg, '$&'));
});
$(".entry").show();
}
});
});
.highlight {
background-color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">lorem ipsum test test1 testing</div>
</div>
<div class="entry">
<div class="title">attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>
It loops over the elements and use a RegExp with a matching group and if the iterated element content matches the Regex replace the matched text with the same content wrapped in a span, otherwise just set the content to its original form.
Original Answer
This is how you should do it:
var val = jQuery(this).val();
if (val.length) {
$(".entry").hide().filter(function() {
var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
var regExp = new RegExp(val, 'ig');
$('.title, .description', this).each(function(k, v) {
if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
$(v).html(newHTML);
}
});
return found;
}).show();
} else {
$(".entry").show();
}
You need to loop over the elements and use a RegExp with a matching group and if this element content matches your Regex replace the matched text with the same content wrapped in a span.
Demo:
This is a working Demo:
$(document).ready(function() {
$("#search").on("keyup click input", function() {
var val = jQuery(this).val();
if (val.length) {
$(".entry").hide().filter(function() {
var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
var regExp = new RegExp(val, 'ig');
$('.title, .description', this).each(function(k, v) {
if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
$(v).html(newHTML);
}
});
return found;
}).show();
} else {
$('.title, .description').each(function(k, v) {
var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
var newHTML = $(v).text().replace(reg, '$&');
$(v).html(newHTML);
});
$(".entry").show();
}
});
});
.highlight {
background-color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">lorem ipsum test test1 testing</div>
</div>
<div class="entry">
<div class="title">attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>
Edit:
This is a Demo that highlights sentences only if more than 2 letters are typed:
$(document).ready(function() {
$("#search").on("keyup click input", function() {
var val = jQuery(this).val();
if (val.length) {
$(".entry").hide().filter(function() {
var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
var regExp = new RegExp(val, 'ig');
if (val.length > 2) {
$('.title, .description', this).each(function(k, v) {
if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
$(v).html(newHTML);
}
});
} else {
$('.title, .description').each(function(k, v) {
var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
var newHTML = $(v).text().replace(reg, '$&');
$(v).html(newHTML);
});
}
return found;
}).show();
} else {
$('.title, .description').each(function(k, v) {
var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
var newHTML = $(v).text().replace(reg, '$&');
$(v).html(newHTML);
});
$(".entry").show();
}
});
});
.highlight {
background-color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">lorem ipsum test test1 testing</div>
</div>
<div class="entry">
<div class="title">attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>

Try with contains(text) instead of filter() .initially hide the All div .Then Show only the text contains div .And apply the span element to matching letter in the children using new RegExp()
For ignore case sensitive match ig in regex and also added code for case insensitive for contains
Updated Fix with .title, .description on children
jQuery(document).ready(function() {
jQuery("#search").on("input", function() {
var val = jQuery(this).val()
jQuery(".entry").hide()
jQuery(".entry:contains(" + val + ")").show()
jQuery(".entry").each(function() {
if ($(this).find(".title, .description:contains(" + val + ")")) {
$(this).find(".title, .description:contains(" + val + ")").html(function() {
return $(this).text().replace(new RegExp('('+val+')', 'ig'), '<span>$1</span>')
})
}
})
});
})
jQuery.expr[':'].contains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
.entry {
background: #fff;
margin-bottom: 10px;
width: 300px;
}
span {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">lorem ipsum test test1 testing</div>
</div>
<div class="entry">
<div class="title">Attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>
<div class="entry">
<div>
<div class="title">For nested element on titan</div>
<div>
<div class="description">fullmetal alchemist nested</div>
</div>
</div>
</div>

Try this:
document.getElementById('search').onkeyup = userInput;
document.getElementById('search').onclick = userInput;
document.getElementById('search').oninput = userInput;
var allEntries = document.querySelectorAll('.entry');
function userInput () {
var val = this.value;
for (var i = 0; i < allEntries.length; i++) {
var entryElement = allEntries[i];
var title = entryElement.querySelector('.title');
var description = entryElement.querySelector('.description');
var noHtmlSearchStr = '';
if (title) noHtmlSearchStr += title.innerText;
if (description) noHtmlSearchStr += description.innerText;
if (noHtmlSearchStr.length > 0) {
if (noHtmlSearchStr.toLowerCase().indexOf(val.toLowerCase()) != -1) {
// Remove existing <b> tags.
var regexp1 = new RegExp('(<b>|<\/b>)', 'gi');
if (title) title.innerHTML = title.innerHTML.replace(regexp1, '');
if (description) description.innerHTML = description.innerHTML.replace(regexp1, '');
if (val.length > 3) {
var regexp2 = new RegExp('(' + val + ')(?!>)', 'gi');
if (title) title.innerHTML = title.innerHTML.replace(regexp2, '<b>$1</b>');
if (description) description.innerHTML = description.innerHTML.replace(regexp2, '<b>$1</b>');
}
entryElement.style.display = 'block';
} else {
entryElement.style.display = 'none';
}
}
}
}
.entry {
background: #fff;
margin-bottom: 10px;
width: 300px;
}
<input id="search">
<div class="entry">
<div class="title">hello world test 123</div>
<div class="description">div lorem <span>ipsum</span> test <div>test1</div> testing span</div>
</div>
<div class="entry">
<div class="title">attack on titan</div>
<div class="description">fullmetal alchemist</div>
</div>
<div class="entry"></div>
<div class="entry">
<div class="title">attack on titan</div>
</div>
<div class="entry">
<div class="description">Let's not go to Camelot, 'tis a silly place</div>
</div>
Explanation of JS code
Bind all events to the userInput() function.
Get all elements with the .entry class and store them in allEntries.
Get the user's input and store in val.
Iterate through allEntries.
Get the text to search on from title and description and store in noHtmlSearchStr.
If val matches some part of noHtmlSearchStr then show the entryElement, otherwise hide it.
Remove <b> tags from title and description.
If the length of the user's search (val) is longer than three characters, highlight the matches on the text, otherwise, don't highlight anything.

Related

jQuery Select Visible Elements After Append

I'm trying to select visible children after appending them into a temp div.
But I got undefined. I've prepared a pen here: codepen
function createTemp() {
var innerObj = $('.main');
var el = $('<div class="doc-temp" style="display: none;"><div class="temp2">' + innerObj.html() + '</div></div>');
$('body').append(el);
var visible = el.children(':visible');
return visible;
}
console.log(createTemp().html());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Well</span> Hello
<span>Three</span> Hi Hello
<span style="display: none;">Four</span>
<span>Five</span> See you
</div>
If your element is hidden it will NOT have ANY :visible descendants!
Also you need the HTML of main
If you want the children that WOULD be visible if the PARENT was, you can do this:
function createTemp() {
var innerObj = $('.main').html();
var el = $('<div class="doc-temp"><div class="temp2"></div></div>');
$("body").append(el);
$(".temp2").append(innerObj);
var children = $(".temp2")[0].childNodes;
return [...children].map(el => {
if (el.getAttribute) {
return el.getAttribute("style") === "display: none;" ? null : el.outerHTML
}
return el === null ? null : el.textContent;
})
}
$("#ta").val(createTemp().join(""));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Well</span> Hello
<span>Three</span> Hi Hello
<span style="display: none;">Four</span>
<span>Five</span> See you
</div>
<textarea rows="100" cols="100" id="ta"></textarea>
Modify your function to below:
function createTemp(){
var innerObj = $('.main');
var el = '<div class="doc-temp" style="display: none;"><div class="temp2">' + innerObj.html() + '</div></div>';
$('body').append(el);
var visible = $('.main').find(':visible');
return visible;
}
After this change, you can iterate through the visible array. Use $.each for this iteration process.

jQuery turn string into span multiple instances

I am trying to separate the .string into span elements for every .item but cannot find the proper way to do it.
I tried the function below but cannot get it working so that it only works on the closest .item.
$(".string").html(
$(".string")
.html()
.split(" ")
.map(function(el) {
return "<span>" + el + "</span>";
})
);
$(".item").each(function() {
var arr = $(".string").text().split(" ");
var html = "";
for (i = 0; i < arr.length; ++i) {
html += "<span>" + arr[i] + "</span>";
}
$(".this").closest(".string").html(html);
});
.string span {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>
You first need to .find the .string inside the .item being iterated over with
var arr = $(this).find(".string").text().split(" ");
else your $(".string") will only match the first .string in the document. Then, to set the child .string of the .item being itearted over, use
$(this).find(".string").html(html);
(closest searches ancestors, not children)
Also make sure not to implicitly create a global variable with
for (i = 0; i < arr.length; ++i) {
(always declare variables you're going to use with const, let, or var)
$(".item").each(function() {
var arr = $(this).find(".string").text().split(" ");
var html = "";
for (let i = 0; i < arr.length; ++i) {
html += "<span>" + arr[i] + "</span>";
}
$(this).find(".string").html(html);
});
.string span {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>
Or, if possible, you might iterate over the .strings directly:
$(".string").each(function() {
var arr = $(this).text().split(" ");
var html = "";
for (let i = 0; i < arr.length; i++) {
html += "<span>" + arr[i] + "</span>";
}
$(this).html(html);
});
.string span {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>
Another option would be to use a regular expression replace - find non-space characters ((\S+)), and replace with those matched non-space characters surrounded by a span: <span>$1</span>:
$(".string").each(function() {
$(this).html(
$(this).html().replace(/(\S+)\s*/g, '<span>$1</span>')
);
});
.string span {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>
You have little bit mistake in your code. change var arr = $(".string").text().split(" "); to var arr = $(this).find(">.string").text().split(" "); to find the .string inside the .item which is in current iteration of loop.
And change $(".this").closest(".string").html(html); to $(this).find(">.string").html(html); to replace the html of .string inside the .item which is in current iteration of loop.
$(".item").each(function() {
var arr = $(this).find(">.string").text().split(" ");
var html = "";
for (i = 0; i < arr.length; ++i) {
html += "<span>" + arr[i] + "</span>";
}
$(this).find(">.string").html(html);
});
.string span {
border: 1px solid
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>
Loop over all the .string elements and create a span for each text splitting by spaces.
Then replace the current div with the created spans:
$.each($('.string'), (ind, val) => {
const spans = $(val).text().split(' ').map(text => $(`<span>${text}</span>`));
$(val).replaceWith(spans);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item">
<div class="string">Test1 Test2 Test3</div>
</div>
<div class="item">
<div class="string">TestA TestB TestC</div>
</div>

Keep element in the bottom of dynamically changing panel

I'm using bootstrap and i have text fields which will make panel larger as they're added dynamically. Now these text fields are inside of a panel element and textfield size is col-lg-9 and there's more room in the col-lg-3 right next to it.
I would like to place a button in that col-lg-3 div, which would stay always in the bottom of the panel - so if the panel height increases due to new text field the button stays still in the bottom. I've tried absolute and relative positioning but nothing has helped + some of the methods pointed out break the scalability (which i really need to keep).
I'm adding my code:
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title panel-header-text">Sisesta nimed, mis pannakse tabelisse</h3>
</div>
<div class="panel-body">
<div class="col-lg-9" id="inputcontainer">
<h4>Sisestamisel tekib uus väli (TAB-iga saab vahetada rida). Tühjasid välju ei arvestata!</h4>
<div class="input-group input-group-lg pdgtop">
<span class="input-group-addon" id="basic-addon1">1.</span>
<input type="text" id="one" class="form-control text-controller" placeholder="Sisesta nimi siia">
</div>
</div>
<div class="col-lg-3 konteiner">
<button type="button" class="btn btn-success buttonel">Valmista tabel</button>
</div>
</div>
The javascript:
/*
#FN01: This function handles the creation of new text fields according to the change in the textfield.
*/
var createNew = true;
var counter = 2;
function getNewInsertion() {
var container = document.getElementById("inputcontainer");
var inputs = document.getElementsByClassName("text-controller");
var lastField = inputs[inputs.length-1];
if (document.activeElement.value.length == 0 && createNew == false){ //if new element is chosen createNew will be set true
createNew = true;
}
else if (createNew == true && lastField.value.localeCompare("") != 0 ){
createNew = false;
//Creates Input Field
var input = document.createElement("input");
input.type = "text";
input.className = "form-control text-controller";
input.placeholder = "Sisesta siia nimi";
//Creates Span to hold the count
var span = document.createElement("span");
span.textContent = counter;
span.className = "input-group-addon";
//Creates input group to put span & input field together
var inputgroup = document.createElement("div");
inputgroup.className = "input-group input-group-lg";
inputgroup.appendChild(span);
inputgroup.appendChild(input);
container.appendChild(inputgroup);
counter += 1;
}
return createNew;
}
/*
#FN02: This is the function to delete the last field (empty) in case the one before last is empty.
*/
function canWeDeleteField(){
var inputs = document.getElementsByClassName("input-group");
var lastInput = inputs[inputs.length-1];
var lastArr = lastInput.childNodes
if (inputs.length < 2){
var last = lastArr[3];
}
else{
var last = lastArr[1];
}
console.log(lastArr);
if (inputs.length >= 2){
var last_prev_Input = inputs[inputs.length-2];
var last_prev_Arr = last_prev_Input.childNodes
if (inputs.length == 2){
var last_prev = last_prev_Arr[3];
}
else{
var last_prev = last_prev_Arr[1];
}
if (last.value.localeCompare("") == 0 && last_prev.value.localeCompare("") == 0){
lastInput.parentNode.removeChild(lastInput);
counter = counter - 1;
}
}
}
/*
#FN03: The call-out function which is triggered when key is pressed while focus is on the textfield.
*/
$(function() {
$("#inputcontainer").bind("paste cut keydown",function(e) {
getNewInsertion();
canWeDeleteField();
})
});
AND THE CSS:
.konteiner {
position: relative;
}
.buttonel {
width: 95%;
padding-right: 1%;
position: absolute;
}
You can check the solution to your problem in the following link Bootstrap equal-height columns experiment.
Basically you have to wrap your columns in a div element containing the classes "row" and "row-eq-height".
Here's a snippet of the result (using your code):
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="http://getbootstrap.com/dist/css/bootstrap.min.css">
<style type="text/css">
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.buttonel {
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title panel-header-text">Sisesta nimed, mis pannakse tabelisse</h3>
</div>
<div class="panel-body">
<div class="row row-eq-height">
<div class="col-lg-9 col-md-9" id="inputcontainer">
<h4>Sisestamisel tekib uus väli (TAB-iga saab vahetada rida). Tühjasid välju ei arvestata!</h4>
<div class="input-group input-group-lg pdgtop">
<span class="input-group-addon" id="basic-addon1">1.</span>
<input type="text" id="one" class="form-control text-controller" placeholder="Sisesta nimi siia">
</div>
</div>
<div class="col-lg-3 col-md-3">
<button type="button" class="btn btn-success buttonel">Valmista tabel</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var createNew = true;
var counter = 2;
function getNewInsertion() {
var container = document.getElementById("inputcontainer");
var inputs = document.getElementsByClassName("text-controller");
var lastField = inputs[inputs.length - 1];
if (document.activeElement.value.length == 0 && createNew == false) { //if new element is chosen createNew will be set true
createNew = true;
} else if (createNew == true && lastField.value.localeCompare("") != 0) {
createNew = false;
//Creates Input Field
var input = document.createElement("input");
input.type = "text";
input.className = "form-control text-controller";
input.placeholder = "Sisesta siia nimi";
//Creates Span to hold the count
var span = document.createElement("span");
span.textContent = counter;
span.className = "input-group-addon";
//Creates input group to put span & input field together
var inputgroup = document.createElement("div");
inputgroup.className = "input-group input-group-lg";
inputgroup.appendChild(span);
inputgroup.appendChild(input);
container.appendChild(inputgroup);
counter += 1;
}
return createNew;
}
/*
#FN02: This is the function to delete the last field (empty) in case the one before last is empty.
*/
function canWeDeleteField() {
var inputs = document.getElementsByClassName("input-group");
var lastInput = inputs[inputs.length - 1];
var lastArr = lastInput.childNodes
if (inputs.length < 2) {
var last = lastArr[3];
} else {
var last = lastArr[1];
}
console.log(lastArr);
if (inputs.length >= 2) {
var last_prev_Input = inputs[inputs.length - 2];
var last_prev_Arr = last_prev_Input.childNodes
if (inputs.length == 2) {
var last_prev = last_prev_Arr[3];
} else {
var last_prev = last_prev_Arr[1];
}
if (last.value.localeCompare("") == 0 && last_prev.value.localeCompare("") == 0) {
lastInput.parentNode.removeChild(lastInput);
counter = counter - 1;
}
}
}
/*
#FN03: The call-out function which is triggered when key is pressed while focus is on the textfield.
*/
$(function() {
$("#inputcontainer").bind("paste cut keydown", function(e) {
getNewInsertion();
canWeDeleteField();
})
});
</script>
</body>
</html>
Hope it helps!

Implementing colspan on DIVS

I have a div layout like this
Style
.l-item{
display:inline-block;
border:1px solid #CCC;
width:20px;
height:20px
}
<div id="head">
<div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">a</div>
<div class="l-item">b</div>
<div class="l-item">b</div>
</div>
<div>
<div class="l-item">x</div>
<div class="l-item">y</div>
<div class="l-item">z</div>
<div class="l-item">z</div>
<div class="l-item">z</div>
<div class="l-item">x</div>
</div>
<div>
<div class="l-item">1</div>
<div class="l-item">2</div>
<div class="l-item">3</div>
<div class="l-item">4</div>
<div class="l-item">4</div>
<div class="l-item">4</div>
</div>
</div>
My requirement is to merge similar valued and sibling DIVS into single DIV as colspan. For that I have an approach like below
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
$(this).siblings().filter(function(){
return $(this).text() == txt;
});
});
});
It seems like it will mess with the DOM, any other solution for this please..
Try this out:- http://jsfiddle.net/adiioo7/rnL3h/
JS:-
$('#head > div').each(function () {
$(this).find('.l-item').each(function () {
var txt = $(this).text();
var items = $(this).siblings().filter(function () {
return $(this).text() == txt;
});
if (items.length > 0) {
$(this).width($(this).width() * (items.length + 1));
items.remove();
}
});
});
Here's a little bit of help to get you started: http://jsfiddle.net/WeJmu
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
var num_eaten = 0;
$(this).siblings().each(function () {
if ($(this).text() === txt) {
num_eaten++;
$(this).remove();
}
});
if (num_eaten > 0) {
$(this).width($(this).width() * (num_eaten + 1));
}
});
});
different approach with next, you can develop it with better way. demo
$('#head > div').each(function(){
$(this).find('.l-item').each(function(){
var txt = $(this).text();
if( $(this).next().text() == txt){
$(this).next().width($(this).next().width() + 20);
$(this).remove();
}
});
});
if by appearance you want consecutive divs with same text to look like a single div/column;
http://jsfiddle.net/WeJmu/2/
$('#head > div').each(function(){
$(".l-item").each(function(){
var $this=$(this);
var $next=$(this).next();
if( $this.text()==$next.text()){
$this.css({'border-right':'none'});
$next.css({'border-left':'none'});
}
});
});

How to get elements by style property value?

I need to get all div elements with "display: none" style and then remove all of these elements. Also i need to select just that divs which are contained in #somecontainer element. Have to do it in RAW javascript. Any idea?
example html:
<table id="listtabletemp">
<thead>
<tr id="theader">
<td id="theaderleft">loolz</td>
</tr>
</thead>
<tbody>
<tr class="" rel="13117025">
<td><div><style>
.ikthgjyhtr{display:none}
.tVOx{display:inline}
</style>
<div style="display:none">crap here</div>
<div></div>
<div></div>
<div style="display:none">crap here</div>
<div class="230">something good</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display:none">crap here</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display: inline">something good</div>something good
<div style="display: inline">something good</div>
<div class="21">something good</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div class="4">something good</div>
<div class="224">something good</div></div>
</td>
</tr>
</tbody>
</table>
Simple, the DOM is your friend:
function removeDivs() {
var container = document.getElementById("somecontainer");
var divs = container.getElementsByTagName("div");
var empty = [];
var getStyle = function(obj, css){
var style = null;
if(obj.currentStyle) {
style = obj.currentStyle[css];
} else if(window.getComputedStyle) {
style = window.getComputedStyle(obj, null).getPropertyValue(css);
}
return(style);
};
for(var i = 0, len = divs.length; i < len; i++) {
var div = divs[i];
if(div && ((div.style.display && div.style.display == "none") || getStyle(div, "display") == "none")) {
empty.push(div);
}
}
for(var i = 0, len = empty.length; i < len; i++) {
var div = empty[i];
div.parentNode.removeChild(div);
}
}
Quick and dirty, here's something to get you started:
http://jsfiddle.net/kttsJ/
var parent = document.getElementById('parent');
var items = parent.getElementsByTagName('DIV');
var hidden = [];
for (var i in items){
if ((items[i]).getAttribute !== undefined){
if ((items[i]).hasAttribute('style')){
if ((/display\:\s*none/gi).test(items[i].getAttribute('style'))){
hidden.push(items[i]);
}
}
}
}
for (var i in hidden){
hidden[i].parentNode.removeChild(hidden[i]);
}
This removes divs with the "display: none" style. I tested it on the OP's example. Note: I added a "some-container" id when testing.
function removeDivs() {
"use strict";
//Some container.
const someContainer = document.getElementById("some-container");
//Divs inside it.
const divsInside = someContainer.querySelectorAll("div");
//Loop, remove div if "display: none".
divsInside.forEach(function (divInside) {
const style = window.getComputedStyle(divInside);
if (style.display === "none") {
someContainer.removeChild(divInside);
}
});
}
removeDivs();

Categories