| Autor | Zpráva | ||
|---|---|---|---|
| Tori Profil |
#1 · Zasláno: 23. 11. 2011, 17:35:18
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 |
#2 · Zasláno: 23. 11. 2011, 20:24:58 · Upravil/a: __construct
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 |
#3 · Zasláno: 23. 11. 2011, 21:28:48 · Upravil/a: Tori
__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;
}
}
} |
||
|
Časová prodleva: 2 roky
|
|||