JavaScript regex to find special words not wrapped in a tag
I'm trying to write a regex to search a string and find words wrapped in curly braces that are not wrapped in a span tag with a specific attribute (data-placeholder).
Example text:
This is a test. Testing <span class="anything">{variable}</span> wrapped without the attribute, but this one <span data-placeholder="val">{variable}</span> is. The first should match, the second should not, and the last one should as well {variable}
The best I've come up with so far is:
/[^>]{(.)*}[^>]/g
But that has a few problems. There may or may not be text after the closing }, so that pattern does not match the last instance in the example text. It will also not match the first instance, I'm not sure how to write "match anything except this word" for the first part of the regex.
The goal is to convert instances of (note anything is literal):
{variable}
<span class="anything">{variable}</span>
To this (or):
<span data-placeholder="">{variable}</span>
<span data-placeholder="" class="anything">{variable}</span>
Without disrupting any existing instances that are already converted.
Thanks!
Edit: solved using a combination of DOM traversal and regex for textnodes. Thanks @jonathan-m and @frankiethekneeman!
My Solution (thanks again to @jonathan-m and @frankiethekneeman):
//remove any broken variables
variables = $( 'span[data-placeholder]', this.editor );
for ( i = 0, len = variables.length; i < len; i++ ) {
if ( pp.arrayIndexOf( dict, variables[ i ].innerHTML ) == -1 ) {
t = variables[ i ].childNodes[ 0 ];
$( t ).unwrap( );
}
}
//convert any variables already in a span tag
variables = $( 'span', this.editor );
for ( i = 0, len = variables.length; i < len; i++ ) {
t = variables[ i ].innerHTML.match( /^{(.)*}$/ );
if ( !variables[ i ].hasAttribute( 'data-placeholder' ) && t != null && pp.arrayIndexOf( dict, t[ 0 ] ) != -1 ) {
variables[ i ].setAttribute( 'data-placeholder', this.getVariable( t[ 0 ] ) );
}
}
//convert any variables in a text node
variables = $( 'p', this.editor );
for ( i = 0, len = variables.length; i < len; i++ ) {
for ( j = 0, len2 = variables[ i ].childNodes.length; j < len2; j++ ) {
if ( variables[ i ].childNodes[ j ].nodeType == 3 ) {
t = variables[ i ].childNodes[ j ].data.match( /{(.)*}/ );
if ( t != null && pp.arrayIndexOf( dict, t[ 0 ] ) != -1 ) {
span = document.createElement( 'span' );
span.setAttribute( 'data-placeholder', this.getVariable( t[ 0 ] ) );
span.innerHTML = t[ 0 ];
variables[ i ].replaceChild( span, variables[ i ].childNodes[ j ] );
}
}
}
}
Loop 1: In case a user has edited the text and turned a variable into something else, break the edited content out of its wrapper.
Loop 2: Check every span tag, if it already has data-placeholder ignore it, if not check its contents to see if its a variable.
Loop 3: Check every p tag, look for text nodes inside it that match a variable. If found, create a span and replace the text node with a wrapper.
Note: Just realized I haven't tested multiple occurrences in a text node, so that may not work with this code. Going to test now.
Working in my Google Chrome directly on this question, I find following code a promising start in the JavaScript console:
Code
nodeList = document.querySelectorAll('span');
nodeArray=[];
for (i=0; i < nodeList.length; i++) {nodeArray.push(nodeList[i]);}
nodeArray.filter(function(node) {return node.innerText.match(/{variable}/)});
Note how we select actual HTML elements based on the Document Object Model and then look for candidates based on their text content. Alternatively one could use .innerHTML, or actually manipulate document content via assignment to these properties.
Result
[
<span class="str">
"/span> wrapped without the attribute, but this one <span data-placeholder="val">{variable}</"
</span>
,
<span class="pln">{variable}</span>
,
<span class="pln">{variable}</span>
,
<span class="comment-copy">
"@Jonathan What are the {variable} and the <span...> following it contained in? Are they in another span, div, p, or body tag? if yes, which?"
</span>
,
<span class="str">/{variable}/</span>
]
jQuery.contains may also be interesting.
链接地址: http://www.djcxy.com/p/59508.html上一篇: 如何正确地表达嵌套的字符串