Word Counter

Home Forums Quform WordPress Word Counter

This topic is: resolved

This topic contains 15 replies, has 3 voices, and was last updated by  DASub 3 weeks, 2 days ago.

Viewing 15 posts - 1 through 15 (of 16 total)
  • Author
    Posts
  • #26650

    DASub
    Participant

    I searched the forums for code for a text area word counter. I found this one for Versions 1

    Textarea word counter

    Is there an update of this article for version 2? If so, I couldn’t find it and would appreciate a link. Thanks.

    #26651

    katw
    Participant

    Hi @dasub, saw your post and thought I could offer a few suggestions.

    Are you wanting to use the word counter in both contexts?

    1. Front-end (as a gauge for user entry)
    2. Back-end (as a form submission validator)

    Steps 1 and 2 should still work fine with QuForm 2.

    Amend line #9 with the new format of element ID class e.g .quform-input-1_28

    For example my textarea field is ID 1_28, and the DIV containing the textarea form field has a CSS class prefix called: .quform-input-.

    Which results in the identifier .quform-input-1_28. I would use that if I was applying it to the textarea field on my form.

    I haven’t tried the Javascript code out but as it’s JQuery this hasn’t changed and should work ok.

    Step 4 also works for QuForm2.

    It is only the Validator part (Step 3) that has changed a lot and wont work in its current form.

    See how you go.

    #26652

    katw
    Participant

    @dasub I made an error on class name, the word count script in its current form requires a form input field ID for the Line 9 entry.

    Which would be .quform-field-1_28 in my example. ‘Field’ not ‘input’ label.

    Word count front-end is working fine for me, my code:

    <script type="text/javascript">
    
    // When DOM ready, do:
    jQuery(document).ready(function($) {
    	// WordCount function
    	var countre = /[\w\u2019\x27\-]+/g;
    	var cleanre = /[0-9.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g;
    
    	function wordCount(tx) {
    		var tc = 0;
    		if (tx) {
    			tx = tx.replace(/\.\.\./g, ' '); // convert ellipses to spaces
    			tx = tx.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;| /gi, ' '); // remove html tags and space chars
    			// deal with html entities
    			tx = tx.replace(/(\w+)(&.+?;)+(\w+)/, "$1$3").replace(/&.+?;/g, ' ');
    			tx = tx.replace(cleanre, ''); // remove numbers and punctuation
    			var wordArray = tx.match(countre);
    			if (wordArray) {
    				tc = wordArray.length;
    			}
    		}
    		return tc;
    	}
    
    	var $counterText = $('<div class="word-counter" />');
    
    	// Get the textarea field
    	$('.quform-field-1_28').after($counterText);
    
    	// Bind the counter function on keyup and blur events
    	$('.quform-field-1_28').bind('keyup blur', function () {
    		// Count the words
    		var val = $(this).val(), count = wordCount(val);
    
    		// Set the counter text
    		$counterText.text(count + '/400 words');// <-- change 400 to word count allowed
    	})
    
    	// Trigger the counter on first load
    	.keyup();
    });
    </script>
    #26653

    katw
    Participant

    Hi @dasub I have mocked up a validator that appears to work ok.

    This should give you a hand while waiting for an answer from the support team.

    This code needs to be added to functions.php or turned into a plugin (which is what I do).

    Enjoy and do a lot of testing as I have only done basics.

    add_action('plugins_loaded', function () {
    	class Quform_Validator_WordCount extends Quform_Validator_Abstract
    	{
    		// ADDED - Used with message handling function
    		const INVALID = 'WordCountInvalid';
    		const TOO_LONG = 'WordCountOver';
    		const TOO_SHORT = 'WordCountUnder';
    
    		// REQUIRED - Does the validation of the field contents
    		// Returns True if valid and False if not
    		public function isValid($value) {
    
    			if ( ! is_string($value)) {// check contents is a string
    				$this->error(self::INVALID);
    				return false;
    			}
    
    			// Set word count parameters below:
    			$min=3;//minimum
    			$max=10;//maximum
    			if (str_word_count($value) > $max) {
    				$this->error(self::TOO_LONG);
    				return false;
    			}
    			if (str_word_count($value) <= $min) {
    				$this->error(self::TOO_SHORT);
    				return false;
    			}
    			return true;
    		}
    
    		// ADDED For improved error messages and readability
    		public static function getMessageTemplates($key = null) {
    			$messageTemplates = array(
    				self::INVALID => __('Invalid data type, string expected',  'quform'),
    				self::TOO_LONG => __('Word count exceeded, please reduce length',  'quform'),
    				self::TOO_SHORT => __('Too brief, please add more',  'quform')
    			);
    
    			if (is_string($key)) {
    				return array_key_exists($key, $messageTemplates) ? $messageTemplates[$key] : null;
    			}
    
    			return $messageTemplates;
    		}
    
    		// REQUIRED - Sets validator baseline or defaults, 
    		// Array() can be empty if not using the added messageTemplates function
    		public static function getDefaultConfig() {
    			$config = apply_filters('quform_default_config_validator_WordCount', array(
    				'messages' => array(
    					self::INVALID => '',
    					self::TOO_LONG => '',
    					self::TOO_SHORT => ''
    				)
    				// Above array -^- added for error messages
    			));
    
    			$config['type'] = 'WordCount';
    
    			return $config;
    		}
    	}
    });
    
    // REQUIRED Adds this validator to form builder interface. Change ### to max number
    add_filter('quform_admin_validators', function (array $validators) {
    	$validators['WordCount'] = array(
    		'name' => 'WordCount ###',
    		'tooltip' => 'Retricts response to ### words',
    		'config' =>  Quform_Validator_WordCount::getDefaultConfig()
    	);
    	return $validators;
    });
    
    // REQUIRED Sets field types available to this validator
    add_filter('quform_visible_validators', function (array $visible) {
    	$visible['text'][] = 'WordCount';
    	$visible['textarea'][] = 'WordCount';
    	return $visible;
    });
    #26655

    katw
    Participant

    It is also worth mentioning the front-end word count indicator uses a different method of counting words to the back-end validator.

    You many need to run a few tests to see if they are both in agreement with the word count max.

    Otherwise users may get frustrated being told they have too many words when the counter says they are under.

    I don’t know if this will happen but you should check. If they don’t agree, you may have to adjust to bring them into agreement (suggest tweaking the javascript one).

    You can use a content generator like Lorem Ipsum to make test entry samples of set word counts.

    All the best

    #26656

    DASub
    Participant

    Thanks so much for all the effort on this! I really appreciate it.

    #26657

    katw
    Participant

    You’re welcome.

    It was a challenge, but I enjoyed it… actually it was a diversion from code I am doing battle with 🙁

    See how you go with it.

    You will see I upgraded the function to include a minimum word count option which you can choose to use or not.

    #26703

    Ally
    Support Staff

    You don't have permission to view this content. Please log in or register and then verify your purchases to gain access.

    #26708

    katw
    Participant

    Hi Ally,

    Use the solution as you wish to write up a V2 Document.

    P.S interested in feedback. Did I interpret the validation actions correctly?

    #26731

    DASub
    Participant

    Overall I really appreciate the effort that katw put into this. The approach works but the word count is pretty inaccurate (e.g. 500 words being counted as 462 by the validator, display shows 462 but further input is blocked by the validator). As katw said, the front-end counter method is different than the validator. I need to spend time trying to figure out how to make them agree or I may need to go back to your character counter.

    #26741

    katw
    Participant

    Hi @dasub, the methods used for determining what constitutes a ‘word’ differs between the two code modules.

    If you research a method you like and share links to the info I can have a look and see if it can be implemented consistently between Javascript and PHP.

    For example an interesting discussion about this topic read this tech note. It raises the point as to whether punctuation like ‘!’ should count, or digits etc

    The issue isn’t a Quform issue but a methodology for ‘how to count’.

    #26759

    Ally
    Support Staff

    You don't have permission to view this content. Please log in or register and then verify your purchases to gain access.

    #26774

    DASub
    Participant

    The counts match perfectly. Thanks. My error checker isn’t working though if the number of words exceeds the $max variable so I’ll need to dig in and see if I let a typo slip in. I’ll report back. Thank you again. Fantastic support!

    #26806

    DASub
    Participant

    Ally, I did find a typo I made and what you gave me now works fine. Thanks.

    Is it possible to have the word counter trim the text string in real-time so that if the number of words exceeds the max while the user is typing/pasting on the front-end, the words beyond the max are either replaced with spaces or not displayed? Otherwise, the user needs to hit submit to get the error message.

    #26828

    Ally
    Support Staff

    You don't have permission to view this content. Please log in or register and then verify your purchases to gain access.

Viewing 15 posts - 1 through 15 (of 16 total)

You must be logged in to reply to this topic.