CKEditor 4 - Dialog/Modal position within iframe - javascript

I'm trying to position the dialog/modal window of CKEditor within my iframe but it seems to want to default to going middle center of my window. In the case of the site I'm working on, the iframe in question is 1000+ px in height, so the modal is way too far down the page and is causing confusion.
Based on this post (ckeditor dialog positioning) I have added the following code to my config file
CKEDITOR.on('dialogDefinition', function(e) {
var dialogName = e.data.name;
var dialogDefinition = e.data.definition;
dialogDefinition.onShow = function() {
var x_pos = this.getPosition().x;
var y_pos = 10;
this.move(x_pos, y_pos); // Top center
};
});
Which works great on initial load, but in the case of a hyperlink in the editor, once you change the "type" (URL, email, etc) it seems that the dialog content refresh also causes a recalculation of the dialog position, which throws it back to the middle center of the window.
So bottom line is I want to make all dialogs stick to the top (maybe 20px offset) and center of my window regardless of the iframe height and have it stay there through a dialog refresh, but not finding much supporting documentation to help with that.
Example of this in action here. Click on the link icon and the dialog appears at the top of the page. Change the "type" from URL to Link and the modal will jump to the middle of the 10000 px height iframe the page is inside of
Further Edit
So the accepted answer worked perfect, but there was still an issue that the hyperlink dialog would now show all fields on initial load, and then once you changed the link type it would remove fields not related to the current selection. So looking further into the documentation, it looks like the correct way to call a dialog is as follows:
CKEDITOR.on('dialogDefinition', function(e) {
var dialogName = e.data.name;
var dialog = e.data.definition.dialog;
dialog.on('show', function () {
var x_pos = this.getPosition().x;
var y_pos = 10;
this.move(x_pos, y_pos); // Top center
this._.moved = 1;
});
});

It looks like the dialog won't try reposition itself if the user has moved it. It tracks this using a variable called moved. You can trick it into thinking it has been moved by setting this variable to 1:
dialogDefinition.onShow = function() {
var x_pos = this.getPosition().x;
var y_pos = 10;
this.move(x_pos, y_pos); // Top center
this._.moved = 1;
};
Note that as per this post, there are negative side-effects to overriding the onShow method that you may want to consider.

Another option (besides the one the user1620220 gave), and an option to re-set the position of the dialog even on layout change is to override the layout function of the dialog:
CKEDITOR.on('dialogDefinition', function(e) {
var dialogName = e.data.name;
var dialogDefinition = e.data.definition;
// Save the old layout function
dialogDefinition.dialog.oldLayout = dialogDefinition.dialog.layout
dialogDefinition.dialog.layout = function() {
// first we need to call the layout function
dialogDefinition.dialog.oldLayout();
// Now we can reposition the way we want:
var x_pos = this.getPosition().x;
var y_pos = 10;
this.move(x_pos, y_pos); // Top center
}
dialogDefinition.onShow = function() {
var x_pos = this.getPosition().x;
var y_pos = 10;
this.move(x_pos, y_pos); // Top center
};
});

Related

Unable to get form's panel x and y coordinates and to set them from a cookie on load

I have a form with a panel inside:
<form id="form" action="/accent/login/enter/">
<div draggable="true" id="panel" title="">
...
The panel is draggable and resizable and has two events:
$('#panel').bind("resize",function(event){
saveform();
})
.bind("drag",function(event){
saveform();
});
The function saveform is supposed to save form's panel width and height and besides x and y coordinates. It saves it in a cookie. I want this behaviour, so that when a user refreshes a page, then the form's panel is positioned and aligned according to those properties saved in a cookie. The first problem I face is that x and y coordinates are recalculated only once, that is when a user drags and drop the form for the first time. As for height and width they are recalculated correctly. And the second problem I face is that I'm unable to set x and y coordinates of a form - I do not know whether the method I use is appropriate or not. So, my saveform function looks like this:
var saveform = function(){
var pos = $('#form:first').offset(), // recalculated only once
height = $('#panel').height(), // it is saved ok
width = $('#panel').width(), // it's ok too
data = {top:Math.round(pos.top),left:Math.round(pos.left),
height:Math.round(height),width:Math.round(width)};
$.cookie('form',data);
}
And this is the method I use to set x and y coordinates of the panel:
var data = $.cookie('form');
$('#panel').position({
of:$('#body'),
my:'left top',
at:'left top',
offset:data.left + " " + data.top
})
Well, I found a solution. Now, my saveform function looks like this:
var saveform = function(){
var pos = $('div.panel').offset(), //I added class="panel" to main div
height = $('#panel').height(),
width = $('#panel').width();
$.cookie('form',{top:pos.top,left:pos.left,
height:height,width:width});
}
And I set panel's x and y coordinated like this:
var data = $.cookie('form');
$('#panel').height(data.height).width(data.width)
.offset({top:data.top,left:data.left});
So, the main trick was to apply offset method in appropriate manner.

Jquery Position not honoring on first call

I am trying to make my autocomplete menu open above the input box if there is not enough space below the input box to display the menu. The code works fine except for on the initial render.
This means that it always displays at the bottom when:
1. Start searching
2. Click in the field and fire the search for the existing text in field
I have it output the position.my and position.at contents and they both are correct for "above" placement but it still displays below the input box.
I have the function called resize that is binded to window scroll and resize also. The moment you scroll the page, the menu gets positioned correctly. My suspect is that it is positioning before fully rendering.
Code
_renderMenu function hook
// Autocomplete _renderMenu function
$(autocomplete_object)._renderMenu = function( ul, item ) {
var that = this;
jQuery.each( items, function( index, item ) {
that._renderItemData( ul, item );
});
// Make sure the menu is now shown to calculate heights and etc (menu is now rendered, position rendering next)
jQuery(ul).show();
autocomplete.resize(ul, options);
autocomplete.create_dropdown_handlers(ul, options);
}
Resize Function
// Resize function
function resize( ul, options ) {
var height;
// If the height of the results is smaller than the space available, set the height to the results height
var ul_height = 0;
jQuery(ul).find('li').each(function(i, element){
ul_height += jQuery(element).height();
});
// Make the height the full height available below the input box but above the window cut off
// Move the dropdown above the input box if there is not enough room below the input box
var $parent = jQuery("#" + options.name);
var padding = 25; // arbitrary number to prevent dropdown from hitting the window border in either direction
var bottom_distance = autocomplete.getViewportHeight() - ($parent.offset().top + $parent.height()) - padding;
var bottom_limit = 200;
var ul_position = {
my: "left top",
at : "left bottom",
of: $parent,
collision: 'none'
};
height = bottom_distance;
if (bottom_distance < bottom_limit) {
var top_distance = $parent.offset().top - padding;
height = top_distance;
// ----- It is getting here fine! -----
ul_position.my = "left bottom";
ul_position.at = "left top";
}
// We have room to show the entire dropdown results without a scrollbar
if (ul_height < height) {
height = 'auto';
}
// Position below or above parent depending on space
jQuery(ul).position(ul_position);
jQuery(ul).css({height: height == 'auto' ? height : height + 'px'});
}
TLDR:
Jquery position is set to show above input field, but it still shows below?
I ended up having to update the autocomplete object's position value as well as the ul position. I believe the issue was that the initial render would inherit the autocomplete's position variable (Which defaults to showing below the input box).
Here is the new line:
// In the resize function after jQuery(ul).position(ul_position);
$parent.autocomplete("option", "position", ul_position); // Now the rendering is correct!
Resize function addition
function resize (ul, options) {
...
calculate the height and position requirements
...
jQuery(ul).position(ul_position);
$parent.autocomplete("option", "position", ul_position); // <-- Addition to honor position for rendering
}

Change margin-top as user scrolls

I am trying to get a div to scroll up at the same amount of pixels as the user scrolls down the page. For example, in Google Chrome when using the mouse wheel, it scrolls down in about 20px intervals. But when you scroll down using the handle, the scrolling amount varies.
Here is my code so far:
var scrollCtr = 50;
$(window).scroll(function(){
scrollCtr = scrollCtr - 20;
$('div.nexus-files').css('margin-top', scrollCtr + 'px');
});
There are a few problems with this:
The user scrolling varies
It needs to subtract from margin-top if scrolling down and add to margin-top if scrolling up
Here is an example:
http://www.enflick.com/
Thanks for the help
You're doing it the wrong way, what you are trying to do should be done using position: fixed on div.nexus-files
div.nexus-files{position: fixed; top: 0;}
but anyway - if you still want to know what you can do with the scroll event - you better get to scrollTop of the document and set the margin-top to the same value
window.onscroll = function(event){
var doc = document.documentElement, body = document.body;
var top = (doc && doc.scrollTop || body && body.scrollTop || 0);
document.getElementById('nexus-files_id').style.marginTop = top+'px';
}
I'm using pure Javascript instead of jQuery because of the overhead that might be crucial when the browser need to calculate stuff in a very short amount of time (during the scrolling). [this can be done even more efficient by storing reference to the element and the doc... but you know..)
I used id based selector to get the specific element instead of class based
AND I SAY AGAIN - this is not how you should do what you were trying to do
Why not using the actual scroll offset as reference or position ?
// or whatever offset you need
var scrollOffset = document.body.scrollTop + 20;
// jQuery
var scrollOffset = $("body").scrollTop() + 20;
Finally Got it
Here is the code I used to accomplish the task.
Most of the code is from http://enflick.com and I modified it to work with my individual situation.
jQuery(window).load(function(){
initParallax();
});
// parallax init
function initParallax(){
var win = jQuery(window);
var wrapper = jQuery('#wrapper');
var bg1 = wrapper.find('.nexus-files');
var koeff = 0.55;
if (bg1.length) {
function refreshPosition(){
var scrolled = win.scrollTop();
var maxOffsetY1 = 450;
var offsetY1 = scrolled * koeff;
var offsetY2 = scrolled * koeff - (maxOffsetY1 * koeff - offsetY1);
if (offsetY1 <= maxOffsetY1 * koeff - offsetY1) {
bg1.css("margin-top", +-offsetY1+"px");
//alert(+-offsetY1+"px");
}
}
refreshPosition();
win.bind('resize scroll', refreshPosition);
}
}

Javascript dialog is programmed to move when the page scrolls, but it flickers. Can this be fixed?

I've written some jQuery code to display a box with data in the corner of the users' web browser. I'm using the .scroll event to make the box stay in the corner as the user scrolls up and down the page. Let me emphasize that I am not using jquery-ui dialog.
The only problem is that the box flickers as the page scrolls. I'm afraid that there will be no cross-browser solution to this problem as the different browsers seem to behave differently with scrolling. Barring a cross-browser solution, an IE solution would be nice (My web application is designed to be used by a specific group of about 100 users in my organization.)
Here are snippets of the relative code:
ExternalScroll: function () {
LittleBlackBook.setPosition();
}
setPosition: function () {
var scrollPosition = $(self).scrollTop();
var cssTop = LittleBlackBookStatic.determineCssTop(this.height, this.isTop, this.vOffset, scrollPosition);
var cssHeight = LittleBlackBookStatic.determineCssHeight(this.height);
var cssLeft = LittleBlackBookStatic.determineCssLeft(this.width, this.isLeft, this.hOffset);
var cssWidth = LittleBlackBookStatic.determineCssWidth(this.width);
this.jQueryObj.css('top', cssTop);
this.jQueryObj.css('height', cssHeight);
this.jQueryObj.css('left', cssLeft);
this.jQueryObj.css('width', cssWidth);
}
var LittleBlackBookStatic = {
determineCssTop: function (height, isTop, vOffset, vScroll) {
var windowHeight = $(self).height();
var scrollPosition = $(self).scrollTop();
var newModalTop = isTop ? vOffset + vScroll : windowHeight - height + vScroll - vOffset;
return newModalTop + 'px';
},
determineCssHeight: function (height) {
return height + 'px';
},
determineCssLeft: function (width, isLeft, hOffset) {
var windowWidth = $(self).width();
var newModalLeft = isLeft ? hOffset : windowWidth - width - hOffset;
return newModalLeft + 'px';
},
determineCssWidth: function (width) {
return width + 'px';
}
} // end LittleBlackBookStatic
I'm using jQuery to look up the scroll position as the page scrolls and change the CSS.
Is there a better way; a way that will make it scroll without flickering? If no, then why not?
You should use fixed positioning for that box instead instead of animating it to keep it in the corner.
You'll use less javascript and avoid flickering that comes with animation.

Proper way to center pop window with Javascript and pass html

Goal: quick and dirty app (client side only) to grab some arguments from one page and put results onto a new page, which can be printed and then closed. Arguments on the original page then can be changed and new page popped.
Used this as a starting point:
https://developer.mozilla.org/en/DOM/window.open
http://www.yourhtmlsource.com/javascript/popupwindows.html
Proof of concept(final version will have about 10 inputs/args)
HTML fragment
<input type="text" id="x">
<form>
<input type=button value="Calculate" onClick="javascript:genResults()">
</form>
JS
function dirtypop(arg)
{
var popwin=window.open('','name','height=300,width=400,status=1,center=1');
popwin.document.write('<html><head><title>Square</title>');
popwin.document.write('</head><body>');
popwin.document.write('<h1>Squared plus one is: '+arg+'</h1>');
popwin.document.write('<p>Close this window</p>');
popwin.document.write('</body></html>');
popwin.document.close();
};
function genResults()
{
x = document.getElementById('x').value;
if (x == parseFloat(x))
{
dirtypop(x*x+1);
}
};
This works(tested on FF3.5 and Chrome), except new window does not pop into center. How to center it? Mozzila says needs chrome=yes and talks about UniversalPrivilege scripts, what kind of beasts are those?
Anything else that can be improved?
Here's one of my custom cross-browser scripts that can be reused dynamically to center any popped window of any size on the screen:
// here's the script
function popWindow(url,winName,w,h) {
if (window.open) {
if (poppedWindow) { poppedWindow = ''; }
//GET SIZE OF WINDOW/SCREEN
windowW = w;
windowH = h;
var windowX = (screen.width/2)-(windowW/2);
var windowY = (screen.height/2)-(windowH/2);
var myExtra = "status=no,menubar=no,resizable=yes,toolbar=no,scrollbars=yes,addressbar=no";
var poppedWindow = window.open(url,winName,'width='+w+',height='+h+',top='+windowY+',left=' + windowX + ',' + myExtra + '');
setTimeout(refreshThis,3000);
}
else {
alert('Your security settings are not allowing our popup windows to function. Please make sure your security software allows popup windows to be opened by this web application.');
}
}
// and you would call it like this:
popWindow('http://www.myurl.com/','myPoppedWindowName','500','400');
// With this example call you would pop a window with a url of http://www.myurl.com/
// which is given the name of myPoppedWindowName
// and a width of 500px along with height of 400px
// which gets centered on the screen according to these size parameters
This will do the trick considering it truly is a cross-browser implementation, including reverse compatibility to browsers in place back in 2001. It also contains a check to make sure the end-user has popup windows enabled.
You'll need to set the top and left properties instead of center=1.
var left = (screen.width - windowWidth) / 2;
var top = (screen.height - windowHeight) / 2;

Categories