diff --git a/.gitattributes b/.gitattributes index f4c34a3..2287dcf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,6 +3,7 @@ *.php text eol=crlf *.html text eol=crlf /tests export-ignore +/examples export-ignore /.github export-ignore /.gitignore export-ignore /.travis.yml export-ignore diff --git a/README.md b/README.md index 27ab388..9a6417d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,6 @@ -# WebFiori UI Package +# WebFiori UI -
-
-
-
-
-
@@ -17,171 +12,73 @@
+
+
+
+
+
+
+
-
-### HTML/PHP Template Files
-Some developers don't like to have everything in PHP. For example, front-end developers like to work directly with HTML since it has femiliar syntax. For this reason, the library include basic support for using HTML or PHP files as templates. If the templates are pure HTML, then variables are set in the document using slots. If the template has a mix between PHP and HTML, then PHP variables can be passed to the template.
-
-#### HTML Templates
-
-Assume that we have HTML file with the following markup:
-``` html
-
-
-
- - Hello Mr.{{ mr-name }}. This is your visit number {{visit-number}} - to our website. -
-- Hello Mr.Ibrahim Ali. This is your visit number 33 - to our website. -
-{{hero-subtitle}}
-{{content}}
+Welcome to our amazing website built with WebFiori UI!
', - 'current-year' => date('Y') +$card = HTMLNode::fromFileAsNode('template.html', [ + 'title' => 'My Card', + 'content' => 'Card body text' ]); - -echo $document; ``` -### PHP Templates with Logic - -Create dynamic templates with PHP logic: +PHP templates with variables: -**blog-post.php:** ```php -WebFiori UI is a powerful library...
In this tutorial, we will explore...
', - 'comments' => [ - [ - 'author' => 'Jane Reader', - 'date' => '2024-01-16', - 'content' => 'Great tutorial! Very helpful.' - ], - [ - 'author' => 'Bob Coder', - 'date' => '2024-01-17', - 'content' => 'Thanks for sharing this. Looking forward to more posts.' - ] - ] +$list = HTMLNode::fromFileAsNode('template.php', [ + 'items' => ['Apple', 'Banana', 'Cherry'] ]); - -echo $blogPost->toHTML(true); ``` -## 🎨 Styling and CSS - -### CSS Management - -```php -use WebFiori\Ui\HTMLNode; - -$element = new HTMLNode('div'); - -// Set individual styles -$element->setStyle([ - 'background-color' => '#f8f9fa', - 'border' => '1px solid #dee2e6', - 'border-radius' => '0.375rem', - 'padding' => '1rem', - 'margin-bottom' => '1rem', - 'box-shadow' => '0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)' -]); - -// Add more styles without overriding -$element->setStyle([ - 'transition' => 'all 0.3s ease', - 'cursor' => 'pointer' -], false); - -// Override specific styles -$element->setStyle([ - 'background-color' => '#e9ecef' -], true); - -// CSS classes management -$element->setClassName('card'); -$element->applyClass('shadow-sm'); -$element->applyClass('hover-effect'); - -// Conditional styling -$isActive = true; -if ($isActive) { - $element->applyClass('active'); - $element->setStyle(['border-color' => '#0d6efd']); -} - -echo $element->toHTML(true); -``` - -### Responsive Design - -```php -// Create responsive grid -$container = new HTMLNode('div', ['class' => 'container-fluid']); -$row = $container->div(['class' => 'row']); - -// Responsive columns -$columns = [ - ['size' => 'col-12 col-md-6 col-lg-4', 'content' => 'Column 1'], - ['size' => 'col-12 col-md-6 col-lg-4', 'content' => 'Column 2'], - ['size' => 'col-12 col-md-12 col-lg-4', 'content' => 'Column 3'] -]; - -foreach ($columns as $col) { - $column = $row->div(['class' => $col['size']]); - $card = $column->div(['class' => 'card h-100']); - $cardBody = $card->div(['class' => 'card-body']); - $cardBody->addChild('p', ['class' => 'card-text'])->text($col['content']); -} - -// Responsive utilities -$hiddenOnMobile = new HTMLNode('div', ['class' => 'd-none d-md-block']); -$hiddenOnMobile->text('This content is hidden on mobile devices'); - -$visibleOnMobile = new HTMLNode('div', ['class' => 'd-block d-md-none']); -$visibleOnMobile->text('This content is only visible on mobile devices'); - -echo $container->toHTML(true); -echo $hiddenOnMobile->toHTML(true); -echo $visibleOnMobile->toHTML(true); -``` - -## 🚀 Advanced Features - -### Iterator and Countable Interfaces - -WebFiori UI implements PHP's Iterator and Countable interfaces for seamless traversal: - -```php -use WebFiori\Ui\HTMLNode; - -$menu = new HTMLNode('ul', ['class' => 'main-menu']); -$menu->li('Home'); -$menu->li('About'); -$menu->li('Services'); -$menu->li('Contact'); - -// Iterate using foreach -foreach ($menu as $index => $menuItem) { - echo "Menu item $index: " . $menuItem->getText() . "\n"; - - // Add CSS class to each item - $menuItem->applyClass('menu-item'); - - // Add click handler - $menuItem->setAttribute('onclick', "handleMenuClick('$index')"); -} - -// Count children -echo "Total menu items: " . count($menu) . "\n"; -echo "Using childrenCount(): " . $menu->childrenCount() . "\n"; - -// Manual iteration control -$menu->rewind(); -while ($menu->valid()) { - $current = $menu->current(); - $key = $menu->key(); - - echo "Processing item at position $key\n"; - - $menu->next(); -} -``` - -### XML Document Generation - -```php -use WebFiori\Ui\HTMLNode; - -// Create SAML assertion -$assertion = new HTMLNode('saml:Assertion', [ - 'xmlns:saml' => 'urn:oasis:names:tc:SAML:2.0:assertion', - 'xmlns:xs' => 'http://www.w3.org/2001/XMLSchema', - 'ID' => '_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75', - 'Version' => '2.0', - 'IssueInstant' => '2004-12-05T09:22:05Z' -]); - -// Add issuer -$assertion->addChild('saml:Issuer')->text('https://idp.example.org/SAML2'); - -// Add subject -$subject = $assertion->addChild('saml:Subject'); -$nameId = $subject->addChild('saml:NameID', [ - 'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' -]); -$nameId->text('user@example.com'); - -// Add conditions -$conditions = $assertion->addChild('saml:Conditions', [ - 'NotBefore' => '2004-12-05T09:17:05Z', - 'NotOnOrAfter' => '2004-12-05T09:27:05Z' -]); - -$audienceRestriction = $conditions->addChild('saml:AudienceRestriction'); -$audienceRestriction->addChild('saml:Audience')->text('https://sp.example.com/SAML2'); - -// Generate XML -echo $assertion->toXML(true); -``` -## ⚡ Performance Tips - -### Optimizing HTML Output - -```php -use WebFiori\Ui\HTMLNode; - -// For production: Use unformatted output -$container = new HTMLNode('div'); -$container->addChild('p')->text('Content here'); - -// Compact output (recommended for production) -$compactHTML = $container->toHTML(false); -echo "Compact size: " . strlen($compactHTML) . " bytes\n"; - -// Formatted output (for development/debugging) -$formattedHTML = $container->toHTML(true); -echo "Formatted size: " . strlen($formattedHTML) . " bytes\n"; - -// Size difference can be significant with large DOMs -echo "Size difference: " . (strlen($formattedHTML) - strlen($compactHTML)) . " bytes\n"; -``` - -### Memory Management - -```php -// Batch operations for better performance -$largeList = new HTMLNode('ul', ['class' => 'large-list']); - -// Instead of adding children one by one: -// for ($i = 0; $i < 10000; $i++) { -// $largeList->li("Item $i"); -// } - -// Use build() method for batch operations: -$items = []; -for ($i = 0; $i < 10000; $i++) { - $items[] = ['li', ['class' => 'list-item'], "Item $i"]; -} -$largeList->build($items); - -// Clean up large objects when done -unset($largeList); - -// Use text nodes for plain text content -$textNode = new HTMLNode(HTMLNode::TEXT_NODE); -$textNode->setText('Large amount of plain text content...'); -``` - -### Efficient Styling - -```php -// Prefer CSS classes over inline styles -$element = new HTMLNode('div'); - -// Less efficient (inline styles) -$element->setStyle([ - 'color' => 'red', - 'font-size' => '14px', - 'margin' => '10px' -]); - -// More efficient (CSS classes) -$element->setClassName('text-danger fs-6 m-2'); - -// Batch style operations -$styles = [ - 'background-color' => '#f8f9fa', - 'border' => '1px solid #dee2e6', - 'border-radius' => '0.375rem', - 'padding' => '1rem' -]; -$element->setStyle($styles); // Single operation instead of multiple calls -``` - -## 📚 API Reference +## API Reference ### Core Classes -#### HTMLNode - -The foundation class for all HTML elements. - -**Constructor:** -```php -public function __construct(string $name = 'div', array $attrs = []) -``` - -**Key Methods:** - -| Method | Parameters | Return | Description | -|--------|------------|--------|-------------| -| `addChild()` | `$node, $attrs = [], $chainOnParent = false` | `HTMLNode` | Adds a child element | -| `setAttribute()` | `string $name, mixed $val = null` | `HTMLNode` | Sets an attribute | -| `setAttributes()` | `array $attrs` | `HTMLNode` | Sets multiple attributes | -| `getAttribute()` | `string $name` | `string\|null` | Gets attribute value | -| `hasAttribute()` | `string $name` | `bool` | Checks if attribute exists | -| `removeAttribute()` | `string $name` | `HTMLNode` | Removes an attribute | -| `setStyle()` | `array $styles, bool $override = false` | `HTMLNode` | Sets CSS styles | -| `setClassName()` | `string $class, bool $override = true` | `HTMLNode` | Sets CSS class | -| `applyClass()` | `string $class, bool $override = true` | `HTMLNode` | Applies CSS class | -| `text()` | `string $text, bool $escEntities = true` | `HTMLNode` | Sets text content | -| `setText()` | `string $text, bool $escEntities = true` | `HTMLNode` | Sets text content | -| `getText()` | - | `string` | Gets text content | -| `toHTML()` | `bool $formatted = false, int $initTab = 0` | `string` | Generates HTML | -| `toXML()` | `bool $formatted = false` | `string` | Generates XML | - -**Element Creation Methods:** - -| Method | Parameters | Return | Description | -|--------|------------|--------|-------------| -| `div()` | `array $attrs = []` | `HTMLNode` | Creates div element | -| `form()` | `array $attrs = []` | `HTMLNode` | Creates form element | -| `input()` | `string $type = 'text', array $attrs = []` | `HTMLNode` | Creates input element | -| `table()` | `array $attrs = []` | `HTMLNode` | Creates table element | -| `tr()` | `array $data = [], array $attrs = [], bool $headerRow = false` | `HTMLNode` | Creates table row | -| `ul()` | `array $items = [], array $attrs = []` | `HTMLNode` | Creates unordered list | -| `ol()` | `array $items = [], array $attrs = []` | `HTMLNode` | Creates ordered list | -| `li()` | `$body, array $attrs = []` | `HTMLNode` | Creates list item | -| `img()` | `array $attrs = []` | `HTMLNode` | Creates image element | -| `anchor()` | `string\|HTMLNode $body, array $attrs = []` | `HTMLNode` | Creates anchor element | -| `paragraph()` | `string\|HTMLNode $body = '', array $attrs = [], bool $escEntities = true` | `HTMLNode` | Creates paragraph | - -#### HTMLDoc +| Class | Description | +|-------|-------------| +| `HTMLNode` | Foundation class for all HTML elements | +| `HTMLDoc` | Represents a complete HTML document | +| `HeadNode` | The HTML head section | +| `HTMLTable` | Table creation and manipulation | +| `HtmlRenderer` | Standalone renderer with per-instance config | +| `TemplateCompiler` | HTML/PHP template loading and compilation | + +### Key Methods (HTMLNode) + +| Method | Description | +|--------|-------------| +| `addChild($node, $attrs)` | Add a child element | +| `setAttribute($name, $val)` | Set an attribute | +| `text($text)` | Set text content | +| `toHTML($formatted)` | Render to HTML string | +| `toXML($formatted)` | Render to XML string | +| `fromFile($path, $vars)` | Load from template | +| `fromFileAsDocument($path, $vars)` | Load as HTMLDoc | +| `fromFileAsNode($path, $vars)` | Load as single node | +| `fromFileAsArray($path, $vars)` | Load as node array | + +## Testing -Represents a complete HTML document. - -**Constructor:** -```php -public function __construct() +```bash +cd tests +php ../vendor/bin/phpunit ``` -**Key Methods:** - -| Method | Parameters | Return | Description | -|--------|------------|--------|-------------| -| `getBody()` | - | `HTMLNode` | Gets the body element | -| `getHeadNode()` | - | `HeadNode` | Gets the head element | -| `setPageTitle()` | `string $title` | `HTMLDoc` | Sets document title | -| `getPageTitle()` | - | `string` | Gets document title | -| `setLanguage()` | `string $lang` | `HTMLDoc` | Sets document language | -| `getLanguage()` | - | `string` | Gets document language | - -#### HeadNode - -Represents the HTML head section. - -**Key Methods:** - -| Method | Parameters | Return | Description | -|--------|------------|--------|-------------| -| `addCSS()` | `string $href, array $attrs = []` | `HeadNode` | Adds CSS file | -| `addJs()` | `string $src, array $attrs = []` | `HeadNode` | Adds JavaScript file | -| `addMeta()` | `string $name, string $content, array $attrs = []` | `HeadNode` | Adds meta tag | -| `setPageTitle()` | `string $title` | `HeadNode` | Sets page title | - -### Constants - -| Constant | Value | Description | -|----------|-------|-------------| -| `HTMLNode::COMMENT_NODE` | `'#COMMENT'` | Identifies comment nodes | -| `HTMLNode::TEXT_NODE` | `'#TEXT'` | Identifies text nodes | -| `HTMLNode::VOID_TAGS` | `array` | List of void HTML tags | - -### Static Methods +## Contributing -| Method | Parameters | Return | Description | -|--------|------------|--------|-------------| -| `HTMLNode::fromFile()` | `string $path, array $vars = []` | `HTMLNode\|HTMLDoc\|array` | Creates nodes from template | - -### Interfaces - -WebFiori UI implements standard PHP interfaces: - -- **Iterator**: Allows foreach loops over child nodes -- **Countable**: Enables `count()` function on nodes - -## 🎯 Examples - -### Complete Web Page - -```php -getHeadNode()->setPageTitle('WebFiori UI Demo'); -$doc->setLanguage('en'); - -// Add CSS and JavaScript -$head = $doc->getHeadNode(); -$head->addCSS('https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css'); -$head->addCSS('assets/custom.css'); -$head->addJs('https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js'); - -$body = $doc->getBody(); - -// Navigation -$nav = $body->addChild('nav', ['class' => 'navbar navbar-expand-lg navbar-dark bg-primary']); -$navContainer = $nav->div(['class' => 'container']); -$navContainer->anchor('WebFiori UI Demo', ['class' => 'navbar-brand', 'href' => '#']); - -// Hero section -$hero = $body->addChild('section', ['class' => 'hero bg-light py-5']); -$heroContainer = $hero->div(['class' => 'container text-center']); -$heroContainer->addChild('h1', ['class' => 'display-4'])->text('Welcome to WebFiori UI'); -$heroContainer->addChild('p', ['class' => 'lead'])->text('Build amazing web interfaces with PHP'); -$heroContainer->addChild('button', ['class' => 'btn btn-primary btn-lg'])->text('Get Started'); - -// Features section -$features = $body->addChild('section', ['class' => 'features py-5']); -$featuresContainer = $features->div(['class' => 'container']); -$featuresContainer->addChild('h2', ['class' => 'text-center mb-5'])->text('Features'); - -$featuresRow = $featuresContainer->div(['class' => 'row']); - -$featuresList = [ - ['title' => 'Object-Oriented', 'description' => 'Clean, maintainable code with OOP principles'], - ['title' => 'Template Support', 'description' => 'HTML and PHP templates with variable injection'], - ['title' => 'Type Safety', 'description' => 'Full type hints and comprehensive documentation'] -]; - -foreach ($featuresList as $feature) { - $col = $featuresRow->div(['class' => 'col-md-4 mb-4']); - $card = $col->div(['class' => 'card h-100']); - $cardBody = $card->div(['class' => 'card-body']); - $cardBody->addChild('h5', ['class' => 'card-title'])->text($feature['title']); - $cardBody->addChild('p', ['class' => 'card-text'])->text($feature['description']); -} - -// Footer -$footer = $body->addChild('footer', ['class' => 'bg-dark text-white py-4']); -$footerContainer = $footer->div(['class' => 'container text-center']); -$footerContainer->addChild('p')->text('© 2024 WebFiori UI. Built with ❤️ and PHP.'); - -echo $doc; -?> -``` +1. Clone the repository +2. Install dependencies: `composer install` +3. Run tests: `cd tests && php ../vendor/bin/phpunit` +4. Check code style: `composer fix-cs` -## 🤝 Contributing +## License -We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details. +This library is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. -### Development Setup +## Support -1. Clone the repository -2. Install dependencies: `composer install` -3. Run tests: `composer test` -4. Check code style: `composer cs-check` +If you encounter any issues, please [open an issue](https://github.com/WebFiori/ui/issues) on GitHub. -## 📄 License +## Changelog -This library is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file +See [Releases](https://github.com/WebFiori/ui/releases) for version history. diff --git a/WebFiori/Ui/TemplateCompiler.php b/WebFiori/Ui/TemplateCompiler.php index 6529041..53cf67a 100644 --- a/WebFiori/Ui/TemplateCompiler.php +++ b/WebFiori/Ui/TemplateCompiler.php @@ -875,7 +875,11 @@ private static function setSlotsHelper($allSlots, $slotsValuesArr, $component) { $trimmed = trim($slotNameFromComponent, '{{ }}'); if ($trimmed == $slotName) { - $component = str_replace($slotNameFromComponent, htmlspecialchars($slotVal), $component); + if ($slotVal instanceof \WebFiori\Ui\HTMLNode) { + $component = str_replace($slotNameFromComponent, $slotVal->toHTML(), $component); + } else { + $component = str_replace($slotNameFromComponent, htmlspecialchars($slotVal), $component); + } } } } diff --git a/examples/01-basic-document/README.md b/examples/01-basic-document/README.md new file mode 100644 index 0000000..0e73ac9 --- /dev/null +++ b/examples/01-basic-document/README.md @@ -0,0 +1,29 @@ +# Basic HTML Document + +This example demonstrates how to create a complete HTML5 document with head metadata and body content. + +## What This Example Shows + +- Creating an `HTMLDoc` instance +- Setting page title and language +- Adding meta tags, CSS, and JavaScript references +- Building body content with semantic elements + +## Files + +- [`example.php`](example.php) - Main example code + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +A complete HTML5 document with head section (title, meta, stylesheets) and a body with header, main, and footer sections. + +## Related Examples + +- [02-elements-and-attributes](../02-elements-and-attributes/) - Working with individual elements +- [07-standalone-renderer](../07-standalone-renderer/) - Controlling output formatting diff --git a/examples/01-basic-document/example.php b/examples/01-basic-document/example.php new file mode 100644 index 0000000..9e8047a --- /dev/null +++ b/examples/01-basic-document/example.php @@ -0,0 +1,31 @@ +setLanguage('en'); + +// Configure head +$head = $doc->getHeadNode(); +$head->setPageTitle('My Application'); +$head->addMeta('description', 'A demonstration of WebFiori UI document creation'); +$head->addMeta('viewport', 'width=device-width, initial-scale=1.0'); +$head->addCSS('https://cdn.example.com/styles.css'); +$head->addJs('https://cdn.example.com/app.js'); + +// Build body +$body = $doc->getBody(); + +$header = $body->addChild('header'); +$header->addChild('h1')->text('Welcome'); +$header->addChild('nav')->addChild('a', ['href' => '/about'])->text('About'); + +$main = $body->addChild('main', ['class' => 'container']); +$main->addChild('p')->text('This is a complete HTML document built with WebFiori UI.'); + +$footer = $body->addChild('footer'); +$footer->addChild('p')->text('© 2024 My Application'); + +echo $doc->toHTML(true); diff --git a/examples/02-elements-and-attributes/README.md b/examples/02-elements-and-attributes/README.md new file mode 100644 index 0000000..88ad1ae --- /dev/null +++ b/examples/02-elements-and-attributes/README.md @@ -0,0 +1,31 @@ +# Elements and Attributes + +This example demonstrates how to create HTML elements, set attributes, chain methods, and iterate over children. + +## What This Example Shows + +- Creating elements with constructor attributes +- Method chaining for fluent API +- Setting styles as arrays +- Boolean (valueless) attributes +- Iterating children with `foreach` +- Nesting elements + +## Files + +- [`example.php`](example.php) - Main example code + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +Several HTML elements demonstrating attributes, styles, nesting, and child iteration. + +## Related Examples + +- [01-basic-document](../01-basic-document/) - Full document structure +- [03-forms-and-input](../03-forms-and-input/) - Form-specific elements diff --git a/examples/02-elements-and-attributes/example.php b/examples/02-elements-and-attributes/example.php new file mode 100644 index 0000000..922ef2b --- /dev/null +++ b/examples/02-elements-and-attributes/example.php @@ -0,0 +1,42 @@ + 'main', 'class' => 'container']); + +// Method chaining +$div->setAttribute('data-role', 'content') + ->setStyle([ + 'padding' => '1rem', + 'margin' => '0 auto', + 'max-width' => '800px' + ]); + +// Adding children +$div->addChild('h2')->text('Element Demo'); +$div->addChild('p', ['class' => 'lead'])->text('Built with method chaining.'); + +// Boolean (valueless) attributes +$div->addChild('input', ['type' => 'text', 'required' => null, 'disabled' => null]); + +// Nested elements +$list = $div->addChild('ul', ['class' => 'features']); +$list->li('Feature One'); +$list->li('Feature Two'); +$list->li('Feature Three'); + +echo "=== Compact Output ===" . PHP_EOL; +echo $div->toHTML(false) . PHP_EOL . PHP_EOL; + +echo "=== Formatted Output ===" . PHP_EOL; +echo $div->toHTML(true) . PHP_EOL; + +// Iterating children +echo "=== Child Nodes ===" . PHP_EOL; + +foreach ($div as $child) { + echo '- ' . $child->getNodeName() . PHP_EOL; +} diff --git a/examples/03-forms-and-input/README.md b/examples/03-forms-and-input/README.md new file mode 100644 index 0000000..63ed63e --- /dev/null +++ b/examples/03-forms-and-input/README.md @@ -0,0 +1,29 @@ +# Forms and Input + +This example demonstrates how to create HTML forms with various input types. + +## What This Example Shows + +- Creating form elements with action and method +- Adding labeled input fields +- Different input types (text, password, email, select, textarea) +- Required and placeholder attributes + +## Files + +- [`example.php`](example.php) - Main example code + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +A complete login form and a contact form with various input types. + +## Related Examples + +- [02-elements-and-attributes](../02-elements-and-attributes/) - General element creation +- [04-tables](../04-tables/) - Displaying structured data diff --git a/examples/03-forms-and-input/example.php b/examples/03-forms-and-input/example.php new file mode 100644 index 0000000..aa5d2a9 --- /dev/null +++ b/examples/03-forms-and-input/example.php @@ -0,0 +1,35 @@ +form(['method' => 'post', 'action' => '/login']); +$form->label('Username:'); +$form->br(); +$form->input('text', ['name' => 'username', 'placeholder' => 'Enter username', 'required' => null]); +$form->br(); +$form->label('Password:'); +$form->br(); +$form->input('password', ['name' => 'password', 'required' => null]); +$form->br(); +$form->br(); +$form->input('submit', ['value' => 'Login']); + +// Contact form +$form2 = $wrapper->form(['method' => 'post', 'action' => '/contact']); +$form2->label('Email:'); +$form2->br(); +$form2->input('email', ['name' => 'email', 'placeholder' => 'you@example.com']); +$form2->br(); +$form2->label('Message:'); +$form2->br(); +$form2->addChild('textarea', ['name' => 'message', 'rows' => '5', 'cols' => '40']) + ->text('Your message here...'); +$form2->br(); +$form2->input('submit', ['value' => 'Send']); + +echo $wrapper->toHTML(true); diff --git a/examples/04-tables/README.md b/examples/04-tables/README.md new file mode 100644 index 0000000..a151b3a --- /dev/null +++ b/examples/04-tables/README.md @@ -0,0 +1,29 @@ +# Tables + +This example demonstrates how to create and manipulate HTML tables. + +## What This Example Shows + +- Creating tables with specified rows and columns +- Setting cell content +- Adding rows and columns dynamically +- Styling tables + +## Files + +- [`example.php`](example.php) - Main example code + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +An HTML table with headers and data rows. + +## Related Examples + +- [02-elements-and-attributes](../02-elements-and-attributes/) - General element creation +- [05-html-templates](../05-html-templates/) - Using templates for repeated structures diff --git a/examples/04-tables/example.php b/examples/04-tables/example.php new file mode 100644 index 0000000..4c2c474 --- /dev/null +++ b/examples/04-tables/example.php @@ -0,0 +1,34 @@ +getCell(0, $col)->text($headers[$col]); + $table->getCell(0, $col)->setAttribute('style', 'font-weight:bold;'); +} + +// Set data rows +$data = [ + ['Alice', 'alice@example.com', 'Admin'], + ['Bob', 'bob@example.com', 'Editor'], + ['Carol', 'carol@example.com', 'Viewer'], +]; + +for ($row = 0; $row < 3; $row++) { + for ($col = 0; $col < 3; $col++) { + $table->getCell($row + 1, $col)->text($data[$row][$col]); + } +} + +// Add a new column dynamically +$table->addColumn(['Status', 'Active', 'Active', 'Inactive']); + +echo $table->toHTML(true); diff --git a/examples/05-html-templates/README.md b/examples/05-html-templates/README.md new file mode 100644 index 0000000..0d4eee0 --- /dev/null +++ b/examples/05-html-templates/README.md @@ -0,0 +1,32 @@ +# HTML Templates + +This example demonstrates loading HTML templates with slot-based variable substitution. + +## What This Example Shows + +- Creating HTML template files with `{{slot}}` syntax +- Loading templates with `fromFileAsNode()` +- Passing variables to fill slots +- Reusing templates with different data +- Passing `HTMLNode` objects as slot values (rendered as raw HTML) + +## Files + +- [`example.php`](example.php) - Main example code +- [`templates/card.html`](templates/card.html) - Card component template +- [`templates/nav.html`](templates/nav.html) - Navigation template + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +HTML cards and navigation rendered from templates with injected content. + +## Related Examples + +- [06-php-templates](../06-php-templates/) - PHP-based templates with logic +- [01-basic-document](../01-basic-document/) - Building documents programmatically diff --git a/examples/05-html-templates/example.php b/examples/05-html-templates/example.php new file mode 100644 index 0000000..40cd42e --- /dev/null +++ b/examples/05-html-templates/example.php @@ -0,0 +1,46 @@ + 'Getting Started', 'content' => 'Learn the basics of WebFiori UI.', 'link' => '/docs/start'], + ['title' => 'Templates', 'content' => 'Build reusable components with slots.', 'link' => '/docs/templates'], + ['title' => 'Rendering', 'content' => 'Control output formatting and quoting.', 'link' => '/docs/render'], +]; + +$container = new HTMLNode('div', ['class' => 'card-grid']); + +foreach ($cards as $data) { + $card = HTMLNode::fromFileAsNode(__DIR__ . '/templates/card.html', $data); + $container->addChild($card); +} + +echo "=== Cards ===" . PHP_EOL; +echo $container->toHTML(true) . PHP_EOL; + +// Load a navigation template +$nav = HTMLNode::fromFileAsNode(__DIR__ . '/templates/nav.html', [ + 'base' => 'https://example.com', + 'home-label' => 'Home', + 'about-label' => 'About Us', + 'contact-label' => 'Contact', +]); + +echo "=== Navigation ===" . PHP_EOL; +echo $nav->toHTML(true) . PHP_EOL; + +// Passing an HTMLNode as a slot value — rendered as raw HTML +$icon = new HTMLNode('span', ['class' => 'icon']); +$icon->text('★'); + +$card = HTMLNode::fromFileAsNode(__DIR__ . '/templates/card.html', [ + 'title' => $icon, // HTMLNode injected as raw HTML + 'content' => 'This card has an HTMLNode in the title slot.', + 'link' => '/docs/nodes-in-slots' +]); + +echo "=== HTMLNode in Slot ===" . PHP_EOL; +echo $card->toHTML(true) . PHP_EOL; diff --git a/examples/05-html-templates/templates/card.html b/examples/05-html-templates/templates/card.html new file mode 100644 index 0000000..db37298 --- /dev/null +++ b/examples/05-html-templates/templates/card.html @@ -0,0 +1,5 @@ + diff --git a/examples/05-html-templates/templates/nav.html b/examples/05-html-templates/templates/nav.html new file mode 100644 index 0000000..9714a2e --- /dev/null +++ b/examples/05-html-templates/templates/nav.html @@ -0,0 +1,5 @@ + diff --git a/examples/06-php-templates/README.md b/examples/06-php-templates/README.md new file mode 100644 index 0000000..05674f2 --- /dev/null +++ b/examples/06-php-templates/README.md @@ -0,0 +1,31 @@ +# PHP Templates + +This example demonstrates loading PHP templates with variable injection and logic. + +## What This Example Shows + +- Creating PHP template files with access to passed variables +- Using loops and conditionals in templates +- Loading PHP templates with `fromFileAsNode()` +- Combining template output with programmatic DOM building + +## Files + +- [`example.php`](example.php) - Main example code +- [`templates/list.php`](templates/list.php) - Dynamic list template +- [`templates/user-card.php`](templates/user-card.php) - User card with conditional logic + +## Running the Example + +```bash +php example.php +``` + +## Expected Output + +A dynamic list and user cards rendered from PHP templates. + +## Related Examples + +- [05-html-templates](../05-html-templates/) - Simpler slot-based templates +- [07-standalone-renderer](../07-standalone-renderer/) - Controlling render output diff --git a/examples/06-php-templates/example.php b/examples/06-php-templates/example.php new file mode 100644 index 0000000..eced714 --- /dev/null +++ b/examples/06-php-templates/example.php @@ -0,0 +1,29 @@ + ['Apple', 'Banana', 'Cherry', 'Date'] +]); + +echo "=== Dynamic List ===" . PHP_EOL; +echo $list->toHTML(true) . PHP_EOL; + +// Load user cards with conditional logic +$users = [ + ['name' => 'Alice Johnson', 'email' => 'alice@example.com', 'isAdmin' => true], + ['name' => 'Bob Smith', 'email' => 'bob@example.com', 'isAdmin' => false], +]; + +$container = new HTMLNode('div', ['class' => 'users']); + +foreach ($users as $user) { + $card = HTMLNode::fromFileAsNode(__DIR__ . '/templates/user-card.php', $user); + $container->addChild($card); +} + +echo "=== User Cards ===" . PHP_EOL; +echo $container->toHTML(true) . PHP_EOL; diff --git a/examples/06-php-templates/templates/list.php b/examples/06-php-templates/templates/list.php new file mode 100644 index 0000000..c3caa44 --- /dev/null +++ b/examples/06-php-templates/templates/list.php @@ -0,0 +1,5 @@ += htmlspecialchars($email) ?>
+ + Admin + +
Comments (= count($comments) ?>)
- -