Skip to content

Commit

Permalink
Move getBookmark() and moveToBookmark() from deprecated dijit/_base/f…
Browse files Browse the repository at this point in the history
…ocus to dijit/selection. This eliminates the Editor dependency on deprecated dijit/_base/focus, but the code is still weird in that editor has it's own enhanced version of getBookmark() and moveToBookmark() that tweak the results of the original methods. Refs #16683 !strict.

git-svn-id: http://svn.dojotoolkit.org/src/dijit/trunk@31279 560b804f-0ae3-0310-86f3-f6aa0a117693
  • Loading branch information
wkeese committed Apr 17, 2013
1 parent 8cd207f commit 74302ff
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 134 deletions.
19 changes: 9 additions & 10 deletions Editor.js
Expand Up @@ -13,8 +13,6 @@ define([
"dojo/sniff", // has("ie") has("mac") has("webkit")
"dojo/string", // string.substitute
"dojo/topic", // topic.publish()
"dojo/_base/window", // win.withGlobal
"./_base/focus", // dijit.getBookmark()
"./_Container",
"./Toolbar",
"./ToolbarSeparator",
Expand All @@ -27,7 +25,10 @@ define([
"./_editor/RichText",
"./main", // dijit._scopeName
"dojo/i18n!./_editor/nls/commands"
], function(require, array, declare, Deferred, i18n, domAttr, domClass, domGeometry, domStyle, keys, lang, has, string, topic, win, focusBase, _Container, Toolbar, ToolbarSeparator, _LayoutWidget, ToggleButton, _Plugin, EnterKeyHandling, html, rangeapi, RichText, dijit){
], function(require, array, declare, Deferred, i18n, domAttr, domClass, domGeometry, domStyle,
keys, lang, has, string, topic,
_Container, Toolbar, ToolbarSeparator, _LayoutWidget, ToggleButton,
_Plugin, EnterKeyHandling, html, rangeapi, RichText, dijit){

// module:
// dijit/Editor
Expand Down Expand Up @@ -459,14 +460,12 @@ define([
if(mark){
if(has("ie") < 9){
if(lang.isArray(mark)){
//IE CONTROL, have to use the native bookmark.
// IE CONTROL, have to use the native bookmark.
bookmark = [];
array.forEach(mark, function(n){
bookmark.push(rangeapi.getNode(n, this.editNode));
}, this);
win.withGlobal(this.window, 'moveToBookmark', focusBase, [
{mark: bookmark, isCollapsed: col}
]);
this.selection.moveToBookmark({mark: bookmark, isCollapsed: col});
}else{
if(mark.startContainer && mark.endContainer){
// Use the pseudo WC3 range API. This works better for positions
Expand Down Expand Up @@ -583,7 +582,7 @@ define([
// Get the currently selected text
// tags:
// protected
var b = win.withGlobal(this.window, focusBase.getBookmark);
var b = this.selection.getBookmark();
var tmp = [];
if(b && b.mark){
var mark = b.mark;
Expand All @@ -599,7 +598,7 @@ define([
if(range){
b.mark = range.cloneRange();
}else{
b.mark = win.withGlobal(this.window, focusBase.getBookmark);
b.mark = this.selection.getBookmark();
}
}
}else{
Expand Down Expand Up @@ -760,7 +759,7 @@ define([
// only restore the selection if the current range is collapsed
// if not collapsed, then it means the editor does not lose
// selection and there is no need to restore it
if(win.withGlobal(this.window, 'isCollapsed', focusBase)){
if(this.selection.isCollapsed()){
this._moveToBookmark(this._savedSelection);
}
delete this._savedSelection;
Expand Down
128 changes: 6 additions & 122 deletions _base/focus.js
Expand Up @@ -5,8 +5,9 @@ define([
"dojo/topic", // publish
"dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
"../focus",
"../selection",
"../main" // for exporting symbols to dijit
], function(array, dom, lang, topic, win, focus, dijit){
], function(array, dom, lang, topic, win, focus, selection, dijit){

// module:
// dijit/_base/focus
Expand All @@ -33,90 +34,8 @@ define([
getBookmark: function(){
// summary:
// Retrieves a bookmark that can be used with moveToBookmark to return to the same range
var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode;

if(win.global.getSelection){
//W3C Range API for selections.
sel = win.global.getSelection();
if(sel){
if(sel.isCollapsed){
tg = cf? cf.tagName : "";
if(tg){
//Create a fake rangelike item to restore selections.
tg = tg.toLowerCase();
if(tg == "textarea" ||
(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
sel = {
start: cf.selectionStart,
end: cf.selectionEnd,
node: cf,
pRange: true
};
return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
}
}
bm = {isCollapsed:true};
if(sel.rangeCount){
bm.mark = sel.getRangeAt(0).cloneRange();
}
}else{
rg = sel.getRangeAt(0);
bm = {isCollapsed: false, mark: rg.cloneRange()};
}
}
}else if(sel){
// If the current focus was a input of some sort and no selection, don't bother saving
// a native bookmark. This is because it causes issues with dialog/page selection restore.
// So, we need to create psuedo bookmarks to work with.
tg = cf ? cf.tagName : "";
tg = tg.toLowerCase();
if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
if(sel.type && sel.type.toLowerCase() == "none"){
return {
isCollapsed: true,
mark: null
}
}else{
rg = sel.createRange();
return {
isCollapsed: rg.text && rg.text.length?false:true,
mark: {
range: rg,
pRange: true
}
};
}
}
bm = {};

//'IE' way for selections.
try{
// createRange() throws exception when dojo in iframe
//and nothing selected, see #9632
rg = sel.createRange();
bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
}catch(e){
bm.isCollapsed = true;
return bm;
}
if(sel.type.toUpperCase() == 'CONTROL'){
if(rg.length){
bm.mark=[];
var i=0,len=rg.length;
while(i<len){
bm.mark.push(rg.item(i++));
}
}else{
bm.isCollapsed = true;
bm.mark = null;
}
}else{
bm.mark = rg.getBookmark();
}
}else{
console.warn("No idea how to store the current selection for this browser!");
}
return bm; // Object
var sel = win.global == window ? selection : new selection.SelectionManager(win.global);
return sel.getBookmark();
},

moveToBookmark: function(/*Object*/ bookmark){
Expand All @@ -125,43 +44,8 @@ define([
// bookmark:
// This should be a returned object from dijit.getBookmark()

var _doc = win.doc,
mark = bookmark.mark;
if(mark){
if(win.global.getSelection){
//W3C Rangi API (FF, WebKit, Opera, etc)
var sel = win.global.getSelection();
if(sel && sel.removeAllRanges){
if(mark.pRange){
var n = mark.node;
n.selectionStart = mark.start;
n.selectionEnd = mark.end;
}else{
sel.removeAllRanges();
sel.addRange(mark);
}
}else{
console.warn("No idea how to restore selection for this browser!");
}
}else if(_doc.selection && mark){
//'IE' way.
var rg;
if(mark.pRange){
rg = mark.range;
}else if(lang.isArray(mark)){
rg = _doc.body.createControlRange();
//rg.addElement does not have call/apply method, so can not call it directly
//rg is not available in "range.addElement(item)", so can't use that either
array.forEach(mark, function(n){
rg.addElement(n);
});
}else{
rg = _doc.body.createTextRange();
rg.moveToBookmark(mark);
}
rg.select();
}
}
var sel = win.global == window ? selection : new selection.SelectionManager(win.global);
return sel.moveToBookmark(bookmark);
},

getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
Expand Down
149 changes: 147 additions & 2 deletions selection.js
@@ -1,9 +1,10 @@
define([
"dojo/_base/array",
"dojo/dom", // dom.byId
"dojo/_base/lang",
"dojo/sniff", // has("ie") has("opera")
"dojo/_base/window"
], function(dom, lang, has, baseWindow){
], function(array, dom, lang, has, baseWindow){

// module:
// dijit/selection
Expand Down Expand Up @@ -366,7 +367,151 @@ define([
}
}
return false; // Boolean
}
},

this.getBookmark = function(){
// summary:
// Retrieves a bookmark that can be used with moveToBookmark to reselect the currently selected range.

// TODO: merge additional code from Editor._getBookmark into this method

var bm, rg, tg, sel = doc.selection, cf = focus.curNode;

if(doc.getSelection){
// W3C Range API for selections.
sel = win.getSelection();
if(sel){
if(sel.isCollapsed){
tg = cf? cf.tagName : "";
if(tg){
// Create a fake rangelike item to restore selections.
tg = tg.toLowerCase();
if(tg == "textarea" ||
(tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
sel = {
start: cf.selectionStart,
end: cf.selectionEnd,
node: cf,
pRange: true
};
return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
}
}
bm = {isCollapsed:true};
if(sel.rangeCount){
bm.mark = sel.getRangeAt(0).cloneRange();
}
}else{
rg = sel.getRangeAt(0);
bm = {isCollapsed: false, mark: rg.cloneRange()};
}
}
}else if(sel){
// If the current focus was a input of some sort and no selection, don't bother saving
// a native bookmark. This is because it causes issues with dialog/page selection restore.
// So, we need to create pseudo bookmarks to work with.
tg = cf ? cf.tagName : "";
tg = tg.toLowerCase();
if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
if(sel.type && sel.type.toLowerCase() == "none"){
return {
isCollapsed: true,
mark: null
}
}else{
rg = sel.createRange();
return {
isCollapsed: rg.text && rg.text.length?false:true,
mark: {
range: rg,
pRange: true
}
};
}
}
bm = {};

//'IE' way for selections.
try{
// createRange() throws exception when dojo in iframe
// and nothing selected, see #9632
rg = sel.createRange();
bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
}catch(e){
bm.isCollapsed = true;
return bm;
}
if(sel.type.toUpperCase() == 'CONTROL'){
if(rg.length){
bm.mark=[];
var i=0,len=rg.length;
while(i<len){
bm.mark.push(rg.item(i++));
}
}else{
bm.isCollapsed = true;
bm.mark = null;
}
}else{
bm.mark = rg.getBookmark();
}
}else{
console.warn("No idea how to store the current selection for this browser!");
}
return bm; // Object
};

this.moveToBookmark = function(/*Object*/ bookmark){
// summary:
// Moves current selection to a bookmark.
// bookmark:
// This should be a returned object from getBookmark().

// TODO: merge additional code from Editor._moveToBookmark into this method

var mark = bookmark.mark;
if(mark){
if(doc.getSelection){
// W3C Range API (FF, WebKit, Opera, etc)
var sel = win.getSelection();
if(sel && sel.removeAllRanges){
if(mark.pRange){
var n = mark.node;
n.selectionStart = mark.start;
n.selectionEnd = mark.end;
}else{
sel.removeAllRanges();
sel.addRange(mark);
}
}else{
console.warn("No idea how to restore selection for this browser!");
}
}else if(doc.selection && mark){
//'IE' way.
var rg;
if(mark.pRange){
rg = mark.range;
}else if(lang.isArray(mark)){
rg = doc.body.createControlRange();
//rg.addElement does not have call/apply method, so can not call it directly
//rg is not available in "range.addElement(item)", so can't use that either
array.forEach(mark, function(n){
rg.addElement(n);
});
}else{
rg = doc.body.createTextRange();
rg.moveToBookmark(mark);
}
rg.select();
}
}
};

this.isCollapsed = function(){
// summary:
// Returns true if there is no text selected
return this.getBookmark().isCollapsed;
};
};

// singleton on the main window
Expand Down

0 comments on commit 74302ff

Please sign in to comment.