Data Sources > Template Content > JavaScript Extension
 Print This Page
Javascript extensions from Centralpoint Data sources

Data Sources > Template Content > JavaScript Extension

When you build a Data Source record with the Select Command builder, the Template Content attribute is filled in for you. This article explains what that default markup is, and what you can change.

The markup arrives in four parts, in this order: the script and style registrations, the table itself, the taxonomy search panel, and the JavaScript that starts the grid plugin. Most of what you will want to change is in that last part.

Script and style registrations

These sit above the table markup and load everything the grid needs.

<link href="/Modules/DataSource/DataTablesJS/Styles.css" rel="stylesheet"> [cp:scripting key='RegisterUnmanagedScriptInclude' url='/Integrations/JQuery/Plugins/dataTables/cp_DataSources_Extender.js' /] [cp:scripting key='RegisterUnmanagedScriptInclude' url='/Scripting/ModuleResults/Export/Scripts.js' /] [cp:scripting key='ExtTable' targetId='dataSource_TUGI' bPaginate='true' sPaginationType='two_button' bFilter='true' bSort='true' bInfo='true' bLengthChange='true' iDisplayLength='100' bJQueryUI='false' bProcessing='true' aLengthMenu='10, 25, 50, 100, 250, -1' aaSorting='0,cpsys_Aposdesccpsys_Apos' asStripeClasses='' bAutoWidth='false' sScrollY='' hasSearchableColumns='1' skippedSearchableColumns='0' /] [cp:scripting key='DataSourceExportButton' id='ExcelXml' type='ExcelXml' imagePath='/Integrations/Centralpoint/Resources/Icons/Microsoft_Excel.png' linkText='Export to Excel Xml Format' /]
  • The <link> tag registers the default styles for the UI built from the Data Source.
  • The RegisterUnmanagedScriptInclude scripts register the system JavaScript plugin files. These are what extend the DataTables.js grid with the filtering, download and export behavior described below.
  • The ExtTable script registers the DataTables.js source plugin itself.
  • The DataSourceExportButton script outputs a button that downloads the results as an XML file which opens in Microsoft Excel.
  • There is no equivalent script for the PDF export. That button is created by the extender plugin and is configured entirely through the pdf block of the JavaScript at the bottom of the Template Content.

The table

<table id="dataSource_XBMN" align="left" style="max-width: none;"> <thead> <tr> <th><input type="checkbox" class="select-all"></th> <th>StartDate</th> <th>Title</th> <th>DataId</th> <th>AutoNumber</th> </tr> </thead> <tbody> [cp:placeholders key='ItemContent' /] </tbody> </table>
  • The columns shown here are reduced for the example. Yours will reflect the relational columns of the table you selected.
  • The first column always holds the checkbox. That is what lets a visitor select rows to download the files referenced in those records, or to use the selected values for something else.
  • ItemContent is where the Item Content attribute is inserted, once per record.

The taxonomy search panel

This sits below the table and gives visitors a way to filter it by taxonomy.

<div class="cp-dtjs overlay"> <div data-filter="taxonomy"> <h2>File Types</h2> [cp:scripting key='FormRadioButtonList' id='TaxonomyList1' selectionmode='Multiple' repeatlayout='Flow' repeatColumns='4' tablename='cpsys_Taxonomy' filter='cpsys_Taxonomy.ParentTaxonomyId = cpsys_Apos8982210e-0447-47d6-9c09-4ad5014e30c6cpsys_Apos' valuefield='SystemName' textfield='Name' /] <hr> <h2>Document Types</h2> [cp:scripting key='FormRadioButtonList' id='TaxonomyList2' selectionmode='Multiple' repeatlayout='Flow' repeatColumns='4' tablename='cpsys_Taxonomy' filter='cpsys_Taxonomy.ParentTaxonomyId = cpsys_Apos10ef4b4d-f913-4447-94fd-11dc71a4b157cpsys_Apos' valuefield='SystemName' textfield='Name' /] <hr> <h2>Terms</h2> [cp:scripting key='FormRadioButtonList' id='TaxonomyList3' selectionmode='Multiple' repeatlayout='Flow' repeatColumns='4' tablename='cpsys_Taxonomy' filter='cpsys_Taxonomy.ParentTaxonomyId = cpsys_Apos39421aa9-99ad-4dfe-8931-3f95ab57b74ccpsys_Apos' valuefield='SystemName' textfield='Name' /] </div> <button type="button" class="srch-tbl">Search Table</button> </div>
  • To finish the setup, update the FormRadioButtonList scripts with taxonomy from the site whose data you are querying.
  • This requires a QueryStringTaxonomyFilter script in the SQL, through the Select Command attribute. The Select Command builder provides it by default.
  • The default gives visitors three tiers of taxonomy, filtering results by File Types, Document Types and Terms. Records matching the selected items are returned.
  • When it is set up correctly a clickable Other Filters element appears, which opens the search controls.

The plugin configuration

This sits at the very bottom of the Template Content and is where nearly all of your customization happens.

The pdf block below is shown with every property at its default value. The Select Command builder writes only hasExport; the rest are defaults the plugin supplies, listed here so the available settings and their values are visible in one place. The other blocks are written out in full by the builder.
<script type="text/javascript"> $('#dataSource_XBMN').cp_DataSourcesExtTable({ onInitComplete: function () { }, searchTermsLabel: "Search for:", taxonomy: { hasSearch: true, queryStringVariableName: "tax", modalTriggerHtml: '<strong>Other Filters:</strong> <img src="/Integrations/Centralpoint/Resources/Icons/Hierarchy.png" alt="filters">', resetButton: "Remove Filters", noneSelectedMessage: "Please select at least one taxonomy item." }, dates: { hasSearch: true, from: "From:", to: "To: ", placeholder: "mm/dd/yyyy", searchButton: "Search", resetButton: "Reset" }, pdf: { hasExport: "[cp:scripting key='HTMLOutput' html='true' roles='private' /]" === "true", buttonHtml: '<img src="/Integrations/Centralpoint/Resources/file_pdf.png" alt="Export to PDF" title="Export to PDF">', orientation: "portrait", cssClass: "", title: "", fileName: "", scope: "applied", generatedLabel: "Generated", rowsLabel: "Rows", ofTotalLabel: "of", filtersLabel: "Filters", dateRangeJoinLabel: "to" }, download: { columnIndex: 0, buttonHtml: 'Download Selected', attributes: ["FileUpload1", "FileUpload2", "FileUpload3", "FileUpload4", "FileUpload5", "Image", "Document"], fileName: "Attachments", selectedRowsControl: { hasControl: true, unfilteredButtonHtml: "View Selected Rows", filteredButtonHtml: "Clear Selected Filter" }, onChange: function (selectedIds) { }, onLoadSelectedIds: function() { return []; } } }); </script>

Top level properties

Property What it does
onInitComplete A callback that runs after the extender plugin has found the table and finished starting up.
searchTermsLabel When the taxonomy search is used, the names of the searched items are listed above the table. This changes the bolded wording in Search for: TaxonomyName1, TaxonomyName2.

Taxonomy properties

Property What it does
hasSearch Set to false and the taxonomy search does not render. If it is true and the trigger still does not appear, there are most likely no checkboxes in the taxonomy panel. The plugin will not give visitors an overlay with nothing in it.
queryStringVariableName Must match the names used in the QueryStringTaxonomyFilter script in your SQL. A base name of tax expects those names to be tax1, tax2, tax3 and so on, starting at 1 and incrementing by 1.
modalTriggerHtml The clickable HTML that opens the search overlay.
resetButton The text inside the reset button, which appears once a visitor has filtered by taxonomy.
noneSelectedMessage The message shown when a visitor searches in the overlay without selecting anything.

Date properties

Property What it does
hasSearch Set to false and the date search does not render.
from and to The label text for the two date inputs.
placeholder The placeholder shown inside each empty date input.
searchButton The text for the search button.
resetButton The text for the reset button, which appears once a visitor has run a date search.
This feature needs QueryString scripts in your SQL with name='' values of fromDate and toDate. The Select Command builder writes them for you.

PDF export properties

The PDF export button renders in the table toolbar beside the column selector and the Excel export. It produces a PDF of the rows the visitor is currently looking at: every row matching the active search, taxonomy and date filters, in the current sort order, without the columns they have hidden and without being limited to the page on screen. Checkboxes and other controls are stripped from the cells, and a column left with an empty header once its control is removed is dropped, so a checkbox column does not print as a blank one.

Above the table the export prints a band naming the report, the generation time in the visitor's own time zone, the row count against the unfiltered total, and the filters in force. It is left out where there is nothing to say, so an unfiltered export carries no filter list.

This feature is for signed-in visitors only. An anonymous visitor is refused, so a report on a public page gains nothing from turning it on. The builder handles this by hiding the button from anonymous visitors rather than offering one that fails, which is what the hasExport value is doing.

Everything on this page concerns the button the plugin provides. The handler behind it can also be posted to directly, from a Form, a custom page, or anything else that can build a table, which is covered in PDF Export Handler.

Property What it does
hasExport Whether the button renders, for signed-in visitors only. Defaults to false, so reports built before this feature do not gain a button when the site is upgraded. An existing report on an authenticated page opts in by adding pdf: { hasExport: true }. It has to be a real boolean; the string "true" will not turn it on.
buttonHtml The inner HTML of the button. The default is the standard PDF icon, in the same shape the column selector uses, so it renders as a bare icon in the toolbar.
orientation Either portrait, the default, or landscape. Anything else is treated as portrait.
scope Either applied, the default, which exports the rows matching the active search, or all, which exports every row and ignores the search box while still following the current sort order. Any other value falls back to applied and logs a warning to the browser console.
title The heading printed at the top of the PDF. When empty the page title is used, so set this on any report whose page title is not a good document heading.
fileName The downloaded file name, without the extension. When empty the title is used. Spaces and ordinary punctuation are kept.
cssClass An extra class on the export wrapper, for styling one report differently from the rest. See below.
generatedLabel
rowsLabel
ofTotalLabel
filtersLabel
dateRangeJoinLabel
The wording of the band above the table, defaulting to Generated, Rows, of, Filters and to. These exist for sites that need different language and most reports never set them.
Leave the comparison around the role-gated script. The script renders true for a signed-in visitor and nothing at all for an anonymous one, so comparing its output to "true" is what turns "nothing" into a usable false. Drop the comparison and an anonymous visitor is left with hasExport: } in the configuration, which is a JavaScript syntax error that stops the whole plugin on that page. Replacing the whole expression with a literal true is the other mistake: it shows the button to anonymous visitors, who are refused when they click it.

Styling the PDF

The PDF is rendered against the site's own stylesheet, so the table arrives looking like the table on screen. The document is wrapped in a class that exists only in the export, so a Design styles record can restyle the printed version without those rules reaching the report on screen. Edits take effect on the next export.

.cp-ds-pdf-export table { font-size: 9px; } .cp-ds-pdf-export th { background: #0a2240; color: #fff; } .cp-ds-pdf-export .cp-ds-pdf-title { font-size: 24px; } /* just one report, configured with cssClass: 'quarterly' */ .cp-ds-pdf-export.quarterly table { font-size: 8px; }
  • .cp-ds-pdf-export wraps the whole document and is the class to target for a site-wide export style.
  • .cp-ds-pdf-title is the heading, .cp-ds-pdf-stamp the band beneath it, and .cp-ds-pdf-meta-label and .cp-ds-pdf-meta-value the small labels and their values inside the band.
  • A value in cssClass is added to the wrapper rather than replacing it, so a site-wide rule keeps applying to a report that brings its own class. Write the narrower rule as .cp-ds-pdf-export.quarterly so it outranks the site-wide one.

Wide tables

A report with many columns does not produce a good PDF, and no setting changes that. Columns are squeezed to fit the page rather than cut off, so no data is ever lost. Past roughly a dozen columns of real content the result is cramped, and past twenty it is very hard to read. Landscape and hiding columns help, but neither moves that boundary far.
  • Where a visitor needs every column of a wide report, the Excel export is the right tool. It already returns every row and every column, and a wide grid is what a spreadsheet is for.
  • The PDF export is for a report somebody prints, files, or sends to a person who will read it as a document.
  • The most effective thing a visitor can do is hide the columns they do not need with the column selector before exporting, since hidden columns are left out.

Download properties

Property What it does
columnIndex The zero-based index of the column holding the row checkbox. Set it to -1 to switch the feature off on a table with no checkbox column. The default of 0 uses the first column; move the checkbox elsewhere and this has to move with it.
buttonHtml The text inside the download button.
attributes The attribute system names within each selected record that hold file paths. These are the files included in the ZIP.
fileName The name of the downloaded ZIP.
selectedRowsControl.hasControl Whether the selected-rows filter button renders. Defaults to false.
selectedRowsControl.unfilteredButtonHtml The inner HTML of that button while the table is not filtered by selected rows.
selectedRowsControl.filteredButtonHtml The inner HTML of that button while the table is filtered by selected rows.
onChange A callback that runs each time a checkbox changes. Commonly used to pass the DataIds to a hidden input. See below.
onLoadSelectedIds A callback that runs once when the plugin starts, to set the selected DataId values. This is how selections survive a postback when the plugin is used inside a form and a visitor is held up by a validator. See below.
The checkbox value has to be the DataId. The markup in that column should look like this:
<input type="checkbox" value="e2ec3c7f-fc71-f011-807a-0050b6c0caf2" class="cp-file-download">

Callback examples

Storing the selection into a hidden form field as it changes:

onChange: function (selectedIds) { $('#cpsys_FormItem_cpsys_DefaultGroup_SelectedDataIds').val(selectedIds.join(', ')); }

And reading it back when the plugin starts, so the selection survives a postback:

onLoadSelectedIds: function() { return $('#cpsys_FormItem_cpsys_DefaultGroup_SelectedDataIds')?.val()?.split(/[,\s]+/); }

Template Content and Item Content

Understanding the difference between the two is essential to building a Data Source that works.

Attribute What goes in it How often it renders
Template Content Wrapper markup, table headers, scripts and styles Once
Item Content The repeating row or card template Once per record
Your Template Content must contain the ItemContent placeholder, or no rows render at all.
ItemContent

That placeholder is where the Item Content template is inserted for every record returned. Without it the Data Source appears empty even when the SQL is returning data perfectly well.

Displaying data with Column scripts

The Column script is the main way to display data inside your Item Content.

<!-- a standard field --> [cp:scripting key='Column' name='Title' /] <!-- a custom attribute --> [cp:scripting key='Column' name='cpsys_Attributes:AuthorName' /] <!-- a formatted date --> [cp:scripting key='Column' name='CreateDate' format='MMMM d, yyyy' /] <!-- with prefix text --> [cp:scripting key='Column' name='cpsys_Attributes:Author' format='Written by {0}' /] <!-- a truncated description --> [cp:scripting key='Column' name='Description' truncate='150' truncatedtextsuffix='...' striphtml='true' /] <!-- a status, with the stored value swapped for a readable one --> [cp:scripting key='Column' name='Status' replacetext='1,2,3' replacewith='Active,Pending,Archived' /]
Parameter What it does Example
name The column or attribute name. Required. name='Title'
format A .NET format string, with {0} standing for the value. format='By {0}'
datatype Forces a data type, such as datetime or number. datatype='datetime'
default What to show when the column is empty. default='N/A'
truncate Maximum character length. truncate='100'
striphtml Removes HTML tags from the value. striphtml='true'
replacetext Comma separated values to find. replacetext='1,2,3'
replacewith Comma separated replacements, in the same order. replacewith='Active,Pending,Archived'
Custom attributes need a prefix. A field that is not in your SQL SELECT but is stored in the record's Attributes XML is reached with cpsys_Attributes: in front of its name, as in name='cpsys_Attributes:CustomField'.