package HTML::Data::Extract;

use strict; use warnings;

use base 'Markup::Processor';

use Markup;
use Alias;

use vars qw(@elements $i $e $type $tag $name @context $content $object_name);

# not sure how useful this "extract" process is going to be, oh well!

sub extract {
	my ($class, $markup) = @_;
	my $p = $class->new($markup);
	$p->{content} = undef;
	$p->{object_name} = undef;
	return $p->main_loop;
}

sub main_loop {
	my $p = attr shift;
	my $data = {};

	while(1) {
		$p->read or last;
		if ($type eq "open" && defined $name && $name !~ /^_/) {
			$object_name = $name;
			undef $content;
			$content = "" if !defined $content;
			if ($tag eq "input") {
				$p->input_extract;
			} elsif ($tag eq "textarea") {
				$p->textarea_extract;
			} elsif ($tag eq "select") {
				$p->select_extract;
			} else {
				$p->non_editable_extract;
			}
			if (defined $content) {
				$data->{$object_name} = $content;
			}
		}
	}
	return $data;
}


sub non_editable_extract {
	my $p = attr shift;
	my $guts = $p->read_container_content;

	if (@$guts > 1) {
		die "can't extract non-editable content; not plain text";
	}
	if (@$guts == 0) {
		$content = "";
	} else { # @guts == 1
		my $element = @$guts[0];
		if ($element->type ne "text") {
			die "can't extract non-editable content; not plain text";
		}
		$content = $guts->[0]->get;
	}
}

sub input_extract {
	my $p = attr shift;
	my $input_type = $e->attr_get("type") || "text";
	if ($input_type eq "submit") {
		die "submit should not have a name, or should start with _"
	} elsif ($input_type eq "checkbox" or $input_type eq "radio") {
		if ($e->attr_exists('checked')) {
			$content = 1;
		} else {
			$content = 0;
		}
	} elsif ($input_type eq "file") {
		# no value attr for a file upload,
		# can't extract anything from it
	} else {
		$content = $e->attr_get("value");
	}
}

sub textarea_extract {
	my $p = attr shift;
	if ($p->read and $type eq "text") {
		$content = $e->get;
	} else {
		$content = "";
	}
}

sub select_extract {
	my $p = attr shift;
	my $found_it;
	while(1) {
		$p->read or last;
		if ($type eq "close" && $tag eq "select") {
			last;
		}
		if ($type eq "open" && $tag eq "option") {
			my $option_e = $e;
			my $option_name = $name;
			if (!defined $option_name) {
				$p->read;
				if ($type eq "text") {
					$option_name = $e->get;
				} else {
					$option_name = "";
				}
			}
			if ($option_e->attr_exists("selected")) {
				$content = $option_name;
				$found_it = 1;
				last;
			}
		}
	}
	if (!$found_it) {
		die qq{couldn't find selected option in <select name="$object_name">};
	}
}

1
