Generates a HTML element with selected tag, content and options.
@param string $name
@param string $content
@param array $htmlOptions
@return string
512628
public function tag($name, $content, $htmlOptions = array()) {
        $element = "<$name ";
        foreach ($htmlOptions as $k => $v) {
            $element .= "$k=\"" . self::encode($v) . "\" ";
        }
        return $element . '>' . $content . '</' . $name . '>';
    }
1180355
public function edit($content)
    {
        if (!array_key_exists('selectOptions', $this->_editViewData)) {
            $this->_editViewData['selectOptions'] = [];
            $selectOptions = BlockSelectOption::where('block_id', '=', $this->_block->id)->get();
            foreach ($selectOptions as $selectOption) {
                $this->_editViewData['selectOptions'][$selectOption->value] = $selectOption->option;
            }
            if (preg_match('/^#[a-f0-9]{6}$/i', key($selectOptions))) {
                $this->_editViewData['class'] = 'select_colour';
            }
        }
        return parent::edit($content);
    }
904392
public static function numberFieldControlGroup($name, $value = '', $htmlOptions = array())
    {
        return self::controlGroup(self::INPUT_TYPE_NUMBER, $name, $value, $htmlOptions);
    }
174482
public function process($content, array $options = [])
    {
        $tagNames = array_keys($this->tags);
        $tagNames[] = 'component';
        if (is_string($content)) {
            $found = false;
            foreach ($tagNames as $tagName) {
                if (strpos($content, '<' . $tagName) !== false) {
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                return $content;
            }
        } elseif (!($content instanceof \IvoPetkov\HTMLServerComponent)) {
            throw new \InvalidArgumentException('');
        }

        $getComponentFileContent = static function($file, $component, $variables) {
            if (is_file($file)) {
                $__componentFile = $file;
                unset($file);
                if (!empty($variables)) {
                    extract($variables, EXTR_SKIP);
                }
                unset($variables);
                ob_start();
                include $__componentFile;
                $content = ob_get_clean();
                return $content;
            } else {
                throw new \Exception('Component file cannot be found (' . $file . ')');
            }
        };

        $getComponentResultHTML = function($component) use (&$getComponentFileContent, $options) {
            $srcAttributeValue = $component->getAttribute('src');
            if ($srcAttributeValue === null) {
                if (isset($this->tags[$component->tagName])) {
                    $srcAttributeValue = $this->tags[$component->tagName];
                } else {
                    throw new \Exception('Component tag name is not defined at ' . (string) $component . '!');
                }
            }
            if ($srcAttributeValue !== null) {
                // todo check alias of alias
                if (isset($this->aliases[$srcAttributeValue])) {
                    $sourceParts = explode(':', $this->aliases[$srcAttributeValue], 2);
                } else {
                    $sourceParts = explode(':', $srcAttributeValue, 2);
                }
                if (isset($sourceParts[0], $sourceParts[1])) {
                    $scheme = $sourceParts[0];
                    if ($scheme === 'data') {
                        if (substr($sourceParts[1], 0, 7) === 'base64,') {
                            return base64_decode(substr($sourceParts[1], 7)); //$this->process(, isset($componentOptions) ? $componentOptions : $options);
                        }
                        throw new \Exception('Components data URI scheme only supports base64 (data:base64,ABCD...)!');
                    } elseif ($scheme === 'file') {
                        return $getComponentFileContent(urldecode($sourceParts[1]), $component, isset($options['variables']) && is_array($options['variables']) ? $options['variables'] : []); //$this->process(isset($componentOptions) ? $componentOptions : $options);
                    }
                    throw new \Exception('Components URI scheme not valid! It must be \'file:\', \'data:\' or an alias.');
                }
                throw new \Exception('Components URI scheme or alias not found at ' . (string) $component . '!');
            }
            throw new \Exception('Component src attribute is missing at ' . (string) $component . '!');
        };

        $disableLevelProcessing = false;
        $domDocument = new HTML5DOMDocument();
        if ($content instanceof \IvoPetkov\HTMLServerComponent) {
            $domDocument->loadHTML($getComponentResultHTML($content), HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
            if (isset($options['recursive']) && $options['recursive'] === false) {
                $disableLevelProcessing = true;
            }
        } else {
            $domDocument->loadHTML($content, HTML5DOMDocument::ALLOW_DUPLICATE_IDS);
        }
        if (!$disableLevelProcessing) {
            $tagsQuerySelector = implode(',', $tagNames);
            for ($level = 0; $level < 1000; $level++) {
                $componentElements = $domDocument->querySelectorAll($tagsQuerySelector);
                if ($componentElements->length === 0) {
                    break;
                }
                $insertHTMLSources = [];
                $list = []; // Save the elements into an array because removeChild() messes up the NodeList
                foreach ($componentElements as $componentElement) {
                    $isInOtherComponentTag = false;
                    $parentNode = $componentElement->parentNode;
                    while ($parentNode !== null && isset($parentNode->tagName)) {
                        if (array_search($parentNode->tagName, $tagNames) !== false) {
                            $isInOtherComponentTag = true;
                            break;
                        }
                        $parentNode = $parentNode->parentNode;
                    }
                    if (!$isInOtherComponentTag) {
                        $list[] = $componentElement;
                    }
                }
                foreach ($list as $i => $componentElement) {
                    $component = $this->makeComponent($componentElement->getAttributes(), $componentElement->innerHTML, $componentElement->tagName);
                    $componentResultHTML = $getComponentResultHTML($component);
                    $isInBodyTag = false;
                    $parentNode = $componentElement->parentNode;
                    while ($parentNode !== null && isset($parentNode->tagName)) {
                        if ($parentNode->tagName === 'body') {
                            $isInBodyTag = true;
                            break;
                        }
                        $parentNode = $parentNode->parentNode;
                    }
                    if ($isInBodyTag) {
                        $insertTargetName = 'html-server-components-compiler-insert-target-' . $i;
                        $componentElement->parentNode->insertBefore($domDocument->createInsertTarget($insertTargetName), $componentElement);
                        $componentElement->parentNode->removeChild($componentElement); // must be before insertHTML because a duplicate elements IDs can occur.
                        $insertHTMLSources[] = ['source' => $componentResultHTML, 'target' => $insertTargetName];
                    } else {
                        $componentElement->parentNode->removeChild($componentElement);
                        $insertHTMLSources[] = ['source' => $componentResultHTML];
                    }
                }
                $domDocument->insertHTMLMulti($insertHTMLSources);
                if (isset($options['recursive']) && $options['recursive'] === false) {
                    break;
                }
            }
        }

        $domDocument->modify(
                HTML5DOMDocument::FIX_MULTIPLE_TITLES |
                HTML5DOMDocument::FIX_DUPLICATE_METATAGS |
                HTML5DOMDocument::FIX_MULTIPLE_HEADS |
                HTML5DOMDocument::FIX_MULTIPLE_BODIES |
                HTML5DOMDocument::OPTIMIZE_HEAD
        );
        return $domDocument->saveHTML();
    }
696326
public static function checkBox($name, $checked = false, $htmlOptions = array())
    {
        $label = TbArray::popValue('label', $htmlOptions, false);
        $labelOptions = TbArray::popValue('labelOptions', $htmlOptions, array());
        self::addCssClass('checkbox', $labelOptions);
        $input = parent::checkBox($name, $checked, $htmlOptions);
        return self::createCheckBoxAndRadioButtonLabel($label, $input, $labelOptions);
    }
593522
public function contentTag($name, $content, array $options = array(), $escape = false)
    {
        if ($content instanceof \Closure) {
            ob_start();
            $ret     = $content();
            $content = ob_get_clean();
            if ($ret !== null) {
                $content = $ret;
            }
        }
        return $this->contentTagString($name, $content, $options, $escape);
    }
548512
public function optionModeNoValue($name, $description)
    {
        $shortcut = null;
        $mode = InputOption::VALUE_NONE;
        return [$name, $shortcut, $mode, $description, $defaultValue = null];
    }
23554
public function input($name, $options = array())
    {
        $options += array(
            "type"  => "text",
            "id"    => $this->id($name),
            "name"  => $this->name($name),
            "error" => true,
            "class" => "",
            "value" => "",
            "label" => null
        );

        $currentValue = $this->getCurrentValue($options['name']);

        $errorHtml = "";
        $fieldHasErrors = false;

        if (!is_null($this->associatedEntity)) {
            // Checkboxes may be posted has data[name][0] and therefore
            // we need to remove it to get the absolute field name.
            $validationName = $options["type"] === "checkbox" ?
                preg_replace('/\[\d+\]$/', '', $name) :
                $name;

            if ($this->associatedEntity->hasErrors($validationName)) {
                if ((bool)$options['error']) {
                    $errorHtml = $this->generateInlineErrors($validationName);
                }
                $fieldHasErrors = true;
                $options['class'] .= " error ";
            }
        }
        unset($options["error"]);

        $label = "";
        if (!is_null($options['label'])) {
            $labelOptions = array(
                "for"    => $options["id"],
                "class" => $fieldHasErrors ? "error" : "",
                "label" => $options["label"],
            );

            $label .= $this->label($options['name'], $labelOptions);
        }
        unset($options['label']);

        switch (strtolower($options['type'])) {
            case "textarea":
                return $label . "\n" . $this->generateTextarea($options, $currentValue) . $errorHtml . "\n";
            case "select":
                return $label . "\n" . $this->generateSelect($options, $currentValue) . $errorHtml . "\n";
            case "radio":
                return $this->generateRadio($options, $currentValue) . $errorHtml . "\n" . $label . "\n";
            case "checkbox":
                return $this->generateCheckbox($options, $currentValue) . $errorHtml . "\n" . $label . "\n";
            case "hidden":
                return $label . "\n" . $this->generateHidden($options, $currentValue) . $errorHtml . "\n";
            default:
                return $label . "\n" . $this->generateTextinput($options, $currentValue) . $errorHtml . "\n";
        }
    }
986326
public function select($name, array $options, $selected = null, array $attributes = [])
    {
        $tag = new Tag('select', $attributes);
        $tag->name = $name;
        
        if ($selected === null)
            $selected = $this->getDefaultValue($name);

        foreach ($options as $value => $label)
        {
            $option = new Tag('option');
            $option->value = $value;
            $option->setText($label);

            if ($selected !== null && $value == $selected)
                $option->selected = true;

            $tag->addChild($option);
        }

        return $tag;
    }
1175560
public static function modalHeader($content, $htmlOptions = array())
    {
        self::addCssClass('modal-header', $htmlOptions);
        $closeOptions = TbArray::popValue('closeOptions', $htmlOptions, array());
        $closeOptions['dismiss'] = 'modal';
        $headingOptions = TbArray::popValue('headingOptions', $htmlOptions, array());
        $closeLabel = TbArray::popValue('closeLabel', $htmlOptions, self::CLOSE_TEXT);
        $closeButton = self::closeButton($closeLabel, $closeOptions);
        self::addCssClass('modal-title', $headingOptions);
        $header = self::tag('h4', $headingOptions, $content);
        return self::tag('div', $htmlOptions, $closeButton . $header);
    }
407523
public static function hidden($name, $value = '', array $htmlOptions = [])
    {
        return self::input('hidden', $name, $value) . self::htmlOptions($htmlOptions) .'>';
    }
648771
public static function thumbnailLink($content, $url = '#', $htmlOptions = array())
    {
        $itemOptions = TbArray::popValue('itemOptions', $htmlOptions, array());
        self::addCssClass('thumbnail', $htmlOptions);
        $content = self::link($content, $url, $htmlOptions);
        return self::tag('li', $itemOptions, $content);
    }
179491
public static function searchQueryControlGroup($name, $value = '', $htmlOptions = array())
    {
        return self::controlGroup(self::INPUT_TYPE_SEARCH, $name, $value, $htmlOptions);
    }
1198620
public static function textArea($name, $value = '', $htmlOptions = array())
    {
        $htmlOptions = self::normalizeInputOptions($htmlOptions);
        return parent::textArea($name, $value, $htmlOptions);
    }
357035
public static function a($href, $content = '', $title = '', $target = '', $options = [])
    {
        $a_tag_tpl = '<a href="%s" title="%s" target="%s"%s>%s</a>';
        return sprintf($a_tag_tpl, $href, $title, $target, self::assembleTagOptions($options), $content);
    }
1296558
public static function urlFieldControlGroup($name, $value = '', $htmlOptions = array())
    {
        return self::controlGroup(self::INPUT_TYPE_URL, $name, $value, $htmlOptions);
    }
919540
protected function htmlOptionsSet($name, $additional = [], $appendStyle = '')
    {
        $class = !empty($this->defaults[$name . 'Class']) ? $this->defaults[$name . 'Class'] : '';
        $style = !empty($this->defaults[$name . 'Style']) ? $this->defaults[$name . 'Style'] : '';

        if (!empty($this->bootstrapDefaults[$name . 'Class'])) {
            $class .= $this->bootstrapDefaults[$name . 'Class'];
        }
        if (!empty($this->bootstrapDefaults[$name . 'Style'])) {
            $style .= $this->bootstrapDefaults[$name . 'Style'];
        }
        if (!empty($this->{$name . 'Class'}) && is_string($this->{$name . 'Class'})) {
            $class .= ' ' . $this->{$name . 'Class'};
        }
        if (!empty($this->{$name . 'Style'}) && is_string($this->{$name . 'Style'})) {
            $style .= ' ' . $this->{$name . 'Style'};
        }

        $return = [
            'class' => $class ? : null,
            'style' => $style ? : null,
        ];

        if (count($additional)) {
            $return = array_merge($return, $additional);
        }
        if ($appendStyle != '') {
            if (!empty($return['style'])) {
                $return['style'] .= (substr(trim($return['style']), -1) != ';' ? ';' : '') . $appendStyle;
            } else {
                $return['style'] = $appendStyle;
            }
        }

        return $return;
    }