Following is my code and relevant HTML , what i wanna do is that i wanna count the number of search-img-box within search-img-ctrl but i get 0 as output, just to tell here that
following div search-img-box is dynamically created.
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl').filter('.search-img-box').length;
alert(numberOfDivs);
});
following is my HTML
<div id="search-img-ctrl" class="search-img-ctrl">
<div id="search-img-box" class="search-img-box" name="search-img-box">
<img width="335" height="206" src="" alt="">
<ul>
</div>
<div id="search-img-box" class="search-img-box" name="search-img-box">
</div> </div>
Here's a fiddle: http://jsfiddle.net/t5jcT/
I changed filter to find and got rid of the duplicate ids in the html.
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl').find('.search-img-box').length;
alert(numberOfDivs);
});
or you can use selectors instead of the find as others have pointed out:
jQuery(document).ready(function() {
var numberOfDivs = jQuery('#search-img-ctrl .search-img-box').length;
alert(numberOfDivs);
});
use .find instead of .filter:
var numberOfDivs = jQuery('#search-img-ctrl').find('.search-img-box').length;
alert(numberOfDivs);
If you want to only find the number of direct children with that class you can use .children
var numberOfDivs = jQuery('#search-img-ctrl').children('.search-img-box').length;
Also make sure you edit your html so that your html elements don't have duplicate IDs
Related
I have a function that's run on a button click. This function will get all of the HTML inside a certain element. That works fine. However, I would like to clean the returned string (HTML) up before using it further in my function:
exportHTML(){
const element = document.getElementById('content');
const innerHTML = element.innerHTML;
}
This works. But due to using Angular, Angular syntax is included within the HTML based on conditions in the source code. For example:
<div _ngcontent-c1=""></div>
OR
<div ng-reflect-klass="panel album"></div>
<div ng-reflect-ng-class="blue"></div>
Is it at all possible to filter these types of values out? In regards to the second and third example above, the classes within those would change quite often:
Is it possible to filter out and remove all _ngcontent-c1="" text
Is it possible to filter out and remove all ng-reflect-klass & ng-reflect-ng-class including the following open and closed quotes (to remove what's inside)
OK, so the attributes would be constant but the values of the attributes would change? If so, you could try this:
.replace(/ng-reflect-klass=\".?\"/,"").replace(/ng-reflect-ng-class=\".?\"/,"").replace(/_ngcontent-c1=\".*?\"/,"")
var content = 'stuff<div ng-reflect-klass="panel album"></div><div ng-reflect-ng-class="blue"></div><div _ngcontent-c1=""></div>end stuff';
console.log(content.replace(/ng-reflect-klass=\".*?\"/g,"").replace(/ng-reflect-ng-class=\".*?\"/g,"").replace(/_ngcontent-c1=\".*?\"/g,""));
Look at the console to view the result.
You could do it with RegExp
const innerHTML = element.innerHTML.replace(/ (_ngcon|ng-).*?".*?"/g, '');
(_ngcon|ng-) find _ngcon or ng- including space as first character
.*?" match everything until first "
.*?" and match everything again for the closing "
I created a JSFiddle as an example of how to do this without using jQuery.
Using the HTML code below as an example
<div id="origin-content">
<div id="div1" _ngcontent-c1="">Content 1</div>
<div id="div2" ng-reflect-klass="panel album">Content 2</div>
<div id="div3" ng-reflect-ng-class="blue">Content 3</div>
</div>
<hr>
<div id="target-content">
</div>
I extracted all children from origin-content and copied them to target-content using the code that follows.
var result = document.getElementById('target-content');
var elems = document.querySelector('#origin-content').children;
var count = elems.length;
for (var i = 0; i < count; i++) {
var val = elems[i];
val.removeAttribute('_ngcontent-c1');
val.removeAttribute('ng-reflect-klass');
val.removeAttribute('ng-reflect-ng-class');
result.innerHTML += val.outerHTML;
}
There is still plenty of room for improvement.
I hope it helps to solve the OP question.
The following solution will remove all the attributes from element:
You can get all the children first. Then loop through them with forEach(). In each iteration, you can use while loop to removeAttribute() until they are exist in the element.
Try the following way:
function exportHTML(){
const element = document.getElementById('content');
const innerHTML = [].slice.call(element.children);
innerHTML.forEach(function(el){
while(el.attributes.length > 0)
el.removeAttribute(el.attributes[0].name);
});
console.log(document.getElementById('content').innerHTML); // output
}
exportHTML();
<div id="content">
<div _ngcontent-c1=""></div>
<div ng-reflect-klass="panel album"></div>
<div ng-reflect-ng-class="blue" another-test></div>
<span test="test-element"></span>
</div>
I have a series of html contents called filters which is generated from database. The contents can change dynamically according to the page. I have given css IDs to each main div and appended a number with them while looping. Below is a sample snippet:
<div><a id="filter-1">Brands</a></div>
<div id="filter-op-1">This is option 1</div>
<div><a id="filter-2">Size</a></div>
<div id="filter-op-2">This is option 2</div>
<div><a id="filter-3">Color</a></div>
<div id="filter-op-3">This is option 3</div>
the ids filter-1 and filter-op-1 and so on are generated by the number of loops, so we dont know how much contents on the page will be generated for the filters.
I need to show/hide the filter-op-x contents by a click, so i wrote the following jQuery code:
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('id');
var child = $('div#filter-op-'+cssId);
child.toggle();
});
});
Now the problem is that it is not working in this way, but if i remove the cssId in js code and -1, -2 etc in html, it start working, but it is hiding all contents no matter which a i clicked.
I dont understant what is causing this issue. Anybody can explain this problem and give some good advice how to handle it?
JsFiddle is here
Thanks
You need to make some changes in your JS code like this:
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('id');
console.log(cssId); // This gives the `a` id.
var id = cssId.split("-")[1]; // Split and get the number part
console.log(id);
var child = $('div#filter-op-'+id); // append the number part here
child.toggle();
});
});
The fiddle: https://jsfiddle.net/sandenay/uk1Lquuh/1/
Problem found :
your cssId always return filter-1, filter-2, filter-3
and child become as 'div#filter-op-'+cssId) ==> 'div#filter-op-filter-1 which is produce wrong id of child div.
I have added extra data attribute
Here is my working code:
HTML :
<div><a id="filter-1" data="1">Brands</a></div>
<div id="filter-op-1">This is option 1</div>
<div><a id="filter-2" data="2">Size</a></div>
<div id="filter-op-2">This is option 2</div>
<div><a id="filter-3" data="3">Color</a></div>
<div id="filter-op-3">This is option 3</div>
JS :
$(document).ready(function () {
$('div a').click(function() {
var self = $(this);
var cssId = self.attr('data');
var child = $('div#filter-op-'+cssId);
child.toggle();
});
});
updated JSFIDDLE example
What I am trying to do is very simple, but I have no idea how I can store result back? So what I am doing here
<div id="test_div">
<div class="wrapper1">My logo wrapper</div>
<div class="keep">My Table</div>
<div class="wrapper2">My Wrapper</div>
</div>
Now, using Javascript, with jQuery, I'll get everything like following:
function foo() {
var html = document.getElementById("test_div").innerHTML;
//now I want to remove some inner divs
var result = $(html).remove("wrapper1"); //I know this is wrong
//but I would like to do something like above, so after I remove an element
//and its contents, the function will return a result
}
So, it's very simple but I don't know how I can do this: first remove a div element inside test_div and then return the remaining contents of test_div. Sorry I forgot to add one very important line I don't wont to remove element from the current page as suggested solution and even using remove method will remove it from the main page So I wanted to keep as it is on the main page but remove and just get refine result to store in result var
Try this :
fiddle : http://jsfiddle.net/3trqLju4/
<div id="test_div">
<div class="wrapper1">My logo wrapper</div>
<div class="keep">My Table</div>
<div class="wrapper2">My Wrapper</div>
</div>
<input type="button" id="btn" value="refine"/>
$("#btn").click(function()
{
var copyhtml = $("#test_div").clone();
$(copyhtml).find(".wrapper1").remove();
alert(copyhtml.html());
});
$(html).remove(".wrapper1");
and
result = document.getElementById("test_div").innerHTML;
Assuming you would like to remove wrapper1 from test_div, you could use:
$("#wrapper1").remove();
If you would like to move wrapper1 and use it later:
var wrapper1 = $("#wrapper1").detach();
$(wrapper1).appendTo("#some-new-div");
I want to get img tags attribute values from any element, img tags could be more than 1, and also can be randomized.
like,
<div> hellow <img src='icons/smile.png' title=':)'> how are u <img src='icons/smile2.png' title=':D'></div>
I want to grab their title attribute values and then want to store in some var currentHTML; with all existing div data.
and then insert into any element just like $('#div').html(currentHTML);
and output should be like this,
hellow :) how are u :D
How can I do this?
Thanks in advance.
Try this:
$("img").each(function()
{
$(this).replaceWith($(this).prop("title"));
});
Fiddle. Its just looping through each image and replacing it (with replaceWith()) with its own title attribute.
UPDATE:
Things got more complex. Check this snippet:
// The text result you want
var currentHTML = "";
// Instead of search for each image, we can search of elements that
// contains images and you want to get their text
$(".images").each(function()
{
// Check note #1
var cloned = $(this).clone().css("display", "none").appendTo($("body"));
// Here we select all images from the cloned element to what
// we did before: replace them with their own titles
cloned.find("img").each(function()
{
$(this).replaceWith($(this).prop("title"));
});
// Add the result to the global result text
currentHTML+= cloned.html();
});
// After all, just set the result to the desired element's html
$("#div").html(currentHTML);
Note #1: Here is what is happening in that line:
var cloned = here we create a var which will receive a cloned element;
the cloned element will the current element $(this).clone();
this element must be hidden .css("display", "none");
and then appended to the document's body .appendTo($("body"));.
Note that in your initial html, the div containing the images received the class images:
<div class="images"> hellow <img src='icons/smile.png' title=':)' /> how are u <img src='icons/smile2.png' title=':D' /></div>
So you can do that on more than one element. I hope this helps.
Here's a neat little function you can reuse.
$(function(){
function getImageReplace($el) {
var $copy = $el.clone();
$copy.find('img').each(function(){
$(this).replaceWith($(this).attr('title'));
});
return $copy.text();
}
//now you can use this on any div element you like
$('#go').click(function() {
alert(getImageReplace($('div')));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> hellow <img src='icons/smile.png' title=':)'> how are u <img src='icons/smile2.png' title=':D'></div>
<button id='go'>Convert images</button>
HTML:
<div class="my_1"></div>
<div class="my_big">
<div class="small" id="id_1"></div>
<div class="small" id="id_2"></div>
<div class="small" id="id_3"></div>
<div class="small" id="id_4"></div>
</div>
javascript:
var css_scope=$(".my_big");
var next_div=$(".my_1").nextAll('.small',css_scope).first();
console.log(" \n next div = "+ next_div.attr('id'));
console shows undefined. But if I exclude the my_big div from html and define var next_div in javascript as follows:
var next_div=$(".my_1").nextAll('.small').first();,
expected output is obtained.
How to make nextAll() work with the mentioned css scoping ?
.nextAll is used to find all the next siblings, you should find the .small from the result of nextAll.
var next_div=$(".my_1").nextAll('.my_big').find('.small').first();
You cannot get to .small from my_1 using nextAll() since they are not siblings. You can get to it using the following selector.
// Get the first element matching ".small" inside an element matching ".my_big"
// that comes immediately after an element matching ".my_1"
var next_div = $('.my_1 + .my_big > .small:first');
Check this demo: http://jsfiddle.net/q6XKR/
If you want to access the first element in my_big div, there's no need to bring my_1 into the scene.
var next_div = $('.my_big').find('.small').first();
console.log(" \n next div = "+ next_div.attr('id'));
Hope it clarifies you somewhat about traversing elements in jQuery.