Как изменить текст в span
Перейти к содержимому

Как изменить текст в span

  • автор:

HTML тег <span>

Тег <span>, также как и тег <div> является универсальным пустым контейнером, однако в отличие от блочного элемента <div>, строчный элемент\<span> определяет отдельные строки, символы или другие строчные элементы для их последующего оформления с помощью CSS стилей, либо для манипулирования ими при помощи скриптов. Тег <span> может быть использован, когда необходимо:

  • выделить какой-либо участок текста цветов, определить для него фон или фоновое изображение
  • изменить шрифт отдельных слов или фраз
  • применить скрипты к определенным участкам текста, например, подсветить синтаксис кода и т.д.

Чтобы не задавать каждый раз стиль внутри тега, можно выделить стиль во внешнюю таблицу стилей, а для идентификации тега использовать атрибуты class или id с именем селектора.

Тег <span> не оказывает никакое влияние на визуальное оформление элементов и не имеет семантического значения.

Синтаксис

Тег <span> — парный, его содержимое пишется между открывающим (<span>) и закрывающим (</span>) тегами.

Пример

Результат

spanexample1

В этом примере мы задали стиль непосредственно в теге.

Пример

Результат

spanexample2

В этом примере мы добавили к тегу атрибут class , и отдельно задали стили для содержимого тега.

Как изменить текст элемента span в JavaScript

Как использовать JavaScript для изменения «hereismytext» на «newtext»?

10 ответов

Для современных браузеров:

Использование innerHTML НЕ РЕКОМЕНДУЕТСЯ. Вместо этого вы должны создать textNode. Таким образом, вы «привязываете» свой текст, и вы, по крайней мере, в этом случае не уязвимы для атаки XSS.

Дополнительные сведения об этой уязвимости: Cross Site Scripting (XSS) — OWASP

Отредактировано ноябрь 4th 2017:

Изменена третья строка кода в соответствии с предложением @mumush: «используйте appendChild() вместо».
Кстати, согласно @Jimbo Jonny, я думаю, что все должно рассматриваться как пользовательский ввод, применяя принцип безопасности по слоям. Таким образом, вы не встретите никаких сюрпризов.

EDIT: Это было написано в 2014 году. Вероятно, вы больше не заботитесь о IE8 и можете забыть об использовании innerText . Просто используйте textContent и textContent с ним, ура.

Если вы подаете текст, и никакая часть текста не предоставляется пользователем (или другим источником, который вы не контролируете), то установка innerHTML может быть приемлемым:

Однако, как отмечают другие, если вы не являетесь источником какой-либо части текстовой строки, использование innerHTML может подвергать вас атакам, связанным с innerHTML контента, например, XSS, если вы не будете осторожны, чтобы сначала дезинформировать текст.

Если вы используете ввод от пользователя, вот один из способов сделать это безопасно, одновременно поддерживая совместимость между браузерами:

Firefox не поддерживает innerText и IE8 не поддерживает textContent поэтому вам нужно использовать оба textContent если вы хотите поддерживать совместимость между браузерами.

И если вы хотите избежать переплавов (вызванных innerText ), где это возможно:

How do I change the text of a span element using JavaScript?

How do I use JavaScript to change "hereismytext" to "newtext"?

simhumileco's user avatar

18 Answers 18

For modern browsers you should use:

While older browsers may not know textContent , it is not recommended to use innerHTML as it introduces an XSS vulnerability when the new text is user input (see other answers below for a more detailed discussion):

Darshan Rivka Whittle's user avatar

Using innerHTML is SO NOT RECOMMENDED. Instead, you should create a textNode. This way, you are «binding» your text and you are not, at least in this case, vulnerable to an XSS attack.

For more information about this vulnerability: Cross Site Scripting (XSS) — OWASP

Edited nov 4th 2017:

Modified third line of code according to @mumush suggestion: «use appendChild(); instead».
Btw, according to @Jimbo Jonny I think everything should be treated as user input by applying Security by layers principle. That way you won’t encounter any surprises.

EDIT: This was written in 2014. A lot has changed. You probably don’t care about IE8 anymore. And Firefox now supports innerText .

If you are the one supplying the text and no part of the text is supplied by the user (or some other source that you don’t control), then setting innerHTML might be acceptable:

However, as others note, if you are not the source for any part of the text string, using innerHTML can subject you to content injection attacks like XSS if you’re not careful to properly sanitize the text first.

If you are using input from the user, here is one way to do it securely while also maintaining cross-browser compatibility:

Firefox doesn’t support innerText and IE8 doesn’t support textContent so you need to use both if you want to maintain cross-browser compatibility.

Стилизация текста с помощью Span

Используйте span, чтобы стилизовать текст в Android! Вы сможете изменить цвет нескольких символов, сделать их кликабельными, изменить размер текста или даже нарисовать свои маркеры для списка с помощью span. Span-ы могут изменить свойства TextPaint , могут рисовать на Canvas , или даже изменить текстовый лайаут и изменить высоту строки текста. Span-ы это объекты разметки, которые могут быть прикреплены или откреплены от текста; они могут быть применены к целому параграфу или части текста.

Давайте рассмотрим, как использовать span, что предоставляют span-ы “из коробки”, как проще создать свой span и наконец как их тестировать:

Стилизация текста в Android

Android предлагает несколько способов стилизации текста:

  • Простые стили (Single style) — когда стиль применяется ко всему тексту отображаемому TextView
  • Мульти стили (Multi style) — когда несколько стилей могут быть применены к тексту, параграфу

Простой стиль (Single style) подразумевает стилизацию всего текста в TextView, используя XML атрибуты или стили и темы (которые применяются к TextView). Этот подход — простой, но не позволяет применить стилизацию к части текста. Например, при применении textStyle=”bold” , текст целиком будет жирным; вы не можете сделать жирным какой-то символ в тексте.

Multi style подразумевает добавление нескольких стилей к одному и тому же тексту. Например, сделать одно слово со стилем italic а другое bold. Мульти стили могут быть реализованы через использование HTML тегов, span-ов или управлением отрисовки текста на холсте Canvas.

HTML теги это простое решение для решения простых задач, таких как: сделать текст жирным, с наклоном, или даже вывести маркеры для списка. Чтобы стилизовать текст, включающий HTML теги, вызовите метод Html.fromHtml . Под капотом — HTML форматирование конвертируется в span-ы. Пожалуйста обратите внимание, что класс Html — не поддерживает все HTML теги и css стили, например чтобы изменить цвет маркеров списка.

Что касается рисования текста на canvas, то это следует использовать, если нужно сделать что-то, что не поддерживается платформой, например рисование текста по кривой.

Span-ы позволяют вам применить одновременно несколько стилей с большой степенью кастомизации. Например, вы можете определить параграфы текста с маркерами, применив BulletSpan . Вы можете, например, изменить расстояние между маркером и текстом, также изменить цвет маркера. Начиная с Android P, вы можете даже установить радиус маркера списка. Вы также можете создать свою реализацию для span. Ознакомьтесь с секцией “Создание кастомных span-ов” ниже, чтобы узнать как это сделать.

Вы можете комбинировать простые стили и мульти стили. Вы можете рассматривать стили, которые вы применяете к TextView как “базовые” стили. Стилизация текста через span-ы применяется “поверх” базового стиля и переписывает базовый стиль. Например, когда меняет цвет текста TextView через атрибут textColor=”@color.blue” и применяем ForegroundColorSpan(Color.PINK) для первых 4 символов текста, то первые 4 символа будут розовыми (потому что span переопределил основной стиль), а цвет остальных символов будет определятся цветом, заданным через атрибут.

Применение Span-ов

При использовании span-ов, вы будете работать с одним из следующих классов: SpannedString , SpannableString or SpannableStringBuilder . Разница между ними заключается в том, что текст или объекты разметки являются изменяемыми или неизменяемыми во внутренней структуре, которую они используют: SpannedString и SpannableString используют линейные массивы для хранения добавляемых span-ов, а SpannableStringBuilder использует дерево отрезков.

Как решить какой класс нужно использовать:

  • Если у вас есть неизменяемый текст, к которому вы хотите применить стили ? -> SpannedString
  • Если ваш стилизованный текст будет меняться -> SpannableStringBuilder
  • Установить небольшое кол-во span-ов (<

Например, если вы работаете с текстом, который не изменяется, но к которому вы хотите прицепить span-ы, вы должны использовать SpannableString .

Все эти классы имплементятся от интерфейса Spanned , но классы которые имеют объекты разметки ( SpannableString и SpannableStringBuilder ) наследуются от Spannable .

Spanned -> неизменный текст и неизменная разметка

Spannable (расширяет Spanned )-> неизменный текст и изменяемая разметка

Примените span через вызов setSpan(Object what, int start, int end, int flags) на Spannable объекте. Здесь what — это объект, который будет применен к тексту с позиции start и по позицию end текста. Флаг указывает, должен ли диапазон расширяться, чтобы включить текст, вставленный в их начальную или конечную точку, или нет. Независимо от того, какой флаг установлен, всякий раз, когда текст вставлен в положение больше начальной точки и меньше конечной точки, диапазон автоматически расширяется.

Например, настройка ForegroundColorSpan может быть такой:

Тк span был настроен используя флаг SPAN_EXCLUSIVE_INCLUSIVE , то когда вставляется текст в конец span-а, span будет расширен, чтобы включить новый текст (те стиль будет применен к добавляемому тексту):

Если span настроен с флагом Spannable.SPAN_EXCLUSIVE_EXCLUSIVE , то вставляемый в конец текст не будет изменен (те стиль не будет применен к добавляемому тексту).

Множество span-ов может быть составлено и присоединено к одному и тому же текстовому сегменту. Например, текст, выделенный как полужирным, так и красным, можно построить таким образом:

Framework spans

Android framework определяет несколько интерфейсов и абстрактных классов, которые проверяются во время измерения и во время рендеринга. У этих классов есть методы, которые позволяют span-у получить доступ к объектам как например TextPaint или Canvas .

Android framework предлагает более 20 классов и интерфейсов в пакете android.text.stylepackage для работы со span-ами, производных от главных интерфейсов и абстрактных классов. Мы сгруппировали span-ы на группы:

  • Исходя из того, изменяет ли span только внешний вид, а также текстовую метрику / макет
  • Исходя из того, влияют ли они на текст по символам или на уровне абзаца

Span-ы которые влияют на представление и метрику текста

Первая категория влияет на представление текста на уровне симовлов: цвет текста или фона, подчеркивание, зачеркивание, и т.д. — заставляет перерисовать текст без его перекомпоновки (пересчета размера view, которое отображает текст). Эти span-ы имплементят UpdateAppearance и расширяют CharacterStyle . CharacterStyle субклассы определяют как рисовать текст посредством предоставления доступа к TextPaint .

Span-ы влияющие на метрику — изменяют размеры лайаута и требуют повторного рендеринга компонентов.

Например, span который влияет на размер текста требует изменение размеров лайаута и перекомпоновки компонентов. Эти span-ы обычно расширяют MetricAffectingSpan класс. Этот абстрактый класс позволяет субклассам определить как span влияет на измерение текста (это делает через предоставление доступа к TextPaint ). Поскольку MetricAffectingSpan расширяет CharacterSpan , подклассы влияют на внешний вид текст на уровне символов.

У вас может быть соблазн всегда пересоздавать CharSequence с текстом и разметкой вызывая TextView.setText(CharSequence) . Но это всегда требует повторного пересчета размеров лайаута и создания дополнительных объектов (что может сказать на отзывчивости ui). Чтобы избежать этого установите текст через вызов TextView.setText(Spannable, BufferType.SPANNABLE) и затем, когда вам будет необходимо изменить span-ы, извлеките Spannable объект из TextView через приведение TextView.getText() к Spannable . Мы заглянем что происходит под капотом TextView.setText в следующей статье.

Для примера, рассмотрим Spannable объект установленный и извлеченный следующим образом:

Теперь, когда мы определили spannableText , мы можем не вызывать textView.setText повторно, потому что мы можем изменять CharSequence объект напрямую через объект spannableText.

Вот как мы можем установить изменить внешний вид, применив span:

Вариант 1: Изменение внешнего вида текста, без изменеия размеров TextView

В приведенном выше примере будет вызван TextView.onDraw , но не TextView.onLayout .

Вариант 2: Изменение размеров текста

Тк RelativeSizeSpan изменяет размер текста, то высота и ширина view может измениться , TextView вызовет методы onMeasure и onLayout .

Character vs paragraph affecting spans

Span могут влиять на текст как на символьном уровне, изменяя например цвет фона, стиль, размер символов, так и на уровне параграфа, например изменяя выравнивание текста в параграфе целиком. В зависимости от того, как нужно стилизовать текст span-ы расширяют CharacterStyle или имплиментят ParagraphStyle . Span-ы которые расширяют ParagraphStyle должны быть прикреплены от первого символа до последнего символа параграфа, иначе вы не стилизация текста не будет отображена. В Android параграфы определяются с новой строки с помощью символа перевода каретки ( \n ) .

Например, CharacterStyle span BackgroundColorSpan может быть прикреплен к любому символу в тексте. Ниже мы прикрепили его начиная с 5-го до 8-го символа:

ParagraphStyle span, QuoteSpan , может быть прикреплен только к началу параграфа. Например, “Text is\nspantastic” включает символ новой строки на 8м символе текста, поэтому мы можем прикрепить QuoteSpan только начиная с позиции 0 или 8, иначе текст не будет стилизован.

Создание кастомных span-ов

Когда вы реализовываете свой span, вы должны решить на каком уровне вы хотите стилизовать текст: на символьном уровне или на уровне параграфа, должны ли стилизация приводить к перекомпоновке view или только перерисовывать текст, без изменения размера view. Но прежде написания своего кода, проверьте существует ли требуемая функциональность в классах фреймворка.

  • Изменение стилизации текста на символьном уровне ->CharacterStyle
  • Изменение стилизации текста на уровне параграфа ->ParagraphStyle
  • Стилизация текста без изменения размера TextView ->UpdateAppearance
  • Стилизация текста c изменением размера TextView ->UpdateLayout

Предположим, что нам нужно реализовать span, который увеличивает размер текста в соотвествии с пропорциями TextView так, как делает это RelativeSizeSpan , и устанавливает цвет текста, как это делает ForegroundColorSpan . Чтобы сделать это вы можете расширить RelativeSizeSpan переопределив метод updateDrawState в котором установить цвет текста используя объект TextPaint .

Замечание: точно такой же эффект может быть достигнут если применить оба существующих класса RelativeSizeSpan и ForegroundColorSpan к тексту.

Тестирование кастомных span-ов

Тестирование span-ов означает проверку того, что действительно были внесены ожидаемые изменения в TextPaint или что на Canvas были отрисованы элементы. Например, рассмотрим пользовательскую реализацию span-a, который добавляет точку (bullet point) абзаца с указанным размером и цветом, а также отступ слева от точки (bullet point). Вы можете посмотреть реализацию здесь android-text sample. Чтобы протестировать этот класс, реализуйте AndroidJUnit , чтобы проверить:

  • Отрисовку круга определенного размера
  • Ничего не рисуется, если span не прикреплен к тексту
  • Установлен правильный отступ, ширина которого передается параметров конструктора

Ниже пример кода для тестирования.

Проверьте полный код теста здесь — BulletPointSpanTest .

Тестирование использования span-ов

Spanned интерфейс позволяет настраивать и извлекать span-ы из текста. Проверьте что span-ы корректно добавлены в нужное место через реализацию Android JUnit теста. В android-text sample мы конвертируем теги разметки точки (bullet point) в маркеры (которые будут отрисованы в TextView). Это можно сделать прицепив BulletPointSpans к тексту, в нужную позицию. Ниже код как это можно протестировать:

Посмотрите MarkdownBuilderTest для других примеров тестов.

Замечание: если вы хотите выполнить итерации по span-ам вне тестов —для большей производительности используйте Spanned#nextSpanTransition вместо Spanned#getSpans .

Span-ы — это мощная концепция, встроенная в функциональность рендеринга текста. Она позволяет стилизовать текст по средством доступа к компонентам TextPaint и Canvas. В Android P мы добавили обширную документацию по framework spans , так что перед тем как реализовывать свои span-ы, проверьте какие span-ы доступны.

В будущих статьях мы расскажем больше о работе span-ов “под капотом” и как их эффективно использовать. Оставайтесь с нами!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *