/** * Renders the sort links. * @return string the rendering result */ protected function renderSortLinks() { $attributes = empty($this->attributes) ? array_keys($this->sort->attributes) : $this->attributes; $links = []; foreach ($attributes as $name) { $links[] = $this->sort->link($name, $this->linkOptions); } return Html::ul($links, array_merge($this->options, ['encode' => false])); }
/** * @inheritdoc */ public function clientValidateAttribute($model, $attribute, $view) { $pattern = Html::escapeJsRegularExpression($this->pattern); $options = ['pattern' => new JsExpression($pattern), 'not' => $this->not, 'message' => Leaps::$app->getI18n()->format($this->message, ['attribute' => $model->getAttributeLabel($attribute)], Leaps::$app->language)]; if ($this->skipOnEmpty) { $options['skipOnEmpty'] = 1; } ValidationAsset::register($view); return 'leaps.validation.regularExpression(value, messages, ' . Json::htmlEncode($options) . ');'; }
/** * Initializes the widget. * If you override this method, make sure you call the parent implementation first. */ public function init() { if ($this->name === null && !$this->hasModel()) { throw new InvalidConfigException("Either 'name', or 'model' and 'attribute' properties must be specified."); } if (!isset($this->options['id'])) { $this->options['id'] = $this->hasModel() ? Html::getInputId($this->model, $this->attribute) : $this->getId(); } parent::init(); }
/** * Initializes the default button rendering callbacks. */ protected function initDefaultButtons() { if (!isset($this->buttons['view'])) { $this->buttons['view'] = function ($url, $model, $key) { $options = array_merge(['title' => Leaps::t('leaps', 'View'), 'aria-label' => Leaps::t('leaps', 'View'), 'data-pjax' => '0'], $this->buttonOptions); return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, $options); }; } if (!isset($this->buttons['update'])) { $this->buttons['update'] = function ($url, $model, $key) { $options = array_merge(['title' => Leaps::t('leaps', 'Update'), 'aria-label' => Leaps::t('leaps', 'Update'), 'data-pjax' => '0'], $this->buttonOptions); return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options); }; } if (!isset($this->buttons['delete'])) { $this->buttons['delete'] = function ($url, $model, $key) { $options = array_merge(['title' => Leaps::t('leaps', 'Delete'), 'aria-label' => Leaps::t('leaps', 'Delete'), 'data-confirm' => Leaps::t('leaps', 'Are you sure you want to delete this item?'), 'data-method' => 'post', 'data-pjax' => '0'], $this->buttonOptions); return Html::a('<span class="glyphicon glyphicon-trash"></span>', $url, $options); }; } }
/** * Renders a single breadcrumb item. * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional. * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link. * @return string the rendering result * @throws InvalidConfigException if `$link` does not have "label" element. */ protected function renderItem($link, $template) { $encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels); if (array_key_exists('label', $link)) { $label = $encodeLabel ? Html::encode($link['label']) : $link['label']; } else { throw new InvalidConfigException('The "label" element is required for each link.'); } if (isset($link['template'])) { $template = $link['template']; } if (isset($link['url'])) { $options = $link; unset($options['template'], $options['label'], $options['url']); $link = Html::a($label, $link['url'], $options); } else { $link = $label; } return strtr($template, ['{link}' => $link]); }
/** * Renders the detail view. * This is the main entry of the whole detail view rendering. */ public function run() { $rows = []; $i = 0; foreach ($this->attributes as $attribute) { $rows[] = $this->renderAttribute($attribute, $i++); } $options = $this->options; $tag = ArrayHelper::remove($options, 'tag', 'table'); echo Html::tag($tag, implode("\n", $rows), $options); }
/** * Normalizes the [[items]] property to remove invisible items and activate certain items. * @param array $items the items to be normalized. * @param boolean $active whether there is an active child menu item. * @return array the normalized menu items */ protected function normalizeItems($items, &$active) { foreach ($items as $i => $item) { if (isset($item['visible']) && !$item['visible']) { unset($items[$i]); continue; } if (!isset($item['label'])) { $item['label'] = ''; } $encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels; $items[$i]['label'] = $encodeLabel ? Html::encode($item['label']) : $item['label']; $hasActiveChild = false; if (isset($item['items'])) { $items[$i]['items'] = $this->normalizeItems($item['items'], $hasActiveChild); if (empty($items[$i]['items']) && $this->hideEmptyItems) { unset($items[$i]['items']); if (!isset($item['url'])) { unset($items[$i]); continue; } } } if (!isset($item['active'])) { if ($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive($item)) { $active = $items[$i]['active'] = true; } else { $items[$i]['active'] = false; } } elseif ($item['active']) { $active = true; } } return array_values($items); }
/** * @inheritdoc */ protected function renderFilterCellContent() { if (is_string($this->filter)) { return $this->filter; } $model = $this->grid->filterModel; if ($this->filter !== false && $model instanceof Model && $this->attribute !== null && $model->isAttributeActive($this->attribute)) { if ($model->hasErrors($this->attribute)) { Html::addCssClass($this->filterOptions, 'has-error'); $error = ' ' . Html::error($model, $this->attribute, $this->grid->filterErrorOptions); } else { $error = ''; } if (is_array($this->filter)) { $options = array_merge(['prompt' => ''], $this->filterInputOptions); return Html::activeDropDownList($model, $this->attribute, $this->filter, $options) . $error; } else { return Html::activeTextInput($model, $this->attribute, $this->filterInputOptions) . $error; } } else { return parent::renderFilterCellContent(); } }
/** * @inheritdoc */ public function clientValidateAttribute($model, $attribute, $view) { $options = ['operator' => $this->operator, 'type' => $this->type]; if ($this->compareValue !== null) { $options['compareValue'] = $this->compareValue; $compareValue = $this->compareValue; } else { $compareAttribute = $this->compareAttribute === null ? $attribute . '_repeat' : $this->compareAttribute; $compareValue = $model->getAttributeLabel($compareAttribute); $options['compareAttribute'] = Html::getInputId($model, $compareAttribute); } if ($this->skipOnEmpty) { $options['skipOnEmpty'] = 1; } $options['message'] = Leaps::$app->getI18n()->format($this->message, ['attribute' => $model->getAttributeLabel($attribute), 'compareAttribute' => $compareValue, 'compareValue' => $compareValue], Leaps::$app->language); ValidationAsset::register($view); return 'leaps.validation.compare(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');'; }
/** * Returns the JS options for the field. * @return array the JS options */ protected function getClientOptions() { $attribute = Html::getAttributeName($this->attribute); if (!in_array($attribute, $this->model->activeAttributes(), true)) { return []; } $enableClientValidation = $this->enableClientValidation || $this->enableClientValidation === null && $this->form->enableClientValidation; $enableAjaxValidation = $this->enableAjaxValidation || $this->enableAjaxValidation === null && $this->form->enableAjaxValidation; if ($enableClientValidation) { $validators = []; foreach ($this->model->getActiveValidators($attribute) as $validator) { /* @var $validator \Leaps\Validator\Validator */ $js = $validator->clientValidateAttribute($this->model, $attribute, $this->form->getView()); if ($validator->enableClientValidation && $js != '') { if ($validator->whenClient !== null) { $js = "if (({$validator->whenClient})(attribute, value)) { {$js} }"; } $validators[] = $js; } } } if (!$enableAjaxValidation && (!$enableClientValidation || empty($validators))) { return []; } $options = []; $inputID = Html::getInputId($this->model, $this->attribute); $options['id'] = $inputID; $options['name'] = $this->attribute; $options['container'] = isset($this->selectors['container']) ? $this->selectors['container'] : ".field-{$inputID}"; $options['input'] = isset($this->selectors['input']) ? $this->selectors['input'] : "#{$inputID}"; if (isset($this->selectors['error'])) { $options['error'] = $this->selectors['error']; } elseif (isset($this->errorOptions['class'])) { $options['error'] = '.' . implode('.', preg_split('/\\s+/', $this->errorOptions['class'], -1, PREG_SPLIT_NO_EMPTY)); } else { $options['error'] = isset($this->errorOptions['tag']) ? $this->errorOptions['tag'] : 'span'; } $options['encodeError'] = !isset($this->errorOptions['encode']) || $this->errorOptions['encode']; if ($enableAjaxValidation) { $options['enableAjaxValidation'] = true; } foreach (['validateOnChange', 'validateOnBlur', 'validateOnType', 'validationDelay'] as $name) { $options[$name] = $this->{$name} === null ? $this->form->{$name} : $this->{$name}; } if (!empty($validators)) { $options['validate'] = new JsExpression("function (attribute, value, messages, deferred, \$form) {" . implode('', $validators) . '}'); } // only get the options that are different from the default ones (set in leaps.activeForm.js) return array_diff_assoc($options, ['validateOnChange' => true, 'validateOnBlur' => true, 'validateOnType' => false, 'validationDelay' => 500, 'encodeError' => true, 'error' => '.help-block']); }
/** * Renders the widget. */ public function run() { $this->registerClientScript(); if ($this->hasModel()) { $input = Html::activeTextInput($this->model, $this->attribute, $this->options); } else { $input = Html::textInput($this->name, $this->value, $this->options); } $route = $this->captchaAction; if (is_array($route)) { $route['v'] = uniqid(); } else { $route = [$route, 'v' => uniqid()]; } $image = Html::img($route, $this->imageOptions); echo strtr($this->template, ['{input}' => $input, '{image}' => $image]); }
/** * Validates an array of model instances and returns an error message array indexed by the attribute IDs. * This is a helper method that simplifies the way of writing AJAX validation code for tabular input. * * For example, you may use the following code in a controller action to respond * to an AJAX validation request: * * ~~~ * // ... load $models ... * if (Leaps::$app->request->isAjax) { * Leaps::$app->response->format = Response::FORMAT_JSON; * return ActiveForm::validateMultiple($models); * } * // ... respond to non-AJAX request ... * ~~~ * * @param array $models an array of models to be validated. * @param mixed $attributes list of attributes that should be validated. * If this parameter is empty, it means any attribute listed in the applicable * validation rules should be validated. * @return array the error message array indexed by the attribute IDs. */ public static function validateMultiple($models, $attributes = null) { $result = []; /* @var $model Model */ foreach ($models as $i => $model) { $model->validate($attributes); foreach ($model->getErrors() as $attribute => $errors) { $result[Html::getInputId($model, "[{$i}]" . $attribute)] = $errors; } } return $result; }
?> </head> <body> <?php $this->beginBody(); ?> <div class="wrap"> <?php NavBar::begin(['brandLabel' => 'CodeForge', 'brandUrl' => Leaps::$app->homeUrl, 'options' => ['class' => 'navbar-inverse navbar-fixed-top']]); $menuItems = [['label' => '威客', 'url' => ['/site/index']], ['label' => '源代码', 'url' => ['/site/code']], ['label' => '活动', 'url' => ['/event']], ['label' => 'CF币', 'url' => ['/site/cfcoin']], ['label' => '关于我们', 'url' => ['/site/about']], ['label' => '联系我们', 'url' => ['/site/contact']]]; if (Leaps::$app->user->isGuest) { $menuItems[] = ['label' => '注册', 'url' => ['/site/signup']]; $menuItems[] = ['label' => '登陆', 'url' => ['/site/login']]; } else { $menuItems[] = '<li>' . Html::beginForm(['/site/logout'], 'post') . Html::submitButton('Logout (' . Leaps::$app->user->identity->username . ')', ['class' => 'btn btn-link']) . Html::endForm() . '</li>'; } echo Nav::widget(['options' => ['class' => 'navbar-nav navbar-right'], 'items' => $menuItems]); NavBar::end(); ?> <div class="container"> <?php echo Breadcrumbs::widget(['links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : []]); ?> <?php echo ''; ?> <?php echo $content; ?>
/** * @inheritdoc */ protected function renderDataCellContent($model, $key, $index) { if ($this->checkboxOptions instanceof Closure) { $options = call_user_func($this->checkboxOptions, $model, $key, $index, $this); } else { $options = $this->checkboxOptions; if (!isset($options['value'])) { $options['value'] = is_array($key) ? json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $key; } } return Html::checkbox($this->name, !empty($options['checked']), $options); }
/** * Formats the value as a hyperlink. * @param mixed $value the value to be formatted. * @param array $options the tag options in terms of name-value pairs. See [[Html::a()]]. * @return string the formatted result. */ public function asUrl($value, $options = []) { if ($value === null) { return $this->nullDisplay; } $url = $value; if (strpos($url, '://') === false) { $url = 'http://' . $url; } return Html::a(Html::encode($value), $url, $options); }
/** * Renders the filter cell. */ public function renderFilterCell() { return Html::tag('td', $this->renderFilterCellContent(), $this->filterOptions); }
/** * Renders a single data model. * @param mixed $model the data model to be rendered * @param mixed $key the key value associated with the data model * @param integer $index the zero-based index of the data model in the model array returned by [[dataProvider]]. * @return string the rendering result */ public function renderItem($model, $key, $index) { if ($this->itemView === null) { $content = $key; } elseif (is_string($this->itemView)) { $content = $this->getView()->render($this->itemView, array_merge(['model' => $model, 'key' => $key, 'index' => $index, 'widget' => $this], $this->viewParams)); } else { $content = call_user_func($this->itemView, $model, $key, $index, $this); } $options = $this->itemOptions; $tag = ArrayHelper::remove($options, 'tag', 'div'); if ($tag !== false) { $options['data-key'] = is_array($key) ? json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : (string) $key; return Html::tag($tag, $content, $options); } else { return $content; } }
/** * Renders a table row with the given data model and key. * @param mixed $model the data model to be rendered * @param mixed $key the key associated with the data model * @param integer $index the zero-based index of the data model among the model array returned by [[dataProvider]]. * @return string the rendering result */ public function renderTableRow($model, $key, $index) { $cells = []; /* @var $column Column */ foreach ($this->columns as $column) { $cells[] = $column->renderDataCell($model, $key, $index); } if ($this->rowOptions instanceof Closure) { $options = call_user_func($this->rowOptions, $model, $key, $index, $this); } else { $options = $this->rowOptions; } $options['data-key'] = is_array($key) ? json_encode($key) : (string) $key; return Html::tag('tr', implode('', $cells), $options); }
/** * @inheritdoc */ public function run() { $this->registerClientScript(); if ($this->hasModel()) { echo Html::activeInput($this->type, $this->model, $this->attribute, $this->options); } else { echo Html::input($this->type, $this->name, $this->value, $this->options); } }
/** * Renders a page button. * You may override this method to customize the generation of page buttons. * @param string $label the text label for the button * @param integer $page the page number * @param string $class the CSS class for the page button. * @param boolean $disabled whether this page button is disabled * @param boolean $active whether this page button is active * @return string the rendering result */ protected function renderPageButton($label, $page, $class, $disabled, $active) { $options = ['class' => $class === '' ? null : $class]; if ($active) { Html::addCssClass($options, $this->activePageCssClass); } if ($disabled) { Html::addCssClass($options, $this->disabledPageCssClass); return Html::tag('li', Html::tag('span', $label), $options); } $linkOptions = $this->linkOptions; $linkOptions['data-page'] = $page; return Html::tag('li', Html::a($label, $this->pagination->createUrl($page), $linkOptions), $options); }
?> <?php echo $form->field($model, 'username')->icon('fa-user')->tooltip('lalala'); ?> <?php echo $form->field($model, 'password')->passwordInput(); ?> <div style="color: #999; margin: 1em 0"> If you forgot your password you can <?php echo Html::a('reset it', ['site/request-password-reset']); ?> . </div> <div class="form-group"> <?php echo Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']); ?> </div> <?php ActiveForm::end(); ?> </div> </div> </div>
/** * Renders the content to be inserted at the end of the body section. * The content is rendered using the registered JS code blocks and files. * @param boolean $ajaxMode whether the view is rendering in AJAX mode. * If true, the JS scripts registered at [[POS_READY]] and [[POS_LOAD]] positions * will be rendered at the end of the view like normal scripts. * @return string the rendered content */ protected function renderBodyEndHtml($ajaxMode) { $lines = []; if (!empty($this->jsFiles[self::POS_END])) { $lines[] = implode("\n", $this->jsFiles[self::POS_END]); } if ($ajaxMode) { $scripts = []; if (!empty($this->js[self::POS_END])) { $scripts[] = implode("\n", $this->js[self::POS_END]); } if (!empty($this->js[self::POS_READY])) { $scripts[] = implode("\n", $this->js[self::POS_READY]); } if (!empty($this->js[self::POS_LOAD])) { $scripts[] = implode("\n", $this->js[self::POS_LOAD]); } if (!empty($scripts)) { $lines[] = Html::script(implode("\n", $scripts), ['type' => 'text/javascript']); } } else { if (!empty($this->js[self::POS_END])) { $lines[] = Html::script(implode("\n", $this->js[self::POS_END]), ['type' => 'text/javascript']); } if (!empty($this->js[self::POS_READY])) { $js = "jQuery(document).ready(function () {\n" . implode("\n", $this->js[self::POS_READY]) . "\n});"; $lines[] = Html::script($js, ['type' => 'text/javascript']); } if (!empty($this->js[self::POS_LOAD])) { $js = "jQuery(window).load(function () {\n" . implode("\n", $this->js[self::POS_LOAD]) . "\n});"; $lines[] = Html::script($js, ['type' => 'text/javascript']); } } return empty($lines) ? '' : implode("\n", $lines); }
/** * Renders the summary text. */ public function renderSummary() { $count = $this->dataProvider->getCount(); if ($count <= 0) { return ''; } $summaryOptions = $this->summaryOptions; $tag = ArrayHelper::remove($summaryOptions, 'tag', 'div'); if (($pagination = $this->dataProvider->getPagination()) !== false) { $totalCount = $this->dataProvider->getTotalCount(); $begin = $pagination->getPage() * $pagination->pageSize + 1; $end = $begin + $count - 1; if ($begin > $end) { $begin = $end; } $page = $pagination->getPage() + 1; $pageCount = $pagination->pageCount; if (($summaryContent = $this->summary) === null) { return Html::tag($tag, Leaps::t('leaps', 'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.', ['begin' => $begin, 'end' => $end, 'count' => $count, 'totalCount' => $totalCount, 'page' => $page, 'pageCount' => $pageCount]), $summaryOptions); } } else { $begin = $page = $pageCount = 1; $end = $totalCount = $count; if (($summaryContent = $this->summary) === null) { return Html::tag($tag, Leaps::t('leaps', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', ['begin' => $begin, 'end' => $end, 'count' => $count, 'totalCount' => $totalCount, 'page' => $page, 'pageCount' => $pageCount]), $summaryOptions); } } return Leaps::$app->getI18n()->format($summaryContent, ['begin' => $begin, 'end' => $end, 'count' => $count, 'totalCount' => $totalCount, 'page' => $page, 'pageCount' => $pageCount], Leaps::$app->language); }
/** * @inheritdoc */ public function run() { if (!$this->requiresPjax()) { echo Html::endTag('div'); $this->registerClientScript(); return; } $view = $this->getView(); $view->endBody(); // Do not re-send css files as it may override the css files that were loaded after them. // It should be removed once pjax supports loading only missing css files $view->cssFiles = null; $view->endPage(true); $content = ob_get_clean(); // only need the content enclosed within this widget $response = Leaps::$app->getResponse(); $response->clearOutputBuffers(); $response->setStatusCode(200); $response->format = Response::FORMAT_HTML; $response->content = $content; $response->send(); Leaps::$app->end(); }
/** * Returns all uploaded files for the given model attribute. * @param \Leaps\Base\Model $model the data model * @param string $attribute the attribute name. The attribute name may contain array indexes * for tabular file uploading, e.g. '[1]file'. * @return UploadedFile[] array of UploadedFile objects. * Empty array is returned if no available file was found for the given attribute. */ public static function getInstances($model, $attribute) { $name = Html::getInputName($model, $attribute); return static::getInstancesByName($name); }
/** * Generates a hyperlink that links to the sort action to sort by the specified attribute. * Based on the sort direction, the CSS class of the generated hyperlink will be appended * with "asc" or "desc". * * @param string $attribute the attribute name by which the data should be sorted by. * @param array $options additional HTML attributes for the hyperlink tag. * There is one special attribute `label` which will be used as the label of the hyperlink. * If this is not set, the label defined in [[attributes]] will be used. * If no label is defined, [[\Leaps\Helper\Inflector::camel2words()]] will be called to get a label. * Note that it will not be HTML-encoded. * @return string the generated hyperlink * @throws InvalidConfigException if the attribute is unknown */ public function link($attribute, $options = []) { if (($direction = $this->getAttributeOrder($attribute)) !== null) { $class = $direction === SORT_DESC ? 'desc' : 'asc'; if (isset($options['class'])) { $options['class'] .= ' ' . $class; } else { $options['class'] = $class; } } $url = $this->createUrl($attribute); $options['data-sort'] = $this->createSortParam($attribute); if (isset($options['label'])) { $label = $options['label']; unset($options['label']); } else { if (isset($this->attributes[$attribute]['label'])) { $label = $this->attributes[$attribute]['label']; } else { $label = Inflector::camel2words($attribute); } } return Html::a($label, $url, $options); }