Convert newlines to <br> in a label - javascript

I need to convert top-level newlines in a label to <br> so that they actually look like newlines.
E.g. the label
<label>Hello
there<div>who
knows</div>what's going on</label>
should become
<label>Hello<br>there<div>who
knows</div>what's going on</label>
I tried already scanning the top-level text nodes using .childNodes and replacing the text, but that leaves a <br> in text output, as in, it doesn't get formatted correctly and is just outputted to text that the user can see.
$("label[for^='answer']").each(function () {
var thisElement = this;
Array.prototype.slice.call($(thisElement)[0].childNodes).forEach(function (elem, index) {
if (typeof elem.nodeValue == 'string') {
$(thisElement)[0].childNodes[index].nodeValue = $(thisElement)[0].childNodes[index].nodeValue.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>');
};
});
});
How can I replace all top-level newlines with correct HTML to make them look like newlines in the output?

You can't simply replace \n inside <label> because it will add <br>s to other elements, such as the <div> inside the <label> on your example.
You will have to iterate over the text nodes and create/insert <br> element in their places.
Also, to identify the text nodes, don't use
if (typeof elem.nodeValue == 'string') {
Use:
if (elem.nodeType === Node.TEXT_NODE) {
Furthermore, see demo below.
//$("label[for^='answer']").each(function () {
$("label.change-me").each(function () {
var thisElement = this;
Array.prototype.slice.call(thisElement.childNodes).forEach(function (elem, index) {
if (elem.nodeType === Node.TEXT_NODE) {
var lines = elem.nodeValue.split('\n');
if (lines.length > 1) { // i.e. there are line breaks
elem.nodeValue = lines[0];
var nextElement = elem.nextSibling;
for (var i = 1; i < lines.length; i++) {
elem.parentNode.insertBefore(document.createElement('br'), nextElement);
elem.parentNode.insertBefore(document.createTextNode(lines[i]), nextElement);
}
}
};
});
});
label { color: red }
div { color: blue }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="change-me">Hello
there<div>who
knows</div>what's going on</label>
<hr>
<label>Hello<br>there<div>who
knows</div>what's going on</label>
<hr>
<label class="change-me">Line-breaks inside
labels
break<div>I'm
inside
div
so
don't
break
me</div>div is over so break
me because we are
back to the label</label>

What i understood by you question, you want to replace the first space with a <br> tag.
So i added the splice() function to a string to solve this
Hope this is what you were looking for. Happy to explain or help in a better solution if needed.
String.prototype.splice = function(idx, rem, str) {
return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};
$("label").each(function() {
var thisText = this.innerHTML;
var result = thisText.splice(thisText.indexOf(" "), 0, "<br>");
this.innerHTML = result;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
Hello there
<div>who knows</div>
what's going on
</label>

Related

getElementsByClassName is not working in if condition

I'm Trying to get all the classnames with "items" and checking if innerHTML of each className by for loop and with given string. But even though the condition is true, nothing is happening in if condition.
I've implemented with the javascript and everything is working except the getElementsByClassName is not working
function clearAndAdd(){
var texter = document.getElementById("textBox").value;
if (texter != ""){
var allList = [];
document.getElementById("textBox").value = "";
created = 'deleteCurrent("'+texter+'")';
document.getElementById("lister").innerHTML = document.getElementById("lister").innerHTML+"<li class='items' onclick='"+created+"'>"+texter+"<span></span></li>";
document.getElementById("textBox").focus();
}
}
function deleteCurrent(text){
var allList = [];
var list = document.getElementsByClassName("items");
for(var i=0; i<list.length; i++){
var value = list[i].innerHTML;
if (value == text){
document.getElementById("output").innerHTML = value;
break;
}
}
}
<!-- HTML code -->
<body>
<div class="input-categories">
<ul id="lister">
</ul>
<input type="text" id="textBox" onblur="clearAndAdd();" />
</div>
<div id="output">
</div>
</body>
When I'm running the code with passing the string in text... even the value and the text are same, if condition is not executed. Can anyone help me with this
The content returned by list[i].innerHTML contains a <span> tag, so obviously it will never match the text you look for.
Instead of innerHTML use the textContent property: that will just return the text content:
var value = list[i].textContent;

How to get the number of input tags containing certain text?

My goal is to flag when a user enters the same text into one input that matches at least one other input's text. To select all of the relevant inputs, I have this selector:
$('input:text[name="employerId"]')
but how do I select only those whose text = abc, for instance?
Here is my change() event that checks for duplicate text among all the inputs on the page. I guess I am looking for something like :contains but for text within an input.
var inputsToMonitorSelector = "input[type='text'][name='employerId']";
$(inputsToMonitorSelector).change(function() {
//console.log($(this).val());
var inputsToExamineSelector = inputsToMonitorSelector
+ ":contains('" + $(this).val() + "')";
console.log(inputsToExamineSelector);
if($(inputsToExamineSelector).length > 1) {
alert('dupe!');
}
});
Or is there no such selector? Must I somehow select all the inputsToMonitorSelector's and, in a function, examining each one's text, incrementing some local variable until it is greater than one?
With input you need to use [value="abc"] or .filter()
$(document).ready(function() {
var textInputSelector = 'input[type="text"][name="employerId"]';
$(textInputSelector).on('input', function() {
$(textInputSelector).css('background-color', '#fff');
var input = $(this).val();
var inputsWithInputValue = $(textInputSelector).filter(function() {
return this.value && input && this.value == input;
});
var foundDupe = $(inputsWithInputValue).length > 1;
if(foundDupe) {
console.log("Dupe found: " + input);
$(inputsWithInputValue).css('background-color', '#FFD4AA');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="employerId" value="abc">
<input type="text" name="employerId" value="">
<input type="text" name="employerId" value="">
<input type="text" name="employerId" value="">
[value="abc"] means if the value is abc
[value*="abc"] * means if the value contains abc
[value^="abc"] ^ means if the value starts with abc
[value$="abc"] $ means if the value ends with abc
Note: :contains() not for inputs , and word text not used with inputs and <select>.. inputs and <select> has a value
In your case .. instead of using
$(inputsToExamineSelector).length > 1)
You may need to use .filter()
$(inputsToExamineSelector).filter('[value*="abc"]').length > 1)
OR
$('input[type="text"][name="employerId"]').filter(function(){
return this.value.indexOf('abc') > -1
// for exact value use >> return this.value == 'abc'
}).length;
And to use a variable on it you can use it like
'[value*="'+ valueHere +'"]'
Something like this works. Attach isDuplicated(myInputs,this.value) to a keyup event listener attached to each input.
var myInputs = document.querySelectorAll("input[type='text']");
function isDuplicated(elements,str){
for (var i = 0; i < myInputs.length; i++) {
if(myInputs[i].value === str){
myInputs[i].setCustomValidity('Duplicate'); //set flag on input
} else {
myInputs[i].setCustomValidity(''); //remove flag
}
}
}
Here's another one. I started with vanilla js and was going for an answer like Ron Royston with document.querySelector(x) but ended up with jquery. A first attempt at several things but here you go:
$("input[type='text']").each(function(){
// add a change event to each text-element.
$(this).change(function() {
// on change, get the current value.
var currVal = $(this).val();
// loop all text-element-siblings and compare values.
$(this).siblings("input[type='text']").each(function() {
if( currVal.localeCompare( $(this).val() ) == 0 ) {
console.log("Match!");
}
else {
console.log("No match.");
}
});
});
});
https://jsfiddle.net/xxx8we6s/

Coloring specific elements in a string

I'm working on a code to color all the curly brackets from my input field (textt). I have no problem finding them using a for and if statement, but i cant seem to color them or even make them bold. This is what i have currently:
function colorBrackets() {
var string = document.getElementById("textt").value;
var a = string.split(" ");
var result = "";
for (var i=0; i<a.length; i++) {
if((a[i] == "{") || (a[i] == "}")) {
a[i].style.color = "blue";
}
}
//brackets is my output field
document.getElementById("brackets").value = result;
}
I appreciate any help!
You need to insert spans around the part of the text you want to color.
I just replaced the { and } in the text with { and } surrounded by styled spans.
Then appended it back as innerHTML and voila.
function colorBrackets() {
let string = document.getElementById("input").innerText;
let result = string.replace(/{|}/g, '<span style="color: red">$&</span>');
document.getElementById("output").innerHTML = result;
}
colorBrackets();
<div id="input">{Hello }</div>
<div id="output"></div>
PS: This wouldn't work inside an input field. Since the value of an input has to be a string and not HTML. But the good news is that you can apply it in a div with contenteditable = true.

Replace Text label before or after input tag

In HTML I have some input tags with labels:
<label>Address <input type="text" name="address" /></label>
<label><input type="text" name="surname" /> Surname</label>
I want to change labels text with a javascript funcion.
I know it's possible eg. with
input_name.parentNode.firstChild.nodeValue = "New label text";
Unfortunatly labels are both before and after input. So firstChild as well as lastChild.
I know it's possible to put labels into <span> and use getElementById. But I prefer not.
Maybe it's also possible adding id or for to the label... But I prefer not.
How can I easly replace the "first TextNode sibling before or after input"?
You could iterate through the childNodes, find the first instance of a TEXT_NODE and replace the text.
var replaceText = function(inputName, newText) {
var TEXT_NODE = 3,
input_name = document.getElementsByName(inputName)[0],
nodes = input_name.parentNode.childNodes;
for (i = 0; i < nodes.length; i++) {
if (nodes[i].nodeType === TEXT_NODE) {
nodes[i].nodeValue = newText;
break;
}
}
};
replaceText("address", "Not an Address");
replaceText("surname", "Not a Surname");
Example on jsfiddle
I would strongly advice to use a cross-browser framework like JQuery instead of using raw Javascript. Then with Jquery:
$('input').bind("keyup", function(event) {
var textNodes = $(this).parent().contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
});
textNodes.each(function() { this.nodeValue = "bla"; });
});
Should work! Demo here: http://jsfiddle.net/Hh33v/6/
See http://api.jquery.com/filter/ and http://api.jquery.com/contents/

Search strings in html

In Javascipt (or better in jQuery), how do I check if a given string is contained in an html content of a <p> and <span> (ORed search)? Example:
<p id="p1">apple boy cat</p>
<p id="p2">ant boy cow</p>
<p id="p3">axe boots cat</p>
<span id="sp1">boots</span>
<span id="sp2">cow</span>
<span id="sp3">ant</span>
Search string: "apple boots cat"
Output:
p1, p3, sp1
var searchArray = 'apple boots cat'.split(' ');
var found = $('p, span').filter(function(idx, elem) {
var html = $(elem).html();
for(var i = 0, l = searchArray.length; i < l; i++) {
if(html.indexOf(searchArray[i]) != -1) {
return true;
}
}
return false;
}).css('color', '#f00');
Demo: http://jsfiddle.net/ThiefMaster/sWd2t/
var phrases = "apple boots cat".split(/\s+/);
$("*").filter(function () {
var found = false;
var $this = $(this);
$.each(phrases, function (phrase) {
if ($this.text().search(phrase) !== -1) {
found = true;
return false; // break the `each`
}
});
return found;
});
This is untested, but you get the idea. Select the elements which you want to search through and then use filter to narrow it down. The initial selector will have a large influence on the speed of this, and you'll also get multiple matches if there are nested elements. Without knowing your circumstances it's hard to recommend anything though - just be aware of these things. Hopefully this is a start.
var words = new RegExp("apple|boots|cat"); // looking for "apple", "boots" and "cat"
var output = $('p, span').filter(function() { // search "p" and "span"
return words.test($(this).text());
}).map(function() {
return $(this).attr('id'); // return the value of "id" from the found nodes
});
Note that the search string uses | instead of space to separate the words. Just do a replace on all the spaces if that's a problem.
This is a slightly convoluted demo, but: given a slightly adapted html:
<form action="#" method="post">
<fieldset>
<input placeholder="Search for string" type="search" id="search" name="search" />
</fieldset>
</form>
<div id="results">0 results.</div>
<div id="wrap">
<p id="p1">apple boy cat</p>
<p id="p2">ant boy cow</p>
<p id="p3">axe boots cat</p>
<span id="sp1">boots</span>
<span id="sp2">cow</span>
<span id="sp3">ant</span>
</div>
And the jQuery:
$('#search').keypress(
function(k) {
var string = $(this).val();
$('.highlight').removeClass('highlight');
$('#wrap').children().filter(':contains(' + string + ')').addClass('highlight');
$('#results').text($('.highlight').length + ' results.');
if (k.which === 13) {
return false;
}
});
JS Fiddle demo, this can give in-page searching options.

Categories