Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 16.05.2010, 01:15
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Поиск текста на странице
Вытаскиваю плагин find из CKEditor, но там так много и так все к редактору привязано, что мне уже кажется легче было самому начать писать. Может зря время теряю и есть независимые решения? Пока ничего не нагуглил.
Ответить с цитированием
  #2 (permalink)  
Старый 16.05.2010, 14:21
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

в чем проблема перебрать все текстовые ноды на странице?
или ты не о том?
Ответить с цитированием
  #3 (permalink)  
Старый 16.05.2010, 14:36
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Слова могут быть разбиты на несколько текстовых узлов
CKEditor может находить даже фрагменты смежных абзацев. Хотелось бы такой же полноценный поиск сделать.
Ответить с цитированием
  #4 (permalink)  
Старый 16.05.2010, 17:30
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

это усложняет разработку, но не сильно, ИМХО
Ответить с цитированием
  #5 (permalink)  
Старый 17.05.2010, 11:18
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Бросил я затею с вытаскиванием плагина find из CKEditor, начал сам писать, вот какие страсти получаются:
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>

<span style="text-decoration: underline; color: #00f; cursor: pointer">Click to find and select «mpden-Sydney College in Virg»</span>

<p>It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of &quot;de Finibus Bonorum et Malorum&quot; (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance.</p>

<script type="text/javascript">
function $Finder(node) {
	this.node = node;
	this.findTextNodes();
	this.calcCharacterIntervals();
}

$Finder.prototype = {
	
	constructor: $Finder,
	
	node: null,
	textNodes: [],
	characterIntervals: [],
	resultIndex: -1,
	result: null,
	
	find: function (text) {
		var length = this.textNodes.length, i = 0;
		if (!length) {
			return false;
		}
		var startContainer, endContainer = this.textNodes[0], startOffset, endOffset, charOffset, str = endContainer.nodeValue, index;
		while (i in this.textNodes) {
			if (str.indexOf(text) == -1) {
				endContainer = this.textNodes[++i];
				if (!endContainer) {
					return false;
				}
				str += endContainer.nodeValue;
			} else {				
				
				startOffset = endContainer.nodeValue.indexOf(text);
				if (startOffset != -1) {
					startContainer = endContainer;
					endOffset = startOffset + text.length;
					charOffset = str.length - (startContainer.nodeValue.length - startOffset);
					break;
				} else {
					endOffset = this.calcEndOffset(endContainer.nodeValue, text);
					index = str.length - (endContainer.nodeValue.length - 1) - (text.length - endOffset);
					startContainer = this.textNodes[this.findTextNodeIndexByCharPos(index)];
					startOffset = this.calcStartOffset(startContainer.nodeValue, text);
					charOffset = index - (text.length - endOffset);
					break;
				}
				
				return false;
			}
		}
		
		return this.result = {
			charOffset: charOffset,
			startContainer: startContainer,
			startOffset: startOffset,
			endContainer: endContainer,
			endOffset: endOffset
		};
	},

	calcStartOffset: function (nodeValue, text) {
		while (text && nodeValue.lastIndexOf(text) != 0) {
			text = text.slice(0, -1);
		}
		return nodeValue.length - text.length;
	},
	
	calcEndOffset: function (nodeValue, text) {
		while (nodeValue.indexOf(text) == -1) {
			text = text.slice(1);
		}
		return text.length;
	},
	
	findTextNodeIndexByCharPos: function (position) {
		for (var i = 0; i <  this.characterIntervals.length; i++){
			if (position <= this.characterIntervals[i]) {
				return i;
			}
		}
	},

	calcCharacterIntervals: function () {
		var i, interval = 0;
		for (i = 0; i < this.textNodes.length; i++) {
			interval += this.textNodes[i].nodeValue.length;
			this.characterIntervals[i] = interval;
		}
	},

	findTextNodes: function () {

		var TEXT_NODE = 3, textNodes = [], j = 0;

		(function (element) {

			var node, nodes = element.childNodes, length = nodes.length, i = -1;
			while (++i < length) {
				node = nodes[i];
				if (node.nodeType == TEXT_NODE) {
					textNodes[j++] = node;
				} else if(node.hasChildNodes()) {
					arguments.callee(node);
				}
			}

		})(this.node);

		this.textNodes = textNodes;
	}
};


document.getElementsByTagName("span")[0].onclick = function () {

	var textBlock = document.getElementsByTagName("p")[0];
	var text = "mpden-Sydney College in Virg";
	var pos = new $Finder(textBlock).find(text);
	var range;

	if (pos) {
	
		if ("selection" in document) {
			range = document.selection.createRange();
			range.moveToElementText(textBlock);
			var range1 = range.duplicate();
			range.moveStart("character", pos.charOffset);
			range1.moveStart("character", pos.charOffset + text.length);
			range.setEndPoint("EndToStart", range1);
			range.select();
		} else {
			range = document.createRange();
			range.setStart(pos.startContainer, pos.startOffset);
			range.setEnd(pos.endContainer, pos.endOffset);
			var sel = getSelection();
			sel.removeAllRanges();
			sel.addRange(range);
		}
		
	}

};
</script>
</body>
</html>
Еще нужно сделать findNext. И выделение иногда неправильное

Последний раз редактировалось Octane, 17.05.2010 в 14:20.
Ответить с цитированием
  #6 (permalink)  
Старый 17.05.2010, 14:03
Аватар для subzey
Пионэр
Отправить личное сообщение для subzey Посмотреть профиль Найти все сообщения от subzey
 
Регистрация: 16.11.2009
Сообщений: 1,322

Octane,
если между «in» и «Virginia» будет два пробела (перенос строки, табуляция), отображаться будет так же, а поиск Ваш работать не будет.

Ну, и плюс, если у элемента display не inline, при отображении начальные и концевые пробельные символы обрезаются, Вы об этом помните?

Последний раз редактировалось subzey, 17.05.2010 в 14:07. Причина: очепятка
Ответить с цитированием
  #7 (permalink)  
Старый 17.05.2010, 14:16
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Угу. Придется писать какой-нибудь метод normalizeWhitespace, который будет выполняться перед поиском. Или есть другие идеи, как сохранить привязку текста к узлам без учета количества символов в nodeValue?

Последний раз редактировалось Octane, 17.05.2010 в 14:36.
Ответить с цитированием
Ответ


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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск на странице no_name jQuery 4 07.09.2010 13:26
Поиск текста на странице derwish Opera, Safari и др. 5 25.09.2009 13:13
Вставка текста с одной страницы в форму на другой странице Dima Общие вопросы Javascript 19 22.01.2009 17:35
Скрытие текста на странице за ссылкой Vlad44 Общие вопросы Javascript 2 13.01.2009 18:02
Поиск текста и замена krestiyaninov Общие вопросы Javascript 1 07.05.2008 13:30