Skip to content

Commit 8157d63

Browse files
committed
Added config file. Fixed small issue with afterSave in Behavior
1 parent e444286 commit 8157d63

File tree

7 files changed

+83
-20
lines changed

7 files changed

+83
-20
lines changed

Config/config.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
$config['Taggable'] = [
3+
'save_field' => 'new_tags', // The name of the field to use when saving new tags
4+
];

Model/Behavior/TaggableBehavior.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
<?php
2+
App::uses('ModelBehavior', 'Model');
3+
Configure::load('Taggable.config');
4+
25
class TaggableBehavior extends ModelBehavior {
36
public $name = 'Taggable';
47

5-
/**
6-
* The field to be saved
7-
* @var string
8-
**/
9-
const SAVE_FIELD = 'new_tags';
10-
118
/**
129
* The Tag model object
1310
* @var Model
@@ -35,6 +32,7 @@ public function beforeFind(Model $Model, $query = array()) {
3532
public function afterFind(Model $Model, $results, $primary = false) {
3633
if (!empty($results[0][$Model->alias])) {
3734
foreach ($results as $k => $row) {
35+
$results[$k][$Model->alias]['taggable__tags'] = array();
3836
if (!empty($row['Tag'])) {
3937
// Adds an ID => TAG array to the model's result
4038
foreach ($row['Tag'] as $tag) {
@@ -44,12 +42,13 @@ public function afterFind(Model $Model, $results, $primary = false) {
4442
}
4543
return $results;
4644
}
47-
debug($results);
4845
return parent::afterFind($Model, $results, $primary);
4946
}
5047

5148
public function beforeSave(Model $Model, $options = array()) {
5249
$data =& $Model->data;
50+
$saveField = Configure::read('Taggable.save_field');
51+
5352
$tags = array();
5453
if (!empty($data['Tag']['Tag'])) {
5554
foreach ($data['Tag']['Tag'] as $k => $tagId) {
@@ -62,8 +61,8 @@ public function beforeSave(Model $Model, $options = array()) {
6261
}
6362
}
6463

65-
if (!empty($data[$Model->alias][self::SAVE_FIELD])) {
66-
$newTags = $this->translateTagStrToArray($data[$Model->alias][self::SAVE_FIELD]);
64+
if (!empty($data[$Model->alias][$saveField])) {
65+
$newTags = $this->translateTagStrToArray($data[$Model->alias][$saveField]);
6766
if (empty($tags)) {
6867
$tags = $newTags;
6968
} else {

Model/TaggableAppModel.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22
App::uses('AppModel', 'Model');
3+
Configure::load('Taggable.config');
4+
35
class TaggableAppModel extends AppModel {
46

57
}

View/Helper/TagHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<?phpclass TagHelper extends AppHelper { public $name = 'Tag'; public $helpers = array( 'Html', 'Form', ); public function beforeRender($writeFile, $options = array()) { $this->Html->css('Taggable.style', null, array('inline' => false)); return parent::beforeRender($writeFile, $options); } /** * Outputs a version of the tag input, but wrapped in a form element to make it stand alone * * @param string $model The model related to the tags * @param array $options Options based on the input method options * @return string; **/ public function form($model, $options = array()) { $options['form'] = true; return $this->input($model, $options); } /** * Outputs a form input for entering tags associated with a model * * @param string $model The model name of the associated model * @param array $options * - form: Boolean to wrap the input in a form tag * - name: The input name * - id: Includes an additional model id (Useful if form is true) * - tags: An array of existing tags (Most times this will be auto-set by the TaggableBehavior) * - legend: The legend to be written across the tags input * * @return string; **/ public function input($model, $options = array()) { $this->Html->script('Taggable.form', array('inline' => false)); $options = array_merge(array( 'form' => false, 'name' => 'new_tags', 'id' => false, 'tags' => array(), 'legend' => 'Tags', ), $options); extract($options); $wrapClass = 'taggable-tags-input'; $out = ''; if (empty($tags)) { if ($this->Html->value("$model.taggable__tags")) { $tags = $this->Html->value("$model.taggable__tags"); } else if ($this->Html->value('Tag')) { $tags = array(); if (!empty($this->request->data['Tag']['Tag'])) { $tags = $this->request->data['Tag']['Tag']; } else { foreach ($this->request->data['Tag'] as $k => $tag) { $tags[$tag['id']] = $tag['tag']; } } } } // Outputs tags input $options = array( 'type' => 'text', 'label' => 'Separate tags with commas', 'placeholder' => '(ie: tag 1, tag 2, tag 3)', ); if (!empty($class)) { $options = $this->Html->addClass($options, $class); } if (!empty($form)) { $options = $this->Html->addClass($options, 'input-append', 'div'); $options['after'] = $this->Form->submit('Add Tags', array('div' => false)); } $out .= $this->Form->input($name, $options); // Outputs existing tags a checkbox list if (!empty($tags)) { if (isset($tags[0]['id'])) { $newTags = array(); foreach ($tags as $tag) { $newTags[$tag['id']] = $tag['tag']; } $tags = $newTags; } $out .= $this->Form->input('Tag', array( 'hiddenField' => false, 'options' => $tags, 'multiple' => 'checkbox', 'label' => false, 'value' => array_keys($tags), //selected 'div' => $wrapClass . '-checkboxes', )); } if (!empty($legend)) { $out = $this->Html->tag('legend', $legend) . $out; } $out = $this->Html->tag('fieldset', $out); if (!empty($id)) { $out .= $this->Form->hidden('id', array('value' => $id)); } // Wraps output in a form if (!empty($form)) { $formOpen = $this->Form->create($model, array('action' => 'edit')); $formClose = $this->Form->end(); $out = $formOpen . $out . $formClose; } return $this->Html->div($wrapClass, $out); } public function tag($text, $options = array()) { $options = array_merge(array( 'tag' => 'span', 'x' => null, 'url' => null, ), $options); extract($options); $out = $text; if ($url) { $out = $this->Html->link($out, $this->__getTagUrl($text, $url)); } if ($x) { $out .= $this->__getXUrl($x); } return $this->Html->tag($tag, $out, array('class' => 'tag')); } public function tagList($tags = null, $options = array()) { if (empty($tags)) { return ''; } $out = ''; foreach ($tags as $tag) { if (isset($tag['tag'])) { $tag = $tag['tag']; } $out .= $this->Html->tag('li', $this->tag($tag, $options)); } return $this->Html->tag('ul', $out, array('class' => 'tags-list')); } public function cloud($tagCount, $options = array()) { if (empty($tagCount)) { return false; } $minFontSize = 10; $maxFontSize = 36; $fontUnit = 'px'; $min = min($tagCount); $max = max($tagCount); $passTag = !empty($this->request->named['tag']) ? $this->request->named['tag'] . ',' : ''; $out = ''; foreach ($tagCount as $tag => $count) { if ($max == $min || $count == $min) { $fontSize = $minFontSize; } else { $fontSize = ((($maxFontSize - $minFontSize) * ($count - $min)) / ($max - $min)) + $minFontSize; } $out .= $this->Html->link($tag, array('tag' => $passTag . $tag), array( 'class' => 'tag', 'style' => 'font-size:' . $fontSize . $fontUnit, 'title' => 'Found ' . $count . ' Tagged as "' . $tag . '"', )); } return $this->Html->div('tags-cloud', $out); } private function __getTagUrl($tag, $url = true) { if ($url === true) { $url = $this->__currentUrl(); } $slug = Inflector::slug($tag); if (is_array($url)) { $url['tag'] = $slug; } else { $url .= '/tag:' . $slug; } return $url; } private function __getXUrl($url = array()) { if (!$url) { return ''; } if ($url === true || $url == 'remove') { $url = array('tag' => false) + $this->__currentUrl(); } return $this->Html->link('&times;', $url, array('escape' => false)); } private function __currentUrl() { $url = Router::parse($this->request->url); if (!empty($url['pass'])) { $url['?'] = $url['pass']; unset($url['pass']); } if (!empty($url['named'])) { $url = $url['named'] + $url; unset($url['named']); } return $url; }}
1+
<?phpConfigure::load('Taggable.config');class TagHelper extends AppHelper { public $name = 'Tag'; public $helpers = array( 'Html', 'Form', ); public function beforeRender($writeFile, $options = array()) { $this->Html->css('Taggable.style', null, array('inline' => false)); return parent::beforeRender($writeFile, $options); } /** * Outputs a version of the tag input, but wrapped in a form element to make it stand alone * * @param string $model The model related to the tags * @param array $options Options based on the input method options * @return string; **/ public function form($model, $options = array()) { $options['form'] = true; return $this->input($model, $options); } /** * Outputs a form input for entering tags associated with a model * * @param string $model The model name of the associated model * @param array $options * - form: Boolean to wrap the input in a form tag * - id: Includes an additional model id (Useful if form is true) * - tags: An array of existing tags (Most times this will be auto-set by the TaggableBehavior) * - legend: The legend to be written across the tags input * * @return string; **/ public function input($model, $options = array()) { $this->Html->script('Taggable.form', array('inline' => false)); $options = array_merge(array( 'form' => false, 'id' => false, 'tags' => array(), 'legend' => 'Tags', ), $options); extract($options); $wrapClass = 'taggable-tags-input'; $out = ''; if (empty($tags)) { if ($this->Html->value("$model.taggable__tags")) { $tags = $this->Html->value("$model.taggable__tags"); } else if ($this->Html->value('Tag')) { $tags = array(); if (!empty($this->request->data['Tag']['Tag'])) { $tags = $this->request->data['Tag']['Tag']; } else { foreach ($this->request->data['Tag'] as $k => $tag) { $tags[$tag['id']] = $tag['tag']; } } } } // Outputs tags input $options = array( 'type' => 'text', 'label' => 'Separate tags with commas', 'placeholder' => '(ie: tag 1, tag 2, tag 3)', ); if (!empty($class)) { $options = $this->Html->addClass($options, $class); } if (!empty($form)) { $options = $this->Html->addClass($options, 'input-append', 'div'); $options['after'] = $this->Form->submit('Add Tags', array('div' => false)); } $out .= $this->Form->input(Configure::read('Taggable.save_field'), $options); // Outputs existing tags a checkbox list if (!empty($tags)) { if (isset($tags[0]['id'])) { $newTags = array(); foreach ($tags as $tag) { $newTags[$tag['id']] = $tag['tag']; } $tags = $newTags; } $out .= $this->Form->input('Tag', array( 'hiddenField' => false, 'options' => $tags, 'multiple' => 'checkbox', 'label' => false, 'value' => array_keys($tags), //selected 'div' => $wrapClass . '-checkboxes', )); } if (!empty($legend)) { $out = $this->Html->tag('legend', $legend) . $out; } $out = $this->Html->tag('fieldset', $out); if (!empty($id)) { $out .= $this->Form->hidden('id', array('value' => $id)); } // Wraps output in a form if (!empty($form)) { $formOpen = $this->Form->create($model, array('action' => 'edit')); $formClose = $this->Form->end(); $out = $formOpen . $out . $formClose; } return $this->Html->div($wrapClass, $out); } public function tag($text, $options = array()) { $options = array_merge(array( 'tag' => 'span', 'x' => null, 'url' => null, 'class' => 'taggable-tag', ), $options); extract($options); $out = $text; debug(compact('text')); if ($url) { $out = $this->Html->link($out, $this->__getTagUrl($text, $url)); } if ($x) { $out .= $this->__getXUrl($x); } return $this->Html->tag($tag, $out, compact('class')); } public function resultTagList($result = null, $options = array()) { $tags = !empty($result['taggable__tags']) ? $result['taggable__tags'] : array(); return $this->tagList($tags, $options); } public function tagList($tags = null, $options = array()) { if (empty($tags)) { return ''; } $out = ''; foreach ($tags as $tag) { if (isset($tag['tag'])) { $tag = $tag['tag']; } $options['class'] = 'taggable-tags-list-item taggable-tag'; debug(compact('tag', 'options')); $out .= $this->tag($tag, $options); } return $this->Html->tag('div', $out, array('class' => 'taggable-tags-list')); } public function cloud($tagCount, $options = array()) { if (empty($tagCount)) { return false; } $minFontSize = 10; $maxFontSize = 36; $fontUnit = 'px'; $min = min($tagCount); $max = max($tagCount); $passTag = !empty($this->request->named['tag']) ? $this->request->named['tag'] . ',' : ''; $out = ''; foreach ($tagCount as $tag => $count) { if ($max == $min || $count == $min) { $fontSize = $minFontSize; } else { $fontSize = ((($maxFontSize - $minFontSize) * ($count - $min)) / ($max - $min)) + $minFontSize; } $out .= $this->Html->link($tag, array('tag' => $passTag . $tag), array( 'class' => 'tag', 'style' => 'font-size:' . $fontSize . $fontUnit, 'title' => 'Found ' . $count . ' Tagged as "' . $tag . '"', )); } return $this->Html->div('tags-cloud', $out); } private function __getTagUrl($tag, $url = true) { if ($url === true) { $url = $this->__currentUrl(); } $slug = Inflector::slug($tag); if (is_array($url)) { $url['tag'] = $slug; } else { $url .= '/tag:' . $slug; } return $url; } private function __getXUrl($url = array()) { if (!$url) { return ''; } if ($url === true || $url == 'remove') { $url = array('tag' => false) + $this->__currentUrl(); } return $this->Html->link('&times;', $url, array('escape' => false)); } private function __currentUrl() { $url = Router::parse($this->request->url); if (!empty($url['pass'])) { $url['?'] = $url['pass']; unset($url['pass']); } if (!empty($url['named'])) { $url = $url['named'] + $url; unset($url['named']); } return $url; }}

webroot/css/style.css

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webroot/css/style.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webroot/scss/style.scss

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,59 @@
1-
$taggable-tags-input-checkbox-size: 11px;
2-
$taggable-tags-input-checkbox-height: 20px;
3-
$taggable-tags-input-checkbox-padding-horizontal: 4px;
1+
$tag-size: 11px;
2+
$tag-line-height: 20px;
3+
$tag-padding-horizontal: 4px;
4+
$tag-border-radius: 2px;
45

5-
$taggable-tags-input-checkbox-selected-bg: #666;
6-
$taggable-tags-input-checkbox-selected-border: #666;
7-
$taggable-tags-input-checkbox-selected-color: #FFF;
6+
$tag-base-color: #FFF;
7+
$tag-base-bg: #666;
8+
$tag-base-border: $tag-base-bg;
89

9-
$taggable-tags-input-checkbox-deselected-bg: #FFF;
10-
$taggable-tags-input-checkbox-deselected-border: #EEE;
11-
$taggable-tags-input-checkbox-deselected-color: #CCC;
10+
$tag-empty-color: #CCC;
11+
$tag-empty-bg: #FFF;
12+
$tag-empty-border: #EEE;
13+
14+
.taggable-tag {
15+
display: inline-block;
16+
vertical-align: top;
17+
&, > a, > a:hover {
18+
color: $tag-base-color;
19+
}
20+
background: $tag-base-bg;
21+
border: 1px solid $tag-base-border;
22+
font-size: $tag-size;
23+
line-height: $tag-line-height;
24+
padding: 0 $tag-padding-horizontal;
25+
border-radius: $tag-border-radius;
26+
}
27+
.taggable-tags-list {
28+
clear: both;
29+
overflow: hidden;
30+
margin-bottom: 10px;
31+
32+
&-item {
33+
margin-right: 4px;
34+
}
35+
}
36+
37+
38+
$taggable-tags-input-checkbox-size: $tag-size;
39+
$taggable-tags-input-checkbox-height: $tag-line-height;
40+
$taggable-tags-input-checkbox-padding-horizontal: $tag-padding-horizontal;
41+
42+
$taggable-tags-input-checkbox-selected-bg: $tag-base-bg;
43+
$taggable-tags-input-checkbox-selected-border: $tag-base-border;
44+
$taggable-tags-input-checkbox-selected-color: $tag-base-color;
45+
46+
$taggable-tags-input-checkbox-deselected-bg: $tag-empty-bg;
47+
$taggable-tags-input-checkbox-deselected-border: $tag-empty-border;
48+
$taggable-tags-input-checkbox-deselected-color: $tag-empty-color;
1249

1350
.taggable-tags-input {
1451
&-checkboxes {
1552
> label, > .form-control {
1653
width: auto;
1754
display: inline-block;
1855
vertical-align: top;
56+
border-radius: $tag-border-radius;
1957

2058
height: auto;
2159
font-size: $taggable-tags-input-checkbox-size;

0 commit comments

Comments
 (0)