How do I remove the last trailing comma?


(Nick Papadatos) #1

Matrix Version: 5.3

Hi squiz folk
Can someone help me with removing the last trailing comma from an asset listing page that is in JSON format?

…“thumbnailURL”:"%asset_metadata_image%"},
I’m sure this has been answered but couldn’t find it anywhere

Never mind - I ended up finding Nics post using position formats -1

Cheers
N


(Andrew Harris) #2

I tend to go the other way around.
a keyword like %asset_count^eq:1::,% at the start of each item will insert a comma before all but the first asset.
(wrote that from memory, so YMMV)

EDIT: Memory failing, correct keyword below!


(John gill) #3

I like this approach, less chance of the bodycopies getting out of sync.

It seems to require %asset_page_position% which wasn’t added until 5.4.2.2.


(Andrew Harris) #4

Ahh, whoops, this is the keyword I use: %asset_list_position^eq:1::,% and that’s been around for yonks. Should work everywhere.


(Nick Papadatos) #5

Thanks guys, after looking at this a tad more closely I believe there are three common ways to approach this.

Option 1:

Add a ^replace on the %asset_listing% keyword to remove the last comma and in this case, any whitespace that might follow it, until the end of the contents of the keyword:

{"root":{
   "cat":[
      %asset_listing^replace:,\s*$%:%
      ],
      %globals_asset_contents_raw:xx%
      %globals_asset_contents_raw:xx%
  }
}

Option 2:

%asset_position^eq:1::,%

Option 3:
is using the position formats with -1as the position target.

In the end whatever works, yeah?
Cheers
Nick


(John gill) #6

Good summary. I never would have thought of #1 (but I suspect it would have the worst performance of the three. Maybe)

For #2, I think that %asset_position% and %asset_list_position% will only work on the first page. On all pages other than page1 none of the assets == 1 and you’re back to malformed JSON. It needs to be %asset_page_position%.


(Nick Papadatos) #7

Thanks John - I ended up using #2 %asset_position^eq:1::, at the beginning of each default format and checked my json on https://jsoneditoronline.org/ with no errors.

Cheers
N


(John gill) #8

Super weird, %asset_position% should never be 1 on subsequent pages. I guess if it’s working it’s working but I can’t work out how.

I just double checked in 5.3 test server and confirmed that when set up with a page size of 3, and the Default Format of <li>%asset_position% %asset_name_linked%</li>, the second page looks like

  • 4 d
  • 5 e
  • 6 f

Must be haunted ¯\_(ツ)_/¯


(Nick Papadatos) #9

hmm, as you can see:

 {
 "root": {
   "cat_1": [
     {
     "id": "1"
     },
     {
      "id": "2"
    }
  ],  end asset-listing - 1
  "cat_2": [
  {
    "id": "1"
  },
  {
    "id": "2"
  }
],  end asset-listing - 2
"cat_3": [
  {
    "id": "1"
  },
   {
    "id": "2"
   }      
  ]  end asset-listing - 3
 }
}

(John gill) #10

It’ll work for the first page of any asset listing, so if you have “Assets per page” set to 0 it’ll be fine.

I suspect that most of the time, when an asset listing is being used to generate JSON then the author probably only ever plans to get one page anyway. Most of ours are like that, although we do have some which have “next” and “prev” properties in the JSON to allow the JavaScript to step through the pager.

If you ever need to access other pages, and you’re pre-5.4.2.2, better to stick to Option #3


(Asharpe) #11

If you’re designing an API (and returning JSON, or even JSONP) you should consider the content type as well.

Here’s a design that renders JSON, and when passed a “callback” parameter will render JSONP with the parameter value as the function name

<MySource_AREA id_name="get_vars" design_area="request_vars">
  <MySource_SET name="method" value="get" />
</MySource_AREA>
<MySource_AREA id_name="content_type_start" design_area="show_if">
    <MySource_SET name="condition" value="keyword_regexp"/>
    <MySource_SET name="condition_keyword" value="globals_get_callback"/>
    <MySource_SET name="condition_keyword_match" value=".+"/>
    <MySource_THEN>
        <MySource_print id_name="__global__" var="content_type" content_type="application/javascript" />
        <MySource_print id_name="get_vars" var="callback"/>(
    </MySource_THEN>
    <MySource_ELSE>
        <MySource_print id_name="__global__" var="content_type" content_type="application/json" />
    </MySource_ELSE>
</MySource_AREA>
<MySource_AREA id_name="page_body" design_area="body"/>
<MySource_AREA id_name="content_type_end" design_area="show_if">
    <MySource_SET name="condition" value="keyword_regexp"/>
    <MySource_SET name="condition_keyword" value="globals_get_callback"/>
    <MySource_SET name="condition_keyword_match" value=".+"/>
    <MySource_THEN>);</MySource_THEN>
</MySource_AREA>

Since we need a comma between each element in the list, but not after the last we can use the position format feature in Matrix. With a little bit of thought we can also get it so we don’t need to update the formats separately!

On the Display Formats screen of the asset listing, create a customised format for position -1, and fill this in as though there’s only a single instance of this type. Then, link this bodycopy div under the default format, and add a new div in the default format just for the separating comma!

This way you only have to edit one of the type formats and they’ll all get the same changes.

It’s also best to have a customisation each for logged out and logged in, so that you can provide some useful content when an unauthorised request is made.


Using Matrix as a REST API endpoint
(Nick Papadatos) #12

Just tried this and worked nicely
When you say -

Then, link this bodycopy div under the default format

Do you mean clone the Position-1 Format content Container div to the Default Format as a linked asset?
Anyway, that’s what I did as that’s how I interpreted it.

I also applied your design above but am not 100% what callback parameters you need to pass? Can you provide an example?

Cheers
N


(Asharpe) #13

You’re using a bit of inconsistent terminology there. “Clone” is a thing you can do, and “link” is a thing you can do. All assets are “linked”, so I’m not sure how to interpret “cloning as a linked asset”.

The goal is you only want to change the format once, irrespective of the position in the listing, so don’t “clone”, as that would create a copy and you still have to update in two places.

Hope that helps :slight_smile:


(Nick Papadatos) #14

sorry was multi tasking I meant drag drop create “new link here” creating a linked asset not cloning - so that you make changes to one spot as you said


(Asharpe) #15

Sorry I missed your question about an example. Say your API is at https://my.site.com/api/v1/useful-endpoint (pro tip: use versioning in the URL!), then to use that endpoint as JSONP you’d include it in your page with something like

<script type="text/javascript">
    function runme(apiResult) {
        console.log(apiResult);
    }
</script>
<script type="text/javascript" src="https://my.site.com/api/v1/useful-endpoint?callback=runme"></script>

That will print the API result in the console. It’s probably worth noting that such a scenario means your API is probably publicly accessible, otherwise you’ll probably be using CORS and you can likely then authenticate as well :slight_smile:

Hope that helps,

A


(Nick Papadatos) #16

Yes, that does help thank you :smile:


(Lewis) #17

Don’t know if this is any help @NickyP?

I’ve had a situation where I’ve needed to send a continuous string of text to another asset so I stich together the individual elements (suffixed with ‘,’ for example) from the asset listing into a string, ^explode:, it, ^array_slice it, starting at 0 and ending at ^asset_count.

%asset_listing^explode:,^array_slice:0:{asset_count}:1%