mostly cross-browser compatibility enhancements

master
Jordi Boggiano 14 years ago
parent 59d1c9f489
commit d049139bd0
  1. 1
      README.mdown
  2. 124
      jquery.selections.js
  3. 88
      php-console.js

@ -34,6 +34,7 @@ Changelog
- Script execution is now done via an async js request, preventing die() and exception to mess up the entire console
- Added a status bar with char/line display
- Added a toggle button to expand/collapse all krumo sub-trees at once
- Cross-browser compatibility enhancements
- 1.0.0
- Initial Public Release

@ -16,7 +16,6 @@
* Source on Github http://github.com/Seldaek/jquery-selections
*/
(function($) {
/**
* sets the caret position
*
@ -24,8 +23,19 @@
* @see $.fn.setSelection
*/
$.fn.setCaret = function(index) {
var range, elem;
elem = this.get(0);
if ($.browser.opera) {
match = this.val().match(/\n/g);
if (match) {
newlines = match.length;
index += newlines;
}
}
this.setSelection(index);
}
};
/**
* returns the caret position, or 0 if the element has no caret
@ -33,28 +43,58 @@
* @return int
*/
$.fn.getCaret = function() {
var elem, range, elemRange, elemRangeCopy;
var elem, range, elemRange, elemRangeCopy, value, caret, pos;
elem = this.get(0);
value = $(elem).val();
// standard browsers
if (elem.selectionStart) {
return elem.selectionStart;
caret = elem.selectionStart;
} else if (document.selection) {
// old IE handling
elem.focus();
range = document.selection.createRange();
if (range === null) {
return 0;
}
elemRange = elem.createTextRange(),
elemRangeCopy = elemRange.duplicate();
elemRange.moveToBookmark(range.getBookmark());
elemRangeCopy.setEndPoint('EndToStart', elemRange);
// handle input texts
if (elem.nodeName === 'INPUT') {
elemRange = elem.createTextRange();
elemRangeCopy = elemRange.duplicate();
elemRange.moveToBookmark(range.getBookmark());
elemRangeCopy.setEndPoint('EndToStart', elemRange);
caret = elemRangeCopy.text.length;
} else {
// handle textareas
elemRangeCopy = range.duplicate();
elemRangeCopy.moveToElementText(elem);
pos = 0;
if (range.text.length > 1) {
pos = Math.max(0, pos - range.text.length);
}
caret = -1 + pos;
elemRangeCopy .moveStart('character', pos);
return elemRangeCopy.text.length;
while (elemRangeCopy.inRange(range)) {
elemRangeCopy.moveStart('character');
caret++;
}
}
} else {
caret = 0;
}
if ($.browser.opera) {
value = value.replace(/\r?\n/g, "\r\n").substr(0, caret);
match = value.match(/\r\n/g);
if (match) {
newlines = match.length;
caret -= newlines;
}
}
return 0;
return caret;
};
/**
@ -69,10 +109,12 @@
elem = this.get(0);
end = end || start;
// standard browsers
if (elem.setSelectionRange) {
elem.focus();
elem.setSelectionRange(start, end);
} else if (elem.createTextRange) {
// old IE handling
range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
@ -83,6 +125,55 @@
return this;
};
/**
* reads the text the user selected
*
* @param int start index of the beginning of the selection
* @param int end index of the end of the selection
* @return string
*/
$.fn.getSelectedText = function() {
var elem = this.get(0);
// standard browsers
if (elem.selectionStart) {
return elem.value.substr(elem.selectionStart, elem.selectionEnd);
}
// old IE
if (document.selection) {
elem.focus();
return document.selection.createRange().text;
}
return '';
};
/**
* injects the given text in place of the current selection
*
* @param string text
* @return object chainable
*/
$.fn.replaceSelection = function(text) {
var elem = this.get(0);
// standard browsers
if (elem.selectionStart) {
elem.value = elem.value.substr(0, elem.selectionStart) + text + elem.value.substr(elem.selectionEnd, elem.value.length);
return this;
}
// old IE
if (document.selection) {
elem.focus();
document.selection.createRange().text = text;
return this;
}
return this;
};
/**
* injects the given text at the current caret position
*
@ -99,6 +190,5 @@
$elem.setCaret(caret + text.length);
return this;
}
}(jQuery));
};
}(jQuery));

@ -13,59 +13,71 @@
*/
$(function() {
var updateStatusBar;
var updateStatusBar, handleKeyPress;
// updates the text of the status bar
updateStatusBar = function() {
var caret, part, matches;
var caret, part, matches, charCount, lineCount;
caret = $('textarea[name="code"]').getCaret();
part = $('textarea[name="code"]').val().substring(0, caret);
matches = part.match(/(\r?\n)?([^\r\n]*)/g);
part = $('textarea[name="code"]').val().substr(0, caret);
matches = part.match(/(\n|[^\r\n]*$)/g);
part = matches.length > 1 ? matches[matches.length - 2] : matches[0];
$('.statusbar').text('Line: ' + Math.max(1, matches.length-1) + ', Column: ' + (matches.length > 2 ? part.length : part.length + 1));
lineCount = Math.max(1, matches.length);
// matched the first char of a line, so matches are only \n's
if (part === "" || part === "\r\n" || part === "\n") {
charCount = 1;
} else {
// matched another char, so we've got the current line as the next-to-last match
charCount = part.length + 1;
lineCount--;
}
$('.statusbar').text('Line: ' + lineCount + ', Column: ' + charCount);
};
$('textarea[name="code"]')
.keydown(function(e) {
var caret, part, matches;
switch(e.keyCode) {
case 9:
// add 4 spaces when tab is pressed
handleKeyPress = function(e) {
var caret, part, matches;
switch(e.keyCode) {
case 9:
// add 4 spaces when tab is pressed
e.preventDefault();
$(this).injectText(" ");
break;
case 13:
// submit form on ctrl-enter or alt-enter
if (e.metaKey || e.altKey) {
e.preventDefault();
$(this).injectText(" ");
break;
case 13:
// submit form on ctrl-enter or alt-enter
if (e.metaKey || e.altKey) {
e.preventDefault();
$('form').submit();
return;
}
$('form').submit();
return;
}
// indent automatically the new lines
// skip because buggy in opera until they fix the preventDefault bug
if ($.browser.opera) {
return;
}
caret = $(this).getCaret();
part = $(this).val().substring(0, caret);
matches = part.match(/(\r?\n +)[^\r\n]*$/);
if (matches) {
$(this).val(function(idx, val) {
return val.substring(0, caret) + matches[1] + val.substring(caret);
});
$(this).setCaret(caret + matches[1].length);
e.preventDefault();
}
break;
// indent automatically the new lines
caret = $(this).getCaret();
part = $(this).val().substr(0, caret);
matches = part.match(/(\n +)[^\r\n]*$/);
if (matches) {
$(this).val(function(idx, val) {
return val.substring(0, caret) + matches[1] + val.substring(caret);
});
$(this).setCaret(caret + matches[1].length);
e.preventDefault();
}
break;
}
updateStatusBar();
};
updateStatusBar();
})
$('textarea[name="code"]')
.keyup(updateStatusBar)
.click(updateStatusBar)
.focus();
if ($.browser.opera) {
$('textarea[name="code"]').keypress(handleKeyPress);
} else {
$('textarea[name="code"]').keydown(handleKeyPress);
}
updateStatusBar();
$('input[name="subm"]').keyup(function(e) {

Loading…
Cancel
Save