Highlight/select multiple divs with ranges w/ contenteditable? - javascript

Let's say I have a set of contenteditable="true" divs.
<div id="0" contenteditable="true"></div>
<div id="1" contenteditable..></div>
<div...etc></div>
I can't have one div, multiple divs is a must. How could I highlight the content of more than one div? Using ranges? Anything else?

The answer is that it depends on the browser. See this example for a test of two methods using Ranges. The first attempts to create a Range per editable <div> and add all of them to the selection. The second attempts to create a single Range encompassing the contents of two editable <div>s.
Results:
In all browsers, it is impossible for the user to create a selection that lives in more than one editable element;
Firefox is the most permissive of the major browsers. Both programmatic methods work.
Safari and Chrome is the least permissive: neither method selects content from more than one editable element.
Opera 11 does not support multiple Ranges in the selection, but does support a selected Range spanning more than one editable element.
IE pre-version 9 does not support DOM Range or the same Selection API as other browsers, but the equivalent TextRange code does not allow selection from more than one editable element.

It is possible to switch the divs to contenteditable="false" on the fly as a consequence of starting a selection in one of them. Something like this gives you the idea (using JQuery):
$('div').bind("selectstart", function() {
$('div').attr("contenteditable", false);
});​
Here's a fiddle to demonstrate (only tested in Chrome).
Note in the fiddle example that the first ContentEditable Div gets the focus. This allows you to type away as normal, but as soon as you select anything, using mouse or keyboard, you'll see you can extend the selection across divs as usual.
This obviously needs fleshing out to work with multiple browsers and to turn back to contenteditable="true" appropriately. But I think the approach is valid.

Related

Javascript: Copy to clipboard in iOS

I'm well aware that iOS Safari doesn't support document.execCommand("copy"). However, I would like to make it as easy as possible for iOS users to copy a block of text.
A user can long-press a word on the page, which will highlight the word. They can then manipulate the selection range to highlight the entire text block, but this can be a bit touchy. Once they have the entire range selected, they get a callout balloon with various options, including copy. I'd like to find a way to simplify this workflow if at all possible.
It's possible to create a button to highlight text for a user with one click. But this doesn't bring up the text options bubble. And when the user long-presses that selection, it reselects just a single word.
Is it possible to highlight an entire text block (with the options bubble) on long press? Are there other ways to make the copy/paste easier for users?

Dynamically sized select element IE not scrolling

When I dynamically add option elements to a select element with a size of say 10 on IE, a scrollbar does not appear once my list of options exceeds the height of my select element, and I am unable to scroll to the rest of the options. This only happens on IE and is an issue when dynamically adding/removing options. Anyone know of workarounds? I've tried creating wrappers and one approach that might work is re-rendering the entire select element each time, but that is wasteful
I don't know the solution to this specific problem,
but you get to ignore a lot of the hassle with cross-browser support on UI elements by using jQuery UI.
If it's possible, you should take a look at https://jqueryui.com/selectmenu/
It's more easily customizable, so if the default select-box' off-by-one pixels annoy you, you can get around that too by using it :)

Chosen drop list outside parent div

I've been using the Chosen plugin for my app, but I've run into several major issues. They all come down to the same thing - the drop list is created as a sibling div to the select element, so it is forced to render inside the parent div. Which, in my case, is set to overflow: auto, which creates undesired behavior if the select is near the bottom of the visible area.
Obviously the solution would be to append the drop-down element to body and use dynamic positioning. I could probably fix it by spending some time with the Chosen code, but I was wondering if there's an existing workaround/branch (the only ones I could find are dated several years ago and are probably missing lots of newer features from the main version). I would imagine this is a pretty common use case (using it inside a dialog comes to mind, too).
Also, it should probably be able to drop up, too, in case it is near the bottom of the page.
Update: I expected this to be a known issue so I thought an example wasn't needed. In any case, here it is: http://jsfiddle.net/ooonqtox/

Get node/element before and after caret position in contenteditable div

I have a contenteditable div in my GWT application and when I press backspace or delete key, I want to get the node before and after caret position and check whether it is a text node or not.
Element element = DOM.createDiv();
element.setAttribute(contenteditable, "true");
basePanel.getElement().appendChild(element);
This is how I created the content editable div.
Any solutions will be appreciative.
Regards.
Dig into selection and range classes. They are not yet browser compatible, so you might use
https://code.google.com/p/rangy/ or
jquery++
for abstraction. You then create a range for your div, expand it by 1 on both ends. then you examine startcontainer and endcontainer to find out their node type.
The selection and range apis are not overly beautiful and working with them is more involved than necessary, but that is the way to get it done.

Get the visible range in Firefox

Is it possible to get the current viewport Range (the visible part of the page inside the browser) using XUL functions from Javascript or plain Javascript?
Thank you!
For the viewport you need to use document.documentElement.scrollTop/scrollLeft/scrollHeight/scrollWidth. There is a slight complication: I think that in quirks mode (document.compatMode is "BackCompat") you need to check these properties on document.body instead of document.documentElement.
See https://developer.mozilla.org/en/DOM/element.scrollTop for documentation.
Edit: It seems that you aren't really interested in the viewport but rather its contents. AFAIK there is no generic way to get the contents of a particular area of the web page. It definitely cannot be described by a single Range object, rather a set of ranges. And even then: if the element has lots of text and all of it is a single TextNode, you won't know which parts of the text are visible and which are not.
However, in some special cases (particularly when the page structure is simple) you might be able to learn what text is being displayed by using range.getBoundingClientRect(). You start by selecting everything in your range and reducing that selection until the range size is within viewport boundaries.
Here is an example that does it for a vertically scrollable <div> containing lots of text: http://jsfiddle.net/5vEdP/ (tested in Firefox 6, Chrome 14 and IE 9). It first needs to make sure that each text character is placed into its own TextNode, otherwise you won't be able to select it separately in a Range object. It then selects the container of the text and moves the start of the range until the top boundary of the range is below the top boundary of the container. And then it does the same thing for the bottom boundary by moving the end of the range. In the end you get a range that selected only the text nodes that are fully visible.
width :document.body.offsetWidth;
height :document.body.offsetHeight;
HERE are better examples for various browsers

Categories