How can I use document.referrer with two different modals? - javascript

I have two different modals on my website, one with specific domains to target, the other to target all pages with domain website.com. Both modals are targeting the document.referrer and each modal has a different id (#closureModal and #parkModal).
My issue is that the #parkModal is firing on all pages (rather than specific pages: website.com/parks/park1, website.com/acitivies/park1, etc) since it starts with the domain website.com.
How can I allow two different modals target the document.referrer without one appearing where it's not meant to? How can I use document.referrer with two different modals?
here is #closureModal's code:
const tsp = ["website.com"];
const closureReferrer = document.referrer;
const referrer_hostname = closureReferrer !== "" ? new URL(closureReferrer).hostname : "";
if (tsp.includes(referrer_hostname)) {
console.log("Don't Show Modal", closureReferrer);
} else {
console.log("Show Modal", closureReferrer);
$( window ).on('load', function() {
console.log("closure modal firing");
$('#closureModal .closure').modal({
backdrop: 'static',
keyboard: false,
show: true
});
});
}
the #parkModal is similar code:
const domains = ["https://website.com/parks/park1", "https://website.com/parks/events/park1", "https://website.com/parks/events/park1", "https://website.com/parks/promotions/park1", "https://website.com/parks/go-green/park1", "https://website.com/parks/info/park1", "https://website.com/parks/activities/park1", "https://website.com/parks/events/park1/#/?park=park1"];
const parkReferrer = document.referrer;
if (domains.includes(parkReferrer)) {
console.log("Don't Show Modal - from Cummins page", parkReferrer);
} else {
console.log("Show Modal - From other Page", parkReferrer);
$( window ).on('load', function() {
console.log("park modal firing");
$('#parkModal').modal({
backdrop: 'static',
keyboard: false,
show: true
});
});
}

I don't immediately see the issue but I do have some advice on what may help you move closer to both better code and something that is easier to diagnose.
I see a lot of code duplication. Is it necessary to have two different window onload events that both look at the referrer and then decide which modal to display? My recommendation is do it all in one onload handler that looks at document.referrer only once, then determines what modal to display (if any).
Something kinda like:
$( window ).on('load', function() {
console.log("park modal firing");
// define your parkReferrers and closureReferrers here
const referrer = document.referrer;
const displayParkReferrerModal = parkReferrers.includes(referrer);
const displayClosureModal = closureReferrers.includes(referrer);
let modalToDisplay;
if (displayParkReferrerModal) {
modalToDisplay = '#parkModal';
} else if (displayClosureModal) {
modalToDisplay = '#closureModal .closure';
}
if (modalToDisplay) {
console.log(modalToDisplay);
$(modalToDisplay).modal({
backdrop: 'static',
keyboard: false,
show: true
});
return;
}
console.log('no matching modal to display');
return;
});
Hope this is helpful. You could also abstract this to a handleReferrerModal function that you then invoke in the load event handler. That might be cleaner if you have multiple different things happening on load.

Related

Auto close a Modal Popup instead of using a button/on-click

I currently have a page that is refreshing and I want to place a modal popup on the screen that gives the user a message such as "Please wait...". The reload is being performed with a $state.reload().
GenericModalService.confirmationSplit($rootScope, modal);
$state.reload();
function confirmationSplit(scope, modal) {
scope.modal = modal;
scope.modalInstance = $uibModal.open({
templateUrl: 'Scripts/app/Modals/ConfirmationSplit.html',
scope: scope,
size: 'md',
backdrop: modal.backdrop != null ? modal.backdrop : true,
})
}
Is there a way that I can close the modal once the $state.reload(); finishes? If not, is there a way that I can set an auto-timer for about 2-3 seconds and then have the modal close without the need to close/dismiss the modal using a button?
Bootstrap uses a jquery plugin to manually manage modals, I think in your case there are 3 useful methods:
// NOTE: I'm assuming the modal's id is #message
//show a modal:
$('#message').modal('show');
// close a modal:
$('#message').modal('hide');
//capture 'modal shown' event:
$('#message').on('shown.bs.modal', function (e) {
// do something...
})
You can use the above pieces of code to manually show the modal and to hide it after the reload event ended.
if you can't catch the reload ended event you can easily set up an interval once the modal has been shown and close it after a set amount of time like this:
$('#message').on('shown.bs.modal', function (e) {
console.log('modal has been shown');
setTimeout(function () {
console.log('closing modal...');
$('#message').modal('hide');
}, 3000)
})
related bootstrap doc: https://getbootstrap.com/docs/4.0/components/modal/#via-javascript

How to open/close sidebar in TinyMCE

In the official TinyMCE docs is nothing written about the possibility to manually open/close the sidebar:
https://www.tinymce.com/docs/advanced/creating-a-sidebar/#editorsidebarapi
Can anybody help me? I think it must be something like this:
editor.getSidebar('mysidebar').close();
I need it, because I want to close my custom sidebar in my file browser callback.
Use tinymce.activeEditor.execCommand('togglesidebar', false, 'sidebarname'); to toggle the sidebar. You could place event dispacthers and listeners to know if it is currently opened or closed:
tinymce.PluginManager.add('cheminfo', function (editor, url) {
editor.ui.registry.addSidebar('cheminfo', {
tooltip: 'My sidebar',
icon: 'comment',
onShow: function (api) {
var event = new CustomEvent('tinymce-chem-sidebar', {'detail': true});
window.parent.document.dispatchEvent(event);
},
onHide: function (api) {
var event = new CustomEvent('tinymce-chem-sidebar', {'detail': false});
window.parent.document.dispatchEvent(event);
}
});
});
Then (I am using React):
// detect sidebar state open/close
document.addEventListener('tinymce-chem-sidebar', function (e) {
setOpen(e.detail);
});
PS: Make sure the sidebar's name is lowercase or it won't work
adding to #Kristiyan Tsvetanov's solution, an alternative to using event listeners in determining open/close state of sidebar, the following code can be used:
function is_sidebar_open() {
//class names taken from using inspect on the
//sidebar area of the editor in a browser session
if ($(".tox-sidebar__slider").hasClass("tox-sidebar--sliding-closed")) {
return false;
}
else {
return true;
}
}
function open_sidebar(){
if (is_sidebar_open() == false){
tinymce.activeEditor.execCommand('togglesidebar', false, 'sidebarname');
}
}
function close_sidebar(){
if (is_sidebar_open() == true){
tinymce.activeEditor.execCommand('togglesidebar', false, 'sidebarname');
}
}

trigger an jQuery UI Dialog if user not authorized

On my website I have two ways to login. The first is used then an user is pushing the Logon button, which trigger an jQuery UI Dialog to open. The second is an normal view, which is used, if an user isn't Authorized, which redirect to an normal login view. But what i liked to do instead, is if an user is not Authorized, it opens the Login jquery ui dialog instead of redirection to the view the user is intended.
This is how i currently are opening the dialog,
$(".openLoginDialog").on("click", function (e) {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
create: function (event, ui) {},
close: function () { $(this).remove() },
open: function (event, ui) {},
modal: true,
position: ['center', 130],
minWidth: 510,
resizable: true,
zIndex: 20000
})
.load(this.href);
});
Because the content in the dialog is an partialView it's called like this:
<div class="items iconlogin highligth-br"><a class="openLoginDialog" data-dialog-id="LoginDialog" data-dialog-title="Login" href="#Url.Action("LogOn", "Authentication", new { returnUrl = Request.Url.ToString() })">Login</a></div>
Also to help me controlling the not Authorized, i have overriden this calls.
public override void OnAuthorization(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Authentication", action = "AccessDenied" }));
}
Last resort would be to redirect to an access denied page, with just an white background, which opens on load, a dialog.
I have a MVC intranet solution that employs functionality similar to what you describing, however it is using windows auth not forms.
Basically I have something like this in the Index...
var userExists = "#ViewBag.User";
// require the user to register if they are not found
if (userExists == "") {
$.get('Home/Register/', function (data) {
$("#Register").html(data);
$("#Register").dialog({
resizable: false,
closeOnEscape: false,
dialogClass: 'no-close',
typeDelay: 250
});
});
}
And then in the controller I just set 'ViewBag.User' to the username if they exist.
Have a look at this example:
http://jqueryui.com/dialog/#modal-form
Notice the autoOpen: false
I'm not familiar with asp.net so I wont be able to help with actual implementation. One approach would be to check where the request came from and if the user is not authorized redirect them back to that page and hit them with a dialog.
Another approach would be to know if the user is authenticated on the page load and override links that require authentication
$(".authRequired").on("click", function (e) {
e.preventDefault();
//fancy logic here to load form and dialog
});

How to retain Javascript state on page change

I have an accordion style navigation list set up so that when categories are clicked it opens up to show sub-categories that link to pages.
What I would like to do is have the accordion navigation list keep it's open or closed state when the new page opens.
I've gathered that cookies work to retain the state on refresh, but how do I retain the state when a different page is visited? All the pages have the same accordion navigation list.
Try Web Storage. Store the state of the tabs on page unload, restore the state on the page load event.
I found a solution, it uses the accordian plug-in found here, http://www.i-marco.nl/weblog/archive/2010/02/27/yup_yet_another_jquery_accordi and the jquery cookie.js plug-in
I added id's to the header anchor tages in the HTNL mark-up like so,
<li>
<a id="m1" class="label" href="#">Sound/Audio Systems</a>
<ul class="acitem">
<li>PA Systems</li>
<li>Loudspeakers</li>
<li>Microphones </li>
<li>DJ Equipment</li>
<li>Sound Processing Equipment</li>
</ul>
</li>
And modified the accordian.js code, I added the lines beginning with $.cookie, and the If statement in the document.ready funciton.
jQuery.fn.initMenu = function() {
return this.each(function(){
var theMenu = $(this).get(0);
$('.acitem', this).hide();
$('li.expand > .acitem', this).show();
$('li.expand > .acitem', this).prev().addClass('active'),
currentID = "";
$('li a', this).click(
function(e) {
e.stopImmediatePropagation();
var theElement = $(this).next();
var parent = this.parentNode.parentNode;
if($(parent).hasClass('noaccordion')) {
if(theElement[0] === undefined) {
window.location.href = this.href;
}
$(theElement).slideToggle('normal', function() {
if ($(this).is(':visible')) {
$(this).prev().addClass('active');
currentID = $(this).prev().attr('id');
$.cookie('menustate', currentID, {expires: 2, path: '/'});
}
else {
$(this).prev().removeClass('active');
$.cookie('menustate', null, {expires: 2, path: '/'});
}
});
return false;
}
else {
if(theElement.hasClass('acitem') && theElement.is(':visible')) {
if($(parent).hasClass('collapsible')) {
$('.acitem:visible', parent).first().slideUp('normal',
function() {
$(this).prev().removeClass('active');
$.cookie('menustate', null, {expires: 2, path: '/'});
}
);
return false;
}
return false;
}
if(theElement.hasClass('acitem') && !theElement.is(':visible')) {
$('.acitem:visible', parent).first().slideUp('normal', function() {
$(this).prev().removeClass('active');
$.cookie('menustate', null, {expires: 2, path: '/'});
});
theElement.slideDown('normal', function() {
$(this).prev().addClass('active');
currentID = $(this).prev().attr('id');
$.cookie('menustate', currentID, {expires: 2, path: '/'});
});
return false;
}
}
}
);
});
};
$(document).ready(function() {
$('.menu').initMenu();$('#side-navigation_frame').show();
if ($.cookie('menustate')) {
var anchor = "",
elementID = $.cookie('menustate');
anchor = document.getElementById(elementID);
$(anchor).addClass('active');
$(anchor).next().show();
}
});
It works nicely, not bad for a beginner, thanks for all the advise.
Rob Fenwick
Cookies "retain state" across the full path and domain for which they are specified. So if you can get them to work for just one page, you should have them work automatically on all pages of your site.
You can still use cookies, you just have to make sure they're not specific to the one page. For example:
document.cookie = 'openitem=5; expires=somedate; path=/';
will be accessible to all pages on the site. More about cookies.
Ok so I took a look at the library you are using, it's a decent library and all but you might find it easier to find solutions to your problems if you use a more standard library like jQuery UI, it has an accordion control http://jqueryui.com/demos/accordion/ and like I mentioned there are so many people using it that the answer to most problems can be found.
But like I mentioned I did take a look at your library. As others have mentioned you would use a cookie to store the value. This library supports 'pre expanding' a particular section of the accordian, to do that you would add the expand class to the element. You can either do that server side or you can do it using JavaScript before initMenu() is called.
The other less elegant option is to trigger the click event on the anchor tag after the call to initMenu. Finally you can use jQuery's show() to show expand the section without animation.
The first thing you have to do is find out which section was clicked on, then you would store that sections name in a cookie. On page load you would get that value and expand the appropriate according section. This is what the code should kinda look like - note this is psuedo code and you have fill in the appropriate parts.
$(function() {
$(".menu.collapsible .label").click(function() {
var accordianSection = $(this).text();
rememberSection(accordianSection);
});
var section = recallSection();
if(section !== undefined) {
expandSection(section);
}
});
The expandSection function can look something like this:
var sectionLink = $(".menu.collapsible .label").filter(function() {
return $(this).text() == section;
});
sectionLink.trigger('click');

How do I detect if a javascript constructor already been run?

I'm using the jquery-tools tabs and carousel in a page I'm working on. The carousel is embedded within a tab, and the tab is loaded in a beforeClick callback.
Normally, the carousel is initialized in the document ready function like so:
$(function() {
// initialize scrollable
$("div.scrollable").scrollable({
size: 3,
clickable: true,
loop: false
}).mousewheel();
This doesn't work when the carousel is loaded via beforeClick, because it when the DOM is ready, this tab hasn't been loaded yet.
$("ul.tabs").tabs("div.panes > div", {
initialIndex: 0,
onBeforeClick: function(event, i) {
// get the pane to be opened
var pane = this.getPanes().eq(i);
var src = this.getTabs().eq(i).attr("href");
var langPattern = "/^" + getLang() + '/';
var forceReload = false;
if (src.match(langPattern) == null)
{
src = getLang() + "/" + src;
forceReload = true;
}
if (pane.is(":empty") || forceReload) {
// load it with a page specified in the tab's href attribute
pane.load(src);
// initialize scrollable - ONLY SHOULD BE DONE ONCE
$("div.scrollable").scrollable({
size: 3,
clickable: true,
loop: false
}).mousewheel();
}
}
}).history();;
My question is a two-parter:
First, is there an event I can add a handler to to initialize the scrollable when it is first loaded?
Second, if there isn't, is there a way I can find out if the scrollable has been constructed yet?
The idea behind this code is to load localized html fragments based on the user's language selection. This is for a catalog on a CD, not online.
You might want to check out the jQuery live event. This event matches all current and future DOM matches.
EDIT 1
You want to bind to div.scrollable's onload event, correct?
$('div.scrollable').live('load', function() {
// etc.
});
I solved my problem by attaching a callback to the load call:
pane.load(src, "", function(){
$("div.scrollable").scrollable({
size: 3,
clickable: true,
loop: false
}).mousewheel();
});

Categories