mirror of
https://github.com/moodle/moodle.git
synced 2025-04-25 02:16:06 +02:00
MDL-41241 Atto: Restrict searching for anchor tags to selection.
This commit is contained in:
parent
30509335dd
commit
8c11cd2e09
@ -97,6 +97,7 @@ M.atto_link = M.atto_link || {
|
||||
resolve_anchors : function() {
|
||||
// Find the first anchor tag in the selection.
|
||||
var selectednode = M.editor_atto.get_selection_parent_node(),
|
||||
anchornodes,
|
||||
anchornode,
|
||||
url;
|
||||
|
||||
@ -105,9 +106,10 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
|
||||
if (anchornode) {
|
||||
if (anchornodes.length > 0) {
|
||||
anchornode = anchornodes[0];
|
||||
M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode);
|
||||
url = anchornode.getAttribute('href');
|
||||
target = anchornode.getAttribute('target');
|
||||
@ -160,7 +162,7 @@ M.atto_link = M.atto_link || {
|
||||
var input,
|
||||
target,
|
||||
selectednode,
|
||||
anchornode,
|
||||
anchornodes,
|
||||
value;
|
||||
|
||||
e.preventDefault();
|
||||
@ -182,42 +184,47 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
if (anchornode) {
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
Y.Array.each(anchornodes, function(anchornode) {
|
||||
target = e.currentTarget.get('parentNode').one('input[type=checkbox]');
|
||||
if (target.get('checked')) {
|
||||
anchornode.setAttribute('target', '_blank');
|
||||
} else {
|
||||
anchornode.removeAttribute('target');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up and down for the nearest anchor tag.
|
||||
* Look up and down for the nearest anchor tags that are least partly contained in the selection.
|
||||
*
|
||||
* @method find_nearest_anchor
|
||||
* @method find_selected_anchors
|
||||
* @param Node node
|
||||
* @return Node|false
|
||||
*/
|
||||
find_nearest_anchor : function(node) {
|
||||
var tagname = node.get('tagName'), hit;
|
||||
find_selected_anchors : function(node) {
|
||||
var tagname = node.get('tagName'), hit, hits;
|
||||
// Direct hit.
|
||||
if (tagname && tagname.toLowerCase() === 'a') {
|
||||
return node;
|
||||
return [node];
|
||||
}
|
||||
// Search down.
|
||||
hit = node.one('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
// Search down but check that each node is part of the selection.
|
||||
hits = [];
|
||||
node.all('a').each(function(n) {
|
||||
if (!hit && M.editor_atto.selection_contains_node(n)) {
|
||||
hits.push(n);
|
||||
}
|
||||
});
|
||||
if (hits.length > 0) {
|
||||
return hits;
|
||||
}
|
||||
// Search up.
|
||||
hit = node.ancestor('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
return [hit];
|
||||
}
|
||||
return false;
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1 +1 @@
|
||||
YUI.add("moodle-atto_link-button",function(e,t){M.atto_link=M.atto_link||{dialogue:null,selection:null,display_chooser:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_link.selection=M.editor_atto.get_selection();if(M.atto_link.selection!==!1&&!M.atto_link.selection.collapsed){var n;M.atto_link.dialogue?n=M.atto_link.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_link.get_form_content(t)),n.set("headerContent",M.util.get_string("createlink","atto_link")),M.atto_link.resolve_anchors(),n.show(),M.atto_link.dialogue=n}},init:function(e){M.editor_atto.add_toolbar_button(e.elementid,"link",e.icon,e.group,this.display_chooser,this)},resolve_anchors:function(){var t=M.editor_atto.get_selection_parent_node(),n,r;if(!t)return;n=M.atto_link.find_nearest_anchor(e.one(t)),n&&(M.atto_link.selection=M.editor_atto.get_selection_from_node(n),r=n.getAttribute("href"),target=n.getAttribute("target"),r!==""&&e.one("#atto_link_urlentry").set("value",r),target==="_blank"?e.one("#atto_link_openinnewwindow").set("checked","checked"):e.one("#atto_link_openinnewwindow").set("checked",""))},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"link",M.atto_link.filepicker_callback)},filepicker_callback:function(e){M.atto_link.dialogue.hide(),e.url!==""&&(M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,e.url))},set_link:function(t){var n,r,i,s,o;t.preventDefault(),M.atto_link.dialogue.hide(),n=t.currentTarget.get("parentNode").one("input[type=url]"),o=n.get("value");if(o!==""){M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,o),i=M.editor_atto.get_selection_parent_node();if(!i)return;s=M.atto_link.find_nearest_anchor(e.one(i)),s&&(r=t.currentTarget.get("parentNode").one("input[type=checkbox]"),r.get("checked")?s.setAttribute("target","_blank"):s.removeAttribute("target"))}},find_nearest_anchor:function(e){var t=e.get("tagName"),n;return t&&t.toLowerCase()==="a"?e:(n=e.one("a"),n?n:(n=e.ancestor("a"),n?n:!1))},get_form_content:function(t){var n=e.Node.create('<form><label for="atto_link_urlentry">'+M.util.get_string("enterurl","atto_link")+"</label><br/>"+'<input type="url" value="" id="atto_link_urlentry" size="32"/>'+"<br/>"+'<label for="atto_link_openinnewwindow">'+M.util.get_string("openinnewwindow","atto_link")+"</label><br/>"+'<input type="checkbox" id="atto_link_openinnewwindow"/>'+"<br/>"+'<button id="openlinkbrowser" data-editor="'+e.Escape.html(t)+'">'+M.util.get_string("browserepositories","atto_link")+"</button>"+"<hr/>"+'<button id="atto_link_urlentrysubmit">'+M.util.get_string("createlink","atto_link")+"</button>"+"</form>"+"<hr/>"+M.util.get_string("accessibilityhint","atto_link"));return n.one("#atto_link_urlentrysubmit").on("click",M.atto_link.set_link),n.one("#openlinkbrowser").on("click",M.atto_link.open_filepicker),n}}},"@VERSION@",{requires:["node","escape"]});
|
||||
YUI.add("moodle-atto_link-button",function(e,t){M.atto_link=M.atto_link||{dialogue:null,selection:null,display_chooser:function(e,t){e.preventDefault(),M.editor_atto.is_active(t)||M.editor_atto.focus(t),M.atto_link.selection=M.editor_atto.get_selection();if(M.atto_link.selection!==!1&&!M.atto_link.selection.collapsed){var n;M.atto_link.dialogue?n=M.atto_link.dialogue:n=new M.core.dialogue({visible:!1,modal:!0,close:!0,draggable:!0}),n.render(),n.set("bodyContent",M.atto_link.get_form_content(t)),n.set("headerContent",M.util.get_string("createlink","atto_link")),M.atto_link.resolve_anchors(),n.show(),M.atto_link.dialogue=n}},init:function(e){M.editor_atto.add_toolbar_button(e.elementid,"link",e.icon,e.group,this.display_chooser,this)},resolve_anchors:function(){var t=M.editor_atto.get_selection_parent_node(),n,r,i;if(!t)return;n=M.atto_link.find_selected_anchors(e.one(t)),n.length>0&&(r=n[0],M.atto_link.selection=M.editor_atto.get_selection_from_node(r),i=r.getAttribute("href"),target=r.getAttribute("target"),i!==""&&e.one("#atto_link_urlentry").set("value",i),target==="_blank"?e.one("#atto_link_openinnewwindow").set("checked","checked"):e.one("#atto_link_openinnewwindow").set("checked",""))},open_filepicker:function(e){var t=this.getAttribute("data-editor");e.preventDefault(),M.editor_atto.show_filepicker(t,"link",M.atto_link.filepicker_callback)},filepicker_callback:function(e){M.atto_link.dialogue.hide(),e.url!==""&&(M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,e.url))},set_link:function(t){var n,r,i,s,o;t.preventDefault(),M.atto_link.dialogue.hide(),n=t.currentTarget.get("parentNode").one("input[type=url]"),o=n.get("value");if(o!==""){M.editor_atto.set_selection(M.atto_link.selection),document.execCommand("unlink",!1,null),document.execCommand("createLink",!1,o),i=M.editor_atto.get_selection_parent_node();if(!i)return;s=M.atto_link.find_selected_anchors(e.one(i)),e.Array.each(s,function(e){r=t.currentTarget.get("parentNode").one("input[type=checkbox]"),r.get("checked")?e.setAttribute("target","_blank"):e.removeAttribute("target")})}},find_selected_anchors:function(e){var t=e.get("tagName"),n,r;return t&&t.toLowerCase()==="a"?[e]:(r=[],e.all("a").each(function(e){!n&&M.editor_atto.selection_contains_node(e)&&r.push(e)}),r.length>0?r:(n=e.ancestor("a"),n?[n]:[]))},get_form_content:function(t){var n=e.Node.create('<form><label for="atto_link_urlentry">'+M.util.get_string("enterurl","atto_link")+"</label><br/>"+'<input type="url" value="" id="atto_link_urlentry" size="32"/>'+"<br/>"+'<label for="atto_link_openinnewwindow">'+M.util.get_string("openinnewwindow","atto_link")+"</label><br/>"+'<input type="checkbox" id="atto_link_openinnewwindow"/>'+"<br/>"+'<button id="openlinkbrowser" data-editor="'+e.Escape.html(t)+'">'+M.util.get_string("browserepositories","atto_link")+"</button>"+"<hr/>"+'<button id="atto_link_urlentrysubmit">'+M.util.get_string("createlink","atto_link")+"</button>"+"</form>"+"<hr/>"+M.util.get_string("accessibilityhint","atto_link"));return n.one("#atto_link_urlentrysubmit").on("click",M.atto_link.set_link),n.one("#openlinkbrowser").on("click",M.atto_link.open_filepicker),n}}},"@VERSION@",{requires:["node","escape"]});
|
||||
|
@ -97,6 +97,7 @@ M.atto_link = M.atto_link || {
|
||||
resolve_anchors : function() {
|
||||
// Find the first anchor tag in the selection.
|
||||
var selectednode = M.editor_atto.get_selection_parent_node(),
|
||||
anchornodes,
|
||||
anchornode,
|
||||
url;
|
||||
|
||||
@ -105,9 +106,10 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
|
||||
if (anchornode) {
|
||||
if (anchornodes.length > 0) {
|
||||
anchornode = anchornodes[0];
|
||||
M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode);
|
||||
url = anchornode.getAttribute('href');
|
||||
target = anchornode.getAttribute('target');
|
||||
@ -160,7 +162,7 @@ M.atto_link = M.atto_link || {
|
||||
var input,
|
||||
target,
|
||||
selectednode,
|
||||
anchornode,
|
||||
anchornodes,
|
||||
value;
|
||||
|
||||
e.preventDefault();
|
||||
@ -182,42 +184,47 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
if (anchornode) {
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
Y.Array.each(anchornodes, function(anchornode) {
|
||||
target = e.currentTarget.get('parentNode').one('input[type=checkbox]');
|
||||
if (target.get('checked')) {
|
||||
anchornode.setAttribute('target', '_blank');
|
||||
} else {
|
||||
anchornode.removeAttribute('target');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up and down for the nearest anchor tag.
|
||||
* Look up and down for the nearest anchor tags that are least partly contained in the selection.
|
||||
*
|
||||
* @method find_nearest_anchor
|
||||
* @method find_selected_anchors
|
||||
* @param Node node
|
||||
* @return Node|false
|
||||
*/
|
||||
find_nearest_anchor : function(node) {
|
||||
var tagname = node.get('tagName'), hit;
|
||||
find_selected_anchors : function(node) {
|
||||
var tagname = node.get('tagName'), hit, hits;
|
||||
// Direct hit.
|
||||
if (tagname && tagname.toLowerCase() === 'a') {
|
||||
return node;
|
||||
return [node];
|
||||
}
|
||||
// Search down.
|
||||
hit = node.one('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
// Search down but check that each node is part of the selection.
|
||||
hits = [];
|
||||
node.all('a').each(function(n) {
|
||||
if (!hit && M.editor_atto.selection_contains_node(n)) {
|
||||
hits.push(n);
|
||||
}
|
||||
});
|
||||
if (hits.length > 0) {
|
||||
return hits;
|
||||
}
|
||||
// Search up.
|
||||
hit = node.ancestor('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
return [hit];
|
||||
}
|
||||
return false;
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -95,6 +95,7 @@ M.atto_link = M.atto_link || {
|
||||
resolve_anchors : function() {
|
||||
// Find the first anchor tag in the selection.
|
||||
var selectednode = M.editor_atto.get_selection_parent_node(),
|
||||
anchornodes,
|
||||
anchornode,
|
||||
url;
|
||||
|
||||
@ -103,9 +104,10 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
|
||||
if (anchornode) {
|
||||
if (anchornodes.length > 0) {
|
||||
anchornode = anchornodes[0];
|
||||
M.atto_link.selection = M.editor_atto.get_selection_from_node(anchornode);
|
||||
url = anchornode.getAttribute('href');
|
||||
target = anchornode.getAttribute('target');
|
||||
@ -158,7 +160,7 @@ M.atto_link = M.atto_link || {
|
||||
var input,
|
||||
target,
|
||||
selectednode,
|
||||
anchornode,
|
||||
anchornodes,
|
||||
value;
|
||||
|
||||
e.preventDefault();
|
||||
@ -180,42 +182,47 @@ M.atto_link = M.atto_link || {
|
||||
return;
|
||||
}
|
||||
|
||||
anchornode = M.atto_link.find_nearest_anchor(Y.one(selectednode));
|
||||
if (anchornode) {
|
||||
anchornodes = M.atto_link.find_selected_anchors(Y.one(selectednode));
|
||||
Y.Array.each(anchornodes, function(anchornode) {
|
||||
target = e.currentTarget.get('parentNode').one('input[type=checkbox]');
|
||||
if (target.get('checked')) {
|
||||
anchornode.setAttribute('target', '_blank');
|
||||
} else {
|
||||
anchornode.removeAttribute('target');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Look up and down for the nearest anchor tag.
|
||||
* Look up and down for the nearest anchor tags that are least partly contained in the selection.
|
||||
*
|
||||
* @method find_nearest_anchor
|
||||
* @method find_selected_anchors
|
||||
* @param Node node
|
||||
* @return Node|false
|
||||
*/
|
||||
find_nearest_anchor : function(node) {
|
||||
var tagname = node.get('tagName'), hit;
|
||||
find_selected_anchors : function(node) {
|
||||
var tagname = node.get('tagName'), hit, hits;
|
||||
// Direct hit.
|
||||
if (tagname && tagname.toLowerCase() === 'a') {
|
||||
return node;
|
||||
return [node];
|
||||
}
|
||||
// Search down.
|
||||
hit = node.one('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
// Search down but check that each node is part of the selection.
|
||||
hits = [];
|
||||
node.all('a').each(function(n) {
|
||||
if (!hit && M.editor_atto.selection_contains_node(n)) {
|
||||
hits.push(n);
|
||||
}
|
||||
});
|
||||
if (hits.length > 0) {
|
||||
return hits;
|
||||
}
|
||||
// Search up.
|
||||
hit = node.ancestor('a');
|
||||
if (hit) {
|
||||
return hit;
|
||||
return [hit];
|
||||
}
|
||||
return false;
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -485,6 +485,27 @@ M.editor_atto = M.editor_atto || {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check that a YUI node it at least partly contained by the selection.
|
||||
* @param Range selection
|
||||
* @param Y.Node node
|
||||
* @return boolean
|
||||
*/
|
||||
selection_contains_node : function(node) {
|
||||
var range, sel;
|
||||
if (window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
|
||||
if (sel.containsNode) {
|
||||
return sel.containsNode(node.getDOMNode(), true);
|
||||
}
|
||||
}
|
||||
sel = document.selection.createRange();
|
||||
range = sel.duplicate();
|
||||
range.moveToElementText(node.getDOMNode());
|
||||
return sel.inRange(range);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the dom node representing the common anscestor of the selection nodes.
|
||||
* @return DOMNode
|
||||
|
File diff suppressed because one or more lines are too long
@ -485,6 +485,27 @@ M.editor_atto = M.editor_atto || {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check that a YUI node it at least partly contained by the selection.
|
||||
* @param Range selection
|
||||
* @param Y.Node node
|
||||
* @return boolean
|
||||
*/
|
||||
selection_contains_node : function(node) {
|
||||
var range, sel;
|
||||
if (window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
|
||||
if (sel.containsNode) {
|
||||
return sel.containsNode(node.getDOMNode(), true);
|
||||
}
|
||||
}
|
||||
sel = document.selection.createRange();
|
||||
range = sel.duplicate();
|
||||
range.moveToElementText(node.getDOMNode());
|
||||
return sel.inRange(range);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the dom node representing the common anscestor of the selection nodes.
|
||||
* @return DOMNode
|
||||
|
21
lib/editor/atto/yui/src/editor/js/editor.js
vendored
21
lib/editor/atto/yui/src/editor/js/editor.js
vendored
@ -483,6 +483,27 @@ M.editor_atto = M.editor_atto || {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check that a YUI node it at least partly contained by the selection.
|
||||
* @param Range selection
|
||||
* @param Y.Node node
|
||||
* @return boolean
|
||||
*/
|
||||
selection_contains_node : function(node) {
|
||||
var range, sel;
|
||||
if (window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
|
||||
if (sel.containsNode) {
|
||||
return sel.containsNode(node.getDOMNode(), true);
|
||||
}
|
||||
}
|
||||
sel = document.selection.createRange();
|
||||
range = sel.duplicate();
|
||||
range.moveToElementText(node.getDOMNode());
|
||||
return sel.inRange(range);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the dom node representing the common anscestor of the selection nodes.
|
||||
* @return DOMNode
|
||||
|
Loading…
x
Reference in New Issue
Block a user