Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 06.08.2010, 06:11
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 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', ''); 
    } 
});
Ответить с цитированием
  #22 (permalink)  
Старый 06.08.2010, 06:47
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 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);
Ответить с цитированием
  #23 (permalink)  
Старый 06.08.2010, 09:12
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,075

....
<!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>
Ответить с цитированием
  #24 (permalink)  
Старый 06.08.2010, 09:49
Аватар для Cuprum
Аспирант
Отправить личное сообщение для Cuprum Посмотреть профиль Найти все сообщения от Cuprum
 
Регистрация: 10.01.2010
Сообщений: 33

Сообщение от x-yuri
так совсем же просто
Спасибо, буду вникать.
Сообщение от x-yuri
вот только зачем ее автоматически убирать? Пользователь ее и так убрать сможет, кликнув на пустом месте.
Может человек выделил тест не для того чтобы вставить цитату, я для других целей (исключать такую возможность нельзя) - тогда в данном случае панель будет мозолить глаз и надо лишне где-то кликнуть, чтобы ее убрать. Пусть лучше исчезает.
Сообщение от x-yuri
Главное, чтобы она не перекрывала выделение
А что не так с перекрытием? Если фрагмент выделен большой, то панель в любом случае будет перекрывать выделение (всплывать над ним). Правда если внешний клик после этого будет на области выделения, то выходит чудно - в Fx и Chrome выделение снимается после события click, а в Opera - уже после события mousedown.
Сообщение от x-yuri
А вы еще говорите, что все должно быть максимально просто
Простота при тщательном изучении всегда усложняется

Приведенные примеры посмотрю попозже, убегаю сейчас.
Ответить с цитированием
  #25 (permalink)  
Старый 06.08.2010, 20:53
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Сообщение от Cuprum
Может человек выделил тест не для того чтобы вставить цитату, я для других целей (исключать такую возможность нельзя) - тогда в данном случае панель будет мозолить глаз и надо лишне где-то кликнуть, чтобы ее убрать. Пусть лучше исчезает.
а если человек отвлекся/задумался, а оно уже исчезло. Опять выделять?

Octane, да, я c Range, Selection не особо много работал. Просто подумал, что $Selection.get могло бы сразу текст возвращать. Или как вариант можно было бы метод getText написать. Но в общем-то мне сложно судить...

рони, хватит one-liner'ами досить
Ответить с цитированием
  #26 (permalink)  
Старый 06.08.2010, 23:37
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 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();
Ответить с цитированием
  #27 (permalink)  
Старый 10.08.2010, 00:09
Аватар для Cuprum
Аспирант
Отправить личное сообщение для Cuprum Посмотреть профиль Найти все сообщения от Cuprum
 
Регистрация: 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 ведет себя адекватно (а может и неадекватно, как посмотреть) скрывая панель по клику на самом выделении.
Прошу разъяснить
Ответить с цитированием
  #28 (permalink)  
Старый 10.08.2010, 01:38
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 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.
Ответить с цитированием
  #29 (permalink)  
Старый 10.08.2010, 14:46
Аватар для Cuprum
Аспирант
Отправить личное сообщение для Cuprum Посмотреть профиль Найти все сообщения от Cuprum
 
Регистрация: 10.01.2010
Сообщений: 33

Octane, Спасибо бо!
Ответить с цитированием
  #30 (permalink)  
Старый 10.08.2010, 16:19
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 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>
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как "обмануть" обработчик события? itPiligrim Events/DOM/Window 0 13.05.2010 22:55
ссылки получали стиль "visited" только на время сессии alexandr_poskrobka Серверные языки и технологии 7 10.03.2010 08:48
как узнать имеется ли обработчик события HelpeR Events/DOM/Window 9 17.02.2010 18:20
Обработчик события: как делает jquery? Shasoft jQuery 35 22.04.2009 09:41
отправка файла через обработчик события submit starrich AJAX и COMET 2 13.08.2008 22:29