hbi99 / defiant.js

http://defiantjs.com
GNU Affero General Public License v3.0
913 stars 91 forks source link

Defiant.js render bringing up error in Symphony CMS #80

Closed jude86-7 closed 8 years ago

jude86-7 commented 8 years ago

Hi, I'm just starting out with defiant.js so please excuse me if I'm going about this in the wrong way.

I have a JSON file that I would like to search. So far I have a dropdown options box; the option is taken into the function and I use JSON.search to find the items I need. This prints in the console.log correctly.

However I then need to print out the results on the webpage. I thought the .render would work best, I am using Symphony CMS which is based on XSLT. However when I include the following on my .xsl page I get the error below;

`` Error: element template only allowed as child of stylesheet Found a top-level element script with null namespace URI I presume this is because it's in an .xsl file rather than .html file. But with our CMS this is the only way we can do this. Please can you let me know if what I would like to do is possible. Many thanks for your time.

hbi99 commented 8 years ago

Hi @jude86-7, You can include / load the XSL template as an XSL file, if you want. The important part is this:

<xsl:template name="first-template">
    <xsl:for-each select="//item">
        <h2><xsl:value-of select="title"/></h2>
        <div><xsl:value-of select="region"/></div>
    </xsl:for-each>
</xsl:template>

...this means that you can exclude the SCRIPT tag.

Since I am fond of XSL, I can + want to help XML, XSLT and related technologies to prosper and widely adapted. If you have your code available online, or a simplified version, I can debug and help you solve your problems. Write me at hbi@longscript.com if you prefer non-public assistance.

Best regards

jude86-7 commented 8 years ago

Hi thank you so much for coming back to me. I've tried excluding the script tag but I get the following error in console;

defiant.min.js:7 Uncaught TypeError: Cannot read property 'setAttribute' of null

Perhaps you would be so kind as to help me see where I am going wrong.

I have an xsl page with the following code (just to see if the template is entered;

<xsl:template name="mart-template">
    test
</xsl:template>

Further down this page I call the defiant.js file along with my external.js file that holds the JSON code;

$.getJSON("URL To JSON Data", function (result) {

    res = JSON.search( result, '//mart[region="' + selectedRegion + '"]');
    //console.log(res);

    htm = Defiant.render('mart-template', res);
    console.log(htm);   

});

I hope this makes sense, please let me know if you need any further information. Thanks again

hbi99 commented 8 years ago

Hi @jude86-7, Is there anyway that you can put an example code online? I am pretty sure I can help you instantly if I can see and experience the error.

Cheers

jude86-7 commented 8 years ago

Hi thanks for coming back to me, I've created a jsfiddle, please find link below;

https://jsfiddle.net/jude86_7/qsfdLt70/

I hope this helps to explain what I am trying to do a little better. If you select an item from the drop down box and click the 'find mart' button it should say 'loading' then you can look in the console for the error.

Many thanks for your help, it's much appreciated.

Thanks

hbi99 commented 8 years ago

Hi, I have added a working version of your code here: https://github.com/hbi99/defiant.js/blob/master/demo/symphony.htm

Notes: 1 - I changed the selection attribute as follows:

<xsl:for-each select="//mart">
To:
<xsl:for-each select="//*">

This is the correct way to select any matches that are about to be rendered.

2 - To render, you should use this syntax to trigger a render:

htm = Defiant.render({
        'template': 'mart-template',
        'data': res,
        'sorter': {
            'order': 'descending',
            'select': 'title',
            'type': 'string'
        }
    });

This passes an object with many possibilities for you to render, in any way you like.

3 - I have disabled this row:

$('#resultsForm').html("<p><strong>Loading...</strong></p>");

The reason is that the rendering will happen very fast...in fact, faster than it takes the browser to first put the placeholder and then replace it with rendered output. So, this row is redundant.

Let me know if you encounter other problems :-)

jude86-7 commented 8 years ago

Hi,

Thank you for coming back to me, it's much appreciated. I've made the changes as you've suggested however I'm still coming up with an issue.

Your code works perfectly when the script tag is around the xsl template. However when I remove the script tag (as my code is written in xsl pages it won't allow the script tag to go around the template tag.) I still get the error 'Uncaught TypeError: Cannot read property 'setAttribute' of null'.

I've updated my jsfiddle below to show your code changes;

https://jsfiddle.net/jude86_7/qsfdLt70/

Please note if you add in the script tags the jsfiddle works. Is there anyway around this?

Many thanks again.

hbi99 commented 8 years ago

Did you also notice that I've surrounded the XSL template with SCRIPT-tags?

<script type="defiant/xsl-template">
jude86-7 commented 8 years ago

Yes, this is what I meant in my previous reply; I can't include these SCRIPT-tags in my xsl page as it says there is a code error.

Error: element template only allowed as child of stylesheet Found a top-level element script with null namespace URI

So I need to remove them if possible but when I do I get the setAttribute null error.

Many thanks

hbi99 commented 8 years ago

Can you post your XSL file? So that I can see it here...

jude86-7 commented 8 years ago

Sure can I send it in a PM? It's a site I'm working on that isn't live to the public yet.

hbi99 commented 8 years ago

Sure...send it to hbi@longscript.com

jude86-7 commented 8 years ago

thanks I've sent a message

hbi99 commented 8 years ago

Hi @jude86-7, Now I understand your problem...the setup you have, does not expose the template to Defiant - hence it can't use it to perform a render. One solution is to add the script block to line 2, in file "search-mart.js". This is not an elegant solution and in for me to make it more elegant, I need to install and familiarize myself with how it works.

    var xslt = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">'+
                '<xsl:template name="mart-template">'+
                '   <xsl:for-each select="//*">'+
                '       <h2><xsl:value-of select="title"/></h2>'+
                '       <div><xsl:value-of select="region"/></div>'+
                '   </xsl:for-each>'+
                '</xsl:template>'+
                '</xsl:stylesheet>';
    Defiant.xsl_template = Defiant.xmlFromString(xslt);
jude86-7 commented 8 years ago

Hi @hbi99

Thank you so much for coming back to me; sorry I have taken a while to reply I was away from my computer for a week.

By adding the code you provided to my js file it's now working as expected. Does it have any performance or other implications doing it this way? Rather than the template in the html file?

Thank you so much again for your help.

hbi99 commented 8 years ago

No performance hit...but I would have preferred to "tap into" the core of Symphony and get the template directly instead of adding it as string in Javascript. As I mentioned above, to do this, I need to read the code of Symphony :-S

Perhaps you should give it a try?

jude86-7 commented 8 years ago

Hi Thank you for coming back to me. I'm a bit tight on time at the moment with deadlines but as soon as I have some space I'll definitely take a look and post any findings I have on here.

On a side note if you like xslt I would recommend symphony as a cms, it's really flexible and has a great community behind it.

Thanks again for your help

hbi99 commented 8 years ago

Already checked it out :-)

I hope the community and the CMS evolves even more.