Need a js guru to help me out with this
- mindfullsilence
- Professor


- Joined: Aug 04, 2008
- Posts: 846
- Status: Offline
So I've decided I suck at javascript. So I'm working on a personal project to get better. I'm trying to create a script that will autoclose an html element that has been typed into a textarea. I've gotten so close and then I hit a brick wall. You can check out the example here: demo.
What is supposed to happen is the script runs every time someone hits the backslash("/"). After the event is triggered, it should append whatever the last open element is.
I'm loading my text into the function up to wherever the cursor is. Then finding all the html elements and sticking them into an array that is pushed into another function. The second function matches each element up in pairs and spits out the remainder(the unclosed tag).
You can see the script here: script
My issue is that if I embed a couple elements and start closing them, I end up with something like "<///p>" instead of "</p>".
Any ideas?
What is supposed to happen is the script runs every time someone hits the backslash("/"). After the event is triggered, it should append whatever the last open element is.
I'm loading my text into the function up to wherever the cursor is. Then finding all the html elements and sticking them into an array that is pushed into another function. The second function matches each element up in pairs and spits out the remainder(the unclosed tag).
You can see the script here: script
My issue is that if I embed a couple elements and start closing them, I end up with something like "<///p>" instead of "</p>".
Any ideas?
Use your words like arrows to shoot toward your goal.
- Anonymous
- Bot


- Joined: 25 Feb 2008
- Posts: ?
- Loc: Ozzuland
- Status: Online
August 4th, 2011, 8:29 pm
- SpooF
- ٩๏̯͡๏۶


- Joined: May 22, 2004
- Posts: 3415
- Loc: Richland, WA
- Status: Offline
I through this together. I think it works.
JAVASCRIPT Code: [ Select ]
function priorElement(html,cursor_pos){
var re = /<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gi
var matches = html.match(re,html)
var elements = [];
var positions = [];
// Run through all the matches
for ( x in matches )
{
// Strip all the randon stuff so we just have the element.
var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
// If it has a trailing backslash ignore it
if(stripped_element.match(/\w\//)) // may want to look for these instead like in your script area|base|basefont|br|hr|input|img|link|meta
continue;
// Get rid of the `>` so we can match Ex. <a href="" class=""> turns, we need to
// matchs `<a` and not `<a>`
var stripped_element = stripped_element.substring(0,stripped_element.length-1)
positions.push(html.search(stripped_element));
elements.push(stripped_element);
}
if(positions && elements) {
var element = 0;
for(var i in positions)
{
if(positions[i] > cursor_pos)
{
// Find the element right before our cursor
element = i - 1;
break;
}
}
if(elements[element] == undefined)
return;
// return just the element, a, center, div, span...
return elements[element].replace(/[\<\/\>]/,'');
}
return;
}
var re = /<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gi
var matches = html.match(re,html)
var elements = [];
var positions = [];
// Run through all the matches
for ( x in matches )
{
// Strip all the randon stuff so we just have the element.
var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
// If it has a trailing backslash ignore it
if(stripped_element.match(/\w\//)) // may want to look for these instead like in your script area|base|basefont|br|hr|input|img|link|meta
continue;
// Get rid of the `>` so we can match Ex. <a href="" class=""> turns, we need to
// matchs `<a` and not `<a>`
var stripped_element = stripped_element.substring(0,stripped_element.length-1)
positions.push(html.search(stripped_element));
elements.push(stripped_element);
}
if(positions && elements) {
var element = 0;
for(var i in positions)
{
if(positions[i] > cursor_pos)
{
// Find the element right before our cursor
element = i - 1;
break;
}
}
if(elements[element] == undefined)
return;
// return just the element, a, center, div, span...
return elements[element].replace(/[\<\/\>]/,'');
}
return;
}
- function priorElement(html,cursor_pos){
- var re = /<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gi
- var matches = html.match(re,html)
- var elements = [];
- var positions = [];
- // Run through all the matches
- for ( x in matches )
- {
- // Strip all the randon stuff so we just have the element.
- var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
- // If it has a trailing backslash ignore it
- if(stripped_element.match(/\w\//)) // may want to look for these instead like in your script area|base|basefont|br|hr|input|img|link|meta
- continue;
- // Get rid of the `>` so we can match Ex. <a href="" class=""> turns, we need to
- // matchs `<a` and not `<a>`
- var stripped_element = stripped_element.substring(0,stripped_element.length-1)
- positions.push(html.search(stripped_element));
- elements.push(stripped_element);
- }
- if(positions && elements) {
- var element = 0;
- for(var i in positions)
- {
- if(positions[i] > cursor_pos)
- {
- // Find the element right before our cursor
- element = i - 1;
- break;
- }
- }
- if(elements[element] == undefined)
- return;
- // return just the element, a, center, div, span...
- return elements[element].replace(/[\<\/\>]/,'');
- }
- return;
- }
#define NULL (::rand() % 2)
- mindfullsilence
- Professor


- Joined: Aug 04, 2008
- Posts: 846
- Status: Offline
I wanted the elements to be closed in succession. So that if I have embedded elements, the function will close them in order. Example:
If I were to type "</" the result would be:
I've adapted your code, spoof, and almost have it working. The only issue is that with embedded elements such as illustrated above, the result is as follow:
HTML Code: [ Select ]
<div>
<p>
<a>
<p>
<a>
- <div>
- <p>
- <a>
If I were to type "</" the result would be:
- First time: a
- Second time: p
- Third time: div
I've adapted your code, spoof, and almost have it working. The only issue is that with embedded elements such as illustrated above, the result is as follow:
- First time: a
- Second time: a
- Third time: p
- Fourth time: div
Use your words like arrows to shoot toward your goal.
- mindfullsilence
- Professor


- Joined: Aug 04, 2008
- Posts: 846
- Status: Offline
I've made some changes to my code that follow a better logic but am still stuck with pretty much the same problem.
Here's the code I have so far:
The problem is on the third embedded html tag. Instead of this result:
I'm getting this:
Here's the code I have so far:
JAVASCRIPT Code: [ Select ]
function unclosed(html,cursor_pos){
//Remove any text after the cursor
html = html.substr(0,cursor_pos);
var re = /<[^<]+?>/gi
var matches = html.match(re,html)
var openers = [];
var closers = [];
var unclosed = [];
// Run through all the matches
for ( x in matches )
{
// Strip all the random stuff so we just have the element.
var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
// If it has a trailing backslash ignore it, since it's slef-closing
if(stripped_element.match(/\w\//))
continue;
// Get rid of the `>` so we can match, we need to match `<a` and not `<a>`
var stripped_element = stripped_element.substring(0,stripped_element.length-1);
stripped_element = stripped_element.replace("<","");
// now we check to see if it is a closing element or not
if(stripped_element.match(/\//))
{
//if it is, stick it in the "closers" array
closers.push(stripped_element);
}
else
{
//otherwise put it in the "openers" array
openers.push(stripped_element);
}
}
// if there are just as many closing tags as there are opening tags
// than all tags are closed, so return false.
if(openers.length == closers.length || openers.length == 0)
{
return false;
}
// if the closers array is empty, push the openers to the
// "unclosed" array and return the last entry
else if(closers.length == 0 && openers.length > 0) {
for ( x in openers )
{
unclosed.push(openers[x]);
}
return unclosed.pop();
}
// now we check for matches between opening and closing tags.
else
{
// go through each entry in the "openers" array
for (x in openers)
{
hasClose = new RegExp("\/"+openers[x],"gi");
// see if theres a match for it in the "closers" array
for (i in closers)
{
// if there is, remove the match from both arrays
// and constinue to the next entry.
if(closers[i].match(hasClose))
{
closers.splice(i,1);
openers.splice(x,1);
break;
}
// if there's not, add the "openers" entry to the
// "unclosed" array
else
{
unclosed.push(openers[x]);
}
}
}
// now return the last entry in the "unclosed" array.
return unclosed.pop();
}
}
//Remove any text after the cursor
html = html.substr(0,cursor_pos);
var re = /<[^<]+?>/gi
var matches = html.match(re,html)
var openers = [];
var closers = [];
var unclosed = [];
// Run through all the matches
for ( x in matches )
{
// Strip all the random stuff so we just have the element.
var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
// If it has a trailing backslash ignore it, since it's slef-closing
if(stripped_element.match(/\w\//))
continue;
// Get rid of the `>` so we can match, we need to match `<a` and not `<a>`
var stripped_element = stripped_element.substring(0,stripped_element.length-1);
stripped_element = stripped_element.replace("<","");
// now we check to see if it is a closing element or not
if(stripped_element.match(/\//))
{
//if it is, stick it in the "closers" array
closers.push(stripped_element);
}
else
{
//otherwise put it in the "openers" array
openers.push(stripped_element);
}
}
// if there are just as many closing tags as there are opening tags
// than all tags are closed, so return false.
if(openers.length == closers.length || openers.length == 0)
{
return false;
}
// if the closers array is empty, push the openers to the
// "unclosed" array and return the last entry
else if(closers.length == 0 && openers.length > 0) {
for ( x in openers )
{
unclosed.push(openers[x]);
}
return unclosed.pop();
}
// now we check for matches between opening and closing tags.
else
{
// go through each entry in the "openers" array
for (x in openers)
{
hasClose = new RegExp("\/"+openers[x],"gi");
// see if theres a match for it in the "closers" array
for (i in closers)
{
// if there is, remove the match from both arrays
// and constinue to the next entry.
if(closers[i].match(hasClose))
{
closers.splice(i,1);
openers.splice(x,1);
break;
}
// if there's not, add the "openers" entry to the
// "unclosed" array
else
{
unclosed.push(openers[x]);
}
}
}
// now return the last entry in the "unclosed" array.
return unclosed.pop();
}
}
- function unclosed(html,cursor_pos){
- //Remove any text after the cursor
- html = html.substr(0,cursor_pos);
- var re = /<[^<]+?>/gi
- var matches = html.match(re,html)
- var openers = [];
- var closers = [];
- var unclosed = [];
- // Run through all the matches
- for ( x in matches )
- {
- // Strip all the random stuff so we just have the element.
- var stripped_element = matches[x].replace(/\s[^\/>]+/g,'');
- // If it has a trailing backslash ignore it, since it's slef-closing
- if(stripped_element.match(/\w\//))
- continue;
- // Get rid of the `>` so we can match, we need to match `<a` and not `<a>`
- var stripped_element = stripped_element.substring(0,stripped_element.length-1);
- stripped_element = stripped_element.replace("<","");
- // now we check to see if it is a closing element or not
- if(stripped_element.match(/\//))
- {
- //if it is, stick it in the "closers" array
- closers.push(stripped_element);
- }
- else
- {
- //otherwise put it in the "openers" array
- openers.push(stripped_element);
- }
- }
- // if there are just as many closing tags as there are opening tags
- // than all tags are closed, so return false.
- if(openers.length == closers.length || openers.length == 0)
- {
- return false;
- }
- // if the closers array is empty, push the openers to the
- // "unclosed" array and return the last entry
- else if(closers.length == 0 && openers.length > 0) {
- for ( x in openers )
- {
- unclosed.push(openers[x]);
- }
- return unclosed.pop();
- }
- // now we check for matches between opening and closing tags.
- else
- {
- // go through each entry in the "openers" array
- for (x in openers)
- {
- hasClose = new RegExp("\/"+openers[x],"gi");
- // see if theres a match for it in the "closers" array
- for (i in closers)
- {
- // if there is, remove the match from both arrays
- // and constinue to the next entry.
- if(closers[i].match(hasClose))
- {
- closers.splice(i,1);
- openers.splice(x,1);
- break;
- }
- // if there's not, add the "openers" entry to the
- // "unclosed" array
- else
- {
- unclosed.push(openers[x]);
- }
- }
- }
- // now return the last entry in the "unclosed" array.
- return unclosed.pop();
- }
- }
The problem is on the third embedded html tag. Instead of this result:
HTML Code: [ Select ]
<div><p><a>
</a></p></div>
</a></p></div>
- <div><p><a>
- </a></p></div>
I'm getting this:
HTML Code: [ Select ]
<div><p><a>
</a></p></p>
</a></p></p>
- <div><p><a>
- </a></p></p>
Use your words like arrows to shoot toward your goal.
Page 1 of 1
To Reply to this topic you need to LOGIN or REGISTER. It is free.
Post Information
- Total Posts in this topic: 4 posts
- Users browsing this forum: No registered users and 229 guests
- You cannot post new topics in this forum
- You cannot reply to topics in this forum
- You cannot edit your posts in this forum
- You cannot delete your posts in this forum
- You cannot post attachments in this forum
