I have a textarea on the page. And decide validate this element. I insert simple text and in js I check the length this element. But when I delete all text I can save without any problem. I see in firebug and in textarea I find
<ul></ul><br/>
}
// js
for(var i=0; length > i; i++){
value = textElements[i].value;
if(value == "" ||(value == "<br/>" && element.tagName == "TEXTAREA")){
full = false;
emptyElements.push(elements[i]);
} else {
empty = false;
elements[i].style.borderColor = "";
elements[i].style.border = "";
}
}
Ad HTML
<br /><div id="edit-contentFrame-form:editor" style="visibility:hidden"><textarea id="edit-contentFrame-form:editor_input" name="edit-contentFrame-form:editor_input"><h3></h3><h3></h3><h3><br/></h3><ul>
</ul></textarea></div>
I try to find existing way to resolve this problem. But nothing to find.
///EDITED
function isEmptyTextArea(){
var str = document.getElementById('edit-contentFrame-form:editor_input').value;
var regexp = new RegExp("(<+[\w]+>+)*", "g");
var matches_array_tags = str.replace(regexp, '');
if(matches_array_tags.length == 0){
return true;
}
return false;
}
You can use regex to replace and strip all the "markup symbols" tags from the textarea if you don't want people to be able to input html.
var txtarea = document.getElementById('txtarea');
if(escape(txtarea.value) === '')
// textarea is empty
Not including whitespaces:
if(escape(txtarea.value.trim()) === '')
// textarea is empty (not including whitespaces)
I resolve my problem with next js function
function isCompleteTagContent(str){
var re= /<\S[^><]*>/g;
var matches_array_tags = str.replace(re, "");
if(matches_array_tags.trim().length == 0){
return true;
}
return false;
}
Related
I am trying to parse and reformat some web page.
The text is well formatted but the DOM structure is not (generated from WYSIWYG editor).
Thus I would like to parse the text content, then find back corresponding element(s) of each portions of the text.
example problem:
//example.html
<div id="a">
ABC
<span id="b">
DEF
<span id="c">
GHI
</span>
<span id="d">
JKR
</span>
</span>
</div>
//script.js
let a = document.getElementById('a');
let text_pos=a.textContent.indexOf('J');
// good way to get element #d from text_pos?
I know one way is to loop through all child elements of #a, then subtract each text length until 0.
But are there better way?
From what I understood from you is that you want to find parent element of the text that you search for. So instead of looping through all the text we will use indexOf search term and then backtrack to get first tag after that we will forward search to get closing tag and return this part of string between first tag and last tag
Another way is to backtrack to find first id= instead of first html tag but Im not sure if all you elements have id attribute
var data = "<div>Data<div id='d'><br/>AB</div></div>";
console.log(getparentElementOf("AB", data))
function getparentElementOf(searchTerm, data){
var indexOfTerm = data.indexOf(searchTerm);
var indexOfFirstTag = getStartIndexOfParentTag(indexOfTerm);
var indexOfEndTag = getEndIndexOfParentTag(indexOfTerm + searchTerm.length, data.length);
var element = data.substr(0, indexOfEndTag +1);
element = data.substring(indexOfFirstTag, element.length);
return element;
}
function getStartIndexOfParentTag(startFromIndex){
var indexOfFirstTag = -1;
var flagClosingBracket = false, flagOpeningBracket = false;
// back track from that found position until you find the first tag
for(var i = startFromIndex; i >= 0; i--){
// If we have detected closing bracket
if(flagClosingBracket == true){
// If we have / then cancel detected closing bracket
if(data[i] == "/"){
flagClosingBracket = false;
}else if(data[i] == "<"){
// otherwise we have found index of our first tage
flagOpeningBracket = true;
indexOfFirstTag = i;
i = -1; // to exit loop
}
}else{
// Otherwise detect closing bracket
if(data[i] == ">"){
flagClosingBracket = true;
}
}
}
return indexOfFirstTag;
}
function getEndIndexOfParentTag(startFromIndex, to){
var indexOfFirstTag = -1;
var flagClosingBracket = false, flagOpeningBracket = false, flagSlash = false;;
// back track from that found position until you find the first tag
for(var i = startFromIndex; i < to; i++){
// If we have detected closing bracket
if(flagOpeningBracket == true){
// If we have / then cancel detected closing bracket
if(data[i] == ">"){
flagOpeningBracket = false;
}else if(data[i] == "/"){
// otherwise we have found index of our first tage
flagSlash = true;
}
}else{
// Otherwise detect closing bracket
if(data[i] == "<"){
flagOpeningBracket = true;
}
}
if(flagSlash == true)
{
if(data[i] == ">"){
flagClosingBracket = true;
indexOfFirstTag = i;
i = to; // to exit loop
}
}
}
return indexOfFirstTag;
}
Well I think the question is alittle confusing but as I undestoood you you want the text of the elements as they are nested you should loop them. As you comment at the question text. I leave you a fragment of a loop with no lenght evaluation:
var strResult = "";
let a = document.getElementById('a');
for(content_word in a.textContent.trim().split("\n")) {
var isaWord = /[aA-zZ]/.test(a.textContent.trim().split("\n")[content_word])
if (isaWord) {
strResult = strResult + a.textContent.trim().split("\n")[content_word].trim()
}
};
console.log(strResult)
I hope this could help.
Regards
I am trying to figure out whether a text box has a given word, regardless of case. For example, how can I determine whether a given text box, #TextBox, has the word "hello" in it?
var specialwords = ['hello','Hello','HELLO']; //special words here
$('#TextBox').keydown(function() {
var text = $(this).val();
text = text.split(" ");
var newtext = "";
for(var i = 0; i < text.length; i++){
// code to check words
}
$("#check").html(newtext);
});
The easiest way to check whether a text box has a given word, irrespective of case, is to convert the text box to lowercase, then split by spaces and find the indexOf the word.
var word = "hello".toLowerCase(); // make sure this word is lowercase
$("#TextBox").keydown(function () {
var text = $(this).val().toLowerCase().split(" ");
if (text.indexOf(word) > -1) {
// do something
} else {
// word is not in the text box
}
})
If you want to check for an array of words, specialWords, wrap the if block in a for loop. This would be O(n²) complexity, but that should be fine, as long as your input isn't extremely long1.
1we're talking thousands upon thousands of words long for it to matter.
function checkAlphaCase(alpha) {
if (alpha == alpha.toLowerCase()) {
alert('LowerCase');
} else if (alpha == alpha.toUpperCase()) {
alert('UppperCase');
} else {
alert('MixedCase');
}
}
checkAlphaCase('ANIR');
TRY this
$(document).ready(function(){
var specialwords = ['hello','Hello','HELLO'];//special words here
$('#TextBox').keydown(function() {
//alert(this);
var text = $(this).val().trim();
console.log(text);
// text = text.trim().split(" ");
var newtext = "";
var up=0,low=0;
for(var i=0;i<text.length;i++){
if(text[i]==" ")
continue;
else{
if(text[i].trim()==text[i].trim().toLowerCase())
low++;
if(text[i].trim()==text[i].trim().toUpperCase())
up++;
}
}
if(up>0 && low>0)
newtext="mix case";
else if(up>0)
newtext="Upper case";
else if(low>0)
newtext="Lower case"
$("#check").html(newtext);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="TextBox">
<div id="check"></div>
You can make a case insensitive regex with all the words like this:
RegExp("\\b(?:" + specialwords.join("|") + ")\\b", "i")
then you can use it against each word. I am not sure what you are doing with the words once you identify them ... I will assume for the purpose of my code snippet that you are ignoring them from the text.
var specialwords = ['hello','world','pizza']; //special words here
var swr = RegExp("\\b(?:" + specialwords.join("|") + ")\\b", "i")
$('#TextBox').keydown(function() {
var text = $(this).val();
text = text.split(" ");
var newtext = [];
for(var i=0; i<text.length; i++){
if (!text.match(swr)) {
newtext.push(text)
}
}
$("#check").html(newtext.join(" "));
});
Using the \b as a word delimiter in regexp you can also check the whole text without breaking up the words if you want.
var specialwords = ['hello','world','pizza']; //special words here
var swr = RegExp("\\b(?:" + specialwords.join("|") + ")\\b", "i")
$('#TextBox').keydown(function() {
var text = $(this).val();
var newtext = text.replace(swr, "");
$("#check").html(newtext);
});
I have the following HTML structure:
<div class="content">
<p>somecontent</p>
<p>another content <span id="name-1">content</span> 1234214</p>
</div>
I want to wrap only numbers in additional span (1234214). So far I've made this:
jQuery(window).load(function() {
jQuery('.content p').html(function(index, value) {
return value.replace(/(\d+)/g, '<span class="mathjaxfont">$1</span>');
});
});
However this replaces the 1 in span id. How can I exclude checking element attributes?
You might want not only to exclude attributes (think about the h1-element for example) but constrain your replacing on the text nodes. See this questions for some ideas on how to get only and work with text nodes: How do I select text nodes with jQuery?
This answer in above question How do I select text nodes with jQuery? gives you a collection of text-nodes on which you can do your string-replacing.
You should use .contents() and .replaceWith() for this:
jQuery('.content p').contents().each(function() {
var method = this.nodeType == 1 ? 'html' : 'replaceWith';
$(this)[method](this.textContent.replace(
/(\d+)/g,
'<span class="mathjaxfont">$1</span>'
));
});
Here's a JSFiddle.
Long and hard solution, but should work in nested elements.
The idea is to handle element's .html() string character by character, wrapping numbers when they are found, but omitting numbers inside tags' definition.
Fiddle.
$(document).ready(function()
{
$('.content p').each(function()
{
$(this).html(handleHtml($(this).html()));
});
});
function handleHtml(html)
{
var resultHtml = "";
var numberStr = "";
var re = /[0-9]/;
var isTag = false, quote = "";
for (var i = 0; i < html.length; i++)
{
var char = html.substr(i, 1);
if (!isTag && re.test(char))
{
numberStr += char;
}
else
{
if (numberStr)
{
resultHtml += wrapNumber(numberStr);
numberStr = "";
}
resultHtml += char;
if (isTag && !quote && (char == '"' || char == "'"))
{
quote = char;
}
else if (quote && quote == char)
{
quote = "";
}
if (char == '<')
{
isTag = true;
}
else if (!quote && char == '>')
{
isTag = false;
}
}
}
if (numberStr)
{
resultHtml += wrapNumber(numberStr);
}
return resultHtml;
}
function wrapNumber(number)
{
return '<span class="mathjaxfont">' + number+ "</span>";
}
I' am use this custom function below to strip out unwanted characters from the textfield, this is done real time. The problem is that it allows spaces and users can enter as many spaces as they want, but I want allow only one space.
Is it possible?
function mask8(x){
var string = document.getElementById(x)
var regex = /[^A-Za-z ]/gi;
$("#"+x).removeClass("error");
if(string.value.search(regex) > -1) {
string.value = string.value.replace(regex, "");
$("#"+x).addClass("error");
}
}
If you just want to automatically collapse multiple spaces down to a single space without making it an error condition, you can do this:
function mask8(x){
var obj = document.getElementById(x);
var val = obj.value;
var illegalChars = /[^A-Za-z ]/gi;
$("#"+x).removeClass("error");
// automatically collapse multiple spaces down to a single space,
// don't make it an error condition
val = val.replace(/\s+/g, " ");
if(val.search(illegalChars) > -1) {
val = val.replace(illegalChars, "");
$("#"+x).addClass("error");
}
obj.value = val;
}
If you want to make multiple spaces an error condition, then you could do this:
function mask8(x){
var obj = document.getElementById(x);
var val = obj.value;
var illegalChars = /[^A-Za-z ]/gi;
var illegalCharsOrMultipleSpaces = /[^A-Za-z ]|\s\s/gi;
$("#"+x).removeClass("error");
if(val.search(illegalCharsOrMultipleSpaces) > -1) {
obj.value = val.replace(illegalChars, "").replace(/\s+/g, " ");
$("#"+x).addClass("error");
}
}
I have seen many posts pertaining to highlighting text in a DIV using javascript, but none do quite what I'm looking for.
What I need to do is highlight the text within a specific DIV, character by character as the user enters the search term. Conversely, as the user backspaces or deletes characters, I need to "de-highlight" the text of the same DIV.
I imagine this has already been done somewhere by someone, but I have not yet found a post here or from Google that behaves exactly as I need.
Any feedback is appreciated.
this code executes as user types characters into an input field. The problem with it is that in some instances, it inserts the string " " into the table as I type and I don't know why, so I'm searching for a different solution.
Thanks for your feedback!
function filterTable(Stxt, table) {
dehighlight(document.getElementById(table));
if (Stxt.value.length > 0)
highlight(Stxt.value.toLowerCase(), document.getElementById(table));
}
function dehighlight(container) {
for (var i = 0; i < container.childNodes.length; i++) {
var node = container.childNodes[i];
if (node.attributes && node.attributes['class'] && node.attributes['class'].value == 'highlighted') {
node.parentNode.parentNode.replaceChild(
document.createTextNode(node.parentNode.innerHTML.replace(/<[^>]+>/g, "")),node.parentNode);
return;
} else if (node.nodeType != 3) {
dehighlight(node);
}
}
}
function highlight(Stxt, container) {
for (var i = 0; i < container.childNodes.length; i++) {
var node = container.childNodes[i];
if (node.nodeType == 3) {
var data = node.data;
var data_low = data.toLowerCase();
if (data_low.indexOf(Stxt) >= 0) {
var new_node = document.createElement('span');
node.parentNode.replaceChild(new_node, node);
var result;
while ((result = data_low.indexOf(Stxt)) != -1) {
new_node.appendChild(document.createTextNode(data.substr(0, result)));
new_node.appendChild(create_node(
document.createTextNode(data.substr(result, Stxt.length))));
data = data.substr(result + Stxt.length);
data_low = data_low.substr(result + Stxt.length);
}
new_node.appendChild(document.createTextNode(data));
}
} else {
highlight(Stxt, node);
}
}
}
function create_node(child) {
var node = document.createElement('span');
node.setAttribute('class', 'highlighted');
node.attributes['class'].value = 'highlighted';
node.appendChild(child);
return node;
}
This can be easily done with a regular expression to change the div's content. Here's a simple implementation :
var s = document.getElementById('s'); // your input
var div = document.getElementById('a'); // the div to change
var t = a.textContent || a.innerText;
s.onkeyup = function(){
div.innerHTML = this.value
? t.replace(new RegExp('('+this.value+')','ig'), '<span class=highlight>$1</span>')
: t;
};
Demonstration (click "Run with JS")
EDIT :
This more sophisticated version works even if you have tables and stuff :
var s = document.getElementById('s');
var div = document.getElementById('a');
function changeNode(n, r, f) {
f=n.childNodes; for(c in f) changeNode(f[c], r);
if (n.data) {
f = document.createElement('span');
f.innerHTML = n.data.replace(r, '<span class=found>$1</span>');
n.parentNode.insertBefore(f, n);
n.parentNode.removeChild(n);
}
}
s.onkeyup = function(){
var spans = document.getElementsByClassName('found');
while (spans.length) {
var p = spans[0].parentNode;
p.innerHTML = p.textContent || p.innerText;
}
if (this.value) changeNode(
div, new RegExp('('+this.value+')','gi')
);
};
Demonstration (click "Run with JS")
My Rangy library has support for this, although I admit it's quite a large script for just this one use.
Demo: http://rangy.googlecode.com/svn/trunk/demos/textrange.html
I made a demo that uses regex.
// Input element
var input = document.getElementById("highlighter"),
// Text container element
divText = document.getElementById("text"),
// using textContent property if it exists
textProp = ("textContent" in divText) ? "textContent" : "innerText",
// Getting text to discard html tags (delete line 6 and use divText.innerHTML if you want to keep the HTML tags)
originalText = divText[textProp];
function handler(){
// if Input.value is empty clear the highlights
if(!this.value){
divText.innerHTML = originalText;
return true;
}
// Regex to group the matches, with tags 'global' and 'case insensitive'
var regex = new RegExp("("+this.value+")", "ig");
// replace text with the new one ($1 refers to first group matched by regex)
divText.innerHTML = originalText.replace(regex, "<span class='highlight'>$1</span>");
};
// adding listener to input.. IE uses attachEvent method
input.addEventListener("keyup", handler, false);
JSFiddle DEMO
let keywords = $("#highlight").html(); //get replace text
let textBody = $("#textBody"); //replace body
//create regular expression //text without case change
let custfilter = new RegExp("(" + keywords + ")", "ig");
//replace with highlight
textBody.html(textBody.html().replace(custfilter, "<b>$1</b>"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<p id="textBody">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
<span id="highlight">IPSUM</span>