-function FluidbookHelp(fluidbook) {\r
- this.autoTimeout;\r
- this.fluidbook = fluidbook;\r
- this.view = $("#helpView");\r
- this.overlay = $("#helpViewOverlay");\r
- this.initEvents();\r
- this.interfaceTop;\r
-}\r
-\r
-FluidbookHelp.prototype = {\r
- init: function () {\r
- var $this = this;\r
- var help = '';\r
-\r
- // Image centrale\r
- var ext = '';\r
- if (this.fluidbook.support.SVG) {\r
- ext = 'svg';\r
- } else {\r
- ext = 'png';\r
- }\r
-\r
- var name = '';\r
- var width = 100;\r
- var height = 200;\r
- var text;\r
- var zoom = 1;\r
- if (this.fluidbook.support.isMobile) {\r
- width = 400;\r
- height = 200;\r
- zoom = 2;\r
- name = 'fingers';\r
- text = this.fluidbook.l10n.__("tap twice or spread your fingers to zoom in");\r
- } else {\r
- name = 'mouse';\r
- text = this.fluidbook.l10n.__('click once to zoom in, click again to zoom out') + '<br />' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out');\r
- }\r
-\r
- help += '<div class="illustration">' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom);\r
- help += '<p>' + text + '</p>';\r
- help += '</div>';\r
-\r
-\r
- // Icons\r
- help += '<div id="icons">';\r
-\r
- var tooltipSelector = '#horizontalNav li > a[data-tooltip]:visible';\r
-\r
- // When the menu position is inverted, the icon help lines need\r
- // to be drawn in the reverse order to avoid text/line overlaps\r
- var tooltips = this.fluidbook.datas.invertMenuPosition ? $(tooltipSelector).get().reverse() : $(tooltipSelector);\r
- var navScale = this.fluidbook.resize.navScale;\r
- var initialHeight = 20 * navScale; // Buffer in line height away from icons\r
- var hStep = 25 * navScale; // The step height - the difference in height between the icon label lines\r
- var h = initialHeight + ($(tooltipSelector).length - 1) * hStep;\r
- var ww = $(window).width();\r
-\r
- $(tooltips).each(function () {\r
- var text = $(this).data('tooltip');\r
- if (text == null || text == undefined || text == '' || $(this).hasClass('hidden')) {\r
- return;\r
- }\r
-\r
- var icon = $(this).find('.nav-icon:visible:first'); // Must get first visible icon so "toggle" icons work\r
- if (icon.length > 0) {\r
- var offset = icon.offset(),\r
- iconWidth = icon.outerWidth() * navScale,\r
- left;\r
-\r
- if ($this.fluidbook.l10n.dir == 'ltr') {\r
- left = offset.left + (iconWidth / 2);\r
- } else {\r
- left = (ww - offset.left - (iconWidth / 2)) * -1;\r
- }\r
-\r
- // Since the outer container has been scaled, we need to factor that in\r
- // for the left position so the lines still meet with the icons\r
- left = left / navScale;\r
-\r
- var c = 'nav';\r
- if ($(this).parents("#afterSearch").length > 0) {\r
- c = 'afterSearch';\r
- }\r
- help += '<div class="icon ' + c + '" style="padding-top:' + h + 'px;left:' + left + 'px;"><span>' + text + '</span></div>';\r
- h -= hStep;\r
- }\r
- });\r
-\r
- help += '</div>';\r
-\r
- // Interface\r
-\r
- var next = this.fluidbook.l10n.__('next double page');\r
- var previous = this.fluidbook.l10n.__('previous double page');\r
- if (this.fluidbook.pad.enabled) {\r
- next = this.fluidbook.l10n.__('next chapter');\r
- previous = this.fluidbook.l10n.__('previous chapter');\r
- }\r
-\r
- help += '<div class="interface">';\r
- help += '<div class="next">' + next + '</div>';\r
- help += '<div class="last">' + this.fluidbook.l10n.__('last page') + '</div>';\r
- help += '<div class="previous">' + previous + '</div>';\r
- help += '<div class="first">' + this.fluidbook.l10n.__('frontpage') + '</div>';\r
- help += '<div class="slider"><span>' + this.fluidbook.l10n.__('drag handle to switch page') + '</span></div>';\r
- help += this.bookmarkLabel();\r
- help += '</div>';\r
-\r
- if (this.fluidbook.pad.enabled) {\r
- help += '<div class="down">' + this.fluidbook.l10n.__('read more') + '<hr /></div>';\r
- }\r
-\r
- this.view.html(help);\r
- //resize();\r
- },\r
- initEvents: function () {\r
- var $this = this;\r
-\r
- $(document).on('click', '.icon-help', function (e) {\r
- $this.show();\r
- if (fluidbook.nav.menuIsOpen) {\r
- fluidbook.nav.menuAPI.close();\r
- }\r
- e.preventDefault();\r
- });\r
-\r
- // Click handler on main helpView div to hide it\r
- $this.overlay.click(function (e) {\r
- e.stopImmediatePropagation();\r
- e.stopPropagation();\r
- e.preventDefault();\r
-\r
- $this.hide();\r
- return false;\r
- });\r
- },\r
- isVisible: function () {\r
- return this.view.is(":visible");\r
- },\r
- show: function (time) {\r
- this.clearTimeout();\r
- if (time == undefined) {\r
- time = 0;\r
- }\r
-\r
- this.fluidbook.interface.displayInterface();\r
-\r
- if (this.isVisible()) {\r
- return false;\r
- }\r
-\r
- var $this = this;\r
-\r
- this.init(); // Re-run init because layout and options might have changed since last run\r
- resize();\r
- this.overlay.show();\r
- this.view.show();\r
-\r
- $("body,#previous,#next").addClass('help');\r
- this.fluidbook.showAllButtons();\r
-\r
- if (time != 0) {\r
- this.autoTimeout = setTimeout(function () {\r
- $this.hide();\r
- }, time * 1000);\r
- }\r
-\r
- return false;\r
- },\r
- hide: function () {\r
- this.clearTimeout();\r
- this.fluidbook.interface.checkHidden();\r
- var $this = this;\r
- if (this.isVisible()) {\r
- this.overlay.hide();\r
- this.view.hide();\r
- $("body,#previous,#next").removeClass('help');\r
- this.fluidbook.hideUnnecessaryButtons();\r
- if (this.fluidbook.support.isMobile) {\r
- $("*").unbind('click', function () {\r
- $this.hide();\r
- });\r
- }\r
- }\r
- return false;\r
- },\r
- toggle: function () {\r
- if (this.isVisible()) {\r
- this.hide();\r
- } else {\r
- this.show();\r
- }\r
- },\r
- resize: function (ww, hh, interfaceScale, navScale) {\r
-\r
- // Repopulate and reposition help overlay elements.\r
- // Mostly important for the RTL languages where icon label position must be recalculated/\r
- // ToDo: Replace this sledgehammer approach with something more elegant\r
- this.init();\r
-\r
- // ToDo: access variables from fluidbook.resize.* if they're not passed to the function. So resize function can be called directly...\r
-\r
- var $this = this,\r
- dir = this.fluidbook.l10n.dir,\r
- menuHeightScaled = (this.fluidbook.datas.menuHeight) * navScale,\r
- arrow = $('#interface #next').get(0).getBoundingClientRect(), // Used for calculating offsets for both #next & #previous\r
- nextTop,\r
- firstTop;\r
-\r
- // The arrow element contains both arrows in a single image\r
- // so we calculate the top position of the labels by percentage\r
- nextTop = Math.round(arrow.top + arrow.height * 0.35);\r
- firstTop = Math.round(arrow.top + arrow.height * 0.71);\r
-\r
- // Navigation arrow labels\r
- this.view.find('.previous, .next').css({\r
- top: nextTop\r
- });\r
- this.view.find('.first, .last').css({\r
- top: firstTop\r
- });\r
-\r
- // Labels are swapped for RTL documents\r
- var prevPosition = (dir == 'ltr') ? {left: Math.round(arrow.width)} : {right: Math.round(arrow.width)},\r
- nextPosition = (dir == 'ltr') ? {right: Math.round(arrow.width)} : {left: Math.round(arrow.width)};\r
-\r
- this.view.find('.previous, .first').css(prevPosition);\r
- this.view.find('.next, .last').css(nextPosition);\r
-\r
-\r
- // Slider label\r
- var positionSliderLabel = function () {\r
- var sliderHelp = $this.view.find('.slider');\r
- var sliderCursor = $('#slidercursor .visible');\r
- sliderHelp.css({\r
- bottom: Math.round(hh - sliderCursor.offset().top),\r
- left: Math.round(sliderCursor.offset().left + (sliderCursor.width() / 2)),\r
- transformOrigin: 'left bottom'\r
- });\r
- };\r
- positionSliderLabel(); // Run immediately\r
- setTimeout(positionSliderLabel, 250); // delay slightly to make sure co-ordinates are correct\r
-\r
- this.view.find('#icons').css({\r
- top: menuHeightScaled,\r
- transform: 'scale(' + navScale + ')'\r
- });\r
-\r
- $("#helpView #icons").css({\r
- fontSize: (14 / navScale) * interfaceScale\r
- });\r
-\r
- this.view.find('.illustration').css({\r
- transform: 'translate(-50%, -50%) scale(' + interfaceScale + ')'\r
- });\r
-\r
- $("#helpView .interface").find('> div').transform({\r
- scale: [interfaceScale, interfaceScale]\r
- })\r
-\r
- },\r
- clearTimeout: function () {\r
- clearTimeout(this.autoTimeout);\r
- },\r
- displayAtStartup: function () {\r
- if (this.fluidbook.datas.helpStartup) {\r
- this.show(parseInt(this.fluidbook.datas.helpStartupTime));\r
- if (this.fluidbook.pad.enabled) {\r
- this.fluidbook.pad.displayInterface();\r
- }\r
- } else {\r
- this.fluidbook.hideUnnecessaryButtons();\r
- }\r
- },\r
-\r
- bookmarkLabel: function () {\r
-\r
- // The bookmark help element is a bit complex because it must be placed in a section of the help overlay that is\r
- // not already used by the icon labels. Since the menu can be either on the left or right, this needs to be taken\r
- // into account. On the first and last pages of the Fluidbook we don't have a left or right page so it might not\r
- // be possible to always display the bookmark icon in this case...\r
-\r
- var dir = this.fluidbook.l10n.dir,\r
- inverted = this.fluidbook.datas.invertMenuPosition,\r
- side = ((dir == 'ltr' && inverted) || (dir == 'rtl' && !inverted)) ? 'left' : 'right',\r
- baseElement = $('#links .bookmark.' + side), // Original element used to provide position and sizing for overlay\r
- html = '';\r
-\r
- // If bookmark icon isn't present on the side we want, it means that we're on\r
- // the first/last page and that side is missing so we can't display the help\r
- if (baseElement.length == 0) {\r
- return '';\r
- }\r
-\r
- // Get the offset and dimensions of the element, taking into account the scaling\r
- var box = baseElement[0].getBoundingClientRect(),\r
- circleExtra = 20 * this.fluidbook.resize.interfaceScale, // How much bigger the circle should be around the bookmark icon\r
- lineLength = 30; // Length of the line to the label text\r
-\r
- // The bookmark icon sits inside a circle that is slightly bigger so in order to make the icon sit exactly\r
- // on the corner of the page, we must offset the difference added by the larger wrapping circle.\r
- var circleOffset = circleExtra / 2;\r
-\r
- // Build a HTML string via jQuery with all the styling\r
- // Bookmark icon:\r
- var icon = $('<div/>').css({\r
- width: Math.round(box.width),\r
- height: Math.round(box.height),\r
- margin: Math.round(circleOffset), // Centre inside circle\r
- backgroundSize: 'contain',\r
- backgroundPosition: 'center',\r
- backgroundRepeat: 'no-repeat',\r
- backgroundImage: baseElement.css('backgroundImage').replace('off.svg', 'on.svg') // Show the "on" state if not already set\r
- })[0].outerHTML;\r
-\r
- // Circle around the icon - slightly bigger\r
- html += $('<div>' + icon + '</div>').css({\r
- width: Math.round(box.width + circleExtra),\r
- height: Math.round(box.height + circleExtra),\r
- borderRadius: '50%',\r
- border: '1px solid'\r
- })[0].outerHTML;\r
-\r
- // Line to text\r
- html += $('<div/>').css({\r
- width: lineLength,\r
- height: 0,\r
- borderBottom: '1px solid',\r
- })[0].outerHTML;\r
-\r
- // Help text label\r
- html += $('<div>' + this.fluidbook.l10n.__('add / remove bookmark') + '</div>').css({\r
- whiteSpace: 'nowrap',\r
- padding: '0 0.5em' // Ensure spacing around text regardless which side the line is on\r
- })[0].outerHTML;\r
-\r
-\r
- // Wrapper with positioning and layout switched depending on the side\r
- var wrapperCSS = { // Shared properties\r
- display: 'flex',\r
- alignItems: 'center',\r
- position: 'absolute',\r
- top: Math.round(box.top - circleOffset)\r
- },\r
- wrapperLayout;\r
-\r
- if (side == 'left') {\r
- wrapperLayout = {\r
- left: Math.round(box.left - circleOffset),\r
- transformOrigin: 'left top',\r
- flexDirection: 'row' // Flexbox direction controls order of elements (icon, line, label)\r
- };\r
- } else {\r
- wrapperLayout = {\r
- right: Math.round(this.fluidbook.resize.ww - box.left - box.width - circleOffset),\r
- transformOrigin: 'right top',\r
- flexDirection: 'row-reverse' // Reverse order of elements for right hand page\r
- }\r
- }\r
-\r
- var wrapper = $('<div class="bookmark-help">' + html + '</div>')\r
- .css(\r
- $.extend(wrapperCSS, wrapperLayout) // Merge all properties\r
- )[0].outerHTML\r
-\r
- return wrapper;\r
- }\r
-};\r
-\r
+function FluidbookHelp(fluidbook) {
+ this.autoTimeout;
+ this.fluidbook = fluidbook;
+ this.view = $("#helpView");
+ this.overlay = $("#helpViewOverlay");
+ this.initEvents();
+ this.interfaceTop;
+}
+
+FluidbookHelp.prototype = {
+ init: function () {
+ var $this = this;
+ var help = '';
+
+ // Image centrale
+ var ext = '';
+ if (this.fluidbook.support.SVG) {
+ ext = 'svg';
+ } else {
+ ext = 'png';
+ }
+
+ var name = '';
+ var width = 100;
+ var height = 200;
+ var text;
+ var zoom = 1;
+ if (this.fluidbook.support.isMobile) {
+ width = 400;
+ height = 200;
+ zoom = 2;
+ name = 'fingers';
+ text = this.fluidbook.l10n.__("tap twice or spread your fingers to zoom in");
+ } else {
+ name = 'mouse';
+ text = this.fluidbook.l10n.__('click once to zoom in, click again to zoom out') + '<br />' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out');
+ }
+
+ help += '<div class="illustration">' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom);
+ help += '<p>' + text + '</p>';
+ help += '</div>';
+
+
+ // Icons
+ help += '<div id="icons">';
+
+ var tooltipSelector = '#horizontalNav li > a[data-tooltip]:visible';
+
+ // When the menu position is inverted, the icon help lines need
+ // to be drawn in the reverse order to avoid text/line overlaps
+ var tooltips = this.fluidbook.datas.invertMenuPosition ? $(tooltipSelector).get().reverse() : $(tooltipSelector);
+ var navScale = this.fluidbook.resize.navScale;
+ var initialHeight = 20 * navScale; // Buffer in line height away from icons
+ var hStep = 25 * navScale; // The step height - the difference in height between the icon label lines
+ var h = initialHeight + ($(tooltipSelector).length - 1) * hStep;
+ var ww = $(window).width();
+
+ $(tooltips).each(function () {
+ var text = $(this).data('tooltip');
+ if (text == null || text == undefined || text == '' || $(this).hasClass('hidden')) {
+ return;
+ }
+
+ var icon = $(this).find('.nav-icon:visible:first'); // Must get first visible icon so "toggle" icons work
+ if (icon.length > 0) {
+ var offset = icon.offset();
+ var iconWidth = parseFloat($(icon).width()) * navScale;
+ var left;
+
+ if ($this.fluidbook.l10n.dir === 'ltr') {
+ left = offset.left + (iconWidth / 2);
+ } else {
+ left = (ww - offset.left - (iconWidth / 2)) * -1;
+ }
+
+ // Since the outer container has been scaled, we need to factor that in
+ // for the left position so the lines still meet with the icons
+ left = left / navScale;
+
+ var c = 'nav';
+ if ($(this).parents("#afterSearch").length > 0) {
+ c = 'afterSearch';
+ }
+ help += '<div class="icon ' + c + '" style="padding-top:' + h + 'px;left:' + left + 'px;"><span>' + text + '</span></div>';
+ h -= hStep;
+ }
+ });
+
+ help += '</div>';
+
+ // Interface
+
+ var next = this.fluidbook.l10n.__('next double page');
+ var previous = this.fluidbook.l10n.__('previous double page');
+ if (this.fluidbook.pad.enabled) {
+ next = this.fluidbook.l10n.__('next chapter');
+ previous = this.fluidbook.l10n.__('previous chapter');
+ }
+
+ help += '<div class="interface">';
+ help += '<div class="next">' + next + '</div>';
+ help += '<div class="last">' + this.fluidbook.l10n.__('last page') + '</div>';
+ help += '<div class="previous">' + previous + '</div>';
+ help += '<div class="first">' + this.fluidbook.l10n.__('frontpage') + '</div>';
+ help += '<div class="slider"><span>' + this.fluidbook.l10n.__('drag handle to switch page') + '</span></div>';
+ help += this.bookmarkLabel();
+ help += '</div>';
+
+ if (this.fluidbook.pad.enabled) {
+ help += '<div class="down">' + this.fluidbook.l10n.__('read more') + '<hr /></div>';
+ }
+
+ this.view.html(help);
+ //resize();
+ },
+ initEvents: function () {
+ var $this = this;
+
+ $(document).on('click', '.icon-help', function (e) {
+ $this.show();
+ if (fluidbook.nav.menuIsOpen) {
+ fluidbook.nav.menuAPI.close();
+ }
+ e.preventDefault();
+ });
+
+ // Click handler on main helpView div to hide it
+ $this.overlay.click(function (e) {
+ e.stopImmediatePropagation();
+ e.stopPropagation();
+ e.preventDefault();
+
+ $this.hide();
+ return false;
+ });
+ },
+ isVisible: function () {
+ return this.view.is(":visible");
+ },
+ show: function (time) {
+ this.clearTimeout();
+ if (time == undefined) {
+ time = 0;
+ }
+
+ this.fluidbook.interface.displayInterface();
+
+ if (this.isVisible()) {
+ return false;
+ }
+
+ var $this = this;
+
+ this.init(); // Re-run init because layout and options might have changed since last run
+ resize();
+ this.overlay.show();
+ this.view.show();
+
+ $("body,#previous,#next").addClass('help');
+ this.fluidbook.showAllButtons();
+
+ if (time != 0) {
+ this.autoTimeout = setTimeout(function () {
+ $this.hide();
+ }, time * 1000);
+ }
+
+ return false;
+ },
+ hide: function () {
+ this.clearTimeout();
+ this.fluidbook.interface.checkHidden();
+ var $this = this;
+ if (this.isVisible()) {
+ this.overlay.hide();
+ this.view.hide();
+ $("body,#previous,#next").removeClass('help');
+ this.fluidbook.hideUnnecessaryButtons();
+ if (this.fluidbook.support.isMobile) {
+ $("*").unbind('click', function () {
+ $this.hide();
+ });
+ }
+ }
+ return false;
+ },
+ toggle: function () {
+ if (this.isVisible()) {
+ this.hide();
+ } else {
+ this.show();
+ }
+ },
+ resize: function (ww, hh, interfaceScale, navScale) {
+
+ // Repopulate and reposition help overlay elements.
+ // Mostly important for the RTL languages where icon label position must be recalculated/
+ // ToDo: Replace this sledgehammer approach with something more elegant
+ this.init();
+
+ // ToDo: access variables from fluidbook.resize.* if they're not passed to the function. So resize function can be called directly...
+
+ var $this = this,
+ dir = this.fluidbook.l10n.dir,
+ menuHeightScaled = (this.fluidbook.datas.menuHeight) * navScale,
+ arrow = $('#interface #next').get(0).getBoundingClientRect(), // Used for calculating offsets for both #next & #previous
+ nextTop,
+ firstTop;
+
+ // The arrow element contains both arrows in a single image
+ // so we calculate the top position of the labels by percentage
+ nextTop = Math.round(arrow.top + arrow.height * 0.35);
+ firstTop = Math.round(arrow.top + arrow.height * 0.71);
+
+ // Navigation arrow labels
+ this.view.find('.previous, .next').css({
+ top: nextTop
+ });
+ this.view.find('.first, .last').css({
+ top: firstTop
+ });
+
+ // Labels are swapped for RTL documents
+ var prevPosition = (dir == 'ltr') ? {left: Math.round(arrow.width)} : {right: Math.round(arrow.width)},
+ nextPosition = (dir == 'ltr') ? {right: Math.round(arrow.width)} : {left: Math.round(arrow.width)};
+
+ this.view.find('.previous, .first').css(prevPosition);
+ this.view.find('.next, .last').css(nextPosition);
+
+
+ // Slider label
+ var positionSliderLabel = function () {
+ var sliderHelp = $this.view.find('.slider');
+ var sliderCursor = $('#slidercursor .visible');
+ sliderHelp.css({
+ bottom: Math.round(hh - sliderCursor.offset().top),
+ left: Math.round(sliderCursor.offset().left + (sliderCursor.width() / 2)),
+ transformOrigin: 'left bottom'
+ });
+ };
+ positionSliderLabel(); // Run immediately
+ setTimeout(positionSliderLabel, 250); // delay slightly to make sure co-ordinates are correct
+
+ this.view.find('#icons').css({
+ top: menuHeightScaled,
+ transform: 'scale(' + navScale + ')'
+ });
+
+ $("#helpView #icons").css({
+ fontSize: (14 / navScale) * interfaceScale
+ });
+
+ this.view.find('.illustration').css({
+ transform: 'translate(-50%, -50%) scale(' + interfaceScale + ')'
+ });
+
+ $("#helpView .interface").find('> div').transform({
+ scale: [interfaceScale, interfaceScale]
+ })
+
+ },
+ clearTimeout: function () {
+ clearTimeout(this.autoTimeout);
+ },
+ displayAtStartup: function () {
+ if (this.fluidbook.datas.helpStartup) {
+ this.show(parseInt(this.fluidbook.datas.helpStartupTime));
+ if (this.fluidbook.pad.enabled) {
+ this.fluidbook.pad.displayInterface();
+ }
+ } else {
+ this.fluidbook.hideUnnecessaryButtons();
+ }
+ },
+
+ bookmarkLabel: function () {
+
+ // The bookmark help element is a bit complex because it must be placed in a section of the help overlay that is
+ // not already used by the icon labels. Since the menu can be either on the left or right, this needs to be taken
+ // into account. On the first and last pages of the Fluidbook we don't have a left or right page so it might not
+ // be possible to always display the bookmark icon in this case...
+
+ var dir = this.fluidbook.l10n.dir,
+ inverted = this.fluidbook.datas.invertMenuPosition,
+ side = ((dir == 'ltr' && inverted) || (dir == 'rtl' && !inverted)) ? 'left' : 'right',
+ baseElement = $('#links .bookmark.' + side), // Original element used to provide position and sizing for overlay
+ html = '';
+
+ // If bookmark icon isn't present on the side we want, it means that we're on
+ // the first/last page and that side is missing so we can't display the help
+ if (baseElement.length == 0) {
+ return '';
+ }
+
+ // Get the offset and dimensions of the element, taking into account the scaling
+ var box = baseElement[0].getBoundingClientRect(),
+ circleExtra = 20 * this.fluidbook.resize.interfaceScale, // How much bigger the circle should be around the bookmark icon
+ lineLength = 30; // Length of the line to the label text
+
+ // The bookmark icon sits inside a circle that is slightly bigger so in order to make the icon sit exactly
+ // on the corner of the page, we must offset the difference added by the larger wrapping circle.
+ var circleOffset = circleExtra / 2;
+
+ // Build a HTML string via jQuery with all the styling
+ // Bookmark icon:
+ var icon = $('<div/>').css({
+ width: Math.round(box.width),
+ height: Math.round(box.height),
+ margin: Math.round(circleOffset), // Centre inside circle
+ backgroundSize: 'contain',
+ backgroundPosition: 'center',
+ backgroundRepeat: 'no-repeat',
+ backgroundImage: baseElement.css('backgroundImage').replace('off.svg', 'on.svg') // Show the "on" state if not already set
+ })[0].outerHTML;
+
+ // Circle around the icon - slightly bigger
+ html += $('<div>' + icon + '</div>').css({
+ width: Math.round(box.width + circleExtra),
+ height: Math.round(box.height + circleExtra),
+ borderRadius: '50%',
+ border: '1px solid'
+ })[0].outerHTML;
+
+ // Line to text
+ html += $('<div/>').css({
+ width: lineLength,
+ height: 0,
+ borderBottom: '1px solid',
+ })[0].outerHTML;
+
+ // Help text label
+ html += $('<div>' + this.fluidbook.l10n.__('add / remove bookmark') + '</div>').css({
+ whiteSpace: 'nowrap',
+ padding: '0 0.5em' // Ensure spacing around text regardless which side the line is on
+ })[0].outerHTML;
+
+
+ // Wrapper with positioning and layout switched depending on the side
+ var wrapperCSS = { // Shared properties
+ display: 'flex',
+ alignItems: 'center',
+ position: 'absolute',
+ top: Math.round(box.top - circleOffset)
+ },
+ wrapperLayout;
+
+ if (side == 'left') {
+ wrapperLayout = {
+ left: Math.round(box.left - circleOffset),
+ transformOrigin: 'left top',
+ flexDirection: 'row' // Flexbox direction controls order of elements (icon, line, label)
+ };
+ } else {
+ wrapperLayout = {
+ right: Math.round(this.fluidbook.resize.ww - box.left - box.width - circleOffset),
+ transformOrigin: 'right top',
+ flexDirection: 'row-reverse' // Reverse order of elements for right hand page
+ }
+ }
+
+ var wrapper = $('<div class="bookmark-help">' + html + '</div>')
+ .css(
+ $.extend(wrapperCSS, wrapperLayout) // Merge all properties
+ )[0].outerHTML
+
+ return wrapper;
+ }
+};
+