Krang::ElementClass - base class for Krang element classes
package ElementSet::element_name; use Krang::ClassLoader base => 'ElementClass';
# override new() to setup element class parameters
sub new {
my $pkg = shift;
my %opt = (name => "element_name", @_);
return $pkg->SUPER::new(%opt);
}
1;
This class serves as the base class for all Krang Element classes.
Element classes are created by inheriting from this class or one of
its sub-classes (Krang::ElementClass::SelectBox, for example).
Sub-classes must override several methods and setup the required
'name' attribute by overriding new().
For a higher-level overview of the Krang element system, see docs/element_system.pod.
Krang::ElementClass objects have the following attributes, available through the standard Krang::MethodMaker accessors. Sub-classes may add new attributes as needed to implement their functionality, but these will always be available.
ref($obj) to
determine the indentifier for the element class. Concrete
(non-abstract) descendents of Krang::ElementClass must define a value
for this attribute.
ucfirst()ing each word in name after
splitting on underscores. Thus, a class with the name
``horizontal_line'' has the default display_name ``Horizontal Line''.
If set to 'xinha', the textarea will be replaced with a Xinha editor. See also 'bulk_edit_tag'.
If one or more siblings of the elementclass also have this attribute set to 'xinha', the bulk edit drop down menu of these elements' parent will have an additional entry 'All WYSIWYG Elements'. This will put the data of all corresponding elements into the Xinha edit area, using the 'bulk_edit_tag' to identify the data's elementclass.
p, ul, ol, h1, h2, h3, h4, h5, h6, hr, table, address, blockquote pre
For a discussion of what is allowed see the documentation for the
class method html_scrubber in Krang::BulkEdit::Xinha::Config.
Besides of formatting the element's data when displayed in Xinha, this tag marks the data as belonging to its elementclass. Block elements that do not have their own elementclass will be put in an elementclass having the bulk_edit_tag 'p'. If no such class exists, a class having its 'name' attribute set to 'paragraph' will be used. If none is found, Krang croaks.
B<Example:>
(Prepending 'Correction: ' before to element's data when bulk editing it)
pkg('ElementClass::Textarea')->new(
name => 'correction',
cols => 30,
rows => 4,
bulk_edit => 'xinha',
bulk_edit_tag => 'pre',
before_bulk_edit => sub {
my (%arg) = @_;
my $element = $arg{element};
return "Correction: " . $element->data;
},
This kind of ``before edit modification'' may be used together with the
attribute before_bulk_save.
B<Example:>
(Stripping 'Correction: ' before saving the element's data
pkg('ElementClass::Textarea')->new(
name => 'correction',
cols => 30,
rows => 4,
bulk_edit => 'xinha',
bulk_edit_tag => 'pre',
before_bulk_save => sub {
my (%arg) = @_;
my $data = $arg{data};
$data =~ s/^Correction: //;
return $data;
},
This kind of ``before save modification'' may be used together with the
attribute before_bulk_edit.
validate() methods.
See validate() for more details. Defaults to 0.
data() is
first called on the object, not when the object is loaded. Defaults
to 0.
paragraph would cause a search through defined element sets for a
class ending in ::paragraph.
An object belonging to classes descending from Krang::ElementClass.
This allows you to instantiate element classes dynamically.
For example:
$class->children([
"paragraph",
"image",
pkg('ElementClass::Text')->new(name => "header"),
LA::image_group->new(location => "bottom"),
]);
Although both scalars and objects are valid inputs to children(), only fully constructed objects will be returned from the accessor.
The following methods are available on all Krang::ElementClass objects, and should not be overriden in sub-classes.
$child = $class->child($name)children() and looping through the results calling name() if all
you need is a particular child class.
$bool = $class->is_container
The following methods are available on all Krang::ElementClass objects. All of these methods may be overridden in child classes to specialize the behavior of an element class.
$html = $class->input_form(element => $element, query => $query)@names = $class->param_names(element => $element)$element->xpath(). If you create a sub-class with multiple form
inputs you will need to override this method.
$data = $class->bulk_edit_data(element => $element)@data = $class->bulk_edit_filter(data => \@data)$html = $class->view_data(element => $element)$element->data with all
HTML tags escaped for display.
$parent->bulk_save_change(class => $child_class, data => $data)($bool, $msg) = $class->validate(element => $element, query => $query)The default implementation respects the required attribute but
otherwise does no checking of the input data.
($bool, $msg) = $class->validate_children(element => $element, query => $query)The default implementation does nothing.
$invalid_html = $class->mark_form_invalid(html => $html)input_form()
invalid when the element fails validate(). The default implementation
wraps the form in <span class="invalid"></span>. This method
may be overridden if the class uses HTML which would be broken by
being wrapped in a span.
$class->load_query_data(element => $element, query => $query)$element->data() must return the value
specified by the user in the form fields provided by
display_form().
The default implementation loads data from the query using
$element-data()> for this element's parameter.
$class->check_data(element => $element, data => $data)$element->data() is called to set a
new value for the element. It may be used to validate the data, in
which case it should croak() if the data is invalid. Classes which
require a particular data structure in $element->data() should
override this method. The default implementation does nothing.
$text = $class->freeze_data(element => $element)The default implementation returns $element->data() as-is.
$class->thaw_data(element => $element, data => $text)The default implementation just calls $element->data($text).
$index_data = $class->index_data(element => $element)@index_data = $class->index_data(element => $element)indexed attribute is true. Elements
which are indexed may be used in calls to Krang::Story->find(). The
return value is limited to 256 characters in length. A list of
strings may be returned which will index against multiple values. The
default implementation returns $element->freeze_data().
$template_data = $class->template_data()template_data() returns is identical to $element->data(),
but some element classes may override this method to return something
different.
$class->linked_stories(element => $element, publisher => $publisher, story_link => $story_links)template_data()
method.
$filtered = $class->filter_element_data(element => $element, query => $query)$html_tmpl = $class->find_template(element => $element, publisher => $publisher)If successful, it will return an instantiated HTML::Template::Expr object with the selected template loaded.
Parameters are as follows:
publisher - The Krang::Publisher object handling the current publish run.
element - The element currently being published - a Krang::Element object.
filename - The name of the template that should be found. If this parameter is not set, find_template() will search for $element->name . '.tmpl'.
publisher is a required argument, and either element or
filename must be passed in as well.
The default process by which a template is loaded goes as follows:
name() . ``.tmpl''
Instead of element, filename arg can be passed in, which should correspond
to the template name you are looking for.
The search starts in the directory $publisher->category->url().
If the template is found, it is loaded into an HTML::Template::Expr object. NOTE - Need rules on checking for deployment/preview settings
If the template is not found, move to the parent directory and repeat the search.
If the root directory is reached, no template exists. Croak.
$class->fill_template(element => $element, tmpl => $html_template, publisher => $publisher)The default implementation walks the element tree by calling
$child->publish() on all children of the current element. If you
decide to override fill_template, but don't want to deal with the
manual work of walking the element tree, make sure to make a call to
$self->SUPER::fill_template().
The default implementation populates the template as follows:
$element->name().
For each UNIQUELY NAMED child element used in the template,
a single variable called $childname is created. For
example, if the element contains children named (paragraph,
paragraph, deck), and both <tmpl_var paragraph> and
<tmpl_var deck> are included in the template, two variables
would be created, paragraph and deck. The value of paragraph
would correspond to the first paragraph child element.
If the template has a loop named after a specific child
(e.g. page_loop) it is created as follows:
If the inside of the loop contains a direct reference to the child
- e.g. <tmpl_var page> - and the child is either a primitive element
or a container for which a separate template exists (e.g. page.tmpl),
then each row of the loop will contain $childname = HTML, where HTML
is the result of publishing $child. If not, each row will contain the
vars returned by $child->fill_template() (i.e. any of its OWN children
used in the template - <tmpl_var paragraph> etc. - will be populated).
Either way, each row will also contain the variable $childname_count
(e.g. page_count)
element_loop (i.e. <tmpl_loop element_loop>), it
is created with a row for every child element. The variables are
the same as for the child-specific loop above with the addition of a boolean
is_$childname.
(Note: If the template contains multiple instances of the same loop, each will
be populated with identical variables. This means that if ANY of them contains a
direct reference to the child, they will all have access to $childname = HTML,
and none will have access to the child's own children.)
contrib_loop that contains all contributor information. See
the section on Contributors
If the element is pageable (see Krang::Element), a series of
variables relating to Pagination. See the section on Pagination.
A variable for the total number of child elements named with the
element name and a trailing _total.
A variable called title containing $story->title().
A variable called slug containing $story->slug().
A variable called page_break containing Krang::Publisher->page_break()
NOTE: If you're developing your own elements, be aware that there exists the potential for naming collisions. For example, if you create a child element named title, you create a collsion with $story->title. Default behavior is that element children take precedence over everything else in a naming collision. Avoid this by choosing better names for your elements.
$html = $class->publish(element => $element, publisher => $publisher)find_template() and fill_template() together.
If successful, publish() will return a block of HTML.
Generally, you will not want to override publish(). Changes to template-handling behavior should be done by overriding find_template(). Changes to the parameters being passed to the template should be done by overriding fill_template(). Override publish() only in the event that neither of the previous solutions work for you.
NOTE: Some elements are simply attributes with a value, and no
formatting to be associated with them. This can be because the
developer of the element tree wants to handle formatting in the parent
element's template, or that there should be no formatting of the data
whatsoever (e.g. $element->template_data() might get embedded in an
<input> tag).
In these cases, the element will have no template associated with it -
which will cause find_template to fail. If the element has no
children, the value of $element->template_data() will be returned as
the result of the publish() call. If the element *does* have
children, publish() will propagate the error, causing fill_template()
to make the element's children available directly to its parent's template.
$class->freeze_data_xml(element => $element, writer => $writer, set => $set)freeze_data() to get a textual
representation and then produces something like this:
<data>$element->freeze_data</data>
The data element is the only valid element that may be written but it may be repeated multiple times. For example, a keywords element might serialize as:
<data>keyword1</data>
<data>keyword2</data>
<data>keyword3</data>
$class->thaw_data_xml(element => $element, data => $data, set => $set)
<data>keyword1</data>
<data>keyword2</data>
<data>keyword3</data>
Then data witll contain:
[ "keyword1", "keyword2", "keyword3" ]
The default implementation calls thaw_data() on $data[0].
$class->order_of_available_children()
{
optgroup => 'My Group',
elements => [qw(
element1
element2
element3
)]
}
$class->clone_hook(element => $element)