r114330 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114329‎ | r114330 | r114331 >
Date:23:30, 20 March 2012
Author:foxtrott
Status:deferred
Tags:
Comment:
first version of distance filter for filtered format; some small fixes
Modified paths:
  • /trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Distance.php (added) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.distance-filter.js (added) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.distance-filter.css (added) (history)
  • /trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.distance-filter.css
@@ -0,0 +1,41 @@
 2+/*
 3+ Stylesheet for the value filter
 4+*/
 5+
 6+.filtered-filters .filtered-distance {
 7+ overflow: visible;
 8+ border: 1px solid #aaa;
 9+ padding: 1em;
 10+ margin: 1em;
 11+}
 12+
 13+.filtered-filters .filtered-distance .filtered-distance-label {
 14+ height: 0;
 15+}
 16+
 17+.filtered-filters .filtered-distance .filtered-distance-label span {
 18+ background-color: white;
 19+ font-weight: bold;
 20+
 21+ position: relative;
 22+ top: -1.8em;
 23+ left: 0;
 24+
 25+ padding: 0 1em;
 26+}
 27+
 28+.filtered-filters .filtered-distance .filtered-distance-slider-cell {
 29+ width: 100%;
 30+}
 31+
 32+.filtered-filters .filtered-distance .filtered-distance-readout {
 33+ margin: 0 1em;
 34+ text-align: right;
 35+}
 36+
 37+.filtered-filters .filtered-distance .filtered-distance-slider {
 38+ border: 1px solid #aaa;
 39+ border-radius: 3px;
 40+ background: #f1f2ff;
 41+ margin: 0 1em;
 42+}
Property changes on: trunk/extensions/SemanticResultFormats/Filtered/skins/ext.srf.filtered.distance-filter.css
___________________________________________________________________
Added: svn:eol-style
143 + native
Index: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Distance.php
@@ -0,0 +1,130 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the SRF_FF_Distance class
 6+ *
 7+ * @author Stephan Gambke
 8+ * @file
 9+ * @ingroup SemanticResultFormats
 10+ */
 11+
 12+/**
 13+ * The SRF_FF_Distance class.
 14+ *
 15+ * Available parameters for this filter:
 16+ * distance filter origin: the point from which the distance is measured (address or geo coordinate)
 17+ * distance filter property: the property containing the point to which distance is measured - not implemented yet
 18+ * distance filter unit: the unit in which the distance is measured
 19+ *
 20+ * @ingroup SemanticResultFormats
 21+ */
 22+class SRF_FF_Distance extends SRF_Filtered_Filter {
 23+
 24+ private $mUnit = null;
 25+ private $mMaxDistance = 1;
 26+
 27+ public function __construct( &$results, SMWPrintRequest $printRequest, SRFFiltered &$queryPrinter ) {
 28+ parent::__construct($results, $printRequest, $queryPrinter);
 29+
 30+ if ( !defined('Maps_VERSION') || version_compare( Maps_VERSION, '1.0', '<' ) ) {
 31+ throw new FatalError('You need to have the <a href="http://www.mediawiki.org/wiki/Extension:Maps">Maps</a> extension version 1.0 or higher installed in order to use the distance filter.<br />');
 32+ }
 33+
 34+ MapsGeocoders::init();
 35+
 36+ $params = $this->getActualParameters();
 37+
 38+ if ( array_key_exists( 'distance filter origin', $params ) ) {
 39+ $origin = MapsGeocoders::attemptToGeocode( $params['distance filter origin'] );
 40+ } else {
 41+ $origin = array( 'lat'=>'0', 'lon' => '0' );
 42+ }
 43+
 44+ if ( array_key_exists( 'distance filter unit', $params ) ) {
 45+ $this->mUnit = MapsDistanceParser::getValidUnit( $params['distance filter unit'] );
 46+ } else {
 47+ $this->mUnit = MapsDistanceParser::getValidUnit();
 48+ }
 49+
 50+ $targetLabel = $printRequest->getLabel();
 51+
 52+ foreach ( $this->getQueryResults() as $id => $filteredItem ) {
 53+
 54+ $row = $filteredItem->getValue();
 55+
 56+ // $filteredItem is of class SRF_Filtered_Item
 57+ // $row is an array of SMWResultArray
 58+
 59+ foreach ( $row as $field ) {
 60+
 61+ // $field is an SMWResultArray
 62+
 63+ $label = $field->getPrintRequest()->getLabel();
 64+
 65+ if ($label === $targetLabel) {
 66+ $field->reset();
 67+ $dataValue = $field->getNextDataValue(); // only use first value
 68+
 69+ if ( $dataValue !== false ) {
 70+
 71+ $posText = $dataValue->getShortText( SMW_OUTPUT_WIKI, false );
 72+ $pos = MapsGeocoders::attemptToGeocode( $posText );
 73+
 74+ if ( is_array( $pos ) ){
 75+ $distance = round( MapsGeoFunctions::calculateDistance( $origin, $pos ) / MapsDistanceParser::getUnitRatio( $this->mUnit ) );
 76+
 77+ if ( $distance > $this->mMaxDistance ) {
 78+ $this->mMaxDistance = $distance;
 79+ }
 80+
 81+ } else {
 82+ $distance = -1;
 83+ }
 84+
 85+ } else {
 86+ $distance = -1; // no location given
 87+ }
 88+ $filteredItem->setData( 'distance-filter', $distance );
 89+ break;
 90+ }
 91+
 92+ }
 93+ }
 94+
 95+ if ( $this->mMaxDistance > 1 ) {
 96+ $base = pow( 10, floor( log10( $this->mMaxDistance ) ) );
 97+ $this->mMaxDistance = ceil ( $this->mMaxDistance / $base ) * $base;
 98+ }
 99+
 100+ }
 101+
 102+ /**
 103+ * Returns the name (string) or names (array of strings) of the resource
 104+ * modules to load.
 105+ *
 106+ * @return string|array
 107+ */
 108+ public function getResourceModules() {
 109+ return 'ext.srf.filtered.distance-filter';
 110+ }
 111+
 112+ /**
 113+ * Returns an array of config data for this filter to be stored in the JS
 114+ * @return null
 115+ */
 116+ public function getJsData() {
 117+ $params = $this->getActualParameters();
 118+
 119+ $ret = array();
 120+
 121+ $ret['unit'] = $this->mUnit;
 122+ $ret['max'] = $this->mMaxDistance;
 123+
 124+ if ( array_key_exists( 'distance filter collapsible', $params ) ) {
 125+ $ret['collapsible'] = trim($params['distance filter collapsible']);
 126+ }
 127+
 128+ return $ret;
 129+ }
 130+
 131+}
Property changes on: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Distance.php
___________________________________________________________________
Added: svn:eol-style
1132 + native
Index: trunk/extensions/SemanticResultFormats/Filtered/filters/SRF_FF_Value.php
@@ -19,18 +19,6 @@
2020 class SRF_FF_Value extends SRF_Filtered_Filter {
2121
2222 /**
23 - * Returns the HTML text that is to be included for this view.
24 - *
25 - * This text will appear on the page in a div that has the view's id set as
26 - * class.
27 - *
28 - * @return string
29 - */
30 - public function getResultText() {
31 - return '';
32 - }
33 -
34 - /**
3523 * Returns the name (string) or names (array of strings) of the resource
3624 * modules to load.
3725 *
Index: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.value-filter.js
@@ -16,67 +16,68 @@
1717
1818 function update( filtered, filtercontrols, target ) {
1919
20 - var values = filtered.data('ext.srf.filtered')['values'];
21 - var selectedInputs = filtercontrols.children('div.filtered-value-option').children('input:checked');
22 -
23 - // show all if no value is checked
24 - if ( selectedInputs.length == 0 ) {
25 - for ( i in values ) {
26 - filtered.filtered( 'voteItemVisibilityAndUpdate', {
27 - 'filter': 'value',
28 - 'printout' : target,
29 - 'visible': true,
30 - 'item': i
31 - });
32 - }
33 -
34 - } else {
35 -
36 - for ( i in values ) {
 20+ var values = filtered.data('ext.srf.filtered')['values'];
 21+ var selectedInputs = filtercontrols.children('div.filtered-value-option').children('input:checked');
3722
38 - var printoutValues = values[i]['printouts'][target]['values'];
39 - var useOr = filtered.filtered( 'getFilterData', {filter: 'value', printout: target, configvar: 'use or'} );
 23+ // show all if no value is checked
 24+ if ( selectedInputs.length == 0 ) {
 25+ for ( i in values ) {
 26+ filtered.filtered( 'voteItemVisibilityAndUpdate', {
 27+ 'filter': 'value',
 28+ 'printout' : target,
 29+ 'visible': true,
 30+ 'item': i
 31+ });
 32+ }
4033
41 - if ( useOr ) {
42 - var selected = false;
 34+ } else {
4335
44 - for ( var j in printoutValues ) {
 36+ for ( i in values ) {
4537
46 - selectedInputs.each(function(){
47 - selected = selected || ( printoutValues[j] == $(this).attr('value') );
48 - });
49 - }
50 - } else {
51 - var selected = ( printoutValues.length > 0 );
 38+ var printoutValues = values[i]['printouts'][target]['values'];
 39+ var useOr = filtered.filtered( 'getFilterData', {filter: 'value', printout: target, configvar: 'use or'} );
5240
53 - if ( selected ) {
54 - // try to find each required value
55 - selectedInputs.each(function(){
 41+ if ( useOr ) {
 42+ var selected = false;
5643
57 - var selectedFoundInPrintout = false;
58 - for ( var j in printoutValues ) {
59 - selectedFoundInPrintout = selectedFoundInPrintout || ( printoutValues[j] == $(this).attr('value') );
 44+ for ( var j in printoutValues ) {
6045
61 - if ( selectedFoundInPrintout ) {
62 - break;
63 - }
 46+ selectedInputs.each(function(){
 47+ selected = selected || ( printoutValues[j] == $(this).attr('value') );
 48+ });
 49+ }
 50+ } else {
 51+ var selected = ( printoutValues.length > 0 );
 52+
 53+ if ( selected ) {
 54+ // try to find each required value
 55+ selectedInputs.each(function(){
 56+
 57+ var selectedFoundInPrintout = false;
 58+ for ( var j in printoutValues ) {
 59+ selectedFoundInPrintout = selectedFoundInPrintout || ( printoutValues[j] == $(this).attr('value') );
 60+
 61+ if ( selectedFoundInPrintout ) {
 62+ break;
6463 }
65 - selected = selected && selectedFoundInPrintout;
66 - });
67 - }
 64+ }
 65+ selected = selected && selectedFoundInPrintout;
 66+ });
6867 }
 68+ }
6969
70 - filtered.filtered( 'voteItemVisibilityAndUpdate', {
71 - 'filter': 'value',
72 - 'printout' : target,
73 - 'visible': selected,
74 - 'item': i
75 - });
 70+ filtered.filtered( 'voteItemVisibilityAndUpdate', {
 71+ 'filter': 'value',
 72+ 'printout' : target,
 73+ 'visible': selected,
 74+ 'item': i
 75+ });
7676
77 - }
7877 }
79 - }
 78+ }
 79+ } // function update( filtered, filtercontrols, target )
8080
 81+
8182 var filtered = this;
8283
8384 var values = this.data('ext.srf.filtered')['values'];
@@ -112,10 +113,10 @@
113114 filtercontrols.append('<div class="filtered-value-label"><span>' + values[i]['printouts'][target]['label'] + '</span></div>');
114115
115116 if ( collapsible != null && ( collapsible == 'collapsed' || collapsible == 'uncollapsed') ) {
 117+
116118 var showControl = $('<span class="filtered-value-show">[+]</span>');
117119 var hideControl = $('<span class="filtered-value-hide">[-]</span>');
118120
119 -
120121 filtercontrols
121122 .prepend(showControl)
122123 .prepend(hideControl);
@@ -123,21 +124,23 @@
124125 filtercontrols = $('<div class="filtered-value-collapsible">')
125126 .appendTo(filtercontrols);
126127
 128+ var outercontrols = filtercontrols
 129+
127130 showControl.click(function(){
128 - filtercontrols.slideDown();
 131+ outercontrols.slideDown();
129132 showControl.hide();
130133 hideControl.show();
131134 });
132135
133136 hideControl.click(function(){
134 - filtercontrols.slideUp();
 137+ outercontrols.slideUp();
135138 showControl.show();
136139 hideControl.hide();
137140 });
138141
139142 if ( collapsible == 'collapsed' ) {
140143 hideControl.hide();
141 - filtercontrols.slideUp(0);
 144+ outercontrols.slideUp(0);
142145 } else {
143146 showControl.hide();
144147 }
Index: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.js
@@ -30,13 +30,11 @@
3131 // init housekeeping on values
3232 for (i in data['values']) {
3333
34 - data['values'][i]['data'] = {
35 -
36 - 'visibility': {
37 - 'overall' : true,
38 - 'votes' : {}
39 - }
 34+ data['values'][i]['data']['visibility'] = {
 35+ 'overall' : true,
 36+ 'votes' : {}
4037 }
 38+
4139 }
4240
4341 return this;
Index: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.distance-filter.js
@@ -0,0 +1,225 @@
 2+/**
 3+ * File holding the distance-filter plugin
 4+ *
 5+ * For this plugin to work, the filtered plugin needs to be available first.
 6+ *
 7+ * @author Stephan Gambke
 8+ * @file
 9+ * @ingroup SemanticResultFormats
 10+ */
 11+
 12+(function ($) {
 13+
 14+ var methods = {
 15+
 16+ init: function( args ){
 17+
 18+ function update( filtered, filterDistance, target ) {
 19+
 20+ var values = filtered.data('ext.srf.filtered')['values'];
 21+
 22+ for ( i in values ) {
 23+
 24+ var distance = values[i]['data']['distance-filter'];
 25+
 26+ filtered.filtered( 'voteItemVisibilityAndUpdate', {
 27+ 'filter': 'value',
 28+ 'printout' : target,
 29+ 'visible': distance <= filterDistance,
 30+ 'item': i
 31+ });
 32+
 33+ }
 34+
 35+ } // function update( filtered, filterDistance, target )
 36+
 37+
 38+ var filtered = this;
 39+
 40+
 41+
 42+ var target = args.printout;
 43+ var values = this.data('ext.srf.filtered')['values'];
 44+ var data = this.data('ext.srf.filtered')['data']['filterdata']['distance'][target];
 45+
 46+ // build filter controls
 47+ var filtercontrols = this.children('.filtered-filters').children('.filtered-distance');
 48+
 49+ // insert the label of the printout this filter filters on
 50+
 51+ for ( var i in values ) break;
 52+
 53+ var readoutAndSlider = $('<tr>');
 54+
 55+ var readout = $('<div class="filtered-distance-readout">' + data['max'] + data['unit'] + '</div>' );
 56+ var slider = $('<div class="filtered-distance-slider">');
 57+
 58+ var readoutTD = $('<td class="filtered-distance-readout-cell">');
 59+ var sliderTD = $('<td class="filtered-distance-slider-cell">');
 60+
 61+ readoutTD.append( readout );
 62+ sliderTD.append( slider );
 63+
 64+ readoutAndSlider
 65+ .append( readoutTD )
 66+ .append( sliderTD );
 67+
 68+ filtercontrols
 69+ .append( '<div class="filtered-distance-label"><span>' + values[i]['printouts'][target]['label'] + '</span></div>' )
 70+ .append( readoutAndSlider );
 71+
 72+ readoutAndSlider.wrap('<table><tbody>');
 73+
 74+ readout.width( readout.width() ); // fix width of readout
 75+
 76+ slider.slider({
 77+ animate: true,
 78+ max: data['max'],
 79+ value: data['max'],
 80+ slide: function(event, ui) {
 81+ readout.empty().append( ui.value + data['unit'] );
 82+ },
 83+ change: function(event, ui) {
 84+ update( filtered, ui.value, target );
 85+ }
 86+ });
 87+
 88+// // insert the label of the printout this filter filters on
 89+// filtercontrols.append('<div class="filtered-value-label"><span>' + values[i]['printouts'][target]['label'] + '</span></div>');
 90+//
 91+// if ( collapsible != null && ( collapsible == 'collapsed' || collapsible == 'uncollapsed') ) {
 92+// var showControl = $('<span class="filtered-value-show">[+]</span>');
 93+// var hideControl = $('<span class="filtered-value-hide">[-]</span>');
 94+//
 95+//
 96+// filtercontrols
 97+// .prepend(showControl)
 98+// .prepend(hideControl);
 99+//
 100+// filtercontrols = $('<div class="filtered-value-collapsible">')
 101+// .appendTo(filtercontrols);
 102+//
 103+// showControl.click(function(){
 104+// filtercontrols.slideDown();
 105+// showControl.hide();
 106+// hideControl.show();
 107+// });
 108+//
 109+// hideControl.click(function(){
 110+// filtercontrols.slideUp();
 111+// showControl.show();
 112+// hideControl.hide();
 113+// });
 114+//
 115+// if ( collapsible == 'collapsed' ) {
 116+// hideControl.hide();
 117+// filtercontrols.slideUp(0);
 118+// } else {
 119+// showControl.hide();
 120+// }
 121+//
 122+// }
 123+//
 124+// // set default config values
 125+// filtered.filtered( 'setFilterData', {filter: 'value', printout: target, configvar: 'use or', configvalue: true} );
 126+//
 127+//
 128+// // insert switches
 129+// if ( switches != null && switches.length > 0 ) {
 130+//
 131+// var switchControls = $('<div class="filtered-value-switches">');
 132+//
 133+// if ( $.inArray('and or', switches) >= 0 ) {
 134+//
 135+// var andorControl = $('<div class="filtered-value-andor">');
 136+// var andControl = $('<input type="radio" name="filtered-value-andor ' +
 137+// target + '" class="filtered-value-andor ' + target + '" value="and">');
 138+//
 139+// var orControl = $('<input type="radio" name="filtered-value-andor ' +
 140+// target + '" class="filtered-value-andor ' + target + '" value="or" checked>');
 141+//
 142+// andControl
 143+// .add( orControl )
 144+// .change(function() {
 145+// filtered.filtered( 'setFilterData', {filter: 'value', printout: target, configvar: 'use or', configvalue: orControl.is(':checked')} );
 146+// update( filtered, filtercontrols, target );
 147+// });
 148+//
 149+// andorControl
 150+// .append( orControl )
 151+// .append(' OR ')
 152+// .append( andControl )
 153+// .append(' AND ')
 154+// .appendTo( switchControls );
 155+//
 156+// }
 157+//
 158+// filtercontrols.append( switchControls );
 159+// }
 160+//
 161+// if ( height != null ) {
 162+// filtercontrols = $( '<div class="filtered-value-scrollable">' )
 163+// .appendTo( filtercontrols );
 164+//
 165+// filtercontrols.height( height );
 166+// }
 167+//
 168+//
 169+// var sortedDistinctValues = [];
 170+//
 171+// for ( var i in distinctValues ) {
 172+// sortedDistinctValues.push(i);
 173+// }
 174+//
 175+// sortedDistinctValues.sort();
 176+//
 177+// // insert options (checkboxes and labels) and attach event handlers
 178+// // TODO: Do we need to wrap these in a form?
 179+// for ( var j in sortedDistinctValues ) {
 180+// var option = $('<div class="filtered-value-option">');
 181+// var checkbox = $('<input type="checkbox" class="filtered-value-value" value="' + sortedDistinctValues[j] + '" >');
 182+//
 183+// // attach event handler
 184+// checkbox.change(function( evt ){
 185+// update(filtered, filtercontrols, target);
 186+// });
 187+//
 188+// option
 189+// .append(checkbox)
 190+// .append(sortedDistinctValues[j]);
 191+//
 192+// filtercontrols
 193+// .append(option);
 194+//
 195+// }
 196+
 197+ return this;
 198+ },
 199+
 200+ alert: function(){
 201+ alert('DistanceFilter!');
 202+ return this;
 203+ }
 204+
 205+ };
 206+
 207+ distanceFilter = function( method ) {
 208+
 209+ // Method calling logic
 210+ if ( methods[method] ) {
 211+ return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
 212+ } else if ( typeof method === 'object' || ! method ) {
 213+ return methods.init.apply( this, arguments );
 214+ } else {
 215+ $.error( 'Method ' + method + ' does not exist on jQuery.filtered.distanceFilter' );
 216+ }
 217+
 218+
 219+ };
 220+
 221+ // attach ListView to all Filtered query printers
 222+ // let them sort out, if ListView is actually applicable to them
 223+ jQuery('.filtered').filtered('attachFilter', 'distance', distanceFilter );
 224+
 225+})(jQuery);
 226+
Property changes on: trunk/extensions/SemanticResultFormats/Filtered/libs/ext.srf.filtered.distance-filter.js
___________________________________________________________________
Added: svn:eol-style
1227 + native
Index: trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered_Item.php
@@ -24,16 +24,16 @@
2525 $this->mQueryPrinter = $queryPrinter;
2626 }
2727
28 - public function setDataForView ( $viewId, &$data ) {
29 - $this->mItemData[$viewId] = $data;
 28+ public function setData ( $viewOrFilterId, $data ) {
 29+ $this->mItemData[$viewOrFilterId] = $data;
3030 }
3131
32 - public function unsetDataForView ( $viewId ) {
33 - unset( $this->mItemData[$viewId] );
 32+ public function unsetData ( $viewOrFilterId ) {
 33+ unset( $this->mItemData[$viewOrFilterId] );
3434 }
3535
36 - public function getDataForView ( $viewId ) {
37 - return $this->mItemData[$viewId];
 36+ public function getData ( $viewOrFilterId ) {
 37+ return $this->mItemData[$viewOrFilterId];
3838 }
3939
4040 public function getValue() {
Index: trunk/extensions/SemanticResultFormats/Filtered/views/SRF_FV_List.php
@@ -138,6 +138,7 @@
139139 foreach ( $row as $field ) {
140140 $first_value = true;
141141
 142+ $field->reset();
142143 while ( ( $text = $field->getNextText( SMW_OUTPUT_WIKI, $this->getQueryPrinter()->getLinker( $first_col ) ) ) !== false ) {
143144 if ( !$first_col && !$found_values ) { // first values after first column
144145 $result .= ' (';
Index: trunk/extensions/SemanticResultFormats/Filtered/SRF_Filtered.php
@@ -18,6 +18,7 @@
1919
2020 $wgAutoloadClasses['SRF_Filtered_Filter'] = $formatDir . 'filters/SRF_Filtered_Filter.php';
2121 $wgAutoloadClasses['SRF_FF_Value'] = $formatDir . 'filters/SRF_FF_Value.php';
 22+$wgAutoloadClasses['SRF_FF_Distance'] = $formatDir . 'filters/SRF_FF_Distance.php';
2223
2324
2425 /**
@@ -68,6 +69,7 @@
6970 */
7071 private $mFilterTypes = array(
7172 'value' => 'SRF_FF_Value',
 73+ 'distance' => 'SRF_FF_Distance',
7274 );
7375
7476 private $mViews;

Status & tagging log