Reputation: 270
I'm using a combination of Mark.js and Tooltipster to display some content. Mark.js appends a class (or multiple classes) to a specific string while the Tooltipster uses the class name to display appropriate content.
I have a bunch of arrays. One group of arrays are used by Mark.js to append classes to words. The other group is used by Tooltipster to display specific content.
For example lets say these arrays are used by Mark.js to append classes to specific words.
//mark.js will use words inside animalsArr to append a class "animal" to the
//words which match the content of this array.
var animalsArr = [
"/cat.*\b/gm",
"/dog.*\b/gm",
"/whale.*\b/gm"
]
//mark.js will use words inside continentsArr to append a class "continent" to the words
//which match the content of this array.
var continentsArr = [
"/Africa.*\b/gm,",
"/Asia.*\b/gm",
"/Australia.*\b/gm"
]
Some random text would look like this in HTML:
Some animals which live in <span class="continent">Africa</span> are </br>
<span class="animal">cat</span> and <span class="animal">dog</span>.
From here on out I'm using the tooltipster to append tooltips to these classes. Let's say I have the following "array" for animals
var animal = {
"prefix": {
"fur" : "Fur: ",
"legs" : "Legs : ",
"teeth" : "Teeth : "
},
"suffix" : {
"cat" : {
"fur" : "Yes.",
"legs" : "Yes.",
"teeth" : "Yes."
},
"dog" : {
"fur" : "Yes.",
"legs" : "Yes.",
"teeth" : "Yes."
},
"whale" : {
"fur" : "No.",
"legs" : "No.",
"teeth" : "No."
}
}
}
Now, let's say I use the cursor to hover over the word cat. I have written a function (with some additional code outside the function) that will display the following content -> Fur : Yes. Legs : Yes. Teeth: Yes. The same function is used for all the animals and it displays the content correctly.
The problem I am having is, that I would like to use the same function to display the content for continents and I can't figure out where to place it, so it can be used in with different tooltip "instances" (<- don't know the correct term).
lets say this is my function
function selectProperStringSet (classname){
//this function includes helper.origin
//it compares the cursor.textContent string with regexes inside animalsArr and selects the appropriate regex to be used from inside animalsArr
...
}
//additional code which selects object based on the regex from animal "array" (suffix.[animal].fur and displays the string
//ie: Fur: Yes. etc.
As you can see the function depends on the classname. For animals I would use selectProperStringSet(animal);
and add some code which would display the prefix.fur + suffix.[animal].fur
. The thing is, I don't want to copy paste the same function to every tooltipster "instance" ie -> ($(.animal).tooltipster({...
, $(.continent).tooltipster({...
).
I would like it to be located somewhere and I would just use the "classname" so the proper content is selected and can be displayed.
I have tried solving this in various ways.
1.) Place the function before the tooltipster is being intialized. In this case the problem is that helper.origin does not exists at this points.
helper.origin is undefined
or
cursor is not defined
(depending on how I try to dislocate / separate the code)
function tooltipsterStuff() {
function lookupArray(x){
let cursorArr = cursor.split(" "); //error: cursor is not defined
// etc
}
$('.animal').tooltipster({
contentAsHTML: true,
animation: 'grow',
updateAnimation: null,
interactive: true,
functionReady: function(instance, helper) {
var cursor = helper.origin.textContent;
//etc
lookupArray(animalsArr);
//etc
}
}
}
2.) I have tried nesting tooltipster classes (".tt" (<- origin.helper) and inside it ".animals") in this case it says
one or more tooltips are already attached to the element below. Ignoring.
function tooltipsterStuff() {
$('.tt').tooltipster({
contentAsHTML: true,
animation: 'grow',
updateAnimation: null,
interactive: true,
functionReady: function(instance, helper) {
var cursor = helper.origin.textContent;
function lookupArray(x){
let cursorArr = cursor.split(" ");
// etc
}
$('.animal').tooltipster({
//etc
lookupArray(animalsArr);
//etc
)};
}
)}
}
I'm at a loss as how to continue. Any help would be welcome. If I can provide any additional information please let me know.
Thank you.
Actual code:
function tooltipsterStuff() {
$('.tooltip').tooltipster();
$('.animal').tooltipster({
contentAsHTML: true,
animation: 'grow',
updateAnimation: null,
interactive: true,
functionReady: function(instance, helper) {
//creation of an empty array which will contain (partially) matched words
let lookupArr = [];
//variable which will contain the regex
let cursorRegex;
//cursor gains the textContent of current cursor location
let cursor = helper.origin.textContent;
// index which will be used to create a regex (at the very end)
let longestWordIndex;
/* I WOULD LIKE TO REUSE THIS FUNCTION FOR EACH TOOLTIPSTER INSTANCE */
/* This function compares the hovered on word with the list of regexes which were used by mark.js to mark a word in html. When match is found it is used outside of the function */
function lookupArray(x){
//if the variable cursor contains multiple words they will be split and inserted into an array
let cursorArr = cursor.split(" ");
//creation of an empty array which will contain indexes of (partially) matched words
let lookupArrIndex = [];
lookupOuter:
for (let i = 0; i < x.length; i++){
//variable which will insert the current location (index) of the string into the lookupArrIndex array
let lookupIndex = i;
//variable which will contain a string, which will be created inside the loop and will be added to lookupArray
let stringMatch = "";
//variable which contains regex from animalsArr -> starting / is removed
let currentString = x[i].toString();
currentString = currentString.substring(1);
//array which contains animal words(s)
let currentArr = currentString.split(" ");
//if animal contains the same number of words as the hovered/cursor class
if (currentArr.length == cursorArr.length){
//for cursorArr string.length
lookupMid:
for (let i = 0; i < cursorArr.length; i++){
//variable which contains cursorArr string
let cursorArrStr = cursorArr[i];
//variable which contains animal string
let currentArrStr = currentArr[i];
//logic to figure out if space should be added
let yy = i;
let newWord;
let oldWord;
newWord = i;
//for number of letters inside cursorArrStr
lookupInner:
for (let i = 0; i < cursorArrStr.length; i++){
if (stringMatch.length > 0 && newWord != oldWord){
stringMatch += " ";
}
if (cursorArrStr[i] == currentArrStr[i]){
stringMatch += cursorArrStr[i];
} else if (stringMatch.length > 0){
lookupArr.push(stringMatch);
lookupArrIndex.push(lookupIndex);
break lookupInner;
} else {
break lookupInner;
}
oldWord = yy;
}
}
}
}
// lookupArrIndex[i] matches lookupArr[i]. Longest lookupArr is used, with the matching lookupArrIndex
let longestWord;
let arr = [];
for(let i = 0; i < lookupArr.length; i++){
arr.push(lookupArr[i].length); //convert to number of characters inside the string
}
longestWord = 0;
for (let i = 0; i < arr.length; i++){
if (longestWord < arr[i]){
longestWord = arr[i]
longestWordIndex = lookupArrIndex[i];
}
}
cursorRegex = new RegExp(x[longestWordIndex]);
}
let forgeText = animal.prefix.fur;
let match;
/************************** start of class animal ***************************/
lookupArray(animalsArr);
let categoryAnimals = [];
for (let k in animal.suffix){
categoryAnimals.push(k);
}
catSuffixLoop:
for (let i = 0; i < categoryAnimals.length; i++){
if (cursorRegex.test(categoryAnimals[i]) === true){
match = animal.suffix[categoryAnimals[i]];
break catSuffixLoop;
}
}
forgeText += match.fur;
instance.content(
forgeText
)
/************************** end of class animal ***************************/
} //end ".animal"
})
}
Upvotes: 0
Views: 226
Reputation: 270
Solved.
Needed to place another argument into the functions brackets.
function tooltipsterStuff() {
function lookupArray(regexList, cursorOrigin){
//etc
Upvotes: 0