How to center the selection in Ace Editor - javascript

I am trying to make it so that when the cursor or the selection (either or both) is moved either left of right in an ace-editor session, the scroll bar scrolls to keep the cursor or selected region in the center of the textarea.
There is a function called centerSelection()
this.centerSelection = function() {
var range = this.getSelectionRange();
var pos = {
row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2),
column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2)
}
this.renderer.alignCursor(pos, 0.5); };
which "Attempts to center the current selection on the screen."
which sounds like what i want but it doesn't seem to be doing anything.
there is also a keybinding for a command called "centerselection"
{
name: "centerselection",
bindKey: bindKey(null, "Ctrl-L"),
exec: function(editor) { editor.centerSelection(); },
readOnly: true}
but it has no Key input for windows, just says null. I don't have a mac so I can't try out Ctrl-L and I'm curious as to why it doesn't have a key input for windows aswell.
after playing with it some more i realise it is working it is just centering the selection row and not the selection column. So is there a way to get the selection to be in the center column as well as the center row?
I think it is because the alignCursor function only aligns the cursor row and not column
this.alignCursor = function(cursor, alignment) {
if (typeof cursor == "number")
cursor = {row: cursor, column: 0};
var pos = this.$cursorLayer.getPixelPosition(cursor);
var h = this.$size.scrollerHeight - this.lineHeight;
var offset = pos.top - h * (alignment || 0);
this.session.setScrollTop(offset);
return offset;
};

Well I think I figured it out, this code below works fine. :)
var cursorLeft = editor.renderer.$cursorLayer.getPixelPosition(0).left;
//gets distance between cursor and left side of textarea in pixels
var scrollerWidth = editor.renderer.$size.scrollerWidth;
//gets the width of the text area (that can be seen)
editor.renderer.scrollToX(cursorLeft - scrollerWidth/2);
//moves the scroller so that the left side i at the same point as the cursor minus half the width of the area that can be seen

Related

Set div width based on scroll position

The code:
http://codepen.io/anon/pen/EjrpMM
So, i'm working on an interesting problem. I am working with a 2000px HTML document, that has a modal placed ontop of it.
The width of the div lightbox is 80%, and it's sitting positioned fixed.
The goal is, when scrolling down the page, to control the width of the div based on the scroll position. At the bottom of the page, it's only a third in size.
I've had trouble figuring out the proper equation or formula for this, and was seeking help.
Currently, I've been trying to look at the window.pageYOffset, to add 2.5% to the div while increasing, and minus 2.5% when scrolling back up, to bring it back to it's 80% width.
However, something isn't working right. I was seeing if the community had any ideas to help solve the problem.
I'm not using any frameworks for this.
Here's my javascript:
var lightBox = document.getElementById('lightBox'),
count = 80,
num = window.pageYOffset;
document.addEventListener('scroll', function(e) {
var offset = window.pageYOffset;
num >= offset ? count += 2.5 : count -= 2.5;
num = offset;
lightBox.style.width = count + '%';
});
View the code here, in this codepen
http://codepen.io/anon/pen/EjrpMM
Thank you!
You just have to change
+= 2.5 and -=2.5 to += 0.7 and -= 0.7
When I checked your code I did this and it worked.
Scroll event fired once on scroll independently on how much you've scrolled. E.g. if you've scrolled 1px scrollbar, or scrolled 100px using mousewheel scroll event will be fired once.
So if you need stable results you will need to calculate your div width depending on scroll position (window.pageYOffset).
Check this codepen fork. I've assumed that in the end of page div width should be 50%.
Core part is:
var lightBox = document.getElementById('lightBox');
var upperBound = 80;
var lowerBound = 50;
var tickValue = (upperBound - lowerBound) / window.innerHeight;
document.addEventListener('scroll', function(e) {
var offset = window.pageYOffset;
var count = upperBound - offset * tickValue;
lightBox.style.width = count + '%';
});
Important note: for crossbrowser way to get innerHeight you can check this answer
This is a simple equation. Let f : scroll |-> f(scroll) be the function that gives you the width of your div. You want f(0) = 0.8, f(2000)= 1/3.
Let's say you want the progression to be linear so f(scroll) = a*scroll + b, you can easily deduce that b = 0.8 and a = (1/3 - 0.8)/2000 = -0.000233. Now for any scroll value, you can find the width of your div.
Now you can change the values when you want, f(scroll) = (minWidth-maxWidth)/pageLength * scroll + maxWidth.

How to snap jQuery UI draggable back to grid correctly after moving freely with no snapping

Using jQuery UI, I have some draggable DIVs. The DIVs snap to a 32x32 grid using the corresponding option grid: [32, 32].
The user can move around the DIVs in the grid but he can also hold down the Alt key to move them freely without snapping to the grid. When the Alt key is held down, I simply change the grid option to [1, 1] for that DIV.
Problem is that the next time that DIV is going to be moved, it will be aligned to a [32,32] grid but there will be an offset.
So what I need to do is:
DIV is dragged around on a 32,32 grid
User presses Alt and now instance is moved freely in a 1,1 grid
User places the DIV somewhere in an uneven coordinate like (103, 67)
Next time the DIV is dragged, first snap it correctly on the 32,32
grid and then start dragging (unless of course the user is pressing
Alt)
http://jsfiddle.net/SwHpa/2/ (ALT key doesn't work quite fluidly in this fiddle, you have to click on the empty space while holding ALT then drag the DIV to test free dragging)
$(document).ready(function(){
$(".draggable").draggable({
grid: [32, 32]
});
});
$(window).on('keydown', function(event){
if (event.keyCode == 18) {
$(".draggable").draggable({
grid: [2, 2]
});
}
});
$(window).on('keyup', function(event){
if (event.keyCode == 18) {
$(".draggable").draggable({
grid: [32, 32]
});
}
});
I'm new to stack overflow, first time ever commenting but maybe something like this would help: http://jsfiddle.net/SwHpa/4/
var myTop = jQuery(".draggable").css("top");
var myLeft = jQuery(".draggable").css("left");
var myNewTop = 0;
var myNewLeft = 0;
myNewTop = Math.floor(myTop / 32) * 32;
myNewLeft = Math.floor(myLeft / 32) * 32;
jQuery(".draggable").css({"top" : myNewTop, "left" : myNewLeft});
After you let go of the alt key, you'll need to re-calculate to the nearest "32" increment. I figured if you take your current top/left and divide it by 32, then Math.floor it to the nearest whole number and finally multiply it against 32 you'll be right back into the square boxes.

html table selection with colspan or rowspan

I have a table which user can select rows and columns with mouse and then merge the selected area into one cell, it works just like ms word table's behaviors.
However, when the table have rowSpan or colSpan, the selected area are not regular rectangle, so I'd like to extend the selection to an regular rectangle for the later mergence.
here is the example with rowspan and colspan, when the selection does not include the td has rowspan, it works fine, otherwise, the selection is wrong.
$('td').mousedown(function () {
$(this).closest('table').find('td').removeClass('selected');
var start = {
x: this.cellIndex,
y: this.parentNode.rowIndex
}
$(this).closest('table').find('td').mouseover(function () {
var x1 = Math.min(start.x, this.cellIndex);
var y1 = Math.min(start.y, this.parentNode.rowIndex);
var x2 = Math.max(start.x, this.cellIndex);
var y2 = Math.max(start.y, this.parentNode.rowIndex);
$(this).closest('table').find('td').each(function () {
var x = this.cellIndex;
var y = this.parentNode.rowIndex;
if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
$(this).addClass('selected');
} else {
$(this).removeClass('selected');
}
});
});
var self = this;
$(document).mouseup(function () {
$(self).closest('table').find('td').unbind('mouseover');
$(document).unbind('mouseup');
});
});
http://jsfiddle.net/uRd87/3/
Selection goes wrong when you have a cell with colspan > 1 because the cellIndex value of the cells after that cell change to adjust for the colspan taken by the previous cell. See the the image below.
This is what your cell selection logic does when you press the mouse down at top left corner of the cell with colspan=2 and drag mouse down to 3rd row (indicated by the red line):
Mouse down on top left corner of cell with colspan=2. Take the cellIndex and rowIndex value of the cell where selection started. Begin cellIndex=2 and rowIndex=0.
Drag the mouse down to 3rd row (indicated by the red line). Ending cellIndex=2 and rowIndex=2
Select cells between and including begin [cellIndex,rowIndex] and end [cellIndex,rowIndex]. In this case select cells [2,0],[2,1],[2,2]. That is where the problem is! Cell [2,1] has moved to the next column to adjust for the previous cell with colspan=2. Though that cell's cellIndex value is 2, you should treat it as if its cellIndex value is 3 and exclude it from selection.
I have found the reason and now I used a jquery plugin named cellPos to solve the cellIndex problem.
However, there still a problem, the selection area can be non-regular rectangle. see the image below.
the first image show the selection area, the arrow indicated the mouse direction.
the second image show what I really what.

jquery dynamic position change

I'm using this jquery color picker plugin http://www.eyecon.ro/colorpicker/ in my web application. I need to do some design tweaks. I'm gonna show some sample features on the application. Please look at this http://jsfiddle.net/FSDPH/8/ there is a movable box with accordions. In the color section, I've implemented that color picker plugin which I can't show in the jsfiddle. What I need is, when the color picker is selected and if the box is moved beyond the (document) section, the box and color picker palette should dynamically change its position inside the document area. I've succeeded in dynamically changing the box position but I can't make it work for the color picker palette.
Here is the jquery code: (for dymanically altering the box and colorpicker palette position)
var dwidth = $(document).width() - 225; // #box_bg width
$("#box_bg").draggable({
stop: function(event, ui) {
var npos = $("#box_bg").position();
if ( npos.left > dwidth)
{
$(".colorpicker").css("left","-133px!important");
$("#box_bg").css("left", dwidth+"px");
}
}
});
In the above code, $("#box_bg") is working when the box is moved beyond the document area. But it is not working for $(".colorpicker") the left property is not changing in the colorpicker.css file. Why is it so?
UPDATE
Here I've shown more clearly, please check this out :)
http://jsfiddle.net/rkumarnirmal/4GrsD/3/
Could anyone guide me?
Thanks!
The left property of the colorpicker is calculated in the plugin every it is shown. Until you change the plugin, the left property will always be calculated on the fly.
Here is the code from the plugin:
show = function (ev) {
var cal = $('#' + $(this).data('colorpickerId'));
cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
var pos = $(this).offset();
var viewPort = getViewport();
var top = pos.top + this.offsetHeight;
var left = pos.left;
if (top + 176 > viewPort.t + viewPort.h) {
top -= this.offsetHeight + 176;
}
if (left + 356 > viewPort.l + viewPort.w) {
left -= 356;
}
cal.css({left: left + 'px', top: top + 'px'});
if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
cal.show();
}
$(document).bind('mousedown', {cal: cal}, hide);
return false;
}

how do i get the x and y position directly under the left bottom side of the input rectangle?

I'm thinking of implementing a custom auto-complete feature so basically my idea now is that i will make an abs positioned div and give it the position here:
(image) http://i.stack.imgur.com/3c5BH.gif
So my question is with a variable referencing the textbox, how do i get the x and y position directly under the left bottom side of the input rectangle?
My script must work in latest versions of IE / FF / Safari / Opera / Chrome
I know i can use a library to do it, but no i'm interested in learning how do they do it (or maybe better ways)?
This question is a lot more complicated than it seems and involves getting the position of the element relative to the document. The code to do so can be pulled from the jquery source (http://code.jquery.com/jquery-1.6.1.js -- search for "jQuery.fn.offset")
in jQuery:
var node = $('#textbox'),
pos = box.offset(); // the complicated piece I'm using jQuery for
node.top += node.height(); // node.offsetHeight without jQuery
node.left += node.width(); // node.offsetWidth without jQuery
The answer can be extremely simplified if you don't care about FF2 or Safari3:
var box = document.getElementById('yourTextBox').getBoundingClientRect(),
left = box.left,
bottom = box.bottom;
x = x offset
y = y offset - ( textbox height +
padding-top + padding-bottom )
Good comments! For my scenario, there is always an offset parent (which is why I use position - http://api.jquery.com/position/). In hopes that it might help someone else wanting a quick fix, here's the code:
// I have a parent item (item) and a div (detail)
// that pops up at the bottom left corner of the parent:
var jItem = $(item);
var pos = jItem.position();
var marginTop = parseInt(jItem.css('margin-top'));
if (isNaN(marginTop)) {
marginTop = 0;
}
$(detail).css("top", pos.top + jItem.outerHeight() + marginTop)
.css("left", pos.left);
$(detail).show();
Just give the box a defined width and height. Then, get its top and left property and add it with the width and height. Simple. I am gonna give you Pseodocode.
<STYLE>
object{width: 100px; height: 20px;}
</STYLE>
<SCRIPT>
x = object.left;
y = object.top;
x = x + object.width;
y = y + object.height;
</SCRIPT>

Categories

Resources