Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
#289 2016-04-04 01:25:13
- lazlo
- Member
- Registered: 2004-02-24
- Posts: 110
Re: etc_query: all things Textpattern
Hey Oleg
Hoping you can help me out again as the <!— alpha list A-Z —> works wonderfully for the “Title” field. In my case I use it for both an Book Title List and an Author List. These articles have alternative titles that exist in a custom field, in one case it is <txp:custom_field name=“Contributor_Full_Name_Reversed” />
For example your following code works for the “Title” field
<!-- alpha list Author display A-Z-->
<txp:etc_query wraptag="ul" class="pull-right breadcrumb" break="li" name="alphalist"
data="SELECT DISTINCT UPPER(SUBSTRING(Title,1,1)) AS alpha FROM textpattern WHERE Status = 4 AND Section = 'authors' ORDER BY alpha"
>
<a href="<txp:site_url /><txp:section />/?alpha={alpha?}">{alpha?}</a>
</txp:etc_query>
<!-- output alphalist and get articles ids when necessary -->
<txp:etc_query globals="_GET" data='<txp:variable name="alphalist" />'
query="//a[text() = '{?alpha|A}']"
replace="&=<span class='active'>{?alpha|A}</span>"
>
{//ul}
<txp:etc_query name="ids" break=","
data="SELECT ID FROM textpattern WHERE UPPER(SUBSTRING(Title,1,1)) = '{?alpha|A}' AND Status = 4 AND Section = 'authors' ORDER BY Title" />
<txp:else />
<txp:variable name="alphalist" />
</txp:etc_query>
<!-- End alpha list -->
I want to use adi_gps to search display the contents of this field <txp:custom_field name=“Contributor_Full_Name_Reversed” /> instead of title.
If my GET was now ?lastfirstalpha do I replace all instances of ?alpha in the above code with ?lastfirstalpha and how do search the custom field itself as it doesn’t seem to be as simple as replacing the “Title” field variable.
Offline
#290 2016-04-04 14:44:09
Re: etc_query: all things Textpattern
Hey Leslie
lazlo wrote #298483:
If my GET was now ?lastfirstalpha do I replace all instances of ?alpha in the above code with ?lastfirstalpha and how do search the custom field itself as it doesn’t seem to be as simple as replacing the “Title” field variable.
Yes, replace alpha
with lastfirstalpha
everywhere, and replace Title
with custom_n
, where n
is the internal number of your Contributor_Full_Name_Reversed
cf (as set in Admin/Advanced). This should give you an alphabetic list populated from Contributor_Full_Name_Reversed
values.
Offline
#291 2016-04-05 06:28:14
- lazlo
- Member
- Registered: 2004-02-24
- Posts: 110
Re: etc_query: all things Textpattern
etc wrote #298486:
Hi Oleg
I think I have to ask this question a different way.
I wanted to have a menu link:
http://kl.rs/authors/?alpha (which would do the A-Z based on Title)
http://kl.rs/authors/?alphaLN (which would do the A-Z based on Contributor_Full_Name_Reversed)
I can’t seem to create an If “?alpha” do this or If “?alphaLN” do that statement with adi_gps.
I think I misunderstood how adi_gps works, and it does not do what I had hoped.
adi_gps can do If “?alpha=B” do this or If “?alpha=C” do that, just fine but that doesn’t help me.
Is there a simpler way (most likely?) for me to accomplish this?
I approaching the menu link method incorrectly altogether?
Any insight would be appreciated.
Last edited by lazlo (2016-04-05 06:28:59)
Offline
#292 2016-04-05 07:41:20
Re: etc_query: all things Textpattern
Ah, I misunderstood it, sorry. If you want to keep to empty http://kl.rs/authors/?alpha
format, neither ect_query
nor adi_gps
will detect ?alpha
switch, but you can do it php-way:
<txp:variable name="alphaset" value='<txp:php>echo isset($_GET["alpha"]);</txp:php>' />
<txp:if_variable name="alphaset" value="1">
... alphalist construction ...
<txp:else />
... something else ...
</txp:if_variable>
And if you don’t want to output A
-articles by default, replace {?alpha|A}
with {?alpha}
in the alphalist construction. Same thing with alphaLN
. Does it help?
Offline
#293 2016-04-05 23:17:51
Re: etc_query: all things Textpattern
Great plugin.
XPath is hard, but it brings great possibilities. One is to let the clients to manage add some simple markup (ie. via Textile) and convert it into “complex” HTML transparently.
Here is a tip:
suppose you have a website built with Bootstrap. The markup for a navbar that include dropdowns can be usually done with nested ul
s and some extra classes. Your client asks to have fine-control over the items shown on the navbar. Those items could be links to sections or links to articles, or links to categories, or links to wherever they want to.
But, then, you would prefer not to give them access to forms and page templates, nor to tinker with complex HTML structures.
You could use mck_snippet to create a Textile snippet were your client could easily add/remove/edit navbar items.But the problem are usually the extra classes needed on each ul
, li
and a
elements that make the navbar. Yes, you could have them all on Textile too, but the Textile markup could become rapidly unmanageable/unreadable for someone non-tech-savvy.
So, mck_snippet alone won’t do it. That’s when etc_query gets into scene.
For this tip to work we need mck_snippet, etc_query and rah_function (optional, if you want current navbar item highlighted with class .active
).
Let’s begin simple.
// "news_menu" snippet (managed via mck_snippet) using Textile.
* "News":/news
** "Blog":/blog
** "Videos":/videos
** "Photos":/photos
As you know, that Textile code will output a simple ul/li/a
structure. Nothing fancy.
Now we need to add all the needed classes to create the markup used by Bootstrap on navbars with dropdown.
// Somewhere (usually at the top) on your page template.
<txp:hide>
First, we create a variable that contains the full page URL (ie. http://www.example.com/news) for the page currently viewed.
This is only necessary if you want to have the navbar item for the current URL to be marked with an class="active".
It will also add the class the top parent item (News, in this example).
</txp:hide>
<txp:variable name="full_page_url"><txp:rah_function call="rtrim" string="/"><txp:site_url /></txp:rah_function><txp:page_url /></txp:variable>
<txp:hide>
Here, we take the full_page_url variable we just created and parse it to extract any query string that it may have.
</txp:hide>
<txp:php>
global $variable;
// This returns the URL path (/some-section/ or /some-section/some-article)
// without any query string and stores it in a txp:variable named "url_path"
$variable['url_path'] = parse_url($variable['full_page_url'], PHP_URL_PATH);
</txp:php>
<txp:hide>
This is a variable I create to keep etc_query code cleaner. It just adds a clickable triangle (▼)
next to the parent item (News, in this example) to trigger the dropdown.
This is an adaptation I did to the BS navbar, as I wanted the parent item
to be a clickable link, so I added this separately.
</txp:hide>
<txp:variable name="dropdown-toggle"><a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">▼</a></txp:variable>
// Somewhere inside your navbar template.
<txp:hide>
Finally, we process our mck_snippet through etc_query.
</txp:hide>
<txp:etc_query
data='<txp:mck_snippet title="'news_menu" />'
query='ul/child::li'
replace='
.@@class=nav-item dropdown;
./a@@class=nav-link;
<txp:if_individual_article>
./a[starts-with(@href, "/<txp:section />")]/ancestor::li@@class={concat(@class," active")};;
</txp:if_individual_article>
./a$=<txp:variable name="dropdown-toggle" />;
//ul@@class=dropdown-menu;
.//li@@class=dropdown-item;
//a[@href="<txp:variable name="url_path" />"]/ancestor::li@@class={concat(@class," active")};
'
/>
Yes, the code make look a bit complex at first (and it certainly is, as XPath is a bit complex by itself). But that etc_query snippet has all the necessary replacements to create the desired markup.
The output will be the following, when visiting the Blog section.
<li class="nav-item dropdown active">
<a href="/news" class="nav-link">News</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">▼</a>
<ul class="dropdown-menu">
<li class="dropdown-item active"><a href="/blog">Blog</a></li>
<li class="dropdown-item"><a href="/videos">Videos</a></li>
<li class="dropdown-item"><a href="/photos">Photos</a></li>
</ul>
</li>
So, as you can see, you go from simple Textile markup that your clients can easily type (with minimal risk of typos or erros) to a complex HTML markup.
You may have noticed that there is no <ul>
element wrapping the output. That’s because I left that out (via the query='ul/child::li'
attribute on @etc_query). That way, you can decide were to put that snippet on your navbar.
See next post with a new tip that will help you better understand what I mean.
Offline
#294 2016-04-05 23:18:37
Re: etc_query: all things Textpattern
See previous post to understand what we are doing on this post.
So now you have a way to let your clients manage their navbars, without the need for them to put a finger on the templates (risking breaking all your work ;) nor writing complex Textile/HTML.
Following the previous example, you want to let your client manage a few parts of the navbar. Let’s say the News subnavbar, the Product subnavbar and the About subnavbar
But repeating the above etc_query code for each sub-part of the menu you want to create is a bit non-DRY.
Let’s fix that with the help of <txp:output_form> and <txp:yield />.
// Your navbar code (in a form or in a page template).
<ul class="navbar">
<txp:output_form form="dropdown-generator">
<txp:mck_snippet title="about_menu" />
</txp:output_form>
<txp:output_form form="dropdown-generator">
<txp:mck_snippet title="product_menu" />
</txp:output_form>
<txp:output_form form="dropdown-generator">
<txp:mck_snippet title="news_menu" />
</txp:output_form>
<!-- Some hardcoded item that you don't want the client to touch. -->
<li class="nav-item"><a href="#">Lorem ipsum</a></li>
</ul><!-- .navbar -->
As you can see, we call the same form (dropdown-generator
), passing a different mck_snippet
to each call. That mck_snippet is the <txp:yield />
that you will see on the next snippet. Yes, it’s like calling the same function a few times, passing a different parameter each time.
// Our "dropdown-generator" form
<txp:etc_query
data='<txp:yield />'
query='ul/child::li'
replace='
.@@class=nav-item dropdown;
./a@@class=nav-link;
<txp:if_individual_article>
./a[starts-with(@href, "/<txp:section />")]/ancestor::li@@class={concat(@class," active")};;
</txp:if_individual_article>
./a$=<txp:variable name="dropdown-toggle" />;
//ul@@class=dropdown-menu;
.//li@@class=dropdown-item;
//a[@href="<txp:variable name="url_path" />"]/ancestor::li@@class={concat(@class," active")};
'
/>
That’s all. We “abstracted” the etc_query snippet, making it reusable. DRY FTW.
Offline
#295 2016-04-06 02:00:56
Re: etc_query: all things Textpattern
This looks like a great idea for a Textpattern Tip, Julián!
Offline
#296 2017-06-02 19:28:30
Re: etc_query: all things Textpattern
Dear etc_query and XPath wizards. I have a bug in my ect_query template, causing it to return nothing when I want it to return something. Here are the details.
Can anyone here offer any guidance?
Last edited by johnstephens (2017-06-02 19:29:01)
Offline
#297 2017-06-05 21:20:32
Re: etc_query: all things Textpattern
I found a solution [posted here].
I expected that using etc_query for search-and-replace would behave like a regular expression, and the original text would return even when it doesn’t contain the search pattern. I could not figure out how to do that with etc_query by itself, but I do know how to use Textpattern’s if_variable tag.
Offline
#298 2017-06-14 16:25:20
Re: etc_query: all things Textpattern
How can I avoid having my self-closing XHML-tags transformed into unclosed tags?
I’ve noticed that etc_query converts self-closing tags like <br />
and <img src='…' />
in my data into unclosed tags, and I don’t know how to fix it.
I’m using the latest stable versions of Textpattern (4.6.2) and etc_query (1.3.3), and I’ve tested this on different installations, and even disabled all other plugins.
Here’s a simple page template I used to test it:
<txp:variable name="content">
<div>
<h1>Hello world</h1>
<style>h1 { font-family: Helvetica; }</style>
<img src='nonexst' />
<p>Hello, <br />this is world</p>
</div>
</txp:variable>
<txp:etc_query data='<txp:variable name="content" />' replace="//@style" />
Despite making sure the br
and img
elements are properly closed in the data, etc_query transforms it them into unclosed tags, like this:
<div>
<h1>Hello world</h1>
<style>h1 { font-family: Helvetica; }</style>
<img src="nonexst"><p>Hello, <br>this is world</p>
</div>
This might be no problem if I was just sending content to the browser, but this site requires strict XHTML markup for output in other formats.
Is there any way to nudge etc_query to return my content without stripping the /
from self-closing tags?
Offline
#299 2017-06-15 07:37:17
Re: etc_query: all things Textpattern
Hi @johnstephens and sorry, I was absent for a moment. Have you tried to call etc_query
with markup="xml"
attribute? But then the source must be XML-valid too.
Offline
#300 2017-06-15 12:07:05
Re: etc_query: all things Textpattern
etc wrote #305970:
Hi @johnstephens and sorry, I was absent for a moment. Have you tried to call
etc_query
withmarkup="xml"
attribute? But then the source must be XML-valid too.
Thank you, @etc. I somehow missed this. It appears to solve the problem! I’ll do some more testing later today.
Thank you so much!
Offline