ვებ დოკუმენტის (ან მისი რომელიმე ნაწილის) კლიენტის მხარეს დამუშავებისას გარდაუვალია დოკუმენტის ელემენტებთან მუშაობა. დღესდღეობით დოკუმენტის ელემენტებთან მუშაობის ორი ყველაზე გავცელებული ე.წ. DOM ფუნქცია არსებობს ერთი ესენია: 1) document ობიექტის getElementById(“element-id”) მეთოდი რომელიც აბრუნებს ელემენტს მითითებული უნიკალური იდენტიფიკატორით (ელემენტის id ატრიბუტის მნიშვნელობა); 2) ელემენტის getElementsByTagName(“tagname”) მეთოდი რომელიც აბრუნებს ელემენტის ქვემდგომ იერარქიაში არსებულ ყველა “tagname” პარამეტრის შესაბამის ელემენტს.
აღნიშნული ორი მეთოდი საკმაოდ ეფექტურად მუშაობს მარტივ შემთხვევებში თუმცა არსებობს რამდენიმე უარყოფითი დეტალიც:
- შეუძლებელია (და არც არის სასურველი. იხ. CSS სელექტორების მინიმიზაცია) რომ დოკუმენტში ყველა ელემენტს გააჩნდეს უნიკალური იდენტიფიკატორი;
- გამომდინარე პირველი მიზეზიდან ყოველთვის როდესაც კი დაგვჭირდება ელემენტის ქვეშ მყოფი რომელიმე ელემენტის მოპოვება მისი ტეგის დასახელების მიხედვით გვიწევს უამრავი არასაჭირო იტერაციის განხორციელება;
მსგავსი ტიპის ამოცანების უფრო მოქნილი ხერხებით გადასაჭრელად არსებობს სპეციალური ენა სახელად XPath. თავისთავად ამ ენის დანიშნულება მდგომარეობს იმაში რომ მარტივად მოვიპოვოთ ინფორმაცია XML დოკუმენტში არსებული რომელიმე ელემენტის შესახებ.
არსებობს თუ არა XPath – ის მხარდაჭერა თანამედროვე ბრაუზერებში? დიახ არსებობს… თუმცა თავსებადობა სხვადასხვა რეალიზაციებს შორის საკმაოდ უხარისხოა.
არსებობს თუ არა რაიმე მზა ბიბლიოთეკები რომლებიც თავიდან აგვარიდებს არსებულ არათავსებადობის პრობლემებს? დიახ არსებობს… მაგრამ რამდენად საჭიროა ყოველი ამოცანისათვის მსგავსი ბიბლიოთეკების გამოყენება? პირადად ჩემის აზრით ამის არანაირი აუცილებლობა არ არსებობს… ხშირ შემთხვევაში საკმაოდ მარტივი გამოსავალიც საკმარისია მიზნის მისაღწევად.
მაგალითად შემდეგი XML დოკუმენტიდან თუ გვსურს ამოვიღოთ “Ann Smith” – ის შესაბამისი sex ელემენტი, XPath გამოსახულებას ექნება ასეთი სახე: “/persons/person[1]/name” (person[1] – აქ იგულისხმება მეორე person ელემენტი რადგან ელემენტების ინდექსაცია იწყება 0 – იდან):
<persons>
<person>
<name>John Doe</name>
<sex>M</sex>
</person>
<person>
<name>Ann Smith</name>
<sex>F</sex>
</person>
</persons>
ამ მარტივი მაგალითიდან კარგად ჩანს თუ რამდენად მარტივია დოკუმენტთან მუშაობა XPath – ის მეშვეობით და რამდენი არასაჭირო კოდის დაწერა დაგვჭირდებოდა იგივე შედეგის მისაღწევად JavaScript – ის სტანდარტული DOM მეთოდების გამოყენებით.
როგორ მივაღწიოთ იგივე შედეგს JavaScript – ით? რადგან ლაპარაკი გვაქვს მარტივ რეალიზაციაზე ჩემს შემთხვევაში საყრდენ წერტილად ავიღე ელემენტის უნიკალური იდენტიფიკატორი, ასეთი ელემენტი აუცილებლად საჭიროა რადგან უმეტეს შემთხვევაში სწორედ კონკრეტული ელემენტის ქვეელემენტებთან მოგვიწევს მუშაობა.
მაგალითად თუ გვაქვს მსგავსი (X)HTML კოდი:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
და გვსურს რომ ამოვიღოთ ქვემენიუს “Sub Menu Item Two” ელემენტი გამოსახულებას ექნება ასეთი სახე: “#test-id/ul/li[2]/ul/li[1]“; გამოსახულება თავსითავად მარტივია თუმცა ზოგიერთ დეტალზე ღირს ყურადღების მიქცევა:
- თუ გვსურს რომ მეთოდმა გადაცემული სტრიქონი მიიღოს XPath გამოსახულებად იგი აუცილებლად უნდა იწყებოდეს # სიმბოლოთო და კონკრეტული ელემენტის უნიკალური იდენტიფიკატორით (მაგ. #test-id);
- ქველემენტების მიმართვა ხდება შემდეგნრაირად: /ul (სლეში და ელემენტის ტეგის სახელი) და იგულისხმება პირველივე მითითებული ტიპის ტეგი;
- კონკრეტული ქველემენტის ამოღება ინდექსით განისაზღვრება შემდეგნაირად: li[2] (ელემენტის დასახელება და შესაბამისი ინდექსი, ამ შემთხვევაში იგულისხმება მესამე li ელემენტი);
თავისთავად ფუნქციის გამოიყურება შემდეგნაირად იგი პარამეტრად ღებულობს სტრიქონს, რომელიც არის ან უბრალოდ ელემენტის უნიკალური იდენტიფიკატორი ან XPath – ის მსგავსი გამოსახულება:
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 42 43 44 | var Util = { dom: { get: function(expression) { //check if passed argument is XPath like expression if (str.substr(0, 1) == '#') { expression = expression.substr(1); var tokens = expression.split('/'); var id = tokens.shift(); //retrive desired element var el = document.getElementById(id); var pattern = /(\w+)\[(\d+)\]/; var match, child; if (el) { for (var i = 0; i<tokens.length; i++) { if ((match = tokens[i].match(pattern)) != null) { for (var j = 0, index = 0; j < el.childNodes.length; j++) { child = el.childNodes[j]; if (child.tagName && child.tagName.toLowerCase() == match[1]) { if (match[2] == index) { el = child; break; } index++ } } } else { el = el.getElementsByTagName(tokens[i]).item(0); } } } //return found element return el; } else { //if expression parameter is simple string just return element return document.getElementById(expression); } } } }; //Usage sample alert(Util.dom.get('#test-id/ul/li[2]/ul/li[1]').innerHTML); alert(Util.dom.get('#test-id/ul/li[2]/ul/li').innerHTML); |
თავისთავად ეს მარტივი რეალიზაცია შორს დგას იდეალურისგან, თუმცა მთელ რიგ შემთხვევებში საკმაოდ მოსახერხებელია მისი გამოყენება… ასევე უფრო მეტად განვითარებაც არ არის რთული, თუმცა ხაზს ვუსვავ რომ უფრო რთული და კომპლექსური შემთხვევებისათვის უმჯობესია ბროუზერებში არსებული შესაბამისი საშუალების გამოყენება მიუხედავად იმისა რომ არსებობს თავსებადობის პრობლემები.
ტეგები: JavaScript, JavaScript DOM, XHTML