JQuery-Mobile
view release on metacpan or search on metacpan
lib/JQuery/Mobile.pm view on Meta::CPAN
package JQuery::Mobile;
use strict;
use warnings;
no warnings 'uninitialized';
use Exporter 'import';
our @EXPORT_OK = qw(new head header footer table panel popup page pages form listview collapsible collapsible_set navbar button controlgroup input rangeslider select checkbox radio textarea);
use Clone qw(clone);
use HTML::Entities qw(encode_entities);
our $VERSION = 0.03;
# 54.4
sub new {
my ($class, %args) = (@_);
my $self = bless {}, $class;
$args{config} ||= {};
$self->{config} = {
'head' => 1, # include <html>, <head>, and <body> tag when rendering a page
'viewport' => 'width=device-width, initial-scale=1', # default viewport
'apple-mobile-web-app-capable' => 1, # enable as apple web app
'apple-touch-icon' => '', # path to apple web app icon image
'apple-touch-icon-72' => '', # path to apple web app icon image (72x72 pixels)
'apple-touch-icon-114' => '', # path to apple web app icon image (114x114 pixels)
'apple-touch-startup-image' => '', # path to apple web app startup image
'jquery-mobile-css' => 'http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css',
'jquery-mobile-js' => 'http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js',
'jquery' => 'http://code.jquery.com/jquery-1.9.1.min.js',
'app-css' => [], # global application CSS files
'app-js' => [], # global application JS files
'app-inline-css' => ' span.invalid{color:#F00000;line-height: 1.5;}', # inline CSS code
'app-inline-js' => '', # inline JS code
'app-title' => '', # <title> in <head>
# a list of default allowed HTML and data-* attributes for UI components (Reference: http://api.jquerymobile.com/data-attribute/)
'header-footer-html-attribute' => ['id', 'class'],
'header-footer-data-attribute' => ['id', 'fullscreen', 'position', 'theme'],
'navbar-html-attribute' => ['id', 'class'],
'navbar-data-attribute' => ['disable-page-zoom', 'enhance', 'fullscreen', 'iconpos', 'tap-toggle', 'theme', 'transition', 'update-page-padding', 'visible-on-page-show'],
'navbar-item-html-attribute' => ['id', 'class', 'target'],
'navbar-item-data-attribute' => ['ajax', 'icon', 'iconpos', 'iconshadow','prefetch', 'theme'],
'page-html-attribute' => ['id', 'class'],
# combine data-attributes for page and dialog
'page-data-attribute' => ['add-back-btn', 'back-btn-text', 'back-btn-theme', 'close-btn', 'close-btn-text', 'corners', 'dom-cache', 'enhance', 'overlay-theme', 'role', 'shadow','theme', 'title', 'tolerance', 'url'],
'table-html-attribute' => ['id', 'class'],
'table-data-attribute' => ['mode'],
'table-head-html-attribute' => ['id', 'class'],
'table-head-data-attribute' => ['priority'],
'panel-html-attribute' => ['id', 'class'],
'panel-data-attribute' => ['corners', 'overlay-theme', 'shadow', 'theme', 'tolerance', 'position-to', 'rel', 'role', 'transition'],
'popup-html-attribute' => ['id', 'class'],
'popup-data-attribute' => ['animate', 'dismissible', 'display', 'position', 'position-fixed', 'swipe-close', 'role', 'theme'],
'listview-html-attribute' => ['id', 'class'],
'listview-data-attribute' => ['autodividers', 'count-theme', 'divider-theme', 'enhance', 'filter', 'filter-placeholder', 'filter-reveal', 'filter-theme', 'filtertext', 'header-theme', 'inset', 'split-icon', 'split-theme', 'theme'],
'listview-item-html-attribute' => ['id', 'class'],
'listview-item-data-attribute' => ['ajax', 'mini', 'rel', 'theme', 'transition'],
'collapsible-html-attribute' => ['id', 'class'],
'collapsible-data-attribute' => ['collapsed', 'collapsed-icon', 'content-theme', 'expanded-icon', 'iconpos', 'inset', 'mini', 'theme'],
'collapsible-set-html-attribute' => ['id', 'class'],
'collapsible-set-data-attribute' => ['collapsed-icon', 'content-theme', 'expanded-icon', 'iconpos', 'inset', 'mini', 'theme'],
'controlgroup-html-attribute' => ['id', 'class'],
'controlgroup-data-attribute' => ['enhance', 'iconpos', 'mini', 'theme', 'type'],
'button-html-attribute' => ['id', 'name', 'class', 'maxlength', 'size', 'type', 'value'],
'button-html-anchor-attribute' => ['id', 'class', 'href', 'target'],
'button-data-attribute' => ['ajax', 'corners', 'dialog', 'direction', 'dom-cache', 'external', 'icon', 'iconpos', 'iconshadow', 'inline', 'mini', 'position-to', 'prefetch', 'rel', 'role', 'shadow', 'theme', 'transition'],
'form-html-attribute' => ['id', 'action', 'class', 'enctype', 'method'],
'form-data-attribute' => ['enhance', 'theme', 'ajax'],
'input-html-attribute' => ['id', 'class', 'disabled', 'max', 'maxlength', 'min', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'size', 'type', 'value', 'accept', 'capture'],
'input-data-attribute' => ['clear-btn', 'clear-btn-text', 'corners', 'highlight', 'icon', 'iconpos', 'iconshadow', 'inline', 'mini', 'shadow', 'theme', 'track-theme'],
'textarea-html-attribute' => ['id', 'name', 'class', 'rows', 'cols', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern'],
'textarea-data-attribute' => ['clear-btn', 'clear-btn-text', 'mini', 'theme'],
'select-html-attribute' => ['id', 'class', 'size', 'maxlength', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern', 'multiple'],
'select-data-attribute' => ['icon', 'iconpos', 'inline', 'mini', 'native-menu', 'overlay-theme', 'theme', 'role'],
'radio-checkbox-html-attribute' => ['id', 'class', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern', 'value'],
'radio-checkbox-data-attribute' => ['mini', 'theme'],
'rangeslider-html-attribute' => ['id', 'name', 'class'],
'rangeslider-data-attribute' => ['highlight', 'mini', 'theme', 'track-theme'],
'label' => sub {
my $args = shift;
return '<strong>' . $args->{label} . '</strong>' if $args->{required};
return $args->{label};
},
'invalid' => sub {
my $args = shift;
my $message = $args->{message};
if (! $message && $args->{type}) {
$message = {
'input' => 'Enter "%FIELDNAME%"',
'checkbox' => 'Check one or more "%FIELDNAME%"',
'radio' => 'Choose "%FIELDNAME%"',
'select' => 'Select an option from "%FIELDNAME%"',
'textarea' => 'Fill in the "%FIELDNAME%"'
}->{$args->{type}};
}
$message ||= 'Enter "%FIELDNAME%"';
$message =~ s/\%FIELDNAME\%/$args->{label}/g;
return '<span class="invalid">' . $message . '</span>' if $args->{invalid};
},
%{$args{config}},
};
return $self;
}
sub head {
my ($self, %args) = @_;
my $head = ' <head>' . "\n" . ' <title>' . $self->{config}->{'app-title'} . '</title>' . "\n" .
' <meta name="viewport" content="' . $self->{config}->{'viewport'} . '" />' . "\n";
# apple icons, startup image
$head .= ' <meta name="apple-mobile-web-app-capable" content="yes" />' . "\n" if $self->{config}->{'apple-mobile-web-app-capable'};
$head .= ' <link rel="apple-touch-icon" href="' . $self->{config}->{'apple-touch-icon'} . '" />' . "\n" if $self->{config}->{'apple-touch-icon'};
$head .= ' <link rel="apple-touch-icon" sizes="72x72" href="' . $self->{config}->{'apple-touch-icon-72'} . '" />' . "\n" if $self->{config}->{'apple-touch-icon-72'};
$head .= ' <link rel="apple-touch-icon" sizes="114x114" href="' . $self->{config}->{'apple-touch-icon-114'} . '" />' . "\n" if $self->{config}->{'apple-touch-icon-114'};
$head .= ' <link rel="apple-touch-startup-image" href="' . $self->{config}->{'apple-touch-startup-image'} . '" />' . "\n" if $self->{config}->{'apple-touch-startup-image'};
my $css_sources = [$self->{config}->{'jquery-mobile-css'}];
push @{$css_sources}, @{$self->{config}->{'app-css'}}, if @{$self->{config}->{'app-css'}};
foreach my $css (@{$css_sources}) {
$head .= ' <link rel="stylesheet" href="' . $css . '" />' . "\n";
}
my $js_sources = [$self->{config}->{'jquery'}, $self->{config}->{'jquery-mobile-js'}];
push @{$js_sources}, @{$self->{config}->{'app-js'}}, if @{$self->{config}->{'app-js'}};
foreach my $js (@{$js_sources}) {
$head .= ' <script src="' . $js . '"></script>' . "\n" if $js;
}
lib/JQuery/Mobile.pm view on Meta::CPAN
id => 'home',
header => {content => '<h1>Home</h1>'},
content => $list
},
{
id => 'item-link',
header => {content => '<h1>Item Heading</h1>'},
content => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit'
},
]
);
=head1 DESCRIPTION
JQuery::Mobile is an interface to jQuery Mobile. It generates HTML markups, such as navbars, forms, and listviews, that are compatible with jQuery Mobile.
=head1 METHODS
=head2 C<new>
To instantiate a new JQuery::Mobile object:
my $jquery_mobile = JQuery::Mobile->new();
Here is a list of optional parameters when instantiating a JQuery::Mobile object:
# default values are shown
my $jquery_mobile = JQuery::Mobile->new(
config => {
'head' => 1, # include <html>, <head>, and <body> tag when rendering a page
'viewport' => 'width=device-width, initial-scale=1', # default viewport
'apple-mobile-web-app-capable' => 1, # enable as apple web app
'apple-touch-icon' => '', # path to apple web app icon image
'apple-touch-icon-72' => '', # path to apple web app icon image (72x72 pixels)
'apple-touch-icon-114' => '', # path to apple web app icon image (114x114 pixels)
'apple-touch-startup-image' => '', # path to apple web app startup image
'jquery-mobile-css' => 'http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css',
'jquery-mobile-js' => 'http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js',
'jquery' => 'http://code.jquery.com/jquery-1.9.1.min.js',
'app-css' => [], # global application CSS files
'app-js' => [], # global application JS files
'app-inline-css' => ' span.invalid{color:#F00000;line-height: 1.5;}', # inline CSS code
'app-inline-js' => '', # inline JS code
'app-title' => '', # <title> in <head>
}
);
The allowed HTML and data-* attributes for each UI component can be customised. By default, HTML attributes are very strict to ensure a clean markup. For data-* attributes, see reference: http://api.jquerymobile.com/data-attribute/.
# default values are shown
my $jquery_mobile = JQuery::Mobile->new(
config => {
'header-footer-html-attribute' => ['id', 'class'],
'header-footer-data-attribute' => ['id', 'fullscreen', 'position', 'theme'],
'navbar-html-attribute' => ['id', 'class'],
'navbar-data-attribute' => ['disable-page-zoom', 'enhance', 'fullscreen', 'iconpos', 'tap-toggle', 'theme', 'transition', 'update-page-padding', 'visible-on-page-show'],
'navbar-item-html-attribute' => ['id', 'class', 'target'],
'navbar-item-data-attribute' => ['ajax', 'icon', 'iconpos', 'iconshadow','prefetch', 'theme'],
'page-html-attribute' => ['id', 'class'],
# combine data-attributes for page and dialog
'page-data-attribute' => ['add-back-btn', 'back-btn-text', 'back-btn-theme', 'close-btn', 'close-btn-text', 'corners', 'dom-cache', 'enhance', 'overlay-theme', 'role', 'shadow','theme', 'title', 'tolerance', 'url'],
'popup-html-attribute' => ['id', 'class'],
'popup-data-attribute' => ['corners', 'overlay-theme', 'shadow', 'theme', 'tolerance', 'position-to', 'rel', 'role', 'transition'],
'listview-html-attribute' => ['id', 'class'],
'listview-data-attribute' => ['autodividers', 'count-theme', 'divider-theme', 'enhance', 'filter', 'filter-placeholder', 'filter-theme', 'filtertext', 'header-theme', 'inset', 'split-icon', 'split-theme', 'theme'],
'listview-item-html-attribute' => ['id', 'class'],
'listview-item-data-attribute' => ['ajax', 'mini', 'rel', 'theme', 'transition'],
'collapsible-html-attribute' => ['id', 'class'],
'collapsible-data-attribute' => ['collapsed', 'collapsed-icon', 'content-theme', 'expanded-icon', 'iconpos', 'inset', 'mini', 'theme'],
'collapsible-set-html-attribute' => ['id', 'class'],
'collapsible-set-data-attribute' => ['collapsed-icon', 'content-theme', 'expanded-icon', 'iconpos', 'inset', 'mini', 'theme'],
'controlgroup-html-attribute' => ['id', 'class'],
'controlgroup-data-attribute' => ['enhance', 'iconpos', 'theme', 'type'],
'button-html-attribute' => ['id', 'name', 'class', 'maxlength', 'size', 'type', 'value'],
'button-html-anchor-attribute' => ['id', 'class', 'href', 'target'],
'button-data-attribute' => ['ajax', 'corners', 'dialog', 'direction', 'dom-cache', 'external', 'icon', 'iconpos', 'iconshadow', 'inline', 'mini', 'position-to', 'prefetch', 'rel', 'role', 'shadow', 'theme', 'transition'],
'form-html-attribute' => ['id', 'action', 'class', 'enctype', 'method'],
'form-data-attribute' => ['enhance', 'theme', 'ajax'],
'input-html-attribute' => ['id', 'class', 'disabled', 'max', 'maxlength', 'min', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'size', 'type', 'value', 'accept', 'capture'],
'input-data-attribute' => ['clear-btn', 'clear-btn-text', 'corners', 'highlight', 'icon', 'iconpos', 'iconshadow', 'inline', 'mini', 'shadow', 'theme', 'track-theme'],
'textarea-html-attribute' => ['id', 'name', 'class', 'rows', 'cols', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern'],
'textarea-data-attribute' => ['clear-btn', 'clear-btn-text', 'mini', 'theme'],
'select-html-attribute' => ['id', 'class', 'size', 'maxlength', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern'],
'select-data-attribute' => ['icon', 'iconpos', 'inline', 'mini', 'native-menu', 'overlay-theme', 'placeholder', 'theme'],
'radio-checkbox-html-attribute' => ['id', 'class', 'readonly', 'disabled', 'title', 'required', 'placeholder', 'title', 'pattern', 'value'],
'radio-checkbox-data-attribute' => ['mini', 'theme']
}
);
The C<label> parameter accepts a sub callback to alter how form field labels are being generated:
my $jquery_mobile = JQuery::Mobile->new(
config => {
'label' => sub {
my $args = shift;
return '<strong>' . $args->{label} . '*</strong>' if $args->{required};
return $args->{label};
},
}
);
=head2 C<head>
C<head()> is called by C<page()> and C<pages()> internally to render the HTML header. Parameters via C<new()> controlls the output of C<head()>.
=head2 C<header>
C<header()> generates header toolbars. Text, buttons, or C<navbar()> can be passed to the C<content> parameter.
print $jquery_mobile->header(
content => $jquery_mobile->button(href => '#', value => 'Home', icon => 'home', iconpos => 'notext') . '<h1>Main Title</h1>',
);
prints:
<div data-role="header">
<a data-icon="home" data-iconpos="notext" data-role="button" href="#">Home</a>
<h1>Main Title</h1>
</div><!-- /header -->
Attributes defined in C<header-footer-html-attribute> and C<header-footer-data-attribute> can be passed to C<header()>, based on the default configuration:
print $jquery_mobile->header(
'content' => '<h1>Header Content</h1>',
'id' => 'home-main-header',
'class' => 'site-header',
'data-id' => 'main-header', # use the 'data-*' prefix since 'id' is both a HTML and data atrribute
'fullscreen' => 'true',
'position' => 'fixed',
'theme' => 'e'
);
=head2 C<footer>
Similar to C<header()>, C<footer()> generates footer toolbars. Attributes defined in C<header-footer-html-attribute> and C<header-footer-data-attribute> can be passed to C<footer()>.
print $jquery_mobile->footer(
position => 'fixed',
content => 'Footer content'
);
=head2 C<popup>
C<popup()> generates popup container divs. Content can be passed via the C<content> parameter:
( run in 1.246 second using v1.01-cache-2.11-cpan-df04353d9ac )