My CMS is exporting strings into a span element like this:
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
I need the 0900 and 1900 as a class so I can add some CSS to them to fill up a bar. This is working fine, but it also exports it as the starting and ending hour so you see '0900' and '1900' in the frontend. I would like to split these strings up so I can add a ':' after the second integer with Javascript. So in this way the strings would be shown as: '09:00' and '19:00' in the frontend.
My knowledge of Javascript is very basic so I don't know how to get this started. Help would be appreciated.
You could select all elements with on of the classes, then add it like below
document.querySelectorAll('.starting-hour, .ending-hour').forEach(e => {
e.innerText = e.innerText.padStart(4, 0);
e.innerText = e.innerText.substring(0, 2) + ':' + e.innerText.substring(2)
})
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
<span class="starting-hour 0900">900</span> - <span class="ending-hour 1900">1900</span>
Create a reusable function that will return you the hour representation of the values in span:
function getHours(val){
return val.substr(0,2)+':'+val.substr(2,4);
}
var start = document.querySelector('.starting-hour').innerText;
document.querySelector('.starting-hour').innerText = getHours(start);
var end = document.querySelector('.ending-hour').innerText;
document.querySelector('.ending-hour').innerText = getHours(end);
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
But, if you do not have exactly four character long hhhh in your span then use this:
function getHours(val){
return val.substr(0,val.length-2)+':'+val.substr(val.length-2,val.length);
}
var start = document.querySelector('.starting-hour').innerText;
document.querySelector('.starting-hour').innerText = getHours(start);
var end = document.querySelector('.ending-hour').innerText;
document.querySelector('.ending-hour').innerText = getHours(end);
<span class="starting-hour 0900">900</span> - <span class="ending-hour 1900">1000</span>
Taking from Ankit's answer, I made code little dynamic to satisfy both 4 digits and 3 digits time example and added both codes.
function getHours(val){
return val.substr(0,val.length - 2)+':'+val.substr(val.length - 2,val.length);
}
var start = document.querySelector('.starting-hour').innerHTML;
document.querySelector('.starting-hour').innerHTML = getHours(start);
var end = document.querySelector('.ending-hour').innerHTML;
document.querySelector('.ending-hour').innerHTML = getHours(end);
var start = document.querySelector('.starting-hour-two').innerHTML;
document.querySelector('.starting-hour-two').innerHTML = getHours(start);
var end = document.querySelector('.ending-hour-two').innerHTML;
document.querySelector('.ending-hour-two').innerHTML = getHours(end);
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
<br>
<br>
<span class="starting-hour-two 900">900</span> - <span class="ending-hour-two 100">100</span>
function getHours(val){
return val.substr(0,val.length - 2)+':'+val.substr(val.length - 2,val.length);
}
var start = document.querySelector('.starting-hour').innerHTML;
document.querySelector('.starting-hour').innerHTML = getHours(start);
var end = document.querySelector('.ending-hour').innerHTML;
document.querySelector('.ending-hour').innerHTML = getHours(end);
var start = document.querySelector('.starting-hour-two').innerHTML;
document.querySelector('.starting-hour-two').innerHTML = getHours(start);
var end = document.querySelector('.ending-hour-two').innerHTML;
document.querySelector('.ending-hour-two').innerHTML = getHours(end);
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
<span class="starting-hour-two 900">900</span> - <span class="ending-hour-two 100">100</span>
Since yout time is always 4 characters long, it makes it easy to slice the string, put in a : then put them together.
var str1 = "0900".slice(0,2);
var str2 = "0900".slice(2,4);
var time = str1 + ":" + str2;
alert(time);
The addColon function takes an element and sets its innerText to itself, but with the a colon inserted before the last two digits.
Use any method you want to select your span elements and pass them over to addColon. I've gone with a querySelector and a forEach iterator.
const addColon = el => el.innerText = el.innerText.replace(/(\d){2}$/, ":$&");
const timeStamps = document.querySelectorAll("span[class*='-hour']");
timeStamps.forEach(stamp => addColon(stamp));
<span class="starting-hour 0900">0900</span> - <span class="ending-hour 1900">1900</span>
Related
I am trying to target the last word within a class and then wrap it with a span so that I can style the last word using Javascript.
<h1 class="title>A long tile</h1>
<h2 class="title>A long tile</h2>
becomes
<h1 class="title>A long <span class="last-word">tile</span></h1>
<h2 class="title>A long <span class="last-word">tile</span></h2>
I've seen some jQuery solutions on Stack which helped a bit, but I'd like a JS version.
I can get this working for the first element on the page, using this code…
var paras = document.querySelector('.title');
function wrapLastWord(elem) {
const textContent = elem.textContent.split(" ");
const lastWord = textContent.pop();
// if the sentence is more than 1 word, wrap the last word with a span. If it's only 1 word, return it without being wrapped by a span
const updatedContent = textContent.join(" ") + (textContent.length > 0 ? ` <span class='last-word'>${lastWord}</span>` : lastWord);
elem.innerHTML = updatedContent;
}
wrapLastWord(paras)
However, I want to target all classes of .title and hence I thought I could use a querySelectorAll and a forEach. I am clearly not understanding how this works.
var paras = document.querySelectorAll('.title');
paras.forEach(function wrapLastWord(elem) {
const textContent = elem.textContent.split(" ");
const lastWord = textContent.pop();
// if the sentence is more than 1 word, wrap the last word with a span. If it's only 1 word, return it without being wrapped by a span
const updatedContent = textContent.join(" ") + (textContent.length > 0 ? ` <span class='last-word'>${lastWord}</span>` : lastWord);
elem.innerHTML = updatedContent;
}
wrapLastWord(paras)
})
Could anyone please give me some pointers to get this working, or suggest an alternative direction
To begin you have a syntax error in your second line missing an "
<h1 class="title>A long <span class="last-word">tile</span></h1>
<h2 class="title>A long <span class="last-word">tile</span></h2>
should be this
<h1 class="title">A long <span class="last-word">tile</span></h1>
<h2 class="title">A long <span class="last-word">tile</span></h2>
As for getting the value using javascript you can simply do
const spanText = document.querySelector('.last-word).innerText
// this will find the first match
console.log(spanText)
//if you want to find all of the ".last-words"
const lastWords = document.querySelectorAll('.last-word')
console.log(lastWords, "<-array like object")
lastWords.forEach((word)=> {
console.log(word.innerText)
})
As for your function
var paras = document.querySelectorAll(".title");
console.log(paras);
paras.forEach(function wrapLastWord(elem) {
const textContent = elem.innerText.split(" ");
console.log(textContent, ' textContent')
const lastWord = textContent.pop();
console.log(lastWord, 'last word')
// // if the sentence is more than 1 word, wrap the last word with a span. If it's only 1 word, return it without being wrapped by a span
const updatedContent = ` <span class='last-word'>${lastWord}</span>`;
console.log(updatedContent, 'updatedContent')
})
You've created updatedContent as you can see in your log, but now you have to decide what you want to do with it. Maybe use one of the append methods you can look at the docs and explore the append method if you want to add it to your page
#JimithyPicker Thanks, you led me to an answer.
My final code is as follows:
const paras = document.querySelectorAll(".title");
paras.forEach(function wrapLastWord(elem) {
const textContent = elem.textContent.split(" ");
const lastWord = textContent.pop();
// if the sentence is more than 1 word, wrap the last word with a span. If it's only 1 word, return it without being wrapped by a span
const updatedContent = textContent.join(" ") + (textContent.length > 0 ? ` <span class='last-word'>${lastWord}</span>` : lastWord);
elem.innerHTML = updatedContent;
});
I hate manually typing steps numbers. So I was trying to write a small function to find some text and replace it with generated step numbers.
And I can't use the ol/li tags because I have multiple groups on the page. So I need to add an "a", "b", etc after the number.
My HTML:
<span class="grouping" v="a">
----My first step
----This is another
----And another
</span>
<br/>
<span class="grouping" v="b">
----second group
----second group 2
</span>
This is my jquery (but it doesn't replace the ---- to a step number).
$(function(){
$(".grouping").each(function(){
var val=$(this).attr("v");
var counter=1;
$(this).find(":contains('----')").each(function(){
$(this).text("("+counter+val+") ");
counter++;
});
});
});
So eventually, I want the webpage to finish like this:
(1a) My first step
(2a) This is another
(3a) And another
(1b) second group
(2b) second group 2
For each of the groupings, get the inner html and split it by newline
If it starts with '----', replace it with an incrementing line number, and append the v value.
Put the html back into the grouping.
$('.grouping').each(function(index, grouping){
var lines = grouping.innerHTML.trim().split("\n");
var lineNumber = 0;
var v = grouping.getAttribute('v');
lines.forEach(function(line, index){
if (line.startsWith('----')) {
lines[index] = '('+ (++lineNumber) + v +') '+ line.slice(4);
}
});
grouping.innerHTML = lines.join('\n');
});
.grouping { white-space: pre; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="grouping" v="a">
----My first step
----This is another
I should not have a line number.
----And another
</span>
<br/>
<span class="grouping" v="b">
I also should not have a line number.
----second group
----second group 2
</span>
You can use split to split the text at '----' and concat with the values (added brs for lisibility so I used html instead of text):
$(function(){
$(".grouping").each(function(){
var val=$(this).attr("v");
var arr = $(this).html().split('----');
if(arr.length > 1){
var str = arr[0], i, l = arr.length;
for(i = 1; i < l; i++){
str += '(' + i + val + ') ' + arr[i];
}
$(this).html(str);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="grouping" v="a">
----My first step<br>
----This is another<br>
----And another<br>
</span>
<br/>
<span class="grouping" v="b">
----second group<br>
----second group 2<br>
</span>
.find() will not work. You should get text of the element and split() it and then change it using map() and replace() and reset text()
$(function(){
$(".grouping").each(function(){
var val=$(this).attr("v");
var counter=1;
let lines = $(this).text().split('\n');
lines = lines.map(ln => {
if(ln.includes('----')){
ln = ln.replace('----',`(${counter}${val})`)
counter++;
}
return ln;
})
lines = lines.filter(ln => ln !== '');
$(this).text(lines.join('\n'));
});
});
.grouping { white-space: pre; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="grouping" v="a">
----My first step
----This is another
----And another
</span>
<br/>
<span class="grouping" v="b">
----second group
----second group 2
</span>
First, I suggest wraping those groups into some kind of tag. for example, span:
<span class="grouping" v="a">
<span class="grouping-item">My first step</span>
</span>
And so on, it will be easier and faster to target those elements.
Then create one function to search through those new tags
$(function(){
// This will create those numbers
function createNumbers(el) {
const mainGroup = el.attr("v");
const children = el.children(".grouping-item");
let i = 1;
children.each(function(){
const currentText = $(this).text();
$(this).text( '('+i+mainGroup+')' + currentText );
i++;
});
}
$(".grouping").each(function(){
createNumbers($(this));
});
});
Have a html string see below.
<div sentence="11">
<p>
how are you Tom, how are you Tom
</p>
</div>
<div sentence="12">
<p>
how are you Tom
</p>
</div>
When user select the name 'Tom', I will replace the string 'Tom' using a name tag with some html style. The result what I want see below.
<div sentence="11">
<p>
how are you <span class="ano-subject" data-oristr="Tom" data-offset="1" data-sentence="11"><NAME></span>, how are you <span class="ano-subject" data-oristr="Tom" data-offset="2" data-sentence="11"><NAME></span>
</p>
</div>
<div sentence="12">
<p>
how are you <span class="ano-subject" data-oristr="Tom" data-offset="1" data-sentence="12"><NAME></span>
</p>
</div>
I will using the code below to do the replace.
var content = HTML CODE ABOVE;
var selectText = 'Tom';
var regex = new RegExp('(?=\\s|^|\\b)(?:' + selectText + ')(?=\\s|$|\\b)', "g");
var pre_sentence = 0;
var offset = 0;
content = content.replace(regex, function(match, position) {
var curr_sentence = ???; // how can I get this element's parent div attribute 'sentence' ?
if(pre_sentence != cur_sentence){
// this is new sentence.
offset = 1;
pre_sentence = curr_sentence;
} else {
offset++;
}
var replace = '<span class="ano-subject" data-oristr="Tom" data-offset="'+offset+'" data-sentence="'+curr_sentence+'"><NAME></span>';
return replace;
});
In my Chrome extension, I'm trying to get info from a page (the value of "data-timestamp": 1490893300813) via a content script, but the result shows 'null'.
//content script:
var tsx = document.getElementsByClassName("date");
var i;
const ts = new Array;
for (i = 0; i < tsx.length; i++) {
var ts[i] = tsx[i].getAttribute("data-timestamp");
console.log("Timestamp" + i + ": " + ts[i]);
}
<!--source code from page:-->
<div class="thread">
<span data-timestamp="1490893300813" class="date">
<span class="absolute">Do, 30.03.2017, 19:01</span>
<span class="relative"></span>
</span>
</div>
I also noticed that the data-timestamp attribute is visible when I show source-code of the page (Ctrl+U) but it isn't visible in DevTools...
You can use document.querySelector('.date') to select the element that has the date class. From there, you can get the element.dataset.timestamp to get the timestamp.
Your code could look something like:
//Get the timestamp as a number ( + is used to convert from a string to a number).
var timestamp = +document.querySelector('.date').dataset.timestamp;
console.log('Timestamp:', timestamp);
//Convert to a Date and display in ISO format for the UTC timezone.
var date = new Date(timestamp);
console.log(date.toISOString());
<div class="thread">
<span data-timestamp="1490893300813" class="date">
<span class="absolute">Do, 30.03.2017, 19:01</span>
<span class="relative"></span>
</span>
</div>
I have output from a CMS where I need to add a style to a certain character in the string. For instance, my output is:
<div class="date">12 // 14 // 2013</div>
How can I add:
<span style="slashColor">
to the two double slashes so that my result would be:
<div class="date">12 <span class="slashColor">//</span> 14 <span class="slashColor">//</span> 2013</div>
Try this:
var original = $('.date').text();
var new_version = original.split('//').join('<span class="slashColor">//</span>');
$('.date').html(new_version);
Fiddle
If you have many div like the example you posted, you can use this:
$('.date').each(function () {
var original = $(this).text();
var new_version = original.split('//').join('<span class="slashColor">//</span>');
$(this).html(new_version)
});
Fiddle
var elements = document.getElementsByClassName('date');
for (var i = 0, e; e = elements[i++]; ) {
e.innerHTML = e.innerHTML.replace(/\/\//g, '<span class="slashColor">//</span>');
}
or the jQuery way:
$('.date').each(function () {
$(this).html($(this).html().replace(/\/\//g, '<span class="slashColor">//</span>'));
}