cheerio: Get normal + text nodes - javascript

I am using cheerio to parse HTML code in different nodes. I can easily do $("*"), but this gets me only normal HTML nodes and not the separate text nodes. Lets consider 3 user inputs:
One:
text only
I need: single text node.
Two:
<div>
text 1
<div>
inner text
</div>
text 2
</div>
I need: text node + div node + text node in same sequence.
Three:
<div>
<div>
inner text 1
<div>
inner text 2
</div>
</div>
<div>
inner text 3
</div>
</div>
I need: 2 div nodes
Possible?

In hope to help someone, filter function seems to return text nodes also.
I got help from this answer: https://stackoverflow.com/a/6520267/3800042
var $ = cheerio.load(tree);
var iterate = function(node, level) {
if (typeof level === "undefined") level = "--";
var list = $(node).contents().filter(function() { return true; });
for (var i=0; i<=list.length-1; i++) {
var item = list[i];
console.log(level, "(" + i + ")", item.type, $(item).text());
iterate(item, level + "--");
}
}
iterate($.root());
HTML input
<div>
text 1
<div>
inner text
</div>
text 2
</div>
Result
-- (0) tag
text 1
inner text
text 2
---- (0) text
text 1
---- (1) tag
inner text
------ (0) text
inner text
---- (2) text
text 2

I hope the following codes can help you.
const cheerio = require("cheerio");
const htmlText = `<ul id="fruits">
<!--This is a comment.-->
<li class="apple">Apple</li>
Peach
<li class="orange">Orange</li>
<li class="pear">Pear</li>
</ul>`;
const $ = cheerio.load(htmlText);
const contents = $('ul#fruits').contents();
console.log(contents.length);// 9, since nodes like '\n' are included
console.log(new RegExp('^\\s*$').test('\n '));
function isWhitespaceTextNode(node){
if(node.type !== 'text'){
return false;
}
if(new RegExp('^\\s*$').test(node.data)){
return true;
}
return false;
}
//Note here: filter is a function provided by cheerio, not Array.filter
const nonWhitespaceTextContents = contents.filter(nodeIndex=>{
const node = contents[nodeIndex];
if(isWhitespaceTextNode(node)){
return false;
}else{
return true;
}
});
console.log(nonWhitespaceTextContents.length);// 5, since nodes like '\n ' are excluded
nonWhitespaceTextContents.each((_, node)=>console.log(node));
//[comment node]
//[li node] apple
//[text node] peach
//[li node] orange
//[li node] pear

If you want all of the immediate children of a node, both text nodes and tag nodes, use .contents() and filter out whitespace-only text nodes.
Here's the code running on your examples:
const cheerio = require("cheerio"); // 1.0.0-rc.12
const tests = [
// added a div container to make the parent selector consistent
`<div>text only</div>`,
`<div>
text 1
<div>
inner text
</div>
text 2
</div>`,
`<div>
<div>
inner text 1
<div>
inner text 2
</div>
</div>
<div>
inner text 3
</div>
</div>`
];
tests.forEach(html => {
const $ = cheerio.load(html);
const result = [...$("div").first().contents()]
.filter(e => e.type !== "text" || $(e).text().trim())
// the following is purely for display purposes
.map(e => e.type === "text" ? $(e).text().trim() : e.tagName);
console.log(result);
});
Output:
[ 'text only' ]
[ 'text 1', 'div', 'text 2' ]
[ 'div', 'div' ]
If you only want the text nodes and not the tags, see How to get a text that's separated by different HTML tags in Cheerio.

Related

How do I get text after single <br> tag in Cheerio

I'm trying to get some text using Cheerio that is placed after a single <br> tag.
I've already tried the following lines:
let price = $(this).nextUntil('.col.search_price.discounted.responsive_secondrow').find('br').text().trim();
let price = $(this).nextUntil('.col.search_price.discounted.responsive_secondrow.br').text().trim();
Here is the HTML I'm trying to scrape:
<div class="col search_price_discount_combined responsive_secondrow" data-price-final="5039">
<div class="col search_discount responsive_secondrow">
<span>-90%</span>
</div>
<div class="col search_price discounted responsive_secondrow">
<span style="color: #888888;"><strike>ARS$ 503,99</strike></span><br>ARS$ 50,39
</div>
</div>
I would like to get "ARS$ 50,39".
If you're comfortable assuming this text is the last child element, you can use .contents().last():
const cheerio = require("cheerio"); // 1.0.0-rc.12
const html = `
<div class="col search_price_discount_combined responsive_secondrow" data-price-final="5039">
<div class="col search_discount responsive_secondrow">
<span>-90%</span>
</div>
<div class="col search_price discounted responsive_secondrow">
<span style="color: #888888;"><strike>ARS$ 503,99</strike></span><br>ARS$ 50,39
</div>
</div>
`;
const $ = cheerio.load(html);
const sel = ".col.search_price.discounted.responsive_secondrow";
const text = $(sel).contents().last().text().trim();
console.log(text); // => ARS$ 50,39
If you aren't comfortable with that assumption, you can search through the children to find the first non-empty text node:
// ...
const text = $([...$(sel).contents()]
.find(e => e.type === "text" && $(e).text().trim()))
.text()
.trim();
console.log(text); // => ARS$ 50,39
If it's critical that the text node immediately follows a <br> tag specifically, you can try:
// ...
const contents = [...$(sel).contents()];
const text = $(contents.find((e, i) =>
e.type === "text" && contents[i-1]?.tagName === "br"
))
.text()
.trim();
console.log(text); // => ARS$ 50,39
If you want all of the immediate text children, see:
How to get a text that's separated by different HTML tags in Cheerio
cheerio: Get normal + text nodes
You should be able to get the price by using:
$('.col.search_price.discounted.responsive_secondrow').html().trim().split('<br>')
This gets the inner HTML of the element, trims extra spaces, then splits on the <br> and takes the 2nd part.
See example at https://jsfiddle.net/b7nt0m24/3/ (note: uses jquery which has a similar API to cheerio)

How to get header ID from the HTML/DOM using react and typescript

I have an app that converts some markdown files to html using marked.js and displays the converted HTML to the web page. In the code snippet below I iterate over text nodes to grab all the raw text values that get displayed to store them in some index where a text value corresponds to a numeric id
// iterate over file objects which contain raw markdown
files.forEach(file => {
// convert file's markdown string to html string using marked.js
const htmlString = marked(file.markDown);
const parser = new DOMParser();
const doc = parser.parseFromString(htmlString, 'text/html');
const walker = document.createTreeWalker(doc, NodeFilter.SHOW_TEXT);
// const walker = document.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT);
let currentNode = walker.currentNode;
while (currentNode != null) {
if (currentNode.textContent != null) {
// index every HTML element's raw text value and assign it to an id
searchIndexReference.push({ id: id++, text: currentNode.textContent });
//console.log('currentNode');
//console.log(currentNode);
}
const nextNode = walker.nextNode();
if (nextNode != null) {
currentNode = nextNode;
} else {
break;
}
}
});
I want to know how I can grab the header id value and add it to the index as well, until the next header id is encountered. That way the searchIndexReference will link text value entries to the header it was under.
Say we have some HTML below:
<h1 id="top-most-header">Top Most Header</h1>
<p>Here is some text 1</p>
<p>Here is some text 2</p>
<h2 id="some-other-section-header">Some Other Section Header</h1>
<p>Here is some text 3</p>
<p>Here is some text 4</p>
These entries would get appended to the searchIndexReference object like so. (Current header id value is stored until the next header is encountered)
{id: 1, headerId: 'top-most-header', text: 'Top Most Header'}
{id: 2, headerId: 'top-most-header', text: 'Here is some text 1'}
{id: 3, headerId: 'top-most-header', text: 'Here is some text 2'}
{id: 4, headerId: 'some-other-section-header', text: 'Some Other Section Header'}
{id: 5, headerId: 'some-other-section-header', text: 'Here is some text 3'}
{id: 6, headerId: 'some-other-section-header', text: 'Here is some text 4'}
This should work for nested elements as well too like ul, li, etc.
I know when I print out currentNode using
const walker = document.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT);
instead of NodeFilter.SHOW_TEXT it shows the full HTML header element with the id, but I'm not sure where to go from there.
printing out currentNode with SHOW_ELEMENT
Check parent node and if it's a header then save the id
if(currentNode.parentNode.nodeName === 'H1') {
headerId = currentNode.parentNode.id
}

Render a native HTML template with JavaScript

With HTML Templates it makes it easy to stamp out snippets of html.
What is a sane way of populating the stamped out templates? In the MDN link above they render the template as follows:
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Acme Kidney Beans 2";
This obviously only works if all the elements are the same tag, and ordered in the same way, which is very brittle.
What if I had a template like this:
<template>
<div>
<h2>__heading__</h2>
<label>__label1__</label><input type="text" value="__value1__">
<label>__label2__</label><input type="text" value="__value2__">
<div>__instruction__</div>
<label>__label3__</label><input type="text" value="__value3__">
</div>
</template>
And say one had this data to render it with:
{
__heading__: 'Lots of things',
__label1__: 'label 1',
__value1__: 'value 1',
__label2__: 'label 2',
__value2__: 'value 2',
__instruction__: 'Do the thing',
__label3__: 'label 3',
__value3__: 'value 3',
}
Then the rendered result would be:
<div>
<h2>Lots of things</h2>
<label>label 1</label><input type="text" value="value 1">
<label>label 2</label><input type="text" value="value 2">
<div>Do the thing</div>
<label>label 3</label><input type="text" value="value 3">
</div>
How would one render the template? PS if this is a XY question, you can use some other means to instead of the dunder fields.
I can only think of adding classes or attributes to each element which has a field to populate, and then perform lots of clonedNode.querySelector() ...seems very unelegant.
Note 9/9/2022: There is a proposal for DOM Parts on the table: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/DOM-Parts.md
You could replace content with Template Literal String notation
string:
<h1>Run ${name}! Run!</h1>
Ain't <b>${tooling}</b> great!!
property Object:
{
name: this.getAttribute("name"),
tooling: "Web Components",
}
The parse(str,v) function
creates a new Function
with a String literal (note the back-ticks)
then executes that Function
passing all v Object values
and Returns the parsed String literal
<template id="MY-ELEMENT">
<h1 style="background:${color}"> Run ${name}! Run!</h1>
Ain't <b>${tooling}</b> great!!
</template>
<my-element name="Forrest"></my-element>
<script>
function parse(str, v = {}) {
try {
return new Function("v",
"return((" + Object.keys(v).join(",") + ")=>`" +
str +
"`)(...Object.values(v))")(v) || "";
} catch (e) {
console.error(e);
}
};
customElements.define("my-element", class extends HTMLElement {
color = "gold";
constructor() {
super().attachShadow({mode: 'open'}).innerHTML = parse(
document.getElementById(this.nodeName).innerHTML, // String
{ // properties
name: this.getAttribute("name"),
tooling: "Web Components",
...this, // to show you can add anything you want to the property bag
});
}
})
</script>
One of the possible solution is manipulation of the HTML string itself. There is not much stuff you can do with content inside DOM tree without some special markup (like you mentioned in your question).
So, you clone the template and modify inner HTML of every child inside the template:
// Gather the template from DOM and clone it
const template = document.querySelector('#target_template');
const clonedDocumentFragment = template.content.cloneNode(true);
// Looks like there is no better way to modify HTML of the whole
// DocumentFragment, so we modify HTML of each child node:
Array
.from(clonedDocumentFragment.children)
.forEach(childElement => renderInnerVariables(
childElement,
{
// Pass your values here
}
));
// And here example of the method replacing those values
function renderInnerVariables(targetElement, variables = {}) {
// Reminder: it can be really unsafe to put user data here
targetElement.innerHTML = targetElement.innerHTML.replace(
// Instead of looping through variables, we can use regexp
// to get all the variables in content
/__([\w_]+)__/,
(original, variableName) => {
// Check if variables passed and target variable exists
return variables && variables.hasOwnProperty(variableName)
// Pass the variable value
? variables[variableName]
// Or pass the original string
: original;
}
);
}
But since it's just a string content modification, you can pretty much just use string templates instead.
If I understood correctly you want to create a template based on object.. if yes you can use this as a start..
What I did was to create a function getTagName(key) which will return a specific string based on the object key (it can be made with a switch most probably but eh.. :( switch on regex ) For example __value2__ will return input
Then I created a function createHtmlElementwith with some conditions in order to set the text/value to my element then I iterate through all the properties and append the newly created element
const data = {
__heading__: 'Lots of things',
__label1__: 'label 1',
__value1__: 'value 1',
__label2__: 'label 2',
__value2__: 'value 2',
__instruction__: 'Do the thing',
__label3__: 'label 3',
__value3__: 'value 3',
}
let container = document.getElementById('container');
// this can be done with switch i think, but for demo i did if statements :(
function getTagName(key) {
key = key.replace('__', ''); //remove __ from front
if (/^heading/.test(key)) return "h2";
if (/^label/.test(key)) return "label";
if (/^value/.test(key)) return "input";
if (/^instruction/.test(key)) return "div";
}
function createHtmlElement(name, key, value) {
let element = document.createElement(name);
if (name === 'label' || name === "h2" || name === "div") {
element.innerHTML = value;
}
if (name === "input") {
element.type = "text";
//element.value = key; // this is not working for i don't know what reason :(
element.setAttribute('value', key);
}
// console.log(element) // decomment if you want to see the element as plain html
return element;
}
for (const [key, value] of Object.entries(data)) {
let tagName = getTagName(key);
let element = createHtmlElement(tagName, key, value);
let brTag = document.createElement("br");
container.appendChild(element);
container.appendChild(brTag);
}
<div id="container">
</div>
<!--
<h2>__heading__</h2>
<label>__label1__</label>
<input type="text" value="__value1__">
<label>__label2__</label>
<input type="text" value="__value2__">
<div>__instruction__</div>
<label>__label3__</label>
<input type="text" value="__value3__">
-->

Targeting a Label using jQuery when an extra Span is present

I have a label in a form defined as follows and the jQuery code below locates the 'Description' label and changes it for me to 'Program Description':
$(".ms-accentText").filter(function () {
return $(this).text() == "Description";
}).text('Program Description');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3 class="ms-accentText">Description</h3>
But I have another label of 'Name' that has html markup that is used to tag the label with an asterisk, to define the associated field as being required, as listed below:
The similar jQuery code which is listed below does not locate and change the label:
$(".ms-accentText").filter(function () {
return $(this).text() == "Name";
}).text('Program Name');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3 class="ms-accentText">Name<span class="ms-formvalidation"> * </span></h3>
How can I target the 'Name' label, when the extra asterisk related html mark-up code included?
I'm new to using jQuery.
Thanks,
Wayne
By using combination of :contains jquery selector + append you can achieve more efficient flow:
$(() => {
const query = 'Name'
const $name = $(`.ms-accentText:contains(${query})`)
.filter(function () {
const textChildTexts = [...this.childNodes]
// filtering to select only direct text nodes
// to skip the asterisk part
.filter(node => node && node.nodeType === Node.TEXT_NODE)
// getting the text out of node
.map(node => node && node.textContent)
// joining all the texts into a string to compare
.join('');
return textChildTexts === query;
});
const $asterisk = $name.find('.ms-formvalidation');
$name.text('Program Name').append($asterisk);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3 class="ms-accentText">Name<span class="ms-formvalidation"> * </span></h3>
<h3 class="ms-accentText">Project Full Name<span class="ms-formvalidation"> * </span></h3>
You could create a custom filtering function that removes any descendant elements and trims the containing text, and use that like this
function f(what) {
return function(index, elem) {
var clone = $(elem).clone();
clone.find('*').remove();
return clone.text().trim() === what;
}
}
$(".ms-accentText").filter(f('Description')).css('color', 'blue');
$(".ms-accentText").filter(f('Name')).css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3 class="ms-accentText">Description</h3>
<h3 class="ms-accentText">Name<span class="ms-formvalidation"> * </span></h3>

How can I dynamically highlight strings on a web page?

I want to create pages with urls such as:
http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins
http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones
http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver
These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, "http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.
I imagine something like this is required, client-side:
var employee = getLastURLPortion(); // return "Billy_Bones" (or whatever)
employee = humanifyTheName(employee); // replaces underscores with spaces, so that it's "Billy Bones" (etc.)
Highlight(employee); // this I have no clue how to do
Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?
If you call the function
highlight(employee);
this is what that function would look like in ECMAScript 2018+:
function highlight(employee){
Array.from(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)"))
.flatMap(({childNodes}) => [...childNodes])
.filter(({nodeType, textContent}) => nodeType === document.TEXT_NODE && textContent.includes(employee))
.forEach((textNode) => textNode.replaceWith(...textNode.textContent.split(employee).flatMap((part) => [
document.createTextNode(part),
Object.assign(document.createElement("mark"), {
textContent: employee
})
])
.slice(0, -1))); // The above flatMap creates a [text, employeeName, text, employeeName, text, employeeName]-pattern. We need to remove the last superfluous employeeName.
}
And this is an ECMAScript 5.1 version:
function highlight(employee){
Array.prototype.slice.call(document.querySelectorAll("body, body *:not(script):not(style):not(noscript)")) // First, get all regular elements under the `<body>` element
.map(function(elem){
return Array.prototype.slice.call(elem.childNodes); // Then extract their child nodes and convert them to an array.
})
.reduce(function(nodesA, nodesB){
return nodesA.concat(nodesB); // Flatten each array into a single array
})
.filter(function(node){
return node.nodeType === document.TEXT_NODE && node.textContent.indexOf(employee) > -1; // Filter only text nodes that contain the employee’s name.
})
.forEach(function(node){
var nextNode = node.nextSibling, // Remember the next node if it exists
parent = node.parentNode, // Remember the parent node
content = node.textContent, // Remember the content
newNodes = []; // Create empty array for new highlighted content
node.parentNode.removeChild(node); // Remove it for now.
content.split(employee).forEach(function(part, i, arr){ // Find each occurrence of the employee’s name
newNodes.push(document.createTextNode(part)); // Create text nodes for everything around it
if(i < arr.length - 1){
newNodes.push(document.createElement("mark")); // Create mark element nodes for each occurrence of the employee’s name
newNodes[newNodes.length - 1].innerHTML = employee;
// newNodes[newNodes.length - 1].setAttribute("class", "highlighted");
}
});
newNodes.forEach(function(n){ // Append or insert everything back into place
if(nextNode){
parent.insertBefore(n, nextNode);
}
else{
parent.appendChild(n);
}
});
});
}
The major benefit of replacing individual text nodes is that event listeners don’t get lost. The site remains intact, only the text changes.
Instead of the mark element you can also use a span and uncomment the line with the class attribute and specify that in CSS.
This is an example where I used this function and a subsequent highlight("Text"); on the MDN page for Text nodes:
(The one occurrence that isn’t highlighted is an SVG node beyond an <iframe>).
I used the following regex to replace all the matching url to create anchors with highlighted text:
(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)
Debuggex Demo
The following code will replace all plain urls. If you don't need them to be replaced to links, just highlight them, remove the tags:
var str = "http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver ";
var highlighted = str.replace( new RegExp("(http://xyzcorp/schedules/(.*?)/)(.*?)( |<|\n|\r|$)","g"), "<a href='$1$3'>$1<span style='background-color: #d0d0d0'>$3</span></a>" );
The content of the highlighted string will be:
<a href='http://xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>Jim_Hawkins</span></a>
<a href='http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>Billy_Bones</span></a>
<a href='http://xyzcorp/schedules/2015Aug24_Aug28/John_Silver'>http://xyzcorp/schedules/2015Aug24_Aug28/<span style='background-color: #d0d0d0'>John_Silver</span></a>
UPDATE:
This function will replace the matching names from the input text:
function highlight_names( html_in )
{
var name = location.href.split("/").pop().replace("_"," ");
return html_in.replace( new RegExp( "("+name+")", "g"), "<span style='background-color: #d0d0d0'>$1</span>" );
}
One solution would be, after window is loaded, to traverse all nodes recursively and wrap search terms in text nodes with a highlight class. This way, original structure and event subscriptions are not preserved.
(Here, using jquery, but could be done without):
Javascript:
$(function() {
// get term from url
var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
// search regexp
var re = new RegExp('(' + term + ')', 'gi');
// recursive function
function highlightTerm(elem) {
var contents = $(elem).contents();
if(contents.length > 0) {
contents.each(function() {
highlightTerm(this);
});
} else {
// text nodes
if(elem.nodeType === 3) {
var $elem = $(elem);
var text = $elem.text();
if(re.test(text)) {
$elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
}
}
}
}
highlightTerm(document.body);
});
CSS:
.highlight {
background-color: yellow;
}
$(function() {
// get term from url
//var term = window.location.href.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
var term = 'http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones/'.match(/\/(\w+)\/?$/)[1].replace('_', ' ');
// search regexp
var re = new RegExp('(' + term + ')', 'gi');
// recursive function
function highlightTerm(elem) {
var contents = $(elem).contents();
if(contents.length > 0) {
contents.each(function() {
highlightTerm(this);
});
} else {
// text nodes
if(elem.nodeType === 3) {
var $elem = $(elem);
var text = $elem.text();
if(re.test(text)) {
$elem.wrap("<span/>").parent().html(text.replace(re, '<span class="highlight">$1</span>'));
}
}
}
}
highlightTerm(document.body);
});
.highlight {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div>
<div class="post-text" itemprop="text">
<p>I want to create pages with urls such as:</p>
<pre style="" class="default prettyprint prettyprinted">
<code>
<span class="pln">http</span>
<span class="pun">:</span>
<span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Jim_Hawkins</span>
<span class="pln">
http</span>
<span class="pun">:</span>
<span class="com">//xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</span>
<span class="pln">
http</span>
<span class="pun">:</span>
<span class="com">//xyzcorp/schedules/2015Aug24_Aug28/John_Silver</span>
</code>
</pre>
<p>These particular URLs would all contain the exact same content (the "2015Aug24_Aug28" page), but would highlight all instances of the name tagged on to the end. For example, " <code>http://xyzcorp/schedules/2015Aug24_Aug28/Billy_Bones</code>
" would show every instance of the name "Billy Bones" highlighted, as if a "Find" for that name was executed on the page via the browser.</p>
<p>I imagine something like this is required, client-side:</p>
<pre style="" class="default prettyprint prettyprinted">
<code>
<span class="kwd">var</span>
<span class="pln"> employee </span>
<span class="pun">=</span>
<span class="pln"> getLastURLPortion</span>
<span class="pun">();</span>
<span class="pln"></span>
<span class="com">// return "Billy_Bones" (or whatever)</span>
<span class="pln">
employee </span>
<span class="pun">=</span>
<span class="pln"> humanifyTheName</span>
<span class="pun">(</span>
<span class="pln">employee</span>
<span class="pun">);</span>
<span class="pln"></span>
<span class="com">// replaces underscores with spaces, so that it's "Billy Bones" (etc.)</span>
<span class="pln"></span>
<span class="typ">Highlight</span>
<span class="pun">(</span>
<span class="pln">employee</span>
<span class="pun">);</span>
<span class="pln"></span>
<span class="com">// this I have no clue how to do</span>
</code>
</pre>
<p>Can this be done in HTML/CSS, or is JavaScript or jQuery also required for this?</p>
</div>
Demo: http://plnkr.co/edit/rhfqzWThLTu9ccBb1Amy?p=preview

Categories