Autor Zpráva
Tori
Profil
Pěkný večer,

jak by se dalo v JS docílit, aby porovnávání řetězců fungovalo jako v MySQL s utf8_unicode_ci?
Totiž: označuju v nějakém textu např.jména spisovatelů, jejich ID vybírám ze selectu v modálním okně. Do okna zároveň posílám označené jméno, aby se mohl předvyplnit formulář na přidání nové položky do číselníku. Chtěla jsem docílit, aby se taky v selectu vybrala položka co nejblíž tomu označenému jménu (kvůli skloňování to málokdy je přesná shoda) - to mi funguje, kromě případů, kdy je ve jméně diakritika. Např.když v selectu jdou za sebou "Kabát, Káča, Kalina, Karas" a dám hledat "Karas", tak mi hledání skončí už na "Káče".
Položky selectu procházím takhle:
function najdiVSelectu(sel, t)	{
	var ln = sel.length; 
	var missed = false; 
	var part = (t.indexOf(',') == -1 ? null : t.slice(0, t.indexOf(','))); 
	var inic = t.charAt(0);
	var opt;
	// console.info('cely text = '+t+", part = "+part);
	for (var i=0; i<ln; i++)	{
		opt = sel[i].text;
		// console.info(t, opt, part);
		if (inic == opt.charAt(0))	{
			missed = true;
			if (opt.indexOf(t) == 0)	{ /* shoda */
				sel[i].selected = true;
				break;
			} else if (opt > t)	{ /* jsme za */
				if (part != null && opt.indexOf(part) == 0)	{ /* da se hledat jen cast a shoduje se */
					sel[i].selected = true;
				} else { /* nelze hledat cast = oznac predchozi */
					sel[(i-1)].selected = true;
				}
				break;
			}
		/* neni option od stejne inicialy = pouzij predchozi. 
		  pokud predchozi neexistuje, nic se nedeje, prvni je implicitne vybrany. */
		} else if (missed === true)	{
			sel[(i-1)].selected = true;
			break;
		}
	}
}

Zatím mě napadlo jen použít něco jako tady. Není nějaký jednodušší postup, než každou z řekněme pár stovek položek selectu převádět na nějaký porovnávatelný řetězec? Díky moc za radu a pardon za nevelmi pěkný kód.
__construct
Profil
Tori:
Pokiaľ som správne pochopil čo chceš:
Predpokladám, že mená autorov máš uložené v nejakej databázi. Dobré riešenie by bolo pridať do tabuľky stĺpec s oddiakritizovaným menom malými písmenami jednorázovo pri vypĺňaní tabuľky. Potom pri hľadaní prevedieš hľadaný výraz do takej istej formy a pohľadáš ho v tabuľke.
Tori
Profil
__construct:
Díky, to by určitě šlo, jen obsah selectu se dynamicky mění a položky tahám AJAXem, tak jsem to chtěla proto řešit až v browseru. Příště zkusím použít váš návrh, zatím jsem to udělala takhle:
var collation = {};

/* Porovná dva řetězce, vrací 0 = shoda, -1 = první je větší, 1 = druhý je větší */
function strcmp(s1, s2)	{
	if (collation['a'] == undefined)	{ // anebo je lepší Object.keys(collation).length == 0  ?
		/* znaky v každé skupině se porovnávají stejně jako první z nich */
		var chars = [ 'aáäàãâ', 'b', 'cćč', 'dď', 'eéěëèê', 'f', 'g', 'h', 'iíïìî', 'j', 'k', 'lĺľ', 
			'm', 'nńňñ', 'oóôòõöő', 'p', 'q', 'rŕř', 'sśš', 'tť', 'uúùůüũû', 'v', 'w', 'x', 'yý', 'zźž' ];
		var key,val;
		for (var i=0; chars[i] !== undefined; i++)	{
			key = chars[i].charAt(0);
			var j=0;
			while (val = chars[i].charAt(j))	{
				collation[val] = key;
				collation[val.toUpperCase()] = key;
				j++;
			}
		}
	}
	
	/* porovnává jen počet znaků podle kratšího slova */
	var ln = Math.min(s1.length, s2.length), l1, l2;
	for (var i=0; i<ln; i++)	{
		l1 = s1.charAt(i);
		l2 = s2.charAt(i);
		if (l1 == l2)	{
			continue;
		} else if (collation[l1] > collation[l2])	{
			return -1;
		} else if (collation[l2] > collation[l1])	{
			return 1;
		}
	}
	return 0;
}

/* označí nejbližší položku v selectu. 1.param = <select> prvek, 2.param = hledaný text */
function searchSel(sel, t)	{
	var ln = sel.length; 
	var	missed = false; 
	var	inic = t.charAt(0).toUpperCase();
	var opt,cmp;
	for (var i=0; i < ln; i++)	{
		opt = sel[i].text;
		/* počítá se s tím, že položky jsou seřazené podle abecedy, takže nejdřív kontroluje iniciálu */
		if (inic == opt.charAt(0).toUpperCase())	{
			missed = true;
			cmp = strcmp(t, opt);
			if (cmp > -1)	{
				sel[(i-cmp)].selected = true;
				return null;
			}
		} else if (missed === true)	{
			sel[(i-1)].selected = true;
			return null;
		}
	}
}

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0