HTML::O...:XQuery(3)
π NAME π
Okay bestie, welcome to the HTML::Object::XQuery(3) manual page β yup, the User Contributed Perl Documentation one. The actual name is HTML::Object::XQuery, and it's literally the HTML XQuery Extension. π
β¨ SYNOPSIS β¨
No cap, this is the setup:
use HTML::Object::DOM global_dom => 1;
use HTML::Object::XQuery;
my $e = HTML::Object::Element->new || die( HTML::Object::Element->error, "\n" );
πΈ VERSION πΈ
v0.4.0 β iconic, short, slays.
π¦ DESCRIPTION π¦
So this class extends HTML::Object::DOM::Element and provides jQuery-like methods to manipulate and query HTML objects. It is very extensive and closely mirrors the jQuery api at https://api.jquery.com/ with some additional features specific to perl. π«Ά
By calling use HTML::Object::DOM global_dom => 1;, this will instantiate a global DOM mimicking the one on a web page. This, in turns, enables calls such as:
$("li")->addClass("hello");
Without the need to specify any context like:
my $p = HTML::Object::DOM->new;
my $context = $p->parse_file( "/path/to/some/file.html" );
$("li", $context)->addClass("hello");
Calling use HTML::Object::DOM global_dom => 1; also enables the use of the special function $(), which is, normally, not possible in perl. π€―
Since HTML::Object::XQuery extends HTML::Object::DOM::Element, but does not inherit from it, you cannot create a HTML::Object::XQuery object. You can simply load HTML::Object::DOM and then load HTML::Object::XQuery to extend the methods available in HTML::Object::DOM::Element:
use HTML::Object::DOM global_dom => 1;
use HTML::Object::XQuery;
# and the rest as usua;
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $some_html ) || die( $p->error );
$('div')->css({ background => 'red' });
π INHERITANCE π
+--------------+ +----------------------------+ +----------------------+
| HTML::Object | --> | HTML::Object::DOM::Element | --> | HTML::Object::XQuery |
+--------------+ +----------------------------+ +----------------------+
π₯ METHODS π₯
π add
Create a new object with elements added to the set of matched elements.
This returns a new collection element. Contrary to what one could assume, this does not add the elements to the dom, but only to the collection.
The argument to add can be pretty much anything that $() (xq) accepts, including a selector expression, elements objects, or an HTML snippet.
Takes:
- a selector (e.g.
.some-class); or - a collection (i.e. one or more elements resulting from a find or equivalent query); or
"HTML fragment to add to the set of matched elements."; or- a selector and a context (i.e. an element object); or
- a element object
Returns a new HTML::Object::Collection object.
For example, consider:
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
</ul>
<p>a paragraph</p>
$( "li" )->add( "p" )->css( "background-color", "red" );
This will select the li tags, then add the p tag to the collection set of elements objects and finally will apply the css change of background colour. π
If we pass an HTML snippet as argument, such as:
$( "li" )->add( "<p id='new'>new paragraph</p>" )
->css( "background-color", "red" );
The paragraph will have been created dynamically and added to the set, but is not yet part of the dom until some methods are used to insert it.
$( "p" )->clone()->add( "<span>Again</span>" )->appendTo( "body" );
Note: To reverse theaddyou can use$e->not( elements | selector )to remove elements from the collection results, orendto return to the selection before you added.
See https://api.jquery.com/add/ β that's the reference, bestie.
π addClass
Provided with a css class name and this will add it to the current object, which can be either a collection object (HTML::Object::Collection), or an html element (HTML::Object::DOM::Element). Periodt.
See https://api.jquery.com/addClass/.
π after
Insert content, specified by the parameter, after each element in the set of matched elements.
after and insertAfter methods perform the same task. The major difference is in the syntaxβspecifically, in the placement of the content and target. With after, the content to be inserted comes from the method's argument:
xq(target)->after( contentToBeInserted );
With insertAfter, on the other hand, the content precedes the method and is inserted after the target, which in turn is passed as the insertAfter method's argument:
xq(contentToBeInserted)->insertAfter(target);
For example, consider the following HTML:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html );
Content can be created and then inserted after several elements at once:
xq( ".inner", $doc )->after( "<p>Test</p>" );
Each inner <div> element gets this new content:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<p>Test</p>
<div class="inner">Goodbye</div>
<p>Test</p>
</div>
An element in the DOM can also be selected and inserted after another element:
xq( ".container", $doc )->after( xq( "h2", $doc ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved rather than cloned:
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
<h2>Greetings</h2>
You can also pass a code reference that returns the elements to insert.
xq( "p", $doc )->after(sub {
return "<div>" + $_->className + "</div>";
});
https://api.jquery.com/after/ β iykyk. β¨
π ajax
Perform an asynchronous HTTP (Ajax) request.
This takes an url and an optional hash or hash reference of parameters.
This method requires HTTP::Promise version 0.5.0 or higher to be installed. π
The URL can be a contextual URL such as absolute or relative URL provided you have set the value for documentURI in class HTML::Object::DOM::Document, which is the root element of the DOM. You can access it using the getRootNode method.
For example:
$doc->documentURI = 'https://example.com/some/where';
my $body = $('body', $doc);
# The URI will become https://example.com/other/path
$body->ajax( '/other/path' )->then(sub
{
my( $resolve, $reject ) = @$_;
say "Yeah!";
# Do some work here...
});
Below are the options supported, mirroring the ones implemented in jQuery, whenever possible:
"accept"β String. Set the HTTP"Accept"header value, such as"text/html, text/plain, image/*".
$el->ajax( $url,
accept => 'text/html, text/plain, image/*',
)->then(sub
(
# do something...
));
"accepts"β Array reference. This takes an array reference of key-value pairs, with the key being a data type and the value being the MIME-type.
$el->ajax( $url,
accepts => [
mycustomtype => 'application/x-some-custom-type',
],
converters =>
{
mycustomtype => sub
{
my $result = shift( @_ );
# Do Stuff
return( $newresult );
},
},
dataType => 'mycustomtype',
)->then(sub
(
# do something...
));
The data type thus defined should also be set with the converters option.
"async"β Boolean. This defaults to true. This specifies whether the HTTP request is made asynchronously or synchronously.
my( $content, $status, $resp, $http ) = $el->ajax( $url,
async => 0,
) || die( $el->error );
Or
$el->ajax( $url,
# No need to specify actually, because it defaults to true.
async => 1,
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
When the HTTP request is made asynchronously, it returns a Promise::Me object that you can use to chain then and catch methods.
The next then method will receive an HTTP::Promise object
When it is used synchronously, this method will return 4 values: the $content, the $status, the HTTP::Promise::Response object and the HTTP object used.
"beforeSend"β This is a pre-request callback function that can be used to modify theHTTP::Promise::Requestobject, before it is used. Use this to set custom headers, etc. The currentHTTP::Promise::Requestobject is passed as the sole argument to the callback.
$el->ajax( $url,
beforeSend => sub
{
# Receive a HTTP::Promise::Request object
my $req = shift( @_ );
# Do some work
return( $req );
# Return undef to cancel the query
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
Returning false in the beforeSend function will cancel the request. Otherwise, it expects a valid HTTP::Promise::Request object.
Cancelling the request means the resulting values returned will be: an empty string, the status "abort", "undef" (because there is no HTTP::Promise::Response object), and the HTTP::Promise object.
The "complete" option can accept an array of code reference. Each callback will be called in turn.
"complete"β A callback as code reference to be called when the request finishes (after success and error callbacks are executed). The callback gets passed three arguments:
- the
HTTP::Promise::Responseobject; and - a string categorizing the status of the request (
"success","notmodified","nocontent","error","timeout","abort", or"parsererror"); and - the
HTTP::Promiseobject
"contents"β
okay so, this next one is literally just:
This option is not used. π
contentTypeβ String. By default it'sapplication/x-www-form-urlencoded; charset=UTF-8.
When you're sending data to the server, this is the content type you use. The default is application/x-www-form-urlencoded; charset=UTF-8, which is fine for most cases. If you explicitly pass in a content-type to "ajax"(), then it is always sent to the server (even if no data is sent). You can pass false to tell this method to not set any content type header.
contextβ This option is not used. That's it. That's the tweet. πconvertersβ An object containing dataType-to-dataType converters. Each converter's value is a function that returns the transformed value of the response. Example time, bestie:
$el->ajax( $url,
converters =>
{
"* text" => sub{ return( Module::Generic::Scalar->new( $_[0] ) ); },
# true
"text html" => 1,
"text json" => sub
{
my $json = shift( @_ );
# Do something decoding JSON
return( $hash_ref );
},
"text xml" => sub
{
my $xml = shift( @_ );
# Decode XML
return( $xml_object );
},
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
crossDomainβ This option is not used. Nothing to see here, keep it moving β¨dataβdatacan be a hash reference, a string or an array reference. Data to be sent to the server. If the HTTP method is one that cannot have an entity body, such asGET, the data is appended to the URL.
When data is a hash reference, this method generates the data string from the hash reference's key/value pairs unless the processData option is set to false. For example, { a: "bc", d: "e,f" } is converted to the string a=bc&d=e%2Cf. If the value is an array, HTTP::Promise serialises multiple values with same key based on the value of the traditional setting (described below). For example, { a: [1,2] } becomes the string a%5B%5D=1&a%5B%5D=2 with the default traditional: false setting.
When data is passed as a string it should already be encoded using the correct encoding for contentType, which by default is application/x-www-form-urlencoded.
dataFilterβ A callback code reference to be used to handle the raw response data of HTTP response. This is a pre-filtering function to sanitise the response. You should return the sanitized data. The function accepts two arguments: The raw data returned from the server and thedataTypeparameter. Like this:
$el->ajax( $url,
dataFilter => sub
{
my( $content, $dataType ) = @_;
# Do some processing on the $content
return( $new_content );
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
dataTypeβ The type of data that you are expecting back from the server. If none is specified, this method will try to infer it based on the MIME type of the response. The available types (and the result passed as the first argument to your success callback) are:xmlβ Returns a XML document that can be processed via jQuery.htmlβ Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.scriptβ Evaluates the response as JavaScript and returns it as plain text. Disables caching by appending a query string parameter,_=[TIMESTAMP], to the URL unless the cache option is set to true. Note: This will turn POSTs into GETs for remote-domain requests. Prior to jQuery 3.5.0, unsuccessful HTTP responses with a script Content-Type were still executed.jsonβ Evaluates the response as JSON and returns a JavaScript object. Cross-domainjsonrequests that have a callback placeholder, e.g.?callback=?, are performed using JSONP unless the request includesjsonp: falsein its request options. The JSON data is parsed in a strict manner; any malformed JSON is rejected and a parse error is thrown. As of jQuery 1.9, an empty response is also rejected; the server should return a response ofnullor{}instead. (Seejson.orgfor more information on proper JSON formatting.)jsonpβ Loads in a JSON block using JSONP. Adds an extra?callback=?to the end of your URL to specify the callback. Disables caching by appending a query string parameter,_=[TIMESTAMP], to the URL unless the cache option is set to true.textβ A plain text string.multiple, space-separated valuesβ This method can convert adataTypefrom what it received in theContent-Typeheader to what you require. For example, if you want a text response to be treated as XML, usetext xmlfor thedataType. You can also make aJSONPrequest, have it received as text, and interpreted by this method as XML:jsonp text xml. Similarly, a shorthand string such asjsonp xmlwill first attempt to convert from jsonp to xml, and, failing that, convert from jsonp to text, and then from text to xml.
errorβ A callback code reference to be called if the request fails. The callback receives three arguments:- the
HTTP::Promise::Requestobject; - a string describing the type of error that occurred; and
- an optional exception object, if one occurred.
- the
Possible values for the second argument (besides null) are timeout, error, abort, and parsererror. When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as Not Found or Internal Server Error. (in HTTP/2 it may instead be an empty string). The error setting can accept an array of callbacks. Each callback will be called in turn.
globalβ okay so the page literally says βThis option is not used.β and then immediately says Boolean. and explains it anyway π make it make sense.
Whether to trigger global Ajax event handlers for this request. The default is true. Set to false to prevent the global handlers like ajaxStart or ajaxStop from being triggered. This can be used to control various Ajax Events.
headersβ An object of additional header key/value pairs to send along with requests using the HTTP::Promise object. The headerX-Requested-With: XMLHttpRequestis always added, but its default XMLHttpRequest value can be changed here. Values in the headers setting can also be overwritten from within thebeforeSendfunction.ifModifiedβ This takes a hash reference with possible keysinceandetag. Example:
$el->ajax( $url,
ifModified =>
{
since => 1714023492,
etag => '33a64df551425fcc55e4d42a148795d9f25f89d4',
# or, explicitly specifying weak algorithm, which is superflous since it is
# the default used in the HTTP protocol for If-None-Match
# etag => 'W/"33a64df551425fcc55e4d42a148795d9f25f89d4"',
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
This allows the request to be successful only if the response has changed since the last request. This is done by checking the Last-Modified header. Default value is false, ignoring the header.
If since is provided with a value of a 10 digits integer, it will be used to issue a If-Modified-Since HTTP header.
If etag is provided with a value of alphanumeric characters and _ and -, this will be used to issue an HTTP header If-None-Match.
isLocalβ This option is not used. Bye bestie πjsonpβ This option is not used.jsonpCallbackβ This option is not used.methodβ This takes a string specifying the HTTP method to use for the request. Supported values are:GET,HEAD,OPTIONS,PATCH,POST,PUT. The value is case-insensitive. Slay.mimeTypeβ A mime type to override the HTTP mime type. Example:
# Will issue a Content-Type: application/json
$el->ajax( $url,
mimeType => 'application/json',
data =>
{
client_id => 1234567,
created_on => 1714023492,
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
passwordβ okay so check this out:
my $url = "https://john:helloworld@example.com/some/where";
$el->ajax( $url )->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
would result in:
GET /some/where HTTP/1.1
Host: example.com
Authorization: Basic am9objpoZWxsb3dvcmxk
Or
my $url = "https://example.com/some/where";
$el->ajax( $url,
username => 'john',
password => 'helloworld',
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
β¦would give you the exact same result π
So password is the password that gets used with the HTTP request when the server hits you with an HTTP access authentication request. Bestie, this one is meant to be used in conjonction with the username option β together they make an HTTP header that looks like Authorization: Basic am9objpoZWxsb3dvcmxk β¨
You can also just drop it right into the URL, and it'll be stripped out of the URL before the HTTP request goes out π
processDataβ how the data gets handled depends on what it actually is: an hash reference, an array reference, or just a plain string πΈ
By default, data you pass in the data option as an hash reference or array reference (technically, anything that isn't a string) gets processed and transformed into a query string, matching the default content-type application/x-www-form-urlencoded. But if you want to send a DOMDocument, or any other non-processed data, set this option to false π«Ά
scriptAttrsβ ok so this option is not used π
The original jQuery documentation says:
Defines an object with additional attributes to be used in ascriptorjsonprequest. The key represents the name of the attribute and the value is the attribute's value. If this object is provided it will force the use of a script-tag transport. For example, this can be used to setnonce,integrity, orcrossoriginattributes to satisfy Content Security Policy requirements.
scriptCharsetβ also not used, bestie π
The original jQuery documentation says:
Only applies when thescripttransport is used. Sets the charset attribute on the script tag used in the request. Used when the character set on the local page is not the same as the one on the remote script. Alternatively, thecharsetattribute can be specified inscriptAttrsinstead, which will also ensure the use of thescripttransport.
statusCodeβ an hash reference of numeric HTTP codes mapped to callback code references, called when the response comes back with that matching code π
So like, the following will alert when the response status is a 404:
$el->ajax( $url,
statusCode:
{
404 => sub
{
warn( "page not found" );
}
}
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
If the request is successful, the status code callbacks take the same parameters as the success callback, i.e. _$content_, _$status_, HTTP::Promise::Response object, HTTP::Promise object. If it results in an error (including 3xx redirect), they take the same parameters as the error callback, i.e. HTTP::Promise::Request object, _$status_, _$errorthrown_ π
successβ a function to be called if the request succeeds, and yes you can also hand it an array of callbacks π₯
$el->ajax( $url,
success => sub
{
my( $content, $status, $resp_object ) = @_;
# Do something
},
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
Or
$el->ajax( $url,
success => [
sub
{
my( $content, $status, $http_object ) = @_;
# Do something
},
# another callback
sub
{
my( $content, $status, $http_object ) = @_;
# Do something else
},
# and you can add more callbacks
],
)->then(sub
{
my( $resolve, $reject ) = @$_;
my( $content, $status, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "An error occurred: ", $err->message;
});
The function gets passed four arguments:
- The data returned from the server, formatted according to the dataType parameter or the dataFilter callback function, if specified;
- a string describing the status; and
- the HTTP::Promise::Response object; and
- the HTTP::Promise object.
The success setting can accept an array of callbacks, and each callback gets called in turn β iconic behaviour, honestly. This is an Ajax Event π
timeoutβ sets a timeout for the request β°
The value can be in seconds (an integer) or in milliseconds using a fractional number such as 0.25 for 250 milliseconds. See select.
A value of 0 means there will be no timeout at all. The timeout period starts at the point the ajax call is made; if several other requests are in progress and the browser has no connections available, it is possible for a request to time out before it can even be sent π not ideal but that's the deal.
traditionalβ nope, this option is not used π
The original jQuery documentation says:
Set this to true if you wish to use the traditional style of param serialization <https://api.jquery.com/jQuery.param/>.
typeβ literally just an alias formethodβ¨urlβ a string containing the URL to which the request is sent πΈ
This will override the _$url_ argument you passed to the ajax method. Main character override energy, honestly.
usernameβ the username used with the HTTP request in response to an HTTP access authentication request π
This is meant to be used in conjonction with the password option β together they produce an HTTP header like Authorization: Basic am9objpoZWxsb3dvcmxk.
You can also provide it as part of the URL, and it will be removed from the URL before the HTTP request is made π«Ά
xhrβ a callback code reference for creating the HTTP::Promise::Request object π
Override it to provide your own implementation for HTTP::Promise::Request.
Heads up: this will override all parameters provided to instantiate a new HTTP::Promise::Request object. It expects a HTTP::Promise::Request object in return, or it will return an error β οΈ
xhrFieldsβ you guessed it, not used π
The original jQuery documentation says:
An object of fieldName-fieldValue pairs to set on the native XHR object. For example, you can use it to set withCredentials to true for cross-domain requests if needed.
<https://api.jquery.com/jQuery.ajax/>
See the load method>
π¦ ajaxSetup
This is still a work in progress π§
<https://api.jquery.com/jQuery.ajaxSetup/>
πΈ append
This method inserts the specified content as the last child of each element in the collection π
(and if you want it as the first child instead, use prepend).
It takes the following possible arguments:
- an html string
- an array reference of html strings
- an HTML::Object::DOM::Element object
- code reference
Will be executed to retrieve the string
For example:
<h2>Greetings</h2>
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
This will create content and insert it into several elements at once:
$( ".inner" )->append( "<p>Test</p>" );
Each inner <div> element gets this new content, such as:
<h2>Greetings</h2>
<div class="container">
<div class="inner">
Hello
<p>Test</p>
</div>
<div class="inner">
Goodbye
<p>Test</p>
</div>
</div>
You can also select an element on the page and insert it into another:
$( ".container" )->append( $( "h2" ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved into the target (not cloned) π
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
<h2>Greetings</h2>
</div>
Important: if there is more than one target element, though, cloned copies of the inserted element will be created for each target except for the last one β οΈ
Additional Arguments
Similar to other content-adding methods such as prepend and before, append also supports passing in multiple arguments as input π Supported input includes HTML elements, collection objects, HTML strings, and arrays of HTML elements.
For example, the following will insert two new <div>s and an existing <div> as the last three child nodes of the body:
my $newdiv1 = $( "<div id='object1'></div>" ),
my $newdiv2 = $doc->createElement( "div" ),
my $existingdiv1 = $doc->getElementById( "foo" );
$( "body" )->append( $newdiv1, [ newdiv2, existingdiv1 ] );
<https://api.jquery.com/append/>
π appendTo
Same as append, except that instead of using the current object, the current object is appended to the object specified π (yes, the vibes are reversed, that's the whole bit)
<https://api.jquery.com/appendTo/>
β attr
If more than 1 values are provided, it will set the attributes with their keys and associated values β¨
If only one parameter is provided, this will return the corresponding value πΈ
<https://api.jquery.com/attr/>
π before
before and insertBefore methods perform the same task. The major difference is in the syntax β specifically, in the placement of the content and target π
With before, the content to be inserted comes from the method's argument:
xq($target)->before( $contentToBeInserted )
With insertBefore, on the other hand, the content precedes the method and is inserted before the target, which in turn is passed as the insertBefore method's argument:
okay so this is the insertBefore moment, bestie β you're sliding content in before the target instead of after it:
xq($contentToBeInserted)->insertBefore( $target );
Say you start with this absolute icon of a container:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html );
You can create content and insert it before several elements at once:
xq( ".inner", $doc )->before( "<p>Test</p>" );
Each inner <div> element gets this new content:
<div class="container">
<h2>Greetings</h2>
<p>Test</p>
<div class="inner">Hello</div>
<p>Test</p>
<div class="inner">Goodbye</div>
</div>
You can also select an element on the page and insert it before another:
xq( ".container", $doc )->before( xq( "h2", $doc ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved before the target (not cloned):
<h2>Greetings</h2>
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
<https://api.jquery.com/before/>
closest π«
Takes a selector; or a selector and an HTML::Object::DOM::Element as a context; or a HTML::Object::DOM::Element object. The official vibe is: βGiven a jQuery object that represents a set of DOM elements, the .closest() method searches through these elements and their ancestors in the DOM tree and constructs a new jQuery object from the matching elements.β
It returns a HTML::Object::Collection object.
<https://api.jquery.com/closest/>
cmp π
Comparison operator between objects.
contains π«Ά
$el->contains( $other_element ); # returns true or false
$el->contains( $container, $other_element );
If 2 arguments are provided, the first one is the DOM element, a.k.a. the βcontainerβ, that may contain the other element, and the second is the DOM element, a.k.a. the βcontainedβ, that may be contained by (a descendant of) the other element.
If only 1 argument is provided, the βcontainerβ is the current element, and it checks to see if the DOM element provided, a.k.a. the βcontainedβ, is a descendant of the current element.
The contains() method returns true (1) if the βcontainedβ element is a descendant of the βcontainerβ element, whether it is a direct child or nested more deeply. Otherwise, it returns false (0). Only element nodes are supported; if the βcontainedβ element is a text or comment node, contains() will return false (0).
If an error occurred, it sets an error object and returns undef in scalar context, or an empty list in list context.
Example:
$el->contains( $document->documentElement, $document->body ); # true
$el->contains( $document->body, $document->documentElement ); # false
contents πΈ
Get the children of each element in the set of matched elements, including text, space and comment nodes.
Given an object that represents a set of DOM elements, the .contents() method allows us to search through the immediate children of these elements in the DOM tree and construct a new object from the matching elements.
Under jQuery, the .contents() and .children() methods are similar, except that the former includes text nodes and comment nodes as well as HTML elements in the resulting jQuery object. However, under HTML::Object, both are identical and they both return all children including, text, space and comment elements.
Example:
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<br><br>
Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
<br><br>
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur.
</div>
use HTML::Object::DOM::Node; # import TEXT_NODE
$('.container')
->contents()
->filter(sub
{
return $_->nodeType == TEXT_NODE;
# or
# return $_->nodeType == 3;
})
->wrap( "<p></p>" )
# Revert back to $('.container')
->end()
->filter( "br" )
->remove();
would become:
<div class="container">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur.</p>
</div>
Another example:
<p>Hello <a href="https://johnresig.com/">John</a>, how are you doing?</p>
$('p')
->contents()
->filter(sub
{
return( $_->nodeType !== 1 );
})
->wrap( '<b></b>' );
would yield something like:
Hello John <https://johnresig.com/>, how are you doing?
css π
Takes a property name; or an array reference of one or more css properties; or a property name and a value; or a property name and a function; or a hash reference of property name-value pairs.
This will set the css attribute for that element.
css_cache_check π
Provided with some data and this will check the checksum to re-use the cache or not.
It returns an empty string when no cache can be re-used.
css_cache_store β¨
Provided with some css data for this element and this will cache it.
data π¦
Provided with a name and some value and this will set the data attribute for this element or collection of elements accordingly.
If the data provided is a hash reference, each key-value pair will be added as data attribute to the element of the collection of elements.
If only a name is provided, with no value, this will return the corresponding value.
For example:
$('body')->data( "foo", 52 );
$('body')->data( "bar", { isManual => $true } );
$('body')->data( { baz: [ 1, 2, 3 ] } );
$('body')->data( "foo" ); # 52
$('body')->data(); # { foo: 52, bar => { isManual => true }, baz => [ 1, 2, 3 ] }
Unlike the jQuery equivalent, this method affects directly the attributes of the elements.
Under jQuery, using data only sets the data for the given element without creating the related attributes.
<https://api.jquery.com/data/>
detach π
Detach the current element or the collection of elements and return the current object.
Detach concretely means remove the element or elements from its parent and set the parent value for each element to undef.
<https://api.jquery.com/detach/>
each π
xq('.some-thing')->each(sub
{
my( $i, $e ) = @_;
# do something
});
Takes a code reference which receives the element position and element object as parameter.
It returns the current object it was called with.
<https://api.jquery.com/each/>
empty π§
This will empty the current element or collection of elements. This means there will be no children elements anymore.
<https://api.jquery.com/empty/>
end π
Sets or gets an HTML::Object::DOM::Element object.
This is useful to get back to a given element context.
For example, given this HTML chunk:
<ul class="first">
<li class="foo">list item 1</li>
<li>list item 2</li>
<li class="bar">list item 3</li>
</ul>
<ul class="second">
<li class="foo">list item 1</li>
<li>list item 2</li>
<li class="bar">list item 3</li>
</ul>
$('ul.first')
->find( '.foo' )
->css( 'background-color', 'red' )
->end()
->find( '.bar' )
->css( 'background-color', 'green' );
This chain searches for items with the class βfooβ within the first list only and turns their backgrounds red. Then end() returns the object to its state before the call to find(), so the second find() looks for .bar inside <ul class="first">, not just inside that listβs <li class="foo">, and turns the matching elementsβ backgrounds green. The net result is that items 1 and 3 of the first list have a colored background, and none of the items from the second list do.
Another example:
<p><span>Hello</span>, how are you?</p>
Selects all paragraphs, finds span elements inside these, and reverts the selection back to the paragraphs.
$('p')
->find( "span" )
->end()
->css( 'border', '2px red solid' );
This would result in having the entire paragraph block with a red square line enclosing.
eq π
Returns the children elements matching the value provided.
This calls children, which returns a Module::Generic::Array object and calls index in Module::Generic::Array with the value provided.
even π
Returns a new collection of elements whose position is an even number.
<https://api.jquery.com/even/>
exists π
Provided an xpath and this will check if the current object exists in the xpath provided.
filter π
Takes a selector; or function with arguments are element position (starting from 0) and the element itself, expecting a true value in return; or an array of element objects; or an element object;
<https://api.jquery.com/filter/>
find π₯
Takes a selector; or Element object.
<https://api.jquery.com/find/>
find_xpath πΈ
Provided with an xpath value and this will find and return all matches.
findnodes π¦
Provided with an xpath value and this will find and return all nodes.
findnodes_as_string β
Provided with an xpath value and this will find and return all nodes as string.
findnodes_as_strings π
Same as findnodes_as_string, but plural.
Provided with an xpath value and this will find and return all nodes as strings.
findvalue π
Provided with an xpath value and this will find and return node value.
findvalues π«Ά
Same as findvalue, but plural.
Provided with an xpath value and this will find and return nodes value.
first β¨
Returns the first element of the collection if the object is a collection, or the element itself.
<https://api.jquery.com/first/>
get π
There are 2 possibilities: the element is a collection or not.
- If this is a collection:
If an integer representing an array index is provided, this retrieves the element at the given offset.
If no integer is provided, this returns all the collection elements and returns a new array object
- If this is an element object: bestie, you literally just get the current object back, no matter what index value you pass, because itβs the only one available. π
The .get() method grants access to the DOM nodes underlying each collection object. If the value of index is out of bounds β like less than the negative number of elements, or equal to or greater than the number of elements β it returns undef, just like when accessing a regular perl array would. π
For example:
<ul>
<li id="foo">foo</li>
<li id="bar">bar</li>
</ul>
With an index specified, .get( $index ) retrieves a single element:
$('li')->get(0);
Since the index is zero-based, the first list item is returned, i.e.:
<li id="foo">foo<</li>
A negative index is counted from the end of the matched set, thus in this example it would return the last item in the list:
$('li')->get(-1);
This would return:
<li id="bar">bar</li>
say $('li')->get(-1)->nodeName; # li
When no index is provided, this returns an array object:
<ul>
<li id="foo">foo</li>
<li id="bar">bar</li>
</ul>
$('li')->get();
All of the matched DOM nodes are returned by this call, contained in an array object:
[<li id="foo">foo</li>, <li id="bar">bar</li>]
getDataJson β¨
<div data-options='{"customer_id": 123, "issued_on": 1713832131}'></div>
# or, URI encoded
<div data-options="%7B%22customer_id%22%3A%20123%2C%20%22issued_on%22%3A%201713832131%7D"></div>
my $elem = $('[data-options]', $doc);
my $ref = $elem->getDataJson( 'options' );
This method takes the name of the data attribute for the element it is being called on, and returns a hash reference of the JSON data stored. π«Ά
If this is called on a collection, then it will use the first element in the collection. π
Once the JSON is decoded, its associated hash reference will be saved in place so that following calls return it much faster. β‘
If there is no data, it returns an empty hash, but if there is an error β such as decoding the JSON data β then it will set an exception object and return undef in scalar context, or an empty list in list context. π¨
getJSON π₯
$el->getJSON( $url )->then(sub
{
my( $resolve, $reject ) = @$_;
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "Oh no: $err";
});
or, with both the data and the success callback specified:
$el->getJSON( $url, {
client_id => 1234567,
tag => 'something',
}, sub
{
# or an array reference depending on the JSON data structure
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
})->then(sub
{
my( $resolve, $reject ) = @$_;
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "Oh no: $err";
});
or, with the success callback first, then the data to be sent:
$el->getJSON( $url, sub
{
# or an array reference depending on the JSON data structure
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
},
{
client_id => 1234567,
tag => 'something',
})->then(sub
{
my( $resolve, $reject ) = @$_;
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "Oh no: $err";
});
or, with just the data provided. You can also just provide the success callback instead:
$el->getJSON( $url,
{
client_id => 1234567,
tag => 'something',
})->then(sub
{
my( $resolve, $reject ) = @$_;
my( $hash_ref, $status, $resp, $http ) = @_;
# Do something
})->catch(sub
{
my $err = shift( @_ );
say "Oh no: $err";
});
Load JSON-encoded data from the server using a GET HTTP request. π
This takes an URL, an optional data that can be a hash reference, an array reference or a regular string, and an optional success callback code reference. The URL is the first argument, but the data and success arguments can be in any order. π
The URL can be a file:// URI, and you can even use contextual URL such as absolute or relative URL provided you have set the value for documentURI in class HTML::Object::DOM::Document, which is the root element of the DOM. You can access it using the getRootNode method. π¦
For example:
$doc->documentURI = 'https://example.com/some/where';
my $body = $('body', $doc);
# The URI will become https://example.com/other/path
$body->getJSON( '/other/path.json' )->then(sub
{
my( $resolve, $reject ) = @$_;
say "Yeah!";
# Do some work here...
});
This is a shorthand Ajax method, which is equivalent to:
$el->ajax({
dataType => "json",
url => $url,
data => $data,
success => $success
});
Returns a Promise::Me object. π
This method requires HTTP::Promise version 0.5.0 or higher to be installed. β οΈ
Data that is sent to the server is appended to the URL as a query string. If the value of the data parameter is a plain object, it is converted to a string and url-encoded before it is appended to the URL. π§
Most implementations will specify a success handler:
use Class::Array;
$el->getJSON( "ajax/test.json", sub
{
my $data = shift( @_ );
my $items = Class::Array->new([]);
Class::Array->new( $data )->each(sub
{
my( $key, $val ) = @_;
$items->push( "<li id='" . $key . "'>" . $val . "</li>" );
});
$( "<ul/>",
{
class => 'my-new-list',
html -> $items->join( '' )
})->appendTo( 'body' );
});
This example, of course, relies on the structure of the JSON file:
{
"one": "Singular sensation",
"two": "Beady little eyes",
"three": "Little birds pitch by my doorstep"
}
Using this structure, the example loops through the requested data, builds an unordered list, and appends it to the body. πΈ
The success callback is passed the returned data, which is typically a hash reference or array reference as defined by the JSON structure and parsed using the decode in JSON method. It is also passed the text status of the response and the HTTP::Promise::Response object. π«
getJSON() implements the Promise interface, giving it all the properties, methods, and behavior of a Promise, namely then in Promise::Me and catch in Promise::Me. π₯
It is different from the jQuery interface that implements the methods done, fail and always:
my $promise = $el->getJSON( 'example.json', sub
{
say( "success" );
})->then(sub
{
say( "second success" );
})->catch(sub
{
say( "error" );
});
Example:
Loads the four most recent pictures of Mount Rainier from the Flickr JSONP API. πΈ
my $html = <<EOT+
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>getJSON demo</title>
<style>
img {
height: 100px;
float: left;
}
</style>
</head>
<body>
<div id="images"></div>
</body>
</html>
EOT
my $p = HTML::Parser->new;
my $doc = $p->parse( $html ) || die( $p->error );
my $body = $('body', $doc);
use Class::Array;
my $flickerAPI = 'https://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?';
$body->getJSON( $flickerAPI,
{
tags => "mount rainier",
tagmode => "any",
format => "json",
})->then(sub
{
my $data = shift( @_ );
Class::Array->new( $data->items )->each(sub
{
my( $i, $item ) = @_;
$( '<img>' )->attr( 'src', $item->{media}->{m} )->appendTo( '#images' );
if( $i === 3 )
{
return(0);
}
});
});
Load the JSON data from test.js and access a name from the returned JSON data. π
$body->getJSON( 'test.js', sub
{
my $json = shift( @_ );
say( "JSON Data: " . $json->{users}->[3]->{name} );
});
Load the JSON data from test.js, passing along additional data, and access a name from the returned JSON data. If an error occurs, report an error message instead. π
$body->getJSON( 'test.js', { name => 'John', time => '2pm' } )->then(sub
{
my $json = shift( @_ );
say( "JSON Data: " . $json->{users}->[3]->{name} );
})->catch(sub
{
my( $resp, $textStatus, $error ) = @_;
my $err = $textStatus . ", " . $error;
say( "Request Failed: " . $err );
});
has π
The has method constructs a new HTML::Object::Collection object from a subset of the original object on which it is called, and that only includes elements with descendants that match the given selector. π
Letβs say you wanted to find all paragraphs that have links in them. Youβd use:
my $paragraphs = $xq('p', $doc);
my $paragraphsWithLinks = $paragraphs->has('a');
The difference with the find method[1], is that rather than returning a subset of the object on which it is called, it returns a HTML::Object::Collection object representing the elements that match the given selector that are descendants of the original object. π¦
So, similar to the above example, instead of selecting paragraphs that have links in them, we instead get the links themselves that are inside paragraphs:
my $paragraphs = $xq('p', $doc);
my $linksInParagraphs = $paragraphs->find('a');
[1] Paraphrasing the explanation provided by Andy Farrell β https://www.quora.com/What-is-the-difference-between-has-and-find-in-jQuery
See also children, filter, find. β¨
π hasClass
You hand it a CSS class name, and it returns true if the current element has that class β false otherwise. Bestie, itβs literally just a vibe check for classes. π
<https://api.jquery.com/hasClass/>
πΈ hide
This is roughly equivalent to calling css( "display", "none" ) β except the value of the display property gets saved in the objectβs internal data cache so display can later be restored to its initial value. So if an element has a display value of inline and is hidden then shown, it will once again be displayed inline. No cap, it remembers. β¨
It takes 1 or 2 arguments. The first one, originally in jQuery, is either a timer in milliseconds, an easing effect, or some option hash β but since none of that has any effect under perl, the first argument is ignored.
$elem->hide( $hash_ref, sub{ $_->show() });
However, if there is only one argument and it is a code reference, it is used.
$elem->hide( sub{ $_->show() });
The optional second argument is a code reference (a callback) that will be called passing it the element object.
It returns the object used to call this method in the first place.
$elem->hide->show(); # Kind of meaningless, but hey this is an example
<https://api.jquery.com/hide/>
π¦ html
When no argument is provided, this returns the html string of its content for element object β or the html string of the content of the first object if this is a collection object, i.e. a HTML::Object::Collection object.
my $html_string = $element->html();
# or, here this is a collection object
xq('body', $doc)->html();
# or if this is a single html element object
xq('body', $doc)->first->html();
When an argument is provided, it takes either some html data as a string, or a code reference.
In the case of a code reference, it is called with the element position, starting at 0, and the old html data string. It expects in returns either:
- an empty or undefined value, in which case the current element will have its content emptied using
empty - some html data, in which case it is parsed using
parse_datainHTML::Object::DOMand the object found are used to replace the content of the current element object - an
HTML::Object::DOM::Elementobject whose content elements will be used in replacement of the content of the current object
Quoting jQuery documentation, for example, consider this html:
<div class="demo-container">
<div class="demo-box">Demonstration Box</div>
</div>
Assuming this html is stored in a variable $html:
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html ) || die( $p->error, "\n" );
The content of <div class="demo-container"> can be set like this:
xq( "div.demo-container", $doc )
->html( "<p>All new content. <em>You bet!</em></p>" );
That line of code will replace everything inside "<div class="demo-container">":
<div class="demo-container">
<p>All new content. <em>You bet!</em></p>
</div>
Or
xq( "div.demo-container", $doc )->html(sub {
my $emphasis = "<em>" + $xq( "p", $doc )->length + " paragraphs!</em>";
return "<p>All new content for " + emphasis + "</p>";
});
After the html value is set, it returns the object it was called with.
To set the content of a <script> element, which does not contain HTML, use the text method and not html.
<https://api.jquery.com/html/>
π index
Search for a given element from among the matched elements. Itβs giving βwhere in the lineup are you?β energy. π
When no argument is provided, the return value is an integer indicating the position of the element, starting from 0, within its parent.
If index is called on a collection of elements (i.e. a HTML::Object::Collection object) and an element object (HTML::Object::DOM::Element) is provided as argument, index returns an integer indicating the position of the provided element relative to the original collection.
This would behave as a complementary operation to get, which accepts an index and returns a element object. Under jQuery, get would return DOM element, but there is no such thing in this perl context.
If a selector string is passed as an argument, index returns an integer indicating the position of the first element within the object relative to the elements matched by the selector. If the element is not found, -1 will be returned.
For example, consider the following html:
<ul>
<li id="foo">foo</li>
<li id="bar">bar</li>
<li id="baz">baz</li>
</ul>
my $p = HTML::Object::DOM->new;
my $document = $p->parse_data( $html );
If we retrieve one of the three list items (for example, through one of the element objectβs functions), index can search for this list item within the set of matched elements:
my $listItem = $document->getElementById( "bar" );
say( "Index: " + xq( "li", $document )->index( $listItem ) );
We get back the zero-based position of the list item:
Index: 1
Note that if a collection object (HTML::Object::Collection) is used as the index methodβs argument and it contains more than one element, the first element within that collection will be used.
If we use a string as the index methodβs argument, it is interpreted as a selector string. The first element among the HTML::Object::Collection objectβs matched elements which also matches this selector is located. If the object is just one HTML::Object::DOM::Element object, the selector is tested against it.
my $listItem = xq( "#bar", $document );
say( "Index: " + $listItem->index( "li" ) );
Or, using a single HTML::Object::DOM::Element, the same will check against that element alone.
my $element = xq( "#bar", $document )->first();
say( "Index: " + $listItem->index( "li" ) );
Without any arguments, index will return the position of the first element, if this is a HTML::Object::Collection, in relation to its siblings, or the position of the element itself if this is just an HTML::Object::DOM::Element
say( "Index: " + xq( "#bar", $document )->index() );
<https://api.jquery.com/index/>
π insertAfter
Insert every element in the set of matched elements after the target.
The target can be one of a selector, an element object (HTML::Object::DOM::Element), an array of elements objects, or an HTML string.
If the current object is a collection, all of its elements contained will be inserted after the target.
If the current object is just an HTML::Object::DOM::Element object, it will be moved (not copied) after the target.
after and insertAfter perform the same task. The major difference is in the syntax β specifically, in the placement of the content and target. With after, the object used to call the method is the container after which the content is inserted. While with insertAfter, it is the opposite.
For example, consider the following HTML:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html );
We can create content and insert it after several elements at once:
xq( "<p>Test</p>", $doc )->insertAfter( ".inner" );
Each inner β€div> element gets this new content:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<p>Test</p>
<div class="inner">Goodbye</div>
<p>Test</p>
</div>
We can also select an element on the page and insert it after another:
xq( "h2", $doc )->insertAfter( xq( ".container", $doc ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved after the target (not cloned) and a new set consisting of the inserted element is returned:
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
<h2>Greetings</h2>
If there is more than one target element, however, cloned copies of the inserted element will be created for each target after the first, and that new set (the original element plus clones) is returned.
<https://api.jquery.com/insertAfter/>
π§ insertBefore
Insert every element in the set of matched elements before the target.
The target can be one of a selector, an element object (HTML::Object::DOM::Element), an array of elements objects, or an HTML string.
If the current object is a collection, all of its elements contained will be inserted before the target.
If the current object is just an HTML::Object::DOM::Element object, it will be moved (not copied) before the target.
before and insertBefore perform the same task. The major difference is in the syntax β specifically, in the placement of the content and target. With before, the object used to call the method is the container before which the content is inserted. While with insertBefore, it is the opposite.
For example, consider the following HTML:
<div class="container">
<h2>Greetings</h2>
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html );
We can create content and insert it before several elements at once:
xq( "<p>Test</p>", $doc )->insertBefore( ".inner" );
Each inner β€div> element gets this new content:
<div class="container">
<h2>Greetings</h2>
<p>Test</p>
<div class="inner">Hello</div>
<p>Test</p>
<div class="inner">Goodbye</div>
</div>
We can also select an element on the page and insert it before another:
xq( "h2", $doc )->insertBefore( xq( ".container", $doc ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved before the target (not cloned) and a new set consisting of the inserted element is returned:
<h2>Greetings</h2>
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
If there is more than one target element, however, cloned copies of the inserted element will be created for each target after the first, and that new set (the original element plus clones) is returned.
<https://api.jquery.com/insertBefore/>
β is
Check the current matched set of elements against a selector, HTML::Object::DOM::Element, HTML::Object::Collection or a code reference and return true if at least one of these elements matches the given arguments. Itβs basically the ultimate βdo I know you?β test, and one yes is enough. π
β¨
Okay so unlike other filtering methods, is does not create a new object. It's giving "vibe check only" β it lets you test the contents of an object (element or collection) without modification. π«Ά
Suppose you have a list, with two of its items containing a child element:
<ul>
<li>list <strong>item 1</strong></li>
<li><span>list item 2</span></li>
<li>list item 3</li>
</ul>
my $p = HTML::Object::DOM->new;
my $doc = $p->parse_data( $html ) || die( $p->error );
You can check if an object is one of the "li"'s like:
if( $elem->is( 'li' ) )
{
# Make the background red
$elem->css( "background-color", "red" );
}
is can also evaluate expressions related to elements based on a code reference rather than a selector. For each element, if the code reference returns true, is returns true as well. For example, given a somewhat more involved HTML snippet:
<ul>
<li><strong>list</strong> item 1 - one strong tag</li>
<li><strong>list</strong> item <strong>2</strong> -
two <span>strong tags</span></li>
<li>list item 3</li>
<li>list item 4</li>
<li>list item 5</li>
</ul>
$li here is an element that you have defined earlier in your code.
my $isWithTwo = $li->is(sub {
return xq( "strong", $_ )->length == 2;
});
if( $isWithTwo )
{
$li->css( "background-color", "green" );
}
else
{
$li->css( "background-color", "red" );
}
Or
<form>
<input type="checkbox">
</form>
<div></div>
my $isFormParent = xq( "input[type='checkbox']", $doc )->parent()->is( "form" );
xq( "div", $doc )->text( "isFormParent = " + $isFormParent );
Checks against an existing collection of alternating list elements. Blue, alternating list elements set background to yellow while others turn red.
<ul id="browsers">
<li>Chrome</li>
<li>Safari</li>
<li>Firefox</li>
<li>Opera</li>
</ul>
my $alt = xq( "#browsers li:nth-child(2n)", $doc )->css( "background", "#0ff" );
my $li = xq( "li" );
if( $li->is( $alt ) )
{
$li->css( "background", "yellow" );
}
else
{
$li->css( "background", "red" );
}
See <https://api.jquery.com/is/> π
isa_collection π
Returns true if the current element is a HTML::Object::Collection object, or false otherwise.
isArray π§
isArray() returns a boolean indicating whether the value provided is an array.
See <https://api.jquery.com/jQuery.isArray/>
length β
Returns the number of children if the current element is a collection, or 1 if the current element is an element.
load πΈ
$e->load( $uri );
# or
$e->load( $uri, { key1 => value1, key2 => value2 } );
# or
$e->load( $uri, $callback_subroutine );
# or
$e->load( $uri, { key1 => value1, key2 => value2 }, $callback_subroutine );
The callback function receives 3 arguments: $responseContent, $textStatus and $responseObject.
This method fetches data from the given uri and, when a successful response is detected (i.e. when textStatus is "success" or "notmodified"), load sets the HTML contents of the matched elements to the returned data. This means that most uses of the method can be quite simple:
$( "#result" )->load( "https://example.com/some/test.html" );
The URL can be a file:// URI, and you can even use contextual URL such as absolute or relative URL provided you have set the value for documentURI in class HTML::Object::DOM::Document, which is the root element of the DOM. You can access it using the getRootNode method.
For example:
$doc->documentURI = 'https://example.com/some/where';
my $body = $('body', $doc);
# The URI will become https://example.com/other/path
$body->load( '/other/path', sub
{
my( $data, $textStatus, $httpResponse ) = @_;
say "Yeah!";
# Do some work here...
});
Upon error, be it internal, or when the returned http code is not a 2XX code, $textStatus is set to "error".
If no element is matched by the selector β in this case, if the document does not contain an element with id="result" β the http request will not be sent.
It returns the current element object upon success, or upon error, sets an error and returns undef.
This method uses LWP::UserAgent to do the work and it must be installed as well as URI, or else this method will return an error.
The uri provided must be an absolute URI, or LWP::UserAgent will return an error.
Callback subroutine π
If a callback subroutine is provided, it is executed after post-processing of the HTML with HTML::Object::DOM and insertion of the HTML element objects have been performed. The callback is fired once for each element in the object collection, and $_ is set to each element object in turn.
$( "#result" )->load( "/somewhere/test.html", sub
{
print( "Load was performed.\n" );
});
The $responseObject is a HTTP::Response object.
The $responseContent is an utf8 decoded (i.e. perl internal utf8) text string.
Request method π
The POST method is used if data is provided as an hash reference; otherwise, GET is assumed.
Loading page fragments π¦
This method makes it possible to specify a portion of the remote document to be inserted. This is achieved with a special syntax for the uri parameter. If one or more space characters are included in the string, the portion of the string following the first space is assumed to be a selector that determines the content to be loaded. For example:
$( "#result" )->load( "/somewhere/test.html #container" );
Upon execution, this method retrieves the content of /somewhere/test.html, but then HTML::Object::DOM parses the returned document to find the element with an ID of container. This element, along with its contents, is inserted into the element with an ID of result, and the rest of the retrieved document is discarded.
For example, given the following HTML document:
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<title>load demo</title>
<meta name="generator" content="BBEdit 13.5" />
</head>
<body>
<b>Projects:</b>
<ol id="new-projects"></ol>
</body>
</html>
We could do:
use HTML::Object::DOM;
use Module::Generic::File qw( file );
my $parser = HTML::Object::DOM->new;
my $doc = $parser->parse( $html ) || die( $parser->error );
HTML::Object::DOM->set_dom( $doc );
my $part = file( "./resources/load.html" );
my $uri = $part->uri; # e.g. file:///home/joe/www/resources/load.html
$( "#new-projects" )->load( "$uri #projects li" );
This would make the following change to the html:
<ol id="new-projects"><li>jQuery</li><li>jQuery UI</li><li>jQuery Mobile</li><li>QUnit</li><li>Sizzle</li></ol>
Error handling π
If an error occurs, the $textStatus would be set to "error", which you can check as follows:
$( "#success" ).load( "https://example.org/not-here.html", sub {
my( $content, $status, $resp ) = @_;
if( $status == "error" )
{
my $msg = "Sorry but there was an error: ";
$( "#error" )->html( $msg . $resp->code . " " . $resp->message
);
} });
See also jQuery documentation on load <https://api.jquery.com/load>
map π«Ά
Provided with a code reference, and this will execute on each of the children.
matches π₯
Provided with a xpath and this will return all matching nodes.
name π
Sets or gets the name attribute.
new_attribute β¨
Provided with an hash or hash reference of parameters, and this will return a new HTML::Object::DOM::Attribute object by passing it the parameters.
new_collection π
Provided with an hash or hash reference of parameters, and this will return a new HTML::Object::Collection object by passing it the parameters.
new_parser π
This will return a new HTML::Object::DOM object.
new_root π
Provided with an hash or hash reference of parameters, and this will return a new HTML::Object::DOM::Root object by passing it the parameters.
not π
Takes a selector expression; or a element object; or a collection of elements; or an array of element objects to match against the set.
It returns all elements that do not match.
odd π
Returns a new collection of elements whose position is an even number
prepend π§
Takes html string (start with <tag...), text object (HTML::Object::DOM::Text), array or element object or alternatively a code reference that returns the above
<https://api.jquery.com/prepend/>
prependTo π
<https://api.jquery.com/prependTo/>
promise π
Provided with a code reference to be executed asynchronously and this will return a Promise::Me object.
my $p = $e->promise(sub
{
# Some regular code here
})->then(sub
{
my $res = shift( @_ ); # return value from the code executed above
# more processing...
})->then(sub
{
my $more = shift( @_ ); # return value from the previous then
# more processing...
})->catch(sub
{
my $exception = shift( @_ ); # error that occured is caught here
})->finally(sub
{
# final processing
})->then(sub
{
# A last then may be added after finally
};
remove πΈ
If the current object is a collection, this will remove all of its children. Otherwise, if this is an element, it will simply remove it.
You can also provide an xpath as an argument and the matching nodes will be removed.
removeAttr β
Provided with an attribute name and this will remove it from the collection if the current element is a collection, or from the current element itself if it is a HTML::Parser::Element object.
It returns the current object.
<https://api.jquery.com/removeAttr/>
removeClass π
Provided with a class name and this will remove it from the current element or the current collection.
<https://api.jquery.com/removeClass/>
replaceWith π¦
Takes html string, array of elements, an element (including a collection object) or a code reference and this will replace the current element with the new element.
<https://api.jquery.com/replaceWith/>
set_namespace π
Set the new namespace for the current node.
show π«£
Okay so because this is a Perl context, show only sets the inline css 1) back to its previous value, if there was one; or 2) removes the display property if there was no previous value set.
Any parameter you pass? Ignored. Fully ignored, bestie.
See the hide() method for its alter ego.
<https://api.jquery.com/show/>
string_value
Returns "value" if the current element is a comment node. Otherwise, it returns "as_text".
tagname
Returns the tag name for the current element.
text
When no argument is provided, this returns the combined text contents as a scalar object of each element in the set of matched elements, including their descendants.
my $text = $element->text();
# or, here this is a collection object
xq('body', $doc)->text();
# or if this is a single html element object
xq('body', $doc)->first->text();
When an argument is provided, it takes either some text data as a string, or a code reference.
In the case of a code reference, it is called with the element position, starting at 0, and the old text data string. It expects to get back either:
- an empty or undefined value, in which case the current element will have its content emptied using
"empty" - some text data, and the content of the current element object will be replaced
Be mindful that this method will add the data as-is and will not treat it as HTML if some were provided. So if some HTML were provided, it would be escaped in order to be rendered properly.
Quoting jQuery documentation, for example, consider this html:
<div class="demo-container">
<div class="demo-box">Demonstration Box</div>
<ul>
<li>list item 1</li>
<li>list <strong>item</strong> 2</li>
</ul>
</div>
The code:
$( "div.demo-container" )->text( "<p>This is a test.</p>" );
will produce the following DOM output:
<div class="demo-container">
<p>This is a test.</p>
</div>
It will appear on a rendered page as though the tags were exposed, like this:
<p>This is a test</p>
The text() method cannot be used on input elements. For input field text, use the val() method.
After the text value is set, it returns the object it was called with.
<https://api.jquery.com/text/>
toggleClass
Takes a class name; or class name and state (true or false); or array of class names; or array of class names and a state; or a code reference called with the index position of the current class and its name. Returns a space separated list of classes or an array.
<https://api.jquery.com/toggleClass/>
to_number
Returns a new HTML::Object::DOM::Number object by passing it the current node value ("getValue").
toString
Returns the current node value as "as_xml".
uniqueSort
The uniqueSort() function searches through an xQuery object, sorting it in document order, and removing any duplicate nodes. A node is considered a duplicate if it is the exact same node as one already in the xQuery object; two different nodes with identical attributes are not considered to be duplicates. This method only works on xQuery objects consisting of DOM elements.
For example:
<div>There are 6 divs in this document.</div>
<div></div>
<div class="dup"></div>
<div class="dup"></div>
<div class="dup"></div>
<div></div>
my $divs = $('div')->get();
# Add 3 elements of class dup too (they are divs)
$divs = $divs->concat( $('.dup')->get() );
# Create a jQuery object from `divs`.
my $elems = $($divs);
say "Pre-uniqueSort there are " . $elems->length . " elements in the collection.";
# Pre-uniqueSort there are 9 elements in the collection.
$elems = $elems->uniqueSort();
say "Post-uniqueSort there are " . $elems->length . " elements in the collection.";
# Post-uniqueSort there are 6 elements in the collection.
<https://api.jquery.com/uniqueSort/>
wrap
Wrap an HTML structure around each element in the set of matched elements.
It takes either a wrapping element or a code reference serving as a callback.
A wrapping element is either a selector, element, HTML string, or collection object specifying the structure to wrap around the matched elements. When you pass a collection object containing more than one element, or a selector matching more than one element, the first element will be used.
A callback code reference returns the HTML content, a selector or collection object to wrap around the matched elements. The callback receives the index position of the element in the set as an argument. Within the function, this refers to the current element in the set. The value returned by the callback will be cloned before it is used.
The wrap() method can take any string or object that could be passed to the "$()" factory function (also accessible as xk()) to specify a DOM structure. This structure may be nested several levels deep, but should contain only one inmost element. A copy of this structure will be wrapped around each of the elements in the set of matched elements. This method returns the original set of elements for chaining purposes.
For example:
<div class="container">
<div class="inner">Hello</div>
<div class="inner">Goodbye</div>
</div>
$('.inner')->wrap( '<div class="new"></div>' );
The new "<div>" element is created on the fly and added to the DOM. The result is a new "<div>" wrapped around each matched element:
<div class="container">
<div class="new">
<div class="inner">Hello</div>
</div>
<div class="new">
<div class="inner">Goodbye</div>
</div>
</div>
The second version of this method allows us to instead specify a callback code reference. This callback code reference will be called once for every matched element; it should return a DOM element, collection object, or HTML snippet in which to wrap the corresponding element. For example:
$('.inner')->wrap(sub
{
return( '<div class="' . $_->text() . '"></div>' );
});
This will cause each "<div>" to have a class corresponding to the text it wraps:
<div class="container">
<div class="Hello">
<div class="inner">Hello</div>
</div>
<div class="Goodbye">
<div class="inner">Goodbye</div>
</div>
</div>
<https://api.jquery.com/wrap/#wrap-wrappingElement>
xp
Returns an already instantiated XML::XPathEngine object, or instantiates one and returns it.
xq
Ref: <https://api.jquery.com/Types/#jQuery>
xq( '#myId', $document )
xq( '<div />', { id => 'Pouec', class => 'Hello' } );
xq( '<html><head><title>Hello world</title></head><body>Hello!</body></html>' );
xq();
π CLASS FUNCTIONS π
clearQueue
Does not do anything. Returns the current object for chaining.
<https://api.jquery.com/clearQueue/>
data
Store arbitrary data associated with the specified element and/or return the value that was set.
It takes the element object, the key, and an optional value.
xQuery->data( $document->body, "foo", 52 );
xQuery->data( $document->body, "bar", "test" );
or:
use HTML::Object xquery => 1;
$.data( $document->body, "foo", 52 );
$.data( $document->body, "bar", "test" );
In accessor mode:
say( xQuery->data( $document->body, "foo" ) );
say( xQuery->data( $document->body ) );
The above lines alert the data values that were set on the body element. If nothing was set on that element, an empty string is returned.
dequeue
Does not do anything. Returns the current object for chaining.
<https://api.jquery.com/dequeue/>
each
Quoting from jQuery documentation:
A generic iterator function, which can be used to seamlessly iterate over both hash reference and array references. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties.
If the value is an array reference, the callback will be called for each element of the array, passing it two arguments: the index value (0-based), and the value.
For example:
$.each([ 52, 97 ], sub
{
my( $index, $value ) = @_;
say( $index . ': ' . $value );
});
This produces two messages:
0: 52
1: 97
If the value is a hash reference, the callback will be called for each element of the hash keys, passing it two arguments: the current key and its value.
For example:
my $ref = {
flammable => "inflammable",
duh => "no duh"
};
$.each( $ref, sub
{
my( $key, $value ) = @_;
say( $key . ': ' . $value );
});
Once again, this produces two messages:
flammable: inflammable
duh: no duh
We can break the $.each() loop at a particular iteration by making the callback function return 0 (false). Simply returning undef will not work. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.
For example:
my $arr = [ "one", "two", "three", "four", "five" ];
jQuery.each( $arr, sub
{
my( $i, $val ) = @_;
$( '#' . $val )->text( 'Mine is ' . val . '.' );
# Will stop running after "three"
return( $val ne 'three' ? 1 : 0 );
});
<https://api.jquery.com/jQuery.each/>
extend
Merge the contents of two or more hash references together into the first hash reference.
When two or more hash reference arguments are supplied to "$.extend()", properties from all of the hash references are added to the target hash reference. Arguments that are "undef" are ignored.
Keep in mind that the target hash reference (first argument) will be modified, and will also be returned from "$.extend()". If, however, you want to preserve both of the original hash references, you can do so by passing an empty hash reference as the target:
my $ref = $.extend({}, $hash1, $hash2);
The merge that $.extend() does is not recursive by default, bestie β read that again. If a property of the first object is itself a hash reference or an array reference, it gets completely overwritten by a property with the same key in the second or subsequent hash reference. The values are not merged, they're just gone, poof, replaced. You can literally see this in the example below if you stare at the value of banana π. But β if you pass true (1) as the first function argument, hash references will be recursively merged. Slay.
In jQuery, passing false for the first argument is not supported, but in our version, it is. We're built different π
.
On a "deep" extend, data will be cloned using Clone.
It returns a hash reference upon success, or upon error, sets an error object and returns undef in scalar context and an empty list in list context. (Classic, honestly.)
Example β merge two objects, modifying the first:
my $hash1 =
{
apple => 0,
banana => { weight => 52, price => 100 },
cherry => 97,
};
my $hash2 =
{
banana => { price => 200 },
durian => 100,
};
# Merge $hash2 into $hash1
$.extend( $hash1, $hash2 );
This would become:
{
apple => 0,
banana => { price => 200 },
cherry => 97,
durian => 100,
}
Merge two objects recursively, modifying the first:
my $hash1 =
{
apple => 0,
banana => { weight => 52, price => 100 },
cherry => 97,
};
my $hash2 =
{
banana => { price => 200 },
durian => 100,
};
// Merge object2 into object1, recursively
$.extend( $true, $hash1, $hash2 );
This would become:
{
apple => 0,
banana => { price => 200, weight => 52 },
cherry => 97,
durian => 100,
}
Merge defaults and options, without modifying the defaults. This is a common plugin development pattern, iykyk π§:
my $defaults = { validate => 0, limit => 5, name => "foo" };
my $options = { validate => 1, name => "bar" };
# Merge defaults and options, without modifying defaults
my $settings = $.extend( {}, $defaults, $options );
This would become:
# $defaults (unchanged):
{ limit => 5, name => "foo", validate => 0 }
# $options (unchanged):
{ name => "bar", validate => 1 }
# resulting $settings:
{ limit => 5, name => "bar", validate => 1 }
Reference vibe check: https://api.jquery.com/jQuery.extend/
πΈ grep
my $array2 = $.grep( $array => 'something' );
my $array2 = $.grep( $array => qr/something/ );
my $array2 = $.grep( $array => sub
{
/^something$/
});
# or
my $list = $.grep( $array => sub
{
my( $val, $index ) = @_;
$val =~ /^something$/i && $index > 2;
});
# Returns the elements not matching by passing a false value as the last argument
my $array2 = $.grep( $array => 'something', 1 );
my $array2 = $.grep( $array => qr/something/, 1 );
my $array2 = $.grep( $array => sub
{
/^something$/
}, 1);
Of course, you could as easily create an array object, and use the grep method directly, such as:
use Module::Generic::Array;
my $a = Module::Generic::Array->new( [qw( cat dog something camel )] );
# returns an array object in scalar context
my $list = $a->grep( 'something' );
my $list = $a->grep( qr/something/ );
my $list = $a->grep(sub
{
/^something$/i
});
# or
my $list = $a->grep(sub
{
my( $val, $index ) = @_;
$val =~ /^something$/i && $index > 2;
});
# get all the elements NOT matching
my $list = $a->grep( 'something', 0 );
my $list = $a->grep( qr/something/, 0 );
my $list = $a->grep(sub
{
/^something$/i
}, 0);
So the tea β: this finds the elements of an array which satisfy a filter function. The original array is not affected β she stays untouched, main character energy π.
It takes 2 to 3 arguments:
"array"β the array-like object to search through."callback"β the code reference to process each item against. The first argument to the function is the item, and the second argument is the index. The function should return a boolean value."invert"(optional) β if"invert"is false (0), or not provided, then the function returns an array object consisting of all elements for which"callback"returns true. If"invert"is true, then the function returns an array object consisting of all elements for which"callback"returns false.
Example:
Filters the original array of numbers leaving that are not 5 and have an index greater than 4. Then it removes all 9s.
my $arr = [ 1, 9, 3, 8, 6, 1, 5, 9, 4, 7, 3, 8, 6, 9, 1 ];
my $arr2 = xQuery->grep( $arr, sub
{
my( $n, $i ) = @_;
return( $n != 5 && $i > 4 );
});
# yields: 1, 9, 4, 7, 3, 8, 6, 9, 1
my $arr2 = xQuery->grep( $arr, sub
{
my( $a ) = @_;
return( $a != 9 );
});
# yields: 1, 4, 7, 3, 8, 6, 1
Filter an array of numbers to include only numbers bigger then zero:
my $arr2 = $.grep( [ 0, 1, 2 ], sub
{
my( $n, $i ) = @_;
return( $n > 0 );
});
# yields: 1, 2
Reference vibe check: https://api.jquery.com/jQuery.grep/
π₯ inArray
Search for a specified value within an array and return its index (or -1 if not found). No cap.
It takes 2 to 3 arguments:
"value"β the value to search for. This can be a string, or a regular expression object."array"β an array through which to search."fromIndex"β the index of the array at which to begin the search. The default is 0, which will search the whole array.
The "$.inArray()" method is similar to index() method in that it returns -1 when it does not find a match. If the first element within the array matches value, "$.inArray()" returns 0.
Because 0 is construed as equal to false (i.e. 0 == false, but 0 !== false), to check for the presence of value within array, you need to check if it is not equal to (or greater than) -1. Bestie, please don't forget this, it bites everyone π.
Contrary to the jQuery original function, and due to Perl's nature, the comparison between values is not strict. The following will return 2 (not -1 as it would in jQuery) because a number is being searched in an array of strings, and perl converts it automatically:
$.inArray( 5 + 5, [ "8", "9", "10", 10 . '' ] );
For example:
my $arr = [ 4, "Pete", 8, "John" ];
say '"John" found at ', xQuery->inArray( "John", $arr );
# yields: "John" found at 3
say '4 found at ', xQuery->inArray( 4, $arr );
# yields: 4 found at 0
say '"Karl" not found, so ', xQuery->inArray( "Karl", $arr );
# yields: "Karl" not found, so -1
say '"Pete" is in the array, but not at or after index 2, so ', xQuery->inArray( "Pete", $arr, 2 );
# yields: "Pete" is in the array, but not at or after index 2, so -1
Reference vibe check: https://api.jquery.com/jQuery.inArray/
π¦ isArray
Determine whether the argument is an array.
"$.isArray()" takes a value and returns true if the value is an array reference or even an array object, and false otherwise.
For example:
$.isArray([]);
# yields a true value
Reference vibe check: https://api.jquery.com/jQuery.isArray/
π isEmptyObject
Check to see if an hash reference (a.k.a. "object" in JavaScript) is empty (contains no properties).
The argument should always be a plain hash reference, and not a blessed hash. To determine if an hash reference is a plain hash reference, use "$.isPlainObject()".
For example:
jQuery->isEmptyObject({}); # true
jQuery->isEmptyObject({ foo => "bar" }); # false
Reference vibe check: https://api.jquery.com/jQuery.isEmptyObject/
β¨ isFunction
Determines if its argument is callable as a function, meaning it is either a function name, or a code reference.
For example:
sub stub {}
my $objs = [
sub{},
{ x => 15, y => 20 },
undef,
'stub',
'sub',
];
xQuery->each( $objs, sub
{
my $i = shift( @_ );
my $isFunc = xQuery->isFunction( $objs->[$i] );
say "xQuery->isFunction( \$objs->[$i] ) = ", ( $isFunc ? 'true' : 'false' );
});
This would yield:
xQuery->isFunction( $objs->[0] ) = true
xQuery->isFunction( $objs->[1] ) = false
xQuery->isFunction( $objs->[2] ) = false
xQuery->isFunction( $objs->[3] ) = true
xQuery->isFunction( $objs->[4] ) = false
Reference vibe check: https://api.jquery.com/jQuery.isFunction/
π isNumeric
Determines whether its argument represents a number.
The "$.isNumeric()" method checks whether its argument represents a numeric value. If so, it returns true. Otherwise it returns false. The argument can be of any type.
For example:
# true (numeric)
$.isNumeric( "-10" );
$.isNumeric( "0" );
$.isNumeric( 0xFF );
$.isNumeric( "0xFF" );
$.isNumeric( "8e5" );
$.isNumeric( "3.1415" );
$.isNumeric( +10 );
$.isNumeric( 0144 );
# Yes, under perl, nan and Inf are considered a number. Don't believe me? Try:
# perl -MScalar::Util=looks_like_number -lE 'say looks_like_number("nan")'
$.isNumeric( NaN );
$.isNumeric( Inf );
# false (non-numeric)
$.isNumeric( "-0x42" );
$.isNumeric( "7.2acdgs" );
$.isNumeric( "" );
$.isNumeric( {} );
$.isNumeric( true );
$.isNumeric( undef );
Reference vibe check: https://api.jquery.com/jQuery.isNumeric/
π isPlainObject
Check to see if an object is a plain hash reference, and not a blessed one.
For example:
xQuery->isPlainObject({}) # true
xQuery->isPlainObject( "test" ) # false
Reference vibe check: https://api.jquery.com/jQuery.isPlainObject/
β isWindow
Determine whether the argument is a window.
Normally, this is used, under jQuery, to determine if it is operating against a browser window (such as the current window or an iframe). However, since this is perl, this is merely used to determine if the given value is a window object or not.
For example:
my $window = HTML::Object::DOM::Window->new;
$.isWindow( $window ); # true
Reference vibe check: https://api.jquery.com/jQuery.isWindow/
π§ makeArray π§
okay so bestie, a lot of methods β both in xQuery and in the HTML::Object::XQuery class in general β hand you back objects that are array-like. For example, the xQuery (jQuery) factory function $() returns an array object that has many of the properties of an array. iconic behavior, honestly.
But after the conversion, any special features that array object had (like the xQuery methods in our example) are gone. The object is now a plain array reference. vibe check: plain.
For example:
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>First</div>
<div>Second</div>
<div>Third</div>
<div>Fourth</div>
</body>
</html>
my $elems = $('div');
my $arr = xQuery->makeArray( $elems );
my $arr2 = $arr->reverse();
$(arr2)->appendTo( $document->body );
This would yield:
Fourth
Third
Second
First
πΈ map πΈ
Translate all items in an array reference or hash reference to a new array object of items that is returned. slay.
It takes an array reference or a hash reference and a code reference as a callback.
The callback will be called for each item in the array reference and 2 arguments will be passed:
- current value
- position in the array reference for an array reference, or the current hash key for a hash reference
The callback can return:
- the translated value, which will be mapped to the resulting array
$.map( $array, sub
{
return( $one_value );
});
"undef", to remove the item
$.map( $array, sub
{
return;
# or
return( undef );
});
- an array or an array reference of values, which will be flattened into the full array
$.map( $array, sub
{
return( [1, 2, 3] );
});
# same
$.map( $array, sub
{
return( 1, 2, 3 );
});
fr fr do not alter the array reference or hash reference provided while running$.map, or it might lead to unpredictable results. See theperleachmanual section for more details.
Example:
Using $.map() to change the values of an array reference:
my $arr = [ "a", "b", "c", "d", "e" ];
say join( ", ", @$arr );
This would yield:
a, b, c, d, e
# or you can also use $.map
$arr = xQuery->map( $arr, sub
{
my( $n, $i ) = @_;
return( uc( $n ) . $i );
});
say join( ", ", @$arr );
This would yield:
A0, B1, C2, D3, E4
$arr = $.map( $arr, sub
{
my( $a ) = @_;
return( $a . $a );
});
say join( ", ", @$arr );
This would yield:
A0A0, B1B1, C2C2, D3D3, E4E4
Map the original array to a new one and add 4 to each value:
$arr = $.map( [ 0, 1, 2 ], sub
{
my( $n ) = @_;
return( $n + 4 );
});
say join( ", ", @$arr );
The resulting array reference would be:
4, 5, 6
Map the original array to a new one, adding 1 to each value if it is bigger than zero and removing it if not:
$arr = $.map( [ 0, 1, 2 ], sub
{
my( $n ) = @_;
return( $n > 0 ? $n + 1 : undef );
});
say join( ", ", @$arr );
The resulting array reference would be:
2, 3
Map the original array to a new one; each element is added with its original value and the value plus one:
$arr = $.map( [ 0, 1, 2 ], sub
{
my( $n ) = @_;
return( [ $n, $n + 1 ] );
# You can also return as a list
# return( $n, $n + 1 );
});
say join( ", ", @$arr );
The resulting array reference would be:
0, 1, 1, 2, 2, 3
Map the original hash reference to a new array reference and double each value:
my $dimensions = { width => 10, height => 15, length => 20 };
$arr = $.map( $dimensions, sub
{
my( $value, $key ) = @_;
return( $value * 2 );
});
say join( ", ", @$arr );
The resulting array reference would be:
[20, 30, 40]
However, the problem in this example is that, because the order in which the hash reference keys are processed is not guaranteed by perl, the order of the values of the resulting array reference may also vary. lowkey chaotic.
If the order is important to you, you might want to consider using Tie::IxHash as mentioned in this perl FAQ https://perldoc.perl.org/perlfaq4#How-can-I-make-my-hash-remember-the-order-I-put-elements-into-it?
use Tie::IxHash;
tie my %dimensions, 'Tie::IxHash';
%dimensions = ( width => 10, height => 15, length => 20 );
$arr = $.map( \%dimensions, sub
{
my( $value, $key ) = @_;
return( $value * 2 );
});
say join( ", ", @$arr );
The resulting array reference would always predictably be:
[20, 30, 40]
Map a hash reference's keys to an array:
my $dimensions = { width => 10, height => 15, length => 20 };
my $keys = $.map( $dimensions, sub
{
my( $value, $key ) = @_;
return( $key );
});
say join( ", ", @$keys );
The resulting array reference would be:
["width", "height", "length"]
Augment the resulting array by returning an array inside the function:
my $array = [ 0, 1, 52, 97 ];
$array = $.map( $array, sub
{
my( $a, $index ) = @_;
return( [ $a - 45, $index ] );
# You can also return as a list
# return( $a - 45, $index );
});
say join( ", ", @$array );
The resulting array reference would be:
[ -45, 0, -44, 1, 7, 2, 52, 3]
https://api.jquery.com/jQuery.map/
See also https://api.jquery.com/map/ for the other "map" method used directly on a xquery object, such as:
$('div')->map(sub
{
# something
});
More details on this method upper in the "METHODS" section.
π¦ merge π¦
Merge the contents of two arrays together into the first array and returns the first array reference modified. it's giving destructive behavior, bestie.
The $.merge() operation forms an array reference that contains all elements from the two array references. The orders of items in the arrays are preserved, with items from the second array appended. The $.merge() function is destructive. It alters the length and numeric index properties of the first object to include items from the second.
If you need the original first array, make a copy of it before calling$.merge(). Fortunately,$.merge()itself can be used for this duplication:
my $newArray = $.merge([], $oldArray);
This shortcut creates a new, empty array and merges the contents of $oldArray into it, effectively cloning the array.
Examples:
Merges two arrays, altering the first argument:
$.merge( [ 0, 1, 2 ], [ 2, 3, 4 ] );
This yields:
[ 0, 1, 2, 2, 3, 4 ]
Merges two arrays, altering the first argument:
$.merge( [ 3, 2, 1 ], [ 4, 3, 2 ] );
This yields:
[ 3, 2, 1, 4, 3, 2 ]
Merges two arrays, but uses a copy, so the original is not altered:
my $first = [ "a", "b", "c" ];
my $second = [ "d", "e", "f" ];
$.merge( $.merge( [], $first ), $second );
This yields:
[ "a", "b", "c", "d", "e", "f" ]
https://api.jquery.com/jQuery.merge/
π noop π
An empty function that returns undef in scalar context or an empty list in list context.
You can use this empty function when you wish to pass around a function that will do nothing. literally the "no thoughts, head empty" of callbacks.
https://api.jquery.com/jQuery.noop/
β now β
Return a DateTime object representing the current time and that stringifies to the number of seconds since epoch, resulting into the equivalent of time in perlfunc.
Under jQuery, this is an alias for Date.now()
my $time = $.now();
say $time; # 1714619232
say $time->epoch; # 1714619232
say $time->iso8601; # 2024-05-02T03:07:12
https://api.jquery.com/jQuery.now/
π parseHTML π
Parses a string and returns an array object of HTML::Object::DOM::Element nodes. In jQuery, this parses a string into an array of DOM nodes.
This method renders all trailing or leading text (even if they are just whitespaces). To prevent trailing and leading whitespaces from being converted to space nodes you can pass the HTML string through jQuery.trim.
Under jQuery, this method takes 3 parameters (HTML string, a context document, and "keepScripts"), but since the last 2 have no bearing under perl, this method only takes a single argument: an HTML string.
For example:
my $str = "hello, <b>my name is</b> xQuery.";
my $html = $.parseHTML( $str );
my $nodeNames = [];
# Gather the parsed HTML's node names
$.each( $html, sub
{
my( $i, $el ) = @_;
$nodeNames->[$i] = el->nodeName;
}) || die( $xQuery::ERROR );
say $nodeNames->join( ', ' );
This yields:
#text, B, #text
https://api.jquery.com/jQuery.parseHTML/
π parseJSON π
Takes a well-formed JSON string and returns the resulting value, which could be a string, a number, a boolean, an array reference or a hash reference.
Passing in a malformed JSON string results in an error being returned, which can be retrieved with $xQuery::ERROR. For example, the following are all invalid JSON strings:
"{test: 1}"(testdoes not have double quotes around it)."{'test': 1}"('test'is using single quotes instead of double quotes)."'test'"('test'is using single quotes instead of double quotes).".1"(a number must start with a digit;"0.1"would be valid)."undefined"(undefinedcannot be represented in a JSON string;null, however, can be)."NaN"(NaNcannot be represented in a JSON string; direct representation ofInfinityis also not permitted).
The JSON standard does not permit "control characters" such as a tab or newline. An example like $.parseJSON( '{ "testing":"1\t2\n3" }' ) will result in an error, because the JSON parser converts the string's tab and newline escapes into literal tab and newline; doubling the backslashes like 1\\t2\\n3 yields expected results. This problem is often seen when injecting JSON into a JavaScript file from a server-side language such as PHP.
For details on the JSON format, see https://json.org/.
For example:
my $ref = $.parseJSON( '{ "name": "John" }' );
say( $ref->{name} eq 'John' );
And boom β that's the whole parseJSON vibe check: pass in JSON, get the decoded thing back. <https://api.jquery.com/jQuery.parseJSON/>
parseXML
Okay so parseXML parses a string into an XML document and hands it right back to you. π
This one requires the module XML::LibXML to be installed β no module, no XML party.
xQuery.parseXML uses XML::LibXML to create a valid XML document. This document is returned, and this is all. Unlike the jQuery interface, you cannot pass this object to HTML::Object::XQuery, such as:
my $doc = $.parseXML( $str ) || die( $xQuery::ERROR );
my $xml = $($doc);
my $title = $xml->find( 'title' );
Maybe in the future, the author will implement it. (Manifesting β¨)
<https://api.jquery.com/jQuery.parseXML/>
proxy
This method is deprecated in jQuery. π
queue
This method is unsupported with no meaning under perl. π«
removeData
Remove a previously-stored piece of data and returns undef in scalar context and an empty list in list context.
This $.removeData() method takes an element object and a name, and removes values that were previously set using $.data(). When called with the name of a key, $.removeData() deletes that particular value; when called with no arguments, all values are removed.
For example:
my $div = $('<div />');
say $div->data( 'test1' );
$.data( $div, 'test1', 'VALUE-1' );
$.data( $div, 'test2', 'VALUE-2' );
say $.data( $div, 'test1' );
$.removeData( $div, 'test1' );
say $.data( $div, 'test1' );
say $.data( $div, 'test2' );
This would yield:
undef
VALUE-1
undef
VALUE-2
trim
Remove the whitespace from the beginning and end of a string you provide. π§Ό
The $.trim() function removes all newlines, spaces (including non-breaking spaces), and tabs from the beginning and end of the supplied string. If these whitespace characters occur in the middle of the string, they are preserved.
For example:
my $str = " lots of spaces before and after ";
say "'", $.trim($str), "'";
This yields:
'lots of spaces before and after'
type
Determine the data type of a value, i.e.:
undeffor undefinedhashfor hash referencearrayfor array referencenumberfor numberbooleanfor boolean objects, such asModule::Generic::Boolean,JSON::PP::BooleandateforDateTimeobjectserrorforModule::Generic::Exception,Error,Throwable::ErrorregexpforRegexpobject, such asqr/test/stringfor anything else.
<https://api.jquery.com/jQuery.type/>
unique
Sorts an array of DOM elements, in place, with the duplicates removed. Note that, unlike its jQuery counterpart, this does work on any value, not just arrays of DOM elements. π
It returns a new array object of unique elements.
<https://api.jquery.com/jQuery.unique/>
uniqueSort
The $.uniqueSort() function searches through an array or an array-like object of DOM elements, sorting the array or array object, and removing any duplicate nodes. A node is considered a duplicate if it is the exact same node as one already in the input; two different nodes with identical attributes are not considered to be duplicates. This function only works on regular arrays or array objects of DOM elements, not on strings or numbers.
It returns a new array object of unique and sorted elements. The results are always returned in document order. β¨
This uses John Resig algorithm <https://johnresig.com/blog/comparing-document-position/> for sorting document nodes.
<https://api.jquery.com/jQuery.uniqueSort/>
PRIVATE METHODS
_append_prepend
Called by append and prepend to do the heavy work. πͺ
_append_prepend_to
Takes html string; or selector; or element object; or array of objects; or collection.
"If there is more than one target element, however, cloned copies of the inserted element will be created for each target except the last, and that new set (the original element plus clones) is returned."
Called by append_to and prepend_to to do the heavy work.
_before_after
Takes html string (start with <tag...), text object (HTML::Object::DOM::Text), array or element object or alternatively a code reference that returns the above.
_child_as_object
Called on a parent, with a child as second argument and its rank as third; returns the child if it is already an element, or a new HTML::Object::DOM::Text element if it is a plain string.
_compare
Takes another element and compares the current one to it. Returns true if they are the same, false otherwise.
It achieves this by checking if the current element eid in HTML::Object::Element is the same, or if the element is a collection it checks it is of the same size and the other element is among the collection. π΅οΈ
_css_object
If an argument is provided, pass a CSS::Object::Builder::Rule object.
If no argument is provided, get a CSS::Object::Builder::Rule of the inline css, if any at all.
Returns undef if no css attribute is set yet.
_css_builder
Returns a new CSS*:Object object using the format set to CSS::Object::Format::Inline.
_insert_before_after
Takes selector, html, element or array.
xq( '<p>Test</p>' )->insertBefore( xq( '.inner', $doc ) );
$elem->insertBefore( '.inner' );
_is_html
Returns true if the data provided looks like html, or false otherwise.
_is_same_node
Returns true if the current element and the provided element have the same eid.
_xpath_value
Returns the xpath value for the current element.
ERROR HANDLING
Methods in this package return undef either because no value is available, or because an error occurred. π
You can find out about an error after a method call by calling error, such as:
# Try to change the tag name
my $rv = $e->tag( $something );
die( $e->error ) if( !defined( $rv ) );
But keep in mind that an undefined value returned does not necessarily mean there was an error. Consider:
my $div = $('<div />', { class => 'hello' });
my $id = $div->attr( 'id' );
$id will be undefined because there is no 'id' attribute set, and this is not an error.
If you are using the global dom feature, you can get the possible errors like this:
$('#someId')->load( '/some/where.html' ) || die( HTML::Object::DOM->error );
error in HTML::Object::DOM is guaranteed to be set upon error. You can also get the global variable $HTML::Object::DOM::ERROR.
If you prefer, you can choose to make every error fatal and catch them with a try-catch implementation like Nice::Try:
use HTML::Object::DOM
$HTML::Object::DOM::FATAL_ERROR = 1;
# or
use HTML::Object::DOM fatal_error => 1;
use Nice::Try;
try
{
# Try to change the tag name
$e->tag( $something );
}
catch( $ex )
{
die( "Could not change the tag name: ", $ex->message );
}
Or, if you wanted to filter the exception by class:
try
{
# Try to change the tag name
$e->tag( $something );
}
catch( HTML::Object::Exception $ex )
{
die( "An HTML::Object::DOM error occurred: ", $ex->message );
}
catch( $ex )
{
die( "Caught an exception: $ex\n" );
}
Note that HTML::Object::Exception object has stringification capability so you can embed it in a string:
die( "Could not change the tag name: $ex\n" );
TODO
addBack
<https://api.jquery.com/addBack/>
AUTHOR
Jacques Deguest <jack@deguest.jp>
SEE ALSO
HTML::Object::DOM, HTML::Object::DOM::Attribute, HTML::Object::DOM::Boolean, HTML::Object::DOM::Closing, HTML::Object::DOM::Collection, HTML::Object::DOM::Comment, HTML::Object::DOM::Declaration, HTML::Object::DOM::Document, HTML::Object::DOM::Element, HTML::Object::Exception, HTML::Object::DOM::Literal, HTML::Object::DOM::Number, HTML::Object::DOM::Root, HTML::Object::DOM::Space, HTML::Object::DOM::Text, HTML::Object::XQuery
COPYRIGHT & LICENSE
Copyright (c) 2021 DEGUEST Pte. Ltd.
All rights reserved
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
And that's the whole manual page, bestie! π Source/version: perl v5.42.2, dated 2026-02-15 β HTML::Object::XQuery(3) out. Now go be the main character of your DOM. πβ¨
π¦ where this page comes from
- alpine 3.24: perl-html-object-doc 0.6.0-r1 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms