I've been coding my own dialog system for exercising and to be able to customize it as i want. Here is what i've done.
$(function(){
$.fn.window = function(attr){
var $self = this;
if(!attr)
attr = {};
$.extend({
autoOpen:false
}, attr);
/**
* Create the window by updating the current jQuery block
* And adding the required classes
*/
this.create= function(){
// Already created
if($self.hasClass('window-window'))
return;
$self.addClass('window-window');
// Creating the header and appending the title
var $windowHeader = $('<div class="window-header"></div>');
var $title = $self.attr('title');
$windowHeader.html($title);
$windowHeader.append('<div class="loading-item loading-item-footer round-loading25" ' +
'data-loading-item="window" style="display:none"></div>');
// Wrapping content in a window-content class
// So the window has the proper format
$self.children().wrapAll('<div class="window-content"></div>');
$self.prepend($windowHeader);
};
/**
* Open the window in a blackish div
* With the events to close it
*/
this.open = function(){
// Creating the background
var $backgroundDiv = $('<div></div>');
$backgroundDiv.addClass('window-background');
// Making it take the size of the page
$backgroundDiv.height($(window).height());
$backgroundDiv.width($(window).width());
$self.detach().appendTo($backgroundDiv);
// The window is hidden by default, showing it
$self.show();
$('html').prepend($backgroundDiv);
// Handling closing the window
$backgroundDiv.click(function(e){
var $target = $(e.target);
if(!$target.hasClass('window-background'))
return;
$self.hide();
$self.detach().appendTo('html');
$backgroundDiv.remove();
});
};
this.create();
if(attr.autoOpen){
this.open();
}
};
});
For now i have doubt about the fact that i'm putting the window out of his native block, in the end of the html document. I wish to put it back to his position but i have no idea yet how to do it. Any idea ?
First of all, you create a jQuery function, but you do it on document.ready $(...). You should just create it, otherwise the function will not be available for other code until document has loaded.
Then you want to insert the window in the same place as the original element, for that you have insertBefore and insertAfter in jQuery. You use prepend, but that inserts it as the first element of $self.
I would urge you to look at the method chaining of jQuery which may make your code much more readable. Instead of:
// Creating the background
var $backgroundDiv = $('<div></div>');
$backgroundDiv.addClass('window-background');
// Making it take the size of the page
$backgroundDiv.height($(window).height());
$backgroundDiv.width($(window).width());
use
// Creating the background
var $backgroundDiv = $('<div></div>')
.addClass('window-background')
// Making it take the size of the page
.css({
height:$(window).height(),
width:$(window).width()
});
for example.
You also use CSS classes to store information, like if something had been clicked or not. That may be OK, but consider that you may want change the CSS classes and suddenly the functionality of your code is strongly linked to the design. Maybe using .data() instead would be better, even if you add more code to also style your elements.
You use .wrap to take the original content and put it in the window. That may be what you wanted all along, but also take a look at https://api.jquery.com/clone/ which allows you to get the elements without removing them from their original source. Again, only if it works better for you.
As a last advice, use http://jsfiddle.net to share your working code, so other people may not only comment on it, but see it in action as well.
I build a small color-picker module. But it only opens up (and then works) when pickColor is called a second time. I also tried to wrap the _openColorPicker into a setTimeout but that didn't work either. In fact, the color-picker didn't show up at all when I did that.
What I found interesting is that the binding to the change event works, so the $ selector must have found the element already.
So I have two questions:
1) why is the picker only showing after the second call to _openColorPicker?
2) why didn't the picker open at all when I wrapper the _openColorPicker call in a setTimeout?
Edit: The _openColorPicker functions gets executed after the user has right-clicked into the document and then clicked on context-menu which is now showing.
Complete Code:
const ColorUtils = {
_initialized: false,
_openColorPicker: function () {
$('#color-picker').click();
},
pickColor: function (onChangeCallback, context) {
if (!this._initialized) {
$('<input/>').attr({
type: 'color',
id: 'color-picker',
display: 'hidden',
value: '#ffffff'
}).appendTo('#centralRow');
this._initialized = true;
$('#color-picker').on('change', onChangeCallback.bind(context));
}
this._openColorPicker();
// version with timeOut
const scope = this;
setTimeout(function () {
scope._openColorPicker();
}, 1000);
}
};
export default ColorUtils;
Above code is used like ColorUtils.pickColor(onColorPicked, this);
Check out this post. Looks like you can't trigger a click on an invisible color picker. That answer suggests giving the element an absolute position and placing it off screen, like so:
position:absolute;
left:-9999px;
top:-9999px;
I tried to replicate your case (for what I understood) : JSFIddle
I made some changes.
I moved the $('<input/>') in a property of the object ColorUtils and appended it to the DOM with absolute position and outside the screen.
(And also commented display:'hidden' because it's either display:none or visibility:hidden and as a CSS property, not Html attribute)
On right clic on the document I instantiate the picker (and register the callback + context) then add a button to the DOM to trigger the picker again.
Does it fulfill your requirements ?
I have a very large HTML page whereby an enterprise user is displaying thousands of database records as part of a batch-update/validation process.
Within the page I need to add tooltips to many of the elements. Previously we have used the trusty approach of doing this in the <head>:
$("elementID").mouseenter(function(){
// tool tip logic
// goes here
});
The problem is that this is adding tens of thousands of lines of JavaScript and causing massive performance problems. So, I am researching the differences of applying this at element level instead. So rather than having the above code for each element that requires a tooltip, I am declaring a single script block like this:
function ShowTooltip(ctrl, tooltip) {
var o = $(ctrl).offset();
var y = o.top;
var x = o.left;
$("#ttfloat").css({ top: o.top, left: o.left });
$("#ttfloat").html(tooltip);
$("#ttfloat").show();
}
function HideToolTip() {
$("#ttfloat").hide();
}
And then firing this using the following approach for each respective element:
<div id="ttfloat"> </div>
<p>Tool tip <span id="lbl1" runat="server" onmouseover="ShowTooltip(this, 'Tip Text');" onmouseout="HideToolTip();">appears here</span></p>
The problem is that when hovering over the <span> elements, there is a flicker of the tooltip element as the browser fires onmouseover repeatedly. I read on other SO solutions that JQuery mouseenter is the way to go to solve this, but can only find examples that wire up the events in the head. Can it be done in-line in the element, or is there a better way altogether? The solution must work with older browsers and be standards compliant.
See JSFiddle
How about something like this:
<span data-tooltip-text="Tip text here">blah blah</span>
And then:
$("[data-tooltip-text]").on({
mouseenter : function() {
var o = $(this).offset();
var tooltip = $(this).attr("data-tooltip-text");
$("#ttfloat").css({ top: o.top, left: o.left })
.html(tooltip)
.show();
},
mouseleave : function() {
$("#ttfloat").hide();
}
});
Demo: http://jsfiddle.net/szCU2/2/
I'd suggest you offset the vertical position of the tooltip a little bit, so that it doesn't completely cover the element that you're hovering over (which is clunky looking, and can potentially cause a mouseleave event since the mouse is then over the tooltip):
o.top + 18; // or whatever offset works for you
Demo: http://jsfiddle.net/szCU2/3/
If the behavior is the same in all of them, you should use a class selector instead of an id selector and simply add that class to all of your divs. Then you just need that code once rather than having a copy of it for every single div. Store the data somewhere useful (like a custom attribute for the div) and use that in your code.
html:
<div id="blah" class="divWithTooltip" data-custom-attribute="some tooltip text">
javascript:
$('.divWithTooltip')
.on('mouseenter', function() {
someMethodToDoYourTooltipStuff( $(this).attr('data-custom-attribute') );
})
.on('mouseout', function() {
someMethodToHideYourTooltip();
});
When using tinyMCE in a jqueryUI modal dialog, I can't use the hyperlink or 'insert image' features.
Basically, after lots of searching, I've found this:
http://www.tinymce.com/develop/bugtracker_view.php?id=5917
The weird thing is that to me it seams less of a tinyMCE issue and more of a jqueryUI issue since the problem is not present when jqueryUI's modal property is set to false.
With a richer form I saw that what happens is that whenever the tinyMCE loses focus, the first element in the form gets focus even if it's not the one focused / clicked.
Does some JavaScript guru have any idea how I might be able to keep the dialog modal and make tinyMCE work?
This fixed it for me when overriding _allowInteraction would not:
$(document).on('focusin', function(e) {
if ($(event.target).closest(".mce-window").length) {
e.stopImmediatePropagation();
}
});
I can't really take credit for it. I got it from this thread on the TinyMCE forums.
(They have moved their bugtracker to github. tinymce/issues/703 is the corresponding github issue.)
It seems there are no propper solution for this issue yet. This is kind of a hack but it really worked for me.
Every time you open the Dialog remove the text area and re add it like following,
var myDialog = $('#myDialog');
var myTextarea = myDialog.find('textarea');
var clonedTextArea = myTextarea.clone(); // create a copy before deleting from the DOM
var myTextAreaParent = myTextarea.parent(); // get the parent to add the created copy later
myTextarea.remove(); // remove the textarea
myDialog.find('.mce-container').remove(); // remove existing mce control if exists
myTextAreaParent.append(clonedTextArea); // re-add the copy
myDialog.dialog({
open: function(e1,e2){
setTimeout(function () {
// Add your tinymce creation code here
},50);
}
});
myDialog.dialog('open');
This seems to fix it for me, or at least work around it (put it somewhere in your $(document).ready()):
$.widget('ui.dialog', $.ui.dialog, {
_allowInteraction: function(event) {
return ($('.mce-panel:visible').length > 0);
}
});
I am normally used to "window.open" to open a popup window into a new URL. How can open a window into a new URL, shadow out/grey out the current window, and on close remove the shadow background.
Is it best to use jQuery to do this? Could I use the default libraries without use jquery plugins?
I want to do something like this and then "disable" my shadow on unload. Hopefully that uses core jQuery libraries or standard javascript calls. I want to avoid using any plugins besides jQuery.
var popup = window.open('http://google.com', 'popup');
showShadow();
$(window).unload(function() {
if(!popup.closed) {
disableShadow();
}
});
Basically, you can open the popup and set that window the beforeunload. In short, something like this:
popup = window.open("", "name", "width=400, height=300")
popup.onbeforeunload = function() { $('#shadow').hide();}
I created a fiddle for you.
http://jsfiddle.net/DDksS/
So you want to build your own modal box using jQuery instead of using an existing plugin? ...OK, let's play (as it was already pointed out, using popups is not a user-friendly solution):
Your check list :
- the trigger
- the shadow layer
- the modal box size and position
- add content to modal and display it along the shadow
1) The trigger is a simple html link to open the content inside the modal
open url
... we will pass the size of the modal via data-width and data-height (HTML5) attributtes.
2) The shadow layer is the html structure that we will append to the body after the trigger. We can set the structure in a js variable
var shadow = "<div class='shadow'></div>";
3) As we mentioned, the size of the modal is set through some data-* attributes in the link. We would need to do some math
var modalWidth = $(this).data("width");
var modalHeight = $(this).data("height");
var modalX = (($(window).innerWidth()) - modalWidth) / 2; // left position
var modalY = (($(window).innerHeight()) - modalHeight) / 2; // top position
NOTE : $(this) is our trigger selector .myModal that we'll get inside an .on("click") method later on. BTW, the .on() method requires jQuery v1.7+
4) Now we need to create the modal's html structure and pass the content href. We'll create a function
function modal(url) {
return '<div id="modal"><a id="closeModal" title="close" href="javascript:;"><img src="http://findicons.com/files/icons/2212/carpelinx/64/fileclose.png" alt="close" /></a><iframe src="' + url + '"></iframe></div>';
}
... as you can see, our structure contains a close button to remove the modal and the shadow layer. The function also gets a parameter when is called (url) which allows to set the src attribute of the iframe tag.
NOTE : we have to use the iframe tag to open external urls, however we should always consider the same origin policy and other security restrictions when using iframes.
So now, we need to put together all the events after we click on our .myModal trigger, which are appending both the shadow and the modal box to the body and to remove them when we click on the close button so
$(".myModal").on("click", function(e) {
e.preventDefault();
// get size and position
modalWidth = $(this).data("width");
modalHeight = $(this).data("height");
modalX = (($(window).innerWidth()) - modalWidth) / 2;
modalY = (($(window).innerHeight()) - modalHeight) / 2;
// append shadow layer
$(shadow).prependTo("body").css({
"opacity": 0.7
});
// append modal (call modal() and pass url)
$(modal(this.href)).appendTo("body").css({
"top": modalY,
"left": modalX,
"width": modalWidth,
"height": modalHeight
});
// close and remove
$("#closeModal").on("click", function() {
$("#modal, .shadow").remove();
});
}); // on
STYLE : of course we will need some basic CSS style to make our modal elements work properly:
.shadow {width: 100%; height: 100%; position: fixed; background-color: #444; top: 0; left:0; z-index: 400}
#modal {z-index: 500; position: absolute; background: #fff; top: 50px;}
#modal iframe {width: 100%; height: 100%}
#closeModal {position: absolute; top: -15px; right: -15px; font-size: 0.8em; }
#closeModal img {width: 30px; height: 30px;}
* SEE DEMO *
BONUS : you could also bind a keyup event to close the modal using the escape key
$(document).keyup(function(event) {
if (event.keyCode === 27) {
$("#modal, .shadow").remove();
}
}); //keyup
LAST NOTE : the code is subject to many improvements and optimization but is a basic layout of what many lightboxes do. My last recommendation : use fancybox for more advanced functionality ... sometimes it doesn't worth the effort to re-invent the wheel ;)
Using Javascript to create new popup windows is so 1990's, not to mention not very user-friendly. What you're looking for, both UI-wise and looks-wise is a modal dialog; there's billions of examples and pre-packaged jquery snippets on how to create modal dialogs, and most client-side UI frameworks such as jQuery UI, YUI and Bootstrap have modal dialog functionality built-in. I'd recommend diving into those.
Try jquery plugins such as fancybox http://fancybox.net/
Basically, you need to attach an event listener to your new window to run the disableShadow() function in your webpage.
If you add this to your code I think it should work.
popup.unload(function() { disableShadow() });
Adapted From: Attach an onload handler on a window opened by Javascript
You should use the beforeUnload event of the window instance returned by the window.open() call, like this:
popup = window.open('relative_url', 'popup');
$(popup).bind('beforeunload', function() {
disableShadow();
});
Note that the URL must be on the same domain in order for the opener window to interact with the popup!
See the fiddle here: http://jsfiddle.net/hongaar/QCABh/
You can open a new window, and when it closes you can execute a function in the opener window.
I'll do a quick example by writing the script right into the new window, but you could also just include it in the HTML that is used for the new window if a link is supplied for the popup:
$("#popupBtn").on('click', openPopup); //using a button to open popup
function openPopup() {
$('#cover').fadeIn(400);
var left = ($(window).width()/2)-(200/2),
top = ($(window).height()/2)-(150/2),
pop = window.open ("", "popup", "width=400, height=300, top="+top+", left="+left),
html = '<!DOCTYPE html>';
html += '<head>';
html += '<title>My Popup</title>';
html += '<scr'+'ipt type="text/javascript">';
html += 'window.onbeforeunload = function() { window.opener.fadeoutBG(); }';
html += '</sc'+'ript>';
html += '</head>';
html += '<body bgcolor=black>';
html += '<center><b><h2 style="color: #fff;">Welcome to my most excellent popup!</h2></b></center><br><br>';
html += '<center><b><h2 style="color: #fff;">Now close me!</h2></b></center>';
html += '</body></html>';
pop.document.write(html);
}
window.fadeoutBG = function() { //function to call from popup
$('#cover').fadeOut(400);
}
Using a fixed cover that is faded in will also prevent any clicks on elements on the page, and you could even attach a click handler to the cover with pop.close() to close the popup if the cover is clicked, just like a modal would close if you clicked outside it.
One of the advantages of calling a function on the parent page from the popup is that values can be passed from the popup to the parent, and you can do a lot of stuff you otherwise could'nt.
FULLSCREEN_FIDDLE
FIDDLE
All you need is standard javascript function showModalDialog. Then your code will look like
var url = 'http://google.com';
showShadow();
var optionalReturnValue = showModalDialog(url);
//Following code will be executed AFTER you return (close) popup window/dialog
hideShadow();
UPDATE
As hongaar stated Opera does not like showModalDialog. And it does not fire on(before)unload when popup is closed either. To make workaround you need timer (window.setTimeout) to periodically check if window still exists. For further details look here
Why don't you just use jQuery UI? I know that you don't want another library but is rather extension of jQuery rather then another lib since it can live without it.
It have great deal of widget and every one of them can be changed,configured.
What is best that it can viewed with different themes, even you can create one with they're theme roller fast and easy, and it can be modularized. Just take what you need in current project.
Check this out:
http://jqueryui.com/dialog/#modal-form
It's really simple to use. With this you can open modal dialog with frame to different url. On close event you can do whatever you want.
Try ColorBox
its simple and easy to use
http://www.jacklmoore.com/colorbox
quick example:
<link rel="stylesheet" href="http://www.jacklmoore.com/colorbox/example1/colorbox.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://www.jacklmoore.com/colorbox/colorbox/jquery.colorbox.js"></script>
<script>
$(document).ready(function(){
//Examples of how to assign the ColorBox event to elements
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
});
</script>
<a class='iframe' href="http://google.com">Outside Webpage (Iframe)</a>
You can also try this out ...
http://fancyapps.com/fancybox/
Examples here
try http://thickbox.net/ in modal type, examples: http://thickbox.net/#examples
I've done this as well.
First off, some URLs simply WILL NOT WORK in an (iframe) modal window; I can't say if it'll work in the browser-supported native modal windows as I haven't tried this. Load google or facebook in an iframe, and see what happens.
Second, things like window onunload events don't always fire (as we've seen some people already).
The accepted answer version will also only work on a static page. Any reloading (even F5 on the page) will cause the shadow to hide. Since I can't comment on the accepted answer, I at least wanted this to be known for anyone else looking at these results.
I've taken a less technical approach to solving this problem in the past: polling.
http://jsfiddle.net/N8AqH/
<html>
<head>
<script type="text/javascript">
function openWindow(url)
{
var wnd = window.open(url);
var timer = null;
var poll = function()
{
if(wnd.closed) { alert('not opened'); clearInterval(timer); }
};
timer = setInterval(poll, 1000);
}
</script>
</head>
<body>
click me
</body>
</html>
See the link above for an example. I tested in IE, FF, and Chrome. My timer is every 1 second, but the effort on the browser is so low you could easily drop this down to 100 ms or so if you wanted it to feel more instant.
All you'd have to do in this example is, after calling window.open, call your "show shadow" function and instead of alerting when you close, call your "hide shadow" function and it should achieve what you're looking for.