Adding a class and ID to headers using Javascript - javascript

The way that Zendesk's Help Centre works is by printing all the sections onto the page without giving them any unique identifier, so it's a pain if you want to implement any sort of scrollspy (updating a sidenav with where you are on the page), and most importantly anchors so that the sidenav actually works.
I'm not that technical and was wondering if anyone knew of a way to add an ID & class to a series of headers using JS?
I'm thinking for each h2 in section-tree-with-article, adding a unique ID, and a class that matches the h2's text?
Any thoughts?

You need to select all the h2 elements, iterate through them and set a class as well as an id with each iteration.
I've simple set the innerHTML as the class. You can modify it according to your use case.
var headers = document.querySelectorAll("div.section-tree-with-article h2");
headers.forEach(function(header, idx) {
header.className = header.textContent.replace(/\s/g, "-"); //You can modify this accordingly
header.id = "uniqueID" + idx; //And similarily the uniqueID
})
<div class="section-tree-with-article">
<ul>
<li class="section">
<h2>Admin 0</h2>
</li>
</ul>
<ul>
<li class="section">
<h2>Admin 1</h2>
</li>
</ul>
<ul>
<li class="section">
<h2>Admin 2</h2>
</li>
</ul>
<ul>
<li class="section">
<h2>Admin 3 4 5</h2>
</li>
</ul>
<ul>
<li class="section">
<h2>Admin 4</h2>
</li>
</ul>
</div>
Here's the same solution in jquery:
$("div.section-tree-with-article h2").each(function(index, value){
var classToAdd = $(this).text();
$(this).attr('class', classToAdd);
$(this).attr('id', "uniqueID" + index);
})

Although this answer does not address your request for a JavaScript solution, I recommend instead using the Help Center's built-in templating system to iterate on the elements and add classes, directly in the html files. Please note that this is only available in the "Professional" and "Enterprise" Zendesk plans.
This example is probably not the best, since you will end up with spaces or other unusable characters in the value of the h2 elements' class attribute (it will replace {{name}} with the section's name), but I hope it will give you an idea of how this works, and how you might use it to achieve a solution.
<div class="section-tree-with-article">
<ul>
{{#each sections}}
<li class="section">
<h2 class="{{name}}" id="{{id}}">{{name}}</h2>
</li>
{{/each}}
</ul>
</div>
will end up something like this:
<div class="section-tree-with-article">
<ul>
<li class="section">
<h2 class="Admin and Settings" id="12345">Admin and Settings</h2>
</li>
<li class="section">
<h2 class="Getting Started" id="45678">Getting Started</h2>
</li>
...[more sections]...
</ul>
</div>
More info on Help Center templating here:
https://support.zendesk.com/hc/en-us/articles/216367358-Help-Center-templating-cookbook-Professional-and-Enterprise-

Related

jQuery - known class of child: find next descendent of parent in top (from parent ID)

I've been searching a lot for this, without any solution so far. As you might also have seen the topic title might be a little hard to interpret and that's because I'm not quite sure how to explain it shortly.
The problem
Looking at the HTML below, I know the class of the last element called "active" and this element is chosen dynamically in jQuery, based on which site the visitor is on currently - i.e. different elements has this class depending on the site. On another site the li with class first-sub-li could have the class active (or for that matter the li with class first). This class is, as said, added dynamically based on the site with jquery. From here on I wish to identify the parent of the element with active which is a direct descendent of top-parent and add a class called active-parent to this. I.e. in the case below i wish to add the active-parent class to the li with class second.
EDIT: Please note that the "depth" of the list can vary, therefore also requiring a "dynamic" approach to picking out the parent. I completely forgot this in the initial writing.
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li"></li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li">
<ul class="second-sub-sub-ul">
<li class="second-sub-sub-li active"></li> <!-- Here -->
</ul>
</li>
</ul>
</li>
</ul>
So far I've tried the following jQuery without succes as it doesn't identify it.
EDIT 2: This actually does work, but initially it didn't as it apparently was called before the class was loaded, despite appearing later in the javascript document. Wrapping it in a $(window).on("load", function() solves the problem as shown below.
$(window).on("load", function() {
$(".active").closest("#top-parent > li").addClass("active-parent");
});
The original code was just $(".active").closest("#top-parent > li").addClass("active-parent");
You can start traversing up with .parent(), it will excluding the self li.
$(".active").parent().closest("li").addClass("active-parent");
You can use :has() selector
$('#top-parent > li:has(.active)').addClass("active-parent");
$('#top-parent > li:has(.active)').addClass("active-parent");
.active-parent {
background-color: red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li"></li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li">
<ul class="second-sub-sub-ul">
<li class="second-sub-sub-li active"></li>
<!-- Here -->
</ul>
</li>
</ul>
</li>
</ul>
I think this is what you're looking for. Find all li which are direct descendants of topmost-parent and filter that for the one which has a child .active. Apply the class.
$('#top-parent > li').filter(function(e){
return $(this).find('.active').length>0;
}).addClass("active-parent");
.active-parent{background-color:red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="top-parent">
<li class="first">
<ul class="first-sub-ul">
<li class="first-sub-li">1.1</li>
</ul>
</li>
<li class="second">
<ul class="second-sub-ul">
<li class="second-sub-li active">2.1</li> <!-- Here -->
</ul>
</li>
</ul>

<br/> tag is affecting all my other divs

Im a newbie and im trying to create a webstie just for practice, I realized that when I want to line break one of the divs (just to make stuf fancy) all my other divs gets linebreaked though, which I dont want. how do you fix this?
<ul class = "nav">
<div class = "head_dividers"><li> Hello <span> World </span> </li> </div>
<div class = "head_dividers"><li> stuff </li></div>
<div class = "head_dividers"><li> Help </li> </div>
</ul>
</div>
You should not have the <li> tags inside of a <div> tag. You can swap them if you like, but generally, <div> is a divider, and the <ul>/<li> items setup their own spacing/breaks (on each new list item).
The <br /> tag, on the other hand, is used inside of your text to create a break at a specific point.
I would recommend something a bit more simple like this:
<ul class="nav">
<li class="head_divider">...</li>
<li class="head_divider">Text<br />Here</li>
<li class="head_divider">...</li>
</ul>
and use CSS to add any necessary styles/spacing.

Simple HTML DOM Parser - trigger click

Hi i'm having below scenario,
Fetching products from other 3rd party website,
Their product page having 3 different tabs and their default html structure is like this,
<ul>
<li class="active">description</li>
<li>Spec</li>
<li>Gallery</li>
<ul>
<div>
<div class="description">product descriptions goes here .... </div>
<div class="spec"></div>
<div class="gallery"></div>
</div>
Is i click on second tab (spec tab) then the html structure is (contents adding dynamically),
<ul>
<li class="active">description</li>
<li>Spec</li>
<li>Gallery</li>
<ul>
<div>
<div class="description">product descriptions goes here .... </div>
<div class="spec"> Specs goes here </div>
<div class="gallery"></div>
</div>
Because of the contents adding dynamically according to tab selection, i cant able to fetch complete contents. Is there any way to click other too and get all contents ?
Did anyone know how to solve this ?
Not sure what are you asking here. but may be worth a try :
var tabs = document.getElementsByTagName("li");
for (var i = 0, x; x = tabs[i++];)
x.click();

ng-repeat without an html element

i am trying to generate a blog list but i got a problem with ng-repeat. my list looks like this
<ul>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
<span class="sep2"></sep>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
<span class="sep2"></sep>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
<li>
<h2>Title</h2>
<p>Message</p>
</li>
</ul>
So after every 2 list items, i have a span that levels my next 2 boxes.
Right now i have this angular code.
<ul>
<li ng-repeat="post in postsJSON">
<h2>{{post.title}}</h2>
<p>{{post.message}}</p>
</li>
</ul>
And i dont know how to generate that span after every second list item.
Thank you in advance, Daniel!
With angular v1.2 it becomes quite easy, using ng-repeat-start, ng-repeat-end and ng-if, you can check it here : http://jsfiddle.net/DotDotDot/XNJvj/1/
Your code will look like this:
<ul>
<li ng-repeat-start='post in postsJSON'>
{{post.item}}<br/>
{{post.message}}
</li>
<span ng-if="$odd && !$first" ng-repeat-end>
<span class="sep2">_____</span>
</span>
</ul>
ng-repeat-start/end allows you to enter a loop in a tag and close it in another, in this case, I also added a condition using the $odd parameter of the ng-repeat, showing only every other span
The issue here is not really with angular but more with the structure of your markup. ul tag should normally only contains li tags as children.
To resolve your issue I will stick to the ng-repeat you already have and create the separator with css. Something like that :
<ul class="blog list">
<li ng-repeat="post in postsJSON" class="blog entry">
<h2>{{post.title}}</h2>
<p>{{post.message}}</p>
</li>
</ul>
CSS :
.blog.entry {
border-bottom : 1px solid black // or whatever color
...
}
or if you need more control on the separator use css :after and do something like
.blog.entry:after {
content : "";
...
}
If you are not familiar with :after you can have a look there

change information in seperate divs with button click

I am trying to accomplish this effect but I'm sure the coding is incorrect. I want the image DIVs to swap content when each button is clicked. This is what I have so far, but I'm sure the code is incorrect. Is there a better way of achieving this? thanks, and forgive me for the noob question.
HTML:
<div class="item-1 content-item">
I am the 1st image content
</div>
<div class="item-2 content-item" style="display: none;">
I am the 2nd image content
</div>
<div class="item-3 content-item" style="display: none;">
I am the 3rd image content
</div>
<div class="item-1 content-item">
I am the content for item 1
</div>
<div class="item-2 content-item" style="display: none;">
I am the content for item 2
</div>
<div class="item-3 content-item" style="display: none;">
I am the content for item 3
</div>
<ul>
<li class="change-item" data-item="1">Item 1</li>
<li class="change-item" data-item="2">Item 2</li>
<li class="change-item" data-item="3">Item 3</li>
</ul>
jQuery:
$('.change-item').click(function(){
var this_item = $(this).attr("data-item");
$('.content-item').hide();
$('.item-' + this_item).fadeIn();
});
A couple tips you might find helpful, even though it is working fine.
Since your items are actually grouped by number and the stuff in between is hidden, you could just group them together.
You should consider using id attributes in your markup. This makes it more clear that each one of your items is unique and makes the javascript run faster.
Your <ul> is technically in order, so it's more properly an <ol>. This is splitting hairs, and will give you numbers instead of bullet points, giving you more work to style it correctly. But it's worth mentioning.
Consider giving some indication that the list items are interactive. You could make them buttons or anchors (so they would display like hyperlinks). Or try a css rule for the cursor to make the mouse pointer change when they a user goes over the link.
Like this:
.change-item {
cursor: pointer;
}
Put it all together, it might look something like this:
HTML:
<div id="item-1" class="content-item">
<img src="/item-1.png"/>
<p>I am the content for item 1</p>
</div>
<div id="item-2" class="content-item" style="display:none;">
<img src="/item-2.png"/>
<p>I am the content for item 2</p>
</div>
<div id="item-3" class="content-item" style="display:none;">
<img src="/item-3.png"/>
<p>I am the content for item 3</p>
</div>
<ol>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ol>
Javascript:
$('.change-item').click(function(){
var this_item = $(this).attr("data-item");
$('.content-item').hide();
$('#item-' + this_item).fadeIn();
});
But as you can tell, your code is fully functional as is. You didn't do anything terribly wrong (good job!), these are just a few things that might make this page easier on you or your users.

Categories

Resources