/** * Build link with active definition in listing * @param Dom $dom * @param array $item * @param bool $orderActiveLink * @return string */ private static function buildLink($dom, $item, $orderActiveLink = false) { // set default link data - text and properties $text = self::applyEscape($item['text'], $item['html'], $item['!secure']); $properties = $item['property']; // try to parse link format for controller/action definition (must be array: 'main/index' to ['main/index']) if (!Obj::isArray($item['link']) && !Str::startsWith('http', $item['link']) && !Str::startsWith('#', $item['link'])) { $item['link'] = [$item['link']]; } // if its a controller/action definition try to work with active class if (Obj::isArray($item['link'])) { // check if css class for active item is defined if (!isset($item['activeClass'])) { $item['activeClass'] = 'active'; } // check if element is active on current URI if (self::isCurrentLink($item['link'], $item['activeOn'], $orderActiveLink) === true) { $properties['class'] = Str::concat(' ', $item['activeClass'], $properties['class']); } } // set href source for link $item['linkProperty']['href'] = self::convertLink($item['link']); // build output <li@params><a @params>@text</li> return $dom->li(function () use($dom, $text, $item) { return $dom->a(function () use($text) { return $text; }, $item['linkProperty']); }, $properties); }
/** * Display nav listing block * @param array $elements */ public static function display($elements) { // check if elements isn't empty and contains rows if (!Obj::isArray($elements) || count($elements['items']) < 1) { return null; } // prepare tab order if ($elements['tabAnchor'] === null) { $elements['tabAnchor'] = Str::randomLatin(mt_rand(6, 12)); } // set global element properties $blockProperty = []; if ($elements['blockProperty'] !== null) { if (Obj::isArray($elements['blockProperty'])) { $blockProperty = $elements['blockProperty']; } unset($elements['blockProperty']); } // check if items have defined active order $activeDefined = Arr::in(true, Arr::ploke('active', $elements['items'])); // prepare tab content $tabContent = null; $tabIdx = 1; // initialize dom model $dom = new Dom(); // prepare items to drow listing $items = []; foreach ($elements['items'] as $item) { // its just a link, drow it as is if ($item['type'] === 'link') { $items[] = $item; } elseif ($item['type'] === 'dropdown') { // build bootstrap dropdown properties $item['dropdown'] = ['class' => 'dropdown-toggle', 'data-toggle' => 'dropdown', 'href' => '#']; $item['property']['class'] = Str::concat(' ', 'dropdown', $item['property']['class']); $items[] = $item; } elseif ($item['type'] === 'tab') { $activeObject = false; $item['type'] = 'link'; // fix for global Listing builder $item['link'] = '#' . $elements['tabAnchor'] . $tabIdx; $item['property']['role'] = 'presentation'; // check if active definition is exist in elements options if ($activeDefined) { if ($item['active'] === true) { $activeObject = true; } } elseif ($tabIdx === 1) { // if not exist set first as active $activeObject = true; } // mark active tab if ($activeObject === true) { $item['property']['class'] .= (Str::length($item['property']['class']) > 0 ? ' ' : null) . 'active'; } // tab special properties for bootstrap $item['linkProperty']['aria-controls'] = $elements['tabAnchor'] . $tabIdx; $item['linkProperty']['role'] = 'tab'; $item['linkProperty']['data-toggle'] = 'tab'; $itemContent = $item['content']; unset($item['content']); $items[] = $item; // draw tab content $tabContent .= $dom->div(function () use($item, $itemContent) { if ($item['html'] === true) { if ($item['!secure'] === true) { return $itemContent; } else { return self::safe($itemContent, true); } } else { return self::nohtml($itemContent); } }, ['role' => 'tabpanel', 'class' => 'tab-pane fade' . ($activeObject === true ? ' in active' : null), 'id' => $elements['tabAnchor'] . $tabIdx]); $tabIdx++; } } // check if global class "nav" isset if ($elements['property']['class'] !== null) { if (!Str::contains('nav ', $elements['property']['class'])) { $elements['property']['class'] = 'nav ' . $elements['property']['class']; } } else { $elements['property']['class'] = 'nav'; } // render final output return $dom->div(function () use($elements, $items, $tabContent, $dom) { // drow listing $listing = Listing::display(['type' => 'ul', 'property' => $elements['property'], 'activeOrder' => $elements['activeOrder'], 'items' => $items]); // drow tabs if isset if ($tabContent !== null) { $tabContent = $dom->div(function () use($tabContent) { return $tabContent; }, ['class' => 'tab-content']); } return $listing . $tabContent; }, $blockProperty); }
/** * Build bootstrap navbar * @param array $elements * @return NULL|string */ public static function display($elements) { // check if elements passed well if (!Obj::isArray($elements) || count($elements['items']) < 1) { return null; } // set default bootstrap properties if not defined $elements['property']['class'] = Str::concat(' ', 'nav', $elements['property']['class']); $elements['nav']['class'] = Str::concat(' ', 'navbar', $elements['nav']['class']); if ($elements['container'] === null) { $elements['container'] = 'container-fluid'; } // set mobile collapse id for toggle $mobCollapseId = $elements['collapseId']; if (Str::likeEmpty($mobCollapseId)) { $mobCollapseId = Str::randomLatin(mt_rand(6, 12)) . mt_rand(1, 99); } // set element id for toggle $ulId = 1; // prepare array's for left, right and static elements $itemsLeft = []; $itemsRight = []; $itemsStatic = null; foreach ($elements['items'] as $item) { if (Obj::isString($item)) { // sounds like a static object w/o render request $itemsStatic .= $item; } else { if ($item['type'] === 'dropdown') { // build bootstrap dropdown properties $item['dropdown'] = ['class' => 'dropdown-toggle', 'data-toggle' => 'dropdown', 'href' => '#']; $item['property']['class'] = Str::concat(' ', 'dropdown', $item['property']['class']); } else { $item['type'] = 'link'; } // set item with position if ($item['position'] !== null && $item['position'] === 'right') { // right position item $itemsRight[] = $item; } else { // left pos item $itemsLeft[] = $item; } } } // build html dom for left and right elements $leftBuild = null; $rightBuild = null; if (count($itemsLeft) > 0) { $mainElemLeft = $elements['property']; // todo: fix me!! $mainElemLeft['id'] .= $ulId; $ulId++; $leftBuild = Listing::display(['type' => 'ul', 'property' => $mainElemLeft, 'activeOrder' => $elements['activeOrder'], 'items' => $itemsLeft]); } if (count($itemsRight) > 0) { $mainElemRight = $elements['property']; // todo: fix me!! $mainElemRight['class'] .= ' navbar-right'; $mainElemRight['id'] .= $ulId; $ulId++; $rightBuild = Listing::display(['type' => 'ul', 'property' => $mainElemRight, 'activeOrder' => $elements['activeOrder'], 'items' => $itemsRight]); } // generate output dom of bootstrap navbar $dom = new Dom(); $body = $dom->div(function () use($leftBuild, $rightBuild, $itemsStatic) { return $leftBuild . $itemsStatic . $rightBuild; }, ['class' => 'collapse navbar-collapse', 'id' => $mobCollapseId]); // drow <nav @properties>@next</nav> return $dom->nav(function () use($dom, $elements, $mobCollapseId, $body) { // drow <div @container>@next</div> return $dom->div(function () use($dom, $elements, $mobCollapseId, $body) { // drow <div @navbar-header>@next</div> $header = $dom->div(function () use($dom, $elements, $mobCollapseId) { // drow <button @collapse>@next</button> $collapseButton = $dom->button(function () use($dom) { $toggleItem = $dom->span(function () { return 'Toggle menu'; }, ['class' => 'sr-only']); $toggleIcon = null; for ($i = 0; $i < 3; $i++) { $toggleIcon .= $dom->span(function () { return null; }, ['class' => 'icon-bar']); } return $toggleItem . $toggleIcon; }, ['type' => 'button', 'class' => 'navbar-toggle collapsed', 'data-toggle' => 'collapse', 'data-target' => '#' . $mobCollapseId]); // drow <div @brand>@brandtext<?div> $brand = null; if (isset($elements['brand'])) { if (isset($elements['brand']['link'])) { $brand = Url::link($elements['brand']['link'], $elements['brand']['text'], ['class' => 'navbar-brand']); } else { $brand = (new Dom())->span(function () use($elements) { return $elements['brand']['text']; }, ['class' => 'navbar-brand']); } } return $collapseButton . $brand; }, ['class' => 'navbar-header']); // return header and body concat return $header . $body; }, $elements['container']); }, $elements['nav']); }
/** * Construct table based on passed elements as array: properties, thead, tbody, rows, items etc * @param array $elements * @return null */ public static function display($elements) { // check passed data if (!Obj::isArray($elements) || count($elements) < 1) { return null; } if (!isset($elements['tbody']) || !Obj::isArray($elements['tbody']['items']) || count($elements['tbody']['items']) < 1) { return null; } $selectOptions = false; if (isset($elements['selectableBox'])) { $selectOptions = $elements['selectableBox']; unset($elements['selectableBox']); } // init dom model $dom = new Dom(); // draw response $table = $dom->table(function () use($dom, $elements, $selectOptions) { $res = null; // check if thead is defined if (isset($elements['thead']) && Obj::isArray($elements['thead']) && count($elements['thead']) > 0 && Obj::isArray($elements['thead']['titles'])) { // add thead container $res .= $dom->thead(function () use($dom, $elements, $selectOptions) { return $dom->tr(function () use($dom, $elements, $selectOptions) { $tr = null; foreach ($elements['thead']['titles'] as $order => $title) { $th = null; if ($title['html'] === true) { if ($title['!secure'] === true) { $th = $title['text']; } else { $th = self::safe($title['text'], true); } } else { $th = htmlentities($title['text']); } // make global checkbox for selectable columns if ($selectOptions !== false && $order + 1 === $selectOptions['attachOrder']) { $th = $dom->input(function () { return null; }, ['type' => 'checkbox', 'name' => 'selectAll']) . ' ' . $th; } // build tr row collecting all th's $tr .= $dom->th(function () use($th) { return $th; }, $title['property']); } // return tr row in thead return $tr; }); }, $elements['thead']['property']); } // parse tbody array elements if (isset($elements['tbody']) && Obj::isArray($elements['tbody']) && isset($elements['tbody']['items']) && Obj::isArray($elements['tbody']['items'])) { // add tbody container $res .= $dom->tbody(function () use($dom, $elements, $selectOptions) { $tr = null; // each all items by row (tr) foreach ($elements['tbody']['items'] as $row) { // sort td items inside row by key increment ksort($row); // add data in tr container $tr .= $dom->tr(function () use($dom, $row, $selectOptions) { $td = null; foreach ($row as $order => $item) { if (!Obj::isInt($order)) { continue; } // collect td item $td .= $dom->td(function () use($dom, $order, $item, $selectOptions) { $text = null; // make text secure based on passed options if ($item['html'] === true) { if ($item['!secure'] === true) { $text = $item['text']; } else { $text = self::safe($item['text'], true); } } else { $text = htmlentities($item['text']); } // check if selectable box is enabled and equal current order id if ($selectOptions !== false && $order === $selectOptions['attachOrder']) { $text = $dom->input(function () { return null; }, Arr::merge($selectOptions['selector'], ['value' => htmlentities($text)])) . ' ' . $text; } return $text; }, $item['property']); } return $td; }, $row['property']); } return $tr; }, $elements['tbody']['property']); } // return all computed code return $res; }, $elements['table']); // check if select box is defined and used if ($selectOptions !== false || Obj::isArray($selectOptions)) { // build js code for "selectAll" checkbox self::buildSelectorHtml($selectOptions); // return response inside "form" tag return $dom->form(function () use($dom, $selectOptions, $table) { foreach ($selectOptions['buttons'] as $btn) { if (!Obj::isArray($btn)) { continue; } $table .= $dom->input(function () { return null; }, $btn) . ' '; } return $table; }, $selectOptions['form']); } return $table; }