mostly cross-browser compatibility enhancements
This commit is contained in:
@@ -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
|
- 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 status bar with char/line display
|
||||||
- Added a toggle button to expand/collapse all krumo sub-trees at once
|
- Added a toggle button to expand/collapse all krumo sub-trees at once
|
||||||
|
- Cross-browser compatibility enhancements
|
||||||
- 1.0.0
|
- 1.0.0
|
||||||
- Initial Public Release
|
- Initial Public Release
|
||||||
|
|
||||||
|
|||||||
+108
-18
@@ -16,7 +16,6 @@
|
|||||||
* Source on Github http://github.com/Seldaek/jquery-selections
|
* Source on Github http://github.com/Seldaek/jquery-selections
|
||||||
*/
|
*/
|
||||||
(function($) {
|
(function($) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the caret position
|
* sets the caret position
|
||||||
*
|
*
|
||||||
@@ -24,8 +23,19 @@
|
|||||||
* @see $.fn.setSelection
|
* @see $.fn.setSelection
|
||||||
*/
|
*/
|
||||||
$.fn.setCaret = function(index) {
|
$.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);
|
this.setSelection(index);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the caret position, or 0 if the element has no caret
|
* returns the caret position, or 0 if the element has no caret
|
||||||
@@ -33,28 +43,58 @@
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
$.fn.getCaret = function() {
|
$.fn.getCaret = function() {
|
||||||
var elem, range, elemRange, elemRangeCopy;
|
var elem, range, elemRange, elemRangeCopy, value, caret, pos;
|
||||||
elem = this.get(0);
|
elem = this.get(0);
|
||||||
|
|
||||||
|
value = $(elem).val();
|
||||||
|
|
||||||
|
// standard browsers
|
||||||
if (elem.selectionStart) {
|
if (elem.selectionStart) {
|
||||||
return elem.selectionStart;
|
caret = elem.selectionStart;
|
||||||
} else if (document.selection) {
|
} else if (document.selection) {
|
||||||
|
// old IE handling
|
||||||
elem.focus();
|
elem.focus();
|
||||||
|
|
||||||
range = document.selection.createRange();
|
range = document.selection.createRange();
|
||||||
if (range === null) {
|
|
||||||
return 0;
|
// 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);
|
||||||
|
|
||||||
|
while (elemRangeCopy.inRange(range)) {
|
||||||
|
elemRangeCopy.moveStart('character');
|
||||||
|
caret++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
elemRange = elem.createTextRange(),
|
caret = 0;
|
||||||
elemRangeCopy = elemRange.duplicate();
|
|
||||||
elemRange.moveToBookmark(range.getBookmark());
|
|
||||||
elemRangeCopy.setEndPoint('EndToStart', elemRange);
|
|
||||||
|
|
||||||
return elemRangeCopy.text.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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 caret;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,10 +109,12 @@
|
|||||||
elem = this.get(0);
|
elem = this.get(0);
|
||||||
end = end || start;
|
end = end || start;
|
||||||
|
|
||||||
|
// standard browsers
|
||||||
if (elem.setSelectionRange) {
|
if (elem.setSelectionRange) {
|
||||||
elem.focus();
|
elem.focus();
|
||||||
elem.setSelectionRange(start, end);
|
elem.setSelectionRange(start, end);
|
||||||
} else if (elem.createTextRange) {
|
} else if (elem.createTextRange) {
|
||||||
|
// old IE handling
|
||||||
range = elem.createTextRange();
|
range = elem.createTextRange();
|
||||||
range.collapse(true);
|
range.collapse(true);
|
||||||
range.moveEnd('character', end);
|
range.moveEnd('character', end);
|
||||||
@@ -83,6 +125,55 @@
|
|||||||
return this;
|
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
|
* injects the given text at the current caret position
|
||||||
*
|
*
|
||||||
@@ -99,6 +190,5 @@
|
|||||||
$elem.setCaret(caret + text.length);
|
$elem.setCaret(caret + text.length);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
};
|
||||||
|
}(jQuery));
|
||||||
}(jQuery));
|
|
||||||
|
|||||||
+53
-41
@@ -13,59 +13,71 @@
|
|||||||
*/
|
*/
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
var updateStatusBar;
|
var updateStatusBar, handleKeyPress;
|
||||||
|
|
||||||
// updates the text of the status bar
|
// updates the text of the status bar
|
||||||
updateStatusBar = function() {
|
updateStatusBar = function() {
|
||||||
var caret, part, matches;
|
var caret, part, matches, charCount, lineCount;
|
||||||
caret = $('textarea[name="code"]').getCaret();
|
caret = $('textarea[name="code"]').getCaret();
|
||||||
part = $('textarea[name="code"]').val().substring(0, caret);
|
part = $('textarea[name="code"]').val().substr(0, caret);
|
||||||
matches = part.match(/(\r?\n)?([^\r\n]*)/g);
|
matches = part.match(/(\n|[^\r\n]*$)/g);
|
||||||
part = matches.length > 1 ? matches[matches.length - 2] : matches[0];
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
||||||
|
$('form').submit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
};
|
};
|
||||||
|
|
||||||
$('textarea[name="code"]')
|
$('textarea[name="code"]')
|
||||||
.keydown(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();
|
|
||||||
$('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;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStatusBar();
|
|
||||||
})
|
|
||||||
.keyup(updateStatusBar)
|
.keyup(updateStatusBar)
|
||||||
.click(updateStatusBar)
|
.click(updateStatusBar)
|
||||||
.focus();
|
.focus();
|
||||||
|
|
||||||
|
if ($.browser.opera) {
|
||||||
|
$('textarea[name="code"]').keypress(handleKeyPress);
|
||||||
|
} else {
|
||||||
|
$('textarea[name="code"]').keydown(handleKeyPress);
|
||||||
|
}
|
||||||
|
|
||||||
updateStatusBar();
|
updateStatusBar();
|
||||||
|
|
||||||
$('input[name="subm"]').keyup(function(e) {
|
$('input[name="subm"]').keyup(function(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user