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));
});
});
Related
I'm building a glossary page. I have a list of each letter of the alphabet at the top of the page, linking via anchor text to the correct section of content.
I want to remove the link from the letter if the letter has no terms.
I'm not getting any errors, but the code is not removing the link, or having any affect as far as I can tell.
Trying to remove link for B
function removeLink (){
var letternavcontent = document.getElementById("letternav").innerHTML;
var letter = document.getElementsByClassName("letter");
if ( letternavcontent.indexOf('B') > -1) {
letter.removeAttribute("href");
}
}
<p id="letternav">| <a class="letter"
href="/glossary.html#a">A</a> | <a class="letter"
href="/glossary.html#b">B</a></p>
Check this pen.
document.getElementsByClassName returns all the elements with that class name, not just one. So you must loop through this list and check each one.
function removeLink (){
var letter = document.getElementsByClassName("letter");
for (var i = 0; i < letter.length; i++) {
if (letter[i].innerHTML.indexOf('B') > -1) {
letter[i].removeAttribute("href");
}
}
}
How about this?
const removeLinkFromLetter = letter => {
// iterates over every letter element
[...document.querySelectorAll('.letter')].forEach(elt => {
// if the element has the specified letter as its text...
if (elt.innerText.trim()==letter) {
// ...change its content to the letter without the anchor tag
elt.innerHTML = letter;
}
});
}
window.onload = () => {
removeLinkFromLetter('A');
}
<p id="letternav">
|
<span class="letter">
<a href="/glossary.html#a">
A
</a>
</span>
|
<span class="letter">
<a href="/glossary.html#b">
B
</a>
</span>
|
</p>
I'm wondering if this is possible. I have some code below:
<p class="page_classList">
<strong>Crops:</strong>
<br>
<span class="cropElem">Berries - Blueberries</span>
<span class="cropElem">Peas</span>
<span class="cropElem">Squash</span>
<span class="cropElem">Okra</span>
</p>
Is there any way to have these spans display themselves in alphabetical order (by crop). This list is displayed when a user clicks on a farm page that is built in wordpress. Can a script rearrange these as the page loads?
Any help would be great!
You loop through and find all the crop elements, delete the element and save the crop name into a list. Sort the list then loop through the list and re-add each element to the <p> this time they will be alphabetical since the list is sorted alphabetically using .sort()
Fiddle: https://jsfiddle.net/d7wug6d8/
var spans = $(".page_classList").find(".cropElem");
var cropNames = [];
spans.each(function(index) {
$(spans[index]).remove();
cropNames.push($(spans[index]).html());
});
cropNames.sort();
$(cropNames).each(function(index) {
$(".page_classList").append('<span class="cropElem">' + cropNames[index] + '</span>\n');
});
This gives the final HTML:
<p class="page_classList">
<strong>Crops:</strong>
<br>
<span class="cropElem">Berries - Blueberries</span>
<span class="cropElem">Okra</span>
<span class="cropElem">Peas</span>
<span class="cropElem">Squash</span>
</p>
For the new HTML you asked for: Fiddle: https://jsfiddle.net/d7wug6d8/1/
var foodItems = $(".page_classList").html().split(",");
foodItems.sort();
$(".page_classList").html(foodItems.join(", "));
In case you already have events set up on your elements, you might not want to recreate them, but rather reorder them. Here is how I would do it:
var container = $('.page_classList'),
data = $('.cropElem');
data.sort(function(a,b){
if($(a).html() > $(b).html()) return 1;
if($(a).html() < $(b).html()) return -1;
return 0;
});
for(var i=0; i<data.length; i++) {
container.append(data[i]);
}
.cropElem{ display: block; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="page_classList">
<strong>Crops:</strong>
<br>
<span class="cropElem">Berries - Blueberries</span>
<span class="cropElem">Peas</span>
<span class="cropElem">Squash</span>
<span class="cropElem">Okra</span>
</p>
Why use append?
When you do append of an element, it does not duplicate it, it moves it. This allows you to reorder your elements.
That is basically what you would do I dont feel like finishing the code though. Then you could loop through the cropArray and output it in between the html span elements.
var cropArray = ["Berries - Blueberries", "Peas", "Squash", "Okra"];
cropArray.sort();
Or simply:
Grab a collection of spans, sort them, and re-append with newly sorted collection.
var els = $('.cropElem');
els.sort(function (a, b) {
a = $(a).text();
b = $(b).text();
// compare
if(a > b) {
return 1;
} else if (a < b) {
return -1;
}
return 0;
});
$('.page_classList').append(els);
span { display: block; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="page_classList">
<strong>Crops:</strong>
<br>
<span class="cropElem">Berries - Blueberries</span>
<span class="cropElem">Peas</span>
<span class="cropElem">Squash</span>
<span class="cropElem">Okra</span>
</p>
I'm trying to select all spans with class .normal on my site, cut the first character and add € as the last character. I'm trying really hard but it just doesn't work even when I try to just replace that with "abc" or any string.
My javascript looks like that:
$(document).ready(function(){
var prices = document.querySelectorAll('span.normal');
for (i=0; i<prices.length; i++) {
prices[i].textContent = prices[i].substring(1) + "€";
}
}
});
Since you are using jQuery already how about making it completely in jQuery?
$(document).ready(function() {
$('span.normal').each(function() {
$(this).text($(this).text().substring(1) + '€');
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>abc</span>
<span class="normal">abc</span>
<span>abc</span>
<span class="normal">abc</span>
var prices = document.querySelectorAll('span.normal');
for (var i = 0; i < prices.length; i++) {
prices[i].innerHTML = prices[i].innerHTML.substring(1) + "€";
}
.normal{
font-color:black;
}
<span class=normal >3543</span>
<span class=normal >34534</span>
I have successfully did a word count on a text area using the following JS:
jQuery('span.after-amount').append(' - You have <span class="wordcount">0</span> words.');
jQuery('textarea').on('input', function($) {
var regex = /\s+/gi;
var count = jQuery(this).val().trim().replace(regex, ' ').split(" ").length;
$('.wordcount').html(count);
});
My HTML:
<textarea class="tmcp-field tmcp-textarea" name="tmcp_textarea_2"></textarea>
<span class="after-amount">You have <span class="wordcount">0</span> words.</span>
<textarea class="tmcp-field tmcp-textarea" name="tmcp_textarea_2"></textarea>
<span class="after-amount">You have <span class="wordcount">0</span> words.</span>
<textarea class="tmcp-field tmcp-textarea" name="tmcp_textarea_2"></textarea>
<span class="after-amount">You have <span class="wordcount">0</span> words.</span>
Here is a Fiddle.
I need to get a word count for each text area, is there an easy way to do this without selecting each textarea individually?
This is my solution, first I change your event handler to keyup, and starting count of each textarea value's length using $(this) so you get the current textarea.
$(function(){
$('textarea').on('keyup', function(){
var wordsLength = $(this).val().length;
$(this).next().find('.wordcount').html(wordsLength);
});
});
Check this updated jsfiddle. Hope this helps
Just finding .wordcount into <li>
jQuery('textarea').on('input', function($) {
var regex = /\s+/gi;
var count = jQuery(this).val().trim().replace(regex, ' ').split(" ").length;
jQuery(this).parent().find('.wordcount').html(count);
);
I have the following structure:
<ul id="myTags"">
<li>
<span class="tagit-label">AA</span>
<a>
<span class="text-icon">×</span>
<span class="ui-icon ui-icon-close"></span>
</a>
<input type="hidden" name="tags" value="AA" style="display:none;">
</li>
<li>
<span class="tagit-label">BB</span>
<a class="tagit-close">
<span class="text-icon">×</span>
<span class="ui-icon ui-icon-close"></span>
</a>
<input type="hidden" name="tags" value="BB" style="display:none;">
</li>
....
</ul>
I want to write a Javascript/jQuery function that will create a string consists of
"AA,BB,..."
How do I collect the values from all of the value attribute at span rows?
This should work:
$('#myTags input[name="tags"]').map(function () {
return $(this).val();
}).get().join(",");
Try this
var textArr = [];
$(".tagit-label").each(function(){
textArr.push($(this).text());
})
console.log(textArr.join());
Use .map()
var array = $('.tagit-label').map(function(){
return $(this).text()
}).get()
console.log(array.join(','))
Demo: Fiddle
You can do this:
var arr = $('#myTags .tagit-label').map(function () {
return $(this).text();
}).get().join(",");
console.log(arr);
Here is my late answer. I tried javascript 1.8 array reduce method, for fun .
var string = [].reduce.apply( $('.tagit-label') , [ function( ar , n ){
return ar.push( $(n).text() ) && ar ;
},[] ] ).join();
or simply
var string = [].reduce.call( $('.tagit-label') , function( ar , n ){
return ar.push( n.innerHTML ) && ar ;
},[] ).join();
Hope this will help learning more on reduce method . http://jsfiddle.net/6TnMT/
var spans = $(".tagit-label");
var str = "";
for (i = 0; i < spans.length; i++) {
str += spans[i].innerHTML+"," ;
}
alert(str);
Fiddle Example
var str= $('.tagit-label').first().text();
$('.tagit-label:not(":first")').each(function(){
str= str +' , '+ $(this).text();
});
alert(str);