Page MenuHomePhabricator

"Add drilldown links" parameter for automatic Special:Drilldown links (in particular for Lists of String)
Open, Needs TriagePublic

Description

We discussed this on the talk page under the heading "Show List of Strings as links to Special:Drilldown".

Here is a patch which allows the user to add an extra "add drilldown links" parameter to #cargo_query so that, for selected fields, each value is automatically displayed as a link to Special:Drilldown with the relevant filter applied.

Currently it works for (a) Lists of String, and (b) String field types.

  • To convert individual items in a List to links it is necessary to amend Cargo code (outside a List we could just use CONCAT in a query).
  • You may think it ought to apply to other types which get a filter on Special:Drilldown (Page, Integer, Float, Date and Datetime). I think Page should be left alone (i.e. a red link if non-existent), and you mentioned practical problems with doing it for Date/Datetime, and I guess Float too (?) - perhaps it should just be extended to Integer.

The automatic drilldown links have the Miga magnifying glass beside them to indicate that they are not normal links.

I have used global variables to create the links but I imagine there is a better way using MediaWiki's classes.

The new parameter takes a list of fields, whose values are to be displayed as Special:Drilldown links. It can be used in the following format.

{{#cargo_query:
tables=Contact
|fields= _pageName, Address, Telephones_numbers, Fax_number
|format=dynamic table
|add drilldown links=Address, Telephone_numbers
}}

I've not finished it or tested it fully, but would appreciate your thoughts!

diff --git a/CargoQueryDisplayer.php b/CargoQueryDisplayer.php
index f37bc7c..aba5cd5 100644
--- a/CargoQueryDisplayer.php
+++ b/CargoQueryDisplayer.php
@@ -86,6 +86,13 @@ class CargoQueryDisplayer {
 	public function getFormattedQueryResults( $queryResults ) {
 		// The assignment will do a copy.
 		$formattedQueryResults = $queryResults;
+
+		if ( array_key_exists( 'add drilldown links', $this->mDisplayParams ) ) {
+			$drillDownFields = explode (',', $this->mDisplayParams['add drilldown links']);
+			#Allow users to separate fields with comma, with or without spaces:
+			$drillDownFields = array_map('trim', $drillDownFields);
+		}
+
 		foreach ( $queryResults as $rowNum => $row ) {
 			foreach ( $row as $fieldName => $value ) {
 				if ( trim( $value ) == '' ) {
@@ -122,8 +129,19 @@ class CargoQueryDisplayer {
 							// list parsing worked.
 							$text .= " · ";
 						}
-						$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
-					}
+						
+						if ( (in_array( $fieldName, $drillDownFields ) ) && ($fieldType == 'String') ) {
+							# Add drilldown links if requested by user (for Lists of Strings)
+							global $wgServer, $wgScriptPath;
+							$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . trim($fieldValue) . '" class="drilldownlink">';
+							$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
+							$text .= '</a>';							
+						} else {
+							# Default: do not add drilldown links 
+							$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
+						}
+	
+					}	
 				} elseif ( $fieldType == 'Date' || $fieldType == 'Datetime' ) {
 					$datePrecisionField = str_replace( '_', ' ', $fieldName ) . '__precision';
 					if ( array_key_exists( $datePrecisionField, $row ) ) {
@@ -150,6 +168,12 @@ class CargoQueryDisplayer {
 				} elseif ( $fieldType == 'Searchtext' && $this->mSQLQuery && array_key_exists( $fieldName, $this->mSQLQuery->mSearchTerms ) ) {
 					$searchTerms = $this->mSQLQuery->mSearchTerms[$fieldName];
 					$text = Html::rawElement( 'span', array( 'class' => 'searchresult' ), self::getTextSnippet( $value, $searchTerms ) );
+				} elseif ( (in_array( $fieldName, $drillDownFields ) ) && ($fieldType == 'String') ) {
+						# Add drilldown links if requested by user (for Strings which aren't in Lists)
+						global $wgServer, $wgScriptPath;
+						$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . $value . '" class="drilldownlink">';
+						$text .= self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
+						$text .= '</a>';							
 				} else {
 					$text = self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
 				}

Event Timeline

Sorry, I should add that currently I just have the CSS in Common.css:

a.drilldownlink {
	padding-right: 12px;
	background-image: url('http://migadv.com/miga/images/miga-query-light.png');
	background-repeat: no-repeat;
	background-position: right top;
}

Oh, very interesting. I agree that it would be great to have some sort of functionality like this. A few thoughts:

  • It may make sense to have "add drilldown links" just be a boolean parameter, instead of holding a list - i.e., if it's set, just add drilldown links to all the relevant fields. But maybe not.
  • It may make sense to have the magnifying glass be the clickable part, instead of the entire word or string. That way it could work equally well for Page values - users could click on either the link to the page, or the "browse" magnifying glass. On the other hand, maybe the magnifying glass is too small a target. It's an option, though.

Cheers. In relation to your two points:

  1. I think it is better the way it is, as it provides flexibility (the user can choose which fields have drilldown links) in an easy-to-use way.
    • However, you could (also) have it that if it has NO parameters, then it sets a variable which adds drilldown links for all fields.
  2. I can see your point but you are right that the icon is too small, particularly on smartphones. I think the answer for Page values is to allow users to decide whether they display as page links or drilldown links (see first point).

Where is the best file to put the CSS? When I move it from Mediawiki:Common.css to the file Cargo.css it ceases to have effect.

Sorry for the delay. Yes, you may be right about all the UI stuff - it would probably help to see it in action.

Yes, Cargo.css won't work, because Special:Drilldown doesn't load it - you need to modify /drilldown/resources/CargoDrilldown.css.

That didn't work for the CSS, for me anyway. The CSS isn't needed in Special:Drilldown, but in a normal page's Cargo query.

In the end I kept it in Cargo.css but added Cargo.css to ext.cargo.datatables in extension.json as follows:

		"ext.cargo.datatables": {
			"styles": [
				"libs/DataTables/css/jquery.dataTables.css",
				"Cargo.css"
			],

There are only four formats which have the

$this->mOutput->addModuleStyles( 'ext.cargo.main' );

line, which loads Cargo.css. These are formats/CargoTagCloudFormat.php, formats/CargoTableFormat.php, formats/CargoExhibitFormat.php, and formats/CargoListFormat.php

Maybe that means that other output formats don't load it, and should.

Sorry, I forgot to add that the CSS did load from Cargo.css for format=table but not for format=dynamic table. I needed it to work for dynamic tables, which is why I ended up adding Cargo.css to the styles of ext.cargo.datatables. I hope it makes sense now!

Yes, now I get it. And adding that module for "datatables" makes sense - and for any other format that might need it.

Earlier you said...

It may make sense to have the magnifying glass be the clickable part, instead of the entire word or string. That way it could work equally well for Page values - users could click on either the link to the page, or the "browse" magnifying glass. On the other hand, maybe the magnifying glass is too small a target. It's an option, though.

... and I disagreed. But I've thought it through and agree with you, as this way would avoid confusion with Page values, and probably would also look neater on the page generally. I'll see what I can do in the next few days.

Here's what I have so far. It's the magnifying glass that is the link. Not tested yet with Integer or Page. Feel free to let me know what you think!

diff --git a/Cargo.css b/Cargo.css
index 5ccbd81..3fbf972 100644
--- a/Cargo.css
+++ b/Cargo.css
@@ -25,3 +25,7 @@ span.searchresult {
 span.searchmatch {
 	font-weight: bold;
 }
+
+a.drilldownlink {
+	/* Insert any CSS here */
+}
\ No newline at end of file
diff --git a/CargoQueryDisplayer.php b/CargoQueryDisplayer.php
index f37bc7c..b37914e 100644
--- a/CargoQueryDisplayer.php
+++ b/CargoQueryDisplayer.php
@@ -86,6 +86,13 @@ class CargoQueryDisplayer {
 	public function getFormattedQueryResults( $queryResults ) {
 		// The assignment will do a copy.
 		$formattedQueryResults = $queryResults;
+
+		if ( array_key_exists( 'add drilldown links', $this->mDisplayParams ) ) {
+			$drillDownFields = explode (',', $this->mDisplayParams['add drilldown links']);
+			#Allow users to separate fields with comma, with or without spaces:
+			$drillDownFields = array_map('trim', $drillDownFields);
+		}
+
 		foreach ( $queryResults as $rowNum => $row ) {
 			foreach ( $row as $fieldName => $value ) {
 				if ( trim( $value ) == '' ) {
@@ -122,8 +129,16 @@ class CargoQueryDisplayer {
 							// list parsing worked.
 							$text .= " &middot; ";
 						}
+						
 						$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
-					}
+						if ( (in_array( $fieldName, $drillDownFields ) ) && (in_array( $fieldType, array('String', 'Integer', 'Page') ) ) ) {
+							# Add drilldown link icon to List items if requested by user & is String/Integer/Page ***
+							global $wgServer, $wgScriptPath, $wgCargoDrilldownLinkIcon;
+							$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . trim($fieldValue) . '">';
+							$text .= '<img src="' . $wgCargoDrilldownLinkIcon . '" class="drilldownlink"/>';
+							$text .= '</a>';
+						} 
+					}	
 				} elseif ( $fieldType == 'Date' || $fieldType == 'Datetime' ) {
 					$datePrecisionField = str_replace( '_', ' ', $fieldName ) . '__precision';
 					if ( array_key_exists( $datePrecisionField, $row ) ) {
@@ -153,6 +168,15 @@ class CargoQueryDisplayer {
 				} else {
 					$text = self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
 				}
+				
+				if ( (!$fieldDescription->mIsList) && (in_array( $fieldName, $drillDownFields ) ) && (in_array( $fieldType, array('String', 'Integer', 'Page') ) ) ) {
+					# Add drilldown link icon if not in List & requested by user & is String/Integer/Page ***
+					global $wgServer, $wgScriptPath, $wgCargoDrilldownLinkIcon;
+					$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . $value . '">';
+					$text .= '<img src="' . $wgCargoDrilldownLinkIcon . '"  class="drilldownlink"/>';
+					$text .= '</a>';							
+				}
+				
 				if ( $text != '' ) {
 					$formattedQueryResults[$rowNum][$fieldName] = $text;
 				}
diff --git a/extension.json b/extension.json
index 2d3240a..a225034 100755
--- a/extension.json
+++ b/extension.json
@@ -198,7 +198,8 @@
 		},
 		"ext.cargo.datatables": {
 			"styles": [
-				"libs/DataTables/css/jquery.dataTables.css"
+				"libs/DataTables/css/jquery.dataTables.css",
+				"Cargo.css"
 			],
 			"scripts": [
 				"libs/DataTables/js/jquery.dataTables.js",
@@ -302,6 +303,7 @@
 		"CargoDrilldownLargestFontSize": -1,
 		"CargoDrilldownMinValuesForComboBox": 40,
 		"CargoDrilldownNumRangesForNumbers": 5,
+		"CargoDrilldownLinkIcon": "http://migadv.com/miga/images/miga-query-light.png",
 		"CargoPageDataColumns": [],
 		"CargoFileDataColumns": [],
 		"CargoHideNamespaceName": [6],
diff --git a/formats/CargoDynamicTableFormat.php b/formats/CargoDynamicTableFormat.php
index 8d9e73f..05126f6 100644
--- a/formats/CargoDynamicTableFormat.php
+++ b/formats/CargoDynamicTableFormat.php
@@ -24,7 +24,6 @@ class CargoDynamicTableFormat extends CargoDisplayFormat {
 	 */
 	function display( $valuesTable, $formattedValuesTable, $fieldDescriptions, $displayParams ) {
 		$this->mOutput->addModules( 'ext.cargo.datatables' );
-
 		// Special handlng for ordering.
 		$dataOrderString = null;
 		if ( array_key_exists( 'order by', $displayParams ) ) {

Okay, I set up this code on my wiki. The new feature looks good! There are some coding choices I disagree with (I don't think the image needs to be a global variable - it can be hardcoded), but those are pretty minor. Overall, this seems like a good feature.

The image itself should probably be improved - it should probably be a little larger, both for greater visibility and greater clickability on mobile devices, and maybe a little darker too. And I think it should change color somehow on hover. I don't know if you have any thoughts about that.

Also, what do you think about allowing "add drilldown links" as a parameter by itself - so that if it doesn't get values, all the relevant fields get a magnifying glass? It's like an earlier suggestion I made, but this time users would have the option of either explicitly specifying the set of fields or not.

Pleased you like it :-)

The image itself should probably be improved - it should probably be a little larger, both for greater visibility and greater clickability on mobile devices, and maybe a little darker too. And I think it should change color somehow on hover. I don't know if you have any thoughts about that.

I agree, but I'm no good at images, sorry (though the colour change should be simple). There is probably something online already that could be adopted/adapted (e.g. https://commons.wikimedia.org/wiki/File:Magnifying_glass_icon.svg).

Also, what do you think about allowing "add drilldown links" as a parameter by itself - so that if it doesn't get values, all the relevant fields get a magnifying glass? It's like an earlier suggestion I made, but this time users would have the option of either explicitly specifying the set of fields or not.

I completely agree with that ("However, you could (also) have it that if it has NO parameters, then it sets a variable which adds drilldown links for all fields.") I'll have a go over the next few days.

In the code below, if you add |add drilldown links (with no equals sign and no parameters) it displays the magnifying glass for all possible fields.

I've changed the icon URL so it's no longer a global variable.

No progress yet on the icon itself though...

diff --git a/Cargo.css b/Cargo.css
index 5ccbd81..3fbf972 100644
--- a/Cargo.css
+++ b/Cargo.css
@@ -25,3 +25,7 @@ span.searchresult {
 span.searchmatch {
 	font-weight: bold;
 }
+
+a.drilldownlink {
+	/* Insert any CSS here */
+}
\ No newline at end of file
diff --git a/CargoQueryDisplayer.php b/CargoQueryDisplayer.php
index f37bc7c..4a5d4f9 100644
--- a/CargoQueryDisplayer.php
+++ b/CargoQueryDisplayer.php
@@ -86,6 +86,13 @@ class CargoQueryDisplayer {
 	public function getFormattedQueryResults( $queryResults ) {
 		// The assignment will do a copy.
 		$formattedQueryResults = $queryResults;
+
+		if ( array_key_exists( 'add drilldown links', $this->mDisplayParams ) ) {
+			$drillDownFields = explode (',', $this->mDisplayParams['add drilldown links']);
+			#Allow users to separate fields with comma, with or without spaces:
+			$drillDownFields = array_map('trim', $drillDownFields);
+		}
+
 		foreach ( $queryResults as $rowNum => $row ) {
 			foreach ( $row as $fieldName => $value ) {
 				if ( trim( $value ) == '' ) {
@@ -122,8 +129,19 @@ class CargoQueryDisplayer {
 							// list parsing worked.
 							$text .= " &middot; ";
 						}
+						
 						$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
-					}
+
+						# Add drilldown link icon to List items if requested by user & is String/Integer/Page ***
+						if (   ( (in_array( $fieldName, $drillDownFields ) ) || (  $drillDownFields[0]=='all' ) )
+							&& (in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+						) {
+							global $wgServer, $wgScriptPath;
+							$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . trim($fieldValue) . '">';
+							$text .= '<img src="http://migadv.com/miga/images/miga-query-light.png" class="drilldownlink"/>';
+							$text .= '</a>';
+						} 
+					}	
 				} elseif ( $fieldType == 'Date' || $fieldType == 'Datetime' ) {
 					$datePrecisionField = str_replace( '_', ' ', $fieldName ) . '__precision';
 					if ( array_key_exists( $datePrecisionField, $row ) ) {
@@ -153,6 +171,19 @@ class CargoQueryDisplayer {
 				} else {
 					$text = self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
 				}
+				
+				# Add drilldown link icon if not in List & requested by user & is String/Integer/Page ***
+				if (   ( !$fieldDescription->mIsList ) 
+					&& ( $fieldName != '_pageName' )
+					&& ( (in_array( $fieldName, $drillDownFields ) ) || ( $drillDownFields[0]=='all' ) ) 
+					&& ( in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+				) {
+					global $wgServer, $wgScriptPath;
+					$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . $value . '">';
+					$text .= '<img src="http://migadv.com/miga/images/miga-query-light.png" class="drilldownlink"/>';
+					$text .= '</a>';							
+				}
+				
 				if ( $text != '' ) {
 					$formattedQueryResults[$rowNum][$fieldName] = $text;
 				}
diff --git a/extension.json b/extension.json
index 2d3240a..f864bdf 100755
--- a/extension.json
+++ b/extension.json
@@ -198,7 +198,8 @@
 		},
 		"ext.cargo.datatables": {
 			"styles": [
-				"libs/DataTables/css/jquery.dataTables.css"
+				"libs/DataTables/css/jquery.dataTables.css",
+				"Cargo.css"
 			],
 			"scripts": [
 				"libs/DataTables/js/jquery.dataTables.js",
diff --git a/formats/CargoDynamicTableFormat.php b/formats/CargoDynamicTableFormat.php
index 8d9e73f..05126f6 100644
--- a/formats/CargoDynamicTableFormat.php
+++ b/formats/CargoDynamicTableFormat.php
@@ -24,7 +24,6 @@ class CargoDynamicTableFormat extends CargoDisplayFormat {
 	 */
 	function display( $valuesTable, $formattedValuesTable, $fieldDescriptions, $displayParams ) {
 		$this->mOutput->addModules( 'ext.cargo.datatables' );
-
 		// Special handlng for ordering.
 		$dataOrderString = null;
 		if ( array_key_exists( 'order by', $displayParams ) ) {
diff --git a/parserfunctions/CargoQuery.php b/parserfunctions/CargoQuery.php
index 68556df..9b39a65 100644
--- a/parserfunctions/CargoQuery.php
+++ b/parserfunctions/CargoQuery.php
@@ -38,6 +38,9 @@ class CargoQuery {
 				if ( $param == 'no html' ) {
 					$noHTML = true;
 				}
+				if ( $param == 'add drilldown links') {
+					$displayParams['add drilldown links'] = 'all';
+				}
 				continue;
 			}
 			if ( count( $parts ) > 2 ) {

From Wikipedia: "The magnifying glass (i.e. Magnifying glass icon.svg, or U+1F50D in Unicode: 🔍) is commonly used as a symbolic representation for the ability to search or zoom, especially in computer software and websites.[4][5]".

The unicode symbol looks really nice when used as a direct replacement for the Miga icon. It looks different on my PC (Chome) and on the iPhone, but both look good. I guess that being a character it is easy to ensure it is the right size alongside the text. Is there any reason not to use a unicode character?

Okay, great! I think the use of the string 'all' is kind of a hack - it would probably be better to have a different $displayParams key - but that's a minor point.

More interesting is the use of the Unicode magnifying glass icon. I think I didn't realize before that there was one. I checked it out on some different browsers and devices - in my opinion, it looks great on MS Edge and IE (pretty much standard black and white), pretty good on the iPhone, fair on Chrome on Windows (maybe a little too colorful), and pretty bad on Android, at least on the Samsung Galaxy - lots of 3D shine, and a drop shadow (?).

Another potential objection to using the Unicode character is that, as far as I can tell, it can't be lightened or darkened on hover, to show that it's clickable, except in Edge/IE. The only thing you can do, it seems, is to make it larger. Maybe that's enough, though.

Certainly using a Unicode character seems like a nicer option, in theory - it would load faster, you can copy/paste it, and accessibility might be better. It does have some of these drawbacks, though. What do you think?

I like the Unicode character :-) I think it maybe looks better on Chrome so it must be a matter of taste.

It is possible to highlight on hover: see the code below. Again, it looks different on different browsers.

Another benefit (as you mentioned) is that it loads just as quickly as the text.

I have added a new $displayParams key and $drillDownAll variable in response to your comment.

Also it now sets $drillDownAll when someone uses either |add drilldown links or (probably mistakenly) |add drilldown links= (with an equals). Before, in the latter case none of the fields would have the magnifying glass.

I've tested it with String, Integer, Page, and List of String input types.

Incidentally I think maybe there is a problem with how Cargo handles Lists of Integer - I've mentioned it on the talk page just now.

diff --git a/Cargo.css b/Cargo.css
index 5ccbd81..07562aa 100644
--- a/Cargo.css
+++ b/Cargo.css
@@ -25,3 +25,8 @@ span.searchresult {
 span.searchmatch {
 	font-weight: bold;
 }
+
+a.drilldownlink:hover {
+	color: transparent;
+	text-shadow: 0 0 0 black;
+}
\ No newline at end of file
diff --git a/CargoQueryDisplayer.php b/CargoQueryDisplayer.php
index f37bc7c..fd49b55 100644
--- a/CargoQueryDisplayer.php
+++ b/CargoQueryDisplayer.php
@@ -86,6 +86,19 @@ class CargoQueryDisplayer {
 	public function getFormattedQueryResults( $queryResults ) {
 		// The assignment will do a copy.
 		$formattedQueryResults = $queryResults;
+
+		if ( array_key_exists( 'add drilldown links', $this->mDisplayParams ) ) {
+			if (!empty($this->mDisplayParams['add drilldown links'])) {
+				$drillDownFields = explode (',', $this->mDisplayParams['add drilldown links']);
+				$drillDownFields = array_map('trim', $drillDownFields); // Remove any spaces
+			} else {
+				$drillDownAll = true; 
+			}
+		}	
+		if ( array_key_exists( 'add all drilldown links', $this->mDisplayParams ) ) {
+			$drillDownAll = true;
+		}
+
 		foreach ( $queryResults as $rowNum => $row ) {
 			foreach ( $row as $fieldName => $value ) {
 				if ( trim( $value ) == '' ) {
@@ -122,8 +135,16 @@ class CargoQueryDisplayer {
 							// list parsing worked.
 							$text .= " &middot; ";
 						}
+						
 						$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
-					}
+						# Add drilldown link icon to List items if requested by user & is String/Integer/Page ***
+						if (   ( ( in_array( $fieldName, $drillDownFields ) ) || $drillDownAll )
+							&& ( in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+						) {
+							global $wgServer, $wgScriptPath;
+							$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . trim($fieldValue) . '" class="drilldownlink">&#128269;</a>';
+						} 
+					}	
 				} elseif ( $fieldType == 'Date' || $fieldType == 'Datetime' ) {
 					$datePrecisionField = str_replace( '_', ' ', $fieldName ) . '__precision';
 					if ( array_key_exists( $datePrecisionField, $row ) ) {
@@ -153,6 +174,17 @@ class CargoQueryDisplayer {
 				} else {
 					$text = self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
 				}
+				
+				# Add drilldown link icon if not in List, is requested by user, is String/Integer/Page, etc ***
+				if (   ( !$fieldDescription->mIsList ) 
+					&& ( $fieldName != '_pageName' )
+					&& ( ( in_array( $fieldName, $drillDownFields ) ) || $drillDownAll ) 
+					&& ( in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+				) {
+					global $wgServer, $wgScriptPath;
+					$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . $value . '" class="drilldownlink">&#128269;</a>';
+				}
+				
 				if ( $text != '' ) {
 					$formattedQueryResults[$rowNum][$fieldName] = $text;
 				}
diff --git a/extension.json b/extension.json
index 2d3240a..f864bdf 100755
--- a/extension.json
+++ b/extension.json
@@ -198,7 +198,8 @@
 		},
 		"ext.cargo.datatables": {
 			"styles": [
-				"libs/DataTables/css/jquery.dataTables.css"
+				"libs/DataTables/css/jquery.dataTables.css",
+				"Cargo.css"
 			],
 			"scripts": [
 				"libs/DataTables/js/jquery.dataTables.js",
diff --git a/formats/CargoDynamicTableFormat.php b/formats/CargoDynamicTableFormat.php
index 8d9e73f..05126f6 100644
--- a/formats/CargoDynamicTableFormat.php
+++ b/formats/CargoDynamicTableFormat.php
@@ -24,7 +24,6 @@ class CargoDynamicTableFormat extends CargoDisplayFormat {
 	 */
 	function display( $valuesTable, $formattedValuesTable, $fieldDescriptions, $displayParams ) {
 		$this->mOutput->addModules( 'ext.cargo.datatables' );
-
 		// Special handlng for ordering.
 		$dataOrderString = null;
 		if ( array_key_exists( 'order by', $displayParams ) ) {
diff --git a/parserfunctions/CargoQuery.php b/parserfunctions/CargoQuery.php
index 68556df..d6e94a5 100644
--- a/parserfunctions/CargoQuery.php
+++ b/parserfunctions/CargoQuery.php
@@ -38,6 +38,9 @@ class CargoQuery {
 				if ( $param == 'no html' ) {
 					$noHTML = true;
 				}
+				if ( $param == 'add drilldown links') {
+					$displayParams['add all drilldown links'] = true;
+				}
 				continue;
 			}
 			if ( count( $parts ) > 2 ) {

Great! The code looks good now.

I've been thinking about this icon issue... and now I'm thinking that a magnifying glass might not be the best image to use anyway. It tends to have a very specific meaning, of a text search, both in web interfaces in general and in MediaWiki specifically. Maybe another image would be less misleading? Unfortunately there's no commonly-accepted "drill-down" icon, but maybe we could have some image that conveys drilling down, or filtering. Something like this (but simpler) might work:

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqEdmqlFuyy2U9pkKLM6J43rLs3UxsH90QkxzqrSNmHG8RLqoj6A

...or something that suggests a literal filter, like this:

https://d30y9cdsu7xlg0.cloudfront.net/png/1131515-200.png

What do you think? Am I overthinking this whole thing?

Yesterday I said...

Also it now sets $drillDownAll when someone uses either |add drilldown links or (probably mistakenly) |add drilldown links= (with an equals). Before, in the latter case none of the fields would have the magnifying glass.

... but now I think if someone uses the = sign with nothing on the right he probably does want none of the fields to have drilldown links (like the default= setting). What do you think?

The magnifying glass icon: I see what you mean but the context here is different as there is no opportunity to enter text to search on.

I'm not too keen on either of the two images in the links. I don't think what is happening here is really a "filter" or "drilldown" - it is potentially increasing the set of results from those which are originally seen - it's only when you get to the Special:Drilldown page that the filtering/drilldown really starts.

As you say, there is no instantly-recognisable icon for what we need. Most places seem not to use an icon but instead use text - e.g. "Filter by" (John Lewis) or "Show results for"/"Refine by" (Amazon). Incidentally I prefer this "filters on the left, results on the right" format to the current Special:Drilldown format.

I'll have a think about it but my gut feeling is that the magnifying glass is the best icon.

If we were to look for another one it might be good to have a unicode character rather then an image.

You may be right about this. Having a "filter" image would be misleading in its own way, since it's not the current set of results that would get filtered on.

I did previously look into using a Unicode character for this. I couldn't find any great matches for the concept of "filtering", but I did find these, which may be options: ❉ ⟱

What do you think?

The ⟱ didn't show up on the iPhone (email or Phabricator website) so there must be something funny about it.

The ❉ looks nice but would require explanation.

I think the 🔍 is the best so far. When I saw the magnifying glass on the Miga demo website it was clear what it meant. Clear enough to think "if I click on that I'll find out more" and then from using it once the exact functionality was clear.

Alright, I think you're right about the magnifying glass.

I'm still not convinced that going with the Unicode character is the best option - some of its implementations are pretty iffy - but it's certainly the easiest option. Let's try it and see how it goes.

I realized I never responded to your question about "add drilldown link=". It probably doesn't matter much either way, but I think you're right that not displaying any drilldown links makes a little more sense for that case...

Brilliant, thanks. One final change to fix the add drilldown link= thing:

diff --git a/Cargo.css b/Cargo.css
index 5ccbd81..07562aa 100644
--- a/Cargo.css
+++ b/Cargo.css
@@ -25,3 +25,8 @@ span.searchresult {
 span.searchmatch {
 	font-weight: bold;
 }
+
+a.drilldownlink:hover {
+	color: transparent;
+	text-shadow: 0 0 0 black;
+}
\ No newline at end of file
diff --git a/CargoQueryDisplayer.php b/CargoQueryDisplayer.php
index f37bc7c..10e4595 100644
--- a/CargoQueryDisplayer.php
+++ b/CargoQueryDisplayer.php
@@ -86,6 +86,14 @@ class CargoQueryDisplayer {
 	public function getFormattedQueryResults( $queryResults ) {
 		// The assignment will do a copy.
 		$formattedQueryResults = $queryResults;
+
+		if ( array_key_exists( 'add drilldown links', $this->mDisplayParams ) ) {
+			$drillDownFields = explode (',', $this->mDisplayParams['add drilldown links']);
+			$drillDownFields = array_map('trim', $drillDownFields); // Remove any spaces
+		} else if ( array_key_exists( 'add all drilldown links', $this->mDisplayParams ) ) {
+			$drillDownAll = true;
+		}
+
 		foreach ( $queryResults as $rowNum => $row ) {
 			foreach ( $row as $fieldName => $value ) {
 				if ( trim( $value ) == '' ) {
@@ -122,8 +130,16 @@ class CargoQueryDisplayer {
 							// list parsing worked.
 							$text .= " &middot; ";
 						}
+						
 						$text .= self::formatFieldValue( $fieldValue, $fieldType, $fieldDescription, $this->mParser );
-					}
+						# Add drilldown link icon to List items if requested by user & is String/Integer/Page ***
+						if (   ( ( in_array( $fieldName, $drillDownFields ) ) || $drillDownAll )
+							&& ( in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+						) {
+							global $wgServer, $wgScriptPath;
+							$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . trim($fieldValue) . '" class="drilldownlink">&#128269;</a>';
+						} 
+					}	
 				} elseif ( $fieldType == 'Date' || $fieldType == 'Datetime' ) {
 					$datePrecisionField = str_replace( '_', ' ', $fieldName ) . '__precision';
 					if ( array_key_exists( $datePrecisionField, $row ) ) {
@@ -153,6 +169,17 @@ class CargoQueryDisplayer {
 				} else {
 					$text = self::formatFieldValue( $value, $fieldType, $fieldDescription, $this->mParser );
 				}
+				
+				# Add drilldown link icon if not in List, is requested by user, is String/Integer/Page, etc ***
+				if (   ( !$fieldDescription->mIsList ) 
+					&& ( $fieldName != '_pageName' )
+					&& ( ( in_array( $fieldName, $drillDownFields ) ) || $drillDownAll ) 
+					&& ( in_array( $fieldType, array('String', 'Integer', 'Page') ) ) 
+				) {
+					global $wgServer, $wgScriptPath;
+					$text .= '<a href="' . $wgServer . $wgScriptPath . '/index.php?title=Special:Drilldown/' . $tableName . '&' . $fieldName . '=' . $value . '" class="drilldownlink">&#128269;</a>';
+				}
+				
 				if ( $text != '' ) {
 					$formattedQueryResults[$rowNum][$fieldName] = $text;
 				}
diff --git a/extension.json b/extension.json
index 2d3240a..f864bdf 100755
--- a/extension.json
+++ b/extension.json
@@ -198,7 +198,8 @@
 		},
 		"ext.cargo.datatables": {
 			"styles": [
-				"libs/DataTables/css/jquery.dataTables.css"
+				"libs/DataTables/css/jquery.dataTables.css",
+				"Cargo.css"
 			],
 			"scripts": [
 				"libs/DataTables/js/jquery.dataTables.js",
diff --git a/formats/CargoDynamicTableFormat.php b/formats/CargoDynamicTableFormat.php
index 8d9e73f..05126f6 100644
--- a/formats/CargoDynamicTableFormat.php
+++ b/formats/CargoDynamicTableFormat.php
@@ -24,7 +24,6 @@ class CargoDynamicTableFormat extends CargoDisplayFormat {
 	 */
 	function display( $valuesTable, $formattedValuesTable, $fieldDescriptions, $displayParams ) {
 		$this->mOutput->addModules( 'ext.cargo.datatables' );
-
 		// Special handlng for ordering.
 		$dataOrderString = null;
 		if ( array_key_exists( 'order by', $displayParams ) ) {
diff --git a/parserfunctions/CargoQuery.php b/parserfunctions/CargoQuery.php
index 68556df..d6e94a5 100644
--- a/parserfunctions/CargoQuery.php
+++ b/parserfunctions/CargoQuery.php
@@ -38,6 +38,9 @@ class CargoQuery {
 				if ( $param == 'no html' ) {
 					$noHTML = true;
 				}
+				if ( $param == 'add drilldown links') {
+					$displayParams['add all drilldown links'] = true;
+				}
 				continue;
 			}
 			if ( count( $parts ) > 2 ) {

The good news: everything works well now!

The bad news: I'm still thinking about the magnifying glass image. Have you looked at it with Chrome on Windows (a very popular combination, of course)? When those magnifying glasses are spread out across the whole page, it's really distracting, I think - a lot of bright blue/turquoise spots all over the page, plus they sort of look to me more like ping pong rackets than magnifying glasses.

I'm also not a big fan of the images turning all black on hover - though I know there's only a very limited set of things you can do with CSS.

What do you think about switching to a real image? I can take care of creating the image(s) - I just don't know how strongly you feel about using Unicode.

I use Chrome on Windows and don't mind it! Though I concede it doesn't look as classy as on most of the other browsers...

Either an image or the unicode character would be fine by me.

At the minute I can replicate the "add drilldown links" Special:Drilldown parameter in normal wiki pages (the #cargo_store pages - using #arraymap) so as long as I can continue to do that I'm happy.

What does that mean? You have some custom wikitext that displays the magnifying glass character and puts a link around it?

Yes, and annoyingly in answering your question I worked out how to use it within a Cargo query too, obviating the need to patch the extension at all... however, I do think it's a good feature, and having a parameter to control it would be easier.

I can put the wikitext here if you think it would be helpful.

I've not perfected it, but here it is, in Template:Add drilldown links.

{{#arraymap:{{{values|}}}|,|@@|@@<span class="plainlinks">[http://www.example.com/Special:Drilldown/{{{table|}}}?{{{field|}}}={{urlencode:@@|WIKI}} &#128269;]<span>|&#32;&middot;&#32;}}

You can use it in the template page of a Cargo query which has the "template" display format (which is what I belatedly realised today).

{{add drilldown links|table=<table name>|field=<field name>|values={{{<field name>|}}} }}

I still hope you will add the feature to Cargo itself.

... obviating the need to patch the extension at all ...

I take this back. It's easy to replicate the standard "table" output using a template, or other simple ones like the lists, but not the more complicated outputs like "dynamic table"...

Aklapper added a subscriber: Yaron_Koren.

This task has been assigned to the same task owner for more than two years. Resetting task assignee due to inactivity, to decrease task cookie-licking and to get a slightly more realistic overview of plans. Please feel free to assign this task to yourself again if you still realistically work or plan to work on this task - it would be welcome!

For tips how to manage individual work in Phabricator (noisy notifications, lists of task, etc.), see https://phabricator.wikimedia.org/T228575#6237124 for available options.
(For the records, two emails were sent to assignee addresses before resetting assignees. See T228575 for more info and for potential feedback. Thanks!)