diff --git a/Console/Templates/twitterbootstrap/common_params.php b/Console/Templates/twitterbootstrap/common_params.php new file mode 100644 index 0000000..d4eca96 --- /dev/null +++ b/Console/Templates/twitterbootstrap/common_params.php @@ -0,0 +1,57 @@ +params['noAppTestCase'])) { + $useAppTestCase = false; +} + +if (!empty($this->params['property'])) { + $property = true; +} + +if (!empty($this->params['parent'])) { + $parentIncluded = true; + $parentClass = Inflector::classify($this->params['parent']); + $parentIdDbVar = Inflector::underscore($parentClass . 'Id'); + $parentIdVar = Inflector::variable($parentClass . 'Id'); + $singularParentName = Inflector::variable($parentClass); + $singularHumanParentName = Inflector::humanize(Inflector::underscore(Inflector::singularize($parentClass))); + $additionalParams = ', $' . $parentIdVar; + if (!empty($this->params['parentSlug'])) { + $parentSlugged = true; + $parentSlugVar = Inflector::variable($parentClass . 'Slug'); + $additionalParams = ', $' . $parentSlugVar; + } +} + +if (!empty($this->params['slug'])) { + $slugged = true; +} + +if (!empty($this->params['user'])) { + $userIncluded = true; + if (is_string($this->params['user'])) { + $userModel = $this->params['user']; + } else { + $userModel = 'User'; + } +} else { + $userIncluded = false; +} + + +?> \ No newline at end of file diff --git a/Console/Templates/twitterbootstrap/views/form.ctp b/Console/Templates/twitterbootstrap/views/form.ctp new file mode 100644 index 0000000..f554a82 --- /dev/null +++ b/Console/Templates/twitterbootstrap/views/form.ctp @@ -0,0 +1,95 @@ + +Meta->add('title', __('{$pageTitle}')); + "?>\n"; ?> +element('TwitterBootstrap.breadcrumb'); ?>\n"; ?> +TwitterBootstrap->create('{$modelClass}', array(\n" . + "\t'class' => 'validate form-horizontal {$pluralVar}',\n" . + "\t'url' => array('action' => \$this->params['action']{$additionalParams}),\n" . + "\t));\n" . + "\t// this is done to setup the FormHelper insteance to the correct model\n" . + "\t\$this->Form->create('{$modelClass}');\n" . + (strpos($action, 'add') !== false ? '' : + "\t\$this->Form->hidden('id');\n" + ) . + "\t?>\n"; ?> +
+

"; ?>

+TwitterBootstrap->input('{$field}', array(\n" . + "\t\t'label' => '" . Inflector::humanize($field) . "',\n" . + "\t\t'help_inline' => ''\n," . + "\t\t));\n"; + } + } + if (!empty($associations['hasAndBelongsToMany'])) { + foreach ($associations['hasAndBelongsToMany'] as $assocName => $assocData) { + echo "\t\t?>\n" . + "\t\t
\n" . + "\t\t\t\n" . + "\t\t\t
\n" . + "\t\t\t\tForm->input('{$assocName}'); ?>\n"; + "\t\t\t
\n" . + "\t\t
\n" . + "\t\t\n"; +?> +
+
+ + Html->link('Cancel', \$this->here); ?>"; ?> +
+ + Action + + + +
+
+ + diff --git a/Console/Templates/twitterbootstrap/views/index.ctp b/Console/Templates/twitterbootstrap/views/index.ctp new file mode 100644 index 0000000..7475cce --- /dev/null +++ b/Console/Templates/twitterbootstrap/views/index.ctp @@ -0,0 +1,92 @@ + +element('TwitterBootstrap.breadcrumb'); ?>\n"; ?> +
+

"; ?>

+ + + + + + + + \n"; + echo "\t\n"; + foreach ($fields as $field) { + $isKey = false; + if (!empty($associations['belongsTo'])) { + foreach ($associations['belongsTo'] as $alias => $details) { + if ($field === $details['foreignKey']) { + $isKey = true; + echo "\t\t\n"; + break; + } + } + } + if ($isKey !== true) { + // TODO: standardize different display types, eg: date + echo "\t\t\n"; + } + } + // actions as a drop down menu + echo "\t\t\n"; + echo "\t\n"; + echo "\n"; + ?> +
Paginator->sort('{$field}'); ?>"; ?>"; ?>
" . + "\n\t\t\t" . + "\n\t\t\t\tHtml->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>" . + "\n\t\t\t" . + "\n\t\t \n"; + echo "\t\t\t
\n"; + echo "\t\t\t\tAction \n"; + echo "\t\t\t\t
    \n"; + echo "\t\t\t\t\t
  • Html->link(__('View'), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
  • \n"; + echo "\t\t\t\t\t
  • Html->link(__('Edit'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
  • \n"; + echo "\t\t\t\t\t
  • Form->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
  • \n"; + echo "\t\t\t\t
\n"; + echo "\t\t\t
\n"; + echo "\t\t
+ element('TwitterBootstrap.pagination'); ?>\n"; ?> +
+
+
+ + Action + + + +
+
diff --git a/Console/Templates/twitterbootstrap/views/view.ctp b/Console/Templates/twitterbootstrap/views/view.ctp new file mode 100644 index 0000000..6d25e91 --- /dev/null +++ b/Console/Templates/twitterbootstrap/views/view.ctp @@ -0,0 +1,146 @@ + +element('TwitterBootstrap.breadcrumb'); ?>\n"; ?> +
+

"; ?>

+
+ $details) { + if ($field === $details['foreignKey']) { + $isKey = true; + echo "\t\t
\n"; + echo "\t\t
\n\t\t\tHtml->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\t \n\t\t
\n"; + break; + } + } + } + if ($isKey !== true) { + echo "\t\t
\n"; + echo "\t\t
\n\t\t\t\n\t\t\t \n\t\t
\n"; + } +} +?> +
+
+
+

"; ?>

+ +
+ $details): ?> + + $details): + $otherSingularVar = Inflector::variable($alias); + $otherPluralHumanName = Inflector::humanize($details['controller']); + ?> + + diff --git a/View/Elements/breadcrumb.ctp b/View/Elements/breadcrumb.ctp new file mode 100755 index 0000000..bfe7c0f --- /dev/null +++ b/View/Elements/breadcrumb.ctp @@ -0,0 +1,62 @@ +TwitterBootstrap->addCrumb() + * + * @param array $crumbs (optional) overwrites the basic crumbs + * @param array $extra_crumbs (optional) additional to the basic crumbs + * @param array $parent (optional) additional to the basic crumbs, right before the current controller + * @param array $beforeAction (optional) additional to the basic crumbs, right before the current action + * + * Examples: + * $this->element('TwitterBootstrap.breadcrumb') + * $this->element('TwitterBootstrap.breadcrumb', array('parent' => array('Edit' => array('action' => 'edit', $event['Event']['id'])))) + * $this->element('TwitterBootstrap.breadcrumb', array('crumbs' => array( + * 'Root' => array('action' => 'root'), + * 'Parent Page ABC' => array('action' => 'some_action', 'some_param'), + * 'Current Page' => '#', + * ))); + */ +if (!isset($crumbs)) { + // auto-determine basic crumbs + $crumbs = array(); + if (array_key_exists('admin', $this->params) && $this->params['admin']) { + $crumbs['Admin'] = '/admin/'; + } + $action = str_replace($this->params['prefix'] . '_', '', $this->params['action']); + if (!empty($parent) && is_array($parent)) { + $crumbs = array_merge($crumbs, $parent); + } + if ($action=='index') { + $crumbs[Inflector::Humanize($this->params['controller'])] = '#'; + if (!empty($beforeAction) && is_array($beforeAction)) { + $crumbs = array_merge($crumbs, $beforeAction); + } + } else { + $crumbs[Inflector::Humanize($this->params['controller'])] = array('controller' => $this->params['controller'], 'action' => 'index'); + if (!empty($beforeAction) && is_array($beforeAction)) { + $crumbs = array_merge($crumbs, $beforeAction); + } + $crumbs[Inflector::Humanize($action)] = '#'; + } + if (isset($current) && is_string($current) && !empty($current)) { + array_pop($crumbs); + $crumbs[$current] = '#'; + } +} +if (isset($extra_crumbs) && is_array($extra_crumbs)) { + $crumbs = array_merge($crumbs, $extra_crumbs); +} +if (!empty($crumbs)) { + foreach ($crumbs as $text => $url) { + if ($text == "Admin") { + echo $this->TwitterBootstrap->addCrumb("".strtoupper($text)."", $url, array('escape' => false)); + } else { + echo $this->TwitterBootstrap->addCrumb($text, $url); + } + } + echo $this->TwitterBootstrap->breadcrumbs(); +} diff --git a/View/Elements/pagination.ctp b/View/Elements/pagination.ctp new file mode 100755 index 0000000..13bc045 --- /dev/null +++ b/View/Elements/pagination.ctp @@ -0,0 +1,82 @@ +Paginator->hasPrev() || $this->Paginator->hasNext()); +if (!empty($this->params['prefix']) && $this->params['prefix']=='admin') { + $showPagination = $showTotal = true; +} +$params = $this->Paginator->params(); +?> + + + diff --git a/View/Example.ctp b/View/Example.ctp new file mode 100755 index 0000000..327b66e --- /dev/null +++ b/View/Example.ctp @@ -0,0 +1,330 @@ +

Comparison and Reference

+
+

Horizontal Form Html

+
+
+
+ +
+ +

In addition to freeform text, any HTML5 text-based input appears like so.

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +

Note: Labels surround all the options for much larger click areas and a more usable form.

+
+
+
+ +
+ + +
+
+
+ +
+ + + +
+
+
+ +
+
+ @ +
+

Here's some help text

+
+
+
+ +
+
+ .00 +
+ Here's more help text +
+
+
+ +
+
+ $.00 +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
+
+
+
+

Horizontal Form Helper

+ Form->create('Member', array('class' => 'form-horizontal')); ?> +
+ TwitterBootstrap->input('text_input', array( + 'label' => 'Text input', + 'help_block' => 'In addition to freeform text, any HTML5 text-based input appears like so.', + )); ?> + TwitterBootstrap->input('checkbox', array( + 'label' => 'Checkbox', + 'type' => 'checkbox', + 'checkbox_label' => 'Option one is this and that—be sure to include why it\'s great' + )); ?> + TwitterBootstrap->input('select_list', array( + 'options' => array('Something', '2', '3', '4'), + )); ?> + TwitterBootstrap->input('multicon_select', array( + 'label' => 'Multicon-select', + 'options' => array('1', '2', '3', '4'), + 'multiple' => 'multiple', + )); ?> + TwitterBootstrap->input('file_input', array( + 'type' => 'file', + )); ?> + TwitterBootstrap->input('textarea', array( + 'type' => 'textarea', + 'rows' => 3, + 'class' => 'input-xlarge', + )); ?> + TwitterBootstrap->input('xcheckboxes', array( + 'label' => 'Checkboxes', + 'legend' => false, + 'type' => "select", + 'multiple' => "checkbox", + 'options' => array( + "Option one is this and that—be sure to include why it's great", + "Option two can also be checked and included in form results", + "Option three can—yes, you guessed it—also be checked and included in form results", + ), + 'help_block' => "Note: Labels surround all the options for much larger click areas and a more usable form." + )); ?> + TwitterBootstrap->radio('radio_buttons', array( + 'label' => 'Radio buttons', + 'legend' => false, + 'type' => "radio", + 'options' => array( + "Option one is this and that—be sure to include why it's great", + "Option two can is something else and selecting it will deselect option one", + ) + )); ?> + TwitterBootstrap->input('inline_checkboxes', array( + 'label' => 'Inline checkboxes', + 'legend' => false, + 'multiple' => "checkbox", + 'class' => "checkbox inline", + 'separator' => " ", + 'options' => array(1, 2, 3), + )); ?> + TwitterBootstrap->input('prepend_text', array( + 'label' => 'Prepend text', + 'class' => 'span2', + 'prepend' => '@', + 'help_block' => "Here's some help text", + )); ?> + TwitterBootstrap->input('append_text', array( + 'label' => 'Append text', + 'class' => 'span2', + 'append' => '.00', + 'help_inline' => "Here's more help text", + )); ?> + TwitterBootstrap->input('a_p_text', array( + 'label' => 'Append and prepend', + 'class' => 'span2', + 'prepend' => '@', + 'append' => '.00', + )); ?> + TwitterBootstrap->input('a_button_text', array( + 'label' => 'Append with button', + 'class' => 'span2', + 'append' => '', + )); ?> + TwitterBootstrap->input('a_twobutton_text', array( + 'label' => 'Two-button append', + 'class' => 'span2', + 'append' => '', + )); ?> +
+ + +
+
+ +
+
+ 'Male', 'female' => 'Female', 'both' => 'Both', 'other' => 'Other'); +$optionsColors = array('red' => 'Red', 'orange' => 'Orange', 'yellow' => 'Yellow', 'green' => 'Green', 'blue' => 'Blue', 'indigo' => 'Indigo', 'violet' => 'Violet', 'black' => 'Black'); +$optionsPets = array('dogs' => 'Dogs', 'cats' => 'Cats', 'fish' => 'Fish', 'birds' => 'Birds'); +$optionsGroups = array(1 => 'Admin', 2 => 'Really Cool Guys', 3 => 'Underwear Models'); +?> +
+

Second Test - automagics

+ Form->create('Member', array('class' => 'form-horizontal')); ?> +
+ TwitterBootstrap->input('id'); ?> + TwitterBootstrap->input('email'); ?> + TwitterBootstrap->input('first_name'); ?> + TwitterBootstrap->input('last_name'); ?> + TwitterBootstrap->input('is_active'); ?> + TwitterBootstrap->radio('gender', array('label' => 'Gender', 'options' => $optionsGender)); ?> + TwitterBootstrap->input('favorite_color', array('label' => 'Favorite Color', 'options' => $optionsColors)); ?> + TwitterBootstrap->input('hated_color', array('label' => 'Hated Colors', 'multiple' => 'checkbox', 'options' => $optionsColors)); ?> + TwitterBootstrap->input('pets', array( + 'multiple' => "checkbox", + 'class' => "checkbox inline", + 'options' => $optionsPets, + )); ?> + TwitterBootstrap->input('salary', array( + 'class' => 'span2', + 'prepend' => '$', + 'append' => 'per year', + )); ?> + TwitterBootstrap->input('Group.Group', array( + 'multiple' => "checkbox", + 'options' => $optionsGroups, + )); ?> +
+ +
+
+

Third Test - automagics + defaults

+ data, which gets merged into $this->Form->data + $this->Form->data = array( + 'Member' => array( + 'id' => 12345, + 'email' => 'member@domain.com', + 'first_name' => 'Jane', + 'last_name' => 'Doe', + 'is_active' => 1, + 'gender' => 'female', + 'favorite_color' => 'blue', + 'hated_colors' => array('green', 'orange', 'violet'), + 'pets' => array('dogs', 'fish'), + 'salary' => '1,000,000', + ), + 'Group' => array( + array('id' => 1, 'title' => 'admin'), + array('id' => 3, 'title' => 'model'), + ), + ); + ?> + Form->create('Member', array('class' => 'form-horizontal')); ?> +
+ TwitterBootstrap->input('id'); ?> + TwitterBootstrap->input('email'); ?> + TwitterBootstrap->input('first_name'); ?> + TwitterBootstrap->input('last_name'); ?> + TwitterBootstrap->input('is_active'); ?> + TwitterBootstrap->radio('gender', array('label' => 'Gender', 'options' => $optionsGender)); ?> + TwitterBootstrap->input('favorite_color', array('label' => 'Favorite Color', 'options' => $optionsColors)); ?> + TwitterBootstrap->input('hated_colors', array('label' => 'Hated Colors', 'multiple' => 'checkbox', 'options' => $optionsColors)); ?> + TwitterBootstrap->input('pets', array( + 'multiple' => "checkbox", + 'class' => "checkbox inline", + 'options' => $optionsPets, + )); ?> + TwitterBootstrap->input('salary', array( + 'class' => 'span2', + 'prepend' => '$', + 'append' => 'per year', + )); ?> + TwitterBootstrap->input('Group.Group', array( + 'multiple' => "checkbox", + 'options' => $optionsGroups, + )); ?> +
+ +
\ No newline at end of file diff --git a/View/Helper/BootstrapFormHelper.php b/View/Helper/BootstrapFormHelper.php index bddecc5..7201ab0 100644 --- a/View/Helper/BootstrapFormHelper.php +++ b/View/Helper/BootstrapFormHelper.php @@ -230,7 +230,7 @@ public function input($field, $options = array()) { $options['state'] = 'error'; $help_block = $this->Html->tag( "span", - $this->error($options['field']), + $this->error($options['field'], null, array('escape' => (isset($options['escapeError']) && $options['escapeError'] === false) ? false : true)), array("class" => "help-block") ); } @@ -347,7 +347,7 @@ public function _helpMarkup($options) { * @access public * @return string */ - public function radio($field, $options = array()) { + public function radio($field, $options = array(), $attributes = array()) { if (is_array($field)) { $options = $field; } else { @@ -360,12 +360,14 @@ public function radio($field, $options = array()) { unset($options["options"]); $inputs = ""; $hiddenField = (isset($options['hiddenField']) && $options['hiddenField']); + $attributes = Set::merge( + array("label" => false, 'hiddenField' => $hiddenField), + $attributes + ); foreach ($opt as $key => $val) { - $input = parent::radio( - $options["field"], - array($key => $val), - array("label" => false, 'hiddenField' => $hiddenField) - ); + $checked = ($key === Re::pluck($options, '/value')); + $attributes['checked'] = $checked; + $input = parent::radio($options["field"], array($key => $val), $attributes); $id = array(); preg_match_all("/id=\"[a-zA-Z0-9_-]*\"/", $input, $id); if (!empty($id[0])) { diff --git a/View/Helper/TwitterBootstrapHelper.php b/View/Helper/TwitterBootstrapHelper.php index 9a35b31..16ee3c9 100644 --- a/View/Helper/TwitterBootstrapHelper.php +++ b/View/Helper/TwitterBootstrapHelper.php @@ -40,6 +40,13 @@ public function search($name = null, $options = array()) { return $this->BootstrapForm->search($name, $options); } + public function create($model = null, $options = array()) { + if (empty($options['class'])) { + $options['class'] = 'form-horizontal'; + } + return $this->BootstrapForm->create($model, $options); + } + public function input($field, $options = array()) { return $this->BootstrapForm->input($field, $options); } @@ -84,6 +91,10 @@ public function add_crumb($title, $url, $options = array()) { return $this->BootstrapHtml->addCrumb($title, $url, $options); } + public function addCrumb($title, $url, $options = array()) { + return $this->BootstrapHtml->addCrumb($title, $url, $options); + } + public function label($message = "", $style = "", $options = array()) { return $this->Bootstrap->label($message, $style, $options); }