Coloring specific elements in a string - javascript

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.

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;

Convert newlines to <br> in a label

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>

Search function filter li's in pure Js

I'm trying to make an input that filters a <ul> based on the value in pure JavaScript. It should filter dynamically with the onkeyup by getting the li's and comparing their inner element name with the filter text.
Here is my function:
var searchFunction = function searchFeature (searchString) {
console.log("Is my search feature working?");
//Get the value entered in the search box
var inputString = document.getElementById('inputSearch');
var stringValue = inputString.value;
//Onkeyup we want to filter the content by the string entered in the search box
stringValue.onkeyup = function () {
//toUpperCase to make it case insensitive
var filter = stringValue.toUpperCase();
//loop through all the lis
for (var i = 0; i < eachStudent.length; i++) {
//Do this for all the elements (h3, email, joined-details, date)
var name = eachStudent[i].getElementsByClassName('student-details')[1].innerHTML;
//display all the results where indexOf() returns 0
if (name.toUpperCase().indexOf(filter) == 0)
eachStudent[i].style.display = 'list-item';
else
eachStudent[i].style.display = 'none';
}
}}
My HTML for the search bar:
<div class="student-search">
<input id="inputSearch" placeholder="Type name here.." type="text"> <button>Search</button></div>
My HTML for one of the li's:
<ul class="student-list">
<li class="student-item cf">
<div class="student-details">
<img class="avatar" src="#">
<h3>John Doe</h3>
<span class="email">John.Doe#example.com</span>
</div>
<div class="joined-details">
<span class="date">Joined 01/01/14</span>
</div>
</li>
I would like to filter all the elements (name, email, joined date) based on the value of the input.
Unfortunately, I don't get any errors and it's simply not working.
The function is correctly invoked because the console.log prints...
Here goes the codepen: http://codepen.io/Delano83/pen/qaxxjA?editors=1010
Any help or comments on my code is very appreciated.
There were several issues:
stringValue.onkeyup - stringValue is the value. You can't onkeyup it.
var eachStudent = document.querySelector(".student-item"); will fetch the first thing with student-item class. You need to use querySelectorAll or just use jquery's $('.find-item').
if (name.toUpperCase().indexOf(filter) == 0) indexOf returns 0 if the filter is found at the beginning of the name. 0 as match if found at index 0. You need to check against -1, which means it was not found at all.
Otherwise it more or less worked, good job.
I also added Jquery for me to fix it faster. If you insist on using pure javascript I am sure you will be able to edit it.
Check it out here: http://codepen.io/anon/pen/WGrrXW?editors=1010. Here is the resulting code:
var page = document.querySelector(".page");
var pageHeader = document.querySelector(".page-header");
var studentList = document.querySelector(".student-list");
var eachStudent = document.querySelectorAll(".student-item");
var studentDetails = document.querySelector(".student-details");
//Recreate Search Element in Js
var searchBar = function createBar(searchString) {
var studentSearch = document.createElement("div");
var input = document.createElement("input");
var searchButton = document.createElement("button");
input.type = "text";
var txtNode = document.createTextNode("Search");
if (typeof txtNode == "object") {
searchButton.appendChild(txtNode);
}
studentSearch.setAttribute("class", "student-search");
input.setAttribute("id", "inputSearch");
//append these elements to the page
studentSearch.appendChild(input);
studentSearch.appendChild(searchButton);
input.placeholder = "Type name here..";
return studentSearch;
}
var searchFunction = function searchFeature(searchString) {
console.log("Is my search feature working?");
//Get the value entered in the search box
var inputString = document.getElementById('inputSearch');
var stringValue = inputString.value;
//Onkeyup we want to filter the content by the string entered in the search box
inputString.onkeyup = function() {
//toUpperCase to make it case insensitive
var filter = $(this).val().toUpperCase()
//loop through all the lis
for (var i = 0; i < eachStudent.length; i++) {
//Do this for all the elements (h3, email, joined-details, date)
var name = $(eachStudent[i]).find('h3').text()
console.log(name, filter, name.toUpperCase().indexOf(filter))
//display all the results where indexOf() does not return -1
if (name.toUpperCase().indexOf(filter) != -1)
eachStudent[i].style.display = 'list-item';
else
eachStudent[i].style.display = 'none';
}
}
}
function addElements() {
console.log('Add search bar, trying to anyway...')
pageHeader.appendChild(searchBar());
// page.appendChild(paginationFilter());
onLoad();
}
window.onload = addElements;
window.onLoad = searchFunction;

Text Box Search / Javascript Function Arrays **not corresponding**

I want the user to "Search" some "Authors" and if they select the one in the database they are sent to a corresponding HTML. Otherwise "No Author Found" displays...
For some reason I cannot wrangle it properly - pls help!
//Search by Author
function searchAuth() {
var search_string = document.getElementById('search_string').value;
var arrayelement = ["John","Stan","Henry","Paul","Samuel"];
for (i=0;i<arrayelement.length;i++) {
if (input == arrayelement.John) {
var itemLink = document.getElementById('demo').innerHTML =
"<a href='https://www.google.ca/?gws_rd=ssl'>Your link</a>";
} else if (input == arrayelement.Stan) {
var itemLink = document.getElementById('demo').innerHTML =
"<a href='https://www.google.ca/?gws_rd=ssl'>Your link</a>";
}else {
var itemLink = document.getElementById('demo').innerHTML =
"Author not found."
}
}
<!--Author-->
<h3>Search By Author</h3>
<form name="searchTest" onsubmit="return(searchAuth());" action="#">
<input type="text" id="search_string" />
<input type="submit"/>
<p id="demo"></p>
Perhaps you are trying to do things like these..
P.S this is just a demo, for you to start :)
EDIT: added few explanation on some stuffs you might get confuse with. :)
//events once textbox gets out focus
//the events varies on which or where do you want to add the event. it can be on click of a search button or submit button just like in your example.
document.getElementById('search-text-box-id').addEventListener("focusout", function() {
//searchString gets the textbox value.
var searchString = document.getElementById('search-text-box-id').value;
var searchList = ["John","Stan","Henry","Paul","Samuel"];
//Loop searchList
for (i=0; i < searchList.length; i++) {
//i which usually means the index or the key of the array's object(s).
var searchItem = "";
//searchList[i] loops its object by getting the index resulting to John, Stan and so on and so forth.
if (searchString == searchList[i]) {
searchItem = searchList[i];
document.getElementById('search-result-container').innerHTML = searchItem + " link";
//stop looping as the loop found a match.
return;
}
else {
searchItem = "Author not found.";
document.getElementById('search-result-container').innerHTML = searchItem;
}
}
});
<label for="search-text-box"></label>
<input type="text" id="search-text-box-id" name="search-text-box" />
<p id="search-result-container"></p>

Removing a text field using Javascript

I have the following code to add text fields when the function is called:
<span id="response"></span>
<script>
var qcountBox = 2;
var acountBox = 2;
var qboxName = 0;
var aboxName = 0;
function addInput()
{
var qboxName="question"+qcountBox;
var aboxName="answer"+acountBox;
if(qcountBox <=10 && acountBox <= 10)
{
document.getElementById('response').innerHTML+='<br/>Question '+qcountBox+': <input type="text" name="'+qboxName+'"/>';
document.getElementById('response').innerHTML+='<br/>Answer '+acountBox+': <input type="text" name="'+aboxName+'"/><br/>';
qcountBox ++;
acountBox ++;
}else
alert("No more than 10 questions allowed at this time.");
}
I also would like to be able to add a function to remove any new fields I have added. Any suggestions? Thanks
<script>
var qcountBox = 1;
var acountBox = 1;
var qboxName = 0;
var aboxName = 0;
function addInput()
{
var qboxName="question"+qcountBox;
var aboxName="answer"+acountBox;
if(qcountBox <=10 && acountBox <= 10)
{
document.getElementById('response').innerHTML+='<div id="'+qcountBox+'"><br/>Question '+qcountBox+': <input type="text" name="'+qboxName+'"/>';
document.getElementById('response').innerHTML+='<br/>Answer '+acountBox+': <input type="text" name="'+aboxName+'"/><br/></div>';
qcountBox ++;
acountBox ++;
}else
alert("No more than 10 questions allowed at this time.");
}
function removeInput(id)
{
document.getElementById(id).innerHTML = '';
}
You can remove any question that you added using the id of the question div (same as qboxName)
Surround each new piece of HTML in a span with a common class name. Then, find all the objects with that class name and remove them.
Add the span and class name to these:
document.getElementById('response').innerHTML+='<span class="added"> <br/>Question '+qcountBox+': <input type="text" name="'+qboxName+'"/></span>';
document.getElementById('response').innerHTML+='<span class="added"><br/>Answer '+acountBox+': <input type="text" name="'+aboxName+'"/><br/></span>';
Then, you can remove all the added spans like this:
var items = document.getElementsByClassName("added");
for (var i = 0; i < items.length; i++) {
items[i].parentNode.removeChild(items[i]);
}
Note: This is a generally better way to add your new HTML as it doesn't rewrite all previous HTML - it just adds new DOM objects:
var span = document.createElement("span");
span.className = "added";
span.innerHTML = '<br/>Question '+qcountBox+': <input type="text" name="'+qboxName+'"/><br/>Answer '+acountBox+': <input type="text" name="'+aboxName+'"/><br/>';
document.getElementById('response').appendChild(span);
You should actually create an input element in javascript and append it to your container through appendChild instead of using innerHTML +=.
You should also set an ID for those fields, not just a name. But it can be the same as theirs names.
Like this
var input = document.createElement("input");
input.type = "text";
input.name = input.id = qboxName;
document.getElementById("response").appendChild(input);
And then, you know, do the same for the other input field you need.
I know you need a text label for the boxes, or whatever, just do the same process to insert a span tag before them.
Also, I don't see a reason for those two counting variables. Instead of qcountBox and acountBox it's totally possible to have only one single counting variable. Maybe I'm wrong but shouldn't you increase this counting before setting the boxes names?
As for removing it, you can use the removeChild method, then, decrease your counting variable. like this:
function removeInput()
{
var qboxName = "question" + count;
var aboxName = "answer" + count;
document.getElementById("response").removeChild(document.getElementById(aboxName));
document.getElementById("response").removeChild(document.getElementById(aboxName));
count--;
}
Maybe if you're going to insert other elements together with these fields, like span tags for labels etc, it would be better to wrap them all up in a div or something, then simply do a removeChild to this container div only.

Categories