ხშირად იყენებთ HTML ფორმის ელემენტების ამ ივენთს?
და რა შემთხვევაში? ალბათ უფრო SELECT ელემენტთან მუშაობისას ხომ? თქვენი არ ვიცი მაგრამ ჩემს პირად პრაქტიკაში განსაკუთრებული გამოყენება ამ ივენთს არ ჰქონია… თუმცა ორიოდე დღის წინ ყველაფერი შეიცვალა და ჩემთვის ერთი ფრიად საინტერესო აღმოჩენა გავაკეთე.
ასეთი რამ გინახავათ?
<div onchange="handleEvent()"> //some other markup </div>
დამეთანხმებით რომ ერთი შეხედვით ამ ივენთის DIV ელემენტთან გამოყენება ცოტა არ იყოს უცნაურია ხომ? რა ცვლილება უნდა მოხდეს ისეთი DIV ელემენტში რომ მისი დამუშავება მოვახდინოთ ამგვარი გზით? ან დავუშვათ და მოხდა ასეთი ცვლილება მაგრამ რანაირად?
მინდა გაგახაროთ და გითხრათ, რომ, პასუხი მარტივია. DIV ელემენტში არანაირი ასეთი ცვლილება არ მოხდება, მაგრამ, თუ მის შიგნით გვაქვს რადმენიმე SELECT და INPUT ელემენტი რომელთა ცვლილების კონტროლი გვესაჭიროება ეს კოდი მომენტალურად იდეალურ გადაწყვეტად იქცევა!
კლასიკურად უფრო სწორად ძველი სკოლის მიდგომით ასეთი ამოცანის გადაჭრის დროს ყველა, SELECT და INPUT ელემენტის onchange ივენთს მივანიჭებდით ჰენდლერს. თუმცა თუ გავიხსენებთ ფაქტს რომ DOM დოკუმენტში ხდომილება ვრცელდება საწყისი ელემენტისგან(ელემენტი რომელზეც უშუალოდ მოხდა ესა თუ ის მოვლენა) ანუ ელემენტების იერარქიაში ქვევიდან ზევით, ჩემს მიერ ნაჩვენები კოდიც მომენტალურად პრაქტიკულ დანიშნულებას შეიძენს. ამ ინფორმაციაზე დაყრდნობით შესაძლებელია ასეთი კოდის დაწერა:
1 2 3 4 5 6 7 8 9 10 |
ნაჩვენები კოდის შესაბამისი ამოცანა მდგომარეობს ყველა INPUT და SELECT ელემენტის onchange ივენთის დაჭერასა და შესაბამის დამუშავებაში. ნაცვლად იმისა რომ გამოვიყენოთ სათითაოდ ყველა ელემენტს onchange ივენთი, მარტივად შეგვიძლია გავაკეთოთ შემდეგი რამ:
1 2 3 4 5 6 7 8 9 10 11 12 13 | document.getElementById('container').onchage = function(e) { //მოვიპოვოთ Event ობიექტი e = e || window.event; //მოვიპოვოთ საწყისი ელემენტი რომელზეც უშუალოდ დაფიქსირდა ივენთი var targetElement = e.target || e.srcElement; //თუ ელემენტი არის SELECT ან INPUT ტიპის შევასრულოთ დანარჩენი სამუშაო if (/^input|select$/i.test(target.nodeName)) { //do something here } } |
დამეთანხმებით რომ ძალიან მარტივია ყველა ელემენტის ცვლილების ამდაგვარი ცენტრალიზებული კონტროლი. ეს არის ზუსტად ე.წ. Event Delegation მოდელი რომელიც ძალიან პოპულარულია დღესდღეობით. რატომ არ ვიცი მაგრამ ჩემთვის onchange ივენთი იმდენად ცალსახად იყო ასოცირებული ფორმის SELECT ელემენტთან რომ მისი ამდაგვარი გზით გამოყენების შესახებ არასოდეს მიფიქრია, თუმცა საბოლოო შედეგმა ყოველგვარ მოლოდინს გადააჭარბა.
იმედია ეს პირადად ჩემთვის ჭკუის სასწავლებელი შემთხვევა თქვენთვისაც სასარგებლო იქნება.
enjoy
ტეგები: JavaScript, JavaScript DOM, JavaScript WTF
ვა, კამფეტ! არ ვიცოდი. კარგია.
წამიერმა ტესტიერებამ ყველა ბროუზერში წარმატებით ჩაიარა გარდა IE-სი. მოვიცლი და ვნახავ.
მართლა კარგი რამეა ფორმების შევსების (და არა მარტო) კონტროლისას.
@ალეკო
არ ვიცი IE – ში არ გამიტესტავს ჯერ, მაგრამ სხვაგან ყველგან კარგად მუშაობს… როგორც ჩანს მომიწევს IE – სთვის გამოგონებების დამატება კოდისთვის
ეგ არის რა, რაღაცას აღმოაჩენ გაგეხარდება და… მერე მოვა IE და მოგი^(&^(&^(ს კარნავალში
ვაააა! სოსოჯან! ეს რა საინტერესო რაღაც დაწერე
არადა რო დაფიქრდე იდიოტიზმამდე მარტივია, მარა მეორეს მხრივ, იდიოტიზმი ეძახე და მე პირადად არც მომაფიქრდებოდა
მადლობა საინტერესო გადაწყვეტილებისათვის
@Gode
ეჰ შოთ.. ეგ “იდიოტიზმამდე მარტივი” რაღაც იდიოტიზმამდე მარტივ რეალობად მიქცია IE – მ
არ მუშაობს ეგ ყველაფერი IE – ში და გამოგონებები მომიწევს… ხოდა თუ გამოვიგონე რაიმე რეალური დავწერ აქ და თუ ვერ გამოვიგონე და მაგასაც ვაღიარებ
ძალიან საინტერესოა, ესეთი რაღაცის გაკეთება აქამდე აზრადაც არ მომივიდოდა
. IE ხო იმენა… ყველაზე მაგრად არ მიყვარს ის რომ onchange event-ი IE-ში checkbox-ზე ფოკუსის დაკარგვის შემდეგ ხდება მხოლოდ (ყოველ ჯერზე მავიწყდება) და ამის გადამკიდეს onclick-ის გამოყენება მიწევს ხოლმე
საშკა
მეც ზუსტად ეგრე ვარ
იძულებით onClick-ზე ვაკეთებ ივენთს.
მე ვიყენებ ფორმის შევსების კორექტულობის დროს და ხშირად ajax-ში, მაგალითად check username ამ შემთხვევაში ყოველ focus-ზე გაიგზავნება მოთხოვნა და ამ შემთხვევაში ონჩეინჯი ჯობია
ვააა, ძაალიან მაგარი რამეა
ამ კედელს შუბლი მაშინ მივარტყი, როდესაც მთელი ლოგიკა უკვე მზად მქონდა. იძულებული ვიყავი შემდეგი მაზოღიზმი გამომეყენა (ეს თუ jQuery-ის იყენებთ):
if ($.browser.msie) { $(':input:not(.button)').change(function(){ $(this).closest('.item-wrapper').trigger('change'); }) }სავარაუდოდ, იგივეს გამეორება pure javascript-შიც შეიძლება, ოღონდ ტარგეტ ელემენტის გადაცემა არ დამჭირვებია და შესაბამისად არ მიცდია. trigger ფუნქცია დამატებით data ელემენტსაც იღებს არგუმენტად, ანუ იდეაში შესაძლებელია შეჩოჩება.
@დავით
დიდი მადლობა სასარგებლო კომენტარისთვის.
ზუსტად მასე მომივიდა მეც
ძალიან დიდი ხანი ვწერე Mac – ზე ისე რომ PC არც გამხსენებია… რამდენიმე დღეში რომ მოვრჩი ყველაფერს და IE – ში გავტესტე გულს შემომეყარა
პრობლემა იმაში კი არ არის ეგ ყველაფერი ავამუშავო, უბრალოდ ძალიან მეზიზღება როდესაც ასეთ შემოვლითი გზებით მიწევს სიარული.
ზუსტ ქეისს აგიხსნი:
არის დიალოგი რომელიც სხვადასხვა ობიექტზე კლიკისას იხსნება და ობიექტის შესაბამის ოპციების ფორმას ტვირთავს სერვერიდან Ajax – ის გამოყენებით.
პრობლემა იმაშია რომ ეს ოპციების ფორმები არის ძალიან რთული და ზოგი საშუალოდ 30/50 ინფუთ ელემენტს შეიცავს.
პოსტში აღწერილი სოლუშენის ძებნა სწორედ მაგის გამო დავიწყე რომ არ მინდოდა სათითაოდ ყველა Ajax რიქვესტის დასრულების შემდეგ სათითაო ინფუთ ელემენტისათვის onchange ივენთების ბაინდინგი მეკეთებინა
ბუნებრივად დამებადა აზრი რომ ეს ივენთები(არა მარტო change) უნდა დამეჭირა მშობელი კონტეინერის გამოყენებით.. თუმცა
IE – ს სპეციფიკადან გამომდინარე რამდენიმე სერიოზული მიზეზია რის გამოც არ მინდოდა სათითაო ელემენტის ჩამორბენა და onchange ივენთის მიბმა:
1) მსგავს კომპლექსურ ფორმებზე მაგ მანიპულაციის ჩატარება ნელია;
2) IE – ში DOM ელემენტზე მიბმული ივენთ ჰენდლერები პოტენციურად memory leak – ების გამომწვევია, ამითომ ოპციების ფორმის ხელახალი ჩატვირთვისას წინა ფორმის ყველა ელემენტის ჩამოვლა და მიბმული ჰენდლერების გა – null – ებაა საჭირო რომ ავირიდოთ თავიდან აღნიშნული პრობლემა
განსაკუთრებით ეს ბოლო ოპერაციაა ნელი რადგან რეკურსიუალდ მთელი იმ კონტეინერის DOM ხე უნდა გავიაროთ და სათითაო ელემენტის ყოველი attributes კოლექცია ვამოწმოთ …
და ასე შემდეგ და ასე შემდეგ
მოკლედ IE დაწყევლილია და ასეთივე დაწყევლილად დარჩება
P.S.
შენი პოსტი შემთხვევით წამეშალა და მე მივაპოსტე ხელმეორედ საბედნიეროდ იმეილში იყო
იმედია ჩემი რეალიზაცია არ დაინგრევა ამ memory leak-ის გამო, იმიტომ რომ გადაწერის თავი ეხლა უკვე ნამდვილად არა მაქვს
@დავით
არა, არ მგონია შენი რეალიზაციის გადაწერა გახდეს საჭირო. jQuery – ს საკმაოდ კარგი იმპლემენტაცია აქვს, ე.წ. internal storage აქვს ივენთ ჰენდლერების და მარტივად მოგვარებადია მეხსიერების პრობლემები. ამ შემთხვევაში არ მქონდა მე მასე და მომიწია დამატებითი ოფლის დაღვრა