Опубликован: 07.11.2006 | Уровень: специалист | Доступ: платный
Лекция 3:

Форматирование текста

Применение данного подхода

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

Для начала нам понадобится функция для просмотра текста и возвращения позиций указанной нами строки. Так как эта функция будет работать со строками, нам нужно создать ее в виде метода объекта строкового типа. Функция findInstances выглядит так.

myString.findInstances (str);

Чтобы найти вхождение строки внутри другой строки, можно использовать indexOf. Сама по себе indexOf выглядит так:

var pos = myString.indexOf (str);

Функция indexOf возвращает номер-индекс первого вхождения str. Теперь нам нужно найти каждое вхождение str, и для этого можно применить другой способ использования indexOf, где указывается номер-индекс, с которого следует начать просмотр:

var pos = myString.indexOf (str, startIndex);

В этой функции должен быть цикл. По нахождении первого вхождения строки, она будет брать номер-индекс первого найденного вхождения str и использовать его в качестве точки начала следующей операции indexOf. Цикл будет повторяться до тех пор, пока не будут найдены все вхождения str, после чего indexOf возвратит значение -1. Цикл закончит свою работу и возвратит массив найденных значений.

String.prototype.findInstances = function(str) {
  var foundAt = [];
  var nextFound = 0;
  // while there are still instances of the string
  while (nextFound != -1) {
    nextFound = this.indexOf(smallStr, nextFound);
    if (nextFound != -1) {
      foundAt.push({begin:nextFound, end:nextFound+str.length});
      nextFound++;
    }
  }
  // return the array of beginning and end values
  return foundAt;
};

Разберем каждую строку этого кода. Сначала мы устанавливаем currIndex на ноль, т.е. на ту позицию, с которой начинается поиск. Далее создаем массив foundAt для добавления в него всех значений, которые нужно возвратить. Затем объявляется переменная nextFound для записи возвращаемого значения. При этом используется слово var для указания того, что переменная должна существовать только во время выполнения функции.

Для настройки цикла используется выражение while(nextFound!=-1), так как нам нужно, чтобы цикл завершал работу, когда больше не может быть найдено ни одно вхождение строки. Первая строка цикла дает нам номер-индекс следующего вхождения строки поиска в более объемной строке, после точки, указываемой currIndex.

nextFound = this.indexOf (str, currIndex);

Если значением nextFound не является -1, это означает, что найдено вхождение строки, и выражения, включенные в условие, будут выполнены. Будет добавлено следующее вхождение строки и увеличено значение nextFound, после чего продолжится выполнение следующего кода:

if (nextFound != -1) {
  foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
  nextFound++;
}

Мы интерпретируем это как объект, содержащий начальное и конечное значения, поэтому можно указать начальную и конечную точки для фрагмента текста.

foundAt.push ({begin:nextFound, end:nextFound+str.length});

Если больше не найдено вхождений строки поиска, nextFound принимает значение -1 и цикл while прекращает свою работу. После этого возвращаются все значения, которые были найдены, и выполнение функции завершается.

return foundAt;

Чтобы опробовать этот метод, создадим новый файл. Добавьте определенный нами метод над и под следующим текстом.

text_str="The eidophor system is a projection television system, 
i.e. it enables enlarged Кtelevision pictures 
to be projected on to a screen. 
An ordinary television picture derives its 
brightness from the fluorescence of 
   a screen bombarded by electrons; 
with the eidophor system, on the other hand, 
a very powerful source of light is controlled by
the television signal 
   picked up by the receiver."
vals=text_str.findInstances("television")

Выполнив код и просмотрев переменные, вы увидите, что vals содержит массив с четырьмя объектами - по одному для каждого вхождения слова "television", указанного в строке выше. Однако чтобы этот метод работал при любых обстоятельствах, необходимо внести в него некоторые изменения.

Преобразование строк

  1. С нашими текущими настройками, если регистр (верхний/нижний) строки поиска не соответствует вхождению в тексте, оно не будет интерпретироваться как найденная строка. Чтобы избежать этого, преобразуем обе строки перед использованием в нижний регистр. Ниже приведены дополнения в коде.
    String.prototype.findInstances = function(str) {
      var foundAt = [] ;
      var nextFound = 0;
    //   change both strings to lower case
      var largeStr = this.toLowerCase();
      var smallStr = str.toLowerCase();
      while (nextFound!=-1) {
        nextFound = largeStr.indexOf(smallStr, nextFound);
        if (nextFound != -1) {
          foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
          nextFound++;
        }
      }
    return foundAt;
    };

    Теперь код будет работать при поиске любой строки внутри любой более объемной строки.

  2. Открываем switchTextFormat1.fla и добавляем на рабочее место текстовое поле и три функции: nooTextFormat, nooTextFormatControl и cleanNooTextFormat. После этого добавляем метод findInstances. Теперь создаем функции для поиска вхождений строки и выделяем их. Сначала нам понадобится функция для инициализации, которая будет вызывать findInstances и записывать результат в массив. После этого она будет вызывать функцию doNext.
    function nooFindAndReplace(textObj, str) {
      this.indices = textObj.text.findInstances(str);
      this.doNext();
    }

    doNext будет использовать метод shift массива для извлечения первой пары индексов из массива indices и затем передавать их в nooTextFormat. Мы передаем doNext в виде функции с обратной связью таким образом, что когда формат одного слова изменится, doNext будет вызвана снова, и мы перейдем к следующему слову.

    function doNext() {
    // if there is another string
      if (indices.length>0) {
        var nexta = this.indices.shift();
        this.tf_txt.nooTextFormat
         (myForm, nexta.begin, nexta.end, 1, 30, this, "doNext");
      }
    }
  3. Наконец, мы определяем строку, в которой будет осуществляться поиск, и затем вызываем функцию.
    this.tf_txt.text = "The eidophor system is 
    a projection television system, 
    i.e. it enables enlarged television pictures 
    to be projected on to a screen. 
    An ordinary television picture derives 
    its brightness from the fluorescence of 
       a screen bombarded by electrons; 
    with the eidophor system, on the other hand, 
    a very powerful source of light is controlled 
    by the television signal 
       picked up by the receiver. " ;
    myForm = this.tf_txt.getTextFormat() ;
    myForm.color = 0x000000;
    myForm.size = 9;
    myForm. bold = true;
    // trigger find and replace
    nooFindAndReplace(this.tf_txt, "television", myForm);

    В окончательном виде весь код будет выглядеть так.

    В окончательном виде весь код будет выглядеть так.
    TextField.prototype.nooTextFormat = function(tForm, begin, end, speed, interval, obja, Кfunc) {
      this.begin = this.current=begin;
      this.end = end+1;
      this.speed = speed;
      this.end = end;
      this.obja = obja;
      this.func = func;
      this.nooTform = tForm;
      this.myNooText = setInterval(this, "nooTextFormatControl", interval);
    };
    TextField.prototype.nooTextFormatControl = function() {
      this.current += this.speed;
      if (this.current>this.end) {
        this.setTextFormat(this.begin, this.end, this.nooTform);
        this.cleanNooTextFormat();
      }   else   {
        this.setTextFormat(this.begin, this.current, this.nooTform);
      }
    };
    TextField.prototype.cleanNooTextFormat = function() {
      delete this.current;
      delete this.nooTform;
      delete this.begin;
      delete this.end;
      clearlnterval(this.myNooText);
      delete this.myNooText;
      this.obja[this.func]();
    };
    String.prototype.findInstances = function(str) {
      var foundAt = [] ;
      var nextFound = 0;
      var largeStr = this.toLowerCase();
      var smallStr = str.toLowerCase();
      while (nextFound!= -1) {
        nextFound = largeStr.indexOf(smallStr, nextFound);
        if (nextFound != -1) {
          foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
          nextFound++;
        }
      }
    return foundAt;
    };
    function nooFindAndReplace(textObj, str) {
      this.indices = textObj.text.findInstances(str) ;
      this.doNext();
    }
    function doNext() {
      if (indices.length>0) {
        var nexta = this.indices.shift();
        this.tf_txt.nooTextFormat(myForm, nexta.begin, nexta.end, 1, 30, this, "doNext");
      }
    }
    this.tf_txt.text = "The eidophor system is a projection television system, i.e. it enables enlarged television pictures to be projected on to a screen. An ordinary television picture derives its brightness from the fluorescence of a screen bombarded by electrons,- with the eidophor system, on the other hand, a very powerful source of light is controlled by the television signal picked up by the receiver.";
    myForm = this.tf_txt.getTextFormat();
    myForm.color = 0x000000;
    myForm.size = 9;
    myForm.bold = true;
    nooFindAndReplace(this.tf_txt, "television", myForm);
    Пример 2.1.
  4. Сохраните файл под именем switchTextFormat2.fla и запустите его. Вы увидите четыре вхождения слова "television", выделенные красным цветом.

The eidophor system is a projection television system, i.e. it enables enlarged television pictures to be projected on to a screen. An ordinary television picture derives its brightness from the fluorescence of a screen bombarded by electrons; with the eidophor system, on the other hand, a very powerful source of light is controlled by the television signal picked up by the receiver.

Используя этот метод, можно добиться большого количества разнообразных эффектов. Например, можно просто изменить некоторые значения в объекте textFormat, изменить скорость и т.д.

Существует несколько менее значимых, но полезных дополнений к этому подходу. Например, функция doNext намеренно написана для отдельного объекта текстового поля и textFormat. В идеале, мы имели бы дело с объектами текста и формата текста, передаваемыми ей в виде аргументов. Это можно реализовать, передавая в начале значения текстовому полю, и затем, когда каждое слово обработано, передавать эти аргументы в doNext для использования при ее следующем вызове. Мы не будем тратить время на то, чтобы разбираться в этом сейчас, однако в файле switchTextFormat3.fla есть комментарии, которые помогут вам уяснить все должным образом. По большому счету, это просто расширение нашей функции обратной связи для передачи аргументов.

Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip? 

Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009
Магомед Алисултанов
Магомед Алисултанов
Россия, Волгоград, лицей 2