$(iframe).bind('keypress', function (e) {
if (e.which == 13) {
var range = iframe.getSelection().getRangeAt(0);
var nodeText = $(range.startContainer, iframe).parent().html();
var leftPart = nodeText.substr(0, range.endOffset);
var rightPart = nodeText.substr(range.endOffset);
$(range.startContainer, iframe).parent().replaceWith('<big>' + leftPart + '</big><p>' + rightPart + '</p>');
return false;
}
});
I've got iframe with some content, e.g:
<p>someText</p>
When i place cursor between "some" and "text", and press enter, i want it to be splitted into this:
<big>some</big><p>Text</p>
everything seems to be working ok, but I also need to change cursor position to the beginnings of this: <p>Text</p>
I know how to set cursor position, but I need to select that element. just $('p', iframe) won't work, because I can have multiply <p> items in iframe. any ideas?
This is an unholy mix of DOM, which considers everything in terms of nodes and offsets, and jQuery-ish HTML-as-strings. The two do not mix well. You've misunderstood the endOffset and startOffset properties of DOM Ranges: they're not offsets within the innerHTML of the container. I suggest looking at MDC or the spec and refactoring your code to only use DOM nodes and not strings of HTML.
Denis ,
Give a common class name to all of them , so that it will effect on the elements.
I would add a dynamic id attribute (or use the metadata plugin) using jQuery to identify the split paragraph. And based on the identified split string place the cursor before the <p> tag. Do make sure to remove the id attribute (or some metadata) once you are done placing the cursor, so that any other splits or a backspace on the same <p> doesn't result in unintended consequences
Hope that helps
I found a nice solution without adding id or class to element. i changed this:
$(range.startContainer, iframe).parent().replaceWith('<big>'+leftPart+'</big><p>'+rightPart+'</p>');
to this:
var leftObject = $('<big>'+leftPart+'</big>');
var rightObject = $('<p>'+rightPart+'</p>');
$(range.startContainer, iframe).parent().replaceWith(leftObject);
leftObject.after(rightObject);
now i got both elements selected in leftObject and rightObject
Related
I want apply my JS on all my Textarea
$_PAGE->addJSOnLoad("
$('#textarea').keyup(function() {
var nombreCaractere = $(this).val().length;
var msg = nombreCaractere + ' caractére(s)';
$('#compteur').text(msg);
'<span id=compteur>' 0 caractére(s)'</span>';
});
");
This code is in constructor of my class textarea I wnat call him 1 times for all textarea
You should change the jquery selector from $('#textarea') to $('textarea') so as to target all textarea in the document.
Also you may want to use $('.compteur') in place of $('#compteur') so that your can have multiple counters, one for each textarea. Do not forget to update your html correspondingly
Edit: Please use $(this).find('.compteur') in place of $('.compteur') so that only the counter within the current textarea is affected
$('#textarea')
selects a HTML element with the ID "textarea". So this will be at max one textarea-element. The selector for all textareas would be just
$('textarea')
javscript event handlers can take a parameter (Event), so
$('textarea').keyup(function() {
var nombreCaractere = $(this).val().length;
var msg = nombreCaractere + ' caractére(s)';
// code for display, todo!
}
would put the event handler on every textarea (<textarea>) on your page. However, the display for the character count is a bit more difficult, unless it's one fixed element that scrolls along.
but let's say, your textareas all have an attribute data-charcount="[id]" that has the id of a div or something, that will display the character count.
Then you could replace
// code for display, todo!
with
$("#"+this.dataset.charcount).text(msg); // <- assuming this works
and your example textarea should look like this:
<textarea data-charcount="compteur"></textarea>
<span id="compteur"></span>
please note: every id should only appear once!
edit replace event.target with this, and fixed small error with string concat
Here is an example. Check the console for the result. The first two divs (not appended; above the <script> in the console) have the proper spacing and indention. However, the second two divs do not show the same formatting or white space as the original even though they are completely the same, but appended.
For example the input
var newElem = document.createElement('div');
document.body.appendChild(newElem);
var another = document.createElement('div');
newElem.appendChild(another);
console.log(document.body.innerHTML);
Gives the output
<div><div></div></div>
When I want it to look like
<div>
<div></div>
</div>
Is there any way to generate the proper white space between appended elements and retain that spacing when obtaining it using innerHTML (or a possible similar means)? I need to be able to visually display the hierarchy and structure of the page I'm working on.
I have tried appending it within an element that is in the actual HTML but it has the same behavior
I'd be okay with doing it using text nodes and line breaks as lincolnk suggested, but it needs to affect dynamic results, meaning I cannot use the same .createTextNode(' </br>') because different elements are in different levels of the hierarchy
No jQuery please
I think you're asking to be able to append elements to the DOM, such that the string returned from document.body.innerHTML will be formatted with indentation etc. as if you'd typed it into a text editor, right?
If so, something like this might work:
function indentedAppend(parent,child) {
var indent = "",
elem = parent;
while (elem && elem !== document.body) {
indent += " ";
elem = elem.parentNode;
}
if (parent.hasChildNodes() && parent.lastChild.nodeType === 3 && /^\s*[\r\n]\s*$/.test(parent.lastChild.textContent)) {
parent.insertBefore(document.createTextNode("\n" + indent), parent.lastChild);
parent.insertBefore(child, parent.lastChild);
} else {
parent.appendChild(document.createTextNode("\n" + indent));
parent.appendChild(child);
parent.appendChild(document.createTextNode("\n" + indent.slice(0,-2)));
}
}
demo: http://jsbin.com/ilAsAki/28/edit
I've not put too much thought into it, so you might need to play with it, but it's a starting point at least.
Also, i've assumed an indentation of 2 spaces as that's what you seemed to be using.
Oh, and you'll obviously need to be careful when using this with a <pre> tag or anywhere the CSS is set to maintain the whitespace of the HTML.
You can use document.createTextNode() to add a string directly.
var ft = document.createElement('div');
document.body.appendChild(ft);
document.body.appendChild(document.createTextNode(' '));
var another = document.createElement('div');
document.body.appendChild(another);
console.log(document.body.innerHTML);
I am trying to find the textual start and end of the selection. So, in the following text, if I selected "world! What a fine" from within "Hello, world! What a fine day it is!", I should get 7 as the start coordinate, and 24 as the end coordinate assuming a zero based index.
How is this achievable?
EDIT:
I am looking to find the selection of text that is not inside any <input> or <textarea> elements.
EDIT:
Decided the solution to use disabled <textarea>s
I use this:
/* Returns 3 strings, the part before the selection, the part after the selection and the selected part */
function getSelected()
{
var u = editor.val();
var start = editor.get(0).selectionStart;
var end = editor.get(0).selectionEnd;
return [u.substring(0, start), u.substring(end), u.substring(start, end)];
}
where editor is $("#editor") or whatever ID your textarea / input field may have.
Usage:
var select = getSelected()
editor.val(select[0] + '<h1>'+ select[2] + '</h1>' + select[1]);
Will wrap selected text in H1. If nothing is selected it will just add empty H1, but you can add checks and functionality to your liking.
** Not tested in all browsers, works in Chrome though **
This is possible but slightly complicated with contenteditable HTML content (as opposed to text within an <input> or <textarea> element). Here's a simple cross-browser implementation:
https://stackoverflow.com/a/4812022/96100
But I know a jQuery plugin that aims your problem and much more - https://github.com/localhost/jquery-fieldselection
I have <textarea> where user can type in his message to the world! Below, there are upload buttons... I would love to add link to uploaded file (don't worry, I have it); right next to the text that he was typing in.
Like, he types in 'Hello, world!', then uploads the file (its done via AJAX), and the link to that file is added in next line to the content of <textarea>. Attention! Is it possible to keep cursor (place where he left to type) in the same place?
All that may be done with jQuery... Any ideas? I know that there are method 'append()', but it won't be for this situation, right?
Try
var myTextArea = $('#myTextarea');
myTextArea.val(myTextArea.val() + '\nYour appended stuff');
This took me a while, but the following jQuery will do exactly what you want -- it not only appends text, but also keeps the cursor in the exact same spot by storing it and then resetting it:
var selectionStart = $('#your_textarea')[0].selectionStart;
var selectionEnd = $('#your_textarea')[0].selectionEnd;
$('#your_textarea').val($('#your_textarea').val() + 'The text you want to append');
$('#your_textarea')[0].selectionStart = selectionStart;
$('#your_textarea')[0].selectionEnd = selectionEnd;
You should probably wrap this in a function though.
You may take a look at the following answer which presents a nice plugin for inserting text at the caret position in a <textarea>.
You can use any of the available caret plugins for jQuery and basically:
Store the current caret position
Append the text to the textarea
Use the plugin to replace the caret position
If you want an "append" function in jQuery, one is easy enough to make:
(function($){
$.fn.extend({
valAppend: function(text){
return this.each(function(i,e){
var $e = $(e);
$e.val($e.val() + text);
});
}
});
})(jQuery);
Then you can use it by making a call to .valAppend(), referencing the input field(s).
You could use my Rangy inputs jQuery plugin for this, which works in all major browsers.
var $textarea = $("your_textarea_id");
var sel = $textarea.getSelection();
$textarea.insertText("\nSome text", sel.end).setSelection(sel.start, sel.end);
Let's say I have the following...
<div id="text">Some text</div>
When my mouse goes over Some, Some will be returned and the same with text.
Is this possible without putting each node into it's own element?
That is pretty much impossible. Since in Javascript you just know that you are hovering over an element (div and/or a textnode in this case), you can't know which word is hovered just like that.
Maybe with alot of effort and some geeky hacks on offsets and/or event.pageX/Y, but I would go for the solution you mentioned yourself, wrapping each word into its own element.
var $text = $('#text');
$text.html($text.text().replace(/\b(\w+)\b/g, "<span class='word'>$1</span>"));
$('.word').bind('mouseenter', function(e){
alert($(this).text());
});
This isn't possible without either wrapping the two nodes in elements or somehow determining the exact position of the text nodes and then binding to some parent's click event. The former option is simpler. Just wrap them in spans:
<div id="text"><span>Some<span> <span>text</span></div>
Or, if you need to wrap them all automatically:
jQuery.fn.getTextNodes = function(){
return this.not('script').contents().map(function(){
var n = this.nodeType;
return n === 3 ? this : n === 1 ? jQuery(this).getTextNodes().get() : [];
});
};
jQuery('#text').getTextNodes().replaceWith(function(){
return jQuery(this.data.replace(/\S+/g, '<span>$&</span>')).filter('span').click(function(){
alert('You just clicked on the word: ' + jQuery.text([this]));
}).end();
});
Demo: http://jsfiddle.net/PYKqM/