It turns URLs into hyperlinks only if I press the space bar or Enter after I type a URL. I want it to turn a URL into a hyperlink as soon as I finish typing it (right after I finish typing .com, .org, .net, etc). I am guessing it has something to do with startOffset / endOffset/ start / end / rng but I can't figure it out: tinymce.PluginManager.add('autolink', function(editor) { var AutoUrlDetectState; var AutoLinkPattern = /^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i; if (editor.settings.autolink_pattern) { AutoLinkPattern = editor.settings.autolink_pattern; } editor.on("keydown", function(e) { if (e.keyCode == 13) { return handleEnter(editor); } }); // Internet Explorer has built-in automatic linking for most cases if (tinymce.Env.ie) { editor.on("focus", function() { if (!AutoUrlDetectState) { AutoUrlDetectState = true; try { editor.execCommand('AutoUrlDetect', false, true); } catch (ex) { // Ignore } } }); return; } editor.on("keypress", function(e) { if (e.keyCode == 41) { return handleEclipse(editor); } }); editor.on("keyup", function(e) { if (e.keyCode == 32) { return handleSpacebar(editor); } }); function handleEclipse(editor) { parseCurrentLine(editor, -1, '(', true); } function handleSpacebar(editor) { parseCurrentLine(editor, 0, '', true); } function handleEnter(editor) { parseCurrentLine(editor, -1, '', false); } function parseCurrentLine(editor, end_offset, delimiter) { var rng, end, start, endContainer, bookmark, text, matches, prev, len, rngText; function scopeIndex(container, index) { if (index < 0) { index = 0; } if (container.nodeType == 3) { var len = container.data.length; if (index > len) { index = len; } } return index; } function setStart(container, offset) { if (container.nodeType != 1 || container.hasChildNodes()) { rng.setStart(container, scopeIndex(container, offset)); } else { rng.setStartBefore(container); } } function setEnd(container, offset) { if (container.nodeType != 1 || container.hasChildNodes()) { rng.setEnd(container, scopeIndex(container, offset)); } else { rng.setEndAfter(container); } } // Never create a link when we are inside a link if (editor.selection.getNode().tagName == 'A') { return; } // We need at least five characters to form a URL, // hence, at minimum, five characters from the beginning of the line. rng = editor.selection.getRng(true).cloneRange(); if (rng.startOffset < 5) { // During testing, the caret is placed between two text nodes. // The previous text node contains the URL. prev = rng.endContainer.previousSibling; if (!prev) { if (!rng.endContainer.firstChild || !rng.endContainer.firstChild.nextSibling) { return; } prev = rng.endContainer.firstChild.nextSibling; } len = prev.length; setStart(prev, len); setEnd(prev, len); if (rng.endOffset < 5) { return; } end = rng.endOffset; endContainer = prev; } else { endContainer = rng.endContainer; // Get a text node if (endContainer.nodeType != 3 && endContainer.firstChild) { while (endContainer.nodeType != 3 && endContainer.firstChild) { endContainer = endContainer.firstChild; } // Move range to text node if (endContainer.nodeType == 3) { setStart(endContainer, 0); setEnd(endContainer, endContainer.nodeValue.length); } } if (rng.endOffset == 1) { end = 2; } else { end = rng.endOffset - 1 - end_offset; } } start = end; do { // Move the selection one character backwards. setStart(endContainer, end >= 2 ? end - 2 : 0); setEnd(endContainer, end >= 1 ? end - 1 : 0); end -= 1; rngText = rng.toString(); // Loop until one of the following is found: a blank space, , delimiter, (end-2) >= 0 } while (rngText != ' ' && rngText !== '' && rngText.charCodeAt(0) != 160 && (end - 2) >= 0 && rngText != delimiter); if (rng.toString() == delimiter || rng.toString().charCodeAt(0) == 160) { setStart(endContainer, end); setEnd(endContainer, start); end += 1; } else if (rng.startOffset === 0) { setStart(endContainer, 0); setEnd(endContainer, start); } else { setStart(endContainer, end); setEnd(endContainer, start); } // Exclude last . from word like "www.site.com." text = rng.toString(); if (text.charAt(text.length - 1) == '.') { setEnd(endContainer, start - 1); } text = rng.toString(); matches = text.match(AutoLinkPattern); if (matches) { if (matches[1] == 'www.') { matches[1] = 'http://www.'; } else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) { matches[1] = 'mailto:' + matches[1]; } bookmark = editor.selection.getBookmark(); editor.selection.setRng(rng); editor.execCommand('createlink', false, matches[1] + matches[2]); editor.selection.moveToBookmark(bookmark); editor.nodeChanged(); } } }); Code (markup):
How would the script know that you have finished typing a URL? Right now when you press space it evaluates if the string has a pattern in the start: https, etc. To do what you want you'll have to check on every key entry if the finishing characters of the string include .com, .org etc. but this etc. has to be an array of all TLDs. Do you think you'll have real benefits from achieving what you describe? I think pressing space is good enough. If you think you really need this functionality I'll look how to do it.
I'd leave well alone. @Blizzardofozz and I are on the same wavelength lets say I typed in mysite.co How is the script to know that I've finished typing? How is the script to know that I'm going to keep going... .co.uk, .com, etc What if I was going to type in a deeplink? something like mysite.com/products/widgets/red/v2.html
How about turning it into a hyperlink if someone types http:// or https:// ? And then a space or a new line will mean the URL is ended. Can this be done?
I guess you guys missed my point. It turns into a hyperlink ONLY after you press the space bar or Enter when you finish typing a URL. A URL will stay like it's a plain text if nothing is pressed. What I want is I want it to start turning into a hyperlink while the URL is being typed. And yes it can be done. I have another editor that does that and I would want this one to do the same, BUT anything I tried didn't work. That script makes no sense to me. To understand what I mean by it "after you press the space bar or Enter" check out this jsfiddle: http://fiddle.tinymce.com/
It happens here: editor.on("keydown", function(e) { if (e.keyCode == 13) { return handleEnter(editor); } }); editor.on("keypress", function(e) { if (e.keyCode == 41) { return handleEclipse(editor); } }); editor.on("keyup", function(e) { if (e.keyCode == 32) { return handleSpacebar(editor); } }); Code (markup): This code checks if you have entered 13 - enter; 41 - select; 32 - space and then makes the magic. The new code should check on every key user presses if he had entered a string that is part of the pattern: var AutoLinkPattern = /^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto?[A-Z0-9._%+\-]+@)(.+)$/i; This after last space user had entered. I have to go now but I'll check tomorrow if you have managed to do it and will try to help if you didn't.
Try changing: editor.on("keyup", function(e) { if (e.keyCode == 32) { return handleSpacebar(editor); } }); Code (markup): into this: editor.on("keyup", function(e) { parseCurrentLine(editor, 0, '', true); }); Code (markup): and see if it will work.
Not quite. Actually when I was trying to make it work it did the same thing to me. Basically to goes like this you start typing http:// or www. the moment it hits the first letter it converts into a hyperlink:
editor.on("keyup", function(e) { return handleSpacebar(editor); }); Code (markup): try like this. just remove the if statement that checks if user presses space and the script will check the string for the URL pattern on every keyup. This should work. Oh I get it - it turns to link the URL when detects www. and then stops turning the string into link? Try what happens if comment out or remove this: if (editor.selection.getNode().tagName == 'A') { return; } Code (markup):
No, it's still doing the same thing. I don't think it's going to work unless something like this happens: you start typing a URL, after you key in http:// or www. it should turn into: <a href="http ://someurlcom">http ://someurl.com and it should stay open until you push the space bar or Enter, then </a> should close it. Other than that I can't see how it's going to work. Everything there goes through DOM, so I am not sure if it's designed to work that way, but maybe you can figure it out.
I didn't see you added this, let me try. I'll post a PS here so that I wouldn't have to run up the comment count. @Blizzardofozz **PS** Still doing the same thing.
I think a better / easier / less resources used solution would be to just use a warning before the editor, saying that links will be converted to actual hyperlinks after pressing space or enter. Having the DOM updating after every keystroke is demanding, and can lead to problems.
My bad I didn't fully analyze the script. This plugin uses editor.execCommand('createlink'...) method to create the link so to achieve what you want it should turn the link into a string again on the next key press and all process to repeat till user hits the space so the string will be turned into a link and again to string every time. Are you sure you've seen this in other editor and what is the name of this editor so I could check? It doesn't seems logical. Is it possible what you have seen is just underlining and coloring of the future link with css? And then after hitting space the string to be converted into a link?
Now that I checked it out, the other editor doesn't use the html dom or "createlink" function. It's a pure regex. My bad. Can this be done with the code I have up there? That would give my users some assurance that the link is / being created while they are entering it. It's all about a quality user experience for me.
Do you mean something like this: <!DOCTYPE html> <html> <head> <title>Test</title> <style> textarea { width: 400px; height: 200px; } </style> </head> <body> <textarea id="textarea"></textarea> <script> var tex = document.getElementById('textarea') , exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; tex.addEventListener('keyup', function(e) { var txt = tex.value; if (e.keyCode == 32) { var ttt = txt.replace(exp, "<a href='$1'>$1</a>") , mor = exp.test(txt); tex.value = ttt; if(mor == true) { exp = null; } } }); </script> </body> </html> Code (markup): However, it only works one time. I don't know how to disable keyup, so I null the element and causes the code error. Maybe the others can help.