06.08.2010, 06:11
|
|
|
|
Регистрация: 27.12.2008
Сообщений: 4,201
|
|
как можно делать замечания, если не хочеться вникать в этот код? (смайлик как у Octane) И при чем тут замена alert'а?
кстати, Octane, ты как-то абстрактно, имхо, подошел к вынесению функциональности. Т.е. я в первую очередь исхожу из того, как что-то будет использоваться. Selection.get() выглядит симпатичнее по сравнению с $Range.stringify($Selection.getRange()). Может, твой вариант чем-то лучше, но я пока не вижу чем. Он сложнее
и все-таки лучше отменять скрытие панели, а то оно может скрыть панель для нового выделения
Function.prototype.makeCancelable = function(){
var self = this;
var r = function(){
if( r.canceled )
return;
return self.apply(this, arguments);
};
r.cancel = function(){
this.canceled = true;
}
return r;
}
var QuotePanel = new Class({
_onMouseUp_body: function( e ){
...
this._panel
...
.animate(
{ ... },
{
'complete': function(){
this._hidePanelCancelable = this._hidePanel().of(this).makeCancelable();
setTimeout( this._hidePanelCancelable, 3000 );
}.of(this)
});
},
_onClick_body: function( e ){
...
if( this._hidePanelCancelable )
this._hidePanelCancelable.cancel();
this._hidePanel();
},
_hidePanel: function(){
this._panel.css('display', '');
}
});
|
|
06.08.2010, 06:47
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
Сообщение от x-yuri
|
кстати, Octane, ты как-то абстрактно, имхо, подошел к вынесению функциональности. Т.е. я в первую очередь исхожу из того, как что-то будет использоваться. Selection.get() выглядит симпатичнее по сравнению с $Range.stringify($Selection.getRange()). Может, твой вариант чем-то лучше, но я пока не вижу чем. Он сложнее
|
Зачем смешивать Selection с Range? Вообще я там поудалял методы, их было больше.
Selection используется редко из-за того, что динамически меняется, как NodeList, а еще в IE почти ничего не умеет, но иногда бывает нужно, поэтому для $Selection оставляем простой интерфейс:
$Selection.get();
$Selection.clear();
$Selection.getRange();
$Selection.selectRange(range);
А большинство работы выполняется с Range:
$Range.create();
$Range.isCollapsed(range);
$Range.stringify(range);
$Range.getRootContainer(range);
$Range.clone(range);
…
Создавать конструктор в этом конкретном случае неудобно, потому что полностью кросс-браузерный интерфейс написать не получится и постоянно обращаться к Range/TextRange-объекту через obj.range бессмысленно, удобнее:
var range = $Selection.getRange(),
text = $Range.stringify(range);
if ($Range.standardsCompliant) {
range…
} else {
range…
}
$Selection.selectRange(range);
|
|
06.08.2010, 09:12
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,124
|
|
....
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div id="link">Выделите ниже текст и кликни тут!!!</div>
<div id="link0">всякий разный текст</div>
<div id="link1">всякий разный текст</div>
<div id="link2">всякий разный текст</div>
<script language="JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript">
$('div').not('#link').mouseup(function () {
var txt=document.selection? document.selection.createRange().text:window.getSelection().toString();
$('#link').one("click",function () {alert(txt)})
});
</script>
</body>
</html>
|
|
06.08.2010, 09:49
|
|
Аспирант
|
|
Регистрация: 10.01.2010
Сообщений: 33
|
|
Сообщение от x-yuri
|
так совсем же просто
|
Спасибо, буду вникать.
Сообщение от x-yuri
|
вот только зачем ее автоматически убирать? Пользователь ее и так убрать сможет, кликнув на пустом месте.
|
Может человек выделил тест не для того чтобы вставить цитату, я для других целей (исключать такую возможность нельзя) - тогда в данном случае панель будет мозолить глаз и надо лишне где-то кликнуть, чтобы ее убрать. Пусть лучше исчезает.
Сообщение от x-yuri
|
Главное, чтобы она не перекрывала выделение
|
А что не так с перекрытием? Если фрагмент выделен большой, то панель в любом случае будет перекрывать выделение (всплывать над ним). Правда если внешний клик после этого будет на области выделения, то выходит чудно - в Fx и Chrome выделение снимается после события click, а в Opera - уже после события mousedown.
Сообщение от x-yuri
|
А вы еще говорите, что все должно быть максимально просто
|
Простота при тщательном изучении всегда усложняется
Приведенные примеры посмотрю попозже, убегаю сейчас.
|
|
06.08.2010, 20:53
|
|
|
|
Регистрация: 27.12.2008
Сообщений: 4,201
|
|
Сообщение от Cuprum
|
Может человек выделил тест не для того чтобы вставить цитату, я для других целей (исключать такую возможность нельзя) - тогда в данном случае панель будет мозолить глаз и надо лишне где-то кликнуть, чтобы ее убрать. Пусть лучше исчезает.
|
а если человек отвлекся/задумался, а оно уже исчезло. Опять выделять?
Octane, да, я c Range, Selection не особо много работал. Просто подумал, что $Selection.get могло бы сразу текст возвращать. Или как вариант можно было бы метод getText написать. Но в общем-то мне сложно судить...
рони, хватит one-liner'ами досить
|
|
06.08.2010, 23:37
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
Сообщение от x-yuri
|
Просто подумал, что $Selection.get могло бы сразу текст возвращать.
|
Насколько я знаю, из document.selection не вытащить выделенный текст, надо сначала TextRange создать. В остальных браузерах Selection хоть и преобразуется в строку, но по спецификации выделение может содержать несколько Range-объектов, поэтому:
var range = $Selection.getRange(), // получаем TextRange или *!*первый*/!* Range
text = $Range.stringify(range); // получаем выделенный текст
Хотя ничего страшного, наверное, не будет, если $Selection добавить метод getText:
$Selection = {
…
getText: function () {
return $Range.stringify(this.getRange());
}
};
Кому как нравится Просто не хотел, чтобы $Selection знал, как работать с Range/TextRange, но этого избежать не совсем получилось, метод для восстановления выделения, все же знает, что надо выполнить textrange.select();
|
|
10.08.2010, 00:09
|
|
Аспирант
|
|
Регистрация: 10.01.2010
Сообщений: 33
|
|
<!DOCTYPE html>
<html><head>
<title>Работа с выделениями</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type="text/css">
#past {height:30px; padding:5px; border:1px solid #000; text-align:center; line-height:30px; color:#000; font:12px Arial, sans-serif; background:#fff; cursor:pointer;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var qPanel = $('<div id="past" style="position:absolute; display:none;"><a href="" id="link">Вставить цитату в поле<a></div>');
var textarea = $('textarea');
var text;
$Selection = {
standardsCompliant: typeof getSelection != "undefined",
get: function () {
return this.standardsCompliant ? getSelection() : document.selection;
},
getRange: function () {
return this.get()[this.standardsCompliant ? "getRangeAt" : "createRange"](0);
}
};
$Range = {
standardsCompliant: $Selection.standardsCompliant,
stringify: function (range) {
return this.standardsCompliant ? range.toString() : range.text;
}
};
qPanel.click(function () {
textarea.val(textarea.val() + '<blockquote>' + text + '</blockquote>\r\n').focus();
$(this).hide();
return false;
});
qPanel.appendTo('body');
$('#paragraph').mouseup(function(e){
text = $Range.stringify($Selection.getRange());
var widthqPanel = qPanel.outerWidth();
if (text)
{
qPanel
.css({
top: e.pageY - 40,
left: e.pageX - widthqPanel/3,
display: 'block',
opacity: 0
})
.animate({
top: '-=' + 10 + 'px',
opacity: 1
}, 250);
}
e.stopPropagation();
});
$('body').click(function() {
if (!text) qPanel.hide();
});
});
</script>
</head><body>
<p id="paragraph">Proin gravida auctor velit vitae facilisis. Vestibulum ac lacus vitae nunc vulputate sodales a eget augue. Quisque ornare enim a nibh ullamcorper volutpat. Nulla imperdiet gravida pulvinar. Proin consequat nisi sit amet augue convallis nec viverra nisl mollis. Nulla in orci metus? Morbi interdum ligula vitae tortor elementum sodales. Curabitur ut ante vitae lectus egestas commodo congue non tortor. Cras mi massa, vulputate id rhoncus ac, facilisis sed leo! Mauris purus urna; ultrices non sodales sed, molestie in neque. Vestibulum ullamcorper orci ac dolor commodo ac aliquam nunc ultrices. Aliquam dapibus congue massa, eleifend vestibulum ligula viverra vitae.</p>
<form action="" name="">
<textarea cols="50" rows="10"></textarea>
</form>
</body></html>
Итак, воспользовался способом Octane (в данном случае он мне больше подходит), отказался от setTimeout (согласен с x-yuri) Возникли вопросы:
1. Не совсем понятно почему панель не скрывается после выделения если сделать клик не на параграфе на котором произошло выделение. (по логике в <body> входит не только #paragraph, но и, например, textarea)
2. Если выделение текста велик о, внешний клик (чтобы скрыть панель) вполне может быть на самой области выделения. Однако панель всплывает повторно. Только Opera ведет себя адекватно (а может и неадекватно, как посмотреть) скрывая панель по клику на самом выделении.
Прошу разъяснить
|
|
10.08.2010, 01:38
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Работа с выделениями</title>
<style type="text/css">
body {
color: #000;
position: relative;
}
.paragraph {
border: 1px solid #000;
}
.quote-popup-menu {
position: absolute;
padding: 10px;
background: #ffc;
border: 1px solid #000;
}
.quote-popup-menu .btn:hover {
color: #fff;
background: #33c;
cursor: pointer;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
<p class="paragraph">Proin gravida auctor velit vitae facilisis. Vestibulum ac lacus vitae nunc vulputate sodales a eget augue. Quisque ornare enim a nibh ullamcorper volutpat. Nulla imperdiet gravida pulvinar. Proin consequat nisi sit amet augue convallis nec viverra nisl mollis. Nulla in orci metus? Morbi interdum ligula vitae tortor elementum sodales. Curabitur ut ante vitae lectus egestas commodo congue non tortor. Cras mi massa, vulputate id rhoncus ac, facilisis sed leo! Mauris purus urna; ultrices non sodales sed, molestie in neque. Vestibulum ullamcorper orci ac dolor commodo ac aliquam nunc ultrices. Aliquam dapibus congue massa, eleifend vestibulum ligula viverra vitae.</p>
<p>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.</p>
<form action="">
<fieldset>
<textarea id="editor-text" name="editor-text" cols="50" rows="10"></textarea>
</fieldset>
</form>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
jQuery.bindContext = function (func, thisObj) {
return function (event) {
return func.call(thisObj, event);
};
};
var $Selection = {
standardsCompliant: typeof getSelection != "undefined",
get: function () {
return this.standardsCompliant ? getSelection() : document.selection;
},
getRange: function () {
return this.get()[this.standardsCompliant ? "getRangeAt" : "createRange"](0);
}
};
var $Range = {
standardsCompliant: $Selection.standardsCompliant,
stringify: function (range) {
return this.standardsCompliant ? range.toString() : range.text;
},
isCollapsed: function (range) {
return this.standardsCompliant ? range.collapsed : !range.htmlText.length;
},
getRootContainer: function (range) {
if (this.standardsCompliant) {
var root = range.commonAncestorContainer;
return root.nodeType == this.TEXT_NODE ? root.parentNode : root;
}
return range.parentElement();
}
};
var quote = function ($) {
return {
template: [
'<blockquote>',
'<p>',
'{QUOTE}',
'</p>',
'</blockquote>',
'\r\n'
].join(""),
templateRegExp: /{QUOTE}/,
menuTemplate: [
'<div class="quote-popup-menu hidden">',
'<span class="btn">Вставить цитату</span>',
'</div>'
].join(""),
root: "body",
text: ".paragraph",
menu: ".quote-popup-menu",
btn: ".btn",
textarea: "#editor-text",
done: false,
range: null,
$menu: null,
$btn: null,
$textarea: null,
init: function (cfg) {
if (this.done) {
return;
}
this.done = true;
$.extend(this, cfg)
this.$textarea = $(this.textarea);
this.createMenu();
this.initEvents();
},
initEvents: function () {
$(document).click($.bindContext(this.toggleMenu, this));
this.$btn.click($.bindContext(this.paste, this));
},
createMenu: function () {
this.$menu = $(this.menuTemplate);
this.$btn = this.$menu.find(this.btn);
this.$menu.appendTo(this.root);
},
paste: function (event) {
this.$textarea.val(this.$textarea.val() + this.template.replace(this.templateRegExp, $Range.stringify(this.range)));
},
saveSelection: function () {
this.range = $Selection.getRange();
},
needShowMenu: function () {
this.saveSelection();
var $root = $($Range.getRootContainer(this.range));
return this.$menu.is(":hidden") && !$Range.isCollapsed(this.range) && ($root.is(this.text) || $root.parent(this.text).length);
},
toggleMenu: function (event) {
if (this.needShowMenu()) {
this.showMenu(event.pageX, event.pageY)
} else {
this.hideMenu();
}
},
showMenu: function (x, y) {
this.$menu.css({
top: y + "px",
left: x + "px"
}).show();
},
hideMenu: function () {
this.$menu.hide();
}
};
}(jQuery);
$(function () {
quote.init();
});
</script>
</body>
</html>
Последний раз редактировалось Octane, 10.08.2010 в 02:22.
|
|
10.08.2010, 14:46
|
|
Аспирант
|
|
Регистрация: 10.01.2010
Сообщений: 33
|
|
Octane, Спасибо бо!
|
|
10.08.2010, 16:19
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
В Opera не генерируется событие click при выделении текста.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Работа с выделениями</title>
<style type="text/css">
body {
color: #000;
position: relative;
}
.paragraph {
border: 1px solid #000;
}
.quote-popup-menu {
position: absolute;
padding: 10px;
background: #ffc;
border: 1px solid #000;
}
.quote-popup-menu .btn:hover {
color: #fff;
background: #33c;
cursor: pointer;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
<p class="paragraph">Proin gravida auctor velit vitae facilisis. Vestibulum ac lacus vitae nunc vulputate sodales a eget augue. Quisque ornare enim a nibh ullamcorper volutpat. Nulla imperdiet gravida pulvinar. Proin consequat nisi sit amet augue convallis nec viverra nisl mollis. Nulla in orci metus? Morbi interdum ligula vitae tortor elementum sodales. Curabitur ut ante vitae lectus egestas commodo congue non tortor. Cras mi massa, vulputate id rhoncus ac, facilisis sed leo! Mauris purus urna; ultrices non sodales sed, molestie in neque. Vestibulum ullamcorper orci ac dolor commodo ac aliquam nunc ultrices. Aliquam dapibus congue massa, eleifend vestibulum ligula viverra vitae.</p>
<p>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.</p>
<form action="">
<fieldset>
<textarea id="editor-text" name="editor-text" cols="50" rows="10"></textarea>
</fieldset>
</form>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
var $Selection = {
standardsCompliant: typeof getSelection != "undefined",
get: function () {
return this.standardsCompliant ? getSelection() : document.selection;
},
getRange: function () {
return this.get()[this.standardsCompliant ? "getRangeAt" : "createRange"](0);
}
};
var $Range = {
standardsCompliant: $Selection.standardsCompliant,
stringify: function (range) {
return this.standardsCompliant ? range.toString() : range.text;
},
isCollapsed: function (range) {
return this.standardsCompliant ? range.collapsed : !range.htmlText.length;
},
getRootContainer: function (range) {
if (this.standardsCompliant) {
var root = range.commonAncestorContainer;
return root.nodeType == this.TEXT_NODE ? root.parentNode : root;
}
return range.parentElement();
}
};
var quote = function ($) {
return {
template: [
'<blockquote>',
'<p>',
'{QUOTE}',
'</p>',
'</blockquote>',
'\r\n'
].join(""),
templateRegExp: /{QUOTE}/,
menuTemplate: [
'<div class="quote-popup-menu hidden">',
'<span class="btn">Вставить цитату</span>',
'</div>'
].join(""),
root: "body",
text: ".paragraph",
btn: ".btn",
textarea: "#editor-text",
done: false,
range: null,
$menu: null,
$btn: null,
$textarea: null,
init: function (cfg) {
if (this.done) {
return;
}
this.done = true;
$.extend(this, cfg)
this.$textarea = $(this.textarea);
this.createMenu();
this.initEvents();
},
initEvents: function () {
var quote = this;
$(document).mousedown(function () {
quote.hideMenu();
}).mouseup(function (event) {
quote.showMenu(event);
});
this.$btn.bind("click mousedown mouseup", function (event) {
if (event.type == "click") {
quote.paste();
}
event.stopPropagation();
});
},
createMenu: function () {
this.$menu = $(this.menuTemplate);
this.$btn = this.$menu.find(this.btn);
this.$menu.appendTo(this.root);
},
paste: function (event) {
this.hideMenu();
this.$textarea.val(this.$textarea.val() + this.template.replace(this.templateRegExp, $Range.stringify(this.range)));
},
saveSelection: function () {
this.range = $Selection.getRange();
},
needShowMenu: function () {
this.saveSelection();
var $root = $($Range.getRootContainer(this.range));
return !$Range.isCollapsed(this.range) && ($root.is(this.text) || $root.parent(this.text).length);
},
showMenu: function (event) {
if (!this.needShowMenu()) {
return;
}
this.$menu.css({
top: event.pageY + "px",
left: event.pageX + "px"
}).show();
},
hideMenu: function () {
this.$menu.hide();
}
};
}(jQuery);
$(function () {
quote.init();
});
</script>
</body>
</html>
|
|
|
|