Skip to content

Instantly share code, notes, and snippets.

@maettig
Forked from 140bytes/LICENSE.txt
Created December 20, 2011 12:59
Show Gist options
  • Save maettig/1501501 to your computer and use it in GitHub Desktop.
Save maettig/1501501 to your computer and use it in GitHub Desktop.
insertTags in 140byt.es

We all know the little toolbar buttons to insert something into a textarea, like BBCode, Wiki markup or HTML tags (fun fact: GitHub doesn't have a toolbar). One of the resources I used once was this German site but there are many more. I was wondering, how much of this nifty, widespread code could be squished into 140 bytes.

Currently, this is 158 154 bytes and I'm looking for your help. One thing I could do is to remove a.focus(); and +b.length but doing so I will loose a major feature. I'm looking for other ways to make this smaller.

function(a, b, c, d, e, f, g) //textarea, left and right tag
{
a.focus( //not really required but very helpful
d = 'selection');
f = a[e = d + 'End']; //get cursor position
g = a.value.split(''); //short replacement for substr
g[a[d += 'Start'] - 1] += b; //append both tags
g[f - 1] += c;
a.value = g.join(''); //set new text
a[e] = a[d] = f + b.length //set cursor position
}
function(a,b,c,d,e,f,g){a.focus(d='selection');f=a[e=d+'End'];g=a.value.split('');g[a[d+='Start']-1]+=b;g[f-1]+=c;a.value=g.join('');a[e]=a[d]=f+b.length}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Thiemo Mättig <http://maettig.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "insertTags",
"description": "Surrounds selected text in a textarea with tags, e.g. BBCode or Wikitext.",
"keywords": [
"bbcode",
"forms",
"tags",
"textarea",
"toolbar"
]
}
<!DOCTYPE html>
<button onclick="insertTags(a, &quot;'''&quot;, &quot;'''&quot;)">'''bold'''</button>
<button onclick="insertTags(a, &quot;''&quot;, &quot;''&quot;)">''italic''</button>
<button onclick="insertTags(a, '[[', ']]')">[[link]]</button><br>
<textarea cols="80" rows="20">Select a word and click a button.</textarea>
<script type="text/javascript">
function(a, b, c, d, e, f, g) //textarea, left and right tag
{
a.focus( //not really required but very helpful
d = 'selection');
f = a[e = d + 'End']; //get cursor position
g = a.value.split(''); //short replacement for substr
g[a[d += 'Start'] - 1] += b; //append both tags
g[f - 1] += c;
a.value = g.join(''); //set new text
a[e] = a[d] = f + b.length //set cursor position
}
var a = document.getElementsByTagName('TEXTAREA')[0];
</script>
@maettig
Copy link
Author

maettig commented Dec 20, 2011

Known bug: Because I'm using split and join instead of substr slice this fails for the first word in the textarea. But it saves 9 3 bytes.

@atk
Copy link

atk commented Dec 21, 2011

Save one byte by using the focus(argument): a.focus(d='selection';e=d+'End';d+='Start').

@maettig
Copy link
Author

maettig commented Dec 22, 2011

Updated, thanks. Here is another idea to save 5 9 bytes, but this will replace the first occurrence of a selected substring instead of the selected one: g=a.value;a.value=g.replace(g=g.slice(a[d],f),b+g+c);.

@atk
Copy link

atk commented Dec 22, 2011

I already thought of that, even tried to think up a clever idea with a replace s/(.{x})(.{y})(.{z})/$1b$2c$3/, but it was considerably longer than the original. Even using exec instead of replace doesn't help there.

@maettig
Copy link
Author

maettig commented Dec 22, 2011

I also tried to use a regular expression but it's, well, complicated. Here is the shortest solution I found so far: a.value=a.value.replace(RegExp('([\\s\\S]{'+a[d]+'})([\\s\\S]{'+(f-a[d])+'})'),'$1'+b+'$2'+c);. The most reliable solution is this, but it's 3 bytes longer than using split: g=a.value;a.value=g.slice(0,a[d])+b+g.slice(a[d],f)+c+g.slice(f);.

@atk
Copy link

atk commented Dec 22, 2011

Eval makes this 4 bytes shorter: a.value=a.value.replace(eval('/([\s\S]{'+a[d]+'})([\s\S]{'+(f-a[d])+'})/'),'$1'+b+'$2'+c);

@maettig
Copy link
Author

maettig commented Dec 22, 2011

I found a reliable (does not work well when nothing is selected) but very short solution based on a regular expression. It works for all positions in the string including the first character. It's short but still to long (164 163 bytes).

function(a,b,c,d,e,f){a.focus(d='selection');e=d+'End';d+='Start';f=a[e];a.value=a.value.replace(/|/g,function(g,h){return a[d]-h?f-h?g:c:b});a[e]=a[d]=f+b.length}
// The following version also works when nothing is selected (168 bytes)
function(a,b,c,d,e,f){a.focus(d='selection');e=d+'End';d+='Start';f=a[e];a.value=a.value.replace(/|/g,function(g,h){return(a[d]-h?g:b)+(f-h?g:c)});a[e]=a[d]=f+b.length}

@atk
Copy link

atk commented Dec 22, 2011

I thought about the possibility of function reusal for the replace callback...

@maettig
Copy link
Author

maettig commented Dec 22, 2011

I give up. The following version (132 bytes) does not care about setting the cursor position at all. But it works in all cases mentioned above (when the first character or nothing is selected). Anyway, new ideas are welcome.

function(a,b,c,d,e,f){a.focus(d='selection');e=a[d+'End'];d=a[d+'Start'];f=a.value;a.value=f.slice(0,d)+b+f.slice(d,e)+c+f.slice(e)}

@xpansive
Copy link

xpansive commented Jan 5, 2012

Do you really need to use split and join at all? You should be able to access into the string like an array.

@maettig
Copy link
Author

maettig commented Jan 5, 2012

@xpansive, I already tried this, but accessing single characters with [] seems to be read-only and can't be abused to insert something.

@xpansive
Copy link

xpansive commented Jan 6, 2012

@maettig Too bad. I was thinking in C...

@maettig
Copy link
Author

maettig commented Jan 16, 2012

Doing the same for Internet Explorer is incredible easy, including setting the focus and not losing the cursor position (78 bytes):

function(a,b,c){a=document.selection.createRange(a.focus());a.text=b+a.text+c}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment