Jump to content

How to set text line/character limits in templates?


photoman355

Recommended Posts

I'm sure the answer is fairly simple but I was wondering if there's an easy way to define the number of lines for a textfield in a template.  I know you can set size limits for images fairly easily using $image->size(100, 100); but wondered if there was the equivalent for text?  

Link to comment
Share on other sites

Assuming you mean the Admin side then it's nice and easy, just check the Input tab of the field in question and you'll see 'Rows' :)

My advice = DOH!

Edited by alanfluff
Link to comment
Share on other sites

Greeting photoman355,

This is not built into ProcessWire by default.  However, there are a couple of nice ways to add it.

I'm using a module in my sites that counts the entered characters, and disallows more than the set number of characters.

Here are the links:

Forum discussion: http://processwire.com/talk/topic/2343-char-counter-for-texttextarea-fields/

Module page: http://modules.processwire.com/modules/textarea-counter/

In the forum discussion, you will see both the module created by boundaryfunctions, and another concept by Soma.

One of these will work for you!

Thanks,

Matthew

Link to comment
Share on other sites

I think you mean something like this:

function wordLimiter($str, $limit = 120, $endstr = '…'){
    $str = strip_tags($str); 
    if(strlen($str) <= $limit) return $str;
        
    $out = substr($str, 0, $limit);
    $pos = strrpos($out, " ");
    if ($pos>0) {
        $out = substr($out, 0, $pos);
    }
    return $out .= $endstr;
}

echo wordLimiter($page->body);
  • Like 5
  • Thanks 1
Link to comment
Share on other sites

Hmm...not as simple as I thought.  

@alanfluff Thanks I knew about the admin side limits but the problem with adding a limit to a field is that you have to create a separate field for each size of text you need. So for example if I was reusing <?=$page->body?> multiple times the text limits would have to be the same.

@MatthewSchenker I had a read of the forum, really useful module.  In this case I can't use it as it uses the same way as Alan's method to set the limit. 

@Soma This is exactly what I was after, many thanks. I noticed you wrote this as a function.  I take it this is pulled from a functions.php file much in the same way as wordpress? To save writing lots of code this makes a lot of sense.  If I wanted to apply the function to say the $page->body tag would I use a get call first or is there a better way?

Link to comment
Share on other sites

Yes helper functions like this can be included using a separate php like in the head.inc and used throughout your templates.

I extracted this function from a module I have for a project. This module has various helper function and then I load it in the templates. It's much the same as if I would include a php with functions and just personal preference.

For example:

$helpers = $modules->get("TemplateHelpers");

then use it like this where I need it.

echo $helpers->wordLimiter($page->body);

I'm not sure what you mean by applying the function to the body. I use this function to create teaser texts that are limited, and show the complete body only on the detail page.

Of course you could modify the body output, that every time you do an echo $page->body, it will run it through a function, but I'm not sure this is a good practice.

This using a hook on the formatValue of textfields would do it: (directly in template like a include, or by making it a module)

function wordLimiter(HookEvent $event){
    $field = $event->argumentsByName('field');
    if($field->name != 'body') return;
    $str = $event->return;
    $limit = 150;
    $endstr = ' …';
    $str = strip_tags($str);
    if(strlen($str) <= $limit) return;
    $out = substr($str, 0, $limit);
    $pos = strrpos($out, " ");
    if ($pos>0) {
        $out = substr($out, 0, $pos);
    }
    return $event->return = $out .= $endstr;
}

wire()->addHookAfter("FieldtypeTextarea::formatValue", null, "wordLimiter");

// now this will trigger the above hook
echo $page->body;

But it's a little cumbersome, as you can't set the limit. Also this strips tags and on HTML text you'll lose formatting. But just to show adn example what is possible.

From your post I guess you like to do something like:

echo $page->body->limit(150); // not possible

It's not possible to do this, because the $page->body, body is just a string and not an object you could add methods to it.

But something like the following would be possible using hooks.

echo $page->wordLimiter("body", 120);

You can use addHook to add a method wordLimiter to page:

function wordLimiter(HookEvent $event){
    $field = $event->arguments[0]; // first argument
    $limit = $event->arguments[1];
    $endstr = isset($event->arguments[2]) ? $event->arguments[2] : ' …';
    $page = $event->object; // the page
    $str = $page->get($field);

    $str = strip_tags($str);
    if(strlen($str) <= $limit) return;
    $out = substr($str, 0, $limit);
    $pos = strrpos($out, " ");
    if ($pos>0) {
        $out = substr($out, 0, $pos);
    }
    return $event->return = $out .= $endstr;
}

// this will add a custom method to Page object
wire()->addHook("Page::wordLimiter", null, "wordLimiter");

// now you can do this
echo $page->wordLimiter("body", 100);

// or this
echo $page->wordLimiter("summary", 100);
  • Like 10
Link to comment
Share on other sites

  • 1 year later...

Did I dream this or is something like this now part of the core in the dev branch?

Not really....see Ryan's mini-tut here: http://www.flamingruby.com/blog/processwire-weekly-13/#1-2

You can easily do this using CKEditor's Wordcount plugin... ;)

Edit:

Misread first post. Disregard my post.

Edited by kongondo
Because I am an idiot :-)
  • Like 1
Link to comment
Share on other sites

Not really....see Ryan's mini-tut here: http://www.flamingruby.com/blog/processwire-weekly-13/#1-2

You can easily do this using CKEditor's Wordcount plugin... ;)

I think, the others are talking about limiting the output of a field. This plugin only counts words/chars inside of CKEditor.

Did I dream this or is something like this now part of the core in the dev branch?

@Pete: where did you found this..?

Link to comment
Share on other sites

  • 1 year later...

@Soma Your code seems to do the work, but does have a little issue. If you use line break or have several paragraphs, it stacks the whole text into one big mess. I have a list in one of my news stories with names on each line. This way it messes up the content quite well :/ Any workarounds for this?

Link to comment
Share on other sites

You should strip or rip the tags before using the output with a text formatter or direct in the template...

/**
 * Wordlimiter cuts a textarea only after complete words not between
 * used in admin.php for seo function and in some templates
 */
function wordLimiter($str = '', $limit = 120, $endstr = '...'){
	if($str == '') return '';
	if(strlen($str) <= $limit) return $str;
	$out = substr($str, 0, $limit);
	$pos = strrpos($out, " ");
	if ($pos>0) {
		$out = substr($out, 0, $pos);
	}
	$out .= $endstr;
	return $out;
}

/**
 * Alternative with regex for striptags function
 * used in admin.php for seo function and in some templates
 */
function ripTags($string) {
    // ----- remove HTML TAGs -----
    $string = preg_replace ('/<[^>]*>/', ' ', $string);
    // ----- remove control characters -----
    $string = str_replace("\r", '', $string);    // --- replace with empty space
    $string = str_replace("\n", ' ', $string);   // --- replace with space
    $string = str_replace("\t", ' ', $string);   // --- replace with space
    // ----- remove multiple spaces -----
    $string = trim(preg_replace('/ {2,}/', ' ', $string));
    return $string;
}

//usage in template like
$default_desc = ripTags($page->shorttext);
$default_desc_out = wordLimiter($default_desc, 160);
//or short
$default_desc = wordLimiter(ripTags($page->shorttext), 160));

regards mr-fan

Link to comment
Share on other sites

@mr-fan, I guess I'm doing something wrong here:

$default_desc = wordLimiter(ripTags($page->body), 160));

I'm trying to output the body elements of several childpages. Something I'm missing here? I got all the other code in the page too, and it runs through, yet no output.

Link to comment
Share on other sites

@mr-fan Soma's solution does already strip tags. 

@Olli like LostKobrakai wrote somas code is complete and use striptags PHP function.

Please provide more information. Have you debug mode on? Have you tried it with only wordLimiter($page->body, 160); ? and/or only ripTags($page->body); ?

regards mr-fan

Link to comment
Share on other sites

  • 1 month later...
  • 1 year later...
On 11.1.2016 at 12:08 PM, Olli said:

@Soma Your code seems to do the work, but does have a little issue. If you use line break or have several paragraphs, it stacks the whole text into one big mess. I have a list in one of my news stories with names on each line. This way it messes up the content quite well :/ Any workarounds for this?

I have searched for a solution. I would shorten the text from my blog entries. This seems to work for me. It keeps the html tags from the editor:

function truncateHtml($text, $length = 100) {
    $current_size = strlen($text);
    $diff = strlen($text);
    $remainder = $current_size - $length;
    while($diff > 0 AND $remainder > 0) {
        $pattern = "/(.*)[^<>](?=<)/s";
        $text = preg_replace($pattern, "$1", $text);
        $diff = $current_size - strlen($text);
        $current_size = strlen($text);
        $remainder = $current_size - $length;
    }
// iff $diff == 0 there are no more characters to remove
// iff $remainder == 0 there should removed no more characters
    return $text;
}

It's from here: https://stackoverflow.com/questions/38548358/cut-html-input-while-preserving-tags-with-php

Post Number 4.

  • Like 1
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
×
×
  • Create New...