Version Filters in HTML5 Output (persisting display instead of toggling)

In the previous post, the sample included a JavaScript which toggled the display attribute of elements between none and block depending on the value of a select element and the MadCap conditions applied to the elements.

But what if the display attribute wasn’t set to block in the first place? This second sample project includes a variation of the previous script which uses a custom data-* attribute to persist the original value of the display elements toggled. Instead of toggling between block and none, the original display attribute value is stored in a custom data* attribute and applied to the display element when the element is made visible again.

Section in W3C Working Draft: Embedding custom non-visible data with the data-* attributes

Why is this better? Not all elements start with a value of block for the display attribute and the default is inline anyhow. As an example, many menus implemented with CSS use a display value of inline to place the menus next to each other instead of underneath the previous. If you don’t care about that sort of thing, the original sample is sufficient. In other words if your granularity for tagging content by version doesn’t extend to elements which use display values of inline or something other than block, you can just toggle between block and none as the values for the display attribute.

Why is this controversial? The controversy surrounds the separation of markup and presentation. It also surrounds the idea of semantic misrepresentation. And the specification at one point indicated as much. Here are some links about that:

HTML Doctor: HTML5 Custom Data Attributes (data-*)

danwebb.net: Put that data-* attribute away, son…You might hurt someone

These are all valid concerns. Add to that, there is another way to indicate visibility. But given the situation of acting on markup in a help system after it has been built, isn’t this worth it? It definitely works. You can have filtering before publishing and in the output itself.

But it wouldn’t hurt to run the filtered content through a screen reader to see how the custom attribute and the filtering technique influences accessibility. My instinct is that it wouldn’t have a negative impact. But that is a subject for another post. This is an ongoing exploration.

sample project (version filter) 2

Version Filters in HTML5 Output

Keep the condition tags but skip the target settings.

Quick unpaid promotion! Attend MadWorld for my session and many others. Meet and learn from top technical communicators.

sample project

filter-in-flare-html5-topic

You can apply conditions to your Flare content and use those conditions to create a version filter in your Flare HTML5 output. The main ingredients are a select element and a little JavaScript. Here’s how.

We’ll start with a fresh project based on the Empty template which comes with Flare.

flare-with-empty-project

To keep it simple, we’ll use the Default condition tag set. But one of the nice things about having condition tag sets is there can be more than one. Since we aren’t going to touch the settings for these tags in the target, this is a situation when a separate set would make sense.

default-conditions

We can change the conditions to represent versions of a product. Periods are not allowed in the Condition Tag field. If you use periods or full stops (.) in version numbers you will have to find a different character for the tag. But you can still use the period in the text of the drop-down we will create in the topic.

new-conditions

Now we can create some content to which to apply the tags.

topic-no-conditions-or-filter

And apply the tags.

adding-condition-to-paragraph

Here is the topic in the XML Editor with the conditions applied:

topic-with-conditions

Now let’s look at those tags in the Text Editor.

topic-with-conditions-in-text-editor

Here is the first tagged paragraph. In the XML for the topic, the MadCap:conditions attribute holds the conditions. The condition is appended to the condition tag set name and a period symbol:

When there is more than one, the conditions are separated by commas.

File that in your memory. Now let’s add the UI for the filter. We can create a snippet to hold the filter for topic reuse. The snippet will use a select element, the element’s children, and some attributes. Here is the snippet in the Text Editor.

snippet-for-filter

There is an id attribute on the select element so the JavaScript can find the filter. The select element fires a JavaScript every time the the selection is changed. Here is the snippet in the topic:

snippet-in-topic

We can’t see the UI for the snippet from the Text Editor or the XML Editor. But we can see a preview when we add the snippet.

insert-snippet-for-filter

The JavaScript will look at the selected option and show or hide tagged elements based on the selection. Here is the JavaScript in Flare’s Text Editor:

show-hide-javascript

There are two functions. The first, getElementsWithAttribute, is used by the other function, showHideVersion, to get all of the elements in the topic with the data-mc-conditions attribute. Remember MadCap:conditions in the topic XML? That becomes data-mc-conditions in the HTML5 output topics.

The showHideVersion function looks for the select element and gets the selected option. Then it loops through all of the elements with data-mc-conditions and shows or hides the elements based on whether the elements include the selected condition.

The last line of the script ensures the script runs when the page initially loads.

We can reference the JavaScript in the master page. There is no default master page in the Empty template. We can base the new master page on the MasterPage.flmsp Factory Template. The script will go after the body element in the master page so we will add it through the Text Editor. Note the relative path to the file.

script-reference-in-master-page

Let’s not forget to add the master page to the target.

adding-master-page-to-target

At this point we are ready to build. Here again is how the output looks. You can select a version and only content tagged with that version appears.

filter-in-flare-html5-topic-drop-down-not-open

 

filter-in-flare-html5-topic

Now you can filter on a single condition in a topic from the published output. In this example and sample, the content must be tagged to appear. But you don’t have to limit yourself to that behavior with your JavaScript. What kind of filter behavior would you expect to see in a version filter? Let me know in the comments.

sample project

Update: There is a follow-up post and sample which persists the original display value instead of toggling between none and block.

Combining Generated and Flare-managed Content

One way to combine generated content with Flare-managed content is to use snippets. Here is a generic structure:

Generated topics each contain:

Generated snippet – periodically refreshed

Generated snippet – updated with Flare editors

Consider a simple case where the generated content comes from a CSV file. For this example, the CSV is analogous to a table with two columns. The first column is a name of some reference subject and the second column is the description.

Flowers,Flowers are structures which are part of some plants…
Unicorns,Unicorns are figments which occur in some imaginations…
Sunbeams,Sunbeams bathe the earth in radiation when another object does not block the sun…
Rainbows,Rainbows lead to the other side…

The term CSV is thrown around loosely. For this example, the CSV has only two entries per line. The entries are delimited by one comma. To provide a simple example, the content itself does not have commas. Here is one way to read a CSV with Visual Basic:

How to: Read From Comma-Delimited Text Files in Visual Basic from MSDN

This example dispenses with the exception handling for reading clarity. But bad files should be expected and handled. There is a decent discussion at the bottom of the article about other considerations.

To create the TOC, topics, and snippets, Linq to XML is used. This has been discussed in previous blog entries. The procedures in the sample are fairly targeted. Generalized, overloaded procedures would be better. But reading clarity, the scopes of the procedures are narrow.

This example also assumes a specific project structure and existing folders. A working utility should check for folders and add folders if necessary. The flexibility to specify sub folders is also a plus. And of course we don’t want to limit ourselves to CSV. But rather than cloud the example, here is the code without all of that:

Here are the generated files in the folders:

generated-flare-files

 

Here is the TOC:

Here is a snippet:

And here is a topic:

 

 

 

Sorting TOCs in an Output with JavaScript

Having discussed sorting TOCs in a project before a build, let’s look at sorting a TOC in an HTML5 target output with JavaScript.

I’m using Google Chrome to test the JavaScript on the online help files for MadCap Flare version 8. Please note that I am using Flare online help because it is a recognizable, high quality HTML5 output. I don’t work for MadCap Software or have any involvement with that help file.

In the screen shot, notice the unordered list for the TOC is being inspected with the developer tools in Chrome. To bring up these tools, right-click somewhere on a page displayed in Chrome and select Inspect element.

TOC tree in Google Chrome

TOC tree in Google Chrome

The unordered list has a class value of “tree” (ul.tree). The children are list items (li) and the class varies depending on the state of the node and the position in the tree. For example, the skin changes the class value when the node is selected. In the next image, the Welcome topic is selected. Notice the value is:

tree-node tree-node-leaf tree-node-selected

TOC tree node in Google Chrome

TOC tree node in Google Chrome

For this post, only the top nodes will be sorted. To test getting those, JavaScript can be executed from the Console which is the option on the far right of the developer tools. This will retrieve the child nodes of the first ul.tree element on the page:

In the next screen shot, this has been executed.

child nodes of TOC tree retrieved with JavaScript

Child nodes of TOC tree retrieved with JavaScript

The result can be assigned to an array and sorted. Once sorted, the content of the list items can be replaced with the sorted content. But the class for the li elements must also be changed. Not only does that class change dynamically when you select the entry but the class varies depending on placement in the tree. To be safe, the class name should also convey.

Rather than multidimensional arrays, JavaScript allows for arrays of objects or arrays of arrays. To keep the class value and the inner HTML together, an array of objects can be used. The sort will be performed on the text of the label. The label text appears as the third descendant of the list item. But there is no other text so it can be taken from the list item itself. Here is a good discussion on Stack Overflow: http://stackoverflow.com/questions/2808926/javascript-multidimensional-arrays.

For basics about JavaScript arrays: w3schools.com JavaScript Array Object tutorial

Since the sort is to be performed on an array of objects, a sort function must be specified. This is a good explanation: http://www.javascriptkit.com/javatutors/arraysort2.shtml. In addition to placing the inner HTML and the class for the node in an array, the label text from the inner HTML is pulled as as a separate piece. The sort is based on the label text. This makes it easier to identify. Otherwise the script would have to drill in to the inner HTML for each node during the sort.

Here is the the code:

To test, you can open an HTML5 output and execute the copied code from the developer tools in a browser. Here is the TOC before:

TOC before sorting with a JavaScript

TOC before sorting with a JavaScript

And here is the TOC in alphabetical order after executing the JavaScript:

TOC after sorting with a JavaScript

TOC after sorting with a JavaScript

What next?

You can add this script to a function and configure a toolbar button to execute it when clicked. MadCap Software has recently posted instructions about how to do that:

Adding Custom Buttons to HTML5 (and WebHelp) Outputs

It would also be nice to script the return to the original order or to script flattening or sorting at each level as was described in the previous post. But I’ll end this post with an appeal for comments about what kinds of sorting would be useful in Flare HTML5 outputs. The spam system on this blog has been changed. If you don’t see you comment published, please email info@tregner.com so I can track your comment down.

Sorting TOCs in a Project

TOC sorting is probably only useful for reference documentation. But please post comments with any use-cases for TOC sorting you can think of. My desire to sort a TOC is threefold. I want to be able to:

  • Flatten a TOC with levels down to one level
  • Sort a flattened TOC in ascending order by the Title attribute of a TocEntry
  • Sort a TOC with a multi-level hierarchy in ascending order by the Title attribute of a TocEntry and respect the level structure

The UI is left to you.

Create a Visual Basic Windows Forms project and build a form with items which correspond to the procedures in the sample. An open file dialog is necessary to select the TOC. With the dialogs, limit the file type to *.fltoc. The TOC structure is rendered in a tree view. I placed it prominently in the center of the form. I used buttons for the options. But radio buttons would make more sense.

A preview of the options display in the tree view when a button is clicked. But nothing is saved until the save dialog is shown. You can use that to overwrite or to create a new TOC. If I see any use-cases, I’ll post a full sample project in a later post.

Web Services Can Be Used in Dynamic and Static Content

Dynamic content and web services complement each other. Flare topics generated from HTML5 targets can use JavaScript to call a web service to show dynamic content based on what is returned from the web service.

An advantage of dynamic content is it is always up-to-date. Disadvantages include slower loading times due to extra scripting and inaccessible content when the web service server is down or busy.

A dynamic approach works well if the web service can be called from the open Internet, preferably without credentials. But what if a web service is behind a firewall or requires a name and password?

Well there are advantages to static content. Static content loads faster. There is also a single location. If the single location is accessible, the content is accessible. There are fewer dependencies.

A previous post described the creation of Flare topics and TOCs using a VB.NET client and Linq to XML. All that is left is to make the web service call in the client and to use the results in the XML programming interface.

This comes in handy when the primary access point to content in a silo is a web service. A similar approach can be taken when the content silo is a database. Just replace web service call with query.

There is really no great leap if you are already creating topics with a client that supports an XML programming interface and web service calls. What kind of web service returned information would you like to see appear in Flare generated content? What platform would you use?

 

Flare to MediaWiki to Flare (part 6, of wiki template articles and snippets)

A mapping effort chronicled in a blog is less than exciting to read. So let’s switch gears and lay some groundwork for the parser. We will use a Wikipedia article as the first test and as a guide for what parts of the markup to tackle firstly. Since wikis are moving targets, we will work with the markup at a specific point in time.

This discussion is going to become complicated very fast. It may seem overly complicated. But rest assured that the parser will be doing the work both ways and the complex structures created in Flare to solve the issues we encounter aren’t much more complex than the wiki markup itself.

The article is http://en.wikipedia.org/wiki/Data_mapping. We can see the source for the article by switching to the Edit tab at http://en.wikipedia.org/w/index.php?title=Data_mapping&action=edit. For my use, I copied the markup to a text file. But remember, we have already established that the markup can be retrieved with an API.

The markup begins with this line followed by an empty line:

{{Data transformation}}

The double curly braces indicate a template. Templates are described in http://en.wikipedia.org/wiki/Help:Template. The term, template, surprises me because templates are pages which can be used in other pages. Snippet or boilerplate would have made more sense to me. But with MediaWiki, templates are for content reuse.

How do we track down that template? Templates can be maintained in the Template namespace. Let’s see if that works. Look here: http://en.wikipedia.org/wiki/Template:Data_transformation.

The template is there. As of writing, it establishes a box in the upper right-hand corner of the article which provides links to data transformation topics. So we will need to pull that article over during import. At the moment, I’m leaning toward storing template articles as snippets and using a naming convention for the snippet files which indicates the file’s status as a Flare version of a wiki template.

Snippets help: http://webhelp.madcapsoftware.com/flare8/Content/Snippets/About_Snippets.htm

This popped up in a Google search: http://www.contentinsomnia.net/reusing-content-on-wikis-and-blogs/. I thought I would share the link since it confirms someone else equates Flare snippets with MediaWiki templates.

For the Flare markup, we can use this:

<MadCap:snippetBlock src=”../Snippets/Template_Data_transformation.flsnp” />

We could use a regular expression for this since the object is replace {{ with:

<MadCap:snippetBlock src=”../Snippets/Template_

And }} with:

.flsnp” />

We should also retain the line ending. This replacement is our rule A for now. Rule B is to record the template name for future export and import. By the way, there is an export option to include templates with http://www.mediawiki.org/wiki/Special:Export.

The third line in the markup is:

{{inline|date=June 2010}}

There are more curly braces. But the contents of the braces seem more complex. The first part indicates another template: http://en.wikipedia.org/wiki/Template:Inline. But the second part indicates to display a date. The template article includes instructions about how to use the Inline template. The template is an appeal to improve the article because the citations are insufficient. The date portion is a parameter: http://www.mediawiki.org/wiki/Help:Templates#Parameters. This must be why it is called a template and not a snippet. How are we going to handle parameters in a snippet? Conditions, variables, something else?

A condition applied to the markup for the snippet block is an attribute for the snippet block element. This makes a condition attractive. But imagine how many conditions we would introduce as we imported more templates with more parameters. Besides, the condition doesn’t influence the appearance of the content until a target is generated. What to include or exclude is set on targets. Similarly, variable values are set on targets. Conditions and variables don’t give us what we want.

What about styles?

That feels closer. But unfortunately, which style to use is established in the markup with a class attribute. An element only gets one of those. If class is used, every parameter value would have to be conveyed through that one attribute. We want class for styles and we don’t want hundreds of MediaWiki template parameter mapped styles.

We could also consider grouping the snippet block in a div element with other elements to represent the parameters. But unfortunately some parameters influence the text of the MediaWiki template article. With the Inline template, you can replace the word article with another word indicated in a parameter. How can we achieve parity with the wiki if this is the case? This is an important decision point. We should convey the parameters to Flare so we can make the round trip. But how concerned are we about the way the parameters are manifested in Flare? In this case, we are probably not very concerned. But the meaning of the template can be changed drastically with a parameter. We must address it.

We can address it with a new attribute. But if we do that, we will run into problems conveying the parameters if the snippet is used elsewhere with different parameters. We will convey the parameters within the name of the snippet itself.

<MadCap:snippetBlock src=”../Snippets/Template_Inline|date=June 2010.flsnp”  />

I’m not sure about the pipe character in the markup, I’ll have to check. Secondly, we can place the parameter information in the snippet so as to display in Flare as intended. We can use another snippet within the template snippet for the parameter.

Snippet propagation.

It can be named according to the template and the parameter and contain the appropriate value. When the round trip is completed, the snippet block for the parameter will be translated to the markup in the template which declares the parameter. But the parameter snippet content will not be conveyed. That content is just for Flare. We can see the markup for the Inline template here: http://en.wikipedia.org/w/index.php?title=Template:No_footnotes&action=edit.

Only one version of the snippet contents will be parsed back into wiki markup when the round trip is completed. But the parameter values will still be parsed from the template snippet names. But what if we want to edit a snippet for the template and have the changes propagate to other versions of the template? You guessed it.

More snippet propagation!

All of the content in between snippets for parameters can also be snippets. This way someone can drill down and make changes in Flare which will be reflected in each parameter set version for the snippet for the wiki template article.

The ground rules and guidelines are:

  1. Don’t rename these snippets. Renaming will change the parameter values returned to the wiki on completion of the round trip.
  2. Only create new snippets as needed. Name the template snippets and parameter snippets according to the template article name and parameter values. Follow the convention strictly. The new parameters will convey to the wiki.
  3. Consider that template changes in wikis are a big deal. Don’t take them lightly.

Wikis use bots and people to maintain things like parameters in transclusions. We are attempting to maintain a similar structure in Flare without the advantage of bots. It may be a good idea to create a validation algorithm to check these projects periodically or even constantly just to ensure the Flare side is maintained such that the wiki is respected.

And on to line 4 of the wiki markup…

 

 

 

Flare to MediaWiki to Flare (part 5, Still Mapping)

Initially I wanted to distinguish between parsing and mapping. But as I study MediaWiki markup, I am increasingly convinced the best approach is to map the markups and create a parsing algorithm based on that. I took a break from this series for some other posts. This is a late evening endeavor. So the pace is slow. But I put some time into the map. In the course of mapping, I’ve realized the structure of the MediaWiki markup is varied. My feeling is that the markup is a product of what works to promote wiki contribution and that it is an evolving structure.

I’m working through this Wikipedia Help article: Help:Wiki markup and making notes in a spreadsheet as I go. Developing the map will take at least a couple of iterations. At the moment, I’m through about one third of the help article. Some of the Flare tags in the table do not show the unique class which will be used. This is a pasting issue.

MediaWiki Markup Flare Topic XML / XHTML
Start End Start Tag Nested Start or End Tag Nested Start or End Tag Nested Start or End Tag Nested Start or End Tag End
== == <h2> </h2>
=== === <h3> </h3>
==== ==== <h4> </h4>
===== ===== <h5> </h5>
====== ====== <h6> </h6>
; : <div > <div> </div> <div > </div> </div>
—- <hr />
__TOC__ Mini TOC Proxy
__NOTOC__ <div />
<br /> <br />
<br> <br />
single newline <div />
empty line </p> <p>
: <div />
<blockquote> </blockquote>
<div style=”width:auto; margin-left:auto; margin-right:auto;”> </div> <div style=”width:auto; margin-left:auto; margin-right:auto;”> </div>
* <ul> <li> <p> </p> </li>
*: <p> </p> </li>
</ul>
# <ol> <li> <p> </p> </li>
#: <p> </p> </li>
newline </ol>
<poem> </poem> <pre> </pre>
<i> </i>
”’ ”’ <b> </b>
”” ”” <b> <i> </i> </b>
{{Smallcaps|small caps}}
<code> </code> <code> </code>
<syntaxhighlight> </syntaxhighlight> <syntaxhighlight> </syntaxhighlight>
<small> </small> <small> </small>
<big> </big> <big> </big>
&nbsp; &nbsp;
{{pad|4em}} <div> </div>
<tt> </tt>
&Agrave;
&Aacute; &Acirc; &Atilde; &Auml; &Aring; &AElig;
&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml;
&Igrave; &Iacute; &Icirc; &Iuml; &Ntilde;
&Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &Oslash;
&Ugrave; &Uacute; &Ucirc; &Uuml; &szlig;
&agrave; &aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil;
&egrave; &eacute; &ecirc; &euml;
&igrave; &iacute; &icirc; &iuml; &ntilde;
&ograve; &oacute; &ocirc; &otilde; &ouml; &oslash; &oelig;
&ugrave; &uacute; &ucirc; &uuml; &yuml;
&iquest; &iexcl; &sect; &para;
&dagger; &Dagger; &bull; &ndash; &mdash;
&lsaquo; &rsaquo; &laquo; &raquo;
&lsquo; &rsquo; &ldquo; &rdquo;
&apos; &quot;
<pre> </pre> <pre> </pre>
<nowiki> <nowiki>
&trade; &copy; &reg; &cent; &euro; &yen;
&pound; &curren;

MadCap Flare + Python + Google Calendar = Topic-based Training Session Scheduler?

There is no code at the end of this post. I’m just brainstorming. What triggered this is a blog post at Google: Python Client Library for Google APIs is out of Beta. Here are some other links for the library: Google APIs Client Library for Python & Write your First App: Prerequisites (Google Calendar API v3).

The idea is to create a Flare project with topics which contain training material for short, perhaps one hour, training sessions. These topics would be organized in sequential order in a TOC or browse sequence. A script would parse the output and create Google Calendar events based on some schedule parameters and the output TOC or browse sequence. The events would have links to the topics. So a student or instructor could access training content through a calendar interface.

Scheduler parameters would be maintained in an accessible place. Maybe a table in a topic or separate data file would work. Parameters would be choices such as:

  • Include weekends
  • Start date
  • Session length
  • Exclude these days
  • Exclude these hours
  • And so forth…

Python comes into play with TOC parsing and making calls to Google calendar with the client library. The Python script would parse the TOC with something like minidom. While looping through each TocEntry, the script would use the client library from Google to create events on a Google Calendar.

Since this post speculates on using Python, it may be helpful to point out that there is a post at MadCap’s MadBlog about a Python script to retrieve MindTouch content: Extracting MindTouch Wiki Content.

Other related links:

A Simple Flare HTML5 Output ‘Re-skin’ with PHP

Although I am not a huge fan of PHP, there are some things it does well. One of those is content reuse on web pages. Having previously built a (no longer extant) website which used little more of PHP than the include function, I admit the choice saved a lot of time and code for little cost. A little PHP enabled content reuse without a CMS.

This post describes a simple “re-skin” of an existing HTML5 output. The idea is to use the topic files and the Toc.xml file to recreate a navigation and topic display. This will be a simple example without many bells and whistles and no CSS. But you can build on it if you find it useful. This example does not goes as far as using the Title attribute for the text of the links or indenting the links based on topic level. This is just a proof-of-concept.

To create the PHP “skin,” you can install PHP on the web server hosting the skin, place the Flare HTML5 output on the web server, and place the code sample in a file called Index.php at the root of the Flare HTML output folder. You can read more about how PHP works at:

http://www.php.net/

In the PHP file, HTML5 syntax will be used for the HTML portions and the scripting will be PHP tags. The “skin” will have a list of linked topics based on Toc.xml in the Data folder of the HTML5 output and a view of the selected topic which appears at the top when you click a link.

A previous post described how to return all of the Link attributes in the TocEntry elements in the Toc.xml file in an HTML5 output with XPATH. That was a building block post. Now we are going to use that block to build the list of linked topics.

In Flare HTML5 output, the URLs for topic navigation appear as a pound sign and topic file name after the URL for the main help file: http://localhost/flareoutput/default.htm#topicname.htm

With this PHP “skin,” the URL will look like this: http://localhost/flareoutput/Index.php?topic=topicname.htm

The first PHP script checks if there is a topic qualifier in the URL.  If there is a topic qualifier, the script removes the / from the beginning. This is because Toc.xml stores the paths that way and PHP expects no / at the beginning of relative URLs in this case. It loads the topic into an iframe at the top of the page. There is also a check to see if the qualifier is there: isset.

The second script uses the XPATH expression to get all of the Link values for TocEntry elements in Toc.xml. It displays each as a hyperlink with a format which uses Index.php and the qualifier with the topic name.

You can install PHP on your web server, copy a Flare HTML5 output to it, place an Index.php file containing the sample below at the root of the output, an open the URL to Index.php to see this work.

Index.php: