https://www.mediawiki.org/wiki/Special:Code/MediaWiki/112972
Revision: 112972 Author: foxtrott Date: 2012-03-04 10:38:06 +0000 (Sun, 04 Mar 2012) Log Message: ----------- very first version of new 'filtered' format Modified Paths: -------------- trunk/extensions/SemanticResultFormats/SRF_Resources.php trunk/extensions/SemanticResultFormats/SRF_Settings.php trunk/extensions/SemanticResultFormats/SemanticResultFormats.php Added Paths: ----------- trunk/extensions/SemanticResultFormats/Filtered/ trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php trunk/extensions/SemanticResultFormats/Filtered/filters/ trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_Filtered_Filter.php trunk/extensions/SemanticResultFormats/Filtered/libs/ trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.list-view.js trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js trunk/extensions/SemanticResultFormats/Filtered/skins/ trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.css trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.value-filter.css trunk/extensions/SemanticResultFormats/Filtered/views/ trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php trunk/extensions/SemanticResultFormats/Filtered/views/SRF_Filtered_View.php Copied: trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php (from rev 112143, trunk/extensions/SemanticResultFormats/Tree/SRF_Tree.php) =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,238 @@ +<?php + +/** + * File holding the SRFFiltered class. + * + * @file + * @ingroup SemanticResultFormats + * @author Stephan Gambke + * + */ + +$formatDir = dirname( __FILE__ ) . '/'; + +$wgAutoloadClasses['SRF_Filtered_Item'] = $formatDir . 'SRF_Filtered_Item.php'; + +$wgAutoloadClasses['SRF_Filtered_View'] = $formatDir . 'views/SRF_Filtered_View.php'; +$wgAutoloadClasses['SRF_FV_List'] = $formatDir . 'views/SRF_FV_List.php'; + +$wgAutoloadClasses['SRF_Filtered_Filter'] = $formatDir . 'filters/SRF_Filtered_Filter.php'; +$wgAutoloadClasses['SRF_FF_Value'] = $formatDir . 'filters/SRF_FF_Value.php'; + + +/** + * Result printer that displays results in switchable views and offers + * client-side (JavaScript based) filtering. + * + * This result printer is ultimately planned to replace exhibit. Currently only + * a list view is available. It is not yet possible to switch between views. + * There is also only the 'value' filter available yet. + * + * Syntax of the #ask call: + * (This is only a syntax example. For currently available features see the + * documentation of the various classes.) + * + * {{#ask:[[SomeCondition]] + * |? SomePrintout |+filter=value, someFutureFilter |+value filter switches=and or, disable, all, none |+someFutureFilter filter option=someOptionValue + * |? SomeOtherPrintout |+filter=value, someOtherFutureFilter |+someOtherFutureFilter filter option=someOptionValue + * + * |format=filtered + * |views=list, someFutureView, someOtherFutureView + * + * |list view type=list + * |list view template=ListItem + * + * |someFutureView view option=someOptionValue + * + * |someOtherFutureView view option=someOptionValue + * + * }} + * + * All format specific parameters are optional, although leaving the 'views' + * parameter empty probably does not make much sense. + * + */ +class SRFFiltered extends SMWResultPrinter { + + /** + * The available view types + * @var array of Strings + */ + private $mViewTypes = array( + 'list' => 'SRF_FV_List', + ); + + /** + * The available filter types + * @var array of Strings + */ + private $mFilterTypes = array( + 'value' => 'SRF_FF_Value', + ); + + private $mViews; + private $mParams; + + public function hasTemplates ( $hasTemplates = null ) { + $ret = $this->hasTemplates; + if ( is_bool( $hasTemplates ) ) { + $this->hasTemplates = $hasTemplates; + } + return $ret; + } + + protected function handleParameters( array $params, $outputmode ) { + parent::handleParameters( $params, $outputmode ); + + //// Set in SMWResultPrinter: + // $this->mIntro = $params['intro']; + // $this->mOutro = $params['outro']; + // $this->mSearchlabel = $params['searchlabel'] === false ? null : $params['searchlabel']; + // $this->mLinkFirst = true | false; + // $this->mLinkOthers = true | false; + // $this->mDefault = str_replace( '_', ' ', $params['default'] ); + // $this->mShowHeaders = SMW_HEADERS_HIDE | SMW_HEADERS_PLAIN | SMW_HEADERS_SHOW; + + $this->mSearchlabel = null; + + $this->mParams = $params; + $this->mViews = array_map( 'trim', explode( ',', $params['views'] ) ); + + } + + /** + * Return serialised results in specified format. + */ + protected function getResultText( SMWQueryResult $res, $outputmode ) { + + // collect the query results in an array + $result = array(); + while ( $row = $res->getNext() ) { + $result[uniqid()] = new SRF_Filtered_Item( $row, $this ); + } + + $resourceModules = array(); + + // prepare filter data for inclusion in HTML and JS + $filterHtml = ''; + $filterHandlers = array(); + $filterData = array(); + + foreach ( $res->getPrintRequests() as $printRequest ) { + $filter = $printRequest->getParameter( 'filter' ); + if ( $filter ) { + + $filtersForPrintout = explode( ',', $filter ); + $filtersForPrintout = array_map('trim', $filtersForPrintout); + + foreach ( $filtersForPrintout as $filterName ) { + if ( array_key_exists( $filterName, $this->mFilterTypes ) ) { + + $filter = new $this->mFilterTypes[$filterName]( $result, $printRequest, $this); + + $resourceModules = $filter->getResourceModules(); + + if ( is_array( $resourceModules ) ) { + array_walk( $resourceModules, 'SMWOutputs::requireResource' ); + } elseif ( is_string( $resourceModules ) ) { + SMWOutputs::requireResource( $resourceModules ); + } + + $printRequestHash = md5( $printRequest->getHash() ); + $filterHtml .= Html::rawElement( 'div', array('class' => "filtered-$filterName $printRequestHash"), $filter->getResultText() ); + + $filterHandlers[$filterName] = null; + $filterData[$filterName][$printRequestHash] = $filter->getJsData(); + + } + } + } + } + + // wrap filters in a div + $filterHtml = Html::rawElement( 'div', array( 'class' => 'filtered-filters' ), $filterHtml ); + + // prepare view data for inclusion in HTML and JS + $viewHtml = ''; + $viewHandlers = array(); + $viewElements = array(); + + foreach ( $this->mViews as $viewName ) { + if ( array_key_exists( $viewName, $this->mViewTypes ) ) { + + // generate unique id + $viewid = uniqid(); + + $view = new $this->mViewTypes[$viewName]( $viewid, $result, $this->mParams, $this ); + + $resourceModules = $view->getResourceModules(); + + if ( is_array( $resourceModules ) ) { + array_walk( $resourceModules, 'SMWOutputs::requireResource' ); + } elseif ( is_string( $resourceModules ) ) { + SMWOutputs::requireResource( $resourceModules ); + } + + $viewHtml .= Html::rawElement( 'div', array('class' => "filtered-$viewName $viewid"), $view->getResultText() ); + + $viewHandlers[$viewName] = null; + $viewElements[$viewName][] = $viewid; + } + } + + // wrap views in a div + $viewHtml = Html::rawElement( 'div', array( 'class' => 'filtered-views' ), $viewHtml ); + + // Define the srf_filtered_values array + SMWOutputs::requireScript( 'srf_filtered_values', Html::inlineScript( + 'srf_filtered_values = {};' + ) + ); + + $resultAsArray = array(); + foreach ( $result as $id => $value ) { + $resultAsArray[$id] = $value->getArrayRepresentation(); + } + + $id = uniqid(); + SMWOutputs::requireScript( 'srf_filtered_values' . $id, + Html::inlineScript( + 'srf_filtered_values["' . $id . '"] = { "values":' . json_encode( $resultAsArray ) . + ', "data": {' . + ' "viewhandlers" : ' . json_encode( $viewHandlers ) . + ', "viewelements" : ' . json_encode( $viewElements ) . + ', "filterhandlers" : ' . json_encode( $filterHandlers ) . + ', "filterdata" : ' . json_encode( $filterData ) . + '}};' + ) + ); + + SMWOutputs::requireResource('ext.srf.filtered'); + + // wrap all in a div + $html = Html::rawElement( 'div', array( 'class' => 'filtered ' . $id ), $filterHtml . $viewHtml ); + + return $html; + } + + + public function getParameters() { + $params = array_merge( parent::getParameters(), + parent::textDisplayParameters() ); + + $params['views'] = new Parameter( 'views' ); + $params['views']->setMessage( 'srf-paramdesc-views' ); + $params['views']->setDefault( '' ); + + foreach ( $this->mViewTypes as $viewType ) { + $params = array_merge($params, call_user_func( array( $viewType, 'getParameters') ) ); + } + + return $params; + } + + public function getLinker( $firstcol = false, $force = false ) { + return ( $force ) ? $this->mLinker : parent::getLinker( $firstcol ); + } + +} Added: trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,76 @@ +<?php + +/** + * File holding the SRF_Filtered_Item class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +/** + * The SRF_Filtered_Item class. + * + * @ingroup SemanticResultFormats + */ +class SRF_Filtered_Item { + + private $mResultArray; + private $mItemData = array(); + private $mQueryPrinter; + + public function __construct($resultArray, SRFFiltered &$queryPrinter) { + $this->mResultArray = $resultArray; + $this->mQueryPrinter = $queryPrinter; + } + + public function setDataForView ( $viewId, &$data ){ + $this->mItemData[$viewId] = $data; + } + + public function unsetDataForView ( $viewId ){ + unset($this->mItemData[$viewId]); + } + + public function getDataForView ( $viewId ){ + return $this->mItemData[$viewId]; + } + + public function getValue() { + return $this->mResultArray; + } + + public function getArrayRepresentation() { + + $printouts = array(); + + foreach ( $this->mResultArray as $i => $field ) { + + $printRequest = $field->getPrintRequest(); + + $label = $printRequest->getLabel(); + $type = $printRequest->getTypeID(); + $params = $printRequest->getParameters(); + + $values = array(); + + $field->reset(); + while ( ( $value = $field->getNextText( SMW_OUTPUT_WIKI, null ) ) !== false ) { + $values[] = $value; + } + + $printouts[ md5($printRequest->getHash()) ] = array( + 'label' => $label, + 'type' => $type, + 'params' => $params, + 'values' => $values, + ); + } + + + return array( + 'printouts' => $printouts, + 'data' => $this->mItemData, + ); + } +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,60 @@ +<?php + +/** + * File holding the SRF_FF_Value class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +/** + * The SRF_FF_Value class. + * + * Available parameters for this filter: + * value filter switches: switches to be shown for this filter; currently only 'and or' supported + * + * @ingroup SemanticResultFormats + */ +class SRF_FF_Value extends SRF_Filtered_Filter { + + /** + * Returns the HTML text that is to be included for this view. + * + * This text will appear on the page in a div that has the view's id set as + * class. + * + * @return string + */ + public function getResultText() { + return ''; + } + + /** + * Returns the name (string) or names (array of strings) of the resource + * modules to load. + * + * @return string|array + */ + public function getResourceModules() { + return 'ext.srf.filtered.value-filter'; + } + + /** + * Returns an array of config data for this filter to be stored in the JS + * @return null + */ + public function getJsData() { + $params = $this->getActualParameters(); + + if ( array_key_exists( 'value filter switches', $params ) ) { + $switches = explode(',', $params['value filter switches'] ); + $switches = array_map('trim', $switches ); + + return array( 'switches' => $switches ); + } + + return null; + } + +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_Filtered_Filter.php =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_Filtered_Filter.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_Filtered_Filter.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,69 @@ +<?php + +/** + * File holding the SRF_Filtered_Filter class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +/** + * The SRF_Filtered_Filter class. + * + * @ingroup SemanticResultFormats + */ +abstract class SRF_Filtered_Filter { + + private $mResults = null; + private $mPrintRequest = null; + private $mQueryPrinter = null; + + public function __construct( &$results, SMWPrintRequest $printRequest, SRFFiltered &$queryPrinter ) { + $this->mResults = $results; + $this->mPrintRequest = $printRequest; + $this->mQueryPrinter = $queryPrinter; + } + + public function &getQueryResults() {return $this->mResults;} + public function &getPrintRequest() {return $this->mPrintRequest;} + public function &getQueryPrinter() {return $this->mQueryPrinter;} + + + public function getActualParameters() { + + return $this->mPrintRequest->getParameters(); + + } + + /** + * Returns the name (string) or names (array of strings) of the resource + * modules to load. + * + * @return string|array + */ + public function getResourceModules() { + return null; + } + + /** + * Returns the HTML text that is to be included for this filter. + * + * This text will appear on the page in a div that has the filter's id set + * as class. + * + * @return string + */ + public function getResultText() { + return ''; + } + + /** + * Returns an array of config data for this filter to be stored in the JS + * @return null + */ + public function getJsData() { + return null; + } + +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_Filtered_Filter.php ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,213 @@ +/** + * File holding the filtered plugin + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +(function ($) { + + var methods = { + + init: function( args ){ + + return this.each( function() { + var data = args['data']; + $(this).data( 'ext.srf.filtered', data ); + + data['data']['pending-filters'] = []; + data['data']['pending-views'] = []; + + for (var i in data['data']['filterhandlers']) { + data['data']['pending-filters'].push(i); + } + + for (var i in data['data']['viewhandlers']) { + data['data']['pending-views'].push(i); + } + + // init housekeeping on values + for (i in data['values']) { + + data['values'][i]['data'] = { + + 'visibility': { + 'overall' : true, + 'votes' : {} + } + } + } + + return this; + }); + }, + + attachView : function( viewName, view ) { + return this.each( function() { + + var $this = $(this); + + var viewhandlers = $this.data('ext.srf.filtered')['data']['viewhandlers']; + + if ( viewName in viewhandlers ) { + viewhandlers[viewName] = view; + } + + var pendingViews = $this.data('ext.srf.filtered')['data']['pending-views']; + + var i = $.inArray(viewName, pendingViews); + pendingViews.splice(i, 1); + + if ( pendingViews.length == 0 && $this.data('ext.srf.filtered')['data']['pending-filters'].length == 0) { + + for (var i in viewhandlers){ + viewhandlers[i].apply( $this, ['updateAllItems'] ); + } + } + + return this; + }); + }, + + attachFilter : function( filterName, filter ) { + return this.each( function() { + + var $this = $(this); + + var handlers = $this.data('ext.srf.filtered')['data']['filterhandlers']; + + if ( filterName in handlers ) { + handlers[filterName] = filter; + var printouts = $this.data('ext.srf.filtered')['data']['filterdata'][filterName]; + + for ( var i in printouts ) { + (handlers[filterName]).apply($this, [ 'init', { + printout: i + } ] ); + } + + } + + var pendingFilters = $this.data('ext.srf.filtered')['data']['pending-filters']; + + // take attached filter from list of pending filters + var i = $.inArray(filterName, pendingFilters); + pendingFilters.splice(i, 1); + + if ( pendingFilters.length == 0 && $this.data('ext.srf.filtered')['data']['pending-views'].length == 0) { + var viewhandlers = $this.data('ext.srf.filtered')['data']['viewhandlers']; + + for (var i in viewhandlers){ + viewhandlers[i].apply( $this, ['updateAllItems'] ); + } + } + return this; + }); + }, + + voteItemVisibility : function( params ) { + var item = this.data('ext.srf.filtered')['values'][params['item']]; + var votes = item.data['visibility']['votes']; + + // Figure out if the vote changed from the filter in the params + var voteChanged = + votes[params['filter'] + ' ' + params['printout']] == undefined || + votes[params['filter'] + ' ' + params['printout']] != params['visible']; + + // Store the new vote + votes[params['filter'] + ' ' + params['printout']] = params['visible']; + + // If vote from filter changed, figure out if it has an impact on the end result + if ( voteChanged ) { + + var visible=true; + for ( var i in votes ) { + visible = visible && votes[i]; + } + + voteChanged = item.data['visibility']['overall'] != visible; + + // Store new end result + item.data['visibility']['overall'] = visible; + } + + + return voteChanged; + }, + + voteItemVisibilityAndUpdate : function( params ) { + + + if ( methods.voteItemVisibility.apply(this, [params]) ) { + + var handlers = this.data('ext.srf.filtered')['data']['viewhandlers']; + + for (var i in handlers){ + handlers[i].apply( this, ['updateItem', params] ); + } + } + return this; + }, + + getFilterData : function ( params ) { + if ( params['filter'] == undefined ) { + return this.data('ext.srf.filtered')['data']['filterdata'] + } else if ( params['printout'] == undefined ) { + return this.data('ext.srf.filtered')['data']['filterdata'][params['filter']]; + } else if ( params['configvar'] == undefined ) { + return this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']]; + } else { + if (this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']] != null) { + return this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']][params['configvar']]; + } else { + return null; + } + } + }, + + setFilterData : function ( params ) { + if ( params['filter'] == undefined || + params['printout'] == undefined || + params['configvar'] == undefined || + params['configvalue'] == undefined ) { + return null; + } else { + if (this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']] == null) { + this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']] = {} + } + this.data('ext.srf.filtered')['data']['filterdata'][params['filter']][params['printout']][params['configvar']] = params['configvalue']; + } + }, + + getValues : function ( params ) { + return this.data('ext.srf.filtered')['data']; + }, + + isVisible : function ( item ) { + return this.data('ext.srf.filtered')['values'][item]['data']['visibility']['overall']; + } + }; + + $.fn.filtered = function( method ) { + + // Method calling logic + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' ); + } + + + }; + +})(jQuery); + +// initialize all Filtered +for ( id in srf_filtered_values ) { + jQuery('.' + id).filtered( { + 'data' : srf_filtered_values[ id ] + }); +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.list-view.js =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.list-view.js (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.list-view.js 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,77 @@ +/** + * File holding the list-view plugin + * + * For this plugin to work, the filtered plugin needs to be available first. + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +(function ($) { + + var methods = { + + init: function( args ){ + return this; + }, + + alert: function(){ + alert('List View!'); + return this; + }, + + updateItem: function(params){ + + var view = this.children('.filtered-views').children('.filtered-list'); + + if ( params.visible ) { + view.children('.' + params.item ).slideDown( 200 ); + } else { + view.children('.' + params.item ).slideUp( 200 ); + } + return this; + }, + + updateAllItems: function(){ + + var filtered = this; + var items = this.children('.filtered-views').children('.filtered-list').children(); + + items.each(function(){ + + var $this = $(this) + var id = $this.attr('id'); + + if (filtered.filtered('isVisible', id)) { + $this.slideDown(0); + } else { + $this.slideUp(0); + } + + }); + + } + + }; + + listView = function( method ) { + + // Method calling logic + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.filtered.listView' ); + } + + + }; + + // attach ListView to all Filtered query printers + // let them sort out, if ListView is actually applicable to them + jQuery('.filtered').filtered('attachView', 'list', listView ); + +})(jQuery); + Property changes on: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.list-view.js ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,182 @@ +/** + * File holding the value-filter plugin + * + * For this plugin to work, the filtered plugin needs to be available first. + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +(function ($) { + + var methods = { + + init: function( args ){ + + function update( filtered, filtercontrols, target ) { + + var values = filtered.data('ext.srf.filtered')['values']; + var selectedInputs = filtercontrols.children('div.filtered-value-option').children('input:checked'); + + for ( i in values ) { + + var printoutValues = values[i]['printouts'][target]['values']; + var useOr = filtered.filtered( 'getFilterData', {filter: 'value', printout: target, configvar: 'use or'} ); + + if ( useOr ) { + var selected = false; + + for ( var j in printoutValues ) { + + selectedInputs.each(function(){ + selected = selected || ( printoutValues[j] == $(this).attr('value') ); + }); + } + } else { + var selected = true; + + for ( var j in printoutValues ) { + + selectedInputs.each(function(){ + selected = selected && ( printoutValues[j] == $(this).attr('value') ); + }); + } + } + + filtered.filtered( 'voteItemVisibilityAndUpdate', { + 'filter': 'value', + 'printout' : target, + 'visible': selected, + 'item': i + }); + + } + } + + var filtered = this; + + var values = this.data('ext.srf.filtered')['values']; + var target = args.printout; + var switches = filtered.filtered( 'getFilterData', {filter: 'value', printout: target, configvar: 'switches'} ); + + // find distinct values and set visibility for all items that have + // some value for this printout + var distinctValues = []; + + var i; + for ( i in values ) { + var printoutValues = values[i]['printouts'][target]['values']; + + for (var j in printoutValues) { + distinctValues[ printoutValues[j] ] = true; + } + + filtered.filtered( 'voteItemVisibility', { + 'filter': 'value', + 'printout' : target, + 'visible': printoutValues.length > 0, + 'item': i + }); + } + + // build filter controls + var filtercontrols = this.children('.filtered-filters').children('.' + target).filter('.filtered-value'); + + // insert the label of the printout this filter filters on + filtercontrols.append('<div class="filtered-value-label"><span>' + values[i]['printouts'][target]['label'] + '</span></div>'); + + // set default config values + filtered.filtered( 'setFilterData', {filter: 'value', printout: target, configvar: 'use or', configvalue: true } ); + + + // insert switches + if ( switches != null && switches.length > 0 ) { + + var switchControls = $('<div class="filtered-value-switches">'); + + if ( $.inArray('and or', switches) ) { + + var andorControl = $('<div class="filtered-value-andor">'); + var andControl = $('<input type="radio" name="filtered-value-andor ' + + target + '" class="filtered-value-andor ' + target + '" value="and">'); + + var orControl = $('<input type="radio" name="filtered-value-andor ' + + target + '" class="filtered-value-andor ' + target + '" value="or" checked>'); + + andControl + .add( orControl ) + .change(function() { + filtered.filtered( 'setFilterData', {filter: 'value', printout: target, configvar: 'use or', configvalue: orControl.is(':checked') } ); + update( filtered, filtercontrols, target ); + }); + + andorControl + .append( orControl ) + .append(' OR ') + .append( andControl ) + .append(' AND ') + .appendTo( switchControls ); + + } + + filtercontrols.append( switchControls ); + } + var sortedDistinctValues = []; + + for ( var i in distinctValues ) { + sortedDistinctValues.push(i); + } + + sortedDistinctValues.sort(); + + // insert options (checkboxes and labels) and attach event handlers + // TODO: Do we need to wrap these in a form? + for ( var j in sortedDistinctValues ) { + var option = $('<div class="filtered-value-option">'); + var checkbox = $('<input type="checkbox" class="filtered-value-value" value="' + sortedDistinctValues[j] + '" checked >'); + + // attach event handler + checkbox.change(function( evt ){ + update(filtered, filtercontrols, target); + }); + + option + .append(checkbox) + .append(sortedDistinctValues[j]); + + filtercontrols + .append(option); + + } + + return this; + }, + + alert: function(){ + alert('ValueFilter!'); + return this; + } + + }; + + valueFilter = function( method ) { + + // Method calling logic + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.filtered.listView' ); + } + + + }; + + // attach ListView to all Filtered query printers + // let them sort out, if ListView is actually applicable to them + jQuery('.filtered').filtered('attachFilter', 'value', valueFilter ); + +})(jQuery); + Property changes on: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.css =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.css (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.css 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,27 @@ +/* + Main stylesheet for the filtered query printer +*/ + + +.filtered { + height: 100%; +} + +.filtered-filters { + height: 40%; + overflow: auto; + border: 1px solid #aaa; + margin: 1em; + position: relative; + top: 0; + left: 0; +} + +.filtered-views { + height: 60%; + overflow: auto; + border: 1px solid #aaa; + padding: 1em; + margin: 1em; +} + Property changes on: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.css ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.value-filter.css =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.value-filter.css (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.value-filter.css 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,40 @@ +/* + Stylesheet for the value filter +*/ + +.filtered-filters .filtered-value { + overflow: visible; + border: 1px solid #aaa; + padding: 1em; + margin: 1em; +} + +.filtered-filters .filtered-value .filtered-value-label { + height: 0; +} + +.filtered-filters .filtered-value .filtered-value-label span { + background-color: white; + font-weight: bold; + + position: relative; + top: -1.8em; + left: 0; + + padding: 0 1em; +} + +.filtered-filters .filtered-value .filtered-value-switches { + border-bottom: 1px solid #aaa; + font-weight: bold; + padding: 0.5em 1em; + + margin-bottom: 1em; +} + +.filtered-filters .filtered-value .filtered-value-option { + display: inline-block; + padding: 0 1em; + width: 20%; +} + Property changes on: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.value-filter.css ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,209 @@ +<?php + +/** + * File holding the SRF_FV_List class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +/** + * The SRF_FV_List class defines the List view. + * + * Available parameters for this view: + * list view type: list|ul|ol; default: list + * list view template: a template rendering a list item + * list view introtemplate: a template prepended to the list + * list view outrotemplate: a template appended to the list + * list view named args: use named args for templates + * + * @ingroup SemanticResultFormats + */ +class SRF_FV_List extends SRF_Filtered_View { + + private $mFormat, $mTemplate, $mIntroTemplate, $mOutroTemplate, $mNamedArgs, $mShowHeaders; + + /** + * Transfers the parameters applicable to this view into internal variables. + */ + protected function handleParameters() { + + $params = $this->getActualParameters(); + + $this->mFormat = $params['list view type']; + $this->mTemplate = $params['list view template']; + $this->mIntroTemplate = $params['list view introtemplate']; + $this->mOutroTemplate = $params['list view outrotemplate']; + $this->mNamedArgs = $params['list view named args']; + + if ( $params['headers'] == 'hide' ) { + $this->mShowHeaders = SMW_HEADERS_HIDE; + } elseif ( $params['headers'] == 'plain' ) { + $this->mShowHeaders = SMW_HEADERS_PLAIN; + } else { + $this->mShowHeaders = SMW_HEADERS_SHOW; + } + } + + /** + * Returns the wiki text that is to be included for this view. + * + * @return string + */ + public function getResultText() { + + $this->handleParameters(); + + // Determine mark-up strings used around list items: + if ( ( $this->mFormat == 'ul' ) || ( $this->mFormat == 'ol' ) ) { + $header = "<" . $this->mFormat . ">\n"; + $footer = "</" . $this->mFormat . ">\n"; + $rowstart = "\t<li class='filtered-list-item "; + $rowend = "</li>\n"; + $listsep = ', '; + } else { // "list" format + $header = ''; + $footer = ''; + $rowstart = "\t<div class='filtered-list-item "; + $rowend = "</div>\n"; + $listsep = ', '; + } + + // Initialise more values + $result = ''; + + if ( $header !== '' ) { + $result .= $header; + } + + if ( $this->mIntroTemplate !== '' ) { + $result .= "{{" . $this->mIntroTemplate . "}}"; + } + + // Now print each row + $rownum = -1; + + foreach ($this->getQueryResults() as $id => $value) { + $row = $value->getValue(); + + $this->printRow( $row, $rownum, $rowstart . $id . "' id='$id' >", $rowend, $result, $listsep ); + } + + if ( $this->mOutroTemplate !== '' ) { + $result .= "{{" . $this->mOutroTemplate . "}}"; + } + + // Print footer + if ( $footer !== '' ) { + $result .= $footer; + } + + return $result; + } + + /** + * Prints one row of a list view. + */ + protected function printRow( $row, &$rownum, $rowstart, $rowend, &$result, $listsep ) { + + $rownum++; + + $result .= $rowstart; + + if ( $this->mTemplate !== '' ) { // build template code + $this->getQueryPrinter()->hasTemplates( true ); + + // $wikitext = ( $this->mUserParam ) ? "|userparam=$this->mUserParam" : ''; + $wikitext = ''; + + foreach ( $row as $i => $field ) { + $wikitext .= '|' . ( $this->mNamedArgs ? '?' . $field->getPrintRequest()->getLabel() : $i + 1 ) . '='; + $first_value = true; + + $field->reset(); + while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getQueryPrinter()->getLinker( $i == 0 ) ) ) !== false ) { + if ( $first_value ) $first_value = false; else $wikitext .= ', '; + $wikitext .= $text; + } + } + + $wikitext .= "|#=$rownum"; + $result .= '{{' . $this->mTemplate . $wikitext . '}}'; + + } else { // build simple list + $first_col = true; + $found_values = false; // has anything but the first column been printed? + + foreach ( $row as $field ) { + $first_value = true; + + while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getQueryPrinter()->getLinker( $first_col ) ) ) !== false ) { + if ( !$first_col && !$found_values ) { // first values after first column + $result .= ' ('; + $found_values = true; + } elseif ( $found_values || !$first_value ) { + // any value after '(' or non-first values on first column + $result .= "$listsep "; + } + + if ( $first_value ) { // first value in any column, print header + $first_value = false; + + if ( ( $this->mShowHeaders != SMW_HEADERS_HIDE ) && ( $field->getPrintRequest()->getLabel() !== '' ) ) { + $result .= $field->getPrintRequest()->getText( SMW_OUTPUT_WIKI, ( $this->mShowHeaders == SMW_HEADERS_PLAIN ? null:$this->getQueryPrinter()->getLinker(true, true) ) ) . ' '; + } + } + + $result .= $text; // actual output value + } + + $first_col = false; + } + + if ( $found_values ) $result .= ')'; + } + + $result .= $rowend; + } + + /** + * A function to describe the allowed parameters of a query for this view. + * + * @return array of Parameter + */ + public static function getParameters() { + $params = parent::getParameters(); + + $params['list view type'] = new Parameter( 'list type' ); + $params['list view type']->setMessage( 'srf-paramdesc-filtered-list-type' ); + $params['list view type']->setDefault( 'list' ); + + $params['list view template'] = new Parameter( 'list template' ); + $params['list view template']->setMessage( 'srf-paramdesc-filtered-list-template' ); + $params['list view template']->setDefault( '' ); + + $params['list view named args'] = new Parameter( 'list named args', Parameter::TYPE_BOOLEAN, false ); + $params['list view named args']->setMessage( 'srf-paramdesc-filtered-list-named-args' ); + + $params['list view introtemplate'] = new Parameter( 'list introtemplate' ); + $params['list view introtemplate']->setMessage( 'srf-paramdesc-filtered-list-introtemplate' ); + $params['list view introtemplate']->setDefault( '' ); + + $params['list view outrotemplate'] = new Parameter( 'list outrotemplate' ); + $params['list view outrotemplate']->setMessage( 'srf-paramdesc-filtered-list-outrotemplate' ); + $params['list view outrotemplate']->setDefault( '' ); + + return $params; + } + + /** + * Returns the name of the resource module to load for this view. + * + * @return string|array + */ + public function getResourceModules() { + return 'ext.srf.filtered.list-view'; + } + +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/SemanticResultFormats/Filtered/views/SRF_Filtered_View.php =================================================================== --- trunk/extensions/SemanticResultFormats/Filtered/views/SRF_Filtered_View.php (rev 0) +++ trunk/extensions/SemanticResultFormats/Filtered/views/SRF_Filtered_View.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -0,0 +1,72 @@ +<?php + +/** + * File holding the SRF_Filtered_View class + * + * @author Stephan Gambke + * @file + * @ingroup SemanticResultFormats + */ + +/** + * The SRF_Filtered_View class. + * + * @ingroup SemanticResultFormats + */ +abstract class SRF_Filtered_View { + + private $mId; + private $mResults; + private $mParameters; + private $mQueryPrinter; + + /** + * Constructor for the view. + * + * @param $id the view id + * @param $results array of SRF_Filtered_Item containing the query results + * @param type $params array of parameter values given as key-value-pairs + */ + public function __construct( $id, &$results, &$params, SRFFiltered &$queryPrinter ) { + $this->mId = $id; + $this->mResults = $results; + $this->mParameters = $params; + $this->mQueryPrinter = $queryPrinter; + } + + public function getId() {return $this->mId;} + public function &getQueryResults() {return $this->mResults;} + public function &getActualParameters() {return $this->mParameters;} + public function &getQueryPrinter() {return $this->mQueryPrinter;} + + /** + * Returns the name (string) or names (array of strings) of the resource + * modules to load. + * + * @return string|array + */ + public function getResourceModules() { + return null; + } + + /** + * A function to describe the allowed parameters of a query for this view. + * + * @return array of Parameter + */ + public static function getParameters() { + return array(); + } + + /** + * Returns the HTML text that is to be included for this view. + * + * This text will appear on the page in a div that has the view's id set as + * class. + * + * @return string + */ + public function getResultText() { + return ''; + } +} Property changes on: trunk/extensions/SemanticResultFormats/Filtered/views/SRF_Filtered_View.php ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/extensions/SemanticResultFormats/SRF_Resources.php =================================================================== --- trunk/extensions/SemanticResultFormats/SRF_Resources.php 2012-03-04 09:38:40 UTC (rev 112971) +++ trunk/extensions/SemanticResultFormats/SRF_Resources.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -124,4 +124,38 @@ 'position' => 'top', ); +$wgResourceModules['ext.srf.filtered'] = $moduleTemplate + array( + 'scripts' => array( + 'Filtered/libs/ext.srf.filtered.js', + ), + 'styles' => array( + 'Filtered/skins/ext.srf.filtered.css', + ), +); + +$wgResourceModules['ext.srf.filtered.list-view'] = $moduleTemplate + array( + 'scripts' => array( + 'Filtered/libs/ext.srf.filtered.list-view.js', + ), +// TODO: Do we need a style file? +// 'styles' => array( +// 'Filtered/skins/ext.srf.filtered.css', +// ), + 'dependencies' => array( + 'ext.srf.filtered' + ), +); + +$wgResourceModules['ext.srf.filtered.value-filter'] = $moduleTemplate + array( + 'scripts' => array( + 'Filtered/libs/ext.srf.filtered.value-filter.js', + ), + 'styles' => array( + 'Filtered/skins/ext.srf.filtered.value-filter.css', + ), + 'dependencies' => array( + 'ext.srf.filtered' + ), +); + unset( $moduleTemplate ); Modified: trunk/extensions/SemanticResultFormats/SRF_Settings.php =================================================================== --- trunk/extensions/SemanticResultFormats/SRF_Settings.php 2012-03-04 09:38:40 UTC (rev 112971) +++ trunk/extensions/SemanticResultFormats/SRF_Settings.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -53,6 +53,7 @@ $srfgFormats[] = 'D3Line'; $srfgFormats[] = 'D3Bar'; $srfgFormats[] = 'D3Treemap'; + $srfgFormats[] = 'filtered'; } # load hash format only if HashTables extension is initialised, otherwise 'Array' format is enough Modified: trunk/extensions/SemanticResultFormats/SemanticResultFormats.php =================================================================== --- trunk/extensions/SemanticResultFormats/SemanticResultFormats.php 2012-03-04 09:38:40 UTC (rev 112971) +++ trunk/extensions/SemanticResultFormats/SemanticResultFormats.php 2012-03-04 10:38:06 UTC (rev 112972) @@ -98,6 +98,7 @@ $wgAutoloadClasses['SRFD3Bar'] = $formatDir . 'D3/SRF_D3Bar.php'; $wgAutoloadClasses['SRFD3Treemap'] = $formatDir . 'D3/SRF_D3Treemap.php'; $wgAutoloadClasses['SRFTree'] = $formatDir . 'Tree/SRF_Tree.php'; +$wgAutoloadClasses['SRFFiltered'] = $formatDir . 'Filtered/SRF_Filtered.php'; unset( $formatDir ); @@ -149,6 +150,7 @@ 'tree' => 'SRFTree', 'ultree' => 'SRFTree', 'oltree' => 'SRFTree', + 'filtered' => 'SRFFiltered', ); $formatAliases = array( _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs