Remove style attribute from all descendants in jquery - javascript

I'm brand new to javascript/jquery, but have been going okay so far (though you'd hate to see my code), but I've hit a wall with trying to strip out style tags from some HTML I'm trying to clone.
The reason for cloning is that the CMS I'm forced to use (which I don't have access to code behind, only able to add code over the top) automatically builds a top nav, and I want to add a duplicate sticky nav once the user scrolls, but also add a couple of elements to the scrolled version.
The original HTML of the top nav looks a bit like like:
<nav id="mainNavigation" style="white-space: normal; display: block;">
<div class="index">
Participate
</div>
<div class="index" style="margin-right: 80px;">
News
</div>
<div class="index active" style="margin-left: 80px;">
<a class="active" href="/about/">About</a>
</div>
<div class="external">
Collection
</div>
<div class="index">
Contact
</div>
</nav>
I had mild success (other than those style tags I want to remove) with the following, even though it doesn't seem to make sense to me, as I expected some of the elements would be repeated (the whole < nav >…< /nav > tag should have been within the #mainNavigation clone, no?):
var originalNavItems = $('#mainNavigation').clone().html();
$("#site").prepend('
<div id="ScrollNavWrapper">
<div class="nav-wrapper show-on-scroll" id="mainNavWrapper">
<nav id="newScrolledNav" style="white-space: normal; display: block;">
<div class="index home">
Home
</div>
' + originalNavItems + '
<div class="newItem">
<a href="http://www.externalsite.com">
View on External Site
</a>
</div>
</nav>
</div>
</div>');
I've tried to use a few answers from related questions on here, but I keep getting incorrect results. Can you help me?

You can strip the style elements like so:
var el = $('#mainNavigation'); // or whatever
el.find('[style]').removeAttr('style');

You can use
var originalNavItems = $('#mainNavigation').clone().find("*").removeAttr("style");
Then you can use .append() to add that html elements
Fiddle

You can clone into an imaginary div and then fetch the mainNavigation also. You can also remove the style attributes along with that. Hope this works for you...
var temp = $('<div />').html($('#mainNavigation').clone());
temp.find('*').removeAttr('style');
originalNavItems = temp.html();

The nav is cloned but the html() function only returns the HTML for the contents and that's why it disappears. You can avoid some string manipulation by adding the cloned element directly before a target element.
$("#site").prepend('
<div id="ScrollNavWrapper">
<div class="nav-wrapper show-on-scroll" id="mainNavWrapper">
<nav id="newScrolledNav" style="white-space: normal; display: block;">
<div class="index home">
Home
</div>
<div class="newItem">
<a href="http://www.externalsite.com">
View on External Site
</a>
</div>
</nav>
</div>
</div>');
$('#mainNavigation').clone()
.find('[style]').removeAttr('style').end()
.insertBefore('#newScrolledNav .newItem');
In the previous case find('[style]') matches elements that have a style attribute.

I'm new to Stack Overflow (and js in general), so this might be really bad ettiquette, but I seem to have accidentally fixed it myself trying to debug my implementation of the first upvoted answer that #Anoop Joshi gave above. Please comment and let me know if it would have been better to just edit my question!
I decided to break the process down into separate steps – similar to #Kiran Reddy's response actually, but I hadn't got to trying his yet.
I tried:
var styledHTML = $('#mainNavigation').clone();
styledHTML.find("div[style]").removeAttr('style');
var originalNavItems = styledHTML.html();
$("#site").prepend('<div… etc.
with a console.log(styledHTML) etc under each line to check what I had at each stage – and it worked! (The code did, console.log didn't?)
I was just doing this to try and log the value of the variables at each stage, but whatever I did fixed it…
Now I need to figure out why I can't even make console.log(variable); work :-/

Try this code
$('#mainNavigation').children().removeAttr('style');
Hope this will help you.

Related

Materialize scrollspy offset issue

So to begin with here is the issue:
The red line should be on topicTimer0 not offset above it. The menu is setup at the top of the body with the following code (notably this is not what the original html looks like but rather after elements have been added with jquery):
<div class="col s2 z-depth-2">
<h3>timer</h3>
<hr>
<ul class="section table-of-contents">
<li><h5>topicTimer0</h5>
<ul></ul>
</li>
<li><h5>topicTimer1</h5>
<ul></ul>
</li>
<li><h5>topicTimer2</h5>
<ul></ul>
</li>
</ul>
</div>
Here is what the original html looks like:
<div class="col s2 z-depth-2">
<h3>timer</h3>
<hr>
<ul class="section table-of-contents">
</ul>
</div>
Here is a JSFiddle of it in this state:(https://jsfiddle.net/u1owwv9p/) now it should be noted on JSFIddle it adds some extra issues like adding a new topicTimer to the list and adding another topic header at the bottom, but these issues do not appear in the actual program, the only one that does is the one I have illustrated.
In case it's desired here is a link to the documentation for what I'm doing here:(http://materializecss.com/scrollspy.html).
This is a strictly css question. In order for these two elements to be centered in relation to each other they need to have the same height:
Setting the height of the <a> element to match that of the <h5> element is one solution [materialize.min.css:13]:
.table-of-contents a {
height: 110%
}
I would suggest manipulating the height, line-height and font-size values of both the <a> and <h5> elements to better understand their dependencies and hopefully find the setting that best fits your needs.

JavaScript slideToggle not working

I've run into a little something that I can't figure out and I was wondering if you could have a go at it.
First off, there's this code:
<li class="mc002">
<ul>
<li>
<div class="label-container">
<a class="btn">label 1</a>
<a class="btn">label 2</a>
</div>
<div class="main-container">
<div class="prj-title">
<h3>New design for my website</h3>
<div class="buttons">
<button data-role="none" class="btn smry">summary</button>
</div>
</div>
<div class="summary">
</div>
<div class="prj-footer">
<h6>filed under:</h6>
<span>webdesign, webdevelopment, UX design</span>
<h6>skills:</h6>
<span>html5, css3, javascript, php</span>
</div>
</div>
</li>
and the JavaScript to make "summary" slide down:
$('.main-container .smry').click(function () {
$(this).closest(".summary").slideToggle(100);
});
The problem with this is that it doesn't work. Can you help me out, please?
The .closest() method doesn't find siblings or cousins, it starts with the current element (.smry, in your case) and goes up through the ancestors, stopping when it finds a match (or returning an empty jQuery object if there is no match).
Try this instead:
$('.main-container .smry').click(function () {
$(this).closest(".main-container").find(".summary").slideToggle(100);
});
This navigates up to the closest containing .main-container element and then uses .find() to go back down to its associated .summary element.
Demo: http://jsfiddle.net/4a8JC/
Note that your code would need to be in a document ready handler and/or in a script block that appears after the elements in question.
(Note also that your summary div would need to have some actual content for this to make sense.)
I'll suggest to use just $(".main-container .summary") instead of closest. It's a little bit heavy operation. And do you have something in .summary. If it is an empty I don't think that you will see something.

If element found, hide only the element after

So let's say I have this scenario of articles:
I have a photo in the left and the content of the article right after the image.
In the content area I have a reservation button.
If the article is reserved, then it will be displayed a small image over the bottom of the photo (transparent written "Reserved").
This stuff is all done.
What I want to do next is to remove the hyperlink-button "Reserve" from the article if it's reserved. Should look like this:
-NormalIMG- [Reservation-Button]
-NormalIMG- [Reservation-Button]
-ReservedIMG- *
-NormalIMG- [Reservation-Button]
-ReservedIMG- *
-NormalIMG- [Reservation-Button]
and so on.
*here's no reservation button
So it's something like this:
Reserve
<!-- reserved article -->
<div class="article">
<div class="image"></div>
<div class="image-reserved"><img src="reserved.jpg" /></div>
<div class="content">
Reserve
</div>
</div>
<!-- reserved article //-->
<!-- unreserved article -->
<div class="article">
<div class="image"></div>
<div class="image-reserved"></div>
<div class="content">
Reserve
</div>
</div>
<!-- unreserved article //-->
<!-- reserved article -->
<div class="article">
<div class="image"></div>
<div class="image-reserved"><img src="reserved.jpg" /></div>
<div class="content">
Reserve
</div>
</div>
<!-- reserved article //-->
I tried with jQuery something like this:
if(!($('.image-reserved').find(img))) {
$('.reserveLink').addCSS('display', 'none');
}
But I got all the "Reserve" links removed...
I realized that I need something that should apply that CSS attribute only after the element 'img' was found.
After that, it should continue the search and apply it when it has to.
I lost all my day trying to figure out a way to get out of this by implementing different structures (using find, has, next, etc.) similar to the above example... but no success.
I'm posting here as a last resort, my hope is completely lost to something that seemed to be so easy to implement...
IMPORTANT NOTE: I know the structure looks weird and it might be really hard for what I want to be implemented, but I am not allowed to modify any code that was written already.
You shoud iterate over each image-reserved :
// For each image reserved
$(".image-reserved").each(function(){
// Count the children
var count = $(this).children("img").length;
// If there's a child (The reserved img), then we delete the following links
if(count > 0){
$(this).next().children(".reserveLink").hide();
}
});
$('.image-reserved').next().hide()
I'd suggest:
$('.content').filter(function(){
return $(this).prev('div.image-reserved').find('img').length;
}).find('a').remove();
JS Fiddle demo.
References:
filter().
find().
prev().
remove().
$('div.image-reserved:not(:empty)+.content a.reserveLink') will find all .image-reserved divs that have content, and select the .reserveLink links in the .content element after them.

Jquery .after() not inserting as expected

EDIT: Solution found How to wrap every 3 child divs with html using jquery?
I'm printing a list with a lot of <div>'s and want to insert a </div><div class="clearfix"> after every 6th <div> with jQuery.
Naturally that would be something like
$('#staffscroll .person:nth-child(5n)').after('</div><div class="clearfix">');
But the output becomes <div class="clearfix"></div> which just doesn't make sense.
Any thoughts?
Ok, maybe should provide some more code..
I'm working with a slideshowscript. The whole take is basicly to put stuff in a <div>.
For example..
<div id="slideshow">
<div class="clearfix"> First slide wrapper
<img>
<img>
<img>
<img>
</div>
<div class="clearfix"> Second slide wrapper
<img>
<img>
<img>
<img>
</div>
<div class="clearfix"> Third slide wrapper
<img>
<img>
</div>
</div>
The problem is that I'm working with a CMS aswell, which havn't got that much control over dynamic output. So my thought was that I just could output all the content, and then provide the slide-wrappers afterwards.
Therefore the </div><div class="clearfix">
Havn't got a clue if it makes any more or less sense now, but I hope you get what I'm trying to do.
The statement you try to insert isn't correct XML. You are thinking about your HTML document as a big string, but this is the wrong way to do if you want to use tools like jQuery.
I suggest you to learn more about DOM and how to use it. Your whole approach is wrong, so your sample of code isn't correctable.
IIRC, jQuery parses the string to a DOM fragment and then inserts it. When your </div><div class="clearfix"> is parsed it's assumed the </div> is an error, and it also closes the <div class="clearfix">. Therefore the effect you observed.
That's because after isn't modifying the HTML -- it's creating new DOM elements and adding them to the document. You should use wrapAll to wrap a group of elements. My guess is that your code will look something like this:
var start = 0,
$list = $('#staffscroll .person').slice(0, 6);
while ($list.length) {
$list.wrapAll('<div class="clearFix"></div>');
start += 6;
$list = $list.end().slice(start, start + 6);
}
jsFiddle working example
As I replace the .wrapAll for .append or a similiar?

jQuery: get a reference to a specific element without using id

I'm tinkering a bit with jquery to show a hidden div when a link is clicked. This should be fairly simple, but there's a flaw to it in this case. I have the following markup:
<div class="first-row">
<div class="week">
<p>Uge 2</p>
<p>(08-01-11)</p>
</div>
<div class="destination">
<p>Les Menuires</p>
<p>(Frankrig)</p>
</div>
<div class="days">4</div>
<div class="transport">Bil</div>
<div class="lift-card">3 dage</div>
<div class="accommodation">
<p><a class="show-info" href="#">Hotel Christelles (halvpension)</a></p>
<p>4-pers. værelse m. bad/toilet</p>
</div>
<div class="order">
<p>2149,-</p>
<p class="old-price">2249,-</p>
</div>
<div class="hotel-info">
<!-- The div I want to display on click -->
</div>
</div>
When I click the "show-info" link I want the "hotel-info" div to display.
My backend devs don't want me to use ids (don't ask me why..) and the above markup is used over and over again to display data. Therefore I need to be able to access the "hotel-info" div in the "first-row" div where the link is clicked.
I've tried to do something like:
$(document).ready(function() {
$('.show-info').click(function() {
var parentElement = $(this).parent().parent();
var lastElementOfParent = parentElement.find(".show-hotel");
lastElementOfParent.show();
});
});
But without a result :-/ Is this possible at all?
Any help is greatly appreciated!
Thanks a lot in advance!
Try this:
$('.show-info').click(function() {
$(this).closest('.accommodation').siblings('.hotel-info').show();
});
Even better imo, as it would be independent from where the link is in a row, if every "row div" has the same class (I assume only the first one has class first-row), you can do:
$(this).closest('.row-class').find('.hotel-info').show();
Reference: .closest, .siblings
Explanation why your code does not work:
$(this).parent().parent();
gives you the div with class .accommodation and this one has no descendant with class .hotel-info.
It is not a good idea to use this kind of traversal for more than one level anyway. If the structure is changed a bit, your code will break. Always try to use methods that won't break on structure changes.
You're right in not using an ID element to find the DIV you want :)
Use closest and nextAll
Live demo here : http://jsfiddle.net/jomanlk/xTWzn/
$('.show-info').click(function(){
$(this).closest('.accommodation').nextAll('.hotel-info').toggle();
});

Categories