MediaWiki:BibleGet.js: Difference between revisions

Content deleted Content added
No edit summary
No edit summary
 
(27 intermediate revisions by the same user not shown)
Line 3:
let domCheckInterval = [];
let ajaxCount = 0;
let BibleQuotesDomElements = [];
(function($,mw){
$(document).ready(function(){
Line 8 ⟶ 9:
console.log("There are " + $('.bibleQuoteRef').length + " bible quotes on this page");
$('.bibleQuoteRef').each(function(){
let $spanel = $(this);
let version = $(this).attr('data-version');
let ref = $(this).attr('data-ref');
let inline = ($(this).attr('data-inline') == "true");
console.log("data-ref = " + ref + " data-inline = " + inline);
if(bibleQuoteCollection.includes(version+"/"+ref)){
//we already have an instance of this bible quote, avoid creating new div
Line 17 ⟶ 20:
//however since the ajax calls are asynchronous, we probably won't have the actual div at the bottom of the page yet
//so let's look for it inside the mouseover event
if(inline){
$spanel.on('mouseenter', function(){
let $bGetTIP = $("div[data-version='"+version+"'][data-ref='"+ref+"']");
console.log('I found ' + $bGetTIP.length + ' div(s) at the bottom of the page with this bible quote');
$bGetTIP.removeClass('hidden');
let top = $spanel.offset().top;
let left = $spanel.offset().left + $spanel.outerWidth() + 15;
$bGetTIP.css({"top":top,"left":left});
if($bGetTIP.hasClass('sticky') || $bGetTIP.is(':offscreen') ){
});
console.log('This element would have been offscreen!');
//how far off the bottom of the screen are we?
/*
let rect = $bGetTIP[0].getBoundingClientRect();
$span.on('mousemove', function(){
let topexcessHeight = $span.offset(rect.y + rect.height) - window.topinnerHeight;
let leftexcessWidth = $span.offset()rect.leftx + $spanrect.outerWidth(width) - window.innerWidth;
//if this amount is less than the distance from the top of the screen,
$bGetTIP.css({"top":top,"left":left});
// then let's just move our div up by that much
});
if(!$bGetTIP.hasClass('sticky')){
*/
if(excessWidth > 0 && excessWidth < rect.x){
console.log('This element was off the right hand side of the screen');
$span.on('mouseleave', function(){
let newLeft;
$bGetTIP = $("div[data-version='"+version+"'][data-ref='"+ref+"']");
if($span.offset().left > rect.width){
//console.log('I found ' + $bGetTIP.length + ' div(s) at the bottom of the page with this bible quote');
newLeft = $span.offset().left - rect.width;
setTimeout(function(){
} else {
$bGetTIP.addClass('hidden');
newLeft = $span.offset().left - rect.width / 2; //center it on the span as a last resort!
$bGetTIP.css({"top":'',"left":''});
},500);
$bGetTIP.css({"left":newLeft});
});
}
if(excessHeight > 0 && excessHeight < rect.y){
console.log('This element was off the bottom of the screen');
let newTop = top - excessHeight;
$bGetTIP.css({"top":newTop});
} else if (excessHeight > rect.y){
$bGetTIP.addClass('sticky');
$bGetTIP.append($('<div>',{class:'closeButton',text:'x'}));
$bGetTIP.on('click','.closeButton',function(){
$bGetTIP.addClass('hidden');
$bGetTIP.css({"top":'',"left":''});
});
//distance of the top of the current window from the top of the document
let newTop = (window.pageYOffset || (document.documentElement || document.body.parentNode || document.body).scrollTop) + 20;
$bGetTIP.css({"top":newTop});
}
}
}
});
/*
$el.on('mousemove', function(){
let top = $span.offset().top;
let left = $span.offset().left + $span.outerWidth();
$bGetTIP.css({"top":top,"left":left});
});
*/
$el.on('mouseleave', function(){
let $bGetTIP = $("div[data-version='"+version+"'][data-ref='"+ref+"']");
//console.log('I found ' + $bGetTIP.length + ' div(s) at the bottom of the page with this bible quote');
if(!$bGetTIP.hasClass('sticky') ){
setTimeout(function(){
$bGetTIP.addClass('hidden');
$bGetTIP.css({"top":'',"left":''});
},500);
}
});
} else {
//if it's not inline we do have to deal with it again
$.ajax({
method: 'POST',
url: '../w/bgetHelper.php',
data: {
"version": version,
"ref": ref
},
success: function(data){
if(data.hasOwnProperty('html')){
$el.empty();
$el.css({"background-color":"white"});
$el.append(data.html);
$el.append($('<p>',{"text": " — powered by BibleGet I/O","css":{"font-size":".9em","text-align":"right","font-style":"italic","font-weight":"bold","color":"gray"}}));
}
},
error: function(jqXHR, textStatus, errorThrown){
console.log("There was an error while trying to communicate with the BibleGet server:")
console.log(errorThrown + ' ' + textStatus + ': ' + jqXHR.responseText);
}
}); //END ajax
}
} else {
bibleQuoteCollection.push(version+"/"+ref);
Line 56 ⟶ 120:
console.log(data);
if(data.hasOwnProperty('html')){
let $bGetTIP = $if('<div>', inline){
"class":let "bibleGetQuote$bGetTIP hidden"= $('<div>', {
"data-versionclass": version"bibleGetQuote",
"data-refversion": refversion,
"htmldata-ref": data.htmlref,
}); "html": data.html
});
$bGetTIP.append($('<p>',{"text": " — powered by BibleGet I/O","css":{"font-size":".9em","text-align":"right","font-style":"italic","font-weight":"bold","color":"gray"}}));
$bGetTIP.append($('<p>',{"text": " — powered by BibleGet I/O","css":{"font-size":".9em","text-align":"right","font-style":"italic","font-weight":"bold","color":"gray"}}));
$('body').append($bGetTIP);
//$span.on('mouseenterbody', function).append($bGetTIP){;
$bGetTIPBibleQuotesDomElements.removeClasspush('hidden'$bGetTIP);
let top = $span.offset().top;
let left = $spanel.offseton().left'mouseenter', + $span.outerWidthfunction() + 15;{
$bGetTIP.cssremoveClass({"top":top,"left":left}'hidden');
} let top = $el.offset().top;
let left = $el.offset().left + $el.outerWidth() + 15;
$bGetTIP.css({"top":top,"left":left});
/*
if($spanbGetTIP.onhasClass('mousemovesticky',) function|| $bGetTIP.is(':offscreen') ){
//are we off the bottom or the right side of the screen, and how much?
let top = $span.offset().top;
let leftrect = $spanbGetTIP[0].offset().left + $span.outerWidthgetBoundingClientRect();
let excessHeight = (rect.y + rect.height) - window.innerHeight;
$bGetTIP.css({"top":top,"left":left});
let excessWidth = (rect.x + rect.width) - window.innerWidth;
});
//if this amount is less than the distance from the top of the screen,
*/
// then let's just move our div up by that much
if(!$spanbGetTIP.onhasClass('mouseleavesticky', function()){
if(excessWidth > 0 && excessWidth < rect.x){
setTimeout(function(){
console.log('This element was off the right hand side of the screen');
$bGetTIP.addClass('hidden');
$bGetTIP.css({"top":'',"left":''}) let newLeft;
if($span.offset().left > rect.width){
},500);
newLeft = $span.offset().left - rect.width;
});
} else {
newLeft = $span.offset().left - rect.width / 2; //center it on the span as a last resort!
}
$bGetTIP.css({"left":newLeft});
}
if(excessHeight > 0 && excessHeight < rect.y){
console.log('This element was off the bottom of the screen');
let newTop = top - excessHeight;
$bGetTIP.css({"top":newTop});
} else if (excessHeight >= rect.y){
$bGetTIP.addClass('sticky');
$bGetTIP.append($('<div>',{class:'closeButton',text:'x'}));
$bGetTIP.on('click','.closeButton',function(){
$bGetTIP.addClass('hidden');
$bGetTIP.css({"top":'',"left":''});
});
//distance of the top of the current window from the top of the document
let newTop = (window.pageYOffset || (document.documentElement || document.body.parentNode || document.body).scrollTop) + 20;
$bGetTIP.css({"top":newTop});
}
}
}
});
/*
$el.on('mousemove', function(){
let top = $span.offset().top;
let left = $span.offset().left + $span.outerWidth();
$bGetTIP.css({"top":top,"left":left});
});
*/
$el.on('mouseleave', function(){
if(!$bGetTIP.hasClass('sticky') ){
setTimeout(function(){
$bGetTIP.addClass('hidden');
$bGetTIP.css({"top":'',"left":''});
},500);
}
});
} else {
$el.empty();
$el.css({"background-color":"white"});
$el.append(data.html);
$el.append($('<p>',{"text": " — powered by BibleGet I/O","css":{"font-size":".9em","text-align":"right","font-style":"italic","font-weight":"bold","color":"gray"}}));
}
}
//console.log("Injected Bible quote for ref = " + ref + " with value obtained from BibleGet service:");
Line 99 ⟶ 209:
$(document).ajaxStop(function(){
console.log("ajaxStop has fired " + ++ajaxCount + " time(s)");
//just because ajax requests have finished doesn't mean the dom manipulation is done...
//let's create a check for all elements before doing any further manipulation
if(domCheckInterval.length === 0){
//We have decided not to append anything to the document during the ajax calls
//We have simply collected the elements to append in an array
//So let's append them now...
$('body').append(BibleQuotesDomElements);
domCheckInterval.push(setInterval(onBGetDomElementsReady,100));
}
Line 117 ⟶ 231:
let [version,ref] = el.split("/");
if($("div[data-version='"+version+"'][data-ref='"+ref+"']").length === 0){
console.log("expected dom element [data-version='"+version+"'][data-ref='"+ref+"'] does not exist yet...");
return false;
}
Line 128 ⟶ 243:
clearInterval(interval);
}
//However we still seem to be running into issues with being able to do calculations on elements
doFurtherDomManipulation();
//So let's maybe wait just a little bit before doing our calculations?
setTimeout(doFurtherDomManipulation,300);
}
};
let doFurtherDomManipulation = function(){
jQuery('.versesParagraph .verseTextbibleGetQuote').each(function(){
console.log("Now manipulating contents of div [data-version='" + jQuery(this).attr('data-version') + "'] [data-ref='" + jQuery(this).attr('data-ref') + "']");
jQuery(this).contents().first().filter(function(){
return (
jQuery(this).find('.versesParagraph .verseText').each(function(){
this.nodeType === 1 && (
jQuery(this).contents().first().filter(function(){
jQuery(this).hasClass('pof') || jQuery(this).hasClass('po') || jQuery(this).hasClass('pol') || jQuery(this).hasClass('pos') || jQuery(this).hasClass('poif') || jQuery(this).hasClass('poi') || jQuery(this).hasClass('poil')
return (
this.nodeType === 1 && (
jQuery(this).hasClass('pof') || jQuery(this).hasClass('po') || jQuery(this).hasClass('pol') || jQuery(this).hasClass('pos') || jQuery(this).hasClass('poif') || jQuery(this).hasClass('poi') || jQuery(this).hasClass('poil')
)
)
}).css({"display":"inline-block","position":"relative","left":function(index){ return "-"+jQuery(this).parent('.verseText').prev('.verseNum').outerWidth(true)+"px"; } });
//HERE IS THE LOGIC:
//IF the (first node) following a .verseText node is not a text node,
//AND it IS an element node with class pof,poif,po,poi,poil...
//THEN change the css display of that (first node) to "inline-block" and left position it removing the width of the span with the verse number
//TODO: shouldn't we do this any time it's the first node within a verseText node, since it follows a verseNum?
jQuery(this).contents().first().filter(function(){
return (
this.nodeType === 1 && (
( jQuery(this).hasClass('pof') || jQuery(this).hasClass('po') || jQuery(this).hasClass('pol') || jQuery(this).hasClass('pos') || jQuery(this).hasClass('poif') || jQuery(this).hasClass('poi') || jQuery(this).hasClass('poil') )
&& jQuery(this).parent('.verseText').prevAll('.verseText').length > 0
&& (
(jQuery(this).parent('.verseText').prevAll('.verseText:first').contents().last()[0].nodeType === 1
&& jQuery(this).parent('.verseText').prevAll('.verseText:first').contents().last().css('display') == 'inline-block'
)
||
jQuery(this).parent('.verseText').prevAll('.verseText:first').contents().last()[0].nodeType === 3
)
)
)
}).parent('.verseText').prev('.verseNum').before('<br>');
)
//HERE IS THE LOGIC:
}).css({"display":"inline-block","position":"relative","left":function(index){ return "-"+jQuery(this).parent('.verseText').prev('.verseNum').outerWidth(true)+"px"; } });
//IF the (first node) following a .verseText node is not a text node,
//HERE IS THE LOGIC:
//IFAND theit (firstIS node)an following a .verseTextelement node iswith notclass apo text node,
//AND this is not the first .verseText node of a chapter
//AND it IS an element node with class pof,poif,po,poi,poil...
//AND the last node of the previous .verseText node has css display:inline-block
 
//THEN changeadd thea cssnewline displaybefore ofthe thatpreceding (first.verseNum node) to "inline-block" and left position it removing the width of the span withcontaining the verse number
//TODO: shouldn't we do this any time it's the first node within a verseText node, since it follows a verseNum?
//HERE INSTEAD WE REMOVE ANY EXTRA SPACES AT THE BEGINNING OF A VERSE...
 
jQuery(this).contentshtml( jQuery(this).firsthtml().filter(functionreplace( /^\s/, '' ) ){;
return (
});
this.nodeType === 1 && (
//Let's also make the poetic verses that have speaker tags line up a little better by removing a tad bit of the indent...
jQuery(this).hasClass('pof') && jQuery(this).parent('.verseText').prevAll('.verseText').length > 0
jQuery(this).find(".pof,.po,.pol,.pos,.poif,.poi,.poil").filter(function(){ return jQuery(this).children('.speaker').length !== 0 })
)
.css("left",function(i,current){
)
return (parseInt(current) - 4 || -15 );
}).parent('.verseText').prev('.verseNum').before('<br>');
}).css("position","relative");
//HERE IS THE LOGIC:
//IF the (first node) following a .verseText node is not a text node,
//AND HERE WE ADD A SPACE BETWEEN NUMBER AND REST OF BOOK NAME TO THOSE BIBLE BOOKS THAT HAVE AN INITIAL NUMBER
//AND it IS an element node with class pof
jQuery(this).find('.bookChapter').each(function(){
//AND this is not the first .verseText node of a chapter
if( unicodeChrClass.test( jQuery(this).html() ) ){
//THEN add a newline before the preceding .verseNum node containing the verse number
jQuery(this).html( jQuery(this).html().replace( unicodeChrClass, '$1 $2' ) );
}
});
jQuery(this).contentsaddClass('ready hidden').first().filter(function(){;
});
return (
};
this.nodeType === 1 && (
( jQuery(this).hasClass('pof') || jQuery(this).hasClass('po') || jQuery(this).hasClass('pol') || jQuery(this).hasClass('pos') || jQuery(this).hasClass('poif') || jQuery(this).hasClass('poi') || jQuery(this).hasClass('poil') )
&& jQuery(this).parent('.verseText').prevAll('.verseText').length > 0
&& jQuery(this).parent('.verseText').prevAll('.verseText:first').contents().last().css('display') == 'inline-block'
)
)
}).parent('.verseText').prev('.verseNum').before('<br>');
//HERE IS THE LOGIC:
//IF the (first node) following a .verseText node is not a text node,
//AND it IS an element node with class po
//AND this is not the first .verseText node of a chapter
//AND the last node of the previous .verseText node has css display:inline-block
//THEN add a newline before the preceding .verseNum node containing the verse number
 
jQuery.expr.filters.offscreen = function(el) {
//HERE INSTEAD WE REMOVE ANY EXTRA SPACES AT THE BEGINNING OF A VERSE...
let rect = el.getBoundingClientRect();
jQuery(this).html( jQuery(this).html().replace( /^\s/, '' ) );
return ( rect.x < 0 || rect.y < 0 ||
(rect.x + rect.width) > window.innerWidth ||
});
(rect.y + rect.height) > window.innerHeight );
//Let's also make the poetic verses that have speaker tags line up a little better by removing a tad bit of the indent...
jQuery(".pof,.po,.pol,.pos,.poif,.poi,.poil").filter(function(){ return jQuery(this).children('.speaker').length !== 0 })
.css("left",function(i,current){
return (parseInt(current) - 4 || -15 );
}).css("position","relative");
 
//AND HERE WE ADD A SPACE BETWEEN NUMBER AND REST OF BOOK NAME TO THOSE BIBLE BOOKS THAT HAVE AN INITIAL NUMBER
jQuery('.bibleQuote .bookChapter').each(function(){
if( unicodeChrClass.test( jQuery(this).html() ) ){
jQuery(this).html( jQuery(this).html().replace( unicodeChrClass, '$1 $2' ) );
}
});
};