Skip to content

Instantly share code, notes, and snippets.

@efann
Last active November 7, 2022 21:01
Show Gist options
  • Select an option

  • Save efann/9898823 to your computer and use it in GitHub Desktop.

Select an option

Save efann/9898823 to your computer and use it in GitHub Desktop.
Basic JavaScript Routines for Drupal
// License: Eclipse Public License - v 2.0 (https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html)
// Updated on November 7, 2022
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
var Beo =
{
foDialogImage: null,
foDialogImageImg: null,
fnDialogImageTitleBarHeight: 0,
fcImageDialogFadeEffect: 'explode',
//----------------------------------------------------------------------------------------------------
initializeBrowserFixes: function ()
{
// Simple, brilliant solution from
// https://amp.reddit.com/r/drupal/comments/3qq70k/d7_cannot_read_property_msie_of_undefined_error
// Fix Drupal admin bar JavaScript errors that look for this deprecated feature.
// And because jQuery and not $ is used, jQuery Migrate can't fix the issue.
jQuery.browser = {version: 0};
let laBrowsers = ['webkit', 'safari', 'opera', 'msie', 'mozilla'];
for (let i = 0; i < laBrowsers.length; i++)
{
jQuery.browser[laBrowsers[i]] = false;
}
try
{
// From https://stackoverflow.com/questions/17367736/jquery-ui-dialog-missing-close-icon
let loBootstrapButton = jQuery.fn.button.noConflict(); // return $.fn.button to previously assigned value
jQuery.fn.bootstrapBtn = loBootstrapButton; // give $().bootstrapBtn the Bootstrap functionality
}
catch (loErr)
{
}
// For browser console
window.onerror = function (message, url, line)
{
console.log('window.onerror was invoked with message = ' + message + ', url ' + url + ', line = ' + line);
};
},
//----------------------------------------------------------------------------------------------------
getCurrentYear: function ()
{
let loNow = new Date();
let lnYear = loNow.getYear();
return ((lnYear < 1000) ? lnYear + 1900 : lnYear);
},
//----------------------------------------------------------------------------------------------------
writeCurrentYear: function ()
{
document.write(this.getCurrentYear());
}
,
//----------------------------------------------------------------------------------------------------
// http://stackoverflow.com/questions/148901/is-there-a-better-way-to-do-optional-function-parameters-in-javascript
writeCurrentDate: function (tlLongVersion)
{
let llLongVersion = (typeof tlLongVersion === 'undefined') ? true : tlLongVersion;
let laMonths = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
let laDays = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
let lnYear = this.getCurrentYear();
let loNow = new Date();
let lcDay = laDays[loNow.getDay()];
let lcMonth = laMonths[loNow.getMonth()];
if (!llLongVersion)
{
lcDay = lcDay.substring(0, 3);
lcMonth = lcMonth.substring(0, 3);
}
document.write(lcDay + ', ' + lcMonth + ' ' + loNow.getDate() + ', ' + lnYear);
},
//----------------------------------------------------------------------------------------------------
// Set the cursor for buttons, radio, checkboxes and combo boxes.
standardizeControls: function ()
{
jQuery('input:submit, input:button, button, td.views-field.views-field-edit-node a, td.views-field.views-field-delete-node a, a.make-button-from-link, div.date-prev a, div.date-next a, li.calendar-year a, li.calendar-month a, li.calendar-day a').each(function (tnIndex)
{
// If already has been stamped with ui-button, like with the Close Icon for jQuery.dialog.
if (jQuery(this).hasClass('ui-button'))
{
// Equivalent of continue. Return false is the equivalent of break;
return (true);
}
// Used by Bootstrap
if (jQuery(this).hasClass('btn-primary'))
{
// Equivalent of continue. Return false is the equivalent of break;
return (true);
}
// If already has an element with an icon. . . .
if (jQuery(this).find('[class^=\'icon\']').length > 0)
{
// Equivalent of continue. Return false is the equivalent of break;
return (true);
}
jQuery(this).button();
});
jQuery('select').each(function (tnIndex)
{
jQuery(this).css('cursor', 'pointer');
});
jQuery('input:checkbox, input:radio').each(function (tnIndex)
{
jQuery(this).css('cursor', 'pointer');
// Get the label which is in the parent due to the Zen theme.
jQuery(this).parent().css('cursor', 'pointer');
});
},
// -------------------------------------------------------------------------------------------------------------------
// From http://www.mkyong.com/jquery/jquery-watermark-effect-on-text-input/
setupWatermark: function (tcID, tcWatermark)
{
let loInput = jQuery(tcID);
if (loInput.length == 0)
{
return;
}
// initialization: set watermark text and class if empty.
if (loInput.val().trim().length == 0)
{
loInput.val(tcWatermark).addClass('watermark');
}
//if blur and no value inside, set watermark text and class again.
loInput.blur(function ()
{
if (jQuery(this).val().trim().length == 0)
{
jQuery(this).val(tcWatermark).addClass('watermark');
}
});
// if focus and text is watermark, set it to empty and remove the watermark class
loInput.focus(function ()
{
if (jQuery(this).val() == tcWatermark)
{
jQuery(this).val('').removeClass('watermark');
}
});
let loForm = loInput.closest('form');
loForm.submit(function ()
{
if (loInput.val() == tcWatermark)
{
loInput.val('').removeClass('watermark');
}
});
},
//----------------------------------------------------------------------------------------------------
// When an image is clicked, using jQuery dialog, the picture is displayed like
// that of FancyBox.
//
// Unfortunately, at the moment, I don't have a way to determine the title bar height
// before it displays. So I use Chrome Inspect when viewing a dialog box to determine
// the height.
// From https://stackoverflow.com/questions/8998612/how-to-pass-the-value-undefined-to-a-function-with-multiple-parameters
// By the way, to pass undefined as a parameter, use void 0
setupImageDialogBox: function (tnTitleBarHeight, tcFadeEffect, tlCheckClass, tcMainContent, tcDefaultImageClass)
{
// By the way, can't use Boolean here. For example, what if tlCheckClass is
// defined and is false. tlCheckClass would always be reset to true.
tlCheckClass = (typeof tlCheckClass !== 'undefined') ? tlCheckClass : true;
tcMainContent = Boolean(tcMainContent) ? tcMainContent : 'div.main-container';
tcDefaultImageClass = Boolean(tcDefaultImageClass) ? tcDefaultImageClass : 'responsive-image-regular';
Beo.fnDialogImageTitleBarHeight = tnTitleBarHeight;
Beo.fcImageDialogFadeEffect = tcFadeEffect;
Beo.createImageDialog();
// Unfortunately, I can't get the title in the template of field.html.twig.
// to override the image output.
let lcPageTitle = jQuery(document).attr('title').split('|')[0].trim();
jQuery(tcMainContent + ' img').each(function ()
{
let loImage = jQuery(this);
if (!Boolean(loImage.attr('alt')))
{
loImage.attr('alt', lcPageTitle);
}
if (!Boolean(loImage.attr('title')))
{
loImage.attr('title', lcPageTitle);
}
loImage.removeAttr('width');
loImage.removeAttr('height');
loImage.removeAttr('style');
if (tlCheckClass)
{
let lcClasses = loImage.attr('class');
if ((!Boolean(lcClasses)) || (lcClasses.indexOf('responsive-image') < 0))
{
loImage.addClass(tcDefaultImageClass);
}
}
if (!loImage.parent().is('a'))
{
let lcSource = loImage.attr('src');
loImage.wrap('<a class="dialogbox-image" href="' + lcSource + '"></a>');
}
});
jQuery('a.dialogbox-image').click(function (toEvent)
{
toEvent.preventDefault();
Beo.onDialogImageClick(jQuery(this));
});
},
// -------------------------------------------------------------------------------------------------------------------
onDialogImageClick: function (toImageLink)
{
let loDialog = Beo.foDialogImage;
let loDialogImg = Beo.foDialogImageImg;
let loImage = toImageLink.find('img');
let lcSource = loImage.attr('src');
let lcAlt = loImage.attr('alt');
if (!Boolean(lcAlt))
{
lcAlt = 'Image';
}
let lcTitle = loImage.attr('title');
if (!Boolean(lcTitle))
{
lcTitle = lcAlt;
}
loDialogImg.attr('src', lcSource);
loDialogImg.attr('alt', lcAlt);
loDialogImg.attr('title', lcTitle);
let loContainer = loDialogImg.parent();
let lnPaddingWidth = parseFloat(loContainer.css('padding-left')) + parseFloat(loContainer.css('padding-right')) + parseFloat(loContainer.css('margin-left')) + parseFloat(loContainer.css('margin-right'));
let lnPaddingHeight = parseFloat(loContainer.css('padding-top')) + parseFloat(loContainer.css('padding-bottom')) + parseFloat(loContainer.css('margin-top')) + parseFloat(loContainer.css('margin-bottom'));
lnPaddingWidth += parseFloat(loDialog.css('border-top-left-radius')) + parseFloat(loDialog.css('border-top-right-radius'));
lnPaddingHeight += parseFloat(loDialog.css('border-bottom-left-radius')) + parseFloat(loDialog.css('border-top-left-radius'));
// For title bar
lnPaddingHeight += Beo.fnDialogImageTitleBarHeight;
// So that on a mobile or any small screen, the dialog box won't fill the absolute
// entire screen. Leaves a small border.
lnPaddingWidth += 10;
lnPaddingHeight += 20;
// This technique is used to get the actual image size.
let loLoadImage = new Image();
loLoadImage.onload = function ()
{
let lnWidth = this.width * 1.0;
let lnHeight = this.height * 1.0;
// Subtract estimated borders and such.
let lnWidthRatio = (jQuery(window).width() - lnPaddingWidth) / lnWidth;
let lnHeightRatio = (jQuery(window).height() - lnPaddingHeight) / lnHeight;
let lnMinRatio = Math.min(lnHeightRatio, lnWidthRatio);
if (lnMinRatio < 1.0)
{
lnHeight *= lnMinRatio;
lnWidth *= lnMinRatio;
}
loDialogImg.css('width', lnWidth + 'px');
loDialogImg.css('height', lnHeight + 'px');
loDialog.dialog('option', 'title', lcTitle);
loDialog.dialog('open');
};
// Now load the image so the above loLoadImage.onload fires.
loLoadImage.src = lcSource;
},
// -------------------------------------------------------------------------------------------------------------------
createImageDialog: function ()
{
let lcDialog = 'BeoDialogForImage';
let lcDialogImg = 'BeoDialogForImageImg';
jQuery('body').append('<div id="' + lcDialog + '" style="display: none;"><img id="' + lcDialogImg + '" alt="" /></div>');
Beo.foDialogImage = jQuery('#' + lcDialog);
Beo.foDialogImageImg = jQuery('#' + lcDialogImg);
// Unfortunately, I tried querying css('width'): it returns a width in
// pixels. So the below is the actual default: I verified in the
// jquery.ui.css file.
let lcDefaultTitleCSS = '90%';
// Shadowbox advice from http://stackoverflow.com/questions/3448813/jqueryui-how-to-make-a-shadow-around-a-dialog-box
Beo.foDialogImage.dialog({
width: 'auto',
height: 'auto',
modal: true,
autoOpen: false,
draggable: false,
resizable: false,
show: {
effect: 'fade',
duration: 300
},
hide: {
effect: Beo.fcImageDialogFadeEffect,
duration: 400
},
open: function (toEvent, toUI)
{
// This step is needed: if the title is wider than the image
// then there will be empty space to the right of the image.
let loTitleSpan = jQuery(this).parent().find('span.ui-dialog-title');
let lnTitleWidth = loTitleSpan.width();
let lnWidth = parseFloat(jQuery(this).parent().find('img').css('width'));
if ((lnTitleWidth + 50) > lnWidth)
{
let lnNewWidth = lnWidth - 50;
// 120 is really small. . . .
if (lnNewWidth < 120)
{
lnNewWidth = 120;
}
loTitleSpan.css('width', lnNewWidth + 'px');
}
},
beforeClose: function (toEvent, toUI)
{
// Reset to the default so subsequent dialog opens with
// larger images aren't effected.
let loTitleSpan = jQuery(this).parent().find('span.ui-dialog-title');
loTitleSpan.css('width', lcDefaultTitleCSS);
}
});
},
// -------------------------------------------------------------------------------------------------------------------
// Now using Lightbox to display images.
setupLightbox: function (tlCheckClass, tcMainContent, tcDefaultImageClass)
{
// By the way, can't use Boolean here. For example, what if tlCheckClass is
// defined and is false. llCheckClass would always be true.
let llCheckClass = (typeof tlCheckClass !== 'undefined') ? tlCheckClass : true;
let lcMainContent = Boolean(tcMainContent) ? tcMainContent : 'div.main-container';
let lcImageClass = Boolean(tcDefaultImageClass) ? tcDefaultImageClass : 'responsive-image-large';
// Unfortunately, I can't get the title in the template of field.html.twig.
// to override the image output.
let lcPageTitle = jQuery(document).attr('title').split('|')[0].trim();
jQuery(lcMainContent + ' img').each(function ()
{
let loImage = jQuery(this);
let lcAlt = loImage.attr('alt');
if (!Boolean(lcAlt))
{
lcAlt = lcPageTitle;
loImage.attr('alt', lcAlt);
}
let lcTitle = loImage.attr('title');
if (!Boolean(lcTitle))
{
lcTitle = lcPageTitle;
loImage.attr('title', lcTitle);
}
loImage.removeAttr('width');
loImage.removeAttr('height');
loImage.removeAttr('style');
if (llCheckClass)
{
let lcClasses = loImage.attr('class');
if ((!Boolean(lcClasses)) || (lcClasses.indexOf('responsive-image') < 0))
{
loImage.addClass(lcImageClass);
}
}
if (!loImage.parent().is('a'))
{
let lcSource = loImage.attr('src');
// From https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format
loImage.wrap(`<a class='dialogbox-image' href='${lcSource}' data-lightbox='${lcTitle}' data-alt='${lcAlt}' data-title='${lcTitle}'></a>`);
}
});
},
// -------------------------------------------------------------------------------------------------------------------
// From https://drupal.org/node/249933
disableFormReturn: function ()
{
jQuery('input').keypress(function (toEvent)
{
return ((toEvent.keyCode == 13) ? false : true);
});
},
// -------------------------------------------------------------------------------------------------------------------
isWindowInIFrame: function ()
{
return (window.location != window.parent.location);
},
//----------------------------------------------------------------------------------------------------
adjustTabsAlignment: function (toTabs)
{
let lnWidth = jQuery(window).width();
if (lnWidth >= 768)
{
if (toTabs.tabs().hasClass('ui-tabs-vertical ui-helper-clearfix'))
{
toTabs.tabs().removeClass('ui-tabs-vertical ui-helper-clearfix');
toTabs.find('li').addClass('ui-corner-top').removeClass('ui-corner-left');
}
}
else
{
if (!toTabs.tabs().hasClass('ui-tabs-vertical ui-helper-clearfix'))
{
toTabs.tabs().addClass('ui-tabs-vertical ui-helper-clearfix');
toTabs.find('li').removeClass('ui-corner-top').addClass('ui-corner-left');
}
}
},
//----------------------------------------------------------------------------------------------------
updateLinksWithExternalURLs: function (tcSelect)
{
jQuery(tcSelect).find('a').each(function ()
{
let loThis = jQuery(this);
let lcHref = loThis.attr('href');
let lcHostname = window.location.hostname;
if (Boolean(lcHref) && (!lcHref.startsWith('/')) && (!lcHref.startsWith('?')) && (!lcHref.startsWith('#')) && (!lcHref.includes(lcHostname)))
{
loThis.attr('target', '_blank');
}
});
jQuery(tcSelect).find('form').each(function ()
{
let loThis = jQuery(this);
let lcAction = loThis.attr('action');
let lcHostname = window.location.hostname;
if (Boolean(lcAction) && (!lcAction.startsWith('/')) && (!lcHref.startsWith('?')) && (!lcHref.startsWith('#')) && (!lcAction.includes(lcHostname)))
{
loThis.attr('target', '_blank');
}
});
}
//----------------------------------------------------------------------------------------------------
};
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
/*----------------------------------------------------------------------------------------*/
/*
Updated on November 21, 2019
*/
/*----------------------------------------------------------------------------------------*/
/*
Watermarks
*/
textarea.watermark,
input.watermark
{
color: #999999;
}
/*----------------------------------------------------------------------------------------*/
/*
Menu items.
*/
.navbar-toggle
{
background-color: #62453D;
position: fixed;
top: 10px;
right: 15px;
}
/*
Brilliant. . . .
From https://julienmelissas.com/animated-x-icon-for-the-bootstrap-navbar-toggle/
Make sure that you add the classes to system/page.html.twig
*/
.navbar-toggle .icon-bar
{
width: 22px;
transition: all 0.2s;
}
.navbar-toggle .top-bar
{
-webkit-transform: translateX(3px) rotate(45deg);
-moz-transform: translateX(3px) rotate(45deg);
-o-transform: translateX(3px) rotate(45deg);
transform: translateX(3px) rotate(45deg);
-webkit-transform-origin: 10% 10%;
-moz-transform-origin: 10% 10%;
-o-transform-origin: 10% 10%;
transform-origin: 10% 10%;
}
.navbar-toggle .middle-bar
{
opacity: 0;
}
.navbar-toggle .bottom-bar
{
-webkit-transform: translateX(3px) rotate(-45deg);
-moz-transform: translateX(3px) rotate(-45deg);
-o-transform: rotate(-45deg);
transform: translateX(3px) rotate(-45deg);
-webkit-transform-origin: 10% 90%;
-moz-transform-origin: 10% 90%;
-o-transform-origin: 10% 90%;
transform-origin: 10% 90%;
}
.navbar-toggle.collapsed .top-bar
{
-webkit-transform: rotate(0);
-moz-transform: rotate(0);
-o-transform: rotate(0);
transform: rotate(0);
}
.navbar-toggle.collapsed .middle-bar
{
opacity: 1;
}
.navbar-toggle.collapsed .bottom-bar
{
-webkit-transform: rotate(0);
-moz-transform: rotate(0);
-o-transform: rotate(0);
transform: rotate(0);
}
/*
Bootstrap uses min-width: 768px settings,
so max-width: 767px works in concert
*/
@media (max-width: 767px)
{
div.navbar-collapse
{
position: fixed;
width: 150px;
top: 53px;
right: 44px;
padding: 0 10px;
overflow: hidden;
border: 1px solid #333333;
background-color: #FBFBF8;
}
div.navbar-collapse ul li
{
float: none;
width: 100%;
}
}
.navbar-inverse .navbar-nav > li > a
{
color: #62453D;
font-weight: normal;
font-size: 1.25em;
}
.navbar-inverse .navbar-nav > li > a:hover,
.navbar-inverse .navbar-nav > li > a:focus
{
color: #0063A0;
}
.navbar-inverse .navbar-nav > .active > a,
.navbar-inverse .navbar-nav > .active > a:hover,
.navbar-inverse .navbar-nav > .active > a:focus
{
color: #62453D;
background-color: lightgray;
}
/*
From https://bootstrapstudio.io/forums/topic/center-navbar/
Centering the navbar.
*/
@media (min-width: 768px)
{
.navbar .navbar-nav
{
display: inline-block;
float: none;
vertical-align: top;
}
.navbar .navbar-collapse
{
text-align: center;
}
}
.expanded.dropdown .caret
{
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
-moz-transition: all 0.2s;
-webkit-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
.expanded.dropdown.open .caret
{
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
-moz-transition: all 0.2s;
-webkit-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
/*----------------------------------------------------------------------------------------*/
/*
From https://stackoverflow.com/questions/20751316/how-to-make-div-to-match-image-height-with-css
Otherwise, the <a></a> will not stretch to fit the image.
*/
/*
This way, the image doesn't briefly appear large and then resize.
I'm also assuming that I will be using the Beo.setupImageDialogBox
for all images.
*/
img
{
display: none;
}
.ui-dialog img
{
display: block;
padding: 0;
}
/* ------ */
.dialogbox-image
{
position: relative;
overflow: hidden;
display: inline-block;
text-align: center;
}
a.dialogbox-image img
{
opacity: 1.0;
-moz-transition: opacity 0.25s ease;
-webkit-transition: opacity 0.25s ease;
transition: opacity 0.25s ease;
}
a.dialogbox-image img:hover
{
opacity: 0.75;
-moz-transition: opacity 0.25s ease;
-webkit-transition: opacity 0.25s ease;
transition: opacity 0.25s ease;
}
/*----------------------------------------------------------------------------------------*/
/*
From https://stackoverflow.com/questions/9189810/css-display-inline-vs-inline-block
I'm modifying .img-responsive from Bootstrap. I need to use inline-block.
*/
.responsive-image-small,
.responsive-image-regular,
.responsive-image-large
{
display: inline-block;
max-width: 100%;
height: auto;
}
.responsive-image-small
{
max-height: 240px;
}
.responsive-image-regular
{
max-height: 350px;
}
.responsive-image-large
{
max-height: 480px;
}
/*
Bootstrap uses min-width: 768px settings,
so max-width: 767px works in concert
*/
@media (max-width: 767px)
{
.responsive-image-small
{
max-height: 175px;
}
.responsive-image-regular
{
max-height: 285px;
}
.responsive-image-large
{
max-height: 415px;
}
}
/*----------------------------------------------------------------------------------------*/
/*
jQuery UI
*/
.ui-dialog
{
z-index: 99999;
}
.ui-dialog .ui-dialog-titlebar
{
padding: 0.1em 1.0em;
}
.ui-dialog .ui-dialog-content
{
padding: 0;
}
.ui-corner-all
{
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.ui-tabs-vertical
{
width: 100%;
}
.ui-tabs-vertical .ui-tabs-nav .ui-tabs-anchor
{
width: 100%;
}
.ui-tabs-vertical .ui-tabs-nav
{
padding: .2em .1em .2em .2em;
float: left;
width: 12em;
}
.ui-tabs-vertical .ui-tabs-nav li
{
clear: left;
width: 100%;
border-bottom-width: 1px !important;
border-right-width: 0 !important;
margin: 0 -1px .2em 0;
}
.ui-tabs-vertical .ui-tabs-nav li a
{
display: block;
}
.ui-tabs-vertical .ui-tabs-nav li.ui-tabs-active
{
padding-bottom: 0;
padding-right: 0.1em;
border-right-width: 1px;
}
.ui-tabs-vertical .ui-tabs-panel
{
padding: 1.0em;
float: left;
width: 100%;
/*
From https://stackoverflow.com/questions/36418352/css-word-wrap-break-word-wont-work
Now, all the text wraps, even the long URLs, and the text no longer overflows the sides.
*/
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
word-break: break-word;
hyphens: auto;
}
/*----------------------------------------------------------------------------------------*/
// Updated on July 19, 2016
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
var Navicon =
{
QUEUE_SCROLL: "MenuScroll",
// -------------------------------------------------------------------------------------------------------------------
setupNavicon: function (tcNavicon, tcMenu, tcWithinMenuList, tfnOnClick)
{
if (jQuery(tcNavicon).length == 0)
{
alert(tcNavicon + " does not exist for setupNavicon.");
return;
}
if (jQuery(tcMenu).length == 0)
{
alert(tcMenu + " does not exist for setupNavicon.");
return;
}
if (jQuery(tcMenu + " " + tcWithinMenuList).length == 0)
{
alert(tcMenu + " " + tcWithinMenuList + " does not exist for setupNavicon.");
return;
}
// Make the menu disappear if window resizing.
jQuery(window).resize(function ()
{
Navicon.toggleNaviconMenu(tcNavicon, tcMenu, true);
});
// Navicon click action.
jQuery(tcNavicon).click(function (toEvent)
{
Navicon.toggleNaviconMenu(tcNavicon, tcMenu, false);
});
// Menu item click action
// Apparently this will include clicking on the <a href> link element.
jQuery(tcMenu + " " + tcWithinMenuList).each(function ()
{
var lcHref = jQuery(this).attr('href');
if (typeof lcHref === "undefined")
{
lcHref = jQuery(this).find('a').attr('href');
}
jQuery(this).click(function (toEvent)
{
toEvent.preventDefault();
Navicon.toggleNaviconMenu(tcNavicon, tcMenu, true);
//it is a good idea to check if the parameter is actually not null
//and that it is a function
if (tfnOnClick && (typeof tfnOnClick == "function"))
{
tfnOnClick(jQuery(this));
}
else
{
Navicon.scrollToAnchor(lcHref);
}
});
});
},
// -------------------------------------------------------------------------------------------------------------------
toggleNaviconMenu: function (tcNavicon, tcMenu, tlForceClose)
{
var loNavicon = jQuery(tcNavicon);
// Should be named something like #navicon-wrapper.
var loWrapper = loNavicon.parent();
var loWrapperParent = loWrapper.parent();
var laLines = [];
loNavicon.find("div.horizontal-line").each(function ()
{
var loLine = jQuery(this);
laLines.push(loLine);
if (!loLine.hasClass('smoothRotateIcon'))
{
loLine.addClass('smoothRotateIcon')
}
});
var loMenu = jQuery(tcMenu);
if (loMenu.is(":visible") || (tlForceClose))
{
loMenu.hide('scale', {percent: 0}, 500);
loWrapper.animate({backgroundColor: "transparent"}, 500);
laLines[1].show();
laLines[0].removeClass('xOn').removeClass('xRotateClockwise');
laLines[2].removeClass('xOn').removeClass('xRotateCounterClockwise');
}
else
{
loMenu.css('top', (loWrapper.position().top + parseInt(loWrapperParent.css("top")) + loWrapper.height()) + 'px');
if (loWrapperParent.css("right") != "auto")
{
loMenu.css('left', (loWrapperParent.position().left) + 'px');
}
else if (loWrapperParent.css("left") != "auto")
{
loMenu.css('left', (parseInt(loWrapperParent.css("left"))) + 'px');
}
else
{
alert("Unable to determine the left side for the menu.\n\n\"" + loWrapperParent.attr('id') + "\" should have either 'left' or 'right' set in the CSS.");
}
laLines[1].hide();
laLines[0].addClass('xOn').addClass('xRotateClockwise');
laLines[2].addClass('xOn').addClass('xRotateCounterClockwise');
loMenu.show('scale', {percent: 100}, 500);
var lcBackgroundColor = loMenu.css("backgroundColor");
loWrapper.animate({backgroundColor: lcBackgroundColor}, 500);
}
},
// -------------------------------------------------------------------------------------------------------------------
// For those times that the front page is launched from a secondary page with an anchor link.
// Something like, /#contact-us.
checkForAnchorLink: function ()
{
if (window.location.hash != '')
{
Navicon.scrollToAnchor(window.location.hash);
}
},
// -------------------------------------------------------------------------------------------------------------------
scrollToAnchor: function (tcHref)
{
// If not on a Drupal front page. . . .
if (jQuery("body.front").length == 0)
{
window.location.href = tcHref;
return;
}
// Get rid of the # character.
// By the way, IE 8 and below doesn't like replace('#', "") and complains
// about illegal character. And IE 8 doesn't have a trim function.
// var lcHref = jQuery.trim(tcHref.replace(/#/g, ""));
var lcSearch = tcHref;
var lnPos = tcHref.indexOf("\#");
if (lnPos == -1)
{
window.location.href = tcHref;
return;
}
lcSearch = tcHref.substr(lnPos);
// If the href has been changed 'cause the menu is on a page other than the front,
// then the anchor reference will be invalid.
if (jQuery(lcSearch).length > 0)
{
// And to work in FireFox you need both body and html.
var lcTop = jQuery(lcSearch).position().top + "px";
// Anything lower than 1000 is just a little too fast, sometimes appearing
// to be immediate.
jQuery("body, html").animate({'scrollTop': lcTop}, {'duration': 1000, 'queue': Navicon.QUEUE_SCROLL});
jQuery("body, html").dequeue(Navicon.QUEUE_SCROLL);
}
}
//----------------------------------------------------------------------------------------------------
}
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment