Jump to content

Text in place of URLs


NoDice
 Share

Recommended Posts

I am sure I have missed something REALLY basic here, but I still have to ask since I have not figured this out. 

If I am to insert an URL and I want to have a text display in its place, how is that accomplished using the URL-field. IE, how do I achieve this basic URL-function:

<a href="http://www.xxyyzz.com">The text I want to show in place of the URL</a>

?

I would have expected that to be a standard choice for the URL-field, but can't seem to find it so I must have missed something. Sorry for what I assume is a dumb question. 

Also, if I wanted to achieve this (url with alternate text) by just using tinymce, would that be possible? Would I need hanna code for that (and how would that be formulated in that case)?

Link to comment
Share on other sites

URL field only stores URL's, while what you're talking about here is HTML link tag and it's value. These are different things:

To achieve what you've described above I would suggest using textarea field with TinyMCE enabled (or without TinyMCE, if you prefer to write your tags as pure HTML yourself.) Other option would be storing URL in an URL field and text within text field -- ie. using two fields and outputting them like this in your template:

<a href="<?php echo $page->my_url_field; ?>"><?php echo $page->my_text_field; ?></a>

The best solution here, of course, depends a lot on where and how you want to use these values.

  • Like 2
Link to comment
Share on other sites

URL field only stores URL's, while what you're talking about here is HTML link tag and it's value. These are different things:

To achieve what you've described above I would suggest using textarea field with TinyMCE enabled (or without TinyMCE, if you prefer to write your tags as pure HTML yourself.) Other option would be storing URL in an URL field and text within text field -- ie. using two fields and outputting them like this in your template:

<a href="<?php echo $page->my_url_field; ?>"><?php echo $page->my_text_field; ?></a>

The best solution here, of course, depends a lot on where and how you want to use these values.

OK, thanks my fellow Nordic PW:er to the east for coming with a prompt reply again! 

I had those workarounds figured, but I have to say that it kind of surprises me that this is not a standard option of the predefined url-field since it would seem to me that more strict markup related things are included in other field types by default, such as the possibility to set heading type with tinyMCE. 

What I want to do is have the possibility to add a couple of links (4 max) to the end of a news post area. The links will therefore be part of a news article template with pictures and such. 

The problem of the first approach is - of course - that I wan't people with no knowledge of HTML to be able to input the url and the text in a simple and understandable way (hence not HTML). That is one of the major reasons I am putting in the effort of adopting a CMS structure. 

The problem with the second approach, as far as I can tell, is that I will have to write more complex php to have the markup links only be included in the markup if I have links/text written in (and only for the number that I do, normally less than the possible four) - but not included if I do not - if I want the page to work. Otherwise I will end up with 1-4 missing links I have not filled them all out, which will be the normal case.   

Once again, to me it appears that this is such a standard URL-field feature (and one you want to give the casual site administrator control over), that one could argue it would make sense to have the option to include the text in the field setup (but I am still a rookie so maybe I have just not seen the principal reason why this would not be right). 

Link to comment
Share on other sites

In your case I would use a repeater with a url field and a text field. People can add as many links as they want and it's clear what goes where. On the template you just have to do:

foreach($page->links as $link) {
    echo "<a href='<?php echo $link->my_url_field; ?>'><?php echo $link->my_text_field; ?></a>";
}

or, maybe better:

if(count($page->links)) {
    echo "<ul class='links-list'>";
        foreach($page->links as $link) {
            echo "<li><a href='<?php echo $link->my_url_field; ?>'><?php echo $link->my_text_field; ?></a></li>";
        }
    echo "</ul>";
}
  • Like 3
Link to comment
Share on other sites

Also, maybe there is no problem with empty links here since nothing will be added to the markup if they are empty. I have been working on a similar problem where I get unwanted empty list items, so I may have been confusing matters a little. I may make a separate post about that when time arises. Will do some more testing - in the meantime, thanks so much for your replies!

Link to comment
Share on other sites

I had those workarounds figured, but I have to say that it kind of surprises me that this is not a standard option of the predefined url-field since it would seem to me that more strict markup related things are included in other field types by default, such as the possibility to set heading type with tinyMCE. 

...

Once again, to me it appears that this is such a standard URL-field feature (and one you want to give the casual site administrator control over), that one could argue it would make sense to have the option to include the text in the field setup (but I am still a rookie so maybe I have just not seen the principal reason why this would not be right). 

I agree with you in that having a text would be standard behavior -- for HTML hyperlink. It's very important to note that HTML hyperlinks created using the "a" element are separate entities from URLs.

There are many use cases for an URL, so it wouldn't really make much sense to add an option for additional content that's related to only one of those. Repeater method described by @diogo is probably the best way to put things like these together.

Another method (probably overkill for most use cases) would be creating a new fieldtype + inputfield for a hyperlink element. There one would definitely expect to be able to fill in text content (and other parameters too, as described by the HTML language reference I linked to earlier.)

I would also like to point out that ProcessWire fields (fieldtypes) very rarely generate any markup. TinyMCE is an input method (inputfield) that generates markup and stores it in textarea fieldtype. Even in that category markup generating inputs are, in my opinion at least, quite rare.

  • Like 2
Link to comment
Share on other sites

I will soon have to create a link list fieldtype, where you could add links with url and text, internal and external. I'm surprised nobody done that yet, as it seems a basic feature a CMS should have. I've used repeaters until now and it's ok I guess too, but maybe a dedicated fieldtype would be nice. Another option is to use a Wysiwyg field as that would already allow for "easy" creating a list of links. Those are all very easy to setup option and flexible. But you know it's fun to develop for PW. Or anyone want to have a go or know if this would make sense at all?

  • Like 3
Link to comment
Share on other sites

I agree with you in that having a text would be standard behavior -- for HTML hyperlink. It's very important to note that HTML hyperlinks created using the "a" element are separate entities from URLs.

Absolutely, and you are right of course, I am talking about a tags, and the fact that I am surprised they are not part of the standard set of fields.

To me, that seems quite strange as I would imagine it is used quite often and since I see no super solid work around (where there really should not need to be one). 

Very grateful for the tips about repeater fields and such - will look into those and try to decide if they will suit my needs. I certainly think they may be the ticket for my other problem but since I have not worked with php before, I have to figure out how to achieve what I am after there. In fact, I'll tell you how I have it set up now and what I am after, and see if you have any views on how the best deal with the problem. 

I have a slider/carousel set up with caption texts tied to the respective slides that I format to overlay the slides.

The slider employs the typical basic unordered list structure. 

My first hand preference would be to have one admin page for the slider so that I can see all the thumbnails for the slides in one page, so whomever is administrating the slider does not have to go into several pages just to check the order of the pictures and such. IE to not use child pages as I assume would be the normal goto solution for PW. 

The text needs to be clearly tied to each slide so the way I have done that now is to make 10 numbered instances each of every field (image, heading, caption text) to be able to put them all in one template that I then use as a basis for a hidden page. 

I have also created 10 li objects with the right php-urls for the content, but the major drawback is that as things stand, I have to go in and comment and uncomment the pre-prepared but sometimes unused li items (when I have fewer slides than 10).

The li objects also have classes set for styling purposes. 

Naturally, the need to mess with the html in the template file is not desired, but that's where I am at now. 

The question is if anyone has a good idea on how to achieve the desired result with only one admin page where I can add more slides that would also generate correctly formatted li objects with classes and links to the new picture, heading, text? So, are repeaters the thing I need here as well? 

If I could get it the way I really want, having the possibility of adding one link per slide, with text description, would be great here as well (so once again, a generic a tag field would have rocked). 

Hope you understand what I am after, but please ask if you want me to provide more details or code snippets. 

Cheers from a hot and beautiful Sicily! 

Link to comment
Share on other sites

Hi NoDice,


this sounds for a use of Repeaters. Instead of creating 10 fields, you only need to create 1 field of each (image, caption, url) and create one repeater field that contains them.

Afterwards you can create as much instances of the repeater as you need. In your case you also should add a checkbox field for enabled/disabled, I assume.

As you already have much fields, you can start with enabling the repeater under SETUP-Modules if it isn't already. (Its a core-module but disabled by default)

Then create a repeater field and assign your desired fields (one of each type).

Last, add the repeater to your template.

voila!

  • Like 2
Link to comment
Share on other sites

@NoDice: this sounds like a perfect match for repeaters.

First you'll create the fields you need; one URL field for link href ("link"), one text (or textarea, if you need longer texts) for your description texts ("description") and one image field for your slideshow images ("image", limited to one image per field).. and also one repeater field (let's call it "slideshow" for this example) that you'll configure to hold all the fields mentioned here.

After that you'll insert the code, which would work just as @diogo mentioned earlier:

<?php
if (count($page->slideshow)) {
    echo "<ul>";
    foreach ($page->slideshow as $item) {
        $thumb = $item->image->size(600,250);
        echo "<li style='background-image: url({$thumb->url})'><a href='{$item->link}'>{$item->description}</a></li>";
    }
    echo "</ul>";
}
?>

I'm making some assumptions about what the markup for your slideshow is like, don't worry about that; you should be quite easily able to adapt above example for your specific needs.

  • Like 3
Link to comment
Share on other sites

... I've used repeaters until now and it's ok I guess too ...

Some people probably prefer to have more (and more specific) field types, while others (like me) prefer more basic building blocks that can be combined on case-by-case basis to make hyperlinks or whatever else is needed. Repeaters are a great way to achieve this.

  • Like 1
Link to comment
Share on other sites

OK team, I finally had time to start work on the repeaters and have got things going as far as displaying the links just the way I wanted.

What I have not been able to figure out is how to use the repeater-field I have created to be able to give news items more than one category per item. 

 I have also tried to follow this tutorial for the overall structure: 

http://wiki.processwire.com/index.php/Simple_News_System

But I have created a repeater field - repeater_news_category_01 -  consisting of the category field  news_category_01 to be able to add more than one category to a post.

I saw in another post that Ryan questioned the syntax in the wiki-tutorial above, and in case it is not good - it would be really nice to point that out for us newbies trying to get into this by using the available wikis and tutorials. 

Anyway, I have got the category list working, and the news item displaying the way they should, but I have not been able to figure out how to deal with the multiple categories. As things stand, the category pages show all news items (not only the ones associated with that category. 

Any pointers (including veiws on syntax in the tutorial or my adaptation) would be much appreciated. Here is the code I have now:

function newsList(){

	// Grab the page name from the url

	$thisCategory = wire("page")->name;

	// If the category is not called "news" then output the category name as a selector for the find.

		
		$category = "repeater_news_category_01.name=" . $thisCategory;
		

	// Get the news posts - limited to ten for later pagination

	$newsposts = wire("pages")->find("parent=/news_articles/, $category, template=news_01, limit=10");

	$out =" ";

	//Loop through the pages

	foreach($newsposts as $newspost){
		$out .="<div class='newsitem'>";
		if($newspost->news_image_01){
			$out .="<a href='{$newspost->news_image_01->url}' class=''>";
			$out .="<img class='align_left' src='{$newspost->news_image_01->size(100,100)->url}'>";
			$out .="</a>";
		}
		$out .="<a href='{$newspost->url}'><h3>{$newspost->title}</h3></a>";
		$out .="<p>{$newspost->summary_01}</p>";
		$out .="</div>";

		if (count($newspost->repeater_link_01)) {
			$out .="<ul class='links-list'>";
		foreach ($newspost->repeater_link_01 as $link) {
			$out .="<li><a href='{$link->link_01}'>{$link->text_01}</a></li>";
		}
		$out .= "</ul>";
}


	}
	// Pagination

	$out .="<div class='pagination'>";
	$out .= $newsposts->renderPager();
	$out .="</div>";

	echo $out;

}
 

Note that for now, I chose to remove most of the "not called news" part from the tutorial since it just gave me a missing definition of $category for the actual news page. Once again, what I am after is having the category links work so that they list only the category associated posts using my repeater as described above.  

Link to comment
Share on other sites

I saw in another post that Ryan questioned the syntax in the wiki-tutorial above, and in case it is not good - it would be really nice to point that out for us newbies trying to get into this by using the available wikis and tutorials. 

Most of the tutorials I've read, I've not been able to really understand how they work and end up getting lost trying to get through them. I don't think it's the fault of the tutorial–I've never been able to learn from tutorials of any sort. I learn by reading the docs and then tinkering with a working example... that's the only thing that seems to work for me. But I recognize that people learn in different ways, and many like tutorials. But I can't vouch for any tutorials I've not personally written. If anyone finds that any of the tutorials have errors or something that doesn't work, let me know what to fix. 

In your case, it sounds like you are now simply trying to manage categories. You don't need a repeater for this unless you need to define other fields together with the category. Chances are you would be better off not using a repeater and instead just using a Page reference field (perhaps with the asmSelect input). 

I'm also wondering about the naming, with items having "_01" at the end. That seems to imply that there might be a "_02" and a "_03", etc. This would be pretty unusual for field naming. Chances are you instead want a single "categories" multi-page reference field (which is the default behavior of the "Page" reference field). 

  • Like 1
Link to comment
Share on other sites

Thanks so much for taking the time to reply Ryan - and for putting this great product out there!

The repeater I used on the news item page template to be able ta associate a post with more than one category. How would I do that in a straightforward manner without a repeater? There is a lot I am not getting still so really very grateful for any nudges in the right direction.

The naming is just an easy way for me to recognize all the fields and templates I have created + it helps when you need a second text field etc.

Link to comment
Share on other sites

The repeater I used on the news item page template to be able ta associate a post with more than one category. How would I do that in a straightforward manner without a repeater? There is a lot I am not getting still so really very grateful for any nudges in the right direction.

Lets say you've got a structure like this:

/posts/

   /some-post/

   /another-post/

   ...and so on...

/categories/

   /plants/

   /fish/

   /birds/

Create a field called "categories" (or whatever you want to call it). On the "details" tab, make sure it says "Multiple pages - PageArray" for the type, which I think is the default. On the "input" tab, set the parent to be /categories/. Also on the "input" tab, choose "asmSelect" as the input field type (or if you prefer something other than asmSelect: checkboxes, select multiple or autocomplete). 

Add your "categories" field to your "post" template. Save. 

Now edit one of your pages below /posts/ and you should be able to select multiple categories. To output those categories on the front-end, you'd do this:

<h3>Categories</h3>
<ul><?php 
foreach($page->categories as $c) {
  echo "<li><a href='$c->url'>$c->title</a></li>";
}
?></ul>
  • Like 1
Link to comment
Share on other sites

Thanks Ryan - that did the trick and checkboxes was just what I was looking for, much better than repeaters!

Now I got the functionality all up and running with the multiple categories and all. The only problem remaining is an error code for missing variable ($category) on the main news page. The reason, from what I can gather, it only gets defined for when the page is not news.

As stated, everything is presented as expected (with all posts on the news page, and the right ones under the category links), but even after trying all kinds of else-combinations and such to set it for when the page actully is News - I can't make the error code go away. 

Here is the code:

function newsList(){
 
	// Grab the page name from the url
 
	$thisCategory = wire("page")->name;
 
	// If the category is not called "news" then output the category name as a selector for the find.
 
 	if($thisCategory !="news") {
		$category = "news_categories_01.name=" . $thisCategory; 
	} 

	// Get the news posts - limited to ten for later pagination
 
	$newsposts = wire("pages")->find("parent=/news_articles/, $category, template=news_01, limit=10");
 
	$out =" ";
 
	//Loop through the pages
 
	foreach($newsposts as $newspost){
		$out .="<div class='newsitem'>";
		if($newspost->news_image_01){
			$out .="<a href='{$newspost->news_image_01->url}' class=''>";
			$out .="<img class='align_left' src='{$newspost->news_image_01->size(100,100)->url}'>";
			$out .="</a>";
		}
		$out .="<a href='{$newspost->url}'><h3>{$newspost->title}</h3></a>";
		$out .="<p>{$newspost->summary_01}</p>";
		$out .="</div>";
 
		if (count($newspost->repeater_link_01)) {
			$out .="<ul class='links-list'>";
		foreach ($newspost->repeater_link_01 as $link) {
			$out .="<li><a href='{$link->link_01}' target='_blank'>{$link->link_text_01}</a></li>";
		}
		$out .= "</ul>";
}
 
 
	}
	// Pagination
 
	$out .="<div class='pagination'>";
	$out .= $newsposts->renderPager();
	$out .="</div>";
 
	echo $out;
 
}

Any suggestions from anyone? Please feel free to point out anything else that could be done in a better way. 

Link to comment
Share on other sites

Also, as promised, the update on the dynamic repeating banner is that it works great! Here is the code I ended up with there if it can help anyone:

<?php			if (count($pages->get("/header-banner/")->repeater_header_banner_01)) {    			echo "<ul class='slides'>";    				foreach ($pages->get("/header-banner/")->repeater_header_banner_01 as $banner) {        				echo "<li><img src='{$banner->header_banner_image_01->url}' alt=''><div class='banner_content'><div class='caption'><h2>{$banner->header_banner_heading_01}</h2>{$banner->header_banner_text_01}<a href='{$banner->link_01}' target='_blank'>{$banner->link_text_01}</a></div><div class='caption_description'>{$banner->header_banner_text_02}</div></li>";			}				echo "</ul>";			}		?>
The one problem I have left to solve are style issues from empty <a> and <p> tags when they are not used. What are the forums best ideas as far as solving that in a neat manner in a repeater contexts such as this? Checkboxes to add classes have come to mind, but perhaps there are better ideas out there?
Link to comment
Share on other sites

Check if the field is filed before outputting the tags. Here's one way of doing it:

// create a variable for each field that includes the html tags only if the field is populated
$link_text_01 = $banner->link_text_01 ? "<a href='{$banner->link_01}' target='_blank'>{$banner->link_text_01}</a>" : "";

// inside the echo replace the entire element by the variable

  • Like 2
Link to comment
Share on other sites

Check if the field is filed before outputting the tags. Here's one way of doing it:

Oh man, that is so great and simple, worked just like I wanted when implemented on all items! Thanks a ton - and sorry for not knowing even basic php! Starting to love this framework even without that knowledge though and your help is awesome.

  • Like 1
Link to comment
Share on other sites

Well, I hope so, and with this one, at least I could figure right away what was going on. I Still don't get how I can solve the problem with the missing variable in post #17 though, I guess that is just a missing else statement somehow, but I can't make it work (it outputs all I wan't but can't get rid of the error code). 

Link to comment
Share on other sites

What's the name of the page where this code is being used?

The title and heading is news and url is /news and all news items are displayed (which is what I want). When I click a category in the list, a new page with heading equal to the category is shown with only the news items tagged with that category listed.

So, everything works just the way I want, just get that undefined variable "category" warning on that main news page.

Another thing I have been having trouble with is getting a short version of the news-item list to be displayed on the home page. It does not seem to work with the same function. Could that be because of the wire-reference? Is there a way to change that to something more general in that case (so that you can use the function anywhere)? 

Link to comment
Share on other sites

Ok, as I thought, this code is the problem

$thisCategory = wire("page")->name;

if($thisCategory !="news") {
    $category = "news_categories_01.name=" . $thisCategory; 
} 
 

When you click a category in the list, the page is not called "news" anymore, so the $category variable is not set. That's why it's missing. You have to adapt the code so that the categories pages are also included on that if check.

--

On your second problem:

wire("page") holds the current page being viewed, so when you use it on the homepage, that's the page that will be called by it, and not "news" as you want. To correct this, you will have to change wire("page") by wire("pages")->get(1234), where 1234 would be the id of the "news page". That will work everywhere.

I'm not sure why you are using wire() in this code, but in case this is not a conscient decision, just wanted to clarify that wire('page') is the same as $page, and wire('pages') is the same as $pages.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...