How to close jQuery Tools Overlay on click, no matter where? - javascript

I've added the Overlay effect of jQuery Tools to my site, using the "Minimum Setup". Unfortunately when the user wants to close it, he must target this tiny circle on the upper right. Usability suffers this way. It would be far better if the user could simply click anywhere to close it.
Can I modify or add some code so it would close the overlay no matter where to user clicks? Or maybe when he clicks outside of the overlay? I couldn't find any notes on that in the docs.

Or maybe when he clicks outside of the overlay?
Check the docs ('Configuration' part):
closeOnClick (default: true)
By default, overlays are closed when the mouse is clicked outside the overlay area. Setting this property to false suppresses this behaviour which is suitable for modal dialogs.
I.e., this functionality is already enabled by default. If it's not working, you might want to show us your overlay configuration.

#NikitaRybak The closeOnClick only works when you're using a expose/mask. I've modified the overlay code to work without a expose/mask..
Tidy the minified javascript..
locate this in the minified code:
b.closeOnClick && a(document).bind("click." + n, function(l) {
and insert this to the function instead
if (!a(l.target).hasClass('overlay') && !a(l.target).hasClass('apple') && !a(l.target).parents('.overlay', f).length && !a(l.target).parents('[rel="#' + a(f).attr('id') + '"]').length && !(a(l.target).attr('rel') == '#' + a(f).attr('id'))) { c.close(l); }
Now if you're using the apple effect, find this in the apple effect code:
b = h('<img src="' + b + '"/>');
and insert class="apple" so it becomes:
b = h('<img class="apple" src="' + b + '"/>');
Hope this helps if anyone needs it..

Try (quick and dirty):
$(document).click(function(){
$('.simple_overlay:visible .close').click();
});

During my experiments I found out that even official jQuery Tools standalone demo doesn't close overlay correctly. For example when I click under the overlayed image it closes but when I click on the right or left side outside of the overlay it doesn't close.
So, in my case I used next solution to close overlay on click anywhere on the document:
<script type="text/javascript">
function closeOverlay(){
$('.overlay:visible .close').click();
}
document.addEventListener('click',closeOverlay,true);
</script>
May be it's dirty too but it works for me.

Related

How to use links in Medium Editor?

I've been trying out the excellent Medium Editor. The problem that I've been having is that I can't seem to get links to "work".
At the simplest, here's some HTML/JS to use to demonstrate the problem:
HTML:
<html>
<head>
<script src="//cdn.jsdelivr.net/medium-editor/latest/js/medium-editor.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/medium-editor/latest/css/medium-editor.min.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/medium-editor/latest/css/themes/beagle.min.css" type="text/css">
</head>
<body>
<div class='editable'>
Hello world. link
</div>
</body>
</html>
Javascript:
var editor = new MediumEditor('.editable');
This fiddle demonstrates the problem (using the code above).
If you hover on the link, a popup appears.
If you click the link, nothing happens.
If you click the popup, a form appears where you can edit the link.
It seems to me that clicking the link should take me wherever the link's href is targeting. The only way to use the link is to right click and either open in a new tab or new window -- which I don't want to ask my users to do.
I feel like I must be missing something simple in the configuration (either the Anchor Preview Options or the Anchor Form Options). Unfortunately, I'm not seeing it.
In my actual application, I'm not using jQuery, but I am using angularjs. If a strictly Medium Editor answer doesn't exist, I can fall back to using basic JS or anything that angularjs provides.
I've found how to bind event.
Here is full event list https://github.com/yabwe/medium-editor/blob/master/CUSTOM-EVENTS.md
Try to change your code to
var editor = new MediumEditor('.editable')
.subscribe("editableClick", function(e){if (e.target.href) {window.open(e.target.href)}})
https://jsfiddle.net/fhr18gm1/
So medium-editor is built on top of the built-in browser support for contenteditable elements. When you instantiate medium-editor, it will add the contenteditable=true attribute to whatever element(s) you provided it.
By default, since the text is now editable (the contenteditable attribute makes the browser treat it as WYSIWYG text) the browser no longer supports clicking on the links to navigate. So, medium-editor is not blocking these link clicks from happening, the browsers do it inherently as part of making the text editable.
medium-editor has built in extensions for interacting with links:
anchor extension
allows for adding/removing links
anchor-preview extension
shows a tooltip when hovering a link
when the tooltip is clicked, allows for editing the href of the link via the anchor extension
I think the underlying goal of the editor is the misunderstanding here. The editor allows for editing text, and in order to add/remove/update links, you need to be able to click into it without automatically navigating away. This is what I think of as 'edit' mode.
However, the html produced as a result of editing is valid html, and if you take that html and put it inside an element that does NOT have the contenteditable=true attribute, everything will work as expected. I think of this as 'publish mode'
I look at editors like word or google docs, and you see a similar kind of behavior where when you edit the document, the links don't just navigate away when you click on them, you have to actually choose to navigate them through a separate action after you click the link. However, on a 'published' version of the document, clicking the link will actually open a browser window and navigate there.
I think this does make for a good suggestion as an enhancement to the existing anchor-preview extension. Perhaps the tooltip that appears when hovering a link could have multiple options in it (ie Edit Link | Remove Link | Navigate to URL).
tldr;
Links are not navigable on click when 'editing' text in a browser via the built-in WYSIWYG support (contenteditable). When not in 'edit' mode, the links will work as expected.
This could make for a nice enhancement to the medium-editor anchor-preview extension.
Working off some ideas from #Valijon in the comments, I was able to get it to work using the following code:
var iElement = angular.element(mediumEditorElement);
iElement.on('click', function(event) {
if (
event.target && event.target.tagName == 'A' &&
event.target.href && !event.defaultPrevented) {
$window.open(event.target.href, '_blank');
}
});
I think the key is that apparently the editor lets the event propogate to the ancestor elements, so I was able to just listen for the click on the top level editor element.
Here, $window is angular's $window service -- If you're not using angularjs, window would do the trick and I used angular.element to ease the event listener registry, but you could do it the old-fashioned way (or using the JS framework of your choice).
What I really wanted when I asked the question was behavior similar to Google Docs when in "edit" mode (as described by Nate Mielnik). I opened an issue on the Medium Editor tracker and they decided not to implement it as part of the core medium editor, but they noted that they would be happy to have someone add that functionality as an extension.
So, I decided to implement that functionality as an extension as suggested. It can be found as part of MediumTools1. The project is still in very early stages (e.g. I haven't done anything to make the styling look better, or to use better minifying practices, etc. but we'll happily accept Pull Requests for that).
The guts of the code look like this:
var ClassName = {
INNER: 'medium-editor-toolbar-anchor-preview-inner',
INNER_CHANGE: 'medium-editor-toolbar-anchor-preview-inner-change',
INNER_REMOVE: 'medium-editor-toolbar-anchor-preview-inner-remove'
}
var AnchorPreview = MediumEditor.extensions.anchorPreview;
GdocMediumAnchorPreview = MediumEditor.Extension.extend.call(
AnchorPreview, {
/** #override */
getTemplate: function () {
return '<div class="medium-editor-toolbar-anchor-preview">' +
' <a class="' + ClassName.INNER + '"></a>' +
' -' +
' <a class="' + ClassName.INNER_CHANGE + '">Change</a>' +
' |' +
' <a class="' + ClassName.INNER_REMOVE + '">Remove</a>' +
'</div>';
},
/** #override */
createPreview: function () {
var el = this.document.createElement('div');
el.id = 'medium-editor-anchor-preview-' + this.getEditorId();
el.className = 'medium-editor-anchor-preview';
el.innerHTML = this.getTemplate();
var targetBlank =
this.getEditorOption('targetBlank') ||
this.getEditorOption('gdocAnchorTargetBlank');
if (targetBlank) {
el.querySelector('.' + ClassName.INNER).target = '_blank';
}
var changeEl = el.querySelector('.' + ClassName.INNER_CHANGE);
this.on(changeEl, 'click', this.handleClick.bind(this));
var unlinkEl = el.querySelector('.' + ClassName.INNER_REMOVE);
this.on(unlinkEl, 'click', this.handleUnlink.bind(this));
return el;
},
/** Unlink the currently active anchor. */
handleUnlink: function() {
var activeAnchor = this.activeAnchor;
if (activeAnchor) {
this.activeAnchor.outerHTML = this.activeAnchor.innerHTML;
this.hidePreview();
}
}
});
As an explanation, I just use medium's flavor of prototypical inheritance to "subclass" the original/builtin AnchorPreview extension. I override the getTemplate method to add the additional links into the markup. Then I borrowed a lot from the base implementation of getPreview, but I bound new actions to each of the links as appropriate. Finally, I needed to have an action for "unlinking" the link when "Remove" is clicked, so I added a method for that. The unlink method could probably be done a little better using contenteditable magic (to make sure that it is part of the browser's undo stack), but I didn't spend the time to figure that out (though it would make a good Pull Request for anyone interested :-).
1Currently, it's the only part, but I hope that'll change at some point. . .

Twitter bootstrap dropdown menu doesn't work properly

I trying to use this menu Bootstrap Collapsible Side Menu but something doesn't work properly. There is + sign and - for open and close. When I open first menu + become - as must be but when I click on second menu first must close and - must become +. I hope you get what I mean. This doesn't work properly. Also when I click on second menu the icon that is front of the name become - also.
I've tried to recreate this menu in jsfiddle but doesn't work there. Doesn't open the menu but you can see what happen with + and - signs. If you click on both links they are with -.
Here is the jsfiddle. I didn't work with jsfiddle before.
Looks like you just forgot to load jquery, or you are loading it after bootstrap. It works fine if you load it properly.
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
http://jsfiddle.net/acidrat/BP6Wh/2/
Check you browser console for error messages.
EDIT
Ok, now i get it. You will have to work with Bootstrap collapse events that are triggered after collapsing.
$('#menu-bar').on('shown.bs.collapse', function () {
var currentlySelectedElement = $(this).find('.collapse.in');
var targetAnchor = $('[data-target="#' + currentlySelectedElement.attr('id') + '"]');
$('[data-target="#' + currentlySelectedElement.attr('id') + '"]').find("i.fa-plus").removeClass("fa-plus").addClass("fa-minus");
});
$('#menu-bar').on('hidden.bs.collapse', function () {
var currentlyCollapsedElements = $(this).find('.collapsed');
currentlyCollapsedElements.each(function () {
$(this).find('i.fa-minus').removeClass('fa-minus').addClass('fa-plus');
});
});
Here the updated jsFiddle: http://jsfiddle.net/acidrat/BP6Wh/5/

style a JavaScript onmouseover alert

This is my code to make the alert appear when i hover over the image;
var special_offers = document.getElementsByClassName("special_offer");
//for each special offer
for(i=0;i<special_offers.length;i++){
var special_offer = special_offers[i];
special_offer.setAttribute("offer_shown", "0");
special_offer.onmouseover = function(){
if( this.getAttribute("offer_shown") == "0" ){
this.setAttribute("offer_shown", "1");
alert('This room has the special offer attached to it, please book soon before you miss out!');
}
}
I wanted to find out how i change this from the bog standard JS alert to a box that i can style, i imagine i'd use some sort of a div.
Any help is much appreciated.
http://www.webdesignerdepot.com/2012/10/creating-a-modal-window-with-html5-and-css3/
This is a good resource for creating your own modal window. You can use your function to fire the modal window you created instead of just using alert() to fire up the standard alert.
Do you want to direct your message to a div?
Create the div
<div id="mySpecialOffer">
Some Text gets updated
</div>
In your js you could then target this id and update with what ever message you would like.
document.getElementById("mySpecialOffer").innerHTML = 'some Text';
You could even hide the div in css and then unhide with the JS.
Or you can create the HTML...
document.getElementById("mySpecialOffer").innerHTML = '<div> Special Offer Div Inserted </div>';
This is even easier with jQuery.
Is this what you had in mind?
What you should do is open a whole new window, like a small webpage with that message. That would be the easiest way to go!Here is a link: http://www.w3schools.com/jsref/met_win_open.asp
You will want to have the window.open() activated when people mouseover an image.you can specify the size and positioning of the window, in this case the center of the screen, and a small window.
Hope that helps!

Jquery .ClickOut Event

Hi everybody,
I have some issue with one of my project. I'm currently developing a toolbar for Google Chrome. The concept is that my extension insert by using a content script an iframe in every page i visit. Materialized in Red on my Printscreen.
After that i've created another iframe who appear when i click on the "Menu" Button. This iframe appear like a dropMenu. Materialized in orange in the printscreen.
Well now let me explain my problem :
When i click on the "dropMenuButton" i execute this code :
$( "#dM1").click( function() {
dropMenu('dropMenu1', $(this).position().left);
});
To be clear the function "dropMenu" will call my background page (by messaging exchange) to show or hide the dropMenu, in function if it's allready activated or not.
Here is the executed code by the "dropMenu function"
if(document.getElementById("dropMenu"))
{
$("#dropMenu").slideUp(800, function() {
$(this).remove();
});
}
else
{
var body = $('body'),
MenuURL = chrome.extension.getURL(dropMenuPage + ".html"),
iframe = $('<iframe id="dropMenu" scrolling="no" src="'+MenuURL+'">');
body.append(iframe);
$("#dropMenu").hide().slideDown(800);
// Shift the menu (Left)
$("#dropMenu").css({left: marginLeft+'px'});
}
So the event on dropMenuButton work perfectly but i want to provide some ameliorations like a .ClickOut event. What i want is that when somebody click outside the dropMenu (in orange) the menu will be hide.
I've tried a lot of things but nothing work...
Hope somebody will provide me some help !
Thanks in advance.
Edit (Injection) :
I've tried to inject the javascript like this :
var injectJs = $('<script type=text/javascript>' +
'$(document).click(function() {' +
'dropMenu("dropMenu1", 0);' +
'});');
body.append(injectJs);
injectJs = $('$("#dropMenu").click( function(e) {' +
'e.stopPropagation();' +
'});' +
'</script>');
body.append(injectJs);
But it didn't seems to inject on the page. It should have a problem somewhere...
Can't you just add a click event on the document? Then on the actual drop down menu (or any other events where you don't want to hide the drop down) prevent any clicks from bubbling up:
$(document).click(function(){
// hide drop down clicking anywhere on page:
$("#dropMenu").slideUp(800, function() {
$(this).remove();
});
});
$("#dropMenu").click( function(e) {
e.stopPropagation(); // prevent click on drop menu from removing the drop down.
});
It works great but like this :
$(document).click(function(){
// hide drop down clicking anywhere on page:
dropMenu('slideUp', 0);
});
$("#dM1").click( function(e) {
e.stopPropagation(); // prevent click on drop menu from removing the drop down.
dropMenu('dropMenu1', $(this).position().left);
});
Now i have to insert the similar code on the global page, someone have an idea how i can insert dynamically a js code ?

html background ad

I have seen a lot of websites which "wrapper" width is 960px. As a background image they have an image which is clickable (some kind of advertise) and the whole webpage is over that image, like on this site.
Can you give me tutorial or something on that ?
Tom's code was a huge help, but I needed pointer cursor for this type of ad, but not for all the site, so I came up with this solution:
$('body').bind('click', function(e) {
if ($(e.target).closest('#container').size() == 0) {
alert('click');
}
}).bind('mouseover', function(e) {
if ($(e.target).closest('#container').size() == 0) {
$(this).css('cursor','pointer');
} else {
$(this).css('cursor','default');
}
});
In the first place you put the ad image as the website background then basically you have to capture the click on the whole body and check if it was in-or-outside of the page content. To do that you have to check if the event target element have the content wrapper (or wrappers if there are multiple) as one of its parent nodes - if not it means the click was outside of the page content.
If you'd like to do it here on StackOverflow you could do it with this bit of code.
$('body').bind('click', function(e){
if(!$(e.target).closest('#content').length) {
alert('ad outside content clicked');
}
});
Feel free to try it in your javascript console - SO is using jQuery so it will work - when you will click outside of the content area (at the edges of the screen) you will get alert that ad was clicked.
You'd obviously have to replace the alert with any kind of callback you'd have for your commercial - opening a new web page or whatever
Hope that helps
Tom
ps.
Keep in mind that this example is using jQuery for simplicity not native JS so you'd need the library for it to work.

Categories