aggiunte funzionalità all'interfaccia
This commit is contained in:
parent
2353dc73ac
commit
4fd23bc14b
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,48 @@
|
||||||
|
.hwt-container {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden !important;
|
||||||
|
-webkit-text-size-adjust: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hwt-backdrop {
|
||||||
|
position: absolute !important;
|
||||||
|
top: 0 !important;
|
||||||
|
right: -99px !important;
|
||||||
|
bottom: 0 !important;
|
||||||
|
left: 0 !important;
|
||||||
|
padding-right: 99px !important;
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hwt-highlights {
|
||||||
|
width: auto !important;
|
||||||
|
height: auto !important;
|
||||||
|
border-color: transparent !important;
|
||||||
|
white-space: pre-wrap !important;
|
||||||
|
word-wrap: break-word !important;
|
||||||
|
color: transparent !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hwt-input {
|
||||||
|
display: block !important;
|
||||||
|
position: relative !important;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
font: inherit;
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hwt-content {
|
||||||
|
border: 1px solid;
|
||||||
|
background: none transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hwt-content mark {
|
||||||
|
padding: 0 !important;
|
||||||
|
color: inherit;
|
||||||
|
}
|
|
@ -1090,8 +1090,6 @@ $(document).ready(function() {
|
||||||
if (role == 'lemmaRadio'){
|
if (role == 'lemmaRadio'){
|
||||||
$('#lemmaCheck').prop('disabled', false);
|
$('#lemmaCheck').prop('disabled', false);
|
||||||
$('#formaCheck').prop('disabled', false);
|
$('#formaCheck').prop('disabled', false);
|
||||||
// $('#lemmaCheck').prop('checked', true);
|
|
||||||
// $('#formaCheck').prop('checked', true);
|
|
||||||
}else{
|
}else{
|
||||||
if (role == 'stringaRadio'){
|
if (role == 'stringaRadio'){
|
||||||
$('#lemmaCheck').prop('disabled', true);
|
$('#lemmaCheck').prop('disabled', true);
|
||||||
|
@ -1100,32 +1098,57 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jQuery(document).delegate('#close_cerca', 'click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
$('#apricerca').attr('style', "display:none;")
|
||||||
|
$('.labelVai span').html("Vai a:");
|
||||||
|
$('#grammarbutton').attr('style', "display:block; width: 51px; height: 51px;");
|
||||||
|
|
||||||
|
$('#browseArea').css('opacity', '1');
|
||||||
|
$('#PagineCanti').prop("disabled", false);
|
||||||
|
$('#PagineCanti').css('overflow', 'auto');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
jQuery(document).delegate('#grammarbutton', 'click', function(e) {
|
jQuery(document).delegate('#grammarbutton', 'click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
$('#browseArea').css('opacity', '0.4');
|
||||||
|
$('#PagineCanti').prop("disabled", true);
|
||||||
|
$('#PagineCanti').css('overflow', 'hidden');
|
||||||
$('.labelVai span').html("Cerca in:");
|
$('.labelVai span').html("Cerca in:");
|
||||||
/*$('.searchCosa').attr('style', "display:block;")
|
|
||||||
$('#lemmaCheck').prop('disabled', true);
|
|
||||||
$('#formaCheck').prop('disabled', true);
|
|
||||||
$('#lemmaCheck').prop('checked', false);
|
|
||||||
$('#formaCheck').prop('checked', false);
|
|
||||||
|
|
||||||
$('#grammarbutton').attr('style', "display:none;");
|
$('#grammarbutton').attr('style', "display:none;");
|
||||||
$('#quitGoButton').attr('style', "display:block;");
|
|
||||||
|
|
||||||
$('#searchValue').val("");
|
|
||||||
$('#stringaRadio').attr('checked', true).click();
|
|
||||||
//$(this).prop('disabled', true);
|
|
||||||
$('#FiltriGrafici').attr('style', "display:none;")
|
|
||||||
|
|
||||||
filtraPerOpen = false;*/
|
|
||||||
$('#apricerca').attr('style', "display:block;")
|
$('#apricerca').attr('style', "display:block;")
|
||||||
|
$('#advanSW').prop('checked',false)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
jQuery(document).delegate('#BottoneCerca', 'click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$("#loader").show();
|
||||||
|
setTimeout(function() {
|
||||||
|
$("#loader").hide();
|
||||||
|
fakeResult();
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
jQuery(document).delegate('a.selectInferno1', 'click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
//var areaText = $('#PagineCanti');
|
||||||
|
$('#PagineCanti').highlightWithinTextarea({
|
||||||
|
highlight: 'paura'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Da Luca JS
|
||||||
$('#cla-TabContent').on('click', '#advanSW', function() {
|
$('#cla-TabContent').on('click', '#advanSW', function() {
|
||||||
if ($(this).prop('checked')) {
|
if ($(this).prop('checked')) {
|
||||||
$("#cla-Advanced").attr('style', "display: block;");
|
$("#cla-Advanced").attr('style', "display: block;");
|
||||||
|
@ -1137,6 +1160,150 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.btn-group a').on('click', function() {
|
||||||
|
var addClaN = $(this).attr('id');
|
||||||
|
switch (addClaN) {
|
||||||
|
case "Grammaticale":
|
||||||
|
addGramCla(1);
|
||||||
|
$('#cla' + tabID + '-tab').tab('show');
|
||||||
|
break;
|
||||||
|
case "Sintattico":
|
||||||
|
addSyntCla(1);
|
||||||
|
$('#cla' + tabID + '-tab').tab('show');
|
||||||
|
break;
|
||||||
|
case "Metafore":
|
||||||
|
addMetaCla(0);
|
||||||
|
$('#cla' + tabID + '-tab').tab('show');
|
||||||
|
break;
|
||||||
|
case "Dialoghi":
|
||||||
|
addDialCla(0);
|
||||||
|
$('#cla' + tabID + '-tab').tab('show');
|
||||||
|
break;
|
||||||
|
case "Struttura":
|
||||||
|
addStruCla(0);
|
||||||
|
$('#cla' + tabID + '-tab').tab('show');
|
||||||
|
break;
|
||||||
|
case "andCond":
|
||||||
|
addLogicCond("AND","#sortable0")
|
||||||
|
break;
|
||||||
|
case "orCond":
|
||||||
|
addLogicCond("OR","#sortable0")
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function fakeResult(){
|
||||||
|
tabellaCanti ="";
|
||||||
|
|
||||||
|
for (j=1;j<20;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectParadiso' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectParadiso' + j +
|
||||||
|
'href="#0" data-added="0">'+'20(3)'+'</a> ';
|
||||||
|
for (j=21;j<30;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectParadiso' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectParadiso' + j +
|
||||||
|
'href="#0" data-added="0">'+'30(2)'+'</a> ';
|
||||||
|
|
||||||
|
for (j=31;j<34;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectParadiso' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#CantiParadiso').append(tabellaCanti);
|
||||||
|
$('#CantiParadiso').attr('style', "display:block;")
|
||||||
|
|
||||||
|
CantiParadiso = true;
|
||||||
|
|
||||||
|
tabellaCanti ="";
|
||||||
|
|
||||||
|
for (j=1;j<10;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectPurgatorio' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectPurgatorio' + j +
|
||||||
|
'href="#0" data-added="0">'+'10(4)'+'</a> ';
|
||||||
|
for (j=11;j<25;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectPurgatorio' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectPurgatorio' + j +
|
||||||
|
'href="#0" data-added="0">'+'25(2)'+'</a> ';
|
||||||
|
|
||||||
|
for (j=26;j<34;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectPurgatorio' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#CantiPurgatorio').append(tabellaCanti);
|
||||||
|
$('#CantiPurgatorio').attr('style', "display:block;")
|
||||||
|
|
||||||
|
CantiPurgatorio = true;
|
||||||
|
|
||||||
|
tabellaCanti ="";
|
||||||
|
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectInferno' + '1' +
|
||||||
|
' href="#0" data-added="0">'+'1(3)'+'</a> ';
|
||||||
|
for (j=2;j<15;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectInferno' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectInferno' + '15' +
|
||||||
|
' href="#0" data-added="0">'+'15(1)'+'</a> ';
|
||||||
|
for (j=16;j<22;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectInferno' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectInferno' + j +
|
||||||
|
'href="#0" data-added="0">'+'22(2)'+'</a> ';
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-red selectInferno' + j +
|
||||||
|
'href="#0" data-added="0">'+'23(4)'+'</a> ';
|
||||||
|
|
||||||
|
|
||||||
|
for (j=24;j<35;j++){
|
||||||
|
tabellaCanti = tabellaCanti +
|
||||||
|
'<a class="f5 link dim br1 bn pa0 mb0 dib dark-green selectInferno' + j +
|
||||||
|
'href="#0" data-added="0">'+j+'</a> ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#CantiInferno').append(tabellaCanti);
|
||||||
|
$('#CantiInferno').attr('style', "display:block;")
|
||||||
|
|
||||||
|
CantiInferno = true;
|
||||||
|
|
||||||
|
$('#apricerca').attr('style', "display:none;")
|
||||||
|
$('.labelVai span').html("Vai a:");
|
||||||
|
$('#grammarbutton').attr('style', "display:block; width: 51px; height: 51px;");
|
||||||
|
|
||||||
|
$('#browseArea').css('opacity', '1');
|
||||||
|
$('#PagineCanti').prop("disabled", false);
|
||||||
|
$('#PagineCanti').css('overflow', 'auto');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//Cesare
|
//Cesare
|
||||||
$(function() {
|
$(function() {
|
||||||
$("#filtri").sortable({
|
$("#filtri").sortable({
|
||||||
|
|
|
@ -0,0 +1,380 @@
|
||||||
|
/*
|
||||||
|
* highlight-within-textarea
|
||||||
|
*
|
||||||
|
* @author Will Boyd
|
||||||
|
* @github https://github.com/lonekorean/highlight-within-textarea
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
let ID = 'hwt';
|
||||||
|
|
||||||
|
let HighlightWithinTextarea = function($el, config) {
|
||||||
|
this.init($el, config);
|
||||||
|
};
|
||||||
|
|
||||||
|
HighlightWithinTextarea.prototype = {
|
||||||
|
init: function($el, config) {
|
||||||
|
this.$el = $el;
|
||||||
|
|
||||||
|
// backwards compatibility with v1 (deprecated)
|
||||||
|
if (this.getType(config) === 'function') {
|
||||||
|
config = { highlight: config };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getType(config) === 'custom') {
|
||||||
|
this.highlight = config;
|
||||||
|
this.generate();
|
||||||
|
} else {
|
||||||
|
console.error('valid config object not provided');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// returns identifier strings that aren't necessarily "real" JavaScript types
|
||||||
|
getType: function(instance) {
|
||||||
|
let type = typeof instance;
|
||||||
|
if (!instance) {
|
||||||
|
return 'falsey';
|
||||||
|
} else if (Array.isArray(instance)) {
|
||||||
|
if (instance.length === 2 && typeof instance[0] === 'number' && typeof instance[1] === 'number') {
|
||||||
|
return 'range';
|
||||||
|
} else {
|
||||||
|
return 'array';
|
||||||
|
}
|
||||||
|
} else if (type === 'object') {
|
||||||
|
if (instance instanceof RegExp) {
|
||||||
|
return 'regexp';
|
||||||
|
} else if (instance.hasOwnProperty('highlight')) {
|
||||||
|
return 'custom';
|
||||||
|
}
|
||||||
|
} else if (type === 'function' || type === 'string') {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'other';
|
||||||
|
},
|
||||||
|
|
||||||
|
generate: function() {
|
||||||
|
this.$el
|
||||||
|
.addClass(ID + '-input ' + ID + '-content')
|
||||||
|
.on('input.' + ID, this.handleInput.bind(this))
|
||||||
|
.on('scroll.' + ID, this.handleScroll.bind(this));
|
||||||
|
|
||||||
|
this.$highlights = $('<div>', { class: ID + '-highlights ' + ID + '-content' });
|
||||||
|
|
||||||
|
this.$backdrop = $('<div>', { class: ID + '-backdrop' })
|
||||||
|
.append(this.$highlights);
|
||||||
|
|
||||||
|
this.$container = $('<div>', { class: ID + '-container' })
|
||||||
|
.insertAfter(this.$el)
|
||||||
|
.append(this.$backdrop, this.$el) // moves $el into $container
|
||||||
|
.on('scroll', this.blockContainerScroll.bind(this));
|
||||||
|
|
||||||
|
this.browser = this.detectBrowser();
|
||||||
|
switch (this.browser) {
|
||||||
|
case 'firefox':
|
||||||
|
this.fixFirefox();
|
||||||
|
break;
|
||||||
|
case 'ios':
|
||||||
|
this.fixIOS();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin function checks this for success
|
||||||
|
this.isGenerated = true;
|
||||||
|
|
||||||
|
// trigger input event to highlight any existing input
|
||||||
|
this.handleInput();
|
||||||
|
},
|
||||||
|
|
||||||
|
// browser sniffing sucks, but there are browser-specific quirks to handle
|
||||||
|
// that are not a matter of feature detection
|
||||||
|
detectBrowser: function() {
|
||||||
|
let ua = window.navigator.userAgent.toLowerCase();
|
||||||
|
if (ua.indexOf('firefox') !== -1) {
|
||||||
|
return 'firefox';
|
||||||
|
} else if (!!ua.match(/msie|trident\/7|edge/)) {
|
||||||
|
return 'ie';
|
||||||
|
} else if (!!ua.match(/ipad|iphone|ipod/) && ua.indexOf('windows phone') === -1) {
|
||||||
|
// Windows Phone flags itself as "like iPhone", thus the extra check
|
||||||
|
return 'ios';
|
||||||
|
} else {
|
||||||
|
return 'other';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Firefox doesn't show text that scrolls into the padding of a textarea, so
|
||||||
|
// rearrange a couple box models to make highlights behave the same way
|
||||||
|
fixFirefox: function() {
|
||||||
|
// take padding and border pixels from highlights div
|
||||||
|
let padding = this.$highlights.css([
|
||||||
|
'padding-top', 'padding-right', 'padding-bottom', 'padding-left'
|
||||||
|
]);
|
||||||
|
let border = this.$highlights.css([
|
||||||
|
'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'
|
||||||
|
]);
|
||||||
|
this.$highlights.css({
|
||||||
|
'padding': '0',
|
||||||
|
'border-width': '0'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$backdrop
|
||||||
|
.css({
|
||||||
|
// give padding pixels to backdrop div
|
||||||
|
'margin-top': '+=' + padding['padding-top'],
|
||||||
|
'margin-right': '+=' + padding['padding-right'],
|
||||||
|
'margin-bottom': '+=' + padding['padding-bottom'],
|
||||||
|
'margin-left': '+=' + padding['padding-left'],
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
// give border pixels to backdrop div
|
||||||
|
'margin-top': '+=' + border['border-top-width'],
|
||||||
|
'margin-right': '+=' + border['border-right-width'],
|
||||||
|
'margin-bottom': '+=' + border['border-bottom-width'],
|
||||||
|
'margin-left': '+=' + border['border-left-width'],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// iOS adds 3px of (unremovable) padding to the left and right of a textarea,
|
||||||
|
// so adjust highlights div to match
|
||||||
|
fixIOS: function() {
|
||||||
|
this.$highlights.css({
|
||||||
|
'padding-left': '+=3px',
|
||||||
|
'padding-right': '+=3px'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleInput: function() {
|
||||||
|
let input = this.$el.val();
|
||||||
|
let ranges = this.getRanges(input, this.highlight);
|
||||||
|
let unstaggeredRanges = this.removeStaggeredRanges(ranges);
|
||||||
|
let boundaries = this.getBoundaries(unstaggeredRanges);
|
||||||
|
this.renderMarks(boundaries);
|
||||||
|
},
|
||||||
|
|
||||||
|
getRanges: function(input, highlight) {
|
||||||
|
let type = this.getType(highlight);
|
||||||
|
switch (type) {
|
||||||
|
case 'array':
|
||||||
|
return this.getArrayRanges(input, highlight);
|
||||||
|
case 'function':
|
||||||
|
return this.getFunctionRanges(input, highlight);
|
||||||
|
case 'regexp':
|
||||||
|
return this.getRegExpRanges(input, highlight);
|
||||||
|
case 'string':
|
||||||
|
return this.getStringRanges(input, highlight);
|
||||||
|
case 'range':
|
||||||
|
return this.getRangeRanges(input, highlight);
|
||||||
|
case 'custom':
|
||||||
|
return this.getCustomRanges(input, highlight);
|
||||||
|
default:
|
||||||
|
if (!highlight) {
|
||||||
|
// do nothing for falsey values
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
console.error('unrecognized highlight type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getArrayRanges: function(input, arr) {
|
||||||
|
let ranges = arr.map(this.getRanges.bind(this, input));
|
||||||
|
return Array.prototype.concat.apply([], ranges);
|
||||||
|
},
|
||||||
|
|
||||||
|
getFunctionRanges: function(input, func) {
|
||||||
|
return this.getRanges(input, func(input));
|
||||||
|
},
|
||||||
|
|
||||||
|
getRegExpRanges: function(input, regex) {
|
||||||
|
let ranges = [];
|
||||||
|
let match;
|
||||||
|
while (match = regex.exec(input), match !== null) {
|
||||||
|
ranges.push([match.index, match.index + match[0].length]);
|
||||||
|
if (!regex.global) {
|
||||||
|
// non-global regexes do not increase lastIndex, causing an infinite loop,
|
||||||
|
// but we can just break manually after the first match
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
|
getStringRanges: function(input, str) {
|
||||||
|
let ranges = [];
|
||||||
|
let inputLower = input.toLowerCase();
|
||||||
|
let strLower = str.toLowerCase();
|
||||||
|
let index = 0;
|
||||||
|
while (index = inputLower.indexOf(strLower, index), index !== -1) {
|
||||||
|
ranges.push([index, index + strLower.length]);
|
||||||
|
index += strLower.length;
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
|
getRangeRanges: function(input, range) {
|
||||||
|
return [range];
|
||||||
|
},
|
||||||
|
|
||||||
|
getCustomRanges: function(input, custom) {
|
||||||
|
let ranges = this.getRanges(input, custom.highlight);
|
||||||
|
if (custom.className) {
|
||||||
|
ranges.forEach(function(range) {
|
||||||
|
// persist class name as a property of the array
|
||||||
|
if (range.className) {
|
||||||
|
range.className = custom.className + ' ' + range.className;
|
||||||
|
} else {
|
||||||
|
range.className = custom.className;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
|
// prevent staggered overlaps (clean nesting is fine)
|
||||||
|
removeStaggeredRanges: function(ranges) {
|
||||||
|
let unstaggeredRanges = [];
|
||||||
|
ranges.forEach(function(range) {
|
||||||
|
let isStaggered = unstaggeredRanges.some(function(unstaggeredRange) {
|
||||||
|
let isStartInside = range[0] > unstaggeredRange[0] && range[0] < unstaggeredRange[1];
|
||||||
|
let isStopInside = range[1] > unstaggeredRange[0] && range[1] < unstaggeredRange[1];
|
||||||
|
return isStartInside !== isStopInside; // xor
|
||||||
|
});
|
||||||
|
if (!isStaggered) {
|
||||||
|
unstaggeredRanges.push(range);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return unstaggeredRanges;
|
||||||
|
},
|
||||||
|
|
||||||
|
getBoundaries: function(ranges) {
|
||||||
|
let boundaries = [];
|
||||||
|
ranges.forEach(function(range) {
|
||||||
|
boundaries.push({
|
||||||
|
type: 'start',
|
||||||
|
index: range[0],
|
||||||
|
className: range.className
|
||||||
|
});
|
||||||
|
boundaries.push({
|
||||||
|
type: 'stop',
|
||||||
|
index: range[1]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sortBoundaries(boundaries);
|
||||||
|
return boundaries;
|
||||||
|
},
|
||||||
|
|
||||||
|
sortBoundaries: function(boundaries) {
|
||||||
|
// backwards sort (since marks are inserted right to left)
|
||||||
|
boundaries.sort(function(a, b) {
|
||||||
|
if (a.index !== b.index) {
|
||||||
|
return b.index - a.index;
|
||||||
|
} else if (a.type === 'stop' && b.type === 'start') {
|
||||||
|
return 1;
|
||||||
|
} else if (a.type === 'start' && b.type === 'stop') {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renderMarks: function(boundaries) {
|
||||||
|
let input = this.$el.val();
|
||||||
|
boundaries.forEach(function(boundary, index) {
|
||||||
|
let markup;
|
||||||
|
if (boundary.type === 'start') {
|
||||||
|
markup = '{{hwt-mark-start|' + index + '}}';
|
||||||
|
} else {
|
||||||
|
markup = '{{hwt-mark-stop}}';
|
||||||
|
}
|
||||||
|
input = input.slice(0, boundary.index) + markup + input.slice(boundary.index);
|
||||||
|
});
|
||||||
|
|
||||||
|
// this keeps scrolling aligned when input ends with a newline
|
||||||
|
input = input.replace(/\n(\{\{hwt-mark-stop\}\})?$/, '\n\n$1');
|
||||||
|
|
||||||
|
// encode HTML entities
|
||||||
|
input = input.replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
|
||||||
|
if (this.browser === 'ie') {
|
||||||
|
// IE/Edge wraps whitespace differently in a div vs textarea, this fixes it
|
||||||
|
input = input.replace(/ /g, ' <wbr>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace start tokens with opening <mark> tags with class name
|
||||||
|
input = input.replace(/\{\{hwt-mark-start\|(\d+)\}\}/g, function(match, submatch) {
|
||||||
|
var className = boundaries[+submatch].className;
|
||||||
|
if (className) {
|
||||||
|
return '<mark class="' + className + '">';
|
||||||
|
} else {
|
||||||
|
return '<mark>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// replace stop tokens with closing </mark> tags
|
||||||
|
input = input.replace(/\{\{hwt-mark-stop\}\}/g, '</mark>');
|
||||||
|
|
||||||
|
this.$highlights.html(input);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleScroll: function() {
|
||||||
|
let scrollTop = this.$el.scrollTop();
|
||||||
|
this.$backdrop.scrollTop(scrollTop);
|
||||||
|
|
||||||
|
// Chrome and Safari won't break long strings of spaces, which can cause
|
||||||
|
// horizontal scrolling, this compensates by shifting highlights by the
|
||||||
|
// horizontally scrolled amount to keep things aligned
|
||||||
|
let scrollLeft = this.$el.scrollLeft();
|
||||||
|
this.$backdrop.css('transform', (scrollLeft > 0) ? 'translateX(' + -scrollLeft + 'px)' : '');
|
||||||
|
},
|
||||||
|
|
||||||
|
// in Chrome, page up/down in the textarea will shift stuff within the
|
||||||
|
// container (despite the CSS), this immediately reverts the shift
|
||||||
|
blockContainerScroll: function() {
|
||||||
|
this.$container.scrollLeft(0);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
this.$backdrop.remove();
|
||||||
|
this.$el
|
||||||
|
.unwrap()
|
||||||
|
.removeClass(ID + '-text ' + ID + '-input')
|
||||||
|
.off(ID)
|
||||||
|
.removeData(ID);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// register the jQuery plugin
|
||||||
|
$.fn.highlightWithinTextarea = function(options) {
|
||||||
|
return this.each(function() {
|
||||||
|
let $this = $(this);
|
||||||
|
let plugin = $this.data(ID);
|
||||||
|
|
||||||
|
if (typeof options === 'string') {
|
||||||
|
if (plugin) {
|
||||||
|
switch (options) {
|
||||||
|
case 'update':
|
||||||
|
plugin.handleInput();
|
||||||
|
break;
|
||||||
|
case 'destroy':
|
||||||
|
plugin.destroy();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error('unrecognized method string');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('plugin must be instantiated first');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (plugin) {
|
||||||
|
plugin.destroy();
|
||||||
|
}
|
||||||
|
plugin = new HighlightWithinTextarea($this, options);
|
||||||
|
if (plugin.isGenerated) {
|
||||||
|
$this.data(ID, plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})(jQuery);
|
Loading…
Reference in New Issue