|
<?php |
|
|
|
class TextAreaCounter extends WireData implements Module { |
|
|
|
/** |
|
* getModuleInfo is a module required by all modules to tell ProcessWire about them |
|
* |
|
* @return array |
|
* |
|
*/ |
|
public static function getModuleInfo() { |
|
|
|
return array( |
|
'title' => 'Textarea Counter', |
|
'version' => 1, |
|
'summary' => 'Proof of concept. Counts chars in a textarea', |
|
'href' => '', |
|
'singular' => true, |
|
'autoload' => true |
|
); |
|
} |
|
|
|
public function init() { |
|
|
|
$this->addHookAfter('InputfieldTextarea::getConfigInputfields', $this, 'hookAddConfig'); |
|
$this->addHookBefore('InputfieldTextarea::render', $this, 'renderBeforeTextarea'); |
|
$this->addHookAfter('InputfieldTextarea::render', $this, 'renderTextarea'); |
|
|
|
} |
|
|
|
|
|
public function hookAddConfig(HookEvent $event) { |
|
// not tinymce fields |
|
if($event->object == 'InputfieldTinyMCE') return; |
|
|
|
// get inputfields from getConfigInputfields |
|
$inputfields = $event->return; |
|
|
|
// add maxchars setting |
|
$f = $this->modules->get('InputfieldInteger'); |
|
$f->label = $this->_('Max. characters'); |
|
$f->description = $this->_('The maximum amount of characters that can be entered.'); |
|
$f->attr('name','maxchars'); |
|
$value = $this->fields->get($event->object->name)->maxchars; |
|
$f->attr('value', $value ? $value : ''); |
|
$inputfields->append($f); |
|
|
|
$f = $this->modules->get('InputfieldInteger'); |
|
$f->label = $this->_('Max. words'); |
|
$f->description = $this_('The maximum amount of words that can be entered.'); |
|
$f->attr('name','maxwords'); |
|
$value = $this->fields->get($event->object->name)->maxwords; |
|
$f->attr('value', $value ? $value : ''); |
|
$inputfields->append($f); |
|
} |
|
|
|
public function renderBeforeTextarea(HookEvent $event){ |
|
|
|
// only on page edits screens |
|
if($this->process != 'ProcessPageEdit') return; |
|
|
|
$field = $event->object; |
|
|
|
// no tinymce fields |
|
if($field == 'InputfieldTinyMCE') return; |
|
|
|
// get field to set attribute, will get rendered by the InputfieldTexarea |
|
$inputfield = $this->fields->get($field->name); |
|
|
|
$types = array( |
|
'chars', |
|
'words' |
|
); |
|
foreach ($types as $type) { |
|
$max = $this->fields->get($event->object->name)->{'max'.$type}; |
|
if ($max && 0 < intval($max)) { |
|
$field->attr('data-max'.$type, $inputfield->{'max'.$type}); |
|
} |
|
} |
|
} |
|
|
|
public function renderTextarea(HookEvent $event){ |
|
// add stuff only to admin pages edit screen |
|
if($this->process != 'ProcessPageEdit') return; |
|
|
|
// not render span if tinymce field |
|
if($event->object == 'InputfieldTinyMCE') return; |
|
|
|
$labels = array( |
|
'chars' => $this->_('Characters left'), |
|
'words' => $this->_('Words left') |
|
); |
|
$append = array(); |
|
$value = $event->object->value; |
|
|
|
foreach ($labels as $type => $label) { |
|
$max = $this->fields->get($event->object->name)->{'max'.$type}; |
|
if ($max && 0 < intval($max)) { |
|
$left = $max - $this->{'count'.ucfirst($type)}($value); |
|
$append[] = '<span class="counter'.ucfirst($type).'">'.$label.': <span class="counterVal">'.$left.'</span></span>'; |
|
} |
|
} |
|
if (0 < count($append)) { |
|
// render counter spans after text field |
|
$event->return .= implode(' ', $append); |
|
// add scripts to admin page |
|
$this->config->scripts->add($this->config->urls->TextAreaCounter . 'TextAreaCounter.js'); |
|
} |
|
} |
|
|
|
private function countChars($str) { |
|
return strlen($str); |
|
} |
|
|
|
private function countWords($str) { |
|
return count(preg_split('/\s+/', $str)); |
|
} |
|
|
|
} |
Link from ProcessWire's website
http://modules.processwire.com/modules/textarea-counter/