2009-01-07 24 views
5

Próbując uczynić moją Javascript nie rzucającym się w oczy, używam onLoad s, aby dodać funkcjonalność do <input> s i takich. Z Dojo, wygląda to mniej więcej tak:Czy istnieje odpowiednik Javascriptu dla Rubiego andand?

var coolInput = dojo.byId('cool_input'); 
if(coolInput) { 
    dojo.addOnLoad(function() { 
    coolInput.onkeyup = function() { ... }; 
    }); 
} 

Lub około równoważnie:

dojo.addOnLoad(function() { 
    dojo.forEach(dojo.query('#cool_input'), function(elt) { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

ktoś pisemnej implementacji Ruby andand abym mógł wykonać następujące czynności?

dojo.addOnLoad(function() { 
    // the input's onkeyup is set iff the input exists 
    dojo.byId('cool_input').andand().onkeyup = function() { ... }; 
}); 

lub

dojo.byId('cool_input').andand(function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

Odpowiedz

2

Dokładna składnia chcesz nie jest możliwa w języku JavaScript. Sposób, w jaki wykonuje JavaScript, musiałby się zmienić w całkiem fundamentalny sposób. Na przykład:

var name = getUserById(id).andand().name; 
//      ^
//      |------------------------------- 
// if getUserById returns null, execution MUST stop here | 
// otherwise, you'll get a "null is not an object" exception 

Jednak JavaScript nie działa w ten sposób. Po prostu nie.

Następująca linia wykonuje niemal dokładnie to, co chcesz.

var name = (var user = getUserById(id)) ? user.name : null; 

Jednak czytelność nie zostanie skalowana na większe przykłady. Na przykład:

// this is what you want to see 
var initial = getUserById(id).andand().name.andand()[0]; 
// this is the best that JavaScript can do 
var initial = (var name = (var user = getUserById(id)) ? user.name : null) ? name[0] : null; 

I jest efekt uboczny tych niepotrzebnych zmiennych. Używam tych zmiennych, aby uniknąć podwójnego wyszukiwania. Zmienne są niszczeniu kontekst, a jeśli to jest to ogromny problem, można użyć funkcji anonimowych:

var name = (function() {return (var user = getUserById(id)) ? user.name : null;})(); 

Teraz zmienna użytkownik jest czyszczony się prawidłowo, i wszyscy są zadowoleni. Ale wow! co za dużo pisania! :)

+3

Lub użyj [CoffeeScript] (http://jashkenas.github.com/coffee-script/#operators): spójrz na "wariant akcesorium operatora egzystencjalnego" '? .' :) –

0

O ile wiem, nie ma wbudowanej funkcji JavaScript, który ma tę samą funkcjonalność. Myślę jednak, że najlepszym rozwiązaniem jest zapytanie o klasę zamiast identyfikatora i użycie dojo.forEach (...), ponieważ masz zagwarantowany niezerowy element w zamknięciu forEach.

Można zawsze używać odpowiednika JavaScript:

dojo.byId('cool_input') && dojo.byId('cool_input').whateverYouWantToDo(...); 
+0

Podwójne wyszukiwanie jest dokładnie tym, czego staram się uniknąć. Nie byłoby to tylko dla dojo.byId; inne funkcje mogą być _far_ wolniejsze. –

0

Nigdy nie używany dojo, ale większość javascript ramy (gdy ma do czynienia z DOM) powrót elementu wywołującego, gdy metoda jest wywoływana z obiektu elementu (słabe sformułowanie, przepraszam). Więc andand() byłby niejawny.

dojo.addOnLoad(function() { 
    dojo.byId('cool_input').onkeyup(function(evt) { /*event handler code*/ 
    }); 
}); 
+0

Z wyjątkiem sytuacji, gdy byId nie znajduje żądanego elementu. Andand po prostu nic nie zrobi, ale twój kod spróbuje wywołać onkeyup na tym nieistniejącym obiekcie. –

1

Jak o coś takiego:

function andand(elt, f) { 
    if (elt) 
    return f(elt); 
    return null; 
} 

połączeń jak ten:

andand(dojo.byId('cool_input'), function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 
3

nie wiem Dojo, ale nie powinno to Twój pierwszy przykład czytać

dojo.addOnLoad(function() { 
    var coolInput = dojo.byId('cool_input'); 
    if(coolInput) 
     coolInput.onkeyup = function() { ... }; 
}); 

W przeciwnym razie możesz skończyć się tryi ng, aby uzyskać dostęp do elementu przed zbudowaniem DOM.

Powrót do pytania: W JavaScript, chciałbym zrealizować andand() jak

function andand(obj, func, args) { 
    return obj && func.apply(obj, args || []); 
} 

Twój Przykładem może być następnie zapisane jako

dojo.addOnLoad(function() { 
    andand(dojo.byId('cool_input'), function() { 
     this.onkeyup = function() { ... }; 
    }); 
}); 

który nie jest aż tak dużo krócej niż przy użyciu wyraźne oświadczenie if - więc po co zawracać sobie głowę?

0

Listę:

Array.prototype.andand = function(property, fn) { 

    if (this.filter(property).length > 0) this.map(fn); 
} 
+0

To nie zadziała. andand powinien zatrzymać wykonywanie, jeśli tablica ma wartość NULL. Oczywiście, jeśli tablica ma wartość zerową, nie jest to już tablica. W związku z tym metoda andand nie jest już dostępna. –

2

Chcesz dojo.behavior.

dojo.behavior.add({ 
    '#cool_input': { 
     onKeyUp: function(evt) { ... } 
    } 
}); 
Powiązane problemy