Better shift+click handling

This commit is contained in:
Aris Feryanto 2011-06-28 09:33:09 +08:00
parent 22ff715452
commit 216b4e80b2
2 changed files with 110 additions and 95 deletions

View File

@ -613,6 +613,7 @@ function checkTransmitDump(theForm, theAction)
} // end of the 'checkTransmitDump()' function
$(document).ready(function() {
$('*').noSelect();
/**
* Row marking in horizontal mode (use "live" so that it works also for
* next pages reached via AJAX); a tr may have the class noclick to remove
@ -623,24 +624,71 @@ $(document).ready(function() {
if ($(e.target).is('a, img, a *')) {
return;
}
// XXX: FF fires two click events for <label> (label and checkbox), so we need to handle this differently
var $tr = $(this);
var $checkbox = $tr.find(':checkbox');
if ($checkbox.length) {
// checkbox in a row, add or remove class depending on checkbox state
var checked = $checkbox.attr('checked');
if (!$(e.target).is(':checkbox, label')) {
checked = !checked;
$checkbox.attr('checked', checked);
}
if (checked) {
$tr.addClass('marked');
if (!e.shiftKey || last_clicked_row == -1) {
// usual click
// XXX: FF fires two click events for <label> (label and checkbox), so we need to handle this differently
var $checkbox = $tr.find(':checkbox');
if ($checkbox.length) {
// checkbox in a row, add or remove class depending on checkbox state
var checked = $checkbox.attr('checked');
if (!$(e.target).is(':checkbox, label')) {
checked = !checked;
$checkbox.attr('checked', checked);
}
if (checked) {
$tr.addClass('marked');
} else {
$tr.removeClass('marked');
}
} else {
$tr.removeClass('marked');
// normaln data table, just toggle class
$tr.toggleClass('marked');
}
// remember the last clicked row
last_click_checked = checked;
last_clicked_row = $tr.index();
last_shift_clicked_row = -1;
} else {
// normaln data table, just toggle class
$tr.toggleClass('marked');
// handle the shift click
var start, end;
// clear last shift click result
if (last_shift_clicked_row >= 0) {
if (last_shift_clicked_row >= last_clicked_row) {
start = last_clicked_row;
end = last_shift_clicked_row;
} else {
start = last_shift_clicked_row;
end = last_clicked_row;
}
$tr.parent().find('tr:not(.noclick)')
.slice(start, end + 1)
.removeClass('marked')
.find(':checkbox')
.attr('checked', false);
}
// handle new shift click
var curr_row = $tr.index();
if (curr_row >= last_clicked_row) {
start = last_clicked_row;
end = curr_row;
} else {
start = curr_row;
end = last_clicked_row;
}
$tr.parent().find('tr:not(.noclick)')
.slice(start, end + 1)
.toggleClass('marked', last_click_checked)
.find(':checkbox')
.attr('checked', last_click_checked);
// remember the last shift clicked row
last_shift_clicked_row = curr_row;
}
});
@ -652,6 +700,22 @@ $(document).ready(function() {
});
})
/**
* True if last click is to check a row.
*/
var last_click_checked = false;
/**
* Zero-based index of last clicked row.
* Used to handle the shift + click event in the code above.
*/
var last_clicked_row = -1;
/**
* Zero-based index of last shift clicked row.
*/
var last_shift_clicked_row = -1;
/**
* Row highlighting in horizontal mode (use "live"
* so that it works also for pages reached via AJAX)
@ -2209,62 +2273,6 @@ $(function() {
menuResize();
});
/**
* For the checkboxes in browse mode, handles the shift/click (only works
* in horizontal mode) and propagates the click to the "companion" checkbox
* (in both horizontal and vertical). Works also for pages reached via AJAX.
*/
$(document).ready(function() {
$('.multi_checkbox').live('click',function(e) {
var current_checkbox_id = this.id;
var left_checkbox_id = current_checkbox_id.replace('_right', '_left');
var right_checkbox_id = current_checkbox_id.replace('_left', '_right');
var other_checkbox_id = '';
if (current_checkbox_id == left_checkbox_id) {
other_checkbox_id = right_checkbox_id;
} else {
other_checkbox_id = left_checkbox_id;
}
var $current_checkbox = $('#' + current_checkbox_id);
var $other_checkbox = $('#' + other_checkbox_id);
if (e.shiftKey) {
var index_of_current_checkbox = $('.multi_checkbox').index($current_checkbox);
var $last_checkbox = $('.multi_checkbox').filter('.last_clicked');
var index_of_last_click = $('.multi_checkbox').index($last_checkbox);
$('.multi_checkbox')
.filter(function(index) {
// the first clicked row can be on a row above or below the
// shift-clicked row
return (index_of_current_checkbox > index_of_last_click && index > index_of_last_click && index < index_of_current_checkbox)
|| (index_of_last_click > index_of_current_checkbox && index < index_of_last_click && index > index_of_current_checkbox);
})
.each(function(index) {
var $intermediate_checkbox = $(this);
if ($current_checkbox.is(':checked')) {
$intermediate_checkbox.attr('checked', true);
} else {
$intermediate_checkbox.attr('checked', false);
}
});
}
$('.multi_checkbox').removeClass('last_clicked');
$current_checkbox.addClass('last_clicked');
// When there is a checkbox on both ends of the row, propagate the
// click on one of them to the other one.
// (the default action has not been prevented so if we have
// just clicked, this "if" is true)
if ($current_checkbox.is(':checked')) {
$other_checkbox.attr('checked', true);
} else {
$other_checkbox.attr('checked', false);
}
});
}) // end of $(document).ready() for multi checkbox
/**
* Get the row number from the classlist (for example, row_1)
*/
@ -2656,4 +2664,35 @@ $(document).ready(function() {
if (elm.length > 0) {
codemirror_editor = CodeMirror.fromTextArea(elm[0], {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"});
}
})
});
/**
* jQuery plugin to cancel selection in HTML code.
*/
(function ($) {
$.fn.noSelect = function (p) { //no select plugin by Paulo P.Marinas
var prevent = (p == null) ? true : p;
if (prevent) {
return this.each(function () {
if ($.browser.msie || $.browser.safari) $(this).bind('selectstart', function () {
return false;
});
else if ($.browser.mozilla) {
$(this).css('MozUserSelect', 'none');
$('body').trigger('focus');
} else if ($.browser.opera) $(this).bind('mousedown', function () {
return false;
});
else $(this).attr('unselectable', 'on');
});
} else {
return this.each(function () {
if ($.browser.msie || $.browser.safari) $(this).unbind('selectstart');
else if ($.browser.mozilla) $(this).css('MozUserSelect', 'inherit');
else if ($.browser.opera) $(this).unbind('mousedown');
else $(this).removeAttr('unselectable', 'on');
});
}
}; //end noSelect
})(jQuery);

View File

@ -859,30 +859,6 @@
}
});
}
$.fn.noSelect = function (p) { //no select plugin by Paulo P.Marinas
var prevent = (p == null) ? true : p;
if (prevent) {
return this.each(function () {
if ($.browser.msie || $.browser.safari) $(this).bind('selectstart', function () {
return false;
});
else if ($.browser.mozilla) {
$(this).css('MozUserSelect', 'none');
$('body').trigger('focus');
} else if ($.browser.opera) $(this).bind('mousedown', function () {
return false;
});
else $(this).attr('unselectable', 'on');
});
} else {
return this.each(function () {
if ($.browser.msie || $.browser.safari) $(this).unbind('selectstart');
else if ($.browser.mozilla) $(this).css('MozUserSelect', 'inherit');
else if ($.browser.opera) $(this).unbind('mousedown');
else $(this).removeAttr('unselectable', 'on');
});
}
}; //end noSelect
})(jQuery);