как можно делать замечания, если не хочеться вникать в этот код? (смайлик как у 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', ''); } }); |
Цитата:
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); |
....
<!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> |
Цитата:
Цитата:
Цитата:
Цитата:
Приведенные примеры посмотрю попозже, убегаю сейчас. |
Цитата:
Octane, да, я c Range, Selection не особо много работал. Просто подумал, что $Selection.get могло бы сразу текст возвращать. Или как вариант можно было бы метод getText написать. Но в общем-то мне сложно судить... рони, хватит one-liner'ами досить ;) |
Цитата:
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(); |
<!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 ведет себя адекватно (а может и неадекватно, как посмотреть) скрывая панель по клику на самом выделении. Прошу разъяснить :help: |
<!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, Спасибо бо!
|
В 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> |
Часовой пояс GMT +3, время: 06:46. |