User:Dennis Groenewegen/Incrementing in subobjects

From semantic-mediawiki.org
< Dennis Groenewegen
Dennis GroenewegenUser:Dennis Groenewegen/Incrementing in subobjects

The problem

Working with subobjects? It may be common for you to place multiple subobjects on a page, typically using a template to set each subobject as well as to present data on the page.

What if you need to record the exact order in which they appear on the page. For instance, you may need to run a query that returns them in that exact same order, or you want to query for the previous/next subobject on the page. To achieve this, each subobject would need a property to store a key that can be used for the sorting condition (sort=) of the query.

SMW itself does not currently provide a built-in solution for you, so how should we go about doing this?

In the following examples, we'll be using a property with data type Number, called "Property:Has sorting number".

Approach 1: increment variable with global scope

Method 1a: using the Variables extension

Using the Variables extension, you can define a variable and use the previous value to increment the number each time a new variable is defined and used.

In the 'multiple-instance' template that sets your subobject, add something like:

{{#subobject:
|Has sort number={{#vardefineecho:@sort number|{{#expr: {{#var:@sort number|0}} + 1 }} }}
|...
}}

Note, however, that the future of the Variables extension is uncertain. MediaWiki's Parsoid is undergoing substantial changes as it is moving towards 'parallelized parsing'. What this means is that variables as defined by the extension may no longer retain global scope. Without the ability to access the previous variable, autoincrementing is impossible.

Method 1b: similar approaches using other extensions

There are extensions that offer parser functions with similar autoincrementing functionality:

However, said changes to Parsoid are likely to affect these extensions, too, for the same reasons.

Approach 2: use JavaScript to generate hard-coded indexes

The idea here is that the index numbers are generated when a user interacts with a form and get saved to the page when the form is submitted. Whenever you add or remove new instances, or change their order, all indexes are automatically re-generated.

This should be possible in both Page Forms (multiple-instance) and FlexForm (wsinstance). Each instance in the form comes with a field, preferably a hidden field, that gets updated automatically through a JavaScript.

The reliance of this method on browser interaction has its obvious downsides. It is not a friendly solution if you need to migrate hundreds of pages to using this method.

@todo : add example

Approach 3: let a parser function transfer the data to a new template (forthcoming)

The first two approaches assume that for each instance, you have a template that handles the subobject directly, but there is an alternative, which further separates the raw data from the semantic data. It involves the following steps:

  1. Use a template to store the raw data for each instance to the page - much as before but without storing subobjects.
  2. Use a parser function that lets you cycle through each instance of a template on the page and keep a record of each number.
  3. In the process, assign data to subobjects. It is in this final step that you can increment numbers and assign the new values to each individual subobject.

Currently working on a new parser function that lets you do this. Part of a custom collection of features for a website called CODECS.

Example: the source page

{{Recipe
|Title=Banana coconut cardamom bread
|Ingredients={{Ingredient
|What=coconut oil
|How much=125g
}}{{Ingredient
|What=ripe bananas
|How many=2
}}{Ingredient
|What=medium eggs
|How many=3
}}
}}

This parser function lets you assign parameters as well as an index to a new 'target' template ("Template:Ingredient subobject" in the example below). It is through this template that you shoulf store your subobjects.

{{#cr-convert-templates:
|page={{FULLPAGENAME}}
  |slot=main
|parenttemplate=Recipe
|parenttemplateparam=Ingredients
|template=Ingredient
|targettemplate=Ingredient subobject
|data=What=>Item, How much=>Mass, How many=>Quantity
|index=Index // index name
}}

Each call to the target template would translate to this:

{{Ingredient subobject
|Index=...
|Item=...
|Mass=...
|Quantity=...
}}

Approach 4: forget about using templates. Use JSON and Lua

Again, as in approach 3, we're separating 'raw data', SMW data and presentation, but we're largely dropping our reliance on wiki templates. First, the source data are stored in a JSON page. Second, Scribunto/Lua is used to read JSON data and declare the subobjects along with their index numbers.

@todo: example