- Копируем исходный код без нумерации строк
- Способ первый, очевидный.
- Второй способ, менее очевидный.
- Небольшая ремарка
- Способ третий, ненормальный.
- Демо
- На что стоит обратить внимание
- Как скопировать html код одного блока сайта и все стили его дочерних элементов?
- Как скопировать кусок html кода вместе со стилями?
Копируем исходный код без нумерации строк
Бывает при выводе информации требуется ее декорировать для лучшего восприятия, нередко оформление сопровождается в том числе и текстом. При выделении и копировании этой информации, оформление копировать не нужно, т.к. нужна только сама информация, и желательно в исходном виде. То есть при копировании часть выделенного текста не должна попадать в буфер обмена.
В моем случае это исходный код, который сопровождается нумерацией строк, так нагляднее и есть возможность сослаться на строку кода. Однако, если мы хотим скопировать часть кода, то он должен копироваться без номера строки.
Многие highlighter’ы этим грешат, при копировании кода копируют в том числе и номера строк. Выходят из ситуации по разному: либо используют хитрую верстку, при которой возможно несовпадении нумерации со строками (можно заметить на github например), или используют специальную кнопку, которая показывает в отдельном окне код без форматирования. Мне показались эти подходы неудовлетворительными, потому решил найти другое решение.
В данной заметке я опишу решение, к которому в итоге пришел. Решение, конечно, частное, но может кому то оказаться полезным в решении собственных задач.
Начнем с того, что кратко пройдемся по возможным вариантам решения.
Способ первый, очевидный.
Самый простой и очевидный способ, это сделать нумерованный список, где каждый элемент списка это отдельная строка. Основной плюс у этого подхода: все просто и не нужно задумываться даже о нумерации. Но при этом нельзя управлять форматом нумерации, нельзя позиционировать маркер (номер строки) и вообще как-то его декорировать. К тому же Internet Explorer и Firefox копируют текст вместе с маркером.
Собственно проблема с копированием перечеркивает возможность использования этого подхода.
Второй способ, менее очевидный.
Второе что приходит на ум — использовать генерируемый контент. Можно даже смирится с тем, что в старых IE это не будет работать (на этот случай можно, конечно, сделать fallback). Но беда в том, что Internet Explorer и Opera копируют весь видимый текст, в том числе и генерируемый контент.
Сложно сказать правы ли разработчики Internet Explorer/Opera или же правы разработчики webkit и Firefox относительно копирования генерируемого контента. Одно можно сказать с уверенностью, что метод не подходит.
Небольшая ремарка
В webkit и Firefox поддерживаются такое свойство CSS как user-select (со своими префиксами -webkit-user-select и -moz-user-select), с помощью которых можно запретить выделять текст. В Internet Explorer’е есть html атрибут unselectable. Однако все это лишь предотвращает начало процесса выделения, то есть если текст все же попал в область выделения, то он будет скопирован.
Более того, все блоки попавшие в область выделения, даже невидимые (display: none; или visibility: hidden;) так же в итоге попадают в буфер обмена.
Все это весьма печально, так как нет нормального способа определить — какой текст нужно копировать, а какой нет.
Способ третий, ненормальный.
Блуждая по интернетам в поисках решения, что-то навело на мысль использовать для вывода декоративного текста. Да-да, поле ввода для вывода текста. Необходимый текст прописываем в значение value, убираем padding, margin, border, background, задаем остальные стили — и никто не скажет что это input. Выделяем наш текст, копируем, вставляем в блокнот — все браузеры ведут себя одинаково, теги с содержимым не вставляются.
Остается побороть неприятный момент, поле ввода может получать фокус, и нельзя начать выделение текста с нумерации — выделяется текст поля. Но это уже, на самом деле, мелочи.
Чтобы нельзя было передать полю фокус мышкой в webkit и Firefox есть приятность — это CSS свойство pointer-events, которому можно задать значение none. Для Internet Explorer’а можно добавить для поля атрибут unselectable=«on». С Opera пока никак.
Чтобы нельзя было передать фокус с клавиатуры (и другими способами) добавляем для атрибуты readonly и tabindex=»-1″.
В Firefox и webkit все отлично, но в Internet Explorer нельзя начать выделение начиная с области нумерации, а в Opera по прежнему выделяется текст поля, а не исходный код. Чтобы решить проблему добавим для каждого дополнительный блок, который будет перекрывать . Этот блок должен иметь те же размеры, что и , а так же быть прозрачным. К сожалению (или к счастью), если если блок не имеет фона, то он «простреливается», то есть ведет себя как будто его нет, потому ему нужно добавить background. Можно добавить либо прозрачный gif файл, либо просто путь к несуществующему файлу, например background: url(#); (можно было бы использовать rgba(), но в IE это поддерживается только начиная с 9й версии).
В итоге имеем следующий html для блока с исходным кодом (переводы строк для наглядности, целевой html должен быть без них, иначе можем получить ненужные переводы строк при копировании):
.code < border: 1px solid #E0E0E0; padding: 1px; margin: 0 1ex; overflow: hidden; font-family: Consolas, monospace; font-size: 100%; color: black; line-height: 1.4em; white-space: pre; /* важно чтобы сохранялись переносы */ >.line < position: relative; /* для webkit, иначе при начале выделения с нумерации будет выделяться текст с самого начала блока */ zoom: 1; /* для IE6/7 */ white-space: pre; /* важно чтобы сохранялись переносы в IE7 */ >.even < background: #F8F8F8; >.odd < background: #F0F0F0; >.lineNumber < display: block; position: absolute; left: 0; padding: 0 .5ex; margin: 0; width: 6ex; line-height: 1.4em; height: 1.4em; background: none; border: none; font-family: Consolas, monospace; font-size: 100%; text-align: right; color: #666; -moz-user-select: none; /* задаем user-select для Firefox & webkit, чтобы блок не попадал в область выделения*/ -webkit-user-select: none; user-select: none; pointer-events: none; /* фактически это свойство делает ненужным блок .over, но пока оно поддерживается только в Firefox & webkit */ >.over < display: block; position: absolute; left: 0; width: 7ex; height: 1.4em; z-index: 1; background: url(.); /* для IE и Opera, иначе блок будет "простреливаться" (пропускать события мыши нижележащим блокам) */ >.lineContent < margin-left: 7ex; padding-left: 2ex; border-left: 2px solid #33BB66; display: block; white-space: pre-wrap; /* сохраняем форматирование, но оставляем возможность переносить по словам */ >.token-string < color: blue; >.token-comment < color: #008200; >.token-keyword
Демо
Демо на примере исходного кода atomjs (надеюсь TheShock не против 😉
Html-кода много, но он генерируется javascript’ом (свой highlighter).
Тестировалось под Chrome/Safari, Firefox 3.6, Opera 11, IE7-9 (переключением режимов в IE9 RC).
На что стоит обратить внимание
- Решение использует только возможности HTML и CSS, без спец хаков для браузеров.
- webkit впереди планеты всей, лучше всего работает в браузерах на его движке, можно сказать идеальный сценарий.
- Для Firefox пробелы в начале строк нужно заменять на иначе при копировании они будут вырезаться.
- В Opera текст начинает выделятся только если курсор мыши находится непосредственно над текстом. Начать выделение можно и с нумерации, но фактически текст начнет выделяться только когда курсор окажется над текстом.
- Важна вложенность свойства white-space. В данном случае ключевыми блоками является .code -> .line -> .lineContent, поэтому рабочим будет цепочка pre -> pre -> pre-wrap и, возможно, другие варианты (нужно проверять). От заданых значений зависит как браузер будет трактовать блоки при преобразовании в текст; при определенных значениях браузер может любой блочный элемент (display: block) выделять в отдельную строку текста, при этом могут получиться пустые строки между строками текста или же игнорировать переносы (например, IE7 может копировать весь текст одной строкой).
При вставке в редактор, который понимает text/html (например, MS Word), так же вставятся поля. Момент неприятный, но чаще редакторы не понимают text/html, так что переживать не стоит.
UPDATE
Найден workaroud чтобы при вставке в Word/Excel не вставлялись поля ввода. Чтобы этого добиться для нужно задать несуществующее значение атрибута type. В таком случае браузеры игнорируют атрибут и поле имеет тип по умолчанию, то есть type=«text», а при копировании (или вставке) не описаны сценарии как поступать с полями неизвестного типа — в итоге поле игнорируется. Так что код можно спокойно вставлять, например, в Word. При этом если код копируется из Chrome/Safari или из IE, то он будет вставлен с раскраской (webkit так же копирует и фон, а IE копирует без фона), что может в ряде случаев может оказаться полезным.
Как скопировать html код одного блока сайта и все стили его дочерних элементов?
Добрый день.
Подскажите пожалуйста действенный способ. Мне понравился 1 блок на американском сайте, я хочу его скопировать без долгой и рутинной работы.
В идеале все должно выглядеть так:
1 Открываем фаербаг
2 Копируем html целого блока
3 Копируем все стили всех вложенных элементов. НЕ только выбранного элемента, а еще всех что внутри.
4 Вставляем внутри своего проекта и все работает 🙂
Скопировать весь css — не подойдет! Нужны стили определенных элементов.
Изображения, шрифты и т.д. ненужно, только конструкцию) Спасибо.
Сложный 9 комментариев
ну так вы сами знаете вариант, чем помочь то? единственно, возможно JS еще понадобится, если есть активные элементы
Дмитрий, в хроме в стандартном и в скаченном фаербаге не удается получить «портянку» всех стилей по убывающей градации. Руками очень затруднительно тыкать на внутренний элемент и копировать стиль, потом также по кругу) Если я ошибаюсь, поправьте.
Paul_Morte: Ну так а что сложного ? качаете файл css с сайта, подключаете его, потом копируете html блок. Делов-то.
Ярослав Иванов: Это может сделать даже младенец. Мне нужна чистая ветвь кода для конкретных элементов. Без мусора.
Paul_Morte: Ну так и сделайте. В чем вопрос тогда ? Что за ветвь ? что за «конкретных файлов» ? Вы задаете простейший вопрос и вам дают простейший ответ, на который вы даете свой ответ: «Да ты че, я и сам знаю». Wtf ?
Paul_Morte: А, понял. Надо блок скопировать без лишних стилей. Не изобрели ученые такого инструмента. Все ручками делайте.
Не может быть) Должно быть решение, простое и лаконичное)
Наверняка есть чистильщики кода. Например взять целый css и потом убрать из него неиспользуемые стили. Я уже много искал, но ничего конкретного нет 🙁
Как скопировать кусок html кода вместе со стилями?
Частенько бывает такое.
Заходим мы такие на новенький сайт и находим интересный блок,
который можно было бы использовать в своих каких либо шаблона.
Давайте разберемся как без труда можно скопировать код блока с его стилями.
Для этого нам понадобится расширение для Chrome SnappySnippet (исходники).
1.Выбираем элемент для копирования
2.Выделяем элемент в инструментах разработчика
3.Переходим на вкладку SnappySnippet в инструментах разработчика
и жмем на кнопку «Create a snippet from inspected element»
4.Копируем получившуюся разметку и стили, после чего наслаждаемся результатом:
Слева исходник, справа скопированный элемент
#DIV_1 < color: rgb(34, 36, 38); height: 198px; overflow-wrap: break-word; text-align: left; width: 268px; word-wrap: break-word; perspective-origin: 150px 112.5px; transform-origin: 150px 112.5px; background: rgb(255, 248, 220) none repeat scroll 0% 0% / auto padding-box border-box; border: 1px solid rgb(224, 220, 191); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px 19.5px; outline: rgb(34, 36, 38) none 0px; padding: 15px 15px 10px; >/*#DIV_1*/ #DIV_2 < color: rgb(34, 36, 38); height: 190px; overflow-wrap: break-word; text-align: left; width: 268px; word-wrap: break-word; perspective-origin: 134px 95px; transform-origin: 134px 95px; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(34, 36, 38) none 0px; >/*#DIV_2*/ #DIV_3 < color: rgb(156, 152, 139); height: 14px; overflow-wrap: break-word; text-align: left; text-transform: uppercase; width: 268px; word-wrap: break-word; perspective-origin: 134px 7px; transform-origin: 134px 7px; border: 0px none rgb(156, 152, 139); font: normal normal bold normal 11px / 14.3px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(156, 152, 139) none 0px; >/*#DIV_3*/ #HR_4, #HR_20 < color: rgb(170, 170, 170); height: 1px; overflow-wrap: break-word; text-align: left; width: 268px; word-wrap: break-word; perspective-origin: 134px 0.5px; transform-origin: 134px 0.5px; background: rgba(0, 0, 0, 0.0980392) none repeat scroll 0% 0% / auto padding-box border-box; border: 0px none rgb(170, 170, 170); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 6.5px 0px 10px; outline: rgb(170, 170, 170) none 0px; >/*#HR_4, #HR_20*/ #DIV_5, #DIV_12 < color: rgb(34, 36, 38); height: 32px; overflow-wrap: break-word; text-align: left; width: 258px; word-wrap: break-word; perspective-origin: 134px 16px; transform-origin: 134px 16px; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px 8px; outline: rgb(34, 36, 38) none 0px; padding: 0px 5px; >/*#DIV_5, #DIV_12*/ #DIV_6, #DIV_13 < color: rgb(130, 130, 130); float: left; height: 20px; overflow-wrap: break-word; text-align: left; width: 30.9531px; word-wrap: break-word; perspective-origin: 15.4688px 10px; transform-origin: 15.4688px 10px; border: 0px none rgb(130, 130, 130); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(130, 130, 130) none 0px; >/*#DIV_6, #DIV_13*/ #A_7, #A_14 < color: rgb(0, 119, 204); cursor: pointer; display: block; height: 20px; overflow-wrap: break-word; text-align: left; text-decoration: none; width: 30.9531px; word-wrap: break-word; perspective-origin: 15.4688px 10.5px; transform-origin: 15.4688px 10.5px; border-top: 0px none rgb(0, 119, 204); border-right: 0px none rgb(0, 119, 204); border-bottom: 1px solid rgba(0, 0, 0, 0); border-left: 0px none rgb(0, 119, 204); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px -1px; outline: rgb(0, 119, 204) none 0px; >/*#A_7, #A_14*/ #DIV_8, #DIV_15 < background-position: 0px -4554px; color: rgb(0, 119, 204); cursor: pointer; display: inline-block; height: 16px; overflow-wrap: break-word; text-align: left; width: 16px; word-wrap: break-word; perspective-origin: 8px 8px; transform-origin: 8px 8px; background: rgba(0, 0, 0, 0) url("http://cdn.sstatic.net/img/favicons-sprite16.png?v=65046080049f82845023d54a3c2662c1") no-repeat scroll 0px -4554px / auto padding-box border-box; border: 0px none rgb(0, 119, 204); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(0, 119, 204) none 0px; >/*#DIV_8, #DIV_15*/ #DIV_9, #DIV_16 < color: rgb(34, 36, 38); float: left; height: 32px; overflow-wrap: break-word; text-align: left; width: 227.031px; word-wrap: break-word; perspective-origin: 113.516px 16px; transform-origin: 113.516px 16px; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(34, 36, 38) none 0px; >/*#DIV_9, #DIV_16*/ #A_10, #A_17 < color: rgb(0, 119, 204); cursor: pointer; display: block; height: 32px; overflow-wrap: break-word; text-align: left; text-decoration: none; width: 227.031px; word-wrap: break-word; perspective-origin: 113.516px 16.5px; transform-origin: 113.516px 16.5px; border-top: 0px none rgb(0, 119, 204); border-right: 0px none rgb(0, 119, 204); border-bottom: 1px solid rgba(0, 0, 0, 0); border-left: 0px none rgb(0, 119, 204); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px -1px; outline: rgb(0, 119, 204) none 0px; >/*#A_10, #A_17*/ #BR_11, #BR_18, #BR_26, #BR_32 < clear: both; color: rgb(34, 36, 38); overflow-wrap: break-word; text-align: left; word-wrap: break-word; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(34, 36, 38) none 0px; >/*#BR_11, #BR_18, #BR_26, #BR_32*/ #DIV_19 < color: rgb(156, 152, 139); height: 14px; overflow-wrap: break-word; text-align: left; text-transform: uppercase; width: 268px; word-wrap: break-word; perspective-origin: 134px 7px; transform-origin: 134px 7px; border: 0px none rgb(156, 152, 139); font: normal normal bold normal 11px / 14.3px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 15px 0px 0px; outline: rgb(156, 152, 139) none 0px; >/*#DIV_19*/ #DIV_21, #DIV_27 < color: rgb(34, 36, 38); height: 16px; overflow-wrap: break-word; text-align: left; width: 258px; word-wrap: break-word; perspective-origin: 134px 8px; transform-origin: 134px 8px; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px 8px; outline: rgb(34, 36, 38) none 0px; padding: 0px 5px; >/*#DIV_21, #DIV_27*/ #DIV_22, #DIV_28 < color: rgb(130, 130, 130); float: left; height: 16px; overflow-wrap: break-word; text-align: left; width: 30.9531px; word-wrap: break-word; perspective-origin: 15.4688px 8px; transform-origin: 15.4688px 8px; border: 0px none rgb(130, 130, 130); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(130, 130, 130) none 0px; >/*#DIV_22, #DIV_28*/ #SPAN_23, #SPAN_29 < color: rgb(130, 130, 130); overflow-wrap: break-word; text-align: left; word-wrap: break-word; border: 0px none rgb(130, 130, 130); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(130, 130, 130) none 0px; >/*#SPAN_23, #SPAN_29*/ #DIV_24, #DIV_30 < color: rgb(34, 36, 38); float: left; height: 16px; overflow-wrap: break-word; text-align: left; width: 227.031px; word-wrap: break-word; perspective-origin: 113.516px 8px; transform-origin: 113.516px 8px; border: 0px none rgb(34, 36, 38); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; outline: rgb(34, 36, 38) none 0px; >/*#DIV_24, #DIV_30*/ #A_25, #A_31 < color: rgb(0, 119, 204); cursor: pointer; display: block; height: 16px; overflow-wrap: break-word; text-align: left; text-decoration: none; width: 227.031px; word-wrap: break-word; perspective-origin: 113.516px 8.5px; transform-origin: 113.516px 8.5px; border-top: 0px none rgb(0, 119, 204); border-right: 0px none rgb(0, 119, 204); border-bottom: 1px solid rgba(0, 0, 0, 0); border-left: 0px none rgb(0, 119, 204); font: normal normal normal normal 13px / 16.9px Arial, 'Helvetica Neue', Helvetica, sans-serif; margin: 0px 0px -1px; outline: rgb(0, 119, 204) none 0px; >/*#A_25, #A_31*/
Важное на Мете
Жизненный цикл вопроса на Stack Overflow
Поможем коллегам сделать первый шаг к профессиональному росту
Обсуждаемое на Мете
4 Почему отклонённая правка?
6 Как реабилитироваться после бана?
Получившийся код можно сразу отправить на jsFiddle, CodePen или JS Bin.
Точность не 100%-я, но результат все равно хорош.
Удивительно, но IE обошел другие браузеры в этом плане.
Скопированные стили не содержат ничего лишнего.
Вот, как это делается в IE11+:
- Открываем инструменты разработчика
- Щелкаем правой кнопкой мыши на нужном элементе
- Выбираем пункт Скопировать элемент со стилями
- Вставляем в любой редактор.