Fog Creek Software
Discussion Board




Knowledge Base
Documentation
Terry's Tips
Darren's Tips

ifAny and ifNotAny

Folks,

Let's say I want to display a list of staff members who have profiles:

Our Staff
  Imma Bozo
  Hugh Betcha

Now let's say we put staff profiles in a Folder called Staff.  We can generate the list with a simple query to retrieve the articles:

foreach x in (folder "Staff")

Now let's say that no staff profiles have been created, so no articles will be retrieved.  What will be displayed?  Just our header:

Our Staff

Question:  How do I discover if the query retrieves an empty set so that I can repress the output of the heading, "Our Staff"? 

In most cases, this is even more important because it is not a simple heading that needs to be supressed, but a complicated table with a specific color scheme.

In the best of all possible words I want:

{$ ifAny x in (folder "Staff") $}
<h1>Our Staff</h1>
...
{$ endIf $}

Joel Finkel
Tuesday, February 11, 2003

I haven't tried this, but I think it would work:

Create an article named "StaffList" that just contains your query. Something like:
{$ foreach x in (folder "Staff") $}{$x.headline$}<br>{$next$}

Then on your "Our Staff" page, you can test whether the list is empty:
{$ foreach x in (filename "StaffList") $}
{$ if nonblank x.body $}
-- put your table header here --
{$ endif$}
{$ next $}

As long as you only have one article named "StaffList", you'll only get one table header.

Now you can have your normal table body stuff below that:
{$ foreach x in folder("Staff") $}
...
{$ next $}

As I said, I haven't tried it, but I think it will work. Please let me know if this helps!

Darren Collins
Tuesday, February 11, 2003

Darren,

That was a real sweet suggestion, but it does not work.  I think this is because the resulting x.body is not fully empty.  It contains a comment, which is placed there by the code generator.

Really clever, though!

-Joel

Joel Finkel
Wednesday, February 12, 2003

Did you try adding the CityScript to the body of the article in HTML mode instead of Normal mode? Possibly Normal mode is adding <p></p> tags or something, which makes the Body non-empty. Make sure there's no spaces or carriage returns around the CityScript, too.

I still haven't had a chance to try this myself, but if I can get it to work, I'll post back here.

Darren Collins
Wednesday, February 12, 2003

My experience with the empty-check on the body was that it didn't work. Don't know why and how though.

Adriaan van den Brand
Thursday, February 13, 2003

Folks,

This should be a fairly simple addition to the product, and will make it much more robust.

It would also be nice to have local loop variables, (counters, for example), and simple arithmetic.  This would help us output tables with alternate rows being shaded, for example.

Thanks.

Joel Finkel
Thursday, February 13, 2003

OK, I've had a chance to test this method, and it does work.

First, you have to use different variables for the two CityScript loops in the two articles (foreach x and foreach y, say).

Then, you have to make absolutely sure the StaffList article's body doesn't contain any extraneous stuff. I did this by putting the whole CityScript loop on one line. I also typed it in HTML mode, and made sure there were no trailing spaces or anything. If you don't do this right, it won't work.

The "if nonblank" trick then worked as expected.

If you have any trouble, let me know and I'll help you out.

Darren Collins
Thursday, February 13, 2003

A good while ago Adrianne showed us this little javascript to count articles:

<SCRIPT language=javascript><!--
var tmp = "{$ foreach x in (all) $}.{$ next $}";
if (tmp.length==0)
{
document.write(" currently no articles on this site.<br>");
} else
{
document.write("currently ",tmp.length," articles on this site.<br>");
}
//--></SCRIPT>

Maybe there's a pony in there someone for someone more clever than me.

tk
Thursday, February 13, 2003

Darren,

An elegant solution to an inelegant problem.  By the way, as I expected, one can use the same loop variables because the page generation for the two pages is not done in the same namespace.  A dependency tree must be built, or the pages must be being generated on a depth-first basis.

I think what I was missing when I tried it was ensuring that everyting was on a single line.  I think the parsers and page generators need some work. 

Thanks!

-Joel

Joel Finkel
Sunday, February 16, 2003

I believe I have a solution that doesn't require any post processing in Javascript.

{$ foreach 1 x in (folder "Staff") $}
    Some header
    {$ foreach s in (folder "Staff") $}
        {$ s.headline $}
        blah blah blah
    {$ next $}
{$ next $}

I'll be putting this into use on my site http://michaelw.net.
I'll aso be using a variation of this combined with dates to group my articles by day.

Michael Winser
Sunday, February 16, 2003

Michael wins the case of beer.

Joel Finkel
Thursday, February 20, 2003

I don't think it works in CityScript:

http://discuss.fogcreek.com/CityDesk/default.asp?cmd=show&ixPost=4357&ixReplies=5

tk
Thursday, February 20, 2003

Yes, Michael's code does work.  In fact, in can be used to implement an ElseIf statment in a VERY weird way.

I want to create SINGLE link to a SINGLE article if it exists in one folder.  Otherwise, I want to create a list of articles found in another folder.

<!-- Create a link to the SINGLE file if it is there -->
{$ foreach 1 y in (folder "Newsletter/PrimaryFile") $}
    {$ if nonblank y.body $}
    <a href="{$y.link$}" >{$y.headline$}</a>
    {$ endif $}
{$ next $}


<!-- Create links to all the other files -->
{$ foreach x in (folder "Newsletter/Articles") $}

    <!-- If the SINGLE file exists, output a "begin comment" -->
    {$ foreach 1 y in (folder "Newsletter/PrimaryFile") $}
    <!--
    {$ next $}

    <a href="{$x.link$}">{$x.headline$}</a>

    <!-- If the SINGLE file exists, output a "end comment" -->
    {$ foreach 1 z in (folder "Newsletter/PrimaryFile") $}
    -->
    {$ next $}

{$ next $}


Of course, this is a quick and very dirty kludge.  What we should have is:

{$ ifAny z in (folder "Newsletter/PrimaryFile") $}

    {$ foreach 1 x in (folder "Newsletter/PrimaryFile") $}
        <a href="{$x.link$}" >{$x.headline$}</a>
    {$ next $}

{$ else $}

    {$ foreach x in (and (folder "Articles")(filename "Newsletter")) $}
        <a href="{$yx.link$}" >{$x.headline$}</a>
    {$ next $}

{$ endIf $}

It might be worthwhile to base the page generator on an established scripting language, such as Tcl or Javascript that would have these constructs built in.

Joel Finkel
Friday, February 21, 2003

My "else" clause in my ifAny example, above was incorrect.  It should read:

{$ ifAny z in (folder "Newsletter/PrimaryFile") $}

    {$ foreach 1 x in (folder "Newsletter/PrimaryFile") $}
        <a href="{$x.link$}" >{$x.headline$}</a>
    {$ next $}

{$ else $}

    {$ foreach x in (folder "Newsletter/Articles) $}
        <a href="{$yx.link$}" >{$x.headline$}</a>
    {$ next $}

{$ endIf $}

Joel Finkel
Friday, February 21, 2003

*  Recent Topics

*  Fog Creek Home