Skip to content

Commit 33a6b57

Browse files
author
Carlos Fernando Avila Gratz
committed
before/insert_before fully implemented
1 parent de64a99 commit 33a6b57

File tree

6 files changed

+134
-130
lines changed

6 files changed

+134
-130
lines changed

Changes

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ Revision history for Perl extension XML::LibXML::jQuery
22

33
{{$NEXT}}
44

5-
- fixed after(content[, content]) signature
6-
- implemented after(function) signature
7-
- insert_after(target) signature fully implemented
5+
- fixed before/after(content[, content]) signature
6+
- implemented before/after(function) signature
7+
- insert_before/insert_after(target) signature fully implemented
88
- target = selector, element, arrayref of elements, HTML string, or jQuery object
99

1010
0.02 2016-06-26T15:07:06Z

README.md

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,32 @@ Unless otherwise noted, all methods behave exactly like the javascript version.
7777

7878
Implemented signatures:
7979

80-
- **add**(Str **selector**)
81-
- **add**(Str **selector**, XML::LibXML::jQuery **context**)
82-
- **add**(Str **html**)
83-
- **add**(ArrayRef\[[XML::LibXML::Node](https://metacpan.org/pod/XML::LibXML::Node)\] **elements**)
84-
- **add**(XML::LibXML::jQuery **selection**)
80+
- add(selector)
81+
- add(selector, [context](https://metacpan.org/pod/XML::LibXML::jQuery))
82+
- add(html)
83+
- add([elements](https://metacpan.org/pod/XML::LibXML::Node))
84+
- add([selection](https://metacpan.org/pod/XML::LibXML::jQuery))
8585

8686
Documentation and examples at [http://api.jquery.com/add/](http://api.jquery.com/add/).
8787

8888
## add\_class
8989

90+
Implemented signatures:
91+
92+
- add\_class(className)
93+
- add\_class(function)
94+
95+
Documentation and examples at [http://api.jquery.com/addClass/](http://api.jquery.com/addClass/).
96+
9097
## after
9198

99+
Implemented signatures:
100+
101+
- after(content\[, content\])
102+
- after(function)
103+
104+
Documentation and examples at [http://api.jquery.com/after/](http://api.jquery.com/after/).
105+
92106
## append
93107

94108
## append\_to
@@ -109,9 +123,9 @@ Documentation and examples at [http://api.jquery.com/add/](http://api.jquery.com
109123

110124
Implemented signatures:
111125

112-
- **data**(Str **key**, Any **value**)
113-
- **data**(Str **key**)
114-
- **data**(HashRef **obj**)
126+
- data(key, value)
127+
- data(key)
128+
- data(obj)
115129

116130
Documentation and examples at [http://api.jquery.com/data/](http://api.jquery.com/data/).
117131

@@ -133,6 +147,14 @@ Documentation and examples at [http://api.jquery.com/data/](http://api.jquery.co
133147

134148
## insert\_after
135149

150+
Implemented signatures:
151+
152+
- insert\_after(target)
153+
154+
All targets supported: selector, element, array of elements, HTML string, or jQuery object.
155+
156+
Documentation and examples at [http://api.jquery.com/insertAfter/](http://api.jquery.com/insertAfter/).
157+
136158
## insert\_before
137159

138160
## filter

lib/XML/LibXML/jQuery.pm

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use HTML::Selector::XPath qw/selector_to_xpath/;
1010
use Carp qw/ confess /;
1111
use JSON qw/ decode_json /;
1212

13-
our $VERSION = "0.02";
13+
our $VERSION = "0.03";
1414
our @EXPORT = qw/ j /;
1515

1616
use constant {
@@ -476,42 +476,56 @@ sub _prepend_to {
476476

477477
sub before {
478478
my $self = shift;
479-
_insert_before($self->new(@_)->{nodes}, $self->{nodes});
479+
my $content = ref $_[0] eq 'CODE'
480+
? $_[0]
481+
: [map { @{ $self->new($_)->{nodes} } } @_];
482+
483+
$self->_insert_before($content, $self->{nodes});
480484
$self;
481485
}
482486

483487
sub insert_before {
484-
my $self = shift;
485-
_insert_before($self->{nodes}, (ref $self)->new(@_)->{nodes});
488+
my ($self, $target) = @_;
489+
$target = _is_selector($target) ? $self->document->find($target)
490+
: (ref $self)->new($target);
491+
492+
$self->_insert_before($self->{nodes}, $target->{nodes});
486493
$self;
487494
}
488495

489496
sub _insert_before {
490-
my ($content, $target) = @_;
491-
return unless @$content;
497+
my ($self, $content, $target) = @_;
498+
return if ref $content eq 'ARRAY' && @$content == 0;
492499

493500
for (my $i = 0; $i < @$target; $i++) {
494501

495502
my $is_last = $i == $#$target;
496503
my $node = $target->[ $i ];
497504
my $parent = $node->parentNode;
505+
my $items;
498506

499-
# content is cloned except for last target
500-
my @items = $i == $#$target ? @$content : map { $_->cloneNode(1) } @$content;
507+
if (ref $content eq 'CODE') {
508+
local $_ = $node;
509+
$items = (ref $self)->new($content->($i, $_))->{nodes};
510+
}
511+
else {
512+
# content is cloned except for last target
513+
$items = $i == $#$target ? $content : [map { $_->cloneNode(1) } @$content];
514+
}
501515

502516
# thats because insertAfter() is not supported on a Document node (as of XML::LibXML 2.0017)
503517
unless ($parent->isa('XML::LibXML::Document')) {
504518

505-
$parent->insertBefore($_, $node) for @items;
519+
$parent->insertBefore($_, $node) for @$items;
506520
next;
507521
}
508522

509523
# workaround for when parent is document:
510524
# append nodes then rotate until content is before node
511-
$parent->lastChild->addSibling($_) for @items;
525+
$parent->lastChild->addSibling($_) for @$items;
512526

513527
my $next = $node;
514-
while (not $next->isSameNode($items[0])) {
528+
while (not $next->isSameNode($items->[0])) {
515529
my $node_to_move = $next;
516530
$next = $node_to_move->nextSibling;
517531
$parent->lastChild->addSibling($node_to_move);

t/before.pl

Lines changed: 0 additions & 88 deletions
This file was deleted.

t/before.t

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,63 @@ use Test::More;
66
use XML::LibXML::jQuery;
77

88

9+
sub test(&@);
910

1011
my $html = '<div class="container"><h2>Greetings</h2><div class="inner">Hello</div><div class="inner">Goodbye</div></div>';
1112

12-
is j($html)->find('.inner')->before('<p>Test</p>')->end->as_html,
13-
'<div class="container"><h2>Greetings</h2><p>Test</p><div class="inner">Hello</div><p>Test</p><div class="inner">Goodbye</div></div>', 'after';
13+
# before(html)
14+
test { $_->find('h2, .inner')->before('<p/>') } 'before(html)';
1415

15-
my $j = j($html);
16-
is $j->find('.inner')->before($j->find('h2'))->end->as_html, '<div class="container"><h2>Greetings</h2><div class="inner">Hello</div><h2>Greetings</h2><div class="inner">Goodbye</div></div>', 'existing element';
16+
test { $_->find('h2, .inner')->before(j('<p/>')) } 'before(jQuery)';
1717

18-
# document
19-
$j = j('<div/><div/><div/>');
20-
j($j->get(0))->before('<span/>');
21-
is $j->document->as_html, "<span></span><div></div><div></div><div></div>\n", 'on root node - node is first child';
18+
test {
19+
my $p = $_->new('<p/>')->append_to($_);
20+
$_->find('h2, .inner')->before($p);
21+
} 'before(jQuery) (existing node)';
2222

23-
# document
24-
$j = j('<foo/><bar/><baz/>');
25-
j($j->get(1))->before('<span/>');
26-
is $j->document->as_html, "<foo></foo><span></span><bar></bar><baz></baz>\n", 'on root node - not first child';
23+
test { $_->find('.inner')->before( j('<one/>'), '<two/>', $_->{document}->createElement('three')) }
24+
'before(jQuery, html, DOMElement)',
25+
'<div class="container"><h2>Greetings</h2><one></one><two></two><three></three><div class="inner">Hello</div><one></one><two></two><three></three><div class="inner">Goodbye</div></div>';
2726

28-
# document
29-
is j('<foo/><bar/><baz/>')->before('<span/>')->document->as_html, "<span></span><foo></foo><span></span><bar></bar><span></span><baz></baz>\n", 'on multiple root node';
27+
test {
28+
29+
$_->find('.inner')->before(sub {
30+
my $i = shift;
31+
sprintf "<%s-%s>", lc $_->textContent, $i;
32+
})
33+
34+
} 'before(function)' => '<div class="container"><h2>Greetings</h2><hello-0></hello-0><div class="inner">Hello</div><goodbye-1></goodbye-1><div class="inner">Goodbye</div></div>';
35+
36+
37+
subtest 'root nodes' => sub {
38+
39+
# document
40+
my $j = j('<div/><div/><div/>');
41+
j($j->get(0))->before('<span/>');
42+
is $j->document->as_html, "<span></span><div></div><div></div><div></div>\n", 'on root node - node is first child';
43+
44+
# document
45+
$j = j('<foo/><bar/><baz/>');
46+
j($j->get(1))->before('<span/>');
47+
is $j->document->as_html, "<foo></foo><span></span><bar></bar><baz></baz>\n", 'on root node - not first child';
48+
49+
# document
50+
is j('<foo/><bar/><baz/>')->before('<span/>')->document->as_html, "<span></span><foo></foo><span></span><bar></bar><span></span><baz></baz>\n", 'on multiple root node';
51+
52+
};
53+
54+
55+
56+
57+
58+
sub test (&@) {
59+
my ($cb, $name, $expected) = @_;
60+
61+
$expected ||= '<div class="container"><p></p><h2>Greetings</h2><p></p><div class="inner">Hello</div><p></p><div class="inner">Goodbye</div></div>';
62+
my $j = j($html);
63+
local $_ = $j;
64+
$cb->($j);
65+
is $j->as_html, $expected, $name;
66+
}
3067

3168
done_testing;

t/insert_before.t

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,36 @@ use Test::More;
66
use XML::LibXML::jQuery;
77

88

9+
10+
sub test (&@);
911
my $html = '<div class="container"><h2>Greetings</h2><div class="inner">Hello</div><div class="inner">Goodbye</div></div>';
12+
my $expected = '<div class="container"><p></p><h2>Greetings</h2><p></p><div class="inner">Hello</div><p></p><div class="inner">Goodbye</div></div>';
13+
14+
15+
test { $_->new('<p/>')->insert_before($_->find('h2, .inner')->{nodes}) } 'insert_before(arrayref)';
16+
17+
test { $_->new('<p/>')->insert_before($_->find('.inner')->add('h2')) } 'insert_before(jQuery)';
18+
19+
test { $_->new('<p/>')->insert_before('h2, .inner') } 'insert_before(selector)';
1020

11-
my $j = j($html);
1221

13-
j('<p>Test</p>')->insert_before($j->find('.inner'));
22+
$expected = '<div class="container"><div class="inner">Hello</div><h2>Greetings</h2><div class="inner">Goodbye</div></div>';
1423

15-
is $j->as_html,
16-
'<div class="container"><h2>Greetings</h2><p>Test</p><div class="inner">Hello</div><p>Test</p><div class="inner">Goodbye</div></div>', 'new content';
24+
test { $_->find('h2')->insert_before('.inner:last-child') } 'insert_before(selector) (move)';
1725

18-
$j = j($html);
19-
is $j->find('h2')->insert_before($j->find('.inner'))->end->as_html, '<div class="container"><h2>Greetings</h2><div class="inner">Hello</div><h2>Greetings</h2><div class="inner">Goodbye</div></div>', 'existing element';
26+
test { $_->find('h2')->insert_before($_->find('.inner:last-child')->get(0)) } 'insert_before(element)';
2027

2128

2229
done_testing;
30+
31+
32+
33+
34+
sub test (&@) {
35+
my ($cb, $name) = @_;
36+
37+
my $j = j($html);
38+
local $_ = $j;
39+
$cb->($j);
40+
is $j->as_html, $expected, $name;
41+
}

0 commit comments

Comments
 (0)