Вставка гиперссылки в форматированный документ

Публикация № 1071558

Программирование - Практика программирования

ФорматированныйДокумент форматированный документ вставка ссылки ссылок

9
Да, форматированный документ это умеет и сам, но возможности можно расширить!

Поводом стала вот эта тема: //infostart.ru/public/74958/
Поскольку мне пришлось немного повозиться с форматированным документом в ходе текущих работ, накидал вариант решения проблемы.

Что позволяет сделать: позволяет превратить указанный (например, выделенный в форме) фрагмент форматированного документа в гиперссылку. При этом сохранив его форматирование. Сразу предупрежу: для случая параграфов и превращения картинок в гиперссылки это годится только как основа для дальнейшей доработки, а вот для форматированного текста это уже готовое решение. Если в обрабатываемом фрагменте уже есть ссылки, сносит их и ставит указанную.

Встроенный в платформу механизм даёт простенький диалог ввода ссылки, не имеет события его обработки/перехвата, и не имеет программного аналога. Значит, сделаем.

Вот полный текст механизма:

// вспомогательная к ВставитьСсылкуВВыделениеФорматированногоДокумента
&НаКлиентеНаСервереБезКонтекста
Процедура СоздатьЭлементПозиции(ФДокумент, рЗакладкаВставки, рДанныеЭлемента)
	рЭлемент=ФДокумент.Вставить(рЗакладкаВставки,рДанныеЭлемента.Текст,рДанныеЭлемента.Элемент.ТипЭлемента);
	ЗаполнитьЗначенияСвойств(рЭлемент,рДанныеЭлемента.Элемент);
	рЭлемент.НавигационнаяСсылка=?(рДанныеЭлемента.Свойство("Ссылка"),рДанныеЭлемента.Ссылка,"");
	рЭлемент.Текст=рДанныеЭлемента.Текст;
КонецПроцедуры	

&НаКлиентеНаСервереБезКонтекста
Функция ВставитьСсылкуВВыделениеФорматированногоДокумента(ФДокумент, рВыделенныйТекст, рСсылка)
Попытка
	рОбласть=ФДокумент.НайтиТекст(рВыделенныйТекст); // ищем везде
	Если рОбласть=Неопределено Тогда
		Возврат "Вставка ссылки невозможна, не определена область выделенного текста!";
	КонецЕсли;
	мЭлементов=ФДокумент.ПолучитьЭлементы(рОбласть.ЗакладкаНачала,рОбласть.ЗакладкаКонца);
	Если мЭлементов.Количество()=0 Тогда 
		Возврат "Вставка ссылки невозможна, не определён выделенный текст!";
	КонецЕсли;
	//
	// проверим, чтобы там уже не было ссылок
	Для каждого рЭлемент Из мЭлементов Цикл
		Если ТипЗнч(рЭлемент)<>Тип("ТекстФорматированногоДокумента") Тогда
			Возврат "Выделенный фрагмент захватывает не только текстовые фрагменты, вставка ссылки невозможна!";
		КонецЕсли;		
		Если Не ПустаяСтрока(рЭлемент.НавигационнаяСсылка) Тогда
			Возврат "В выделенном фрагменте уже фигурирует ссылка, необходимо сначала её убрать!";
		КонецЕсли;
	КонецЦикла;
	
	// конструируем последовательность новых элементов по их позициям согласно выделенной области
	рВесьТекст=ФДокумент.ПолучитьТекст();
	позиНачВыделения=СтрНайти(рВесьТекст,рВыделенныйТекст); // нумерация с 0!
	позиКонВыделения=позиНачВыделения+СтрДлина(рВыделенныйТекст)-1;
	//
	мНовыхЭлементов=Новый Массив;
	позиНачРаб=позиНачВыделения; // позиционирование элементов ФТ идёт встык, без +1
	позиНачЧтен=позиНачВыделения;
	рПозицияВставки=ФДокумент.ПолучитьПозициюПоЗакладке(мЭлементов[0].ЗакладкаНачала);
	//
	Для каждого рЭлемент Из мЭлементов Цикл
		позиНачЭлемента=ФДокумент.ПолучитьПозициюПоЗакладке(рЭлемент.ЗакладкаНачала);
		позиКонЭлемента=ФДокумент.ПолучитьПозициюПоЗакладке(рЭлемент.ЗакладкаКонца);
		//
		// на будущее, доработать, если кому понадобится, в т.ч. сопоставление ссылок картинкам
		рТипЭлемента=ТипЗнч(рЭлемент);
		//Если рТипЭлемента=Тип("ТекстФорматированногоДокумента") Тогда
			рСвойстваЭлемента=Новый Структура("ЦветТекста,ЦветФона,Шрифт,Текст");
		//ИначеЕсли рТипЭлемента=Тип("ПараграфФорматированногоДокумента") Тогда
		//	рСвойстваЭлемента=Новый Структура("ГоризонтальноеПоложение,МеждустрочныйИнтервал,Отступ,ТипПараграфа");
		//ИначеЕсли рТипЭлемента=Тип("КартинкаФорматированногоДокумента") Тогда
		//	рСвойстваЭлемента=Новый Структура("Ширина,Высота,Картинка");
		//КонецЕсли;
		//
		ЗаполнитьЗначенияСвойств(рСвойстваЭлемента,рЭлемент);
		рСвойстваЭлемента.Вставить("ТипЭлемента",рТипЭлемента);
		//
		Если позиНачЭлемента<позиНачРаб Тогда
			Если позиКонЭлемента>позиКонВыделения Тогда
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент",позиНачЭлемента,позиНачВыделения-1,рСвойстваЭлемента));
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент,Ссылка",позиНачВыделения,позиКонВыделения,рСвойстваЭлемента,рСсылка));
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент",позиКонВыделения,позиКонЭлемента,рСвойстваЭлемента));
				Прервать; // вся выделенная область целиком поместилась в один элемент
			Иначе
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент",позиНачЭлемента,позиНачЧтен-1,рСвойстваЭлемента));
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент,Ссылка",позиНачЧтен,позиКонЭлемента,рСвойстваЭлемента,рСсылка));
				позиНачРаб=позиКонЭлемента; // именно так, без +1
				позиНачЧтен=позиКонЭлемента+1;
			КонецЕсли;
		ИначеЕсли позиНачЭлемента=позиНачРаб Тогда
			Если позиКонЭлемента>позиКонВыделения Тогда
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент,Ссылка",позиНачЧтен,позиКонВыделения,рСвойстваЭлемента,рСсылка));
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент",позиКонВыделения+1,позиКонЭлемента,рСвойстваЭлемента));
				Прервать; // конечный хвостовой элемент, на котором закончилось выделение
			Иначе
				мНовыхЭлементов.Добавить(Новый Структура("Начало,Конец,Элемент,Ссылка",позиНачЧтен,позиКонЭлемента,рСвойстваЭлемента,рСсылка));
				позиНачРаб=позиКонЭлемента; // именно так, без +1
				позиНачЧтен=позиКонЭлемента+1;
			КонецЕсли;
		КонецЕсли;
		//
	КонецЦикла;
	
	// получаем тексты "кусочками"
	Для каждого знч Из мНовыхЭлементов Цикл
		знч.Вставить("Текст",Сред(рВесьТекст,знч.Начало,знч.Конец-знч.Начало+1));
	КонецЦикла;
	
	// удаляем все попавшие под обработку старые элементы
	Для й=-1*(мЭлементов.Количество()-1) По 0 Цикл
		рЭлемент=мЭлементов.Получить(-й);
		ФДокумент.Удалить(рЭлемент.ЗакладкаНачала,рЭлемент.ЗакладкаКонца);
	КонецЦикла;
	
	// создаём новые согласно указанным позициям и настройкам
	рЗакладкаВставки=ФДокумент.ПолучитьЗакладкуПоПозиции(рПозицияВставки);
	Для й=-1*(мНовыхЭлементов.Количество()-1) По 0 Цикл
		СоздатьЭлементПозиции(ФДокумент, рЗакладкаВставки, мНовыхЭлементов.Получить(-й));
	КонецЦикла;
	
	Возврат "";
Исключение
	Возврат "ВставитьСсылкуВВыделениеФорматированногоДокумента, общая ошибка: "+ОписаниеОшибки();
КонецПопытки;
КонецФункции

Вызывать это можно, например, так:

ВыдТекст=Элементы.ВашДокумент.ВыделенныйТекст;
ВашаСсылка="http://www.1c.ru";
Результат=ВставитьСсылкуВВыделениеФорматированногоДокумента(ВашДокумент,ВыдТекст,ВашаСсылка);
Если не ПустаяСтрока(Результат) Тогда
	ПоказатьПредупреждение(,рРезультат);
КонецЕсли;


Напомню, чтобы ФД не приписывал спереди e1c:// и прочую ересь, указывайте протокол, например, "http://", причём, если вы хотите использовать ФД в своих целях, туда можно напихать свои адресообразные данные, например какие-нибудь гуиды, главное, чтобы протокол был. Ну и, конечно, ловить щелчок лучше не в поле ФД, а закинув содержимое ФД в html-поле, и уж там по Click'у смотреть href.

Кстати ещё на заметку: форматирование ФД не совсем wisiwig применительно к html-полю, т.е. иногда прямо разительно отличается вид. Но писать xslt-преобразование и пытаться понять, что он каким образом показывает - это уже удовольствие отдельное.

9

См. также

Специальные предложения

Избранное Подписка Сортировка: Древо
В этой теме еще нет сообщений.
Оставьте свое сообщение