რამდენიმე თვის წინ დავწერე პოსტი, HTML ფორმის ელემენტის onchange ივენთისა და მისი დელეგირების შესახებ.
ნახსენებ პოსტში ნაჩვენებია onchange ივენთის დელეგირების მაგალითი სადაც ფორმის ყველა ელემენტის აღნიშნული ივენთის ცენტრალიზებული კონტროლი ხორციელდება მშობელი ელემენტის onchange ივენთის მეშვეობით.
მსგავსი შედეგის მიღწევა შესაძლებელი ე.წ. Event Bubbling – ის წყალობით რაც ივენთის, საწყისი ელემენტიდან მშობელი ელემენტისკენ გავრცელებას ეწოდება. მეტი თვალსაჩინოებისთვის იხ. სურათი(სურათისათვის განსაკუთრებული მადლობა ირაკლის):
ივენთის გავცელების(შვილიდან მშობლის მიმართულებით) ასეთი მეთოდი ყველა ბრაუზერში ერთნაირად მუშაობს. და წესით ეს უნდა ეხებოდეს ყველა ტიპის ივენთს. თუმცა როგორც მოსალოდნელი იყო IE – ში მისი მერვე ვერსიის ჩათვლით სწორედ ამ ივენთზე აღმოჩნდა შეზღუდვა და იგი საწყისი ელემენტს(ელემენტი რომელზეც უშუალოდ წარმოიშვა ეს ივენთი) იქეთ არ ვრცელდება.
ერთი შეხედვით, ამ ჩიხიდან რამდენიმე გამოსავალი შეიძლება მოიძებნოს:
- ფორმის ყველა ელემენტის ჩამოვლა და მათთვის onchange ივენთ ჰენდლერის მინიჭება. თუმცა აქ მთელ რიგ პრობლემებს წავაწყდებით:
- ელემენტებზე ასეთი გზით ივენთ ჰენდლერების მინიჭება IE – ში იწვევს მეხსიერებასთან დაკავშირებულ პრობლემებს, ე.წ. memory leaks. ეს გარემოება განსაკუთრებით მნიშვნელოვანია თუ ფორმაში ბევრი ელემენტები გვაქვს.
- თუ ფორმის ელემენტები იტვირთება დინამიურად Ajax – ის მეშვეობით, ყოველი ასეთი ჩატვირთვის შემდეგ საჭიროა: ა) ყველა ფორმის ელემენტისა და მათი ივენთ ჰენდლერების განადგურება რათა თავიდან ავირიდოთ მეხსიერებასთან დაკავშირებული პრობლემები; ბ) ახლად ჩატვირთული ელემენტების იტერაცია და მათთვის შესაბამისი ივენთ ჰენდლერების განსაზღვრა.
დამეთანხმებით რომ აღწერილი ორი მეთოდი დიდი მოქნილებით არ გამოირჩევა.
- ნაცვლად onchange ივენთისა გამოვიყენოთ onfocus და onblur ივენთები. თუმცა აღმოჩნდა რომ არც ამ ივენთების გავრცელება არ ხდება ტრადიციული(შვილიდან მშობლის მიმართულებით) მეთოდით.
გარკვეული კვლევა ძიების შემდეგ მივაგენი ისეთ ივენთებს(დიდი მადლობა PPK – ს) რომელთა ბაბლინგი IE – ში ისე მუშაობს როგორც საჭიროა. ეს ივენთებია onfocusin და onfocusout.
როგორ შეიძლება აღნიშნული ივენთების გამოყენება პრობლემის გადასაჭრელად? სანამ უშუალოდ კოდის წერას დავიწყებთ საჭიროა კარგად გავერკვეთ თუ როგორ მუშაობს onchange ივენთი HTML ფორმის ცალკეული ელემენტებისათვის და ასევე თუ რა გვერდის ავლის მექანიზმების გამოყენებაა შესაძლებელი IE – ში.
SELECT ელემენტი
ამ ელემენტის შემთხვევაში onchange ივენთი წარმოიშვება მხოლოდ იმ ჩამოსაშლელი სიიდან კონკრეტული ელემენტის ამორჩევის დროს. IE – ში იგივე ხდომილების ემულაციისათვის შესაძლებელია onclick ივენთის გამოყენება, თუმცა, ასეთ შემთხვევაში ივენთი ორჯერ წარმოიშვება ერთხელ ელემენტის გააქტიურებისას ხოლო მეორედ ჩამოსაშლელი სიიდან მნიშვნელობის არჩევისას. თუმცა ამ პრობლემის არიდება მარტივად არის შესაძლებელი სწორედ onfocusin და onfocusout ივენთების მეშვეობით რადგან ეს ორივე ივენთი წარმოიშვება onclick ივენთამდე, გამომდინარე აქედან შესაძლებელია წინა ივენთის ტიპის დამახსოვრება და შემდგომ უკვე დადგენა ეს იყო პირველი კლიკი თუ ჩამოსაშლელი მენიუდან ელემენტის არჩევა მოხდა?
INPUT text და TEXTAREA ელემენტები
ამ ელემენტების შემთხვევაში onchange ივენთი წარმოიშვება როდესაც ელემენტი კარგავს ფოკუსს. IE – ში იგივეს მიღწევა შესაძლებელია onfocusout ივენთის მეშვეობით.
INPUT checkbox და radio ელმენტები
ამ ელემენტების შემთხვევაში onchange ივენთი წარმოიშვება მათი მნიშვნელობის ცვლილების თანავე. IE – ში იგივე შედეგის მისაღებად მარტივად არის შესაძლებელი onclick ივენთის გამოყენება.
მაშ ასე წინა სამი პარაგრაფში გამოიკვეთა სამი ისეთი ივენთი რომელთა გამოყენებაც შესაძლებელია onchange ბაბლინგის ემულაციისათვის. ეს ივენთებია: onclick, onfocusin, onfocusout.
ამ ინფორმაციაზე დაყრდნობით მარტივად არის შესაძლებელი სულ რამდენიმე სტრიქონი კოდით გადავწყვიტოთ პრობლემა:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | (function() { var div = document.getElementById('testonchange'); //ყველა ბრაუზერი IE - ს გარდა if (document.addEventListener) { div.onchange = function(e) { //აქ შეგვიძლია გამოვიძახოთ ივენთის უშუალო ჰენდლერი }; } else { //IE - ს სპეციფიური რეალიზაცია var previousEvent = null; div.onfocusin = div.onfocusout = div.onclick = function() { var e = window.event, target = e.srcElement, isSelect = target.nodeName == 'SELECT', notTextInput = target.nodeName == 'INPUT' && /^radio|checkbox$/i.test(target.type), isTextInput = (target.nodeName == 'INPUT' && target.type == 'text') || target.nodeName == 'TEXTAREA', validElement = notTextInput || isSelect; if (isSelect && !target.size && /^focus(in|out)$/.test(previousEvent)) { validElement = null; } previousEvent = e.type; if ((e.type == 'click' && validElement) || (e.type == 'focusout' && isTextInput)) { //აქ შეგვიძლია გამოვიძახოთ ივენთის უშუალო ჰენდლერი } }; } div = null; })(); |
ეს არის და ეს
კოდის დეტალური გარჩევით თავს აღარ შეგაწყენთ, ხოლო რეალური დემონსტრაცია შეგიძლიათ იხილოთ აქ.
