# Copyright (c) 1999-2010 bivio Software, Inc. All rights reserved. # # Visit http://www.bivio.biz for more info. # # This library is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 2.1 of the # License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, you may get a copy from: # http://www.opensource.org/licenses/lgpl-license.html # # $Id: ViewShortcuts.pm,v 2.44 2012/01/17 00:08:05 nagler Exp $ package Bivio::UI::HTML::ViewShortcuts; use strict; #TODO: Should be UI.ViewShortcuts or UIHTML, but can't do this right now use Bivio::Base 'Bivio::UI::ViewShortcuts'; use Bivio::IO::Trace; our($VERSION) = sprintf('%d.%02d', q$Revision: 2.44 $ =~ /\d+/g); my($_WF) = b_use('Bivio::UI::HTML::WidgetFactory'); my($_V6) = b_use('IO.Config')->if_version(6); my($_LINK_TARGET) = $_V6 ? undef : '_top'; my($_ATTRS) = {}; our($_TRACE); my($_AA) = b_use('Action.Acknowledgement'); sub BOP_HTML_CLASSES { return [qw( acknowledgement actions all want_sep alphabetical_chooser amount_cell ascend attachment author blog body bottom bottom_left bottom_right byline checkbox checkbox_label date desc descend empty_list err_title even excerpt field field_err footer footer_left footer_middle footer_right form_prose forward go header header_left header_middle header_right heading help_wiki_add inline label label_err label_ok list list_actions logo logo_su main main_body main_bottom main_left main_middle main_right main_top menu msg msg_compose msg_sep nav next not_found num odd off on paged_list pager part parts prev prose realm required rounded_box rounded_box_body search selected selector sep user_settings simple standard_submit su submit task_menu text text_html text_plain textarea title tools top top_left top_right topic tuple user_state value want_sep )]; } sub vs_alphabetical_chooser { # (proto, string) : UI.Widget # Generates a list of links which are alphabetically ordered and pass their # "letter" on to the ListQuery.search. my($proto, $list_model) = @_; my($all) = Bivio::Biz::Model->get_instance($list_model) ->LOAD_ALL_SEARCH_STRING; return $proto->vs_call('String', $proto->vs_call('Join', [ map({( $_ =~ /^A/ ? $_ eq $all ? ' | ' : '' : ' ', $proto->vs_call('Link', $proto->vs_call('Join', [$_]), ['->format_uri', undef, [sub { return { 'ListQuery.search' => $_[1], 'ListQuery.date' => $_[0]->get($_[2]) ->get_query->get('date'), }; }, $_, "Model.$list_model", ], ], ), )} 'A'..'Z', $all), ]), ); } sub vs_blank_cell { # (proto) : UI.Widget # (proto, int) : UI.Widget # Returns a cell which renders a blank. Makes the code clearer to use. my($proto, $count) = @_; return $proto->vs_join(' ' x ($count || 1)); } sub vs_clear_dot { # (self, any, any) : Widget.ClearDot # (self, any, any) : Widget.ClearDot # B>. my($proto, $width, $height) = @_; return $proto->vs_new('ClearDot', { defined($width) ? (width => $width) : (), defined($height) ? (height => $height) : (), }); } sub vs_clear_dot_as_html { # (self, int, int) : string # Returns an html string which loads a ClearDot image in # width and height. # # Don't use in rendering code. Use L instead. my(undef) = shift; my($c) = _use('ClearDot'); return $c->as_html(@_); } sub vs_correct_table_layout_bug { # (self) : UI.Widget # Returns a widget which renders a table layout correction javascript if # necessary. my($proto) = @_; return $proto->vs_call('If', [['->get_request'], 'Type.UserAgent', '->has_table_layout_bug'], $proto->vs_call('Script', 'correct_table_layout_bug')); } sub vs_descriptive_field { # (proto, any) : array_ref # Calls vs_form_field and adds I to the result. I # is an optional string, widget value, or widget. It is always wrapped # in a String with font form_field_description. my($proto, $field) = @_; my($name, $attrs) = ref($field) ? @$field : $field; my($label, $input) = $proto->vs_form_field($name, $attrs); return [ $label->put(cell_class => 'form_field_label'), $proto->vs_call('Join', [ $input, [sub { my($req) = shift->get_request; my($proto, $name) = @_; #TODO: Need to create a separate space for field_descriptions so we don't # default to something that we don't expect. my($v) = $req->get_nested('Bivio::UI::Facade', 'Text') ->unsafe_get_value($name, 'field_description'); return $v ? $proto->vs_call( 'String', $proto->vs_call('Prose', '

' . $v . '

'), 'form_field_description', ) : ''; }, $proto, $name], ], { cell_class => 'form_field_input', }), ]; } sub vs_director { # (proto, any, hash_ref, UI.Widget, UI.Widget) : UI.Widget # B>. my($proto) = shift; return $proto->vs_new('Director', @_); } sub vs_display { return _wf(@_); } sub vs_edit { return _wf(@_); } sub vs_escape_html { # (self, array_ref) : array_ref # Wraps I in L, my(undef, $value) = @_; return [\&_escape, $value]; } sub vs_fe { # (proto, string) : string # Calls SUPER and escapes. return Bivio::HTML->escape(shift->SUPER::vs_fe(@_)); } sub vs_first_focus { # (proto, any) : UI.Widget # Returns script widget that focuses on the first field on the page. # I is optional. my($proto, $control) = @_; my($w) = $proto->vs_call('Script', 'first_focus'); return defined($control) ? $proto->vs_call('If', $control, $w) : $w; } sub vs_form_field { # (proto, string) : array # Creates a new I and returns the widgets (label, field). # This is equivalent to: # # vs_new('FormField', @_)->get_label_and_field my($proto) = shift; return $proto->vs_new('FormField', @_)->get_label_and_field; } sub vs_html_attrs_initialize { my($proto, $widget, $attrs, $source) = @_; $widget->map_invoke( 'unsafe_initialize_attr', $attrs || $proto->vs_html_attrs_merge, undef, [$source], ); return; } sub vs_html_attrs_merge { my(undef, $extra) = @_; return [qw(class id), @{$extra || []}]; } sub vs_html_attrs_render { my($proto, $widget, $source, $attrs) = @_; return join( '', map($proto->vs_html_attrs_render_one($widget, $source, $_), @{$attrs || $proto->vs_html_attrs_merge}), ); } sub vs_html_attrs_render_one { my($proto, $widget, $source, $attr) = @_; return '' unless length(my $v = $widget->render_simple_attr($attr, $source)); my($k) = $attr =~ /^[A-Z]/ ? lc($attr) : ($attr =~ /([^_]+)$/)[0]; if ($k =~ /^(?:class|id)$/) { _trace($k, '=', $v) if $_TRACE && !$_ATTRS->{$k}->{$v}++; $v =~ s/^b_// unless $_V6; } return ' ' . $k . '="' . Bivio::HTML->escape_attr_value($v) . '"'; } sub vs_image { # (proto, any) : Widget.Image # (proto, any, any, hash_ref) : Widget.Image # B>. my($proto, $icon, $alt, $attrs) = @_; _use('Image'); return Bivio::UI::HTML::Widget::Image->new({ src => $icon, (defined($alt) || ref($icon) ? (alt => $alt) : (alt_text => $icon)), $attrs ? %$attrs : (), }); } sub vs_join { # (proto, any, ...) : Widget.Join # B>. my($proto, @values) = @_; my($values) = int(@values) == 1 && ref($values[0]) eq 'ARRAY' ? $values[0] : [@values]; return $proto->vs_new('Join', $values); } sub vs_link { # (proto, string) : Widget.Link # (proto, any, string) : Widget.Link # (proto, any, string, string) : Widget.Link # (proto, any, array_ref) : Widget.Link # (proto, any, UI.Widget) : Widget.Link # (proto, any, string) : Widget.Link # If only I is supplied, it is used for both the label and the href. # It will also be the control for the link. This is the preferred way # to create links. # # Returns a C with I