Skip to content

Commit

Permalink
Target acquired
Browse files Browse the repository at this point in the history
  • Loading branch information
jonom committed Mar 10, 2016
1 parent e62a0d4 commit 28068a5
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 3 deletions.
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# For more information about the properties used in this file,
# please see the EditorConfig documentation:
# http://editorconfig.org

# Default for all files
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true

# PSR-2 for PHP
[*.php]
indent_style = space

# The indent size used in the package.json file cannot be changed:
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
[{*.yml,package.json}]
indent_size = 2
indent_style = space
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2016, Jono Menz
Copyright (c) 2016, Jonathon Menz
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# silverstripe-text-target-length
Set character length recommendations on SilverStripe text form fields
# Text Target Length for SilverStripe CMS

![Character limits in action](screenshots/character-count.gif)

If you see a field marked 'Description' you know roughly what type of content to put in there. But how do you know how much of it to write? A single sentence might do, but maybe a paragraph or more is required? A great content plan should recommend an ideal length for every type of content, so content authors and designers alike can make informed decisions.

This module extends the `TextField` and `TextareaField` classes in SilverStripe to allow you to set a recommended content length, and set soft upper and lower limits on character count.

## Requirements

SilverStripe 3.1+ (3.3 tested)

## Installation

### Composer (best practice)

[Packagist listing](https://packagist.org/packages/jonom/silverstripe-text-target-length) and [installation instructions](http://doc.silverstripe.org/framework/en/trunk/installation/composer#adding-modules-to-your-project)

### Manually

I promise it's worth your time to learn how to use Composer. If painless updating isn't your thing though you can download and extract this project, rename the module folder 'text-target-length', place it in your project root and run a dev/build?flush=1.

## How to use

With the module installed you can call call `setTargetLength()` on `TextField` and `TextareaField` form fields.

```php
// Ideal length: 100 characters
// Minimum: 75 (automatically set at 75% of ideal)
// Maximum: 125 (automatically set at 125% of ideal)
$field->setTargetLength(100);

// Ideal length: 100 characters
// Minimum: 25
// Maximum: 150
$field->setTargetLength(100, 25, 150);
```

## Want to see more like this?

I donate a lot of my time to open-source projects, so if you use this module in a commercial project a small donation to keep me motivated would be much appreciated. If you'd like to sponsor additional development on this module I'd love to hear from you.

[<img src="https://www.paypalobjects.com/en_AU/i/btn/btn_donate_LG.gif" alt="Donate">](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z5HEZREZSKA6A)

## To Do

- [ ] Extension for HTMLEditorField?
- [ ] Translation
- [ ] Customise hint text through config

## Maintainer contact

[jonathonmenz.com](http://jonathonmenz.com)
6 changes: 6 additions & 0 deletions _config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

if (!defined('TEXTTARGETLENGTH_DIR')) {
//Assumes this module is installed in web root
define('TEXTTARGETLENGTH_DIR', basename(dirname(__FILE__)));
}
9 changes: 9 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
Name: text-target-length
---
TextField:
extensions:
- TextTargetLengthExtension
TextareaField:
extensions:
- TextTargetLengthExtension
43 changes: 43 additions & 0 deletions code/TextTargetLengthExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/**
* Apply this extension to TextareaField and/or TextField
* to allow setting of ideal, min and max lengths. These are
* soft limits only, to give CMS users an idea of target length.
*/
class TextTargetLengthExtension extends Extension
{

/**
* Set a target character length for text in a field.
*
*
* @param Int $idealCharCount the ideal number of characters for this text
* @param Int $minCharCount (default: null) the minimum number of characters for this text
* @param Int $maxCharCount (default: null) the maximum number of characters for this text
* @return FormField
*/
public function setTargetLength($idealCharCount, $minCharCount = null, $maxCharCount = null)
{
$field = $this->owner;
$idealCharCount = (int)$idealCharCount;
if (!$idealCharCount > 0) return $field;

// Set defaults
if ($minCharCount === null) $minCharCount = round($idealCharCount * .75);
if ($maxCharCount === null) $maxCharCount = round($idealCharCount * 1.25);

// Validate
if (!($maxCharCount >= $idealCharCount && $idealCharCount >= $minCharCount)) return $field;

// Activate
$field->addExtraClass('target-length');
$field->setAttribute('data-target-ideal-length', $idealCharCount);
$field->setAttribute('data-target-min-length', $minCharCount);
$field->setAttribute('data-target-max-length', $maxCharCount);
Requirements::javascript(TEXTTARGETLENGTH_DIR.'/javascript/text-target-length.js');
Requirements::css(TEXTTARGETLENGTH_DIR.'/css/text-target-length.css');

return $field;
}
}
17 changes: 17 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "jonom/silverstripe-text-target-length",
"description": "Set character length recommendations on SilverStripe text form fields",
"type": "silverstripe-module",
"keywords": ["silverstripe", "textfield", "textareafield", "target"],
"license": "BSD-3-Clause",
"authors": [{
"name": "Jonathon Menz",
"homepage": "http://jonathonmenz.com"
}],
"require": {
"silverstripe/cms": "^3.1"
},
"extra": {
"installer-name": "text-target-length"
}
}
20 changes: 20 additions & 0 deletions css/text-target-length.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.target-length p.target-length-count {
color: #8796a3;
margin: 0 auto;
padding: .25em 0;
}
.target-length p.target-length-count i,
.target-length p.target-length-count b {
color: #00a651;
}
.target-length p.target-length-count b {
font-weight: bold;
}
.target-length p.target-length-count.over i,
.target-length p.target-length-count.over b {
color: #e3080a;
}
.target-length p.target-length-count.under i,
.target-length p.target-length-count.under b {
color: #e39d08;
}
58 changes: 58 additions & 0 deletions javascript/text-target-length.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
(function($) {
$.entwine('ss.targetlength', function($){

$('div.field.target-length input').entwine({

updateCount: function() {
var field = $(this);
var countEl = field.next('p.target-length-count');
if (!countEl) return;
var charCount = field.val().length;
if (field.data('previousCount') === charCount) return;
var ideal = field.data('targetIdealLength');
var min = field.data('targetMinLength');
var max = field.data('targetMaxLength');
var targetFulfilled = Math.round((charCount / ideal)*20)*5; //5% increments
var remark = 'Great!';
var remarkClass = 'good';
if ((charCount >= min && charCount < ((min + ideal) / 2)) || (charCount <= max && charCount > ((max + ideal) / 2))) {
remark = 'Okay';
} else if (charCount < min) {
remark = 'Keep going!';
remarkClass = 'under';
if (charCount === 0) remark = '';
} else if (charCount > max) {
remark = 'Too long'
remarkClass = 'over';
}
countEl.attr('class', remarkClass + ' target-length-count');
countEl.html('Length target: <b>' + targetFulfilled + '%</b> <i>' + remark + '</i>');
field.data('previousCount', charCount);
},
onadd: function() {
// Insert extra markup
var field = $(this);
field.parent().append('<p class="target-length-count">');
this.updateCount();
},
onpropertychange: function() {
this.updateCount();
},
onchange: function() {
this.updateCount();
},
onclick: function() {
this.updateCount();
},
onkeyup: function() {
this.updateCount();
},
oninput: function() {
this.updateCount();
},
onpaste: function() {
this.updateCount();
}
});
});
}(jQuery));
Binary file added screenshots/character-count.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 28068a5

Please sign in to comment.