summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin J Doherty2009-09-09 07:06:46 +0000
committerBenjamin J Doherty2009-09-09 07:06:46 +0000
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