Files
Chateau-deau/high/highcharts/api/js/api.js
Le Stagiaire 0cfc5938bd first commit
2024-11-08 15:31:00 +01:00

1171 lines
30 KiB
JavaScript

var $hilighted,
$hilightedMenuItem,
optionDictionary = {},
names = [],
buildApiOffline,
offline = {},
API = {},
methods = [],
memberInfo = {},
usedUrls = [],
page = PAGE,
buildPage;
function loadScript(url, callback) {
//http://www.nczonline.net/blog/2009/07/28/the-best-way-to-load-external-javascript/
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function() {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
function toDot (id){
return id.replace(/[-]+/g,'.');
}
function escapeHTML(html) {
if (typeof html === 'string') {
html = html
.replace('\u25CF', '\\u25CF')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
return html;
}
function escapeSelector (name) {
return name.replace('<', '\\<').replace('>', '\\>');
}
function activateInternalLinks($parent) {
$('a[href^="#"]', $parent).each(function (i, anchor) {
$(anchor).click(function (e) {
memberClick(anchor.href.replace(/.*#/, ''), e);
return false;
});
});
}
/**
* Highligth a specific option by coloring it in the menu view and section view
*/
function hilight (id) {
var linkId, $el, $detailsWrap = $('#details-wrap');
$el = $('div.member#' + escapeSelector(id));
// clear old
if ($hilighted) {
$hilighted.removeClass('hilighted');
}
if ($hilightedMenuItem) {
$hilightedMenuItem.removeClass('hilighted');
}
if ($el.length === 0) {
$detailsWrap.scrollTop(0);
} else {
// hilight new
$hilighted = $el;
$hilighted.addClass('hilighted');
// Scroll to the hilighted member
$detailsWrap.animate({ scrollTop: $hilighted.offset().top + $detailsWrap.scrollTop() - 160 }, 400);
// Workaround for weird case where an element wont scroll under certain conditions
// http://stackoverflow.com/questions/1830080/jquery-scrolltop-doesnt-seem-to-work-in-safari-or-chrome-windows#answer-4165094
$('body, html, document').animate({ scrollTop: $hilighted.offset().top + $detailsWrap.scrollTop() - 160 }, 400);
}
linkId = id.replace(/[^a-z0-9<>\\]+/gi,'.');
$hilightedMenuItem = $('a[href="/' + getBasePath() + linkId +'"]').not('.plus');
$hilightedMenuItem.addClass('hilighted');
}
/**
* Expand and load children when necessary of current level
*/
function toggleExpand($elem, callback) {
var $_menu = $elem.find('div[id$="-menu"]').first(),
_id = $_menu.attr('id').replace("-menu",""),
displayChildrenCallback = function () {
$('.dots', $elem).removeClass('loading');
$elem.removeClass("collapsed");
$elem.addClass("expanded");
$_menu.slideDown();
// show relevant section
if (/[A-Z]/.test(_id[0])) {
_id = 'object-' + _id;
}
toggleSection(_id);
if (callback) {
callback();
}
};
if ($elem.hasClass('collapsed')) {
/* if not loaded, load children, standard we have three children */
if ($_menu.children().size() == 1) {
$('.dots', $elem).addClass('loading');
loadChildren(_id, false, displayChildrenCallback);
} else {
displayChildrenCallback();
}
} else {
// hide children
$_menu.slideUp('normal',function(){
$elem.removeClass("expanded");
$elem.addClass("collapsed");
});
}
}
function toggleSection(sectionId) {
$section = $("#details > div.section:visible");
// hide current section
if($section){
$section.hide();
}
if (/[^\\]</.test(sectionId)) {
sectionId = sectionId.replace('<', '\\<').replace('>', '\\>');
}
$('#details > div.section#' + sectionId).show();
}
/**
* Makes a member name with dot-notation wrappable as html by splitting it at the dots and returning spans with text
*
* @param memberTitle - the dot-notation member title
*/
function wrappableMemberTitle(memberTitle) {
var parts = memberTitle.split('.'),
wrappableMemberTitle = '',
index;
for (index in parts) {
wrappableMemberTitle += '<span>.' + parts[index] + '</span>';
}
// Replace first dot
wrappableMemberTitle = wrappableMemberTitle.replace(/\./, '');
return wrappableMemberTitle;
}
function addSectionOption(val){
var title = val.fullname.replace('<', '&lt;').replace('>', '&gt;');
$section = $('<div class="section" id="' + val.name + '" style="display:none;"></div>').appendTo('#details');
$('<h1>' + wrappableMemberTitle(title) + '</h1>'
+ (val.description ? '<div class="section-description">' + val.description + '</div>': '')
+ (val.demo ? '<div class="demo section-demo"><h4>Try it:</h4> ' + val.demo + '</div>': '' )).appendTo($section);
activateInternalLinks($section);
$(document).triggerHandler({ type:"xtra.btn.section.event",id: optionDictionary[val.fullname], table: 'option' });
}
function addSectionObject(val){
var title = val.title;
$section = $('<div class="section" id="object-' + val.name + '" style="display:none;"></div>').appendTo('#details');
$('<h1>' + wrappableMemberTitle(title) + '</h1>').appendTo($section);
$('<div class="section-description">' + val.description + '</div>').appendTo($section);
activateInternalLinks($section);
$(document).triggerHandler({ type:"xtra.btn.section.event",id: 'object-'+ val.name, table: 'object'});
}
function markupReturnType(s) {
var basePath;
if (historyEnabled()) {
basePath = '/' + getBasePath();
} else {
basePath = '#';
}
s = s.replace(/[<>]/g, function (a) {
return {
'<': '&lt;',
'>': '&gt;'
}[a];
});
s = s.replace(/(Axis|Chart|Element|Highcharts|Point|Renderer|Series)/g, '<a href="' + basePath + '$1">$1</a>');
return s;
}
/**
* Checks if the history API
* @returns {boolean}
*/
function historyEnabled() {
return runDB &&
window.history !== undefined &&
window.history !== null &&
window.history.pushState !== undefined &&
window.history.pushState !== null;
}
/**
* Makes info about a member available at the memberInfo map for e.g. rich cards.
*
* @param memberObject - an object containing information about a member
*/
function storeMember(memberObject) {
// Add a pretty name with '()' if the member is a method
memberObject.prettyName = memberObject.fullname + (memberObject.type === 'method' ? '()' : '');
// Add the member to the memberInfo map with the dot-notation name
memberInfo[memberObject.fullname] = memberObject;
}
/**
* Creates a script element for the Google Rich Card and returns it as a jQuery object.
*
* @returns {*|jQuery|HTMLElement} the Google Rich Card script as a jQuery object
*/
function addRichCardScript() {
var script = document.createElement("script");
script.id = "richCard";
script.type = "application/ld+json";
document.getElementsByTagName("head")[0].appendChild(script);
return $(script);
}
/**
* Returns the memberInfo of a specific member, or an empty object if it does not exist.
*
* @returns {object} the memberInfo of a specific member, or an empty object if it does not exist
*/
function getMemberInfo(member) {
return memberInfo[member] ? memberInfo[member] : {};
}
/**
* Modifies or creates the Google Rich Card with information from the member.
*
* If the card does not exist, it is created via addRichCardScript().
*
* @param member - the id of the member (dot-notation)
*/
function modifyRichCard(member) {
var cardScript = $('#richCard'),
json = {
"@context": "http://schema.org/",
"@type": "APIReference",
"name": member,
"image": "http://api.highcharts.com/resources/images/" + PRODUCTNAME + ".svg",
"description": getMemberInfo(member).description
};
if (cardScript.length < 1) {
cardScript = addRichCardScript();
}
cardScript.html(JSON.stringify(json, null, 4));
}
/**
* Simulates a click on a link to a member by loading it with JS through gotoSection().
* If an event is provided, its preventDefault() is called, and history is rewritten
* with window.history.pushState().
*
* @param member - the id of a member, e.g. "exporting.chartOptions"
* @param e - the click event
*/
function memberClick(member, e) {
var path = location.pathname,
url;
// Handle history only if there was an event.
// If not, this function was called by accessing
// the site or navigating the history.
if (e !== undefined) {
// Prevents the page to be loaded from the server
e.preventDefault();
// Remove trailing slash
path = path.replace(/\/$/, '');
if (page.length < 1) {
// Add member to url if there was no existing page
url = path + '/' + member;
} else {
// Remove old member from path and add new member if there was a page
url = path.substring(0, path.lastIndexOf('/')) + '/' + member;
}
// Update page variable to member
page = member.replace(/\//g, '');
if (historyEnabled()) {
window.history.pushState({'page': page}, member, url);
} else {
window.location.hash = member;
}
}
// Load content
gotoSection(member, true);
}
/**
* Checks if a string has a value.
* @param string - the string to check
* @returns {boolean} true if the string is neither undefined or empty
*/
function strHasValue(string) {
return string !== undefined && string.length > 0;
}
/**
* Returns a the same string with capitalized first letter
* E.g. "highcharts" returns "Highcharts"
*
* @param {string} string - the string to capitalize
*
* @returns {string} a string with capitalized first letter
*/
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
/**
* Get the path between domain name and member
* E.g. localhost:8080/highcharts-api/highcharts/data
* | base path |
*
* @returns {string} the path between domain name and member
*/
function getBasePath() {
var ctxt = CTXT.replace('/', ''),
prod = PRODUCTNAME + '/';
if (strHasValue(ctxt)) {
ctxt += '/';
}
return ctxt + prod;
}
/**
* Sets the first part of the document title to the member name, and returns it.
* E.g. "exporting.buttons.contextButton" sets
* "exporting.buttons.contextButton | Highcharts API Reference" as the document
* title.
*
* @param {string} memberName
* - name of the member, e.g.
* "exporting.buttons.contextButton"
*
* @returns {string} the page title
*/
function memberToDocumentTitle(memberName) {
var title;
title = getMemberInfo(memberName).prettyName + ' | ' + capitalizeFirstLetter(PRODUCTNAME) + ' API Reference';
document.title = title;
return title;
}
/**
* Sets the page content to the splash page
*/
function showSplashPage() {
var $splashPage = $('#splashText'),
$plus = $('.plus');
if($section){
$section.hide();
}
if ($plus.hasClass('expanded')) {
$plus.removeClass('expanded');
$plus.addClass('collapsed');
$plus.find('div[id$="-menu"]').slideUp();
}
$splashPage.show();
}
function loadOptionMemberInSection(obj, isParent){
//add member to section in div#details
var $_section = $('div#' + obj.parent.replace('<', '\\<').replace('>', '\\>') + '.section'),
$memberDiv,
contextClass = obj.description && obj.description.indexOf('<p>') > -1 ? '' : ' context';
$memberDiv = $('<div class="member" id="' + obj.name + '"><h2 class="title">' + obj.title + '</h2>'
+ (obj.returnType ? '<span class="returnType">: ' + markupReturnType(obj.returnType) + '</span>' : '')
+ (obj.deprecated ? '<div class="deprecated"><p>Deprecated</p></div>' : '' )
+ (obj.since ? '<div class="since">Since ' + obj.since + '</div>' : '' )
+ (obj.description ? '<div class="description">' + obj.description
+ (obj.defaults ? ' Defaults to <code>' + escapeHTML(obj.defaults) + '</code>.' : '')
+ '</div>' : '')
+ (obj.context ? '<div class="description' + contextClass + '">The <code>this</code> keyword refers to the '+ markupReturnType(obj.context) +' object.</div>' : '')
+ (obj.demo ? '<div class="demo"><h4>Try it:</h4> ' + obj.demo + '</div>': '' )
+ (obj.seeAlso ? '<div class="see-also"><h4>See also:</h4> ' + obj.seeAlso + '</div>': '' )
+ '</div>').appendTo($_section);
activateInternalLinks($memberDiv);
$('div#' + escapeSelector(obj.name) + '.member h2.title').html(function() {
var title = $.trim($(this).text());
return $('<a href="/' + getBasePath() + obj.fullname + '" ' + (isParent ? '' : 'class="noChildren"') + '>' + title + '</a>').click(function(e){
memberClick(obj.fullname, e);
});
});
}
function loadObjectMemberInSection(obj) {
$memberDiv = $('<div class="member" id="' + obj.name + '">'
+ '<h2 class="title">' + obj.title + '</h2> '
+ (obj.params ? '<span class="parameters">' + obj.params + '</span>' : '')
+ (obj.since ? '<div class="since">Since ' + obj.since + '</div>' : '' )
+ (obj.deprecated ? '<div class="deprecated"><p>Deprecated</p></div>' : '' )
+ '<div class="description"><p>' + obj.description + '</p>'
+ (obj.paramsDescription ? '<h4>Parameters</h4><ul id="paramdesc"><li>' +
obj.paramsDescription.replace(/\|\|/g,'</li><li>') + '</li></ul>' : '')
+ (obj.returnType ? '<h4>Returns</h4><ul id="returns"><li>' + markupReturnType(obj.returnType) + '</li></ul>' : '')
+ '</div>'
+ (obj.demo ? '<div class="demo"><h4>Try it:</h4> ' + obj.demo + '</div>': '' )
+ '</div>').appendTo('div#object-' + obj.parent + '.section');
$('div#' + escapeSelector(obj.name) + '.member h2.title').html(function() {
var title = $.trim($(this).text());
return $('<a href="/' + getBasePath() + obj.fullname + '" class="noChildren">' + title + '</a>').click(function(e){
memberClick(obj.fullname, e);
});
});
activateInternalLinks($memberDiv);
}
function loadChildren(name, silent, callback) {
var isObject = /[A-Z]/.test(name[0]),
url = CTXT + '/' + (isObject ?
'object/' + PRODUCTNAME + '-obj/child/' + name :
'option/' + PRODUCTNAME + '/child/' + name);
// If url has been used to load children before, do not load them again
if ($.inArray(url, usedUrls) !== -1) {
return;
}
// Add the url to the list of used urls
usedUrls.push(url);
$.ajax({
type: "GET",
url: url,
dataType: "json",
error: function () {
var $menu;
$menu = $('div#' + escapeSelector(name) + '-menu');
$('.dots', $menu.parent()).removeClass('loading').addClass('error').html('Error');
},
success: function (data) {
var display = 'block',
$menu, $menuItem;
if (silent) {
display = 'none';
}
name = name.replace('<', '\\<').replace('>', '\\>');
$menu = $('div#' + name + '-menu');
$.each(data, function (key, val) {
var $div = $('<div></div>').appendTo($menu), $plus, $menuLink,
name,
title,
defaults,
cls;
// Remove duplicate series<seriesType>.type-properties
if (/series<.+>--type/.test(val.name)) {
return true; // return true in $.each() is the same as continue loop
}
// Make info available for e.g. rich cards
storeMember(val);
/*if (val.type === 'method') {
name = val.name.replace('--', '.') + '()';
} else if (val.type === 'property') {
name = val.name.replace('--', '.');
} else {
name = val.fullname;
}*/
name = val.fullname;
if (val.isParent) {
var preBracket = '{',
postBracket = '}';
if (val.returnType && val.returnType.indexOf('Array') === 0) {
preBracket = '[{';
postBracket = '}]';
}
$menuItem = $('<div class="menuitem collapsed"></div>');
$menuLink = $('<a href="/' + getBasePath() + name + '">' + val.title + '</a>').appendTo($menuItem);
$menuLink.click(function (e) {
memberClick(val.fullname, e);
});
$plus = $('<a href="/' + getBasePath() + name + '" class="plus"></a>').appendTo($menuItem);
$plus.click(function (e) {
e.preventDefault();
if ($plus.parent().hasClass('collapsed')) {
$menuLink.click();
} else {
toggleExpand($plus.parent());
}
});
$menuItem.append(':&nbsp;' + preBracket + '<span class="dots"><span>…</span></span>');
// add empty submenu
$('<div id="' + val.name + '-menu" style="display:none"><div>').appendTo($menuItem);
$menuItem.append(postBracket);
$menuItem.appendTo($menu);
addSectionOption(val);
} else {
if (val.type === 'method') {
title = val.title + '()';
methods.push(val.fullname);
} else {
title = val.title;
}
$menuLink = $('<a href="/' + getBasePath() + name + '">' + title + '</a>').appendTo($div);
$menuLink.click(function (e) {
hideSidebar();
memberClick(name, e);
});
if (val.type === 'method') {
defaults = '[function]';
} else if (val.type === 'property') {
defaults = '[' + val.returnType + ']';
} else if (val.defaults === 'null' || val.defaults === 'undefined' || val.defaults === '' || val.defaults === undefined) {
defaults = val.defaults;
} else if (val.returnType === 'String' || val.returnType === 'Color') {
defaults = '"' + val.defaults + '"';
} else {
defaults = val.defaults;
}
if (val.returnType) {
cls = val.returnType.toLowerCase();
} else {
cls = '';
console.warn('Missing returnType for ' + val.fullname);
}
$('<span class="value value-' + cls + '">: ' + escapeHTML(defaults) + '</span>').appendTo($div);
}
if (isObject) {
loadObjectMemberInSection(val);
} else {
loadOptionMemberInSection(val, val.isParent);
}
});
$(document).triggerHandler({
type: "xtra.btn.member.event",
id: isObject ? 'object-' + name : name,
table: isObject ? 'object' : 'option'
});
if (callback) {
callback();
}
}
});
}
function gotoSection(anchor, hilighted) {
var name,
levels,
$_parentparent,
callbackStack = [];
// Handle typed parent item, like series<line>
name = anchor.split('.');
if (name.length > 1) {
name[name.length - 1] = '-' + name[name.length - 1];
}
name = name.join('-');
levels = name.split(/[-]{1,2}/);
// Asyncronously expand parent elements of selected item
$.each(levels, function(i) {
callbackStack.push(function () {
var proceed = true,
level,
$_menu,
$_parent;
if (levels[i]) {
level = levels.slice(0, i + 1).join('-');
if (level.indexOf('<') > -1) {
$_parentparent = $('#' + level.split('<')[0] + '-menu').parent();
level = escapeSelector(level);
}
$_menu = $('#' + level + '-menu');
$_parent = $_menu.parent();
if ($_menu && $_parent.hasClass('collapsed')) {
if ($_parentparent && $_parentparent.hasClass('collapsed')) {
toggleExpand($_parentparent);
}
// Do the toggle, and pass the next level as the callback argument
toggleExpand($_parent, callbackStack[i + 1]);
proceed = false;
}
}
if (level) {
// For the last path item, show the section etc
if (/[A-Z]/.test(level[0])) {
level = 'object-' + level;
}
if ($('#details > div.section#' + level).length) {
toggleSection(level);
// empty search
$("#search").val("");
}
}
if (proceed && callbackStack[i + 1]) {
callbackStack[i + 1]();
}
});
});
// Hilighting is the last operation in the async stack
if (hilighted) {
callbackStack.push(function () {
if (strHasValue(name)) {
// Highlight if there was a member
// E.g. product#some.member
hilight(name);
// Update the Google Rich Card
modifyRichCard(anchor);
// Set the page title
memberToDocumentTitle(anchor);
} else {
showSplashPage();
}
});
}
// Start the recursive iteration
callbackStack[0]();
}
/**
* Add the first level menu items on page load
*/
function addFirstLevelMenuItem(key, val, type) {
var $menuItem = $('<div class="menuitem collapsed"></div>').appendTo('#' + type + 's'),
$plus, $menuLink,
sectionId = val.fullname || val.name,
title = escapeHTML(val.title),
mainSection,
name = val.name,
recurseToType = false,
menuItemPrefix = '',
prefix = ': {',
suffix = '}';
// Make info available for e.g. rich cards
storeMember(val);
if (val.returnType && val.returnType.indexOf('Array') === 0) {
if (val.returnType === 'Array<Object>') {
prefix = ': [{';
suffix = '}]';
} else {
prefix = ': [';
suffix = ']';
}
}
// Global options
if ($.inArray(val.name, ['global', 'lang']) !== -1) {
$menuItem = $('<div class="menuitem collapsed"></div>').appendTo('#global-options');
}
// Handle the series<line> syntax
if (sectionId.indexOf('<') > -1) {
mainSection = sectionId.split('<')[0];
// The first time we encounter a menu item on the syntax series<line>, add the series menu item
if ($('#' + mainSection + '-menu').length === 0) {
sectionId = title = name = mainSection;
prefix = ': [';
suffix = ']';
recurseToType = true; // run this method again, but now for the { type: "line" } menu item
} else {
$menuItem.appendTo($('#' + mainSection + '-menu'));
menuItemPrefix = '{<br class="typed"/>';
title = '<span class="typed">type: "' + sectionId.split('<')[1].split('>')[0] + '"</span>';
prefix = ', ';
}
}
if (menuItemPrefix) {
$menuItem.append(menuItemPrefix);
}
$menuLink = $('<a href="/' + getBasePath() + sectionId + '">' + title + '</a>')
.appendTo($menuItem)
.click(function(e){
memberClick(sectionId, e);
return false;
});
if (val.isParent) {
$plus = $('<a href="/' + getBasePath() + sectionId + '" class="plus"></a>')
.appendTo($menuItem)
.click(function (e) {
e.preventDefault();
if ($plus.parent().hasClass('collapsed')) {
$menuLink.click();
} else {
toggleExpand($plus.parent());
}
});
}
$menuItem.append(prefix);
$('<span class="dots"><span>…</span></span>').appendTo($menuItem);
if(val.isParent) {
$('<div id="' + name + '-menu" style="display:none"><div>').appendTo($menuItem);
}
$menuItem.append(suffix);
// create sections in div#details
if (type === 'option') {
addSectionOption(val);
} else {
addSectionObject(val);
}
if (recurseToType) {
addFirstLevelMenuItem.apply(null, arguments);
}
}
prepareOffline = function(callback) {
offline = {highcharts: {}, highstock: {}, highmaps: {}};
// now we have the data loaded we rewrite $.ajax for offline use
$.ajax = function(obj) {
var result,
splitted;
if (obj.url === '/' + PRODUCTNAME + '/names') {
result = API[PRODUCTNAME].names;
}
if (obj.url === '/option/'+ PRODUCTNAME + '/main') {
result = API[PRODUCTNAME].main.option;
}
if (obj.url === '/object/'+ PRODUCTNAME + '-obj/main') {
result = API[PRODUCTNAME].main.object;
}
splitted = obj.url.split('object/' + PRODUCTNAME + '-obj/child/');
if (splitted.length > 1) {
result = API[PRODUCTNAME].object[splitted[1]].children;
}
splitted = obj.url.split('option/' + PRODUCTNAME + '/child/');
if (splitted.length > 1) {
result = API[PRODUCTNAME].option[splitted[1]].children;
}
// result to handler
obj.success(result);
};
callback();
};
// build dictionary for offline use
buildApiOffline = function(data, callback) {
var option,
names,
type,
i = 0;
API[PRODUCTNAME] = { option: [], object: [], main: {}, names: [] };
names = API[PRODUCTNAME].names;
function fillWithType(type) {
var idx,
slot = API[PRODUCTNAME][type],
main = API[PRODUCTNAME].main[type] = [],
name;
// Loop over options in dump file
for (idx = 0; idx < data[type].length; idx++) {
option = data[type][idx];
name = option.name;
names.push(name);
if (option.isParent) {
// Store main options separately
if (!/-/.test(name)) {
main.push(option);
}
if (slot[name] == undefined) {
slot[name] = {details: option, children: []};
} else {
/* In case the parent option was already
* deducted from a child option
*/
slot[name].details = option;
}
}
// we have a child!
if (slot.hasOwnProperty(option.parent)) {
slot[option.parent].children.push(option);
} else {
slot[option.parent] = {details: null, children: [option]};
}
}
}
while(i < 2) {
type = ['option', 'object'][i];
fillWithType(type);
i++
}
callback();
};
buildPage = function() {
// autocomplete
$.ajax({
type: "GET",
url: CTXT + '/' + PRODUCTNAME + '/names',
// Always load synchronously
async: false,
dataType: "json",
success: function (data) {
$.each(data, function (key, val) {
var dotted = toDot(val);
names.push(dotted);
optionDictionary[dotted] = val;
});
$("#search" ).autocomplete({
source: names,
autoFocus: true,
minLength: 2,
select: function( event, ui ) {
memberClick(ui.item.value, event);
},
position: {
my: 'left top',
of: '#search-wrap'
}
});
}
});
// load main options and build folded menu tree
$.ajax({
type: "GET",
url: CTXT + '/option/' + PRODUCTNAME + '/main',
// Always load synchronously
async: false,
dataType: "json",
success: function (data) {
$.each(data, function (key, val) {
addFirstLevelMenuItem(key, val, 'option');
});
}
});
// load objects of product
$.ajax({
type: "GET",
url: CTXT + '/object/' + PRODUCTNAME + '-obj/main',
// Always load synchronously
async: false,
dataType: "json",
success: function (data) {
$.each(data, function (key, val) {
addFirstLevelMenuItem(key, val, 'object');
});
}
});
// check url for anchor, remove also '()' from old links for object.method().
anchor = window.location.hash.replace('#', '').replace('()','');
if (strHasValue(anchor)) {
memberClick(anchor);
}
if (/\?object_not_found=true/.test(window.location.search)) {
dottedName = window.location.hash.split('#').pop();
internalName = optionDictionary[dottedName];
$('div#' + internalName).append('<div class="error">The object/option wasn\'t found in the database, maybe iẗ́\'s inherited??</div>');
}
// focus search
$("#search")[0].focus();
};
/**
* Checks if the sidebar is open based on the body class.
*
* @returns {boolean} true if the sidebar is open; false if not
*/
function sidebarIsOpen() {
return $('body').hasClass('sidr-open');
}
/**
* Hides the sidebar if it is open.
*/
function hideSidebar() {
if (sidebarIsOpen()) {
$('#sidebar-nav-link').click();
}
}
/**
* Initializes the sidebar functionality.
*/
function initializeSidebar() {
// Sidr sidebar activation
$('.sidebar-nav-link').sidr({
name: 'nav',
displace: false
});
// Make clicking the page wrapper and nav links also collapse the sidebar
$('#details-wrap').click(function () {
hideSidebar();
});
}
/**
* Adds simulation of history navigation by detecting changes to the history state.
*
* @return [undefined] - nothing
*/
function simulateHistory () {
if (historyEnabled()) { // Use the history API if available
/**
* Updates the history with memberClick().
*
* If it is stored in the history state, the page will be used to update.
* If not, the global PAGE variable will be used.
*
* @param e - the event that triggered the history update
*/
window.onpopstate = function (e) {
console.log('@updateHistory', PAGE, e);
if (e.state !== undefined && e.state !== null && e.state.page !== undefined) {
memberClick(e.state.page);
} else {
memberClick(PAGE);
}
}
} else { // Use the #-notation if history API is not available
window.onhashchange = function (e) {
memberClick(window.location.hash.replace(/#/, ''));
}
}
}
// Startup
$(function () {
var hash = location.hash,
href,
url;
// Fallback for old urls with # instead of /.
// Replaces # with /
if (strHasValue(hash)) {
page = hash.replace(/#/, '');
href = hash.replace(/#/, '/');
url = location.pathname + href;
if (historyEnabled()) {
window.history.replaceState({'page': page}, href, url);
} else {
PAGE = page;
}
}
// Initialize sidr sidebar
initializeSidebar();
if (runDB) {
buildPage();
} else {
// prepare dump object
prepareOffline(function () {
// load offline data
loadScript('./js/' + PRODUCTNAME + '.json', function() {
buildApiOffline(offline[PRODUCTNAME], buildPage);
});
});
// hide elements that don't make sence in offline mode
$('.hidden-offline').hide();
}
// convert hash from redirected dash syntax to new dot syntax
if (/-/.test(location.hash)) {
location.hash = location.hash.replace(/(--|-)/g, '.');
}
// Add scrollanimation to button
$("a[href='#top']").click(function() {
$("html, body").animate({ scrollTop: 0 }, "slow");
return false;
});
$(window).on('scroll', function() {
var button = $("#scrollTop");
if (!$("#top").isOnScreen()) {
if (button.css('display') == 'none') {
button.fadeIn("slow");
}
} else {
if (button.css('display') == 'block') {
button.fadeOut("slow");
}
}
});
$.fn.isOnScreen = function(){
var win = $(window),
viewport = {
top : win.scrollTop(),
left : win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
function updateHeight() {
var $wrapper = $("#wrapper"),
$wrapperContainer = $("#wrapper .container");
if (jQuery(window).width() >= 768) {
// Disable
var padding,
height = $(window).height() - $('#top').height() - $('#footer').height();
$wrapper.height(height);
padding = $wrapperContainer.innerHeight() - $wrapperContainer.height();
height = $wrapper.height() - padding;
$("#wrapper-inner").height(height);
$("#nav-wrap").height(height);
$("#details-wrap").height(height);
} else {
// no height defined on the element for mobile devices
$('#nav-wrap').removeAttr('style');
}
}
updateHeight();
$(window).resize(updateHeight);
// Make the Highcharts/Highstock links dynamic
$('#highstock-link, #highcharts-link').click(function () {
this.href += location.hash;
});
// Login shortcut (hot corner)
$("<div>")
.css({
position: 'absolute',
display: 'block',
width: '10px',
height: '10px',
right: 0,
cursor: 'pointer'
})
.click(function () {
var ctxt = strHasValue(CTXT) ? CTXT.replace(/\//g, '') + '/' : '';
$('<iframe src="/'+ ctxt + 'auth/login">').dialog({
height: 300
});
})
.prependTo('#top .container');
// Call the custom simulateHistory() function to allow history navigation
// with 'back' and 'forward'
simulateHistory();
if (strHasValue(page)) {
memberClick(page);
}
});