JS: Add link dynamically to all elements of certain class - javascript

I work in a system where we have these elements representing a part of an audio clip, and a timeline for the audio that is browsable (click around to play different parts). However, the elements representing the parts of the audio clip does not actually link to the parts of the audio.. (so no "click this to play this part").
I have deducted that it is possible to link to a specific part of the call via for example: http://thelink.com/timeline?startms=%221600326183999%22. And that the elements all have an attribute called "startms", for example:
<div class="segment-item" startms="1600326183999"></div>
Is there any way I could loop through all the elements in the page with the class "segment-item" and add a href="" with the value of their individual "startms" value to the link (http://thelink.com/timeline?startms=%22TheValueHere%22).
Then finally, since I cannot build an addon to my browser for this, would it be possible to make a snipped which can be pasted into the console for easy use when I need it? Any other suggestions to making such a thing be easily accessible for usage without making or using an addon for chrome?

If you want to add the link to the element, you should add it like that
const elements = document.getElementsByClassName("segment-item")
for (element of elements) {
const a = document.createElement("a")
a.href = `http://thelink.com/timeline?startms=%22${element.getAttribute("startms")}%22`
a.innerText = "LINK NAME"
element.appendChild(a)
}

Adding a link based on element properties goes like this
const elements = document.getElementsByClassName("segment-item")
for (element of elements) {
element.innerHTML = `<a href="http://thelink.com/timeline?startms=%22${element.getAttribute("startms")}%22">
Link name
</a>`
}

Related

back and forth between nodes in vanilla javascript

I'm expanding a site (menright.com) that displays about fifty years of photos. This link goes to the first photo page: (https://menright.com/pages/photoPages/photos-1967.php). Each photo is followed by a caption, and there is a button that allows the viewer to see a longer description that replaces the caption. The button isn't working here but allows you to see what I'm talking about.
To implement this I have an img (the button) inside of a p tag (the caption). Clicking the button substitutes the longer description drawn from the alt and the title in a second img (the picture) immediately above the caption.
I can't use IDs since there are many captions and pictures on each page.
Here is the HTML skeleton of the significant parts of the problem:
<img alt='long description' title='location image taken' />
<p class='the caption'> <img class='get long description button' /> </p>
I'm thinking I have to find the node of the target (the button), track its parent (the caption), and then get the alt and title from something like a previousSibling (the picture) and use the innerHTML of the parent (the caption) to display the long description.
Am I correct in this assumption, or is there another way to do this? And if this is the technique I need to use, how do I do it? I'm totally new to using nodes in my vanilla Javascript, and I don't want to add JSquery or other libraries to my pages.
This is my first post here, though I've used the site for years. Thanks for any help you might provide!
I'm thinking I have to find the node of the target (the button), track its parent (the caption), and then get the alt and title from something like a previousSibling (the picture) and use the innerHTML of the parent (the caption) to display the long description.
Am I correct in this assumption, or is there another way to do this?
If you stick to that structure, yes, that's what you'd do (probably previousElementSibling so you don't have to worry about intervening Text nodes), and setting textContent rather than innerHTML unless you want < and & in the text to be interpreted as HTML. You'd probably do it via event delegation on whatever container has all of these in it (body, if there's nothing nearer):
theContainer.addEventListener("click", event => {
const btn = event.target.closest(".get.long.description.button");
if (btn && theContainer.contains(btn)) {
const p = btn.parentElement;
const alt = p.previousElementSibling?.alt;
if (alt) {
p.textContent = alt; // `textContent` assuming you don't have tags
}
}
});
But if you can wrap all of that in an element:
<div class="wrapper">
<img alt='long description' title='location image taken' />
<p class='the caption'>
<img class='get long description button' />
</p>
</div>
...you can make it more robust:
theContainer.addEventListener("click", event => {
const wrapper = event.target.closest(".container");
if (wrapper && theContainer.contains(wrapper)) {
const p = wrapper.querySelector(".the.caption");
const alt = wrapper.querySelector(".location.image.taken")?.alt;
if (alt) {
p.textContent = alt; // `textContent` assuming you don't have tags
}
}
});
That doesn't rely on the exact relationship between the elements, just that they're all in the same container, so you can move them around as the page design evolves without changing your code.

Aria-live region is not reading out updates when an element is removed on chrome

When you dynamically add an element to an aria-live region, Chrome will read out all the items in that region which is great.
But when you remove an element, Chrome does not re-read out the list. This is an issue when you're using the region for errors and such, as when the user has fixed an error, the list is not re-read out.
Example here: https://codepen.io/mildrenben/pen/WNNzVzN?editors=1010
<div aria-live='assertive'>
</div>
<button id='add'>add</button>
<button id='remove'>remove</button>
const addBtn = document.querySelector('#add')
const removeBtn = document.querySelector('#remove')
const ariaLive = document.querySelector('div')
let tick = 0
addBtn.addEventListener('click', () => {
let newElem = document.createElement('span')
newElem.textContent = tick
tick++
console.log(ariaLive, newElem)
ariaLive.appendChild(newElem)
})
removeBtn.addEventListener('click', () => {
ariaLive.removeChild(ariaLive.lastChild)
})
The correct method should be to use the aria-relevant attribute, however the browser support is very poor, and as such it is not reliable.
I don't normally advocate for doing hacky things to make a browser behave a certain way, but if you really need to make the live region report removals, here's what I would suggest:
Set the aria-atomic attribute on your live region to true. This means that the screen reader will read the entire contents of the live region each time content is added (but not removed).
When you delete an element from the live region, add another invisible element, wait a few hundred milliseconds, and then delete that element.
The live region should announce all of the contents (minus the deletion) when the remove button is pressed.
Example fiddle here: https://jsfiddle.net/mug6vonf/3/
You should also use aria-relevant :
Values:
A space-delimited list of one or more of the following values:
additions are insertion of nodes into the live region; should be considered relevant.
removals are deletion of nodes; should be considered relevant.
text are changes to the textual content of existing nodes; should be considered relevant.
all is equivalent to additions removals text.
aria-relevant="additions text" is the default value on a live region.
The default value doesn't include removals, which you probably need.

Is there a to change the value of an element using JavaScript

I'm trying to change the value of an element on a third-party web page using a JavaScript Add-on to display a hyperlink
I already have the link on the page i would like to be able to click it
I think I'm on the right track using document.getElementById although I'm not sure how to then change the id into a "a href" and then how to pass it back into the value.
Sorry, this is a bit of a tricky situation so I'll try my best to explain it. On a third-party web-page which we use for our HR related tasks, there is a section titled "File Link" although this isn't a link. When you copy and paste the address into a browser it displays the file. What i am trying to do is create a hyperlink on the "File Link" section to remove the need to copy and paste the link. Because this is a third party website. We have access to the JavaScript on the website and need to change the address into a hyperlink. I'm not entirely sure this is possible.The element id is "__C_cb_file_link" and i would like to insert the link address into the element using a variable then add the link parameters into the variable then reinsert it into the element/value.
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = "<a href="+intoLink+"</a>;
intoLink.value = hLink;
}
window.onload = linkIt();
<td><div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674"/></td></tr>
In below code first we read input value with new link (however we can read this value from other html tags), then we remove this element (and button) and add to parent element (of removed input) the new link
function linkIt() {
let intoLink = __C_cb_file_link.value;
let parent = __C_cb_file_link.parentNode;
__C_cb_file_link.remove();
btn.remove();
parent.innerHTML += `${intoLink}`;
}
<input id="__C_cb_file_link" value="https://example.com">
<button id="btn" onclick="linkIt()">Link It</button>
There are a number of issues with your code:
1) The code snippet in your question doesn't run because of a missing " at the end of the second line of the linkIt() function.
2) intoLink is a hidden field so anything you add to it will not be visible in the page
3) Even if point 2 were not true, setting the value of a form field will not cause HTML to appear on the page (at best you might get some plain text in a textbox).
4) "<a href="+intoLink+"</a>" doesn't work because intoLink is a complex object which represents the entire hidden field element (not just its value property). You can't convert a whole object into a string directly. You need to extract the value of the field.
A better way to do this is by creating a new element for the hyperlink and appending it to the page in a suitable place. Also I recommend not adding your event via onload - when written using this syntax only one onload event can exist in a page at once. Since you're amending another page which isn't under your control you don't want to disable any other load events which might be defined. Use addEventListener instead, which allows multiple handlers to be specified for the same event.
Demo:
function linkIt() {
var intoLink = document.getElementById("__C_cb_file_link");
var hLink = document.createElement("a");
hLink.setAttribute("href", intoLink.value);
hLink.innerHTML = "Click here";
intoLink.insertAdjacentElement('beforebegin', hLink);
}
window.addEventListener('load', linkIt);
<td>
<div class="sui-disabled" title="">m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674</div>
<input type="hidden" name="__C_cb_file_link" id="__C_cb_file_link" value="m-files://view/37FF751C-A23F-4233-BD8B-243834E67731/0-46524?object=C46A7624-D24B-45F3-A301-5117EFC1F674" /></td>
</tr>
P.S. m-files:// is not a standard protocol in most browsers, unless some kind of extension has been installed, so even when you turn it into a hyperlink it may not work for everyone.
[UPDATE] I supose that your "__C_cb_file_link" was a paragraph so I get the previous text http://mylink.com and create a link with, is it what you want, right?
function linkIt() {
let fileLink = document.getElementById("__C_cb_file_link");
let hLink = fileLink.textContent;
fileLink.innerHTML = ""+hLink+"";
}
linkIt();
<div>
<p id="__C_cb_file_link">http://myLink.com</p>
</div>

Change Dynamic Link Text In Javascript

I currently have a slideshow run with HTMl CSS and JS at the moment for the navigation buttons below the slideshow it is just placing numbers instead of text. Is there a way to grab the images title and use it or custom text for each slide link. Below i included the Javascript that makes the navigation buttons and adds the text. If you need anything else just let me know.
If i can just specify text in this JS file that would work too.
Also if it may help im using Kickstart HTML Template.
Link to view it http://bliskdesigns.com/clients/timbr/
var items = $(this).find('li');
wrap.append('<ul class="slideshow-buttons"></ul>');
items.each(function(index){
wrap.find('.slideshow-buttons')
.append('<li>'+(index+2)+'</li>');
});
It's difficult to give you a concise answer with what you've provided, however:
Assuming that in the code you've provided:
items is an array containing each slide in your slideshow;
That each element in items contains an img;
That the text that you want to appear in the slideshow nav is the title attribute of each img;
That the unordered list being built by wrap is the navigation;
That the text you want to change is the numeral within the anchor of each item injected into wrap.
Here's a potential answer:
// put all slides into 'items'
var items = $(this).find('li');
// append the wrap element with an unordered list
wrap.append('<ul class="slideshow-buttons"></ul>');
// loop over each item
items.each(function(index){
// grab the title attribute of the img child of this instance of items
var titleText = $(this).find('img').attr('title');
// push a new <li> into 'wrap'
wrap.find('.slideshow-buttons').append('<li>'+titleText+'</li>');
});
This should just be a direct replacement for wherever in your project the code you've included above came from.
As I say: I can't promise that this will work without a lot more information, but in theory it will. Make sure that each of your images has a title:
<img src="/link/to/image.kpg" alt="alternative text" title="text you want to appear in the slider navigation" >
Alternatively, you can use the text in the image's alt tag instead by changing this line from above:
// grab the alt attribute of the img child of this instance of items
var titleText = $(this).find('img').attr('alt');
In the list items you can add the text that you want to display instead of numbers, as shown below.
<li data-displayText="Timber Mart"> <img src="http://i.imgur.com/4XKIENA.png" width="920" /> </li>
Then in above code you can use the text instead of index, as shown below.
wrap.find('.slideshow-buttons')
.append('<li>'+$(items[index]).attr("data-displayText")+'</li>');

Change the class of a hyperlink depending on its text

I'm trying to set up a web page that contains links to pages that have Disqus comments on them. There is specific guidance on adding a comment count to a link that Disqus provides, but it's not great. You are limited to using an <a> element, and it replaces the text of the hyperlink with new text.
So, if I create a hyperlink like this on my site:
linktext
after the page loads, it looks like this:
<a class="link-processed" href="http://mysite.com/posts/1234#disqus_thread">
(1 and 0)
</a>
(note that, by default, the replacement text would be "1 comment and 0 reactions" but I have modified the default text to return just the numbers, in brackets.)
When the text of the hyperlink is "(0 and 0)" I'd like to hide the link. When it is anything else, I'd like to replace the text of the link with an image link (little speech bubble or similar.)
I am thinking that the way to do this might be to use a couple of classes. I'll apply the first class (hidelink) by default, and use javascript to apply the second class to the <a> element.
However, now I'm stuck. Javascript is not my native domain. This seems like it should be a straightforward task, though?
What are your browser requirements? If you're using IE8+ (or most other browsers) you could use querySelectorAll or getElementsByClassName to get all processed links and then check if its text match your condition:
var elems = document.querySelectorAll('.link-processed');
for(var i = 0, size = elems.length; i < size; i++)
{
if(elems[i].innerText === "(0 and 0)")
{
//0 and 0. Do something
}
}
Alternatively, if you're using jQuery, you could simply select all elements that contain "0 and 0", using the pseudo class :contains:
$("a:contains('0 and 0')")

Categories