Skip Menu |

This queue is for tickets about the HTML-Form CPAN distribution.

Report information
The Basics
Id: 104516
Status: new
Priority: 0/
Queue: HTML-Form

People
Owner: Nobody in particular
Requestors: DAKKAR [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 6.03
Fixed in: (no value)



Subject: [patch] add indices to speed up find_input on large forms
The attached patch implements a set of indices (on input name, id, and class) to significantly speed up the find_input call for large forms. It also adds a test for a previously-untested case: that when changing the name of an input, the input is findable through the new name.
Subject: 0001-add-indices-to-speed-up-find_input-on-large-forms.patch
From 1a2fd8c106fd27b11706974cd82d93da40fba18b Mon Sep 17 00:00:00 2001 From: Gianni Ceccarelli <gianni.ceccarelli@net-a-porter.com> Date: Tue, 19 May 2015 11:49:00 +0100 Subject: [PATCH] add indices to speed up find_input on large forms --- lib/HTML/Form.pm | 50 +++++++++++++++++++++++++++++++++++++++++++------- t/form-selector.t | 3 ++- 2 files changed, 45 insertions(+), 8 deletions(-) mode change 100644 => 100755 t/form-selector.t diff --git a/lib/HTML/Form.pm b/lib/HTML/Form.pm index 0d3797f..7ec7fa0 100644 --- a/lib/HTML/Form.pm +++ b/lib/HTML/Form.pm @@ -490,11 +490,18 @@ input with the given name and/or type. sub find_input { my($self, $name, $type, $no) = @_; + my $inputs; + if (defined $name) { + $name="^$name" unless $name=~m{^[#.^]}; + $inputs=$self->{'inputs-by-key'}{$name}; + } + else { + $inputs=$self->{inputs}; + } if (wantarray) { my @res; my $c; - for (@{$self->{'inputs'}}) { - next if defined($name) && !$_->selected($name); + for (@$inputs) { next if $type && $type ne $_->{type}; $c++; next if $no && $no != $c; @@ -505,8 +512,7 @@ sub find_input } else { $no ||= 1; - for (@{$self->{'inputs'}}) { - next if defined($name) && !$_->selected($name); + for (@$inputs) { next if $type && $type ne $_->{type}; next if --$no; return $_; @@ -868,9 +874,27 @@ sub add_to_form { my($self, $form) = @_; push(@{$form->{'inputs'}}, $self); + $self->{form}=$form; + $self->_add_to_form_by_key($form,'^',$self->name); + $self->_add_to_form_by_key($form,'#',$self->id); + $self->_add_to_form_by_key($form,'.',$self->class); $self; } +sub _add_to_form_by_key { + my ($self,$form,$prefix,$key)=@_; + return unless defined $key; + push(@{$form->{'inputs-by-key'}{$prefix.$key}},$self); +} + +sub _del_from_form_by_key { + my ($self,$form,$prefix,$key)=@_; + return unless defined $key; + + @{$form->{'inputs-by-key'}{$prefix.$key}}= + grep {$_ ne $self} @{$form->{'inputs-by-key'}{$prefix.$key}}; +} + sub strict { my $self = shift; my $old = $self->{strict}; @@ -933,7 +957,11 @@ sub name { my $self = shift; my $old = $self->{name}; - $self->{name} = shift if @_; + if (@_) { + $self->_del_from_form_by_key($self->{form},'^',$old); + $self->{name}=shift; + $self->_add_to_form_by_key($self->{form},'^',$self->{name}); + } $old; } @@ -941,7 +969,11 @@ sub id { my $self = shift; my $old = $self->{id}; - $self->{id} = shift if @_; + if (@_) { + $self->_del_from_form_by_key($self->{form},'#',$old); + $self->{id}=shift; + $self->_add_to_form_by_key($self->{form},'#',$self->{id}); + } $old; } @@ -949,7 +981,11 @@ sub class { my $self = shift; my $old = $self->{class}; - $self->{class} = shift if @_; + if (@_) { + $self->_del_from_form_by_key($self->{form},'.',$old); + $self->{class}=shift; + $self->_add_to_form_by_key($self->{form},'.',$self->{class}); + } $old; } diff --git a/t/form-selector.t b/t/form-selector.t old mode 100644 new mode 100755 index 9cba445..5cdcec4 --- a/t/form-selector.t +++ b/t/form-selector.t @@ -3,7 +3,7 @@ use strict; use Test qw(plan ok); -plan tests => 12; +plan tests => 13; use HTML::Form; @@ -35,6 +35,7 @@ ok(j(map $_->value, $form->find_input(".A")), "1:2"); $form->find_input("#id2")->name("n2"); $form->value("#id2", 22); ok($form->click->uri->query, "n1=1&n2=22"); +ok($form->value('n2'),22); # try some odd names ok($form->find_input("##foo")->name, "#bar"); -- 2.0.5