Jump to content
bfncs

Char counter for text/textarea fields

Recommended Posts

Hi Matthew,

this shouldn't have anythind to do with the module itself, but you might try the following:

  1. Delete everything related to the module from your /site/modules folder.
  2. Use PHPMyAdmin or something similiar to look in the "modules" table of the database. Delete the entries named "TextareaCounter" or "TextAreaCounter".
  3. Delete all files starting with "Modules." from your /site/assets/cache folder (ah, forgot this at first post...)
  4. Install again as usual.

I haven't tested this in any way, but his hopefully helps.

Edit: Sorry to cause you problems with the rename, I just thought it would make more sense with the lowercase "a"...

  • Like 1

Share this post


Link to post
Share on other sites

Hi boundaryfunctions,

I'll try that.

Another thing is that, sometimes, for whatever reason, when I do an update to my JQuery/JS elements, they stop working for a little while, then work properly again at some point. It might be a cache thing, I don't know.

Thanks,

Matthew

EDIT: I cleared out the entry from my file server. Then in PHPMyAdmin I discovered that -- yes, in fact, there was an entry for "TextAreaCounter" in the "Modules" table. I deleted that, then installed the module as normal and it is working great now.

EDIT EDIT: I think this one can be moved from "wish list" to "done list."

Share this post


Link to post
Share on other sites

Tested here and works great! Thanks for making this Boundaryfunctions and Soma! I look forward to seeing this in the modules directory. This is a very useful module for sure.

Minor point, but longer term, I wonder about the hooking method and whether that might present problems for future InputfieldTextarea derivatives. This one specifically excludes TinyMCE, but feasibly there are future others it might need to as well. It makes me wonder if this module might better exist as an Inputfield itself (InputfieldTextareaCounter) or perhaps as a module config setting where you check boxes for which Inputfields it should apply to. Or perhaps as a core addition to existing InputfieldTextarea. These are just ideas for the future, but seems like what you've got here now is working great and I look forward to using it!

  • Like 3

Share this post


Link to post
Share on other sites

Ryan, thanks a lot for looking into this, your feedback is very much appreciated!

You're raising a really valid point there, I didn't really think about problems with other derivates, but you're completely right. I think this should be approached before submitting to the modules directory because depending on the solution, it might block the easy update path for some users later.

I'm not so shure which of your proposed solutions, that all sound reasonable, is the way to go here. Thus my question about the module as an input field itself: would there be any problems for a user to change from a normal InputfieldTextarea to a InputfieldTextareaCounter and back? If this is trivial (as it looks to me), I think this might be the cleanest solution to do it. Otherwise I like the checkbox solution second best, but it requires more configuration knowledge (I already see the "Why is my InputfieldXY behaving strangely?" thread in front of my mental eye).

  • Like 1

Share this post


Link to post
Share on other sites

Tested here and works great! Thanks for making this Boundaryfunctions and Soma! I look forward to seeing this in the modules directory. This is a very useful module for sure.

Minor point, but longer term, I wonder about the hooking method and whether that might present problems for future InputfieldTextarea derivatives. This one specifically excludes TinyMCE, but feasibly there are future others it might need to as well.

if($field != "InputfieldTextarea") return;

I'm not completely getting it about derivates. But of course I wasn't thinking about all consequences and what would be best way to go. But Ryan think makes some valid points here.

Extending InputfieldText or Textarea and just create a field for having counters versus a module only with options to chose which text field has the counter might work, but would need to also be able to make counter settings for each individual. Damn so many options it's hard to see through :D

  • Like 2

Share this post


Link to post
Share on other sites

The problem with derivates will occur, if someone adds another module where the counter doesn't fit in to InputfieldTextarea (like with TinyMCE). This won't break anything directly, because the counter only comes to action if you enter limits in the field configuration, but still this is something making it possible to do something wrong (and maybe don't get why).

The simplicity of if($field != "InputfieldTextarea") return; is a good idea to prevent this. On the other hand this will also prevent adding the counter to derivates of InputfieldTextarea where it actually would make sense.

The same is true for making it as a distinct field, because it wouldn't allow to add functionality with modules working with InputfieldTextarea hooks only, even if it makes sense.

Ryans proposed solution with a config setting to select on which variants of Inputsfields this should act would be the most flexible solution, but on the other hand, Soma, you're right about options everythere, this is really overcomplicating things for the clueless user.

I think all different methods mentioned here have their pros and cons, I'm not really sure, which one would be the best way to go. Maybe there are even more options?

  • Like 1

Share this post


Link to post
Share on other sites

Greetings,

I've been using the counter developed in this thread, and it's terrific. I'm just digging into the code in recent days.

It does seem, as boundaryfunctions explains, that any solution has its limits. But for the sake of being straightforward so the client has no confusion, I think the current solution works well. Here's my thinking, based on the current project I am working on for an arts organization...

As the developer, I am always the one determining which fields are placed into the template: I have yet to have a client ask me if they can add a core field to their templates on their own! Therefore, I can figure out ahead of time whether or not I'm including a field that needs character/word limits, and I make sure that the type of field I include is correct for that purpose.

In those cases where the client is more sophisticated and wants to add fields themselves, they would be sophisticated enough to know which fields are capable of character limits.

One of the things I love about ProcessWire is that it keeps everything as clean as possible. Following this philosophy, I think the current use of the character limits element works best. It simply requires reasonable understanding from the developer or the client. (Extrapolating, I think the character limits element is a good example for other elements.)

Thanks,

Matthew

  • Like 1

Share this post


Link to post
Share on other sites

Hey Matthew,

first, thanks a lot for testing and using it, I'm always glad if something is helpful to other and to get back feedback from it!

What you're pointing out there is something that I had in mind, too: the one activating the functionality for a field is usually a dev and should know what he or her is doing (i.e. don't add the counter for WYSIWYG textareas). Since you literally have to enter limits for every single field you want to use this with either way, the practical implications of the current behaviour shouldn't be too critical.

On the other hands: minimizing the chance for something to go wrong is always something to go for, assuming that the user will know what to do is never an execuse. Also it's tedious, to have to look up things in the documentation of each single module you use, even for the simplest things (reminds me of MODX the bad way...).

The discussion is also interesting, as this is a pattern that might be used by others modules, too. It would be great to have a working example for building this kind of field modification module (with validation and interactivity) using best practices that can be used in other places afterwards.

Just thinking out loud here, wouldn't it be possible for the Inputfield class to have a function isPlaintext() or even better to add an interface InputfieldHasPlaintextValue that modules with plain text values (no markup, no WYSIWYG, etc) would implement? On the one hand, this would make it easy in this case to check, whether the module is applyable and might be useful for others. On the other hand, I like that Pw isn't bloated with stuff like that myself, starting with this, where would you stop...

I'm leaning towards implementing Ryans proposal to have a module setting for this now. This should provide sensible defaults for all core module Inputfields and make it possible, to add the functionality to all derivates of InputfieldTextarea later. Tinkering with it when you're only using the basic functionality and nothing else wouldn't be necessary that way, but it still would be possible to add the functionality for all super custom fields you add later. In the module settings, this should be hidden enough for good I think.

  • Like 1

Share this post


Link to post
Share on other sites

Another factor to consider with the current solution is that it depends on an autoload module (executed on every request). That's a little less efficient than a solution that is specifically called upon when needed, as an Inputfield would be. From that respect, it would probably make sense for this to be InputfieldTextareaCounter. It would also be the simplest and most straightforward to implement and maintain. The drawback would be that you couldn't apply the counter functionality to other types of unknown future textarea derivative inputfields. But if someone is making a new text inputfield, chances are it's like TinyMCE, ACE editor or some other type of thing that wouldn't be compatible with the counter anyway. Ultimately the functionality provided here is pretty darn useful regardless of how it's implemented. But if I were implementing it myself, I'd probably make it an Inputfield rather than an autoload module. As a bonus, this would also guarantee compatibility with non-admin Inputfield forms, like those from FormBuilder, FormTemplateProcessor or API generated Inputfield forms.

  • Like 4

Share this post


Link to post
Share on other sites

Hi , 

I have tested this modul, but it doesnt work if the textarea is into a repeater field.

Is there some patch to apply for this?.

Thank you in advance.

Raul

Share this post


Link to post
Share on other sites

Hi Raul,

thanks for testing and posting! I'm pretty sure that you are right, but there's currently no ready-to-use fix for it. I doubt it would be too hard to do, but I currently don't have enough time. I already filed an issue on Github for it, though, and I hope that there will be a working fix soon.

With kind regards,

Marc

Share this post


Link to post
Share on other sites

thanks this module is great!

Share this post


Link to post
Share on other sites
The module does not work on my installation (with the latest PW dev installed):

I receive a 404 error

........ /wire/modules/Inputfield/InputfieldTinyMCE/tinymce-3.5.8/plugins/charcount_maxlength/editor_plugin.js

And indeed there is not such a folder charcount_maxlength within that wire directory.

EDIT: Maybe a false alarm. The offending plugin call charcount_maxlength was not anywhere in your code,

but buried in our field's settings for TinyMCE. I will check now how that entry came in there.

Share this post


Link to post
Share on other sites

Hi ceberlin,

this plugin is not intended for the use with a RTE editor like TinyMCE. It only works with plain textarea inputs.

Share this post


Link to post
Share on other sites

Great Module !

I just added a setting to truncate the inserted text instead of revert to the old text. I wished to do it the Gig Hub way, but I don't understand how to do that. I've put the changed module on my github account. ( sorry )

If you like it, maybe you can add it to your TextareaCounter module. 

  • Like 2

Share this post


Link to post
Share on other sites
I wished to do it the Gig Hub way, but I don't understand how to do that

You can do it even in the site. Just go to the file you want to change and edit it. They will ask you if you want to fork the whole project, you just have to say yes and edit the page to make a pull-request.

  • Like 2

Share this post


Link to post
Share on other sites

Hi Martin,

thanks a lot for adding this option, very nice!

Because of the Github trouble, I manually created a patch from your changes and commited it:

https://github.com/boundaryfunctions/TextareaCounter/commit/f740d8f8

I recognized that your repository is not actually a fork of mine from a Git point of view, and this is what made it complicated. The normal development model is "Fork and Pull" and should more or less include these steps:

  1. Create a fork of the repository you want to work on.
  2. Clone your fork to your computer, create a new branch and do all changes on one topic in there.
  3. Push that branch to your fork on Github.
  4. File a pull request.

With kind regards,

Marc

  • Like 3

Share this post


Link to post
Share on other sites

Hi Marc,

Thank you very much adding the truncate option & and the detailed description for the path to follow using git.

Many thanks,

Martijn

Share this post


Link to post
Share on other sites

Hi, the module is only checking the presence of tinyMCE and not of CKeditor, is this correct?

Share this post


Link to post
Share on other sites

How to get round problems with form builder with this module?

It is throwing errors both on saving a form and when I submit the form on the site - though the form is working.

Notice: Trying to get property of non-object in /home/claysvehiclerepairs/public_html/site/modules/TextareaCounter/TextareaCounter.module on line 50
 
Notice: Trying to get property of non-object in /home/claysvehiclerepairs/public_html/site/modules/TextareaCounter/TextareaCounter.module on line 58
 
Notice: Trying to get property of non-object in /home/claysvehiclerepairs/public_html/site/modules/TextareaCounter/TextareaCounter.module on line 66
 
 
Thanks!

Share this post


Link to post
Share on other sites

It's simply that the module isn't made for Formbuilder. This module needs a Field to work with. Formbuilder doesn't use Fields, only Inputfields.

It's failing in these here:

$value = $this->fields->get($event->object->name)->maxchars;

https://github.com/boundaryfunctions/TextareaCounter/blob/master/TextareaCounter.module#L50


Hi, the module is only checking the presence of tinyMCE and not of CKeditor, is this correct?

That's correct.

Share this post


Link to post
Share on other sites

I wasn't sure it had been changed - I noticed a post from Ryan a couple of pages back about making it compatible.

I am not actually trying to use it with formbuilder at all - it is just generating the error all on its own :)

Share this post


Link to post
Share on other sites

Whut?

I remember that was about with Textareas Profield not Formbuilder.

Huh? You wrote you try to use it with formbuilder. 

Share this post


Link to post
Share on other sites

Nope - it is just throwing that error when I use formbuilder. 

It is when debug is on. When you save a form that includes a textarea, you get the error and when you use the form in the front end I also get the error. But this is happening simply because the counter module is installed on the system, not because I have tried to include it in a form.

Ryan's comment is here:

https://processwire.com/talk/topic/2343-char-counter-for-texttextarea-fields/?p=22901

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By VeiJari
      Hi, this is the first we are trying to make a page that has only one type of user that has access to every page. 
      The other users should only have a given access to specific pages, not to the whole template.
      My structure
      -Field -Organisation -Project -Report I want that the "measurer" role only has access to "project x" and it's children, but no view access to every project, organisation or field. I've tried to do this with https://modules.processwire.com/modules/page-edit-per-user/ but it still needs a view access to the whole tree to see the "project x" page. Or is there something I haven't figured out?
      Maybe I have to make it via the API: a select field in the "organisation" template where the admins could add the users and then I use hook to update the privileges?
      Have you done something like this and how did you accomplish it?
      Any help would be appreciated.
       
    • By MoritzLost
      This module allows you to integrate hCaptcha bot / spam protection into ProcessWire forms. hCaptcha is a great alternative to Google ReCaptcha, especially if you are in the EU and need to comply with privacy regulations.

      The development of this module is sponsored by schwarzdesign.
      The module is built as an Inputfield, allowing you to integrate it into any ProcessWire form you want. It's primarily intended for frontend forms and can be added to Form Builder forms for automatic spam protection. There's a step-by-step guide for adding the hCaptcha widget to Form Builder forms in the README, as well as instructions for API usage.
      Features
      Inputfield that displays an hCaptcha widget in ProcessWire forms. The inputfield verifies the hCaptcha response upon submission, and adds a field error if it is invalid. All hCaptcha configuration options for the widget (theme, display size etc) can be changed through the inputfield configuration, as well as programmatically. hCaptcha script options can be changed through a hook. Error messages can be translated through ProcessWire's site translations. hCaptcha secret keys and site-keys can be set for each individual inputfield or globally in your config.php. Error codes and failures are logged to help you find configuration errors. Please check the README for setup instructions.
      Links
      Github Repository and documentation InputfieldHCaptcha in the module directory Screenshots (configuration)

      Screenshots (hCaptcha widget)

       
       

       
    • By Juergen
      Hello @ all,
      I have created an inputfield with a configuration field in the backend where you can set a time format for every language (see screenshot below).

      As you can see both language values (default and German) have the default value(%R), but I have set different values, which were correctly stored in the DB (see screenshot below):

      As you can see the values are '%R' and '%r'.
      I have created the configuration inputfield like this:
      /** @var InputfieldText $f */ $languages = $this->wire('languages'); $f = $this->wire('modules')->get('InputfieldText'); $f->attr('name+id', 'timeformat'); $f->label = $this->_('Timeformat on frontend'); $f->initValue = '%R';//default value $f->attr('value', $this->timeformat ? $this->timeformat : '%R'); $this->message($this->get('timesformat')); if($languages) { $f->useLanguages = true; foreach($languages as $language) { if($language->isDefault()) continue; $f->set("value$language", (string) $this->get("timeformat$language->id")); } } $f->inputType = 'text'; $f->description = $this->_('Please enter the time format that the times should appear on the frontend in strftime format.'); $f->notes = sprintf($this->_('For example shows the time as 08:00, as 08:00 AM. You can find more examples at %s.'), '<a href="https://www.php.net/manual/de/function.strftime.php">https://www.php.net/manual/de/function.strftime.php</a>'); $f->columnWidth = 100; The important part here is:
      if($languages) { $f->useLanguages = true; foreach($languages as $language) { if($language->isDefault()) continue; $f->set("value$language", (string) $this->get("timeformat$language->id")); } } I have borrowed the code from the DateTimeInputfield (https://github.com/processwire/processwire/blob/master/wire/modules/Inputfield/InputfieldDatetime/InputfieldDatetime.module), but the field values will be always populated with the default value ('%R').
      Are I am missing something? Does anyone has experience with multilanguage fields and could help me out?
      Thanks in advance.
    • By Juergen
      Hello @ all,
      I am creating a new inputfield/fieldtype to store opening hours, but I am struggeling to save values from multiple dynamic created inputfields in 1 column of the database.
      Scenario:
      The user can enter one or more opening times per day in a UI.
      Fe:
      Monday open from 08:00 to 12:00 and from 14:00 to 17:00 Tuesday open from 08:00 to 12:00 and from 14:00 to 19:00 and so on
      Via a little JavaScript you can add as much opening times as you need per day - the additional inputfield will be created dynamically.
      After form submission all the values are in the POST array -> this works (see example below):
      ProcessWire\WireInputData Object ( [openinghours_mo-0-start] => 09:00 [openinghours_mo-0-finish] => 13:00 [openinghours_mo-1-start] => 14:00 [openinghours_mo-1-finish] => 18:00 [openinghours_mo-2-start] => 21:00 [openinghours_mo-2-finish] => 23:00 [openinghours_tu-0-start] => 09:00 [openinghours_tu-0-finish] => 13:00 [openinghours_tu-1-start] => 14:00 [openinghours_tu-1-finish] => 18:00 [openinghours_we-0-start] => 09:00 [openinghours_we-0-finish] => 13:00 [openinghours_we-1-start] => 14:00 [openinghours_we-1-finish] => 18:00 [openinghours_th-0-start] => 09:00 [openinghours_th-0-finish] => 13:00 [openinghours_th-1-start] => 14:00 [openinghours_th-1-finish] => 18:00 [openinghours_fr-0-start] => 09:00 [openinghours_fr-0-finish] => 13:00 [openinghours_fr-1-start] => 14:00 [openinghours_fr-1-finish] => 18:00 [openinghours_sa-0-start] => [openinghours_sa-0-finish] => [openinghours_so-0-start] => [openinghours_so-0-finish] => ) The property name is always the name attribute of the field 😉 . If the property is empty means closed on that day.
      Now I need to combine all those values into 1 array (or json array) and store it in the database in 1 column called 'hours' in my case (see screenshot below):

      In my ___processInput(WireInputData $input) method I have tried to make it work like this:
      public function ___processInput(WireInputData $input): self { $name = $this->attr('name'); $value = $this->attr('value'); //input object includes always every input on the page, so lets filter out only inputs from this field //we need to do this, because the number of values is variable - so extract only values that starts with $name.'_' $nameAttributes = []; foreach($input as $key=>$value){ if(substr($key, 0, strlen($name.'_')) === $name.'_'){ $nameAttributes[$key] = $value; } } // loop through all inputfields of this fieldtype $time_values = []; foreach($nameAttributes as $nameAttr => $value) { $time_values[$nameAttr] = $value; } } //save it in the database $input->set('hours', serialize($time_values)); return $this; } The only important part of this code is the last part with the serialize function.
      After saving it will create a record in the database, but the value is always NULL (default value) (see below).

      Checking $time_values returns all the values, but printing out "$this" shows me that the property "hours" inside the Openinghours object is empty (see below) - so the mistake must be there, but I dont know where?!?!?!?
      [title] => Home [openinghours] => ProcessWire\OpeningHours Object ( [data] => Array ( [hours] => ) ) If I check the sleepValue() method or the sanitizeValue() - they are also empty. So it seems that the values will not reach these methods. I havent found a clear documentation of whats going on behind the saving process of an inputfield.
      As far as I know the saving process starts with the form submission. The values are in the POST array and will be processed by the processInput() method. Before they will be saved in the database they will be sanitized by the sanitizeValue() mehtod and afterwards they will be prepared for storage in the sleepValue() method.  The last step is the storage itself.
      Has someone an idea what is missing by storing values from multiple fields into 1 database column or has someone a working example of such a scenario on github to help me out.
      A clear explanation of the storage process will be also helpful.
      Thanks and best regards
    • By Juergen
      Hello @ all!
      I want to share a simple fieldtype and inputfield to store address data with you.
      I have created this inputfield for learning purposes and it has no fancy functionality. It is simply for storing address data such as street, number, postalcode and so on in one table. As an addition you can store latitude and longitude too, so you can use them in maps.
      Here is a screenshot of what it looks like:

      You can select which fields are mandatory and you can choose if the inputs for longitude and latitude should be displayed. These settings can be configured in the field configuration.
      If you find this inputfield useful you can download it at https://github.com/juergenweb/FieldtypeSimpleAddress
      There you will find a detailed explanation. If you have an idea of an usefull feature that can be added or you have detected a bug, please report it in my github account.
       
×
×
  • Create New...