I previously did some popups / dialogs that I've now got regression error in () and want to recode to use JQuery for the DIVs / popups / dialogs. Moving to Jquery will be an advantage since we can enable repositioning and resize for dialogs / popups which we can't if the popup is just a DIV which places itself over the other elements.
Now I wonder what is the "best" way to make popups / dialogs / DIV appear with JQuery? I'd rather not add a plugin and only include the basic JQuery file. can you tell me how to do it?
The current page makes something like a popup but it is not repositionable.
The way I would do this is create a .popup class that contains the basic layout features for the popup. Then add this class to a hidden <div> at the top of the page.
Then when a popup is needed, attatch the draggable and resizable attributes of jQuery to it. After that, load the popup's content with a .get() request from a page dedicated for popup content and then .show() it.
Example
CSS
.popup
{
display:none;
position:absolute;
// some other nice styling features
}
HTML
<body>
<div class='popup'></div>
...
page content
...
</body>
Javascript
function popup(){
// for the draggable you may want to specify the drag handle like only the title of the popup
var popup = $('.popup');
popup.draggable();
popup.resizable();
$.get('/getPopup.php?action=theKindOfPopupRequested', function(data) {
popup.html(data);
popup.show('fast');
});
}
Sources:
http://jqueryui.com/demos/resizable/
http://jqueryui.com/demos/draggable/
Here's a rudimentary dialog plugin:
http://jsfiddle.net/pjUUQ/
(function($) {
var dialogHTML = '<div class="dialog"></div>';
$.openDialog = function(opts) {
// Create the DIV for dialog without inserting into DO
var dialog = $(dialogHTML);
dialog.appendTo('body');
// Give dialog some basic CSS
dialog.css({
position: 'absolute', // positioned
'z-index': Math.pow(2,32) // make it sit on top
});
// Position the dialog on the screen
var horizOffset = ($(window).width() - opts.width || dialog.outerWidht()) / 2;
var vertOffset = ($(window).height() - opts.height || dialog.outerHeight()) / 2;
dialog.css({
left: horizOffset,
right: horizOffset,
top: vertOffset,
bottom: vertOffset
});
// Return dialog object to make it chainable
return dialog;
};
}(jQuery));
$.openDialog({width: 200, height: 100}).append('hello world');
You can certainly add a lot to it, like handling key events to close on Esc, adding a titlebar with the buttons. But you probably already know how to do these things anyway.
Few things to note when creating dialogs:
Set a high-enough z-index so that dialog is always on top
Append the dialog element to BODY
In my experience, performance is somewhat better if the dialog HTML isn't always present on the page. This goes against graceful degradation, but the lighter the DOM tree, the faster the app seems to go. So it's best to add the dialog element to the tree as needed.
EDIT: Note that my dialog plugin does not expect you to have a predefined HTML on the page. It just conjures up a div. So, you don't select an element and convert it to a dialog. Instead, you create one anew.
Related
I have a table sorter html page, the sample is here.
$('table').tablesorter({
theme: 'blue',
widgets: ['zebra', 'scroller'],
widgetOptions: {
scroller_height: 400
}
});
How can I make the bottom button visible even when the windows height is very small (say, can only show one or two rows)? Ideally scroller_height can be some type like $(window).height()/2 and it can automatically update when the window is resized.
The expected is that even when the window is small, the bottom button appears in the screen without scroll action.
If you want to make the scroller window dynamically adjust its height, there are two demos on the main wiki page under Widgets > Scroller.
http://jsfiddle.net/Mottie/txLp4xuk/2/
http://jsfiddle.net/Mottie/abkNM/8037/
Essentially, all you need to do is adjust the outer scroll window height
$('.tablesorter-scroller-table').css({
height: '',
'max-height': height + 'px'
});
Here is the demo you shared updated, and has a minimum height set to 100px.
I'd say that there are a few ways to achieve what you want, and one easy way is to:
create a function that checks the visibility of your table versus the viewport;
Code below:
function checkVisible() {
var bottom_of_table = $("#mytable").offset().top + $("#mytable").outerHeight();
var bottom_of_screen = $(window).scrollTop() + $(window).height();
if(bottom_of_screen > bottom_of_table){
$("#buttons-container").removeClass('bottom-fixed');
}
else {
$("#buttons-container").addClass('bottom-fixed');
}
}
If it exceeds the viewport, add a CSS class to your buttons container that fixes it to the bottom of the screen. Otherwise, remove this class and display the button container normally, at the bottom of the table.
You'd want to run this function-check on load and on window resize, as follows:
$(document).ready(function() {
checkVisible();
$(window).on('resize', checkVisible);
});
I've updated your fiddle: http://jsfiddle.net/12nt19vg/12/show/
Try resizing the window and let me know if this is the behavior you're looking for.
EDIT: Incorporating your additional spec in the comments, I've added an outer div to your buttons container and modified your CSS to visually create the effect that I think you're looking for.
Please take a look at this fiddle: http://jsfiddle.net/12nt19vg/27/show/
We would like to have a greater control of where and how we position the tinymce toolbar. We found this option fixed_toolbar_container which solves a lot for us but brings us an anoying problem. The documents say the fixed_toolbar_container (http://www.tinymce.com/wiki.php/Configuration:fixed_toolbar_container) can be used to have a fixed toolbar. But we actually would like to use it to be absolute so we can position it relative to it's container.
I created a JS Fiddle to demonstrate the problem: http://jsfiddle.net/ronfmLym/2/. When you open the toolbar by clicking on the text the toolbar will be positioned absolute. When you open a submenu (i.e. by clicking on "file") a submenu will open. Now when you start scrolling the submenu won't stick to the toolbar. This is because these submenu's get the mce-fixed class because we set the fixed_toolbar_container property.
<div class="element">
<div class="toolbar-container"></div>
<div class="content">
<p>Text</p>
</div>
</div>
Is there any way to make the submenu's stick to the toolbar when positioned absolute and scrolling? Keep in mind that we are switching to a fixed positioning when the toolbar is going off screen.
We thought we could maybe fix it by modifying the container element of de submenu's by using the piece of code below and overwriting the top-position of the submenu's and setting the positioner to absolute with css. But that seems to mess up the tooltips and tinymce doesn't recalculate the "left" css-property of the submenu's so the position in still off.
tinymce.ui.Control.prototype.getContainerElm = function() {
return document.getElementById('toolbar-container');
};
The only corresponding question I could find on stackoverflow was this one: TinyMCE push down submenus using fixed_toolbar_container, no answers there.
Tried wrapping the toolbar in a div and using position:relative; to try and hack it together, but didn't cooperate this time.
It appears that the toolbar actually is accounting for its position at the time of click. So your only conflict is if the opened toolbar is position:absolute and then changes to position:fixed or vice versa.
Your best [manual] bet would be to call a function at the same time that you change the position of the toolbar that:
Detects if any menus are open.
Changes the toolbar position.
Reopens the menus that were open.
The lazy (discouraged) fix would be to close all submenus whenever the position changes. This will fix the layout, but it will require the user to click once again to bring the menu back.
Sorry this isn't a silver bullet answer :(
This answer follows Brian John's suggestion:
I'm using this method to position any open mce-floatpanel (This is typescript, but it shouldn't be too hard to convert to ES or whatever you need.):
positionTinyMceDropdowns() {
// TODO: You'll need to replace all occurrences
// of this.mceWrapperElement with whatever is
// wrapping your TinyMCE. If you have only a
// single instance, you can just replace it
// with document
const button = <HTMLElement> this.mceWrapperElement.getElementsByClassName('mce-opened').item(0);
const items = document.getElementsByClassName('mce-floatpanel');
let wrapperNode: HTMLElement;
for (let i = 0; i < items.length; i++) {
const currentItem = <HTMLElement> items.item(i);
if (currentItem.style.display !== 'none') {
wrapperNode = currentItem;
break;
}
}
if (!wrapperNode || !button) {
return;
}
const styles = wrapperNode.style;
styles.display = 'block';
styles.position = 'absolute';
const bodyRect = document.body.getBoundingClientRect();
const buttonRect = button.getBoundingClientRect();
// get absolute button position:
let y = buttonRect.top - bodyRect.top;
y += 33; // toolbar line height;
styles.top = `${Math.floor(y)}px`;
}
The instances I found in which it needs to be called:
on window scroll (or if the editor is wrapped in a scrolling container, then whenever that scrolls)
on window resize (or if the editor is wrapped in a container that resizes without the window being resized, then whenever that container is resized)
So here's a sample for the simplest case in angular (again, adept to whichever js framework you're using):
import { HostListener } from '#angular/core';
// ...
#HostListener('window:resize', ['$event'])
#HostListener('window:scroll', ['$event'])
public onResize() {
this.positionTinyMceDropdowns();
}
Interestingly on iOS devices (and perhaps other mobile devices?) mce-floatpanel wasn't even positioned correctly after it had just been opened. So I had to add this:
tinymceConfig.setup = (editor: TinyMceEditor) => {
editor.on('init', () => {
const panel = this.mceWrapperElement.querySelector('.mce-tinymce.mce-panel');
if (panel) {
panel.addEventListener('touchend', () => {
this.positionTinyMceDropdowns();
});
}
});
};
I think the config setting fixed_toolbar_container is poorly explained in TinyMCE 6 documentation but when you correctly configure it, you'll find it will work much more nice (especially for inline mode) than the default configuration that tries to emulate position:sticky.
In practice, you want to fixed_toolbar_container set to a string that's CSS selector for the container, typically something like "#mycontainer".
After that, you can move the container element using its CSS properties, the TinyMCE user interface nicely follows around. (Modulo typical TinyMCE bugs, of course. For example, the submenus overflow to right with very narrow viewports.)
Note that TinyMCE positions stuff where it uses position:absolute relative to fixed_toolbar_container container and if you move that container around, in some cases you must execute editor.dispatch("ResizeWindow") to trigger TinyMCE to re-calculate the absolutely positioned elements.
See demo using custom container with position:sticky at https://jsfiddle.net/8bndv26t/1/.
I'm making a web application that uses Kinetic.js for some fancy
graphical functions, and I want to show a tooltip with some information about each element when the users hovers over it.
I've already figured out how to invoke a function on hover with Kinetic.js:
myKineticObject.on("mousemove", function() {
// Change content of tooltip depending on myKineticObject
// Set position of tooltip to cursor position
// Show tooltip
});
myKineticObject.on("mouseout", function() {
// Hide tooltip
}
I've decided to use the seemingly nice Opentip to show the tooltip.
The only problem is that Kinetic.js doesn't create any usable DOM elements to use as a target for opentip.
This is (roughly) what my HTML looks like:
<html>
<head><!-- Styles --></head>
<body>
<div id="container">
<canvas class = "kineticjs-buffer-layer">
<canvas class = "kineticjs-path-layer">
<canvas class = "myLayer1">
<canvas class = "myLayer2">
<!-- ... more layers -->
</div>
<!-- Scripts -->
</body>
</html>
Important to know is that these canvas elements all have the same width and height and stack on eachother. So they're unusable as targets.
So instead of using a DOM element to use as the target for my tooltip, I need to
manually show/hide and position the tooltip.
I've figured out how to do the showing and hiding like this:
var tooltip = new Opentip(
"div#container", //target element
"DummyContent", // will be replaced
"My Title", // title
{
showOn: null, // I'll manually manage the showOn effect
});
I now do the following:
myKineticObject.on("mousemove", function() {
tooltip.show();
});
myKineticObject.on("mouseout", function() {
tooltip.hide();
}
The only problem is that it just shows up at the top left of the page, and I can't find anything in the docs on how to position this thing manually.
Suggestions or ideas welcome. I'm also open to using a different tooltip library, if necessary.
Thanks!
It appears (with no knowledge of Opentip, besides a quick look at the docs) that you can set 'fixed' to true in the config. Since the target is null, the docs suggest fixed=true should make the tooltip appear at the mouse position, but not follow it once the mouse is moved around.
How does that sound?
I managed to solve the problem like this, for those of you who are looking for a solution too:
group.on("mousemove", function(event) {
tooltip.content = //change content
tooltip.show();
$("#opentip-1").offset({ left: event.offsetX, top: event.offsetY });
});
code: http://jsfiddle.net/MDnrk/7/
for those too lazy to click the link:
$j(function(){
// need to fix some things that CSS doesn't seem to be able to fix (esp cross browser)
fix_drawer_height()
$j(window).resize(function() {
fix_drawer_height()
});
})
function fix_drawer_height(){
var new_height = document.body.offsetHeight - $j(".redline_info_scrollable").offset().top;
$j(".redline_info_scrollable").css({
'max-height': new_height + 'px;'
});
}
now, in my app, fix_drawer_height() gets called on DOM ready, but it doesn't seem to be called in teh JS fiddle.. so I'm not sure if that is the correct medium to show this problem.
Still not sure what would couse the window resize listener to not set the max-height appropriately. =\
The goal is to have the scrollable div always stretch to the height of the window.
Normally I'd just use height: 100% in the CSS, but that isn't really cross browser, and won't work with how the div is positioned in my actual app.
thanks!
You can use this:
function fix_drawer_height() {
$('.redline_info_scrollable').height($(document).height());
}
and add it in your onload or onresize;
working code: http://jsfiddle.net/MDnrk/13/
I am trying to use jCarousel plugin for jQuery in order to provide my website users with scrollable (horizontal) content.
The content I am mentioning is basically user defined <li> elements, styled so that they have a feel and look of a tab. so basically I am trying to achieve the same effect of the tabs in pageflakes.com. As you may imagine, the users are creating tabs and providing tab names by themselves..
jCarousel needs you to specify a fixed width for the content e.g., all their examples are based upon images that have fixed height and width. but in my case I have not control over what the user will name his/her tab...making it impossible for me to guess the width of the total container div.
I have tried using a silly method such as guessing the width programatically assuming each letter being approx 5 pixels and multiplying 5 with the length of the word they have given as a name for a tab. even in this case, i needed to manipulate the css file dynamically which I am not sure how to do and even if it is feasable to do so..
Any solutions appreciated...
<lu>
<li class='MyTab' id='578'>This is my tab</li>
<li class='MyTab' id='579'>of which I can</li>
<li class='MyTab' id='580'>never guess</li>
<li class='MyTab' id='581'><img src='img/bullet_key.png' /> The length of</li>
</lu>
The above html is produced programatically through ajax_tabs_output.aspx, loaded into a javascript array and the jCarousel takes care of the rest..
function outputTabsArray() {
$.ajax({
url: 'ajax_tabs_output.aspx',
type: 'get',
data: 'q=array',
async: false,
success: function(out)
{
tabs_array = out;
}
});
}// end outputTabsArray
function mycarousel_itemLoadCallback(carousel, state)
{
for (var i = carousel.first; i <= carousel.last; i++) {
if (carousel.has(i)) {
continue;
}
if (i > tabs_array.length) {
break;
}
carousel.add(i, mycarousel_getItemHTML(tabs_array[i-1]));
}
};
/**
* Item html creation helper.
*/
function mycarousel_getItemHTML(item)
{
return '<div class="MyTab" id="' + item.tab_id + "'>" + item.tab_name + '</div>';
};
$('#mycarousel').jcarousel({
size: tabs_array.length,
itemLoadCallback: {onBeforeAnimation: mycarousel_itemLoadCallback}
});
The closest thing to what you want is probably jscrollhorizontalpane. I've never used it so I can't vouch for it's effectiveness as a solution to this specific problem.
This sort of widget shouldn't be to hard to make if you want to attempt it. I'll break down the approximate method I would use:
Make sure to use plenty of wrappers.
<div class="scrollable">
<div class="window">
<div class="space">
<ul class="tabs">
<li class="tab">...</li>
<li class="tab">...</li>
<li class="tab">...</li>
</ul>
</div>
</div>
←
→
</div>
What we'll be doing is shifting the "space" element back and forth inside "window" element. This can be done by setting position:relative to "window" and position:absolute to "space" and then shift it about using left:-??px, but I'll use the scrollLeft property.
Add some CSS.
.window {
overflow : hidden;
width : 100%;
}
.space {
width : 999em; /* lots of space for tabs */
overflow : hidden; /* clear floats */
}
.tabs {
float : left; /* shrink so we can determine tabs width */
}
.tab {
float : left; /* line tabs up */
}
This is just the basic stuff that the technique needs. Some of this stuff could be applied by jQuery,
Add events to window resize.
$(window)
.resize(function () {
var sz = $('.window');
var ul = sz.find('ul');
if ( sz.width() < ul.width() ) {
$('.scrollable a.left, .scrollable a.right').show();
}
else {
$('.scrollable a.left, .scrollable a.right').hide();
}
})
.trigger('resize');
Add events to scroll buttons.
$('.scrollable a.left').hover(
function (e) {
var sz = $('.window');
sz.animate({ scrollLeft : 0 }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
$('.scrollable a.right').hover(
function (e) {
var sz = $('.window');
var margin = sz.find('ul').width() - sz.width();
sz.animate({ scrollLeft : margin }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
Done!
The widths could also be calculated by looping through the "tab" elements and summing upp outerWidth. This is unnecessary if you have full control but might be a better choice for a full standalone plugin.
From what I can tell, you're trying make JCarousel do something it was never designed to do. Based on what I read on the JCarousel website it appears to be an image rotator.
What it sounds like you want is a tabbed interface. See JQuery UI Tabs for a demo and documentation on how to implement it.
If I'm totally wrong and all you're looking for is a tutorial on how to do proper CSS tabs, have a look at:
http://unraveled.com/projects/css_tabs/
Soviut,
You are actually quite right! I am trying to make JCarousel do something it wasn't designed for.
However, I also wouldn't like to use a tab plugin or any similar stuf as I NEED FULL CONTROL over my output. Such as injecting more elements into the tabs when needed such as double clicking, loading and many other etc. etc.
Actually what I am looking for a way to scroll horizontally the content within a div with arrows on the left and right.. To be more precise, I need the exact same structure of the tabs seen in www.pageflakes.com
The user will be able to create tabs by clicking on a link (or any other element for that matter), they will be able to inline edit its name, whenever they have more tabs then the length of the div, the buttons will be visible allowing them to slide inside the div, I will have events bound to their load, click and double click events.
To summarize I have everything ready and working except for the sliding/scrolling part. Its only I have to get help from you guys regarding how to achieve this functionality..
Kind regards,
What you're looking for isn't tabs, but draggable panels. One example can be found here, called JQuery Portlets. The related blog entry about Portlets can be found here.
You may also want to look into JQuery UI's Draggable, Droppable, and Sortable plugins.