summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin J Doherty2009-09-09 07:06:46 (GMT)
committer Benjamin J Doherty2009-09-09 07:06:46 (GMT)
commitf5e8fd8698162f98336b3f0ee7edecff3344e15d (patch)
tree553b1e7af95280042f119e9b066c0b577e7ab511
Initial commit of Semantic Views module. This module allows site builders and themers to specify HTML elements and classes for unformatted style and field row style output.
-rw-r--r--semanticviews-view-fields.tpl.php39
-rw-r--r--semanticviews-view-unformatted.tpl.php19
-rw-r--r--semanticviews-view.tpl.php83
-rw-r--r--semanticviews.info5
-rw-r--r--semanticviews.module148
-rw-r--r--semanticviews.views.inc35
-rw-r--r--semanticviews_plugin_row_fields.inc71
-rw-r--r--semanticviews_plugin_style_default.inc115
8 files changed, 515 insertions, 0 deletions
diff --git a/semanticviews-view-fields.tpl.php b/semanticviews-view-fields.tpl.php
new file mode 100644
index 0000000..884a65d
--- /dev/null
+++ b/semanticviews-view-fields.tpl.php
@@ -0,0 +1,39 @@
+<?php
+// $Id$
+/**
+ * @file semanticviews-view-fields.tpl.php
+ * Default simple view template to all the fields as a row.
+ *
+ * - $view: The view in use.
+ * - $fields: an array of $field objects. Each one contains:
+ * - $field->content: The output of the field.
+ * - $field->raw: The raw data for the field, if it exists. This is NOT output
+ * safe.
+ * - $field->class: The safe class id to use.
+ * - $field->handler: The Views field handler object controlling this field.
+ * Do not use var_export to dump this object, as it can't handle the
+ * recursion.
+ * - $row: The raw result object from the query, with all data it fetched.
+ *
+ * @ingroup views_templates
+ */
+?>
+<?php foreach ($fields as $id => $field): ?>
+
+ <?php if ($field->element_type): ?>
+ <<?php print $field->element_type;?><?php print drupal_attributes($field->attributes); ?>>
+ <?php endif; ?>
+
+ <?php if ($field->label): ?>
+ <label<?php print drupal_attributes($field->attributes); ?>>
+ <?php print $field->label; ?>:
+ </label>
+ <?php endif; ?>
+
+ <?php print $field->content; ?>
+
+ <?php if ($field->element_type): ?>
+ </<?php print $field->element_type;?>>
+ <?php endif; ?>
+
+<?php endforeach; ?> \ No newline at end of file
diff --git a/semanticviews-view-unformatted.tpl.php b/semanticviews-view-unformatted.tpl.php
new file mode 100644
index 0000000..1e145e6
--- /dev/null
+++ b/semanticviews-view-unformatted.tpl.php
@@ -0,0 +1,19 @@
+<?php
+// $Id$
+/**
+ * @file views-view-unformatted.tpl.php
+ * Default simple view template to display a list of rows.
+ *
+ * @ingroup views_templates
+ */
+?>
+<?php if (!empty($title)): ?>
+ <<?php print $group_element; ?><?php print drupal_attributes($group_attributes); ?>>
+ <?php print $title; ?>
+ </<?php print $group_element; ?>>
+<?php endif; ?>
+<?php foreach ($rows as $id => $row): ?>
+ <<?php print $row_element; ?><?php print drupal_attributes($row_attributes[$id]); ?>>
+ <?php print $row; ?>
+ </<?php print $row_element; ?>>
+<?php endforeach; ?>
diff --git a/semanticviews-view.tpl.php b/semanticviews-view.tpl.php
new file mode 100644
index 0000000..9cc375b
--- /dev/null
+++ b/semanticviews-view.tpl.php
@@ -0,0 +1,83 @@
+<?php
+// $Id$
+/**
+ * @file semanticviews-view.tpl.php
+ * Main view template
+ *
+ * Variables available:
+ * - $css_name: A css-safe version of the view name.
+ * - $header: The view header
+ * - $footer: The view footer
+ * - $rows: The results of the view query, if any
+ * - $empty: The empty text to display if the view is empty
+ * - $pager: The pager next/prev links to display, if any
+ * - $exposed: Exposed widget form/info to display
+ * - $feed_icon: Feed icon to display, if any
+ * - $more: A link to view more, if any
+ * - $admin_links: A rendered list of administrative links
+ * - $admin_links_raw: A list of administrative links suitable for theme('links')
+ *
+ * @ingroup views_templates
+ */
+?>
+<div<?php print drupal_attributes($attributes); ?>>
+ <?php if ($admin_links): ?>
+ <div class="views-admin-links views-hide">
+ <?php print $admin_links; ?>
+ </div>
+ <?php endif; ?>
+ <?php if ($header): ?>
+ <div class="view-header">
+ <?php print $header; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($exposed): ?>
+ <div class="view-filters">
+ <?php print $exposed; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($attachment_before): ?>
+ <div class="attachment attachment-before">
+ <?php print $attachment_before; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($rows): ?>
+ <div class="view-content">
+ <?php print $rows; ?>
+ </div>
+ <?php elseif ($empty): ?>
+ <div class="view-empty">
+ <?php print $empty; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($pager): ?>
+ <?php print $pager; ?>
+ <?php endif; ?>
+
+ <?php if ($attachment_after): ?>
+ <div class="attachment attachment-after">
+ <?php print $attachment_after; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($more): ?>
+ <?php print $more; ?>
+ <?php endif; ?>
+
+ <?php if ($footer): ?>
+ <div class="view-footer">
+ <?php print $footer; ?>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($feed_icon): ?>
+ <div class="feed-icon">
+ <?php print $feed_icon; ?>
+ </div>
+ <?php endif; ?>
+
+</div> <?php /* class view */ ?>
diff --git a/semanticviews.info b/semanticviews.info
new file mode 100644
index 0000000..d86038a
--- /dev/null
+++ b/semanticviews.info
@@ -0,0 +1,5 @@
+; $Id$
+name = Semantic Views
+description = Views 2 plugins for UI management of output markup
+core = 6.x
+dependencies[] = views
diff --git a/semanticviews.module b/semanticviews.module
new file mode 100644
index 0000000..73cc5bf
--- /dev/null
+++ b/semanticviews.module
@@ -0,0 +1,148 @@
+<?php
+// $Id$
+/**
+ * @file semanticviews.module
+ * TODO: Enter file description here.
+ */
+
+/**
+ * Implementation of hook_views_api().
+ */
+function semanticviews_views_api() {
+ return array(
+ 'api' => 2.0,
+ );
+}
+
+/**
+ * Preprocess theme function to print a single record from a row, with fields
+ */
+function template_preprocess_semanticviews_view_fields(&$variables) {
+ $view = $variables['view'];
+ // Loop through the fields for this view.
+ $variables['fields'] = array(); // ensure it's at least an empty array.
+ foreach ($view->field as $id => $field) {
+ // render this even if set to exclude so it can be used elsewhere.
+ $field_output = $view->field[$id]->theme($variables['row']);
+ if (empty($field->options['exclude'])) {
+ $object = new stdClass();
+
+ $object->content = $field_output;
+ if (isset($view->field[$id]->field_alias) && isset($variables['row']->{$view->field[$id]->field_alias})) {
+ $object->raw = $variables['row']->{$view->field[$id]->field_alias};
+ }
+ else {
+ $object->raw = NULL; // make sure it exists to reduce NOTICE
+ }
+
+ $object->handler = &$view->field[$id];
+
+ $semantic_html = $variables['options']['semantic_html'][$id];
+ $object->element_type = check_plain($semantic_html['element_type']);
+ $object->attributes = array();
+ if ($semantic_html['class']) {
+ $object->attributes['class'] = $semantic_html['class'];
+ }
+
+ $object->label = check_plain($view->field[$id]->label());
+ $variables['fields'][$id] = $object;
+ }
+ }
+}
+
+/**
+ * Display the simple view of rows one after another
+ */
+function template_preprocess_semanticviews_view_unformatted(&$variables) {
+ $variables['group_element'] = check_plain($variables['options']['group']['element_type']);
+ $variables['group_attributes'] = array();
+ if ($variables['options']['group']['class']) {
+ $variables['group_attributes']['class'] = $variables['options']['group']['class'];
+ }
+
+ // TODO: set a default or handle empty value.
+ $variables['row_element'] = check_plain($variables['options']['row']['element_type']);
+ $last_every_nth = $variables['options']['last_every_nth'];
+
+ $variables['row_attributes'] = array();
+ foreach ($variables['rows'] as $id => $row) {
+ $variables['row_attributes'][$id] = array();
+ $classes = array();
+ if ($variables['options']['row']['class']) {
+ $classes[] = str_replace('#', $id, $variables['options']['row']['class']);
+ }
+ if ($id == 0 && $variables['options']['row']['first_class']) {
+ $classes[] = $variables['options']['row']['first_class'];
+ }
+ if (($last_every_nth && ($id + 1) % $last_every_nth == 0) ||
+ (!$last_every_nth && $id == count($variables['rows']))) {
+ $classes[] = $variables['options']['row']['last_class'];
+ }
+ // TODO: implement configurable row striping
+ //$classes[] = $id % 2 ? 'even' : 'odd';
+
+ if (!empty($classes)) {
+ $variables['row_attributes'][$id]['class'] = implode(' ', $classes);
+ }
+ }
+}
+
+function semanticviews_theme_registry_alter(&$theme_registry) {
+ if (isset($theme_registry['views_view'])) {
+
+ // Add the module's path to the theme paths.
+ if (isset($theme_registry['views_view']['theme paths'])) {
+ $module_path = drupal_get_path('module', 'semanticviews');
+ array_push($theme_registry['views_view']['theme paths'], $module_path);
+ }
+
+ // Add an additional preprocess function to the theme info.
+ if (isset($theme_registry['views_view']['preprocess functions'])) {
+ $module_path = drupal_get_path('module', 'semanticviews');
+ array_push($theme_registry['views_view']['preprocess functions'], 'template_preprocess_semanticviews_view');
+ }
+ }
+}
+
+/**
+ * The class attributes of the outer div of a View cannot be changed when the
+ * view uses AJAX. The Views ajax scripts need these classes to attach
+ * behaviors.
+ * - view-dom-id-%
+ * OR
+ * - view-id-% and view-display-id-%
+ *
+ * @see template_preprocess_views_view
+ * @see ajax_view.js
+ *
+ * @param <type> $variables
+ */
+function template_preprocess_semanticviews_view(&$variables) {
+ if ($variables['view']->plugin_name == 'semanticviews_default') {
+ $variables['template_file'] = 'semanticviews-view';
+ $variables['attributes'] = array();
+
+ // Container class attributes are stacked in an array.
+ $classes = array();
+
+ // TODO: Bring class attribute into UI for configuration.
+ //$classes[] = 'view';
+ if ($variables['view']->use_ajax) {
+
+ // The old way Ajax Views were selected for behaviors.
+ //$classes[] = 'view-'. $variables['css_name'];
+ //$classes[] = 'view-id-'. $variables['name'];
+ //$classes[] = 'view-display-id-'. $variables['display_id'];
+
+ // The new way.
+ $classes[] = 'view-dom-id-'. $variables['dom_id'];
+ }
+ if (!empty($classes)) {
+ $variables['attributes']['class'] = implode(' ', $classes);
+ }
+ if ($variables['view']->style_options['id']) {
+ // TODO: Prevent ID collision. Or not?
+ $variables['attributes']['id'] = $variables['view']->style_options['id'];
+ }
+ }
+} \ No newline at end of file
diff --git a/semanticviews.views.inc b/semanticviews.views.inc
new file mode 100644
index 0000000..a969d5d
--- /dev/null
+++ b/semanticviews.views.inc
@@ -0,0 +1,35 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_views_plugins().
+ */
+function semanticviews_views_plugins() {
+ return array(
+ 'style' => array(
+ 'semanticviews_default' => array(
+ 'title' => t('Semantic Views : Unformatted'),
+ 'help' => t('Displays rows one after another.'),
+ 'handler' => 'semanticviews_plugin_style_default',
+ 'theme' => 'semanticviews_view_unformatted',
+ 'uses row plugin' => TRUE,
+ 'uses options' => TRUE,
+ 'uses grouping' => TRUE,
+ 'type' => 'normal',
+ //'help topic' => 'style-unformatted',
+ ),
+ ),
+ 'row' => array(
+ 'semanticviews_fields' => array(
+ 'title' => t('Semantic Views : Fields'),
+ 'help' => t('Displays the fields with an optional template.'),
+ 'handler' => 'semanticviews_plugin_row_fields',
+ 'theme' => 'semanticviews_view_fields',
+ 'uses fields' => TRUE,
+ 'uses options' => TRUE,
+ 'type' => 'normal',
+ //'help topic' => 'style-row-semanticfields',
+ ),
+ ),
+ );
+} \ No newline at end of file
diff --git a/semanticviews_plugin_row_fields.inc b/semanticviews_plugin_row_fields.inc
new file mode 100644
index 0000000..bf716fe
--- /dev/null
+++ b/semanticviews_plugin_row_fields.inc
@@ -0,0 +1,71 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Contains the semantic row style plugin.
+ */
+
+/**
+ * The semantic 'fields' row plugin
+ *
+ * This displays fields one after another, giving options for HTML element and
+ * class.
+ *
+ * @ingroup views_row_plugins
+ */
+class semanticviews_plugin_row_fields extends views_plugin_row {
+ function option_definition() {
+ $options = parent::option_definition();
+ $options['semantic_html'] = array();
+
+ // Until the view's row settings are actually being edited, $this is only
+ // the plugin. Probably then this has no meaningful effect?
+ if ($this->display) {
+ foreach ($this->display->handler->get_handlers('field') as $field => $handler) {
+ $options['semantic_html'][$field]['element_type'] = array('default' => 'div');
+ $options['semantic_html'][$field]['class'] = array('default' => 'views-field-'. views_css_safe($field));
+ }
+ }
+ return $options;
+ }
+
+ /**
+ * Provide a form for setting options.
+ */
+ function options_form(&$form, &$form_state) {
+ $form['semantic_html'] = array(
+ '#tree' => TRUE,
+ );
+ foreach ($this->display->handler->get_handlers('field') as $field => $handler) {
+ $default_value = $this->options['semantic_html'][$field];
+ $form['semantic_html'][$field] = array(
+ '#title' => $handler->ui_name(),
+ '#type' => 'fieldset',
+ '#attributes' => array(
+ 'class' => 'container-inline',
+ ),
+ );
+ $form['semantic_html'][$field]['element_type'] = array(
+ '#title' => 'Element',
+ '#type' => 'textfield',
+ '#size' => '10',
+ '#default_value' => $default_value['element_type'],
+ );
+ $form['semantic_html'][$field]['class'] = array(
+ '#title' => 'Class attribute',
+ '#type' => 'textfield',
+ '#size' => '30',
+ '#default_value' => $default_value['class'],
+ );
+ }
+ }
+
+ /**
+ * Validate the options form.
+ */
+ function options_validate(&$form, &$form_state) {
+ parent::options_validate($form, $form_state);
+ // TODO: validate that the elements and classes are valid HTML. This is not
+ // a substitute for output filtering.
+ }
+} \ No newline at end of file
diff --git a/semanticviews_plugin_style_default.inc b/semanticviews_plugin_style_default.inc
new file mode 100644
index 0000000..0d8c49c
--- /dev/null
+++ b/semanticviews_plugin_style_default.inc
@@ -0,0 +1,115 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Contains the default style plugin.
+ */
+
+/**
+ * Default style plugin to render rows one after another with no decorations.
+ *
+ * @ingroup views_style_plugins
+ */
+class semanticviews_plugin_style_default extends views_plugin_style {
+ /**
+ * Set default options
+ */
+ function options(&$options) {
+ parent::options($options);
+ }
+
+ /**
+ * Set default options
+ */
+ function option_definition() {
+ $options = parent::option_definition();
+
+ $options['last_every_nth'] = array('default' => '0');
+
+ return $options;
+ }
+
+ /**
+ * Render the given style.
+ */
+ function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $form['id'] = array(
+ '#type' => 'textfield',
+ '#title' => t('View ID attribute'),
+ '#default_value' => $this->options['id'],
+ );
+ //$pager = $this->view->pager['items_per_page'];
+ $form['last_every_nth'] = array(
+ '#type' => 'textfield',
+ '#title' => t('[last] every N-th'),
+ '#default_value' => $this->options['last_every_nth'],
+ '#description' => 'This could be used to make regular insertions of a "last" class in every nth element. Using 0 or leaving this empty means only the last item on the page gets the "last" class.',
+ );
+ $form['group'] = array(
+ '#type' => 'fieldset',
+ '#title' => 'Grouping title',
+ '#description' => 'If using groups, the view will insert the grouping\'s title field.',
+ /*
+ '#attributes' => array(
+ 'class' => 'container-inline',
+ ),
+ */
+ );
+ $form['group']['element_type'] = array(
+ '#title' => 'Element',
+ '#type' => 'textfield',
+ '#size' => '10',
+ '#default_value' => $this->options['group']['element_type'],
+ );
+ $form['group']['class'] = array(
+ '#title' => 'Class attribute',
+ '#type' => 'textfield',
+ '#size' => '30',
+ '#default_value' => $this->options['group']['class'],
+ );
+ $form['row'] = array(
+ '#type' => 'fieldset',
+ '#title' => 'Row',
+ /*
+ '#attributes' => array(
+ 'class' => 'container-inline',
+ ),
+ */
+ );
+ $form['row']['element_type'] = array(
+ '#title' => 'Element',
+ '#type' => 'textfield',
+ '#size' => '10',
+ '#default_value' => $this->options['row']['element_type'],
+ );
+ $form['row']['class'] = array(
+ '#title' => 'Class attribute',
+ '#type' => 'textfield',
+ '#size' => '30',
+ '#default_value' => $this->options['row']['class'],
+ '#description' => 'Insert a # where you want row numbers to be inserted.',
+ );
+ $form['row']['first_class'] = array(
+ '#title' => 'FIRST class attribute',
+ '#type' => 'textfield',
+ '#size' => '30',
+ '#default_value' => $this->options['row']['first_class'],
+ );
+ $form['row']['last_class'] = array(
+ '#title' => 'LAST class attribute',
+ '#type' => 'textfield',
+ '#size' => '30',
+ '#default_value' => $this->options['row']['last_class'],
+ );
+ }
+
+ /**
+ * Validate the options form.
+ */
+ function options_validate(&$form, &$form_state) {
+ parent::options_validate($form, $form_state);
+ // TODO: validate that the elements and classes are valid HTML. This is not
+ // a substitute for output filtering.
+ }
+} \ No newline at end of file