Skip to content
This repository was archived by the owner on Mar 5, 2024. It is now read-only.

DOCSP-877 & DOCSP-879 - Parameterize filter and update saved pref. #161

Merged
merged 2 commits into from
Nov 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 28 additions & 39 deletions sphinxext/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@
.. raw:: html

<div class="tabs">
<ul class="tab-strip tab-strip--singleton" role="tablist">
{{ for tab in tabs sortLanguages }}
<ul class="tab-strip tab-strip--singleton" role="tablist" %PREFERENCE%>
{{ for tab in tabs %FILTER% }}
{{ # Only render the tab here if i < 5 }}
{{ if i lessThan(5) }}
<li class="tab-strip__element" data-tabid="{{ tab.id }}" role="tab" aria-selected="{{ if i zero }}true{{ else }}false{{ end }}">{{ tab.name }}</li>
{{ end }}
{{ end }}
{{ if tabs numberOfLanguages greaterThan(5) }}
{{ if tabs len greaterThan(5) }}
<li class="tab-strip__element dropdown">
<a class="dropdown-toggle" data-toggle="dropdown">Other <span class="caret"></span></a>
<ul class="dropdown-menu tab-strip__dropdown" role="menu">
{{ for tab in tabs sortLanguages }}
{{ for tab in tabs %FILTER% }}
{{ # Only render the tab here if i >= 5 }}
{{ if i greaterThanOrEqual(5) }}
<li data-tabid="{{ tab.id }}" aria-selected="{{ if i zero }}true{{ else }}false{{ end }}">{{ tab.name }}</li>
Expand All @@ -46,33 +46,7 @@
{{ end }}
</ul>
<div class="tabs__content" role="tabpanel">
{{ for tab in tabs sortLanguages}}
<div class="tabpanel-{{ tab.id }}">

{{ tab.content convertSections }}

.. raw:: html

</div>
{{ end }}
</div>
</div>
'''

TABSGS_TEMPLATE = '''
.. raw:: html

<div class="tabs">
<ul class="tab-strip tab-strip--singleton" role="tablist">
{{ for tab in tabs }}
{{ # Only render the tab here if i < 5 }}
{{ if i lessThan(5) }}
<li class="tab-strip__element" data-tabid="{{ tab.id }}" role="tab" aria-selected="{{ if i zero }}true{{ else }}false{{ end }}">{{ tab.name }}</li>
{{ end }}
{{ end }}
</ul>
<div class="tabs__content" role="tabpanel">
{{ for tab in tabs }}
{{ for tab in tabs %FILTER% }}
<div class="tabpanel-{{ tab.id }}">

{{ tab.content convertSections }}
Expand Down Expand Up @@ -110,6 +84,7 @@
'''

def setup(app):
# Handle headers inside tab directives
directive = template.create_directive('h1', H1_TEMPLATE, template.BUILT_IN_PATH, True)
app.add_directive('h1', directive)

Expand All @@ -122,15 +97,34 @@ def setup(app):
directive = template.create_directive('h4', H4_TEMPLATE, template.BUILT_IN_PATH, True)
app.add_directive('h4', directive)

directive = template.create_directive('tabs', TABS_TEMPLATE, template.BUILT_IN_PATH, True)
app.add_directive('tabs', directive)
# Create drivers tab directive
directive = template.create_directive('tabs-drivers', buildTemplate("sortLanguages", "drivers"), template.BUILT_IN_PATH, True)
app.add_directive('tabs-drivers', directive)

directive = template.create_directive('tabs-gs', TABSGS_TEMPLATE, template.BUILT_IN_PATH, True)
# Create getting started tab directive
# Shares preference with drivers if possible, no error checking
directive = template.create_directive('tabs-gs', buildTemplate("", "drivers"), template.BUILT_IN_PATH, True)
app.add_directive('tabs-gs', directive)

# Create general purpose tab directive with no error checking
directive = template.create_directive('tabs', buildTemplate("", ""), template.BUILT_IN_PATH, True)
app.add_directive('tabs', directive)

return {'parallel_read_safe': True,
'parallel_write_safe': True}

def buildTemplate(tabFilter, preference):
# If tabFilter is not a string, make it an empty string
if type(tabFilter) != str:
tabFilter = ""
template = TABS_TEMPLATE.replace("%FILTER%", tabFilter)

if type(preference) == str and preference != "":
template = template.replace("%PREFERENCE%", "data-tab-preference=\"" + preference + "\"")
else:
template = template.replace("%PREFERENCE%", "")

return template

def convertSections(tabContent):
"""Convert rst-style sections into custom directives that ONLY insert
Expand All @@ -141,11 +135,6 @@ def convertSections(tabContent):

fett.Template.FILTERS['convertSections'] = convertSections

def numberOfLanguages(tabData):
return len(LANGUAGES_RAW)

fett.Template.FILTERS['numberOfLanguages'] = numberOfLanguages

def getLanguageNames(tabData):
for tab in tabData:
index = LANGUAGES_IDS.index(tab['id'])
Expand Down
84 changes: 65 additions & 19 deletions themes/mongodb/src/js/componentTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,54 @@ class TabsSingleton {
constructor(key) {
this.key = key;
this.tabStrip = document.querySelector('.tab-strip--singleton');

// Only tab sets will have a type, init and try to retrieve
this.type = null;
if (this.tabStrip !== null) {
this.type = this.tabStrip.getAttribute('data-tab-preference');
}
}

get languagePref() {
return window.localStorage.getItem(this.key);
/**
* Return the tabPref object containing preferences for tab sets
* and page specific prefs. Returns an empty object if it doesn't
* exist.
* @returns {object} Tab preference object.
*/
get tabPref() {
return JSON.parse(window.localStorage.getItem(this.key)) || {};
}

set languagePref(value) {
window.localStorage.setItem(this.key, value);
/**
* Sets the tabPref object depending on whether the tab belongs
* to set (e.g., "drivers") or if it's a one-off page.
* @param {object} value The "tabId" and optional "type" (tab set)
*/
set tabPref(value) {
const tabPref = this.tabPref;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd not make this local variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline, calling the getter method above.


// If "type" exists it belongs to a tab set
if (this.type) {
// Set top-level fields for tab set preferences
tabPref[value.type] = value.tabId;
} else if (tabPref.pages) {
// Store one-off pages in the pages embedded document
tabPref.pages[window.location.pathname] = value.tabId;
} else {
// Init pages embedded doc if it doesnt exist and store one-off
tabPref.pages = {};
tabPref.pages[window.location.pathname] = value.tabId;
}

// Write pref object back to localStorage
window.localStorage.setItem(this.key, JSON.stringify(tabPref));
}

/**
* Return the first singleton tab ID on the page.
* @returns {string} The first singleton tab ID found.
*/
getFirstLanguage() {
getFirstTab() {
const tabsElement = this.tabStrip.querySelector('.tab-strip__element[aria-selected=true]');
if (!tabsElement) { return null; }

Expand All @@ -42,12 +75,18 @@ class TabsSingleton {
for (const element of this.tabStrip.querySelectorAll('[data-tabid]')) {
element.onclick = (e) => {
// Get the tab ID of the clicked tab
const currentAttrValue = e.target.getAttribute('data-tabid');
const tabId = e.target.getAttribute('data-tabid');
const type = this.tabStrip.getAttribute('data-tab-preference');

// Build the pref object to set
const pref = {};
pref.tabId = tabId;
pref.type = type;

// Check to make sure value is not null, i.e., don't do anything on "other"
if (currentAttrValue) {
if (tabId) {
// Save the users preference and re-render
this.languagePref = currentAttrValue;
this.tabPref = pref;
this.update();

e.preventDefault();
Expand All @@ -60,20 +99,27 @@ class TabsSingleton {

update() {
if (!this.tabStrip) { return; }

let languagePref = this.languagePref;
if (!languagePref) {
languagePref = this.getFirstLanguage();
} else if (!this.tabStrip.querySelector(`[data-tabid="${languagePref}"]`)) {
// Confirm a tab for their languagePref exists at the top of the page
languagePref = this.getFirstLanguage();
let type = this.type;

let tabPref = this.tabPref;

if (!tabPref) {
// Display the first tab when there is no pref
tabPref = this.getFirstTab();
} else if (tabPref.pages && tabPref.pages[window.location.pathname]) {
// Check if current page has a one-off page specific pref
tabPref = tabPref.pages;
type = window.location.pathname;
} else if (!this.tabStrip.querySelector(`[data-tabid="${tabPref[type]}"]`)) {
// Confirm a tab for their tabPref exists at the top of the page
tabPref = this.getFirstTab();
}

if (!languagePref) { return; }
if (!tabPref) { return; }

// Show the appropriate tab content and mark the tab as active
showHideTabContent(languagePref);
this.showHideSelectedTab(languagePref);
showHideTabContent(tabPref[type]);
this.showHideSelectedTab(tabPref[type]);
}

/**
Expand Down Expand Up @@ -128,5 +174,5 @@ class TabsSingleton {

// Create tab functionality for code examples
export function setup() {
(new TabsSingleton('languagePref')).setup();
(new TabsSingleton('tabPref')).setup();
}
Loading