📜 ⬆️ ⬇️

My convenient bike (Javascript interface) for navigating through an XML document

I have such fun - "bike". No, it's not about environmentally friendly transport. I like to invent something new. But when the topic is already hackneyed, and the task has already been solved so many times in all sorts of variations, the search for even a new, but next solution is a “bicycle”. Well, you understand. Another bike ... In practice, for me, this is one of the main ways of learning.

I decided to thoroughly deal with JavaScript (I used it often before, but only because of need, with bio-additives and vitamins, in the form of a dish called JQuery). The result seemed interesting to me, but due to reading about ElementTraversal , I decided that it might be interesting to someone else ...

from = new Target;

//
node = from.next().inner().previous().previous().get();


About how I lived up to this ...

')
I have such fun - "bike". No, it's not about environmentally friendly transport. I like to invent something new. But when the topic is already hackneyed, and the task has already been solved so many times in all sorts of variations, the search for even a new, but next solution is a “bicycle”. Well, you understand. Another bike ... In fact, for me, this is one of the main ways of learning.

The first thing I want to say is that I am not a programmer (although I also have a degree in computer technology). I am a designer (now officially called the art director, but the essence is the same), in the broadest sense of the word (and not the graphic artist, with whom in our country it is customary to associate this profession, although, again, I have an art education and about twenty certificates in various national crafts, which he studied in school years). Speaking more simply, I consider my main professional skill to be the ability to find an original, and ideally optimal, solution to the problem. And, “bicycle” is an integral part of the process. And the purpose of this lyrical digression is to try to draw your attention, not to the characteristics of the attached code, but to the characteristics of the proposed approach.

Initially, of course, due to the need for lotto and grammar-school girls (so that they could be used cross-browserly and, if necessary, could be used in other languages, after a minimal modification), decided to use DOM for these purposes (you might think there were more options). After disposing of the relevant waste paper, on the topic “how others live”, I realized that there are not many approaches besides using the DOM in its pure form, which is quite tiresome: five corresponding functions from John Resign's “ProJavaScript”, already mentioned ElementTraversal (in fact, the same five functions plus one more, for getting the number of children), well, or trying XML Simple in PHP. As for me, it is either possible or clearer, or less monstrous.

Then there were the creative torments (as an integral part of the creative process), periodically interrupted by cries: “Sssss ... and! Why doesn’t it work! ” And so on, which is hardly of interest to you. So, finally, the result.

The class for storing the reference to the element and the necessary functions for working with it (by default, the root element of the document is set):

// Target
Target = function ( element ) {
var _element = element || document.documentElement;
this.get = function () { return _element }
this.set = function ( element ) { _element = element || document.documentElement }
}


The method for finding the element that precedes the current one (or the element passed to the method as a parameter), with the amendment that the set is considered cyclic, that is, the last element in the set is considered previous with respect to the first:

// previous
Target.prototype.previous = function ( element ) {
var element = element || this.get();
if( element != document.documentElement.parentNode ) {
element = element.previousSibling || element.parentNode.lastChild;
while( element && element.nodeType != 1 ) { element = element.previousSibling }
}
this.set( element );
return this;
}


The method for finding the element following the current one (or the passed method as a parameter) is, in its effect, the opposite of the one described earlier:

// next
Target.prototype.next = function ( element ) {
var element = element || this.get();
if( element != document.documentElement.parentNode ) {
element = element.nextSibling || element.parentNode.firstChild;
while( element && element.nodeType != 1 ) { element = element.nextSibling }
}
this.set( element );
return this;
}


Method for finding the parent (external) element, with respect to the current (or passed to the method as a parameter):

// outer
Target.prototype.outer = function ( element ) {
var element = element || this.get();
if( element.parentNode != document.documentElement.parentNode ) { element = element.parentNode }
this.set( element );
return this;
}


Method for finding the first child (internal) element, with respect to the current (or passed method as a parameter):

// inner
Target.prototype.inner = function ( element ) {
var element = element || this.get();
if( element.childNodes.length != 0 ) {
for( var i = 0; i < element.childNodes.length; i++ ) {
if( element.childNodes.item( i ).nodeType == 1 ) {
element = element.childNodes.item( i );
break;
}
}
}
this.set( element );
return this;
}


Methods change the link inside an instance of a class whose value can be obtained, as can be seen from the code by means of the get () method and set by the set () method. The object itself is returned as its work (oh yes, jQuery traumatized my psyche, and not only mine, I think).

Result:

from.next().inner().previous().previous().get();

Then after using it in practice (in subsequent experiments with JavaScript, and later with transferring this mechanics to Ruby and PHP, where I used it in parsing XML documents), another method appeared, which I see (or rather the format of the template transmitted to it in as a parameter) and is what may be of interest to you (and therefore the reason for writing this article on Habré). The method for performing a sequence of actions according to a pattern (similar to “the first car from the center, left, left, up to the pillar is right there”), in which the transition to the parent element corresponds to the “<” symbol, the first child “>” preceding “- ", The following" + "(example: the chain .outer (). Next (). Inner (). Previous (). Previous () corresponds to the template" <+> - "):

// select
Target.prototype.select = function ( path ) {
var steps = path.split( "" );
for( var i = 0; i < steps.length; i++ ) {
if( steps[ i ] == "-" ) { this.previous() }
if( steps[ i ] == "+" ) { this.next() }
if( steps[ i ] == "<" ) { this.outer() }
if( steps[ i ] == ">" ) { this.inner() }
}
return this;
}


The previous example can be rewritten as:

from = new Target;

// a, , (, ),
node = from.select( “+>--” ).get();


Afterword: there is a thought to add the ability to specify the number of iterations in the template (so that instead of “>>> ++++++” write “> 3 + 6”), but not yet implemented.

One more epilogue: in general, who are interested in such epics, is it worth writing like this in the future or is it not a place like lyrics on Habré?

Source: https://habr.com/ru/post/94206/


All Articles