Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

ConfiForms MultiSelect into multiple rows

Sven B
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
April 26, 2019

Hi,

I have a form, which alows the entry of a multiselect field.
Something like: | Key | Value | Multi1, 2, 3 |

I would need this multiselect field in another tableView to be displayed as single rows.

| Key | Value | Multi1 |
| Key | Value | Multi2 |
| Key | Value | Multi3 |

Can someone help me out?

2 answers

1 vote
Alex Medved _ConfiForms_
Community Champion
April 30, 2019

Probably you can just use the ConfiForms TableView Merger macro and set the parameter to "flatten entries"

Screenshot 2019-04-30 at 13.39.17.png

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 30, 2019

Seriously! Um ... yeah, I guess that is way better. I totally forgot about that macro ... I way over engineered it.

0 votes
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 29, 2019

Not sure there is any easy way to do this with the display of the TableView macro. However, you can set the TableView macro to be able to export. A couple of the options for the export are CSV (flatten) and XLS (flatten). The flatten exports will do exactly what you are asking.

image.png

image.png

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 29, 2019

After thinking about it a little more I realized that I do have a way to do with combining a user macro I wrote a couple years ago and the method above. Here is the user macro. It will display a CSV that is either attached to a page or accessible via URL as a table on a Confluence page. With the method above you could get the URL for the flattened CSV and then put that URL in the below user macro and it would be displayed on the page as a table. The URL for the flattened CSV would look like this. Change it to fit your setup. Also, see the screenshot for how it would look. The top table is the TableView macro  and the bottom is the user macro.

image.pngCSV User Macro Code

Macro Name:
csv_table

Macro Title:
CSV Table

Macro Body Processing:
No macro body

Template:

## Developed by: Davin Studer
## Date created: 05/07/2014
## @param CSVName:title=CSV File|type=string|required=false|desc=If the CSV is attached to a page use this field.
## @param Page:title=Page Title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @param CSVURL:title=CSV URL|type=string|required=false|desc=If the CSV is not attached to a page but is accessible via URL use this field.
## @param TopHeader:title=Top Header Row|type=boolean|required=false|default=false|desc=Check if the top row should be a header row?

###########################################################################
## These are used for getting around velocity issues when writing jQuery ##
###########################################################################
#set($d = '$')
#set($p = '#')
#set($error = "")

#if($paramCSVName && $paramCSVName != "" && $paramCSVURL && $paramCSVURL)
    #set($error = $error + "<p>Use either the CSV File field or the CSV URL field. Not both.</p>")
#end

##############################
## Create a unique id value ##
##############################
#set( $id=$action.dateFormatter.calendar.timeInMillis )

#if( $paramPage && $paramPage != "" )
    ##########################
    ## Get the page manager ##
    ##########################
    #set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
    #set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
    #set( $containerManager=$getInstanceMethod.invoke(null,null) )
    #set( $containerContext=$containerManager.containerContext )
    #set( $pageManager=$containerContext.getComponent('pageManager') )

    ##########################
    ## Find the page        ##
    ##########################
    #set( $parts = $paramPage.split(":") )
    #set( $i = 0 )
    #set( $len = 0 )
    #set( $key = "" )
    #set( $name = "" )

    ##Having trouble finding out the length/size of $parts ... brute force it
    #foreach( $part in $parts )
        #set( $len = $len + 1 )
    #end
    
    #if( $len == 1 )
        #set( $key = $content.spaceKey )
        #set( $name = $paramPage )
    #else
        #foreach( $part in $parts )
            #if( $i == 0 )
              #set( $key = $part )
              #set( $i = $i + 1 )
           #else
              #set( $name = $part )
           #end
        #end
    #end

    #set( $tempcontent = "" )

    #if( $pageManager )
        #set( $tempcontent = $pageManager.getPage($key, $name) )
    #end

    #if( $tempcontent && $tempcontent != "" )
        #set( $content = $tempcontent )
    #else
        The page "$paramPage" was not found in this space.
        #set( $content = "" )
    #end
#end

#set( $attachments = $attachmentManager.getLatestVersionsOfAttachments($content) )

############################################################################
## Could not find a method to sort the $attachments in Alphabetical order ##
## Must sort them myself ... bubble sort                                  ##
############################################################################
#set( $size = $attachments.size() )
#foreach( $junk in $attachments )
    #set( $count = -1 )
    #foreach( $line in $attachments )
        #set( $count = $count + 1 )
        #if( $velocityCount < $size )
            #if( $line.getTitle().compareToIgnoreCase($attachments.get($velocityCount).getTitle()) > 0 )
                #set( $tmp = $attachments.get($velocityCount) )
                #set( $junk = $attachments.set($velocityCount, $line) )
                #set( $junk = $attachments.set($count, $tmp) )
            #end
        #end
    #end
#end

#if($paramCSVURL && $paramCSVURL != "")
    #set($csvURL = $paramCSVURL)
#else
    #set( $baseUrl = $action.getGlobalSettings().getBaseUrl() )
    
    #foreach( $attachment in $attachments )
        #if( $attachment.getTitle().toLowerCase() == $paramCSVName.toLowerCase() )
            #set( $url = $attachment.getDownloadPathWithoutVersion() )
        #end
    #end
    #set($csvURL = ${baseUrl} + ${url})
#end

#########################################################################
## This will only run on the macro properties dialog. It will add a    ##
## dropdown to select a CSV file.                                      ##
#########################################################################
<script type="text/javascript">
AJS.toInit(function(){
    /////////////////////////////////////////////////
    // Are we on the macro properties edit screen? //
    /////////////////////////////////////////////////
    if(self != top && window.parent.AJS.${d}('${p}macro-browser-preview').length > 0) {
        var options = '<option value="">Select a file</option>';
        var csvInput = window.parent.AJS.${d}('${p}macro-param-CSVName');
        var pageInput = window.parent.AJS.${d}('${p}macro-param-Page');
        var refresh = window.parent.AJS.${d}('${p}macro-browser-preview-link');
        var secondBlur = false;
        
        //Hide cvsInput ... this will be updated programatically by our new dropdown
        csvInput.css('display','none');

        //Remove copy input if it exists ... macro preview refresh
        window.parent.AJS.${d}('${p}macro-param-CSVName-copy').remove();

        //Add copy field
        csvInput.before('<select class="select" id="macro-param-CSVName-copy" name="macro-param-CSVName-copy"></select>');

        //Reference to new field
        var csvInputCopy = window.parent.AJS.${d}('${p}macro-param-CSVName-copy');

        //Change original csvInput field when dropdown copy is changed
        csvInputCopy.change(function(){
            csvInput.val(csvInputCopy.val());
        });

        //Register change event for page input to populate the attachments for that page
        //This focus/blur workaround is because if you select a page from the page hint
        //popup the blur and change events won't have the full value right away. They will
        //only see what the user typed which may not be the complete page title. So, after 500
        //milliseconds we will focus it and then blur it to get the real value. The secondBlur boolean
        //is to make sure we only run the blur event on the second time around.
        pageInput.change(function(){
            secondBlur = false;
            
            setTimeout(function(){
                secondBlur = true;
                window.parent.AJS.${d}('${p}macro-param-Page').focus();
                window.parent.AJS.${d}('${p}macro-param-Page').blur();
            }, 500);
        });
        pageInput.blur(function(){
            if(secondBlur) {
                secondBlur = false;
                
                //Clear csvInput since we are doing a preview refresh to get new dropdown values
                csvInput.val('');

                //Refresh the preview window which will trigger a fetch of the attachments from the specified page.
                refresh.click();
            }
        });
        
        csvInputCopy.html('');
        #foreach( $attachment in $attachments )
            #if($attachment.getFileExtension() == "csv")
                #if($attachment.getTitle().toLowerCase() == $paramCSVName.toLowerCase())
                    #set( $selected = ' selected="selected"' )
                #else
                    #set( $selected = '' )
                #end
            options += '<option value="$attachment.getTitle()"$selected>$attachment.getTitle()</option>';
            #end
        #end
        if(options == '<option value="">Select a file</option>') {
            csvInput.val('');
        }
        csvInputCopy.html(options);
    }
});
</script>
#########################################################################
## End                                                                 ##
#########################################################################

##########################
## Render the CSV table ##
##########################
#if($error && $error != "")
    $error
#else
    #if((${url} && ${url} != "") || ($paramCSVURL && $paramCSVURL != ""))
    <script type="text/javascript">
    //CSV parser from https://github.com/evanplaice/jquery-csv
    RegExp.escape=function(e){return e.replace(/[-\/\\^${d}*+?.()|[\]{}]/g,"\\${d}&")};AJS.${d}.csv={defaults:{separator:",",delimiter:'"',headers:true},hooks:{castToScalar:function(e,t){var n=/\./;if(isNaN(e)){return e}else{if(n.test(e)){return parseFloat(e)}else{var r=parseInt(e);if(isNaN(r)){return null}else{return r}}}}},parsers:{parse:function(e,t){function f(){o=0;u="";if(t.start&&t.state.rowNum<t.start){s=[];t.state.rowNum++;t.state.colNum=1;return}if(t.onParseEntry===undefined){i.push(s)}else{var e=t.onParseEntry(s,t.state);if(e!==false){i.push(e)}}s=[];if(t.end&&t.state.rowNum>=t.end){a=true}t.state.rowNum++;t.state.colNum=1}function l(){if(t.onParseValue===undefined){s.push(u)}else{var e=t.onParseValue(u,t.state);if(e!==false){s.push(e)}}u="";o=0;t.state.colNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}if(!t.state.colNum){t.state.colNum=1}var i=[];var s=[];var o=0;var u="";var a=false;var c=RegExp.escape(n);var h=RegExp.escape(r);var p=/(D|S|\r\n|\n|\r|[^DS\r\n]+)/;var d=p.source;d=d.replace(/S/g,c);d=d.replace(/D/g,h);p=RegExp(d,"gm");e.replace(p,function(e){if(a){return}switch(o){case 0:if(e===n){u+="";l();break}if(e===r){o=1;break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}u+=e;o=3;break;case 1:if(e===r){o=2;break}u+=e;o=1;break;case 2:if(e===r){u+=e;o=1;break}if(e===n){l();break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}throw new Error("CSVDataError: Illegal State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");case 3:if(e===n){l();break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}if(e===r){throw new Error("CSVDataError: Illegal Quote [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}throw new Error("CSVDataError: Illegal Data [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");default:throw new Error("CSVDataError: Unknown State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}});if(s.length!==0){l();f()}return i},splitLines:function(e,t){function a(){s=0;if(t.start&&t.state.rowNum<t.start){o="";t.state.rowNum++;return}if(t.onParseEntry===undefined){i.push(o)}else{var e=t.onParseEntry(o,t.state);if(e!==false){i.push(e)}}o="";if(t.end&&t.state.rowNum>=t.end){u=true}t.state.rowNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}var i=[];var s=0;var o="";var u=false;var f=RegExp.escape(n);var l=RegExp.escape(r);var c=/(D|S|\n|\r|[^DS\r\n]+)/;var h=c.source;h=h.replace(/S/g,f);h=h.replace(/D/g,l);c=RegExp(h,"gm");e.replace(c,function(e){if(u){return}switch(s){case 0:if(e===n){o+=e;s=0;break}if(e===r){o+=e;s=1;break}if(e==="\n"){a();break}if(/^\r${d}/.test(e)){break}o+=e;s=3;break;case 1:if(e===r){o+=e;s=2;break}o+=e;s=1;break;case 2:var i=o.substr(o.length-1);if(e===r&&i===r){o+=e;s=1;break}if(e===n){o+=e;s=0;break}if(e==="\n"){a();break}if(e==="\r"){break}throw new Error("CSVDataError: Illegal state [Row:"+t.state.rowNum+"]");case 3:if(e===n){o+=e;s=0;break}if(e==="\n"){a();break}if(e==="\r"){break}if(e===r){throw new Error("CSVDataError: Illegal quote [Row:"+t.state.rowNum+"]")}throw new Error("CSVDataError: Illegal state [Row:"+t.state.rowNum+"]");default:throw new Error("CSVDataError: Unknown state [Row:"+t.state.rowNum+"]")}});if(o!==""){a()}return i},parseEntry:function(e,t){function u(){if(t.onParseValue===undefined){i.push(o)}else{var e=t.onParseValue(o,t.state);if(e!==false){i.push(e)}}o="";s=0;t.state.colNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}if(!t.state.colNum){t.state.colNum=1}var i=[];var s=0;var o="";if(!t.match){var a=RegExp.escape(n);var f=RegExp.escape(r);var l=/(D|S|\n|\r|[^DS\r\n]+)/;var c=l.source;c=c.replace(/S/g,a);c=c.replace(/D/g,f);t.match=RegExp(c,"gm")}e.replace(t.match,function(e){switch(s){case 0:if(e===n){o+="";u();break}if(e===r){s=1;break}if(e==="\n"||e==="\r"){break}o+=e;s=3;break;case 1:if(e===r){s=2;break}o+=e;s=1;break;case 2:if(e===r){o+=e;s=1;break}if(e===n){u();break}if(e==="\n"||e==="\r"){break}throw new Error("CSVDataError: Illegal State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");case 3:if(e===n){u();break}if(e==="\n"||e==="\r"){break}if(e===r){throw new Error("CSVDataError: Illegal Quote [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}throw new Error("CSVDataError: Illegal Data [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");default:throw new Error("CSVDataError: Unknown State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}});u();return i}},helpers:{collectPropertyNames:function(e){var t,n,r=[];for(t in e){for(n in e[t]){if(e[t].hasOwnProperty(n)&&r.indexOf(n)<0&&typeof e[t][n]!=="function"){r.push(n)}}}return r}},toArray:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i=t.state!==undefined?t.state:{};var t={delimiter:r.delimiter,separator:r.separator,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,state:i};var s=AJS.${d}.csv.parsers.parseEntry(e,t);if(!r.callback){return s}else{r.callback("",s)}},toArrays:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i=[];var t={delimiter:r.delimiter,separator:r.separator,onPreParse:t.onPreParse,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,onPostParse:t.onPostParse,start:t.start,end:t.end,state:{rowNum:1,colNum:1}};if(t.onPreParse!==undefined){t.onPreParse(e,t.state)}i=AJS.${d}.csv.parsers.parse(e,t);if(t.onPostParse!==undefined){t.onPostParse(i,t.state)}if(!r.callback){return i}else{r.callback("",i)}},toObjects:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;r.headers="headers"in t?t.headers:AJS.${d}.csv.defaults.headers;t.start="start"in t?t.start:1;if(r.headers){t.start++}if(t.end&&r.headers){t.end++}var i=[];var s=[];var t={delimiter:r.delimiter,separator:r.separator,onPreParse:t.onPreParse,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,onPostParse:t.onPostParse,start:t.start,end:t.end,state:{rowNum:1,colNum:1},match:false,transform:t.transform};var o={delimiter:r.delimiter,separator:r.separator,start:1,end:1,state:{rowNum:1,colNum:1}};if(t.onPreParse!==undefined){t.onPreParse(e,t.state)}var u=AJS.${d}.csv.parsers.splitLines(e,o);var a=AJS.${d}.csv.toArray(u[0],t);var i=AJS.${d}.csv.parsers.splitLines(e,t);t.state.colNum=1;if(a){t.state.rowNum=2}else{t.state.rowNum=1}for(var f=0,l=i.length;f<l;f++){var c=AJS.${d}.csv.toArray(i[f],t);var h={};for(var p in a){h[a[p]]=c[p]}if(t.transform!==undefined){s.push(t.transform.call(undefined,h))}else{s.push(h)}t.state.rowNum++}if(t.onPostParse!==undefined){t.onPostParse(s,t.state)}if(!r.callback){return s}else{r.callback("",s)}},fromArrays:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i="",s,o,u,a;for(u=0;u<e.length;u++){s=e[u];o=[];for(a=0;a<s.length;a++){var f=s[a]===undefined||s[a]===null?"":s[a].toString();if(f.indexOf(r.delimiter)>-1){f=f.replace(r.delimiter,r.delimiter+r.delimiter)}var l="\n|\r|S|D";l=l.replace("S",r.separator);l=l.replace("D",r.delimiter);if(f.search(l)>-1){f=r.delimiter+f+r.delimiter}o.push(f)}i+=o.join(r.separator)+"\r\n"}if(!r.callback){return i}else{r.callback("",i)}},fromObjects:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;r.headers="headers"in t?t.headers:AJS.${d}.csv.defaults.headers;r.sortOrder="sortOrder"in t?t.sortOrder:"declare";r.manualOrder="manualOrder"in t?t.manualOrder:[];r.transform=t.transform;if(typeof r.manualOrder==="string"){r.manualOrder=AJS.${d}.csv.toArray(r.manualOrder,r)}if(r.transform!==undefined){var i=e;e=[];var s;for(s=0;s<i.length;s++){e.push(r.transform.call(undefined,i[s]))}}var o=AJS.${d}.csv.helpers.collectPropertyNames(e);if(r.sortOrder==="alpha"){o.sort()}if(r.manualOrder.length>0){var u=[].concat(r.manualOrder);var a;for(a=0;a<o.length;a++){if(u.indexOf(o[a])<0){u.push(o[a])}}o=u}var f,a,l,c=[],h;if(r.headers){c.push(o)}for(f=0;f<e.length;f++){l=[];for(a=0;a<o.length;a++){h=o[a];if(h in e[f]&&typeof e[f][h]!=="function"){l.push(e[f][h])}else{l.push("")}}c.push(l)}return AJS.${d}.csv.fromArrays(c,t,r.callback)}}
    
    AJS.toInit(function(){
        AJS.${d}.get("${csvURL}", function( data ) {
            var result = AJS.${d}.csv.toArrays(data);
            var html = '';
            var count = 0;
            var topHeader = $paramTopHeader;
    
            for(var row in result) {
                
                if(count == 0) {
                    if(topHeader) {
                        html += '<thead>\r\n';
                        html += '<tr>\r\n';
                        for(var item in result[row]) {
                            html += '<th class="confluenceTh">' + result[row][item] + '</th>\r\n';
                        }
                        html += '</tr>\r\n';
                        html += '</thead>\r\n';
                        html += '<tbody>\r\n';
                    } else {
                        html += '<tbody>\r\n';
                        html += '<tr>\r\n';
                        for(var item in result[row]) {
                            html += '<td class="confluenceTd">' + result[row][item] + '</td>\r\n';
                        }
                        html += '</tr>\r\n';
                    }
                } else {
                    html += '<tr>\r\n';
                    for(var item in result[row]) {
                        html += '<td class="confluenceTd">' + result[row][item] + '</td>\r\n';
                    }
                    html += '</tr>\r\n';
                }
                count++
            }
            html += '</tbody>\r\n';
            AJS.$('#csv-table-$id').html(html);
        });
    });
    </script>
    #end
    <table id="csv-table-$id" class="confluenceTable tablesorter">
    </table>
#end
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 29, 2019

After thinking about it a bit there is a way to show it as a table on a page. You can get the URL for the flattened CSV file from the method above. It would look like this ...

https://{your server}/ajax/confiforms/export.action?t=flatten.csv&pageId={your page id}&fd={your form name}%3A{your page id ... again}&fields={field 1}%2C{field 2}%2C{field 3}%2C{field n+1}&filter=

From there you could use a user macro that I wrote a couple of years ago to display the CSV as a table. The user macro code is below. Also there is and example screenshot of what it looks like. The top table is the TableView macro and the bottom table is the flattened CSV version of that table displayed via the user macro.

image.pngCSV Table User Macro Code

Macro Name:
csv_table

Macro Title:
CSV Table

Macro Body Processing:
No macro body

Template

## Developed by: Davin Studer
## Date created: 05/07/2014
## @param CSVName:title=CSV File|type=string|required=false|desc=If the CSV is attached to a page use this field.
## @param Page:title=Page Title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @param CSVURL:title=CSV URL|type=string|required=false|desc=If the CSV is not attached to a page but is accessible via URL use this field.
## @param TopHeader:title=Top Header Row|type=boolean|required=false|default=false|desc=Check if the top row should be a header row?

###########################################################################
## These are used for getting around velocity issues when writing jQuery ##
###########################################################################
#set($d = '$')
#set($p = '#')
#set($error = "")

#if($paramCSVName && $paramCSVName != "" && $paramCSVURL && $paramCSVURL)
    #set($error = $error + "<p>Use either the CSV File field or the CSV URL field. Not both.</p>")
#end

##############################
## Create a unique id value ##
##############################
#set( $id=$action.dateFormatter.calendar.timeInMillis )

#if( $paramPage && $paramPage != "" )
    ##########################
    ## Get the page manager ##
    ##########################
    #set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
    #set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
    #set( $containerManager=$getInstanceMethod.invoke(null,null) )
    #set( $containerContext=$containerManager.containerContext )
    #set( $pageManager=$containerContext.getComponent('pageManager') )

    ##########################
    ## Find the page        ##
    ##########################
    #set( $parts = $paramPage.split(":") )
    #set( $i = 0 )
    #set( $len = 0 )
    #set( $key = "" )
    #set( $name = "" )

    ##Having trouble finding out the length/size of $parts ... brute force it
    #foreach( $part in $parts )
        #set( $len = $len + 1 )
    #end
    
    #if( $len == 1 )
        #set( $key = $content.spaceKey )
        #set( $name = $paramPage )
    #else
        #foreach( $part in $parts )
            #if( $i == 0 )
              #set( $key = $part )
              #set( $i = $i + 1 )
           #else
              #set( $name = $part )
           #end
        #end
    #end

    #set( $tempcontent = "" )

    #if( $pageManager )
        #set( $tempcontent = $pageManager.getPage($key, $name) )
    #end

    #if( $tempcontent && $tempcontent != "" )
        #set( $content = $tempcontent )
    #else
        The page "$paramPage" was not found in this space.
        #set( $content = "" )
    #end
#end

#set( $attachments = $attachmentManager.getLatestVersionsOfAttachments($content) )

############################################################################
## Could not find a method to sort the $attachments in Alphabetical order ##
## Must sort them myself ... bubble sort                                  ##
############################################################################
#set( $size = $attachments.size() )
#foreach( $junk in $attachments )
    #set( $count = -1 )
    #foreach( $line in $attachments )
        #set( $count = $count + 1 )
        #if( $velocityCount < $size )
            #if( $line.getTitle().compareToIgnoreCase($attachments.get($velocityCount).getTitle()) > 0 )
                #set( $tmp = $attachments.get($velocityCount) )
                #set( $junk = $attachments.set($velocityCount, $line) )
                #set( $junk = $attachments.set($count, $tmp) )
            #end
        #end
    #end
#end

#if($paramCSVURL && $paramCSVURL != "")
    #set($csvURL = $paramCSVURL)
#else
    #set( $baseUrl = $action.getGlobalSettings().getBaseUrl() )
    
    #foreach( $attachment in $attachments )
        #if( $attachment.getTitle().toLowerCase() == $paramCSVName.toLowerCase() )
            #set( $url = $attachment.getDownloadPathWithoutVersion() )
        #end
    #end
    #set($csvURL = ${baseUrl} + ${url})
#end

#########################################################################
## This will only run on the macro properties dialog. It will add a    ##
## dropdown to select a CSV file.                                      ##
#########################################################################
<script type="text/javascript">
AJS.toInit(function(){
    /////////////////////////////////////////////////
    // Are we on the macro properties edit screen? //
    /////////////////////////////////////////////////
    if(self != top && window.parent.AJS.${d}('${p}macro-browser-preview').length > 0) {
        var options = '<option value="">Select a file</option>';
        var csvInput = window.parent.AJS.${d}('${p}macro-param-CSVName');
        var pageInput = window.parent.AJS.${d}('${p}macro-param-Page');
        var refresh = window.parent.AJS.${d}('${p}macro-browser-preview-link');
        var secondBlur = false;
        
        //Hide cvsInput ... this will be updated programatically by our new dropdown
        csvInput.css('display','none');

        //Remove copy input if it exists ... macro preview refresh
        window.parent.AJS.${d}('${p}macro-param-CSVName-copy').remove();

        //Add copy field
        csvInput.before('<select class="select" id="macro-param-CSVName-copy" name="macro-param-CSVName-copy"></select>');

        //Reference to new field
        var csvInputCopy = window.parent.AJS.${d}('${p}macro-param-CSVName-copy');

        //Change original csvInput field when dropdown copy is changed
        csvInputCopy.change(function(){
            csvInput.val(csvInputCopy.val());
        });

        //Register change event for page input to populate the attachments for that page
        //This focus/blur workaround is because if you select a page from the page hint
        //popup the blur and change events won't have the full value right away. They will
        //only see what the user typed which may not be the complete page title. So, after 500
        //milliseconds we will focus it and then blur it to get the real value. The secondBlur boolean
        //is to make sure we only run the blur event on the second time around.
        pageInput.change(function(){
            secondBlur = false;
            
            setTimeout(function(){
                secondBlur = true;
                window.parent.AJS.${d}('${p}macro-param-Page').focus();
                window.parent.AJS.${d}('${p}macro-param-Page').blur();
            }, 500);
        });
        pageInput.blur(function(){
            if(secondBlur) {
                secondBlur = false;
                
                //Clear csvInput since we are doing a preview refresh to get new dropdown values
                csvInput.val('');

                //Refresh the preview window which will trigger a fetch of the attachments from the specified page.
                refresh.click();
            }
        });
        
        csvInputCopy.html('');
        #foreach( $attachment in $attachments )
            #if($attachment.getFileExtension() == "csv")
                #if($attachment.getTitle().toLowerCase() == $paramCSVName.toLowerCase())
                    #set( $selected = ' selected="selected"' )
                #else
                    #set( $selected = '' )
                #end
            options += '<option value="$attachment.getTitle()"$selected>$attachment.getTitle()</option>';
            #end
        #end
        if(options == '<option value="">Select a file</option>') {
            csvInput.val('');
        }
        csvInputCopy.html(options);
    }
});
</script>
#########################################################################
## End                                                                 ##
#########################################################################

##########################
## Render the CSV table ##
##########################
#if($error && $error != "")
    $error
#else
    #if((${url} && ${url} != "") || ($paramCSVURL && $paramCSVURL != ""))
    <script type="text/javascript">
    //CSV parser from https://github.com/evanplaice/jquery-csv
    RegExp.escape=function(e){return e.replace(/[-\/\\^${d}*+?.()|[\]{}]/g,"\\${d}&")};AJS.${d}.csv={defaults:{separator:",",delimiter:'"',headers:true},hooks:{castToScalar:function(e,t){var n=/\./;if(isNaN(e)){return e}else{if(n.test(e)){return parseFloat(e)}else{var r=parseInt(e);if(isNaN(r)){return null}else{return r}}}}},parsers:{parse:function(e,t){function f(){o=0;u="";if(t.start&&t.state.rowNum<t.start){s=[];t.state.rowNum++;t.state.colNum=1;return}if(t.onParseEntry===undefined){i.push(s)}else{var e=t.onParseEntry(s,t.state);if(e!==false){i.push(e)}}s=[];if(t.end&&t.state.rowNum>=t.end){a=true}t.state.rowNum++;t.state.colNum=1}function l(){if(t.onParseValue===undefined){s.push(u)}else{var e=t.onParseValue(u,t.state);if(e!==false){s.push(e)}}u="";o=0;t.state.colNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}if(!t.state.colNum){t.state.colNum=1}var i=[];var s=[];var o=0;var u="";var a=false;var c=RegExp.escape(n);var h=RegExp.escape(r);var p=/(D|S|\r\n|\n|\r|[^DS\r\n]+)/;var d=p.source;d=d.replace(/S/g,c);d=d.replace(/D/g,h);p=RegExp(d,"gm");e.replace(p,function(e){if(a){return}switch(o){case 0:if(e===n){u+="";l();break}if(e===r){o=1;break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}u+=e;o=3;break;case 1:if(e===r){o=2;break}u+=e;o=1;break;case 2:if(e===r){u+=e;o=1;break}if(e===n){l();break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}throw new Error("CSVDataError: Illegal State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");case 3:if(e===n){l();break}if(/^(\r\n|\n|\r)${d}/.test(e)){l();f();break}if(e===r){throw new Error("CSVDataError: Illegal Quote [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}throw new Error("CSVDataError: Illegal Data [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");default:throw new Error("CSVDataError: Unknown State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}});if(s.length!==0){l();f()}return i},splitLines:function(e,t){function a(){s=0;if(t.start&&t.state.rowNum<t.start){o="";t.state.rowNum++;return}if(t.onParseEntry===undefined){i.push(o)}else{var e=t.onParseEntry(o,t.state);if(e!==false){i.push(e)}}o="";if(t.end&&t.state.rowNum>=t.end){u=true}t.state.rowNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}var i=[];var s=0;var o="";var u=false;var f=RegExp.escape(n);var l=RegExp.escape(r);var c=/(D|S|\n|\r|[^DS\r\n]+)/;var h=c.source;h=h.replace(/S/g,f);h=h.replace(/D/g,l);c=RegExp(h,"gm");e.replace(c,function(e){if(u){return}switch(s){case 0:if(e===n){o+=e;s=0;break}if(e===r){o+=e;s=1;break}if(e==="\n"){a();break}if(/^\r${d}/.test(e)){break}o+=e;s=3;break;case 1:if(e===r){o+=e;s=2;break}o+=e;s=1;break;case 2:var i=o.substr(o.length-1);if(e===r&&i===r){o+=e;s=1;break}if(e===n){o+=e;s=0;break}if(e==="\n"){a();break}if(e==="\r"){break}throw new Error("CSVDataError: Illegal state [Row:"+t.state.rowNum+"]");case 3:if(e===n){o+=e;s=0;break}if(e==="\n"){a();break}if(e==="\r"){break}if(e===r){throw new Error("CSVDataError: Illegal quote [Row:"+t.state.rowNum+"]")}throw new Error("CSVDataError: Illegal state [Row:"+t.state.rowNum+"]");default:throw new Error("CSVDataError: Unknown state [Row:"+t.state.rowNum+"]")}});if(o!==""){a()}return i},parseEntry:function(e,t){function u(){if(t.onParseValue===undefined){i.push(o)}else{var e=t.onParseValue(o,t.state);if(e!==false){i.push(e)}}o="";s=0;t.state.colNum++}var n=t.separator;var r=t.delimiter;if(!t.state.rowNum){t.state.rowNum=1}if(!t.state.colNum){t.state.colNum=1}var i=[];var s=0;var o="";if(!t.match){var a=RegExp.escape(n);var f=RegExp.escape(r);var l=/(D|S|\n|\r|[^DS\r\n]+)/;var c=l.source;c=c.replace(/S/g,a);c=c.replace(/D/g,f);t.match=RegExp(c,"gm")}e.replace(t.match,function(e){switch(s){case 0:if(e===n){o+="";u();break}if(e===r){s=1;break}if(e==="\n"||e==="\r"){break}o+=e;s=3;break;case 1:if(e===r){s=2;break}o+=e;s=1;break;case 2:if(e===r){o+=e;s=1;break}if(e===n){u();break}if(e==="\n"||e==="\r"){break}throw new Error("CSVDataError: Illegal State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");case 3:if(e===n){u();break}if(e==="\n"||e==="\r"){break}if(e===r){throw new Error("CSVDataError: Illegal Quote [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}throw new Error("CSVDataError: Illegal Data [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]");default:throw new Error("CSVDataError: Unknown State [Row:"+t.state.rowNum+"][Col:"+t.state.colNum+"]")}});u();return i}},helpers:{collectPropertyNames:function(e){var t,n,r=[];for(t in e){for(n in e[t]){if(e[t].hasOwnProperty(n)&&r.indexOf(n)<0&&typeof e[t][n]!=="function"){r.push(n)}}}return r}},toArray:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i=t.state!==undefined?t.state:{};var t={delimiter:r.delimiter,separator:r.separator,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,state:i};var s=AJS.${d}.csv.parsers.parseEntry(e,t);if(!r.callback){return s}else{r.callback("",s)}},toArrays:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i=[];var t={delimiter:r.delimiter,separator:r.separator,onPreParse:t.onPreParse,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,onPostParse:t.onPostParse,start:t.start,end:t.end,state:{rowNum:1,colNum:1}};if(t.onPreParse!==undefined){t.onPreParse(e,t.state)}i=AJS.${d}.csv.parsers.parse(e,t);if(t.onPostParse!==undefined){t.onPostParse(i,t.state)}if(!r.callback){return i}else{r.callback("",i)}},toObjects:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;r.headers="headers"in t?t.headers:AJS.${d}.csv.defaults.headers;t.start="start"in t?t.start:1;if(r.headers){t.start++}if(t.end&&r.headers){t.end++}var i=[];var s=[];var t={delimiter:r.delimiter,separator:r.separator,onPreParse:t.onPreParse,onParseEntry:t.onParseEntry,onParseValue:t.onParseValue,onPostParse:t.onPostParse,start:t.start,end:t.end,state:{rowNum:1,colNum:1},match:false,transform:t.transform};var o={delimiter:r.delimiter,separator:r.separator,start:1,end:1,state:{rowNum:1,colNum:1}};if(t.onPreParse!==undefined){t.onPreParse(e,t.state)}var u=AJS.${d}.csv.parsers.splitLines(e,o);var a=AJS.${d}.csv.toArray(u[0],t);var i=AJS.${d}.csv.parsers.splitLines(e,t);t.state.colNum=1;if(a){t.state.rowNum=2}else{t.state.rowNum=1}for(var f=0,l=i.length;f<l;f++){var c=AJS.${d}.csv.toArray(i[f],t);var h={};for(var p in a){h[a[p]]=c[p]}if(t.transform!==undefined){s.push(t.transform.call(undefined,h))}else{s.push(h)}t.state.rowNum++}if(t.onPostParse!==undefined){t.onPostParse(s,t.state)}if(!r.callback){return s}else{r.callback("",s)}},fromArrays:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;var i="",s,o,u,a;for(u=0;u<e.length;u++){s=e[u];o=[];for(a=0;a<s.length;a++){var f=s[a]===undefined||s[a]===null?"":s[a].toString();if(f.indexOf(r.delimiter)>-1){f=f.replace(r.delimiter,r.delimiter+r.delimiter)}var l="\n|\r|S|D";l=l.replace("S",r.separator);l=l.replace("D",r.delimiter);if(f.search(l)>-1){f=r.delimiter+f+r.delimiter}o.push(f)}i+=o.join(r.separator)+"\r\n"}if(!r.callback){return i}else{r.callback("",i)}},fromObjects:function(e,t,n){var t=t!==undefined?t:{};var r={};r.callback=n!==undefined&&typeof n==="function"?n:false;r.separator="separator"in t?t.separator:AJS.${d}.csv.defaults.separator;r.delimiter="delimiter"in t?t.delimiter:AJS.${d}.csv.defaults.delimiter;r.headers="headers"in t?t.headers:AJS.${d}.csv.defaults.headers;r.sortOrder="sortOrder"in t?t.sortOrder:"declare";r.manualOrder="manualOrder"in t?t.manualOrder:[];r.transform=t.transform;if(typeof r.manualOrder==="string"){r.manualOrder=AJS.${d}.csv.toArray(r.manualOrder,r)}if(r.transform!==undefined){var i=e;e=[];var s;for(s=0;s<i.length;s++){e.push(r.transform.call(undefined,i[s]))}}var o=AJS.${d}.csv.helpers.collectPropertyNames(e);if(r.sortOrder==="alpha"){o.sort()}if(r.manualOrder.length>0){var u=[].concat(r.manualOrder);var a;for(a=0;a<o.length;a++){if(u.indexOf(o[a])<0){u.push(o[a])}}o=u}var f,a,l,c=[],h;if(r.headers){c.push(o)}for(f=0;f<e.length;f++){l=[];for(a=0;a<o.length;a++){h=o[a];if(h in e[f]&&typeof e[f][h]!=="function"){l.push(e[f][h])}else{l.push("")}}c.push(l)}return AJS.${d}.csv.fromArrays(c,t,r.callback)}}
    
    AJS.toInit(function(){
        AJS.${d}.get("${csvURL}", function( data ) {
            var result = AJS.${d}.csv.toArrays(data);
            var html = '';
            var count = 0;
            var topHeader = $paramTopHeader;
    
            for(var row in result) {
                
                if(count == 0) {
                    if(topHeader) {
                        html += '<thead>\r\n';
                        html += '<tr>\r\n';
                        for(var item in result[row]) {
                            html += '<th class="confluenceTh">' + result[row][item] + '</th>\r\n';
                        }
                        html += '</tr>\r\n';
                        html += '</thead>\r\n';
                        html += '<tbody>\r\n';
                    } else {
                        html += '<tbody>\r\n';
                        html += '<tr>\r\n';
                        for(var item in result[row]) {
                            html += '<td class="confluenceTd">' + result[row][item] + '</td>\r\n';
                        }
                        html += '</tr>\r\n';
                    }
                } else {
                    html += '<tr>\r\n';
                    for(var item in result[row]) {
                        html += '<td class="confluenceTd">' + result[row][item] + '</td>\r\n';
                    }
                    html += '</tr>\r\n';
                }
                count++
            }
            html += '</tbody>\r\n';
            AJS.$('#csv-table-$id').html(html);
        });
    });
    </script>
    #end
    <table id="csv-table-$id" class="confluenceTable tablesorter">
    </table>
#end

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events