Skip to content

Commit 0e75743

Browse files
committed
gh-66: add dropdown list plugin for sphinx
1 parent 105c70d commit 0e75743

File tree

4 files changed

+199
-2
lines changed

4 files changed

+199
-2
lines changed

sphinx/_static/dropdown.css

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
.b-download-list -> .dropdown-list
3+
4+
.b-download-list-item -> .dropdown-list-item
5+
6+
.b-download-list-item-url -> .dropdown-list-item-uri
7+
.b-download-list-item-drop -> .dropdown-list-item-content
8+
9+
.p-drop-close -> .dropdown-close
10+
.p-drop-open -> .dropdown-open
11+
*/
12+
13+
14+
.dropdown-list-item-content {
15+
-webkit-transition: all 0.2s ease-in-out;
16+
-moz-transition: all 0.2s ease-in-out;
17+
-o-transition: all 0.2s ease-in-out;
18+
-ms-transition: all 0.2s ease-in-out;
19+
transition: all 0.2s ease-in-out;
20+
}
21+
22+
.dropdown-list {
23+
margin:0;
24+
padding:0;
25+
display:block;
26+
list-style:none;
27+
}
28+
29+
.dropdown-list {
30+
border-top:1px solid #e5e5e5;
31+
}
32+
.dropdown-list-item-content {
33+
height:0px;
34+
overflow:hidden;
35+
opacity:0;
36+
filter:alpha(opacity=0);
37+
padding-left:17px;
38+
font-size:14px;
39+
color:#404040;
40+
padding-right:40px;
41+
}
42+
.dropdown-list-item-content.dropdown-open {
43+
height:auto;
44+
opacity:1;
45+
filter:alpha(opacity=100);
46+
padding-top:17px;
47+
padding-bottom:12px;
48+
}
49+
.dropdown-list-item-content a {
50+
text-decoration:none;
51+
}
52+
.dropdown-list-item-content a:hover {
53+
text-decoration:underline;
54+
}
55+
56+
.dropdown-list-item-content ul {
57+
padding-left: 18px;
58+
}
59+
60+
.dropdown-list-item {
61+
font-size:18px;
62+
color:#404040;
63+
padding:14px 0;
64+
border-bottom:1px solid #e5e5e5;
65+
}
66+
.dropdown-list-item-url {
67+
display:block;
68+
color:inherit;
69+
text-decoration:none;
70+
}
71+
.dropdown-list-item-url.dropdown-close,
72+
.dropdown-list-item-url.dropdown-open {
73+
background-position:100% 50%;
74+
background-repeat:no-repeat;
75+
padding-right:40px
76+
}
77+
.dropdown-list-item-url.dropdown-close {
78+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAMAAABBPP0LAAAAPFBMVEUAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBts0nFAAAAE3RSTlMA7vt5Z0M3BPbhwLSxoo1XLSQbFXczDQAAAFtJREFUCNdVyEcOgDAMBdFJp6b5/nfFiYIEb+M/hnAmlnQGiEautPoSEzlE5Ga6dR70XU9GZR17h2Z0OHB6TEPV8fF+dGWKm0xbZAl2tA3wKla78OFFPD/OrfEA4fgEiY3/8xIAAAAASUVORK5CYII=');
79+
}
80+
.dropdown-list-item-url.dropdown-open {
81+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAMAAABBPP0LAAAAQlBMVEUAAAAWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeIWjeL1n1bsAAAAFXRSTlMA+PDlrwQ7NPzAn417dWxjVUYtJBv7ej5FAAAAXElEQVQI11WIWRaAIAzERlRQ9q33v6qtyFPz0U6ChxDwIxGlr+eD6Mivl4WYpUw34lL08KpYYuSjqnhbeXrA81sb0MUdGCel4+RncWN5njCKtn2EfSNlAC0+i8YFvbIFGAtHQ/cAAAAASUVORK5CYII=');
82+
}
83+
.dropdown-list-item-url.dropdown-open {
84+
color:#168de2;
85+
}
86+
.dropdown-list-item .b-example-code {
87+
margin-left:14px;
88+
}
89+
90+
@media screen and (max-width: 992px) {
91+
.dropdown-list-item {
92+
font-size: 16px;
93+
padding: 11px 0;
94+
}
95+
.dropdown-list-item-content.dropdown-open {
96+
padding: 25px 0 15px;
97+
}
98+
}

sphinx/_static/dropdown.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
$(function() {
2+
var open = 'dropdown-open';
3+
var close = 'dropdown-close';
4+
var download_drop_item = '.dropdown-list-item-url';
5+
var download_drop_item_parent = '.dropdown-list-item';
6+
var download_drop_box = '.dropdown-list-item-content';
7+
if ($(download_drop_item)) {
8+
var download_drop_items = $(download_drop_item);
9+
for (var i=0; i<download_drop_items.length; i++) {
10+
if ($(download_drop_items[i]).parents(download_drop_item_parent).find(download_drop_box).length != 0) {
11+
$(download_drop_items[i]).addClass(close);
12+
}
13+
};
14+
}
15+
$(download_drop_item).click(function() {
16+
if($(this).parents(download_drop_item_parent).find(download_drop_box).length!=0) {
17+
if ($(this).hasClass(open)) {
18+
$(this).removeClass(open);
19+
$(this).parents(download_drop_item_parent).find(download_drop_box).removeClass(open);
20+
$(this).parents(download_drop_item_parent).find(download_drop_box).addClass(close);
21+
} else {
22+
$(this).addClass(open);
23+
$(this).parents(download_drop_item_parent).find(download_drop_box).addClass(open);
24+
$(this).parents(download_drop_item_parent).find(download_drop_box).removeClass(close);
25+
}
26+
}
27+
return false;
28+
});
29+
});

sphinx/_templates/layout.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
{% set script_files = script_files + [
1010
'_static/stacktable.min.js',
1111
'_static/headers.js',
12+
'_static/dropdown.js',
1213
'_static/jquery.sticky-kit.min.js'
1314
] %}
1415
{% set css_files = [
1516
'_static/sphinx_design.css',
17+
'_static/dropdown.css'
1618
] + css_files %}
1719

1820
{% set main_page = title in ["Documentation", "Документация"] %}
@@ -38,8 +40,8 @@
3840
{% else %}
3941
class="b-section-title b-ellipsis toggle-navigation"
4042
{% endif %}
41-
title="{{ title | cleantitle }}">
42-
{{ title | cleantitle }}
43+
title="{{ title }}">
44+
{{ title }}
4345
</h2>
4446
{{- language_selector() -}}
4547
</div>

sphinx/ext/DropdownList.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from docutils import nodes
2+
from docutils.parsers.rst import Directive
3+
from docutils.parsers.rst import directives
4+
from docutils.parsers.rst.roles import set_classes
5+
from sphinx.util.nodes import nested_parse_with_titles
6+
7+
class ddlistitem(nodes.Part, nodes.TextElement): pass
8+
class ddlist(nodes.Sequential, nodes.FixedTextElement): pass
9+
10+
class DDListDirective(Directive):
11+
12+
required_arguments = 0
13+
optional_arguments = 0
14+
# This enable content in directive
15+
has_content = True
16+
17+
def run(self):
18+
self.assert_has_content()
19+
node = nodes.Element() # make anonymous container for text parsing
20+
self.state.nested_parse(self.content, self.content_offset, node)
21+
ddnode = self.build_ddmenu_from_list(node)
22+
self.add_name(ddnode)
23+
return [ddnode] + []
24+
25+
def build_ddmenu_from_list(self, node):
26+
if len(node) != 1 or not isinstance(node[0], (nodes.bullet_list,
27+
nodes.enumerated_list)):
28+
self.severe("Error while processing ddlist directive")
29+
ddnode = ddlist()
30+
for item in node[0]:
31+
new_item = ddlistitem()
32+
title = item.children.pop(0)
33+
title_ref = nodes.reference('', '', internal=False, refuri='',
34+
classes=['dropdown-list-item-url',
35+
'dropdown-close'])
36+
title_ref += title
37+
38+
content = nodes.container('', classes=['dropdown-list-item-content'])
39+
content += item.children
40+
41+
new_item += [title_ref, content]
42+
print(type(title_ref.parent), title_ref.parent)
43+
ddnode += new_item
44+
return ddnode
45+
46+
def visit_print_elem(node, tab):
47+
for child in node.children:
48+
print '\t' * tab, type(child)
49+
visit_print_elem(child, tab + 1)
50+
51+
def visit_ddlist_node(self, node):
52+
self.body.append(self.starttag(node, 'ul', CLASS='dropdown-list'))
53+
visit_print_elem(node, 1)
54+
55+
def depart_ddlist_node(self, node):
56+
self.body.append('\n</ul>\n')
57+
58+
def visit_ddlistitem_node(self, node):
59+
self.body.append(self.starttag(node, 'li', CLASS='dropdown-list-item'))
60+
61+
def depart_ddlistitem_node(self, node):
62+
self.body.append('\n</li>\n')
63+
64+
def setup(app):
65+
app.add_directive('ddlist', DDListDirective)
66+
67+
app.add_node(ddlist, html=(visit_ddlist_node, depart_ddlist_node))
68+
app.add_node(ddlistitem, html=(visit_ddlistitem_node, depart_ddlistitem_node))

0 commit comments

Comments
 (0)