mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
tabs feature, adding macro and documentation
This commit is contained in:
parent
03c75b811e
commit
054adcbc43
@ -23,9 +23,9 @@ class DefaultController extends Controller
|
||||
|
||||
public function testAction()
|
||||
{
|
||||
return $this->render('ChillMainBundle:Test:index.html.twig', [
|
||||
return $this->render('ChillMainBundle:Tabs:index.html.twig', [
|
||||
'tabs' => [
|
||||
"test1" => [
|
||||
'test1' => [
|
||||
[
|
||||
'name' => "Link 1",
|
||||
'content' => "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae auctor eu augue ut. Elementum nisi quis eleifend quam. Faucibus purus in massa tempor nec. Turpis massa sed elementum tempus egestas sed sed risus. Etiam sit amet nisl purus in mollis nunc sed id. Enim nunc faucibus a pellentesque sit amet porttitor eget. Risus nec feugiat in fermentum posuere. Augue mauris augue neque gravida. Sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper eget. Id leo in vitae turpis massa sed elementum tempus egestas. Mauris commodo quis imperdiet massa. Fames ac turpis egestas integer eget aliquet nibh praesent. Urna porttitor rhoncus dolor purus non enim praesent elementum. Donec enim diam vulputate ut pharetra sit. Auctor neque vitae tempus quam. Mattis rhoncus urna neque viverra justo nec ultrices.",
|
||||
@ -47,7 +47,7 @@ class DefaultController extends Controller
|
||||
'content' => "Vel elit scelerisque mauris pellentesque pulvinar. Ornare suspendisse sed nisi lacus sed viverra tellus. Massa tincidunt dui ut ornare lectus sit. Congue nisi vitae suscipit tellus mauris a diam. At auctor urna nunc id cursus metus aliquam. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Mattis aliquam faucibus purus in massa tempor nec feugiat. Et leo duis ut diam quam. Auctor augue mauris augue neque. Purus ut faucibus pulvinar elementum integer enim neque volutpat. Scelerisque felis imperdiet proin fermentum leo. Diam sit amet nisl suscipit adipiscing bibendum est ultricies. Consectetur libero id faucibus nisl tincidunt. Vel fringilla est ullamcorper eget nulla facilisi. Pharetra diam sit amet nisl suscipit adipiscing. Dignissim diam quis enim lobortis. Auctor eu augue ut lectus arcu bibendum at varius.",
|
||||
]
|
||||
],
|
||||
"test2" => [
|
||||
'test2' => [
|
||||
[
|
||||
'name' => "Link 1",
|
||||
'link' => "http://localhost",
|
||||
@ -73,8 +73,9 @@ class DefaultController extends Controller
|
||||
//'link' => "http://localhost",
|
||||
'content' => "Vel elit scelerisque mauris pellentesque pulvinar. Ornare suspendisse sed nisi lacus sed viverra tellus. Massa tincidunt dui ut ornare lectus sit. Congue nisi vitae suscipit tellus mauris a diam. At auctor urna nunc id cursus metus aliquam. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Mattis aliquam faucibus purus in massa tempor nec feugiat. Et leo duis ut diam quam. Auctor augue mauris augue neque. Purus ut faucibus pulvinar elementum integer enim neque volutpat. Scelerisque felis imperdiet proin fermentum leo. Diam sit amet nisl suscipit adipiscing bibendum est ultricies. Consectetur libero id faucibus nisl tincidunt. Vel fringilla est ullamcorper eget nulla facilisi. Pharetra diam sit amet nisl suscipit adipiscing. Dignissim diam quis enim lobortis. Auctor eu augue ut lectus arcu bibendum at varius.",
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -78,38 +78,41 @@ let isLinkRef = function(link) {
|
||||
window.addEventListener('load', function()
|
||||
{
|
||||
tabParams.forEach(function(unit) {
|
||||
|
||||
let tabPanel = document.querySelector('#'+ unit.id );
|
||||
if (tabPanel) {
|
||||
|
||||
let
|
||||
tabPanel = document.querySelector('#'+ unit.id ),
|
||||
nav = tabPanel.querySelector('nav'),
|
||||
tabs = nav.querySelectorAll('ul.nav-tabs li.nav-item'),
|
||||
links = nav.querySelectorAll('ul.nav-tabs li.nav-item a.nav-link'),
|
||||
contents = tabPanel.querySelectorAll('div.tab-content div.tab-pane')
|
||||
;
|
||||
let
|
||||
nav = tabPanel.querySelector('nav'),
|
||||
tabs = nav.querySelectorAll('ul.nav-tabs li.nav-item'),
|
||||
links = nav.querySelectorAll('ul.nav-tabs li.nav-item a.nav-link'),
|
||||
contents = tabPanel.querySelectorAll('div.tab-content div.tab-pane')
|
||||
;
|
||||
|
||||
if (unit.type == 'pill') {
|
||||
tabPanel.classList.add('pills');
|
||||
}
|
||||
|
||||
if (! unit.startPanel) {
|
||||
unit.startPanel = 1;
|
||||
}
|
||||
|
||||
setPaneHeight(contents);
|
||||
|
||||
// initial position
|
||||
setNewActive(links, contents, unit.startPanel);
|
||||
|
||||
// listen
|
||||
links.forEach(function(link) {
|
||||
if (isLinkRef(link) == false) {
|
||||
link.addEventListener('click', function()
|
||||
{
|
||||
resetActive(links, contents);
|
||||
setNewActive(links, contents, countNewActive(links, link));
|
||||
});
|
||||
if (unit.type == 'pill') {
|
||||
tabPanel.classList.add('pills');
|
||||
}
|
||||
});
|
||||
|
||||
if (! unit.initPane) {
|
||||
unit.initPane = 1;
|
||||
}
|
||||
|
||||
setPaneHeight(contents);
|
||||
|
||||
// initial position
|
||||
setNewActive(links, contents, unit.initPane);
|
||||
|
||||
// listen
|
||||
links.forEach(function(link) {
|
||||
if (isLinkRef(link) == false) {
|
||||
link.addEventListener('click', function()
|
||||
{
|
||||
resetActive(links, contents);
|
||||
setNewActive(links, contents, countNewActive(links, link));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
126
Resources/views/Tabs/README.md
Normal file
126
Resources/views/Tabs/README.md
Normal file
@ -0,0 +1,126 @@
|
||||
# Fonctionnalité Tabs sur Chill-Main
|
||||
|
||||
Version 0.2
|
||||
|
||||
(to be translated)
|
||||
|
||||
## Description générale
|
||||
|
||||
**Tabs** est pensé comme une fonctionnalité paramétrique, qui permet de déployer facilement un ou plusieurs groupes d'onglets, avec des options qui permettent de varier son affichage et son comportement.
|
||||
|
||||
Le comportement naturel, ce sont des panneaux qui sont affichés ou cachés en javascript, lorqu'on clique sur l'onglet relatif.
|
||||
|
||||
|
||||
|
||||
## Controller
|
||||
```
|
||||
// in myController.php
|
||||
|
||||
public function myPageAction()
|
||||
{
|
||||
return $this->render('mytemplate.html.twig', [
|
||||
'tabs' => [
|
||||
'myFirstPanel' => [
|
||||
[ 'name' => "Link 1",
|
||||
'content' => "content text"
|
||||
],
|
||||
[ 'name' => "Link 2",
|
||||
'content' => "content text for link 2"
|
||||
]
|
||||
],
|
||||
'mySecondPanel' => [
|
||||
[ 'name' => "Link 1",
|
||||
'content' => "content text"
|
||||
],
|
||||
[ 'name' => "Link 2",
|
||||
'link' => "http://my.url"
|
||||
]
|
||||
]
|
||||
],
|
||||
// ...
|
||||
]);
|
||||
}
|
||||
```
|
||||
#### Description
|
||||
|
||||
* On peut définir plusieurs panneaux d'onglets qui s'afficheront dans une même page ;
|
||||
* Voici la description du tableau passé au template depuis le controller :
|
||||
|
||||
* Au départ on rassemble tous les panneaux d'onglets dans une seule clé, nommée ici `tabs` (la variable est utilisée dans le template, mais son nom peut changer);
|
||||
* Au niveau suivant, chaque clé correspond à l'identifiant(id) d'un panneau d'onglet ;
|
||||
* Au niveau suivant, chaque onglet est défini par un tableau, qui comprends les clés suivantes :
|
||||
|
||||
* la clé `name`, le titre de l'onglet ;
|
||||
* la clé `content`, le contenu du panneau relatif à l'onglet. A ce stade, si `content` contient un tableau, il vous faudra adapter la boucle twig de la macro (voir ci-dessous) ;
|
||||
* une clé `link` (facultative)
|
||||
|
||||
* Lorsque la clé `link` est définie pour un onglet, le comportement est différent : le lien est suivi et on quitte la page. Un panneau d'onglets peut être mixte, avec certains onglets qui sont en réalité des liens.
|
||||
|
||||
|
||||
## Template
|
||||
|
||||
```
|
||||
{# in mytemplate.html.twig #}
|
||||
|
||||
{% block css%}
|
||||
<link rel="stylesheet" href="{{ asset('build/tabs.css') }}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block js%}
|
||||
<script type="text/javascript">
|
||||
|
||||
let tabParams = [{
|
||||
id : 'myFirstPanel',
|
||||
type: 'tab',
|
||||
initPane: 2,
|
||||
disposition: 'horizontal',
|
||||
fade: true
|
||||
},
|
||||
{
|
||||
id : 'mySecondPanel',
|
||||
type: 'pill',
|
||||
initPane: 5,
|
||||
disposition: 'vertical',
|
||||
fade: false
|
||||
}
|
||||
];
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ asset('build/tabs.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% import '@ChillMain/Tabs/macro.html.twig' as tabsPanel %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{# Display one tabsPanel #}
|
||||
{{ tabsPanel.displayOne(tabs, 'myFirstPanel') }}
|
||||
|
||||
{# Display all tabPanels #}
|
||||
{{ tabsPanel.display(tabs) }}
|
||||
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
* Il faut commencer par charger la feuille de style `tabs.css` et le script `tabs.js` à l'intérieur des blocs css et js ;
|
||||
* Avant d'appeler `tabs.js`, on définit un tableau d'options pour le script :
|
||||
|
||||
* **id**: string, la clé identifiant du panneau d'onglet (obligatoire)
|
||||
* **type**: [tab|pill] affecte l'affichage (default: tab)
|
||||
* **initPane**: entier, numéro de l'onglet à afficher au chargement de la page (default: 1)
|
||||
* [prévu] **disposition**: [horizontal|vertical] affecte l'affichage (default: horizontal)
|
||||
* [prévu] **fade**: boolean, transition (default: false)
|
||||
|
||||
* Ensuite on peut importer la macro `@ChillMain/Tabs/macro.html.twig` qui permet d'afficher les panneaux d'onglets, soit un par un, soit tous les panneaux ;
|
||||
* Ou on peut s'inspirer des boucles twig de la macro pour en écrire de nouvelles personnalisées ;
|
||||
|
||||
|
||||
## Limitations
|
||||
* On ne peut pas afficher plusieurs fois le même panneau dans la même page
|
||||
|
||||
## Aller plus loin
|
||||
* fixer les options disposition et fade
|
||||
* js, calculer puis fixer la hauteur du panneau suivant le plus long
|
||||
* controller, avec link, on clique il charge une nouvelle page, avec le même panneau d'onglet ?!
|
||||
* insérer le initPane dans les urls en paramètres GET &initPane=xx
|
||||
* quand tab.content n'est pas un string : un bloc de code html, un tableau..
|
43
Resources/views/Tabs/index.html.twig
Normal file
43
Resources/views/Tabs/index.html.twig
Normal file
@ -0,0 +1,43 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{% block title %}Page de test{% endblock %}
|
||||
|
||||
{% block css%}
|
||||
<link rel="stylesheet" href="{{ asset('build/tabs.css') }}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block js%}
|
||||
<script type="text/javascript">
|
||||
|
||||
let tabParams = [{
|
||||
id : 'test1',
|
||||
type: 'tab',
|
||||
initPane: 2,
|
||||
disposition: 'horizontal',
|
||||
fade: true
|
||||
},
|
||||
{
|
||||
id : 'test2',
|
||||
type: 'pill',
|
||||
initPane: 5,
|
||||
disposition: 'vertical',
|
||||
fade: false
|
||||
}
|
||||
];
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ asset('build/tabs.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% import '@ChillMain/Tabs/macro.html.twig' as tabsPanel %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{# Display one tabsPanel
|
||||
{{ tabsPanel.displayOne(tabs, 'test1') }}
|
||||
#}
|
||||
|
||||
{# Display all tabPanels #}
|
||||
{{ tabsPanel.display(tabs) }}
|
||||
|
||||
{% endblock %}
|
36
Resources/views/Tabs/macro.html.twig
Normal file
36
Resources/views/Tabs/macro.html.twig
Normal file
@ -0,0 +1,36 @@
|
||||
{#
|
||||
Display only one panel
|
||||
#}
|
||||
{% macro displayOne(tabs, panel) %}
|
||||
<div class="tabs" id="{{ panel }}">
|
||||
<nav>
|
||||
<ul class="nav-tabs" role="tablist">
|
||||
{% for tab in tabs[panel] %}
|
||||
<li class="nav-item">
|
||||
{% set ref = (tab.link is defined )? tab.link : '#' %}
|
||||
<a class="nav-link" href="{{ ref }}">{{ tab.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
{% for tab in tabs[panel] %}
|
||||
<div class="tab-pane fade" role="tabpanel">
|
||||
{% if tab.content is defined %}
|
||||
<p>{{ tab.content }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{#
|
||||
Display all panels
|
||||
#}
|
||||
{% macro display(tabs) %}
|
||||
{% import _self as tabsPanel %}
|
||||
{% for panel,array in tabs %}
|
||||
{{ tabsPanel.displayOne(tabs, panel) }}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
@ -1,59 +0,0 @@
|
||||
{% extends '@ChillMain/layout.html.twig' %}
|
||||
|
||||
{% block title %}Page de test{% endblock %}
|
||||
|
||||
{% block css%}
|
||||
<link rel="stylesheet" href="{{ asset('build/tabs.css') }}"/>
|
||||
{% endblock %}
|
||||
|
||||
{% block js%}
|
||||
<script type="text/javascript">
|
||||
|
||||
let tabParams = [{
|
||||
id : 'test1',
|
||||
type: 'tab',
|
||||
startPanel: 2,
|
||||
disposition: 'horizontal',
|
||||
fade: true
|
||||
},
|
||||
{
|
||||
id : 'test2',
|
||||
type: 'pill',
|
||||
startPanel: 5,
|
||||
disposition: 'vertical',
|
||||
fade: false
|
||||
}
|
||||
];
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ asset('build/tabs.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% for key,tabsPanel in tabs %}
|
||||
<div class="tabs" id="{{ key }}">
|
||||
<nav>
|
||||
<ul class="nav-tabs" role="tablist">
|
||||
{% for tab in tabsPanel %}
|
||||
<li class="nav-item">
|
||||
{% set ref = (tab.link is defined )? tab.link : '#' %}
|
||||
<a class="nav-link" href="{{ ref }}">{{ tab.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="tab-content">
|
||||
{% for tab in tabsPanel %}
|
||||
<div class="tab-pane fade" role="tabpanel">
|
||||
{% if tab.content is defined %}
|
||||
<p>{{ tab.content }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user