Comunidad de diseño web y desarrollo en internet

Buscador de texto en Flash MX 2004 y ActionScript 2.0

ORIENTANDO NUESTRO PROYECTO

Con este tutorial aprenderemos paso a paso como crear una objeto Buscador de texto con ActionScript 2.0 mediante una clase que luego podremos aplicar a todos nuestros proyectos.

Cabe decir que aunque esta clase no es un gran proyecto (de hecho no merece llamarse ni proyecto XD), sí que es cierto que todas nuestras clases debemos orientarlas para que el usuario final, léase el programador, pueda utilizar dicho objeto para diversas finalidades y que tenga cabida en multitud de aplicaciones que éste pueda desarrollar.

Así con esto, ¿cómo debemos crear nuestros métodos? ¿qué propiedades tendrá y cuales no? Este tipo de preguntas son las que inicialmente agolpan nuestra mente a la hora de realizar nuestra primera clase, entonces debemos preguntarnos nosotros si alguien hiciese una objeto Buscador qué necesitariamos para programarla y poder tener un objeto realmente potente. Es cuando llegamos a la definición del constructor, las propiedades y los métodos.

El constructor

La definición del constructor nos va a marcar gran parte del diseño en nuestras propiedades y métodos. Una forma fácil de encarar el desarrollo de este, es preguntarnos cual sería la forma más fácil para hacer una búsqueda con el objeto que estoy creando, es decir, si yo fuese el programador que va a usar este objeto, ¿cómo me gustaría poder programarla?

Nosotros como programador podriamos crear nuestro objeto de la siguiente manera:

var miBusqueda:Buscador = new Buscador(texto a buscar);

No parece una gran idea esto, si queremos buscar otro texto tendríamos que crear un nuevo objeto. Quizá si lo hacemos de esta otra manera:

var miBusqueda:Buscador = new Buscador(caja de texto donde buscar);

Esto tiene mejor pinta... pero, un momento, ¿y si he de buscar el texto en varias cajas? ¿y si quiero cambiar la caja de texto donde se realiza la búsqueda dinámicamente? Vaya, tendría que crear varios objetos para realizar la misma búsqueda, esto sin duda ralentizaría mucho la tarea del desarrollador aparte de que sería más difícil de programar. Entonces quizá sería mejor algo así como:

var miBusqueda:Buscador = new Buscador();

Efectivamente, no es ningún pecado dejar nuestro constructor vacío, con las propiedades y los métodos configuraremos nuestro objeto para que busque el texto que deseamos, añadirle las opciones y demás cosas que veamos importantes.

Las propiedades

Nuestro deseo es crear un objeto Buscador como los que pueden ofrecernos nuestros navegadores por ejemplo, así que, habrán un par de opciones clásicas como podrían ser "Búsqueda por palabra exacta" y "Diferenciar entre mayúsculas y minúsculas" las cuales podrían ser un par de propiedades Booleanas que podemos activar y desactivar mediante unos checkBox como en cualquier programa de la actualidad.

Pero esto no es todo, no sólo tenemos que pensar en las 'opciones', pues las propiedades no se ciñen a esto solamente. Cuando creemos nuestras propiedades debemos pensar en todas aquellas variables que sería bueno cambiar dinámicamente, es decir, en nuestro tiempo de ejecución.

Es obvio, que las Booleanas anteriores las cambiaremos dinamicamente, pues cuando estamos haciendo la búsqueda podemos seleccionar como deseamos que sea. Como hemos explicado anteriormente también sería recomendable crear una propiedad miCampo para que el programador pueda realizar búsquedas en varios campos.

Estas podrían ser fácilmente nuestras propiedades:

miCampo Campo de texto objetivo donde realizaremos la búsqueda.
dMayMin Booleano para activar/desactivar la diferenciación entre mayúsculas y minúsculas.
palabraExacta Booleano para activar/desactivar la búsqueda por palabra exacta.

El hecho de incluir una propiedad miCampo y no incluirla en el constructor del objeto (p. ej: var miBusqueda:Buscador = new Buscador(mitexto_txt)) nos proporcionará una flexibilidad a la hora de programar mucho mayor, pudiendo hacer combinaciones más potentes al poder seleccionar el campo de realizar la búsqueda.

Ahora veremos como encarar nuestros métodos, los cuales nos darán la funcionalidad del objeto.

Los métodos

Una vez definidas las propiedades nuestra elección de métodos será considerablemente más fácil. Ya sabemos que nosotros podremos decirle al objeto, en qué caja de texto buscar (miCampo), y si queremos activar las opciones de búsqueda (dMayMin y palabraExacta) podemos hacerlo con un simple Booleano.

Ahora sólo nos falta decir que el objeto busque, para lo cual necesitaremos un método que podría ser:

miBusqueda.buscar("Texto a buscar");

Este método nos devolverá -1 en caso de que no haya encontrado nada y, en caso de que encuentre algo, nos devolverá la posición de la primera coincidencia. Cada vez que ejecutemos el método este seguirá buscando en la caja de texto hasta que no encuentre nada y devuelva -1.

¿Por qué lo hacemos así? El programador tendrá así la flexibilidad de una vez recibida la posición del texto hacer con el lo que le plazca, colorearlo, seleccionarlo, cambiarle el formato, etc... nosotros podríamos hacer esto por el, pero el programador tendria que ceñirse solamente a eso, una selección o algo por el estilo.

También estaría bien incluir un método que buscase el total de coincidencias en la caja de texto, para poder mostrar mensajes del tipo "coincidencia 1/7". Algo así estaría bien:

miBusqueda.buscarTodo("Texto a buscar");

Bueno, ahora "sólo" queda programar esto, así que si no tienes un programador esclavizado te sugiero que sigas con todo lo que viene ahora.

PROGRAMANDO NUESTRO OBJETO

Ahora toca trabajar

Después de definir nuestros métodos y propiedades nos va a tocar programar (qué remedio :P), así que con los pasos anteriores vamos a crear nuestra clase aunque de momento esté vacía. Crear un archivo que se llame Buscador.as, recordar que este tiene que estar en la misma carpeta que vuestra .fla, si no, no funcionará.

class Buscador {
//Constructor
function Buscador() {
}
//Método: buscar("texto a buscar") --> Devuelve la posición inicial del primer
//texto coincidente.

public function buscar(palabra:String) {
}
//Método: buscarTodo("texto a buscar") --> Nos devuelve el número total de veces
//que está el texto que nos ha pasado el usuario.

public function buscarTodo(palabraTodo:String) {
}
//----------- GETTERS Y SETTERS -------------//
//Diferenciar entre mayúsculas y minúsculas

public function set dMayMin(dMM:Boolean):Void {
}
public function get dMayMin():Boolean {
}
//Búsqueda por palabra exacta
public function set palabraExacta(palExac:Boolean):Void {
}
public function get palabraExacta():Boolean {
}
}

Como podéis ver en el código hemos creado dos funciones (buscar y buscarTodo) que serán nuestros métodos, también hemos creado las propiedades mediante getters y setters. Hay una propiedad que no hemos creado así, es miCampo, la cual tiene que decirnos sobre qué campo de texto debemos hacer las búsquedas. En vez de usar getters y setters para esto utilizaremos una práctica muy utilizada en lenguajes como C++, los apuntadores (dios!! como los odiaba cuando era estudiante).

Crear un apuntador es muy fácil, sólo tenemos que crear una variable pública sin definición de tipo de variable y luego en nuestro .fla igualarla a la caja de texto objetivo. Esto lo que hará será crear una variable que "apuntará" a la caja de texto, ya que la variable en sí no puede ser la caja de texto. Parece cosa de magia potagia, pero os prometo que funciona.

Vamos a programar las propiedades ahora, son más fáciles que los métodos y así podremos ir viendo como toma forma nuestra clase. Cambia tu código actual de la clase por este otro:

class Buscador {
public var miCampo;
private var palEx, difMM:Boolean;
private var elTexto_str:String;
//Constructor
function Buscador() {
this.difMM = false;
this.palEx = false;
}
//Método: buscar("texto a buscar") --> Devuelve la posición inicial del primer
//texto coincidente.

public function buscar(palabra:String) {
}
//Método: buscarTodo("texto a buscar") --> Nos devuelve el número total de veces
//que está el texto que nos ha pasado el usuario.

public function buscarTodo(palabraTodo:String) {
}
//----------- GETTERS Y SETTERS -------------//
//Diferenciar entre mayúsculas y minúsculas

public function set dMayMin(dMM:Boolean):Void {
if (this.difMM == true) {
elTexto_str = this.miCampo.text;
} else if (this.difMM == false) {
elTexto_str = this.miCampo.text.toLowerCase();
}
this.difMM = dMM;
}
public function get dMayMin():Boolean {
return this.difMM;
}
//Búsqueda por palabra exacta
public function set palabraExacta(palExac:Boolean):Void {
this.palEx = palExac;
}
public function get palabraExacta():Boolean {
return this.palEx;
}
}

Ya están listas las propiedades y no las vamos a volver a tocar más. ¿Increíble no? Esto está chupado estarás pensando... bueno, luego se complica. Con las funciones Set le ponemos los valores a nuestras propiedades y con los Get recuperamos los valores para poder visualizarlos, compararlos o lo que nos apetezca hacer.

En la propiedad dMayMin, hemos hecho una cosa extraña en el Set que nos servirá para coger el texto tal cual o en minúsculas. Así, cuando seleccionamos "Diferenciar mayúsculas y minúsculas" lo que haremos será coger el texto normal, sino, lo cogeremos en minúsculas y lo compararemos con el texto a buscar pasado a minúsculas también. Esto lo hacemos así porque Flash entiende que es diferente la palabra "CristaLab" que "cristaLab", así pasando todo el texto a minúsculas (tanto el texto a buscar como el texto donde buscamos) nos aseguramos que todo el texto es igual y nos encontrará las coincidencias.

Ahora ya podemos crear el .fla y hacer nuestra primera prueba cambiando los valores a las propiedades del objeto Buscador. Escribe el siguiente código y graba el .fla en la misma carpeta que el .as:

var miBusqueda:Buscador = new Buscador();
miBusqueda.dMayMin = true;
trace(miBusqueda.dMayMin);

Si quitas la línea 2 de código verás que el trace te devuelve en la ventana del OutPut "false", esto es porque nosotros en el constructor le hemos dado unos valores iniciales, que serán los valores que tendrán esas propiedades por defecto.

Deberíamos crear un interfaz para poder trabajar mejor con la clase... veamos que se puede hacer.

Vista orevia de la interfaz
  1. buscar_txt: Caja de texto input con "mostrar borde" seleccionado. Tipografía _sans a tamaño 11.
  2. buscar_btn: Botón normal y corriente con los tres estados, nada complicado, jeje.
  3. palab_btn: Clip de película con dos fotogramas, uno con la caja en blanco y la otra con la caja en color naranja. Los dos fotogramas tienen un stop().
  4. mayus_btn: Igual que el anterior.
  5. texto_txt: Caja de texto dinámica, multilínea, texto html no, selección no, _sans y tamaño de letra 10.
  6. status_txt: Caja de texto dinámica, multilínea no, texto html no, selección no, _sans y tamaño de letra 10.

Esta será nuestra pantalla donde probaremos los resultados que nos dé nuestra clase, podéis cambiar algunas cosas como la tipografía o el tamaño de letra, así lo adecuáis a vuestros gustos. Procurar también hacer la interfaz en una capa separada al código, es más usable.

Al código del .fla podéis añadirle lo siguiente:

var palabExacta:Boolean = new Boolean(false);
var mayusMinus:Boolean = new Boolean(false);
buscar_btn.onRelease = function() {
miBusqueda.miCampo = texto_txt;
};
palab_btn.onPress = function() {
if (palabExacta == false) {
this.nextFrame();
miBusqueda.palabraExacta = true;
palabExacta = true;
} else if (palabExacta == true) {
this.prevFrame();
miBusqueda.palabraExacta = false;
palabExacta = false;
}
};
mayus_btn.onPress = function() {
if (mayusMinus == false) {
this.nextFrame();
miBusqueda.dMayMin = true;
mayusMinus = true;
} else if (mayusMinus == true) {
this.prevFrame();
miBusqueda.dMayMin = false;
mayusMinus = false;
}
};

Ahora cambiando la clase un poco haremos que nuestro objeto realice su primera búsqueda.

EL MÉTODO BUSCAR()

Ahora las cosas se empiezan a complicar aunque sea sólo un poco. Implementaremos nuestra búsqueda añadiendo la opción más sencilla que es la diferenciación entre mayúsculas y minúsculas, luego añadiremos la opción de palabra exacta, bastante más difícil de programar.

Cambia tu clase Buscador y dejala como esta que sigue:

class Buscador01 {
public var miCampo;
private var palEx, difMM:Boolean;
private var buscarPal, elTexto_str:String;
private var posicionBusq, busqueda:Number;
//Constructor
function Buscador01() {
posicionBusq = 0;
this.difMM = false;
this.palEx = false;
}
//Método: buscar("texto a buscar") --> Devuelve la posición inicial del primer
//texto coincidente. A cada ejecución busca desde la ultima coincidencia.

public function buscar(palabra:String) {
buscarPal = palabra;
if (buscarPal != "") {
if (difMM == true) {
elTexto_str = this.miCampo.text;
busqueda = elTexto_str.indexOf(buscarPal, posicionBusq);
} else if (difMM == false) {
elTexto_str = this.miCampo.text.toLowerCase();
busqueda = elTexto_str.indexOf(buscarPal.toLowerCase(), posicionBusq);
}
//Si busqueda devuelve -1 es que no se ha encontrado nada
if (busqueda == -1) {
//Si hemos llegado al final o no se ha encontrado nada, ponemos a 0 //la posición
posicionBusq = 0;
return busqueda;
} else if (busqueda != -1) {
//Se ha encontrado algo, sumamos a la posición y devolvemos valor
posicionBusq = busqueda+buscarPal.length;
return busqueda;
}
}
}
//Método: buscarTodo("texto a buscar") --> Nos devuelve el número total de veces
// que está el texto que nos ha pasado el usuario.

public function buscarTodo(palabraTodo:String) {
}
//----------- GETTERS Y SETTERS -------------//
//Diferenciar entre mayúsculas y minúsculas

public function set dMayMin(dMM:Boolean):Void {
if (this.difMM == true) {
elTexto_str = this.miCampo.text;
} else if (this.difMM == false) {
elTexto_str = this.miCampo.text.toLowerCase();
}
this.difMM = dMM;
}
public function get dMayMin():Boolean {
return this.difMM;
}
//Búsqueda por palabra exacta
public function set palabraExacta(palExac:Boolean):Void {
this.palEx = palExac;
}
public function get palabraExacta():Boolean {
return this.palEx;
}
}
Y el código de tu .fla así:
var palabExacta:Boolean = new Boolean(false);
var mayusMinus:Boolean = new Boolean(false);

var miBusqueda:Buscador01 = new Buscador01();
miBusqueda.miCampo = texto_txt;
buscar_btn.onRelease = function() {
resul = miBusqueda.buscar(buscar_txt.text);
if (resul != -1) {
status_txt.text = "Has encontrado la palabra "+buscar_txt.text;
Selection.setFocus(texto_txt);
Selection.setSelection(resul, resul+buscar_txt.length);
} else if (resul == -1) {
status_txt.text = "Fin de la búsqueda";
Selection.setFocus(buscar_txt);
Selection.setSelection(0, buscar_txt.length);
}
};
//Botones tipo CheckBox
palab_btn.onPress = function() {
if (palabExacta == false) {
this.nextFrame();
miBusqueda.palabraExacta = true;
palabExacta = true;
} else if (palabExacta == true) {
this.prevFrame();
miBusqueda.palabraExacta = false;
palabExacta = false;
}
};
mayus_btn.onPress = function() {
if (mayusMinus == false) {
this.nextFrame();
miBusqueda.dMayMin = true;
mayusMinus = true;
} else if (mayusMinus == true) {
this.prevFrame();
miBusqueda.dMayMin = false;
mayusMinus = false;
}
};

Analicemos la clase Buscador primero. La variable "buscarPal" recoge nuestro texto a buscar, luego tenemos un if-else donde realizaremos la busqueda del texto según si hemos escogido o no, diferenciar entre mayusculas y minusculas. La busqueda se realiza de la siguiente manera.

En la variable elTexto_str recogemos lo que hay en la caja de texto a buscar y hacemos un indexOf de la palabra a buscar y desde la posición inicial igual a 0. El método indexOf, nos busca un texto y si existe nos devuelve la posición inicial de donde se encuentra este, si no existe, devuelve -1. La posición a buscar primero será 0, ya que empezamos buscando desde el principio, pero cada vez que se ejecute seguirá buscando desde el último punto donde se encontró una coincidencia, no desde el principio otra vez.

Así, cuando busqueda es -1, reiniciamos variables y devolvemos el valor, pero si no es -1, la variable posicionBusq será igual a la posición donde se ha encontrado una palabra más el largo de esa palabra, así nos posicionaremos al final de esta para continuar buscando.

Siguiendo la curva de aprendizaje ahora veremos como hacer el método buscarTodo, y por último, acabaremos con la propiedad palabraExacta.

EL MÉTODO BUSCARTODO()

Este método es muy similar al anterior lo único que hemos de realizar la búsqueda dentro de un bucle para que se ejecute hasta que no encuentre nada y nos devuelva así el resultado de coincidencias totales.

Veamos el código:

//Método: buscarTodo("texto a buscar") --> Nos devuelve el número total de
//veces que está el texto que nos ha pasado el usuario.

public function buscarTodo(palabraTodo:String){
buscaTodo = palabraTodo;
contarTodo = 0;

if (buscarPal != ""){
do {
if (difMM == true){
elTodo_str = this.miCampo.text;
busquedaTodo = elTodo_str.indexOf(buscaTodo, posicionTodo);
}
else if (difMM == false){
elTodo_str = this.miCampo.text.toLowerCase();
busquedaTodo = elTodo_str.indexOf(buscaTodo.toLowerCase(), posicionTodo);
}

//Si busqueda devuelve -1 es que no se ha encontrado nada
if (busquedaTodo == -1){
//Si hemos llegado al final o no se ha encontrado nada, ponemos a 0 //el contador
posicionTodo = 0;
}
else if (busquedaTodo != -1){
//Se ha encontrado algo, sumamos al contador y seguimos buscando más
//adelante

contarTodo++;
posicionTodo = busquedaTodo + buscaTodo.length;
}
} while(busquedaTodo != -1)
}

return contarTodo;
}

Como podéis ver la función es casi igual pero implementada dentro de un do-while para que así nos cuente las palabras que hay en toda la caja de texto, el bucle finalizará cuando no se haya encontrado nada y devolveremos los parámetros.

Tip: No olvides añadir tus nuevas variables. Tipo String son buscaTodo, busquedaTodo y elTodo_str; tipo Number son posicionTodo y contarTodo.

Supongo que estarás pensando cosas del estilo "¡Genial! ¡Qué bueno soy!", pero como diría el Señor Lobo en Pulp Fiction "No empecemos a chuparnos las ****** (Censurado por phpBB)". Esta es la parte fácil tampoco hay que tirar campanas al vuelo, aunque de momento tengamos gran parte de nuestra clase programada y ya está casi lista para usar. Pero falta lo más difícil... la (maldita) búsqueda por palabra exacta.

LA PROPIEDAD PALABRAEXACTA

Ahora llegamos al meollo de la cuestión, realmente os he estado dando la vara durante todo el tutorial diciendo que esto es muy difícil, la verdad es que no lo es tanto (MWAHAHAHAHAHAHA) una vez entenáis las limitaciones que tiene Flash en relación a las búsquedas de texto.

El método indexOf() nos encuentra una cadena de texto dentro de un String, pero el problema que tenemos es que no nos dice si esa cadena es exacta, es decir, si no tiene letras a los lados. Así tendremos que comparar si el String buscado tiene letras a los lados, cosa que podemos hacer comparando sus caracteres ASCII para ir más rápido. Para tener el código más ordenado (hay que ser limpios) esa comparación la haremos una función privada dentro de nuestra clase.

La función es esta:

	//Función: textoExacto("texto a buscar") --> Nos devuelve true si el texto que
//hemos pasado está escrito exactamente. Si no devuelve false.

private function txtExacto(buscarTexto:String) {
textoExacto = buscarTexto;
resulExacto = true;
primeraBien = true;
ultimaBien = true;
primera = textoExacto.substr(0, 1);
ultima = textoExacto.substr(textoExacto.length-1, 1);
//A = 65 Z = 90
//a = 97 z = 122

if ((primera.charCodeAt(0)>=65 && primera.charCodeAt(0)<=90) || (primera.charCodeAt(0)>=97 && primera.charCodeAt(0)<=122)) {
primeraBien = false;
}
if ((ultima.charCodeAt(0)>=65 && ultima.charCodeAt(0)<=90) || (ultima.charCodeAt(0)>=97 && ultima.charCodeAt(0)<=122)) {
ultimaBien = false;
}
if (primeraBien == true && ultimaBien == true) {
resulExacto = true;
} else {
resulExacto = false;
}
return resulExacto;
}

Tip: Añadir las nuevas variables Booleanas primeraBien, ultimaBien, resulExacto; y las variables String primera, ultima y textoExacto.

En este código lo que hacemos es coger el carácter anterior y posterior de nuestra cadena de texto y compararlos para saber si son letras. En caso de que una de las dos (o ambas) sea una letra significará que la cadena actual, está dentro de otra y por lo cual no es una palabra exacta. Por ejemplo:

Palabra a buscar = carro

Me gusta tu carrocería... nena --> Devuelve False al detectar una C a la derecha.

Comete los macarrones --> Devuelve False al detectar una A a la izquierda y una N en la derecha.

¡mi carro me lo robaron! --> Devuelve True al no detectar letras al lado.

De esta forma nos estamos asegurando también un posible bug, y es que las palabras que estuviesen entre signos si han de ser identificadas. Así todas las palabras entre interrogaciones, exclamaciones, puntos, comas, etc... también serán detectadas.

Modificando el método buscarTodo

Bien, una vez tenemos montada nuestra función, vamos a aplicarla primero a buscarTodo que será más sencillo. Dejadlo tal cual se ve abajo:

//Método: buscarTodo("texto a buscar") --> Nos devuelve el número total de veces
// que está el texto que nos ha pasado el usuario en la caja correspondiente.

public function buscarTodo(palabraTodo:String){
buscaTodo = palabraTodo;
contarTodo = 0;
if (buscarPal != ""){
do {
if (difMM == true){
elTodo_str = this.miCampo.text;
busquedaTodo = elTodo_str.indexOf(buscaTodo, posicionTodo);
}
else if (difMM == false){
elTodo_str = this.miCampo.text.toLowerCase();
busquedaTodo = elTodo_str.indexOf(buscaTodo.toLowerCase(), posicionTodo);
}

if (palEx == true){
palaExa_str = elTodo_str.substr(elTodo_str.indexOf(buscaTodo, posicionTodo)-1, buscaTodo.length+2);
matchCase = txtExacto(palaExa_str);
}
else if (palEx == false){
matchCase = true;
}

//Si busqueda devuelve -1 es que no se ha encontrado nada
if (busquedaTodo == -1){
//Si hemos llegado al final o no se ha encontrado nada, ponemos a 0 //el contador
posicionTodo = 0;
}
else if (busquedaTodo != -1 && matchCase == true){
//Se ha encontrado algo, sumamos al contador y seguimos buscando más
//adelante

contarTodo++;
posicionTodo = busquedaTodo + buscaTodo.length;
}
else if (busquedaTodo != -1 && matchCase == false){
posicionTodo = busquedaTodo + buscaTodo.length;
}
} while(busquedaTodo != -1)
}

return contarTodo;
}

Ahora mismo ya no tendremos que tocar más nuestro método buscarTodo!! Genial!! Ya has completado este método en su totalidad y está listo para usarse, pero antes veamos qué hemos cambiado (no olvides poner las nuevas variables matchCase:Boolean y palaExa_str:String).

Hemos colocado un if-else nuevo para saber si está activada la opción de palabra exacta. Si está activado cogeremos la palabra a buscar más, un carácter anterior y otro posterior, para luego llamar a la función txtExacto que comprobará si el primer y último carácter son letras o no, si el resultado es true, significará que la palabra es correcta. Si os fijáis cuando no buscamos por palabra exacta siempre es true, ya que las palabras buscadas siempre serán correctas.

Ahora también, en los if-else de más abajo tenemos tres variantes.

  1. Si busquedaTodo es igual a -1, significa que hemos llegado al final. Inicializamos la variable posicionTodo para empezar a buscar desde el principio
  2. Si busquedaTodo es diferente a -1 y matchCase es igual a True, hemos encontrado una coincidencia. Sumamos uno a la variable que cuenta coincidencias y seguimos buscando.
  3. Si busquedaTodo es diferente a -1 y matchCase es igual a False, hemos encontrado una coincidencia, pero, esta dentro de una cadena de texto y ha sido desechada. No sumamos, pero seguimos buscando.

Los cambios como podéis ver no son muy grandes y ni de gran dificultad una vez sabemos las limitaciones de Flash cuando trabaja con texto.

Modificando el método buscar

Este método quizá tiene más cambios que no el método buscarTodo, pero éstos siguen el mismo patrón que en buscarTodo, así que encontraremos algo de código similar que entenderemos rapidamente.

Lo primero es lo primero, así que aquí tenéis el código modificado:

//Método: buscar("texto a buscar") --> Devuelve la posición inicial del primer
//texto coincidente.

public function buscar(palabra:String){
buscarPal = palabra;
if (buscarPal != ""){
do {
if (difMM == true){
elTexto_str = this.miCampo.text;
busqueda = elTexto_str.indexOf(buscarPal, posicionBusq);
}
else if (difMM == false){
elTexto_str = this.miCampo.text.toLowerCase();
busqueda = elTexto_str.indexOf(buscarPal.toLowerCase(), posicionBusq);
}

if (palEx == true){
palaExa_str = elTexto_str.substr(elTexto_str.indexOf(buscarPal, posicionBusq)-1, buscarPal.length+2);
matchCase = txtExacto(palaExa_str);
}
else if (palEx == false){
matchCase = false;
}

//Si busqueda devuelve -1 es que no se ha encontrado nada
if (busqueda == -1){
//Si hemos llegado al final o no se ha encontrado nada, ponemos a 0 el contador
posicionBusq = 0;
matchCase = true;

return busqueda;
}
else if (busqueda != -1 && matchCase == true && palEx == true){
//Se ha encontrado una palabra exacta
posicionBusq = busqueda + buscarPal.length;

return busqueda;
}
else if (busqueda != -1 && matchCase == false && palEx == true){
//Se ha encontrado una palabra no exacta, buscando palabra exacta
posicionBusq = busqueda + buscarPal.length;
matchCase = true;
}
else if (busqueda != -1 && palEx == false){
//Se ha encontrado una palabra no exacta
posicionBusq = busqueda + buscarPal.length;
matchCase = true;

return busqueda;
}
} while (busqueda != -1 && matchCase == true)
}
}

Vaya... cuántas cosas nuevas!! Bueno, bueno, poco a poco que no hay prisa. El cambio más grande en este método ha sido la inclusión de un do-while, pilar de este método a la hora de hacer las búsquedas.

Este bucle servirá para que cuando encontremos una palabra que no sea exacta, siga buscando hasta que la encuentre, sino, se pararía en un texto no coincidente. Lo explicare con un ejemplo que quizá se entienda mejor:

Palabra exacta a buscar: carro.

Texto donde buscamos: La carrocería de mi carro es la caña.

Si el bucle no existiese la busqueda se pararía en la palabra carrocería, ya que aunque no tomase la palabra como buena, la busqueda finalizaría ahí, y nuestro método ha de comprobar donde hay el primer texto válido en la búsqueda seleccionada. El bucle lo que hará será mirar si carrocería es una palabra exacta, comprobará que no, y seguirá buscando hasta que encuentre la palabra carro.

Una vez entendido esto, podemos ver que dentro tenemos algo similar a buscarTodo, con un if-else nuevo para saber si hemos de buscar una palabra exacta o no. En este caso en el else la variable matchCase es false siempre, porque nos ha de encontrar la primera palabra coincidente, no todas las coincidentes, así evitaremos que el bucle llegue hasta la última palabra, que es o que hace justamente el método buscarTodo.

Como en el método buscarTodo también han cambiado los if-else de más abajo donde comprobamos si hay coincidencias, ahora hay dos nuevos:

  1. Si búsqueda es igual a -1, significa que hemos llegado al final e inicializamos la variable para que empiece buscando desde la posición 0 del texto.
  2. Si búsqueda es diferente a -1 y matchCase es igual a True y palEx es igual a True, significa que hemos encontrado una palabra exacta. Nos posicionamos al final de la palabra buscada para cuando se ejecute de nuevo el método y devolvemos el valor.
  3. Si búsqueda es diferente a -1 y matchCase es igual a False y palEx es igual a True , significa que hemos encontrado una palabra haciendo una busqueda por palabra exacta. Nos ponemos al final del texto, colocamos matchCase en True y así el bucle sigue buscando hasta que encuentre (o no) una palabra exacta válida.
  4. Si búsqueda es diferente a -1 y palEx es igual a False , significa que hemos encontrado una palabra no exacta. Nos ponemos al final del texto y devolvemos el valor.

¿Es posible que hayamos acabado ya? ¡¡Pues sí!!

Este es el fin de esta clase que espero os sea muy útil, y a la cual me gustaría que le sacaseis toda la potencia que tiene pues va mucho más allá de lo que parece.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Descargar Archivo

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate