mashery / sparrow Goto Github PK
View Code? Open in Web Editor NEWA flexible, mobile-friendly theme for the Mashery Portal.
Home Page: https://mashery.github.io/sparrow
License: Other
A flexible, mobile-friendly theme for the Mashery Portal.
Home Page: https://mashery.github.io/sparrow
License: Other
Several are now private
th,
thead td {
// background-color: lighten( $color-gray-light, 5% );
font-weight: bold;
vertical-align: bottom;
.page-search & {
font-weight: normal;
}
.search-form & {
vertical-align: top;
}
}
/**
* Show different content for signed-in or signed-out users
*/
.is-logged-in .hide-logged-in,
.is-logged-out .hide-logged-out {
@extend [hidden];
}
in header/zzz_dom.js
:
/**
* Load true active state on sub nav links
*/
portalReady(function () {
// Variables
var links = document.querySelectorAll( '.sub ul a' );
var url = location.protocol + '//' + location.host + location.pathname;
var isDocsLanding = document.documentElement.classList.contains( 'dom-docs' );
/**
* Add active class to link
*/
var activate = function ( elem ) {
var parent = elem.parentNode;
if (!parent) return;
parent.className += ' js-active';
};
// Check if current link is active
for ( var i = 0, len = links.length; i < len; i++ ) {
// Get href
var href = links[i].href;
// Sanity check
if ( !href ) continue;
if ( isDocsLanding && /\/docs\/read\/Home/.test(href) ) {
activate( links[i] );
return;
}
if ( href === url.replace(/#([^\\s]*)/g, '') ) {
activate( links[i] );
return;
}
}
});
Use getCookie
instead of the full blown cookie library
Don't target only th
, as GUI will use tr
inside thead
.
/**
* @section Tables
* Styling for tables
*/
table {
border-collapse: collapse;
border-spacing: 0;
margin-bottom: $spacing;
max-width: 100%;
width: 100%;
}
th,
td {
text-align: left;
padding: calc-em(8px);
}
thead {
border-bottom: calc-em(2px) solid $color-gray-light;
}
th,
thead td {
// background-color: lighten( $color-gray-light, 5% );
font-weight: bold;
vertical-align: bottom;
}
tbody tr {
border-top: calc-em(1px) solid $color-gray-light;
}
td {
vertical-align: top;
}
/**
* Adds zebra striping
*/
.table-striped tbody tr:nth-child(odd) {
background-color: lighten( $color-gray-light, 7% );
}
/**
* Reduces padding on condensed tables
*/
.table-condensed th,
.table-condensed td, {
padding: calc-em(4px);
}
/**
* Pure CSS responsive tables
* Adds label to each cell using the [data-label] attribute
* @link https://techblog.livingsocial.com/blog/2015/04/06/responsive-tables-in-pure-css/
*/
@media (max-width: $bp-medium) {
.table-responsive {
thead {
display: none;
visibility: hidden;
}
tr {
border-top: calc-em(1px) solid lighten( $color-gray-light, 3% );
display: block;
padding: calc-em(8px);
}
td {
border: 0;
display: block;
padding: calc-em(4px);
&:before {
content: attr(data-label);
display: block;
font-weight: bold;
}
}
}
}
/**
* Add table headers that are missing from the GUI generate tables
*/
var addTableHeaders = function () {
'use strict';
// Feature test
var supports = 'querySelector' in document;
if ( !supports ) return;
// Variables
var tables = document.querySelectorAll( 'table' );
/**
* Get the closest matching element up the DOM tree.
* @param {Element} elem Starting element
* @param {String} selector Selector to match against (class, ID, data attribute, or tag)
* @return {Boolean|Element} Returns null if not match found
*/
var getTbody = function ( elem ) {
for ( ; elem && elem !== document && elem.nodeType === 1; elem = elem.parentNode ) {
if ( elem.tagName.toLowerCase() === 'tbody' ) {
return elem;
}
}
return null;
};
for (var i = 0; i < tables.length; i++) {
// Check if a table head already exists
var thead = tables[i].querySelector( 'thead' );
if ( thead ) continue;
// Get the first table row and conver it to a thead
var row = tables[i].querySelector('tr');
var tbody = getTbody( row );
if ( !row || !tbody ) continue;
thead = document.createElement('thead');
thead.innerHTML = '<tr>' + row.innerHTML + '</tr>';
console.log(tbody.parentNode);
tbody.parentNode.insertBefore( thead, tbody );
row.parentNode.removeChild( row );
}
};
// Run script initializations when the Portal is ready
portalReady(function () {
astro.init();
clickToHighlight.init();
fluidvids.init({
selector: ['iframe', 'object'], // runs querySelectorAll()
players: ['www.youtube.com', 'player.vimeo.com'] // players to support
});
houdini.init();
modals.init();
rightHeight.init();
smoothScroll.init();
stickyFooter.init();
tabby.init();
addTableHeaders();
});
The Mashery Portal WYSIWYG generates tables that are missing the required <thead>
and <th>
elements. You can fix this by calling the addTableHeaders()
JavaScript method. This is done for you already in the Body JavaScript section of Portal Setup in the Dashboard.
portalReady(function () {
addTableHeaders();
});
white-space: nowrap;
/**
* fullWidth.js
* Copyright (c) 2017. TIBCO Software Inc. All Rights Reserved.
* @description Make page full-width (no padding or centering)
* @version 0.0.1
* @author Chris Ferdinandi
* @param {Boolean} hideH1 If true, hide the H1 header
* @param {Boolean} wide If true, go wide instead of full width
*/
var fullWidth = function ( hideH1, wide ) {
'use strict';
// Feature test
if ( !document.querySelector || !window.addEventListener ) return;
// Variables
var meta = document.querySelector( '.section-meta' );
var edit = document.querySelector( '.section-menu .edit' );
var h1 = document.querySelector( 'h1.first' );
// Go full width
if (wide) {
document.documentElement.classList.add( 'dom-wide' );
} else {
document.documentElement.classList.add( 'dom-full-width' );
}
// Wrap elements in container class
if ( meta ) {
wrapElem( meta, '<div class="container">{{content}}</div>' );
}
if ( edit ) {
wrapElem( edit.parentNode.parentNode, '<div class="container">{{content}}</div>' );
}
if ( h1 ) {
// If enabled, hide the primary h1 element
if ( hideH1 ) {
h1.style.display = 'none';
h1.style.visibility = 'hidden';
}
wrapElem( h1, '<div class="container">{{content}}</div>' );
}
};
/**
* Houdini Subnav
* @description A Houdini expand-and-collapse functionality to documentation pages.
* @version 1.0.2
* @author Chris Ferdinandi
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('houdiniSubnav', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.houdiniSubnav = factory(root);
}
})(window || this, function (root) {
'use strict';
//
// Variables
//
var houdiniSubnav = {}; // Object for public APIs
var supports = !!document.querySelector && !!root.addEventListener; // Feature test
var settings, theNav, navs, navOriginal;
// Default settings
var defaults = {
selectorNav: '#sub > ul',
selectorNavs: '#sub > ul > li',
isAccordion: false,
iconShow: '+',
iconHide: '–',
iconAfter: true,
iconMargin: '0.5em',
initClass: 'js-houdini-subnav',
};
//
// Methods
//
/**
* A simple forEach() implementation for Arrays, Objects and NodeLists
* @private
* @param {Array|Object|NodeList} collection Collection of items to iterate
* @param {Function} callback Callback function for each iteration
* @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
*/
var forEach = function (collection, callback, scope) {
if (Object.prototype.toString.call(collection) === '[object Object]') {
for (var prop in collection) {
if (Object.prototype.hasOwnProperty.call(collection, prop)) {
callback.call(scope, collection[prop], prop, collection);
}
}
} else {
for (var i = 0, len = collection.length; i < len; i++) {
callback.call(scope, collection[i], i, collection);
}
}
};
/**
* Merge defaults with user options
* @private
* @param {Object} defaults Default settings
* @param {Object} options User options
* @returns {Object} Merged values of defaults and options
*/
var extend = function () {
// Variables
var extended = {};
var deep = false;
var i = 0;
var length = arguments.length;
// Check if a deep merge
if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
deep = arguments[0];
i++;
}
// Merge the object into the extended object
var merge = function (obj) {
for ( var prop in obj ) {
if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
// If deep merge and property is an object, merge properties
if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
extended[prop] = extend( true, extended[prop], obj[prop] );
} else {
extended[prop] = obj[prop];
}
}
}
};
// Loop through each object and conduct a merge
for ( ; i < length; i++ ) {
var obj = arguments[i];
merge(obj);
}
return extended;
};
/**
* Create the link node
* @private
* @param {Node} navlink The current link element
* @param {Boolean} isActive If true, current link is the active one
* @param {Number} index The index for the current link in the nodeslist
*/
var renderLink = function ( navlink, isActive, index ) {
// Create link
var toggle = navlink.parentNode.querySelector( 'a[data-collapse]' ) || document.createElement( 'a' );
var location = settings.iconAfter ? navlink.nextSibling : navlink;
toggle.href = '#docs-subnav-' + index;
toggle.innerHTML = '<span class="collapse-text-show">' + settings.iconShow + '</span><span class="collapse-text-hide">' + settings.iconHide + '</span>';
toggle.classList.add( 'collapse-toggle' );
toggle.setAttribute( 'data-collapse', true );
if ( isActive ) {
toggle.classList.add( 'active' );
navlink.parentNode.classList.add( 'active-parent' );
}
if ( settings.isAccordion ) { toggle.setAttribute( 'data-group', 'docs-subnav' ); }
// Add margin
if ( settings.iconAfter ) {
toggle.style.marginLeft = settings.iconMargin;
} else {
toggle.style.marginRight = settings.iconMargin;
}
// Inject link into DOM
navlink.parentNode.insertBefore(toggle, location);
};
/**
* Loop through each subnav element and add expand-and-collapse attributes
* @private
* @param {NodesList} navs Nav elements
*/
var addAttributes = function ( navs, offset ) {
offset = offset ? offset : '';
forEach(navs, function (nav, index) {
// Get subnav
var subnav = nav.querySelector( 'ul' );
// If no subnav, move on to the next nav element
if ( !subnav ) return;
// Get subnav link
var navlink = nav.firstChild;
// Determine if nav is active
var isActive = nav.classList.contains( 'active' );
// Remove .active class from parent li
nav.classList.remove( 'active' );
// Render the link
renderLink( navlink, isActive, offset + '-' + index );
// Add classes and ID to subnav
subnav.classList.add( 'collapse' );
subnav.id = 'docs-subnav-' + offset + '-' + index;
if ( isActive ) { subnav.classList.add( 'active' ); }
// If subnav has subnav, run again
var subSubNavs = subnav.children;
addAttributes( subSubNavs, offset + '-' + index );
});
};
/**
* Destroy the current initialization.
* @public
*/
houdiniSubnav.destroy = function () {
if ( !settings ) return;
// Remove init class
document.documentElement.classList.remove( settings.initClass );
// Restore original nav
theNav.innerHTML = navOriginal;
// Reset variables
settings = null;
theNav = null;
navs = null;
};
/**
* Initialize Houdini
* @public
* @param {Object} options User settings
*/
houdiniSubnav.init = function ( options ) {
// feature test
if ( !supports ) return;
// Destroy any existing initializations
houdiniSubnav.destroy();
// Variables
settings = extend( defaults, options || {} ); // Merge user options with defaults
theNav = document.querySelector( settings.selectorNav );
navs = document.querySelectorAll( settings.selectorNavs );
// If set to only run on Docs and not docs page, end
if ( !document.body.classList.contains( 'page-docs' ) ) return;
// Add class to HTML element to activate conditional CSS
document.documentElement.classList.add( settings.initClass );
// Save original nav
navOriginal = theNav.innerHTML;
// Add Houdini hooks to subnav
addAttributes( navs );
};
//
// Public APIs
//
return houdiniSubnav;
});
Add a callback
/**
* conditionalContactFields.js
* @description Show or hide contact form fields based on the response to one question
* @version 0.0.1
* @author Chris Ferdinandi
*/
var conditionalContactFields = function ( question, answers ) {
'use strict';
// Sanity check
if ( !question || !answers || Object.prototype.toString.call(answers) !== '[object Object]' ) return;
// Feature test
if ( !document.querySelector || !window.addEventListener ) return;
//
// Variables
//
//
// Methods
//
/**
* A simple forEach() implementation for Arrays, Objects and NodeLists.
* @private
* @author Todd Motto
* @link https://github.com/toddmotto/foreach
* @param {Array|Object|NodeList} collection Collection of items to iterate
* @param {Function} callback Callback function for each iteration
* @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
*/
var forEach = function ( collection, callback, scope ) {
if ( Object.prototype.toString.call( collection ) === '[object Object]' ) {
for ( var prop in collection ) {
if ( Object.prototype.hasOwnProperty.call( collection, prop ) ) {
callback.call( scope, collection[prop], prop, collection );
}
}
} else {
for ( var i = 0 ; i < collection.length; i++ ) {
callback.call( scope, collection[i], i, collection );
}
}
};
/**
* Get the closest matching element up the DOM tree.
* @private
* @param {Element} elem Starting element
* @param {String} selector Selector to match against (class, ID, data attribute, or tag)
* @return {Boolean|Element} Returns null if not match found
*/
var getClosest = function ( elem, selector ) {
// Variables
var firstChar = selector.charAt(0);
var attribute, value;
// If selector is a data attribute, split attribute from value
if ( firstChar === '[' ) {
selector = selector.substr(1, selector.length - 2);
attribute = selector.split( '=' );
if ( attribute.length > 1 ) {
value = true;
attribute[1] = attribute[1].replace( /"/g, '' ).replace( /'/g, '' );
}
}
// Get closest match
for ( ; elem && elem !== document; elem = elem.parentNode ) {
// If selector is a class
if ( firstChar === '.' ) {
if ( elem.classList.contains( selector.substr(1) ) ) {
return elem;
}
}
// If selector is an ID
if ( firstChar === '#' ) {
if ( elem.id === selector.substr(1) ) {
return elem;
}
}
// If selector is a data attribute
if ( firstChar === '[' ) {
if ( elem.hasAttribute( attribute[0] ) ) {
if ( value ) {
if ( elem.getAttribute( attribute[0] ) === attribute[1] ) {
return elem;
}
} else {
return elem;
}
}
}
// If selector is a tag
if ( elem.tagName.toLowerCase() === selector ) {
return elem;
}
}
return null;
};
var hideField = function ( field ) {
if ( !field ) return;
field.style.display = 'none';
field.style.visibility = 'hidden';
if ( !field.value || field.value === '' ) {
field.value = 'null';
}
};
var showField = function ( field ) {
if ( !field ) return;
field.style.display = 'block';
field.style.visibility = 'visible';
if ( field.value === 'null' ) {
field.value = '';
}
};
var hideFields = function ( chosen ) {
forEach(answers, function (fields, answer) {
// Don't hide the select answer fields
if ( chosen.toString() === answer.toString() ) return;
// Sanity check
if ( Object.prototype.toString.call(fields) !== '[object Array]' ) return;
// Hide the fields
forEach(fields, function (selector) {
hideField( document.querySelector( '[for="' + selector + '"]' ) );
hideField( document.querySelector( '#' + selector ) );
});
});
};
var showFields = function ( chosen ) {
// Get the fields
var fields = answers[chosen];
// Sanity check
if ( !fields ) return;
if ( Object.prototype.toString.call(fields) !== '[object Array]' ) return;
// Hide the fields
forEach(fields, function (selector) {
showField( document.querySelector( '[for="' + selector + '"]' ) );
showField( document.querySelector( '#' + selector ) );
});
};
/**
* Handle toggle click events
* @private
*/
var eventHandler = function (event) {
var toggle = getClosest( event.target, question );
if ( !toggle ) return;
hideFields( toggle.value );
showFields( toggle.value );
};
//
// Event Listeners and inits
//
// Get the question selector
var selector = document.querySelector( question );
if ( !selector ) return;
// Show/hide fields on load
hideFields( selector.value );
// Listen for click events
document.addEventListener('click', eventHandler, false);
};
/**
* breadcrumbs.js
* @description Add breadcrumbs to the Portal
* @version 1.0.1
* @author Chris Ferdinandi
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('breadcrumbs', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.breadcrumbs = factory(root);
}
})(window || this, function (root) {
'use strict';
//
// Variables
//
var breadcrumbs = {}; // Object for public APIs
var supports = !!document.querySelector; // Feature test
var settings, path;
// Default settings
var defaults = {
pages: 'all', // all | docs | page | blog | forum | ioDocs | account
exclude: '.dom-landing',
selector: '#page',
docs: 'Documentation',
ioDocs: 'IO-Docs',
forumAddCategory: 'Add Category',
accountMyAccount: 'My Account',
accountMyKeys: 'My API Keys',
accountMyApps: 'My Applications',
memberManage: 'Manage My Account',
memberEmail: 'Change Email',
memberPassword: 'Change Password',
customTitles: {},
initClass: 'js-breadcrumbs',
containerClass: 'container padding-top-small text-muted link-plain',
listClass: 'list-inline list-inline-breadcrumbs',
callback: function () {},
};
//
// Methods
//
/**
* Convert string to title case
* @private
* @param {String} str The string to convert to title case
* @return {String} Title cased string
* @url http://stackoverflow.com/a/4878800/1293256
* @todo If IO-Docs, custom override
*/
var toTitleCase = function ( str ) {
// Variables
var titleCase;
// Otherwise, transform to title case
titleCase = str.replace( /\w\S*/g,
function ( txt ) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
// Manual overrides for certain pages
if ( titleCase === 'Docs' ) titleCase = settings.docs; // Documentation
if ( titleCase === 'Io-docs' ) titleCase = settings.ioDocs; // IO-Docs
if ( titleCase === 'Category-add' ) titleCase = settings.forumAddCategory; // New Forum Category
if ( titleCase === 'Mykeys' ) titleCase = settings.accountMyKeys; // My API Keys
if ( titleCase === 'Myapps' ) titleCase = settings.accountMyApps; // My Applications
if ( document.body.id === 'page-member' && titleCase === 'Edit' ) titleCase = settings.memberManage; // Manage Account
if ( document.body.id === 'page-member' && titleCase === 'Email' ) titleCase = settings.memberEmail; // Change email
if ( document.body.id === 'page-member' && titleCase === 'Passwd' ) titleCase = settings.memberPassword; // Change password
if ( settings.customTitles.hasOwnProperty( titleCase.toLowerCase() ) ) titleCase = settings.customTitles[titleCase.toLowerCase()]; // Custom overrides
// @todo If forum and not "add category", return empty after 'forum'
return titleCase;
};
/**
* Remove junk from the path and set variables
* @private
* @param {String} path The URL path
* @return {[type]} [description]
*/
var sanitizePath = function () {
// If Docs or Blog, remove /read and /Home
if ( document.body.classList.contains( 'page-docs' ) || document.body.classList.contains( 'page-blog' ) ) {
path = path.replace( /\/read/, '' ).replace( /\/Home/, '' );
}
// If Forum, remove /read
if ( document.body.classList.contains( 'page-forum' ) ) {
path = path.replace( /\/read/, '' );
}
// If Profile, remove redundant /profile
if ( document.body.classList.contains( 'page-profile' ) ) {
path = path.substring( path.indexOf( '/profile' ), 8 );
}
// Remove leading and trailing slashes
if ( path.charAt(0) === '/' ) { path = path.substr(1); }
if ( path.charAt( path.length - 1 ) === '/' ) { path = path.substr(0, path.length - 1); }
};
/**
* Create breadcrumb markup
* @private
* @return {String} The breadcrumb markup
*/
var createBreadcrumbs = function () {
// Variables
var crumbs = path.split( '/' );
var count = crumbs.length;
var breadcrumbs = '<li><a href="/">Home</a></li>';
var isForum = document.body.classList.contains( 'page-forum' );
var link = '';
// If it's the landing page, remove link from "Home" breadcrumb
if ( document.documentElement.classList.contains( 'dom-landing' ) ) breadcrumbs = '<li>Home</li>';
// Create breadcrumb links
buoy.forEach(crumbs, function (crumb, index) {
// If crumb is empty or it's the forum, bail
if ( crumb === '' || isForum ) return;
// Create the title
var title = toTitleCase( crumb.replace( /_/g, ' ' ) );
// If the last crumb, don't add a link
if ( index === count - 1 ) {
breadcrumbs += '<li>' + title + '</li>';
return;
}
// If is account/member page, override App/Member crumb
if ( document.body.classList.contains( 'page-apps' ) || document.body.classList.contains( 'page-member' ) ) {
if ( title === 'Apps' || title === 'Member' ) {
breadcrumbs += '<li><a href="/apps/mykeys">' + settings.accountMyAccount + '</a></li>';
return;
}
}
// Otherwise, create a linked crumb
link += '/' + crumb;
console.log(link);
breadcrumbs += '<li><a href="' + link + '">' + title + '</a></li>';
});
// Custom breadcrumb for the forum
if ( isForum ) {
if ( document.documentElement.classList.contains( 'dom-forum' ) ) {
breadcrumbs += '<li>Forum</li>';
} else {
breadcrumbs += '<li><a href="/forum">Forum</a></li>';
}
}
return '<div class="' + settings.containerClass + '" id="nav-breadcrumbs"><ul class="' + settings.listClass + '" id="nav-breadcrumbs-list">' + breadcrumbs + '</ul></div>';
};
/**
* Load breadcrumbs into the DOM
* @private
*/
var loadCrumbs = function () {
// Remove junk from the path
sanitizePath();
// Create breadcrumbs
var breadcrumbs = createBreadcrumbs();
// Inject breadcrumbs into the DOM
loadHTML( breadcrumbs, document.querySelector( settings.selector ) );
// Run callback
settings.callback();
};
/**
* Check to see if the page is on the exclude/include list
* @private
* @return {Boolean} Returns true if the breadcrumbs should be loaded onto the page
*/
var okToRun = function () {
// Variables
var selectors = '';
// Don't run on explicitly excluded pages
if ( settings.exclude && document.querySelector( settings.exclude ) ) return false;
// Don't run on the wiki page
if ( document.body.classList.contains( 'page-wiki' ) ) return false;
// Create selector(s)
if ( Object.prototype.toString.call( settings.pages ) === '[object Array]' ) {
// Get number of pages
var count = settings.pages.length;
// For each one, create a selector
buoy.forEach(settings.pages, function (page, index) {
// Add a comma delimiter to all but the last item
var delimiter = index + 1 === count ? '' : ', ';
// Special dual class for account pages
if ( page === 'account' ) {
selectors += '.page-account, .page-member';
return;
}
// Create selector
selectors += '.page-' + page + delimiter;
});
} else {
// If it should be run on all pages, return true
if ( settings.pages === 'all' ) return true;
// Create selector
selectors = '.page-' + settings.pages;
}
// If selectors exist, OK to run.
// Otherwise, return false.
var pages = document.querySelectorAll( selectors );
if ( pages.length === 0 ) return false;
return true;
};
/**
* Destroy the current initialization.
* @public
*/
breadcrumbs.destroy = function () {
if ( !settings ) return;
// Remove init class
document.documentElement.classList.remove( settings.initClass );
// Remove breadcrumbs from the DOM
var breadcrumbs = document.querySelector( '#nav-breadcrumbs' );
if ( breadcrumbs ) {
breadcrumbs.parentNode.removeChild( breadcrumbs );
}
// Reset variables
settings = null;
path = null;
};
/**
* Initialize Houdini
* @public
* @param {Object} options User settings
*/
breadcrumbs.init = function ( options ) {
// feature test
if ( !supports ) return;
// Destroy any existing initializations
breadcrumbs.destroy();
// Merge user options with defaults
settings = buoy.extend( true, defaults, options || {} );
// Check if it's ok to run based on user settings
if ( !okToRun() ) return;
// Get the current URL path
path = window.location.pathname;
// Add class to HTML element to activate conditional CSS
document.documentElement.classList.add( settings.initClass );
// Load breadcrumbs onto the page
loadCrumbs();
};
//
// Public APIs
//
return breadcrumbs;
});
;(function (window, document, undefined) {
'use strict';
// SVG feature detection
var supports = !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect;
// If SVG is supported, add `.svg` class to <html> element
if ( !supports ) return;
document.documentElement.className += (document.documentElement.className ? ' ' : '') + 'svg';
})(window, document);
thead {
border-bottom: calc-em(2px) solid $color-gray-light;
.search-form & {
border-bottom: 0;
}
}
th,
thead td {
// background-color: lighten( $color-gray-light, 5% );
font-weight: bold;
vertical-align: bottom;
.search-form & {
vertical-align: top;
}
}
In body.js
:
// Run script initializations when the Portal is ready
portalReady(function () {
astro.init();
clickToHighlight.init();
fluidvids.init({
selector: ['iframe', 'object'], // runs querySelectorAll()
players: ['www.youtube.com', 'player.vimeo.com'] // players to support
});
houdini.init({
selectorToggle: '.collapse-toggle',
});
rightHeight.init({
selector: '.js-right-height',
selectorContent: '.js-right-height-content',
});
smoothScroll.init({
selector: '.js-scroll',
selectorHeader: '.js-scroll-header',
});
stickyFooter.init({
selector: '.js-sticky-footer',
});
tabby.init({
selectorToggle: '.js-tab',
selectorToggleGroup: '.tabs',
selectorContent: '.tabs-pane',
selectorContentGroup: '.js-tabs-content',
});
addTableHeaders();
});
// Calculate pixels from ems
@function calc-px($em, $base: 16) {
$em: strip-unit($em);
$base: strip-unit($base);
@if $em == 1px {
@return 1px;
}
@return ($em * $base) * 1px;
}
@media (max-width: (calc-em(calc-px($bp-large) - 1))) { ... }
/**
* Houdini Subnav
* @description A Houdini expand-and-collapse functionality to documentation pages.
* @version 1.0.0
* @author Chris Ferdinandi
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('houdiniSubnav', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.houdiniSubnav = factory(root);
}
})(window || this, function (root) {
'use strict';
//
// Variables
//
var houdiniSubnav = {}; // Object for public APIs
var supports = !!document.querySelector && !!root.addEventListener; // Feature test
var settings, theNav, navs, navOriginal;
// Default settings
var defaults = {
selectorNav: '#sub > ul',
selectorNavs: '#sub > ul > li',
isAccordion: false,
iconShow: '+',
iconHide: '–',
iconAfter: true,
iconMargin: '0.5em',
initClass: 'js-houdini-subnav',
};
//
// Methods
//
/**
* Create the link node
* @private
* @param {Node} navlink The current link element
* @param {Boolean} isActive If true, current link is the active one
* @param {Number} index The index for the current link in the nodeslist
*/
var renderLink = function ( navlink, isActive, index ) {
// Create link
var toggle = document.createElement( 'a' );
var location = settings.iconAfter ? navlink.nextSibling : navlink;
toggle.href = '#docs-subnav-' + index;
toggle.innerHTML = '<span class="collapse-text-show">' + settings.iconShow + '</span><span class="collapse-text-hide">' + settings.iconHide + '</span>';
toggle.classList.add( 'collapse-toggle' );
toggle.setAttribute( 'data-collapse', true );
if ( settings.iconAfter ) {
toggle.style.marginLeft = settings.iconMargin;
} else {
toggle.style.marginRight = settings.iconMargin;
}
if ( isActive ) { toggle.classList.add( 'active' ); }
if ( settings.isAccordion ) { toggle.setAttribute( 'data-group', 'docs-subnav' ); }
// Inject link into DOM
navlink.parentNode.insertBefore(toggle, location);
};
/**
* Loop through each subnav element and add expand-and-collapse attributes
* @private
* @param {NodesList} navs Nav elements
*/
var addAttributes = function ( navs ) {
buoy.forEach(navs, function (nav, index) {
// Get subnav
var subnav = nav.querySelector( 'ul' );
// If no subnav, move on to the next nav element
if ( !subnav ) return;
// Get subnav link
var navlink = nav.firstChild;
// Determine if nav is active
var isActive = nav.classList.contains( 'active' );
// Remove .active class from parent li
nav.classList.remove( 'active' );
// Render the link
renderLink( navlink, isActive, index );
// Add classes and ID to subnav
subnav.classList.add( 'collapse' );
subnav.id = 'docs-subnav-' + index;
if ( isActive ) { subnav.classList.add( 'active' ); }
// If subnav has subnav, run again
var subSubNavs = subnav.querySelectorAll( 'ul > li' );
addAttributes( subSubNavs );
});
};
/**
* Destroy the current initialization.
* @public
*/
houdiniSubnav.destroy = function () {
if ( !settings ) return;
// Remove init class
document.documentElement.classList.remove( settings.initClass );
// Restore original nav
theNav.innerHTML = navOriginal;
// Reset variables
settings = null;
theNav = null;
navs = null;
};
/**
* Initialize Houdini
* @public
* @param {Object} options User settings
*/
houdiniSubnav.init = function ( options ) {
// feature test
if ( !supports ) return;
// Destroy any existing initializations
houdiniSubnav.destroy();
// Variables
settings = buoy.extend( defaults, options || {} ); // Merge user options with defaults
theNav = document.querySelector( settings.selectorNav );
navs = document.querySelectorAll( settings.selectorNavs );
// If set to only run on Docs and not docs page, end
if ( !document.body.classList.contains( 'page-docs' ) ) return;
// Add class to HTML element to activate conditional CSS
document.documentElement.classList.add( settings.initClass );
// Save original nav
navOriginal = theNav.innerHTML;
// Add Houdini hooks to subnav
addAttributes( navs );
};
//
// Public APIs
//
return houdiniSubnav;
});
(labels[n].innerText || labels[n].textContent)
thead
/tbody
to avoid some quirksloadCSS('https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,700');
if ( docCookies.getItem( 'fontsLoaded' ) ) {
document.documentElement.className += ' fonts-loaded';
} else {
var font = new FontFaceObserver('Source Sans Pro');
font.load().then(function () {
var expires = new Date(+new Date() + (7 * 24 * 60 * 60 * 1000)).toUTCString();
document.cookie = 'fontsLoaded=true; expires=' + expires;
document.documentElement.className += ' fonts-loaded';
});
}
And cookies.js
in detects.js
:
/*\
|*|
|*| :: cookies.js ::
|*|
|*| A complete cookies reader/writer framework with full unicode support.
|*|
|*| Revision #1 - September 4, 2014
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*| https://developer.mozilla.org/User:fusionchess
|*| https://github.com/madmurphy/cookies.js
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntaxes:
|*|
|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
|*| * docCookies.getItem(name)
|*| * docCookies.removeItem(name[, path[, domain]])
|*| * docCookies.hasItem(name)
|*| * docCookies.keys()
|*|
\*/
var docCookies = {
getItem: function (sKey) {
if (!sKey) { return null; }
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
// setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
// if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
// var sExpires = "";
// if (vEnd) {
// switch (vEnd.constructor) {
// case Number:
// sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
// break;
// case String:
// sExpires = "; expires=" + vEnd;
// break;
// case Date:
// sExpires = "; expires=" + vEnd.toUTCString();
// break;
// }
// }
// document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
// return true;
// },
// removeItem: function (sKey, sPath, sDomain) {
// if (!this.hasItem(sKey)) { return false; }
// document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
// return true;
// },
// hasItem: function (sKey) {
// if (!sKey) { return false; }
// return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
// },
// keys: function () {
// var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
// for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
// return aKeys;
// }
};
/**
* Houdini subnav
*/
.js-houdini ul.collapse.active {
margin-left: $spacing;
}
/**
* Houdini Subnav
* @description A Houdini expand-and-collapse functionality to documentation pages.
* @version 1.0.1
* @author Chris Ferdinandi
*/
(function (root, factory) {
if ( typeof define === 'function' && define.amd ) {
define('houdiniSubnav', factory(root));
} else if ( typeof exports === 'object' ) {
module.exports = factory(root);
} else {
root.houdiniSubnav = factory(root);
}
})(window || this, function (root) {
'use strict';
//
// Variables
//
var houdiniSubnav = {}; // Object for public APIs
var supports = !!document.querySelector && !!root.addEventListener; // Feature test
var settings, theNav, navs, navOriginal;
// Default settings
var defaults = {
selectorNav: '#sub > ul',
selectorNavs: '#sub > ul > li',
isAccordion: false,
iconShow: '+',
iconHide: '–',
iconAfter: true,
iconMargin: '0.5em',
initClass: 'js-houdini-subnav',
};
//
// Methods
//
/**
* A simple forEach() implementation for Arrays, Objects and NodeLists
* @private
* @param {Array|Object|NodeList} collection Collection of items to iterate
* @param {Function} callback Callback function for each iteration
* @param {Array|Object|NodeList} scope Object/NodeList/Array that forEach is iterating over (aka `this`)
*/
var forEach = function (collection, callback, scope) {
if (Object.prototype.toString.call(collection) === '[object Object]') {
for (var prop in collection) {
if (Object.prototype.hasOwnProperty.call(collection, prop)) {
callback.call(scope, collection[prop], prop, collection);
}
}
} else {
for (var i = 0, len = collection.length; i < len; i++) {
callback.call(scope, collection[i], i, collection);
}
}
};
/**
* Merge defaults with user options
* @private
* @param {Object} defaults Default settings
* @param {Object} options User options
* @returns {Object} Merged values of defaults and options
*/
var extend = function () {
// Variables
var extended = {};
var deep = false;
var i = 0;
var length = arguments.length;
// Check if a deep merge
if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) {
deep = arguments[0];
i++;
}
// Merge the object into the extended object
var merge = function (obj) {
for ( var prop in obj ) {
if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) {
// If deep merge and property is an object, merge properties
if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) {
extended[prop] = extend( true, extended[prop], obj[prop] );
} else {
extended[prop] = obj[prop];
}
}
}
};
// Loop through each object and conduct a merge
for ( ; i < length; i++ ) {
var obj = arguments[i];
merge(obj);
}
return extended;
};
/**
* Create the link node
* @private
* @param {Node} navlink The current link element
* @param {Boolean} isActive If true, current link is the active one
* @param {Number} index The index for the current link in the nodeslist
*/
var renderLink = function ( navlink, isActive, index ) {
// Create link
var toggle = navlink.parentNode.querySelector( 'a[data-collapse]' ) || document.createElement( 'a' );
var location = settings.iconAfter ? navlink.nextSibling : navlink;
toggle.href = '#docs-subnav-' + index;
toggle.innerHTML = '<span class="collapse-text-show">' + settings.iconShow + '</span><span class="collapse-text-hide">' + settings.iconHide + '</span>';
toggle.classList.add( 'collapse-toggle' );
toggle.setAttribute( 'data-collapse', true );
if ( isActive ) { toggle.classList.add( 'active' ); }
if ( settings.isAccordion ) { toggle.setAttribute( 'data-group', 'docs-subnav' ); }
// Add margin
if ( settings.iconAfter ) {
toggle.style.marginLeft = settings.iconMargin;
} else {
toggle.style.marginRight = settings.iconMargin;
}
// Inject link into DOM
navlink.parentNode.insertBefore(toggle, location);
};
/**
* Loop through each subnav element and add expand-and-collapse attributes
* @private
* @param {NodesList} navs Nav elements
*/
var addAttributes = function ( navs, offset ) {
offset = offset ? offset : '';
forEach(navs, function (nav, index) {
// Get subnav
var subnav = nav.querySelector( 'ul' );
// If no subnav, move on to the next nav element
if ( !subnav ) return;
// Get subnav link
var navlink = nav.firstChild;
// Determine if nav is active
var isActive = nav.classList.contains( 'active' );
// Remove .active class from parent li
nav.classList.remove( 'active' );
// Render the link
renderLink( navlink, isActive, offset + '-' + index );
// Add classes and ID to subnav
subnav.classList.add( 'collapse' );
subnav.id = 'docs-subnav-' + offset + '-' + index;
if ( isActive ) { subnav.classList.add( 'active' ); }
// If subnav has subnav, run again
var subSubNavs = subnav.children;
addAttributes( subSubNavs, offset + '-' + index );
});
};
/**
* Destroy the current initialization.
* @public
*/
houdiniSubnav.destroy = function () {
if ( !settings ) return;
// Remove init class
document.documentElement.classList.remove( settings.initClass );
// Restore original nav
theNav.innerHTML = navOriginal;
// Reset variables
settings = null;
theNav = null;
navs = null;
};
/**
* Initialize Houdini
* @public
* @param {Object} options User settings
*/
houdiniSubnav.init = function ( options ) {
// feature test
if ( !supports ) return;
// Destroy any existing initializations
houdiniSubnav.destroy();
// Variables
settings = extend( defaults, options || {} ); // Merge user options with defaults
theNav = document.querySelector( settings.selectorNav );
navs = document.querySelectorAll( settings.selectorNavs );
// If set to only run on Docs and not docs page, end
if ( !document.body.classList.contains( 'page-docs' ) ) return;
// Add class to HTML element to activate conditional CSS
document.documentElement.classList.add( settings.initClass );
// Save original nav
navOriginal = theNav.innerHTML;
// Add Houdini hooks to subnav
addAttributes( navs );
};
//
// Public APIs
//
return houdiniSubnav;
});
https://stagingcs9.mashery.com/member/register
By clicking the "Register" button, I certify that I have read and agree to the Mashery Terms of Service and Privacy Policy
Copyright (c) 2017, TIBCO Software Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
The name of TIBCO Software Inc. may not be used to endorse or promote products derived from this software without specific prior written permission of TIBCO Software Inc.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Targets:
h1.first
- H1 heading on most pages#sub > h2
- Docs subnav#main > h1
- IO Docs, My Account, Signed Out Confirm, (prefix with page selector).dom-login-login h2.sign-in
- Sign InAdd specific page targets, too
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.