diff --git a/README.md b/README.md index 086bc24..3112882 100755 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ The following widgets are currently available: * Alert * Breadcrumbs * Button +* Carousel * Chip * DatePicker * DetailView @@ -70,25 +71,21 @@ The following widgets are currently available: * GridView with ActionColumn * Icon * LinkPager +* MaterialBox * Modal * Nav * NavBar +* Parallax * Progress * RangeInput * Select * SideNav +* Slider * Spinner * SubmitButton * SwitchButton * TimePicker -These widgets are planned for development: - -* Card -* Collapsible -* Collection -* Toast - ## Gii support If you are creating your CRUD controller and view files using Gii you can get materialized view files by integrating the adapted Gii templates. @@ -127,6 +124,7 @@ Unfortunately the issue still exists in the latest release, but can be fixed tem Hopefully one of the upcoming releases of Materialize will fix the issue. + ## Sample layout As of version 1.0.6 there is a sample layout file included in the package. You can use this file to get inspiration for @@ -136,6 +134,13 @@ You can find the sample layout file in ```src/layout/main.php```. ## Change log +### 1.5.0 - 2017-06-05 +* added [Carousel](https://github.com/MacGyer/yii2-materializecss/blob/master/src/widgets/media/Carousel.php) +* added [MaterialBox](https://github.com/MacGyer/yii2-materializecss/blob/master/src/widgets/media/MaterialBox.php) +* added [Parallax](https://github.com/MacGyer/yii2-materializecss/blob/master/src/widgets/media/Parallax.php) +* added [Slider](https://github.com/MacGyer/yii2-materializecss/blob/master/src/widgets/media/Slider.php) +* improved sample layout + ### 1.4.0 - 2017-06-05 * added [RangeInput](https://github.com/MacGyer/yii2-materializecss/blob/master/src/widgets/form/RangeInput.php) * updated Materialize to v0.98.2 diff --git a/composer.json b/composer.json index 7edc57a..983bb3e 100755 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "role": "Developer" } ], - "version": "1.4.0", + "version": "1.5.0", "require": { "php": ">=5.6.0", "yiisoft/yii2": "~2.0.0", diff --git a/src/layout/main.php b/src/layout/main.php index db893ec..679943b 100644 --- a/src/layout/main.php +++ b/src/layout/main.php @@ -17,6 +17,7 @@ + <?= Html::encode($this->title) ?> @@ -106,4 +107,4 @@ endBody() ?> -endPage() ?> \ No newline at end of file +endPage() ?> diff --git a/src/widgets/media/Carousel.php b/src/widgets/media/Carousel.php new file mode 100644 index 0000000..83b14d0 --- /dev/null +++ b/src/widgets/media/Carousel.php @@ -0,0 +1,188 @@ +not be encoded. + * + * ```php + * 'itemOptions' => [ + * 'class' => 'amber white-text' // this class will be used for all carousel elements + * ], + * 'items' => [ + * [ + * 'content' => Html::img('http://lorempixel.com/800/800/sports/2'), + * ], + * [ + * 'content' => '

Carousel item heading

Arbitrary content

' + * 'options' => ['class' => 'carusel-item-override'] // overrides $itemOptions + * ] + * ], + * 'fixedItemOptions' => [ + * 'tag' => 'p', + * 'content' => 'Some content', + * ], + * ``` + * @author Christoph Erdmann + * @package widgets + * @subpackage media + * + * @see http://materializecss.com/carousel.html + */ +class Carousel extends BaseWidget +{ + /** + * @var array the HTML attributes for the carousel container tag. + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $carouselOptions = []; + + /** + * @var array the HTML attributes for each carousel item's tag. + * These options will be merged with the individual item options. + * + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $itemOptions = []; + + /** + * @var false|array the configuration for the fixed item. + * + * The following special options are recognized: + * - tag: the fixed item's HTML tag name + * - content: the content of the fixed item. Please note: this can be HTML and will not be encoded. + * + * If you do not want the fixed item to be rendered, set this option to `false`. + * @see http://materializecss.com/carousel.html#special + */ + public $fixedItemOptions = false; + + /** + * @var array the carousel items. + * Provide a sub-array for each item which can have the keys `tag`, `content` and `options`. + */ + public $items = []; + + /** + * @var boolean whether the carousel has full width. + */ + public $fullWidth = false; + + /** + * @var boolean whether to show navigation indicators. + */ + public $showIndicators = false; + + /** + * @var boolean whether to start with first slide at the end. + * @see http://materializecss.com/carousel.html#options + */ + public $noWrap = false; + + /** + * Initialize the widget. + */ + public function init() + { + parent::init(); + + Html::addCssClass($this->carouselOptions, ['plugin' => 'carousel']); + if ($this->fullWidth) { + Html::addCssClass($this->carouselOptions, ['fullwidth' => 'carousel-slider']); + $this->clientOptions['fullWidth'] = true; + } + + $this->clientOptions['noWrap'] = $this->noWrap; + $this->clientOptions['indicators'] = $this->showIndicators; + + $this->registerPlugin('carousel', '.carousel'); + } + + /** + * Execute the widget. + */ + public function run() + { + $tag = ArrayHelper::remove($this->options, 'tag', 'div'); + $html[] = Html::beginTag($tag, $this->options); + $html[] = Html::beginTag('div', $this->carouselOptions); + $html[] = $this->renderFixedItem(); + $html[] = $this->renderItems(); + $html[] = Html::endTag('div'); + $html[] = Html::endTag($tag); + + return implode("\n", $html); + } + + /** + * Parses all [[items]] and renders item list. + * + * @return string the item list markup + */ + protected function renderItems() + { + if (!$this->items) { + return ''; + } + + $html = []; + + foreach ($this->items as $item) { + $html[] = $this->renderItem($item); + } + + return implode("\n", $html); + } + + /** + * Renders a single carousel item. + * + * @param array $item the item configuration + * @return string the item markup + */ + protected function renderItem($item = []) + { + $tag = ArrayHelper::getValue($item, 'tag', 'div'); + $content = ArrayHelper::getValue($item, 'content', ''); + $options = ArrayHelper::getValue($item, 'options', []); + $options = ArrayHelper::merge($this->itemOptions, $options); + + Html::addCssClass($options, ['item' => 'carousel-item']); + + return Html::tag($tag, $content, $options); + } + + /** + * Renders the optional fixed item. + * + * @return string the fixed item's markup + */ + protected function renderFixedItem() + { + if ($this->fixedItemOptions === false) { + return ''; + } + + $tag = ArrayHelper::remove($this->fixedItemOptions, 'tag', 'div'); + $content = ArrayHelper::remove($this->fixedItemOptions, 'content', ''); + + Html::addCssClass($this->fixedItemOptions, ['fixed-item' => 'carousel-fixed-item']); + + return Html::tag($tag, $content, $this->fixedItemOptions); + } +} diff --git a/src/widgets/media/MaterialBox.php b/src/widgets/media/MaterialBox.php new file mode 100644 index 0000000..72ec64e --- /dev/null +++ b/src/widgets/media/MaterialBox.php @@ -0,0 +1,91 @@ + + * @package widgets + * @subpackage media + * + * @see http://materializecss.com/media.html#materialbox + */ +class MaterialBox extends BaseWidget +{ + /** + * @var string the source of the image. + * You must either specify this option or provide an image source via [[$imageOptions]]. + */ + public $imageSrc; + + /** + * @var array the HTML attributes for the image tag. + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $imageOptions = []; + + /** + * @var string|false the caption of the image. + * If you do not want a caption to be rendered, set this option to `false`. + */ + public $imageCaption = false; + + /** + * @var boolean whether the image caption shall be HTML-encoded. This defaults to `true`. + */ + public $encodeImageCaption = true; + + /** + * Initialize the widget. + * @throws InvalidConfigException + */ + public function init() + { + parent::init(); + + if (!$this->imageSrc) { + $imageSrc = ArrayHelper::remove($this->imageOptions, 'src', null); + if (!$imageSrc) { + throw new InvalidConfigException("Image src must be defined."); + } + + $this->imageSrc = $imageSrc; + } + + Html::addCssClass($this->imageOptions, ['plugin' => 'materialboxed']); + + if ($this->imageCaption !== false) { + $this->imageOptions['data-caption'] = $this->encodeImageCaption ? Html::encode($this->imageCaption) : $this->imageCaption; + } + } + + /** + * Execute the widget. + * @return string the widget's markup. + */ + public function run() + { + $this->registerPlugin('materialbox', '.materialboxed'); + + $tag = ArrayHelper::remove($this->options, 'tag', 'div'); + $html[] = Html::beginTag($tag, $this->options); + + $html[] = Html::img($this->imageSrc, $this->imageOptions); + + $html[] = Html::endTag($tag); + + return implode("\n", $html); + } +} diff --git a/src/widgets/media/Parallax.php b/src/widgets/media/Parallax.php new file mode 100644 index 0000000..8818f28 --- /dev/null +++ b/src/widgets/media/Parallax.php @@ -0,0 +1,77 @@ + + * @package widgets + * @subpackage media + * + * @see http://materializecss.com/parallax.html + * @see http://materializecss.com/parallax-demo.html + */ +class Parallax extends BaseWidget +{ + /** + * @var string the source of the image. + * You must either specify this option or provide an image source via [[$imageOptions]]. + */ + public $imageSrc; + + /** + * @var array the HTML attributes for the image tag. + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $imageOptions = []; + + /** + * Initialize the widget. + * @throws InvalidConfigException + */ + public function init() + { + parent::init(); + + if (!$this->imageSrc) { + $imageSrc = ArrayHelper::remove($this->imageOptions, 'src', null); + if (!$imageSrc) { + throw new InvalidConfigException("Image src must be defined."); + } + + $this->imageSrc = $imageSrc; + } + + $this->registerPlugin('parallax', '.parallax'); + } + + /** + * Execute the widget. + * @return string the widget's markup. + */ + public function run() + { + $tag = ArrayHelper::remove($this->options, 'tag', 'div'); + $html[] = Html::beginTag($tag, $this->options); + $html[] = Html::beginTag('div', ['class' => 'parallax-container']); + $html[] = Html::beginTag('div', ['class' => 'parallax']); + $html[] = Html::img($this->imageSrc, $this->imageOptions); + $html[] = Html::endTag('div'); + $html[] = Html::endTag('div'); + $html[] = Html::endTag($tag); + + return implode("\n", $html); + } +} diff --git a/src/widgets/media/Slider.php b/src/widgets/media/Slider.php new file mode 100644 index 0000000..aed3e68 --- /dev/null +++ b/src/widgets/media/Slider.php @@ -0,0 +1,199 @@ +not be encoded. + * + * ```php + * 'slideOptions' => [ + * 'class' => 'slide-item' // this class will be used for all slide elements (
  • ) + * ], + * 'slides' => [ + * [ + * 'image' => ['src' => '/source/of/image'], + * ], + * [ + * 'image' => ['src' => '/source/of/image'], + * 'caption' => [ + * 'content' => '

    Caption content

    ', + * 'align' => Slider::CAPTION_ALIGN_RIGHT + * ], + * 'options' => ['class' => 'slide-item-override'] // overrides $slideOptions + * ] + * ] + * ``` + * @author Christoph Erdmann + * @package widgets + * @subpackage media + * + * @see http://materializecss.com/media.html#slider + */ +class Slider extends BaseWidget +{ + /** + * Sets the caption alignment to `left`. + */ + const CAPTION_ALIGN_LEFT = 'left-align'; + + /** + * Sets the caption alignment to `center`. + */ + const CAPTION_ALIGN_CENTER = 'center-align'; + + /** + * Sets the caption alignment to `right`. + */ + const CAPTION_ALIGN_RIGHT = 'right-align'; + + /** + * @var array the HTML attributes for the slider container tag. + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $sliderOptions = []; + + /** + * @var array the HTML attributes for each slider's `
  • ` tag. + * These options will be merged with the individual slide options. + * + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $slideOptions = []; + + /** + * @var array the HTML attributes for each caption. + * These options will be merged with the individual caption options. + * + * @see [yii\helpers\BaseHtml::renderTagAttributes()](http://www.yiiframework.com/doc-2.0/yii-helpers-basehtml.html#renderTagAttributes()-detail) + * for details on how attributes are being rendered. + */ + public $captionOptions = []; + + /** + * @var array the slide items. + * Provide a sub-array for each slide which contains at least the `image` key for the image options. Every image must + * have a `src` with the image's URL. + */ + public $slides = []; + + /** + * @var boolean whether to show the slider's navigation indicators + */ + public $showIndicators = true; + + /** + * @var boolean whether this is a fullscreen slider + */ + public $fullscreen = false; + + /** + * Initialize the widget. + */ + public function init() + { + parent::init(); + + Html::addCssClass($this->sliderOptions, ['plugin' => 'slider']); + + if ($this->fullscreen === true) { + Html::addCssClass($this->sliderOptions, ['fullscreen' => 'fullscreen']); + } + + $this->clientOptions['indicators'] = $this->showIndicators; + $this->registerPlugin('slider', '.slider'); + } + + /** + * Execute the widget. + * @return string the rendered markup + */ + public function run() + { + $tag = ArrayHelper::remove($this->options, 'tag', 'div'); + $html[] = Html::beginTag($tag, $this->options); + $html[] = Html::beginTag('div', $this->sliderOptions); + $html[] = $this->renderSlides(); + $html[] = Html::endTag('div'); + $html[] = Html::endTag($tag); + + return implode("\n", $html); + } + + /** + * Parses all [[slides]] and generates the slide list. + * @return string the list markup + */ + protected function renderSlides() + { + $slides = []; + foreach ($this->slides as $slide) { + $slides[] = $this->renderSlide($slide); + } + $html[] = Html::tag('ul', implode("\n", $slides), ['class' => 'slides']); + return implode("\n", $html); + } + + /** + * Renders a single slide. + * + * @param array $slideConfig the configuration for the slide + * @return string the slide's markup + */ + protected function renderSlide($slideConfig = []) + { + $imageOptions = ArrayHelper::getValue($slideConfig, 'image', []); + $imageSrc = ArrayHelper::remove($imageOptions, 'src', null); + if (!$imageSrc) { + return ''; + } + + $caption = $this->renderCaption(ArrayHelper::getValue($slideConfig, 'caption', false)); + $options = ArrayHelper::getValue($slideConfig, 'options', []); + $options = ArrayHelper::merge($this->slideOptions, $options); + + $html[] = Html::beginTag('li', $options); + $html[] = Html::img($imageSrc, $imageOptions); + $html[] = $caption; + $html[] = Html::endTag('li'); + return implode("\n", $html); + } + + /** + * Renders the caption markup. + * @param false|array $captionConfig the caption configuration data + * @return string the markup of the caption + */ + protected function renderCaption($captionConfig) + { + if ($captionConfig === false) { + return ''; + } + + $content = ArrayHelper::getValue($captionConfig, 'content', ''); + $alignment = ArrayHelper::getValue($captionConfig, 'align', null); + $options = ArrayHelper::getValue($captionConfig, 'options', []); + $options = ArrayHelper::merge($this->captionOptions, $options); + + Html::addCssClass($options, ['caption' => 'caption']); + if ($alignment) { + Html::addCssClass($options, ['align' => $alignment]); + } + + return Html::tag('div', $content, $options); + } +}