WeAreDoomed
WeAreDoomed

Reputation: 270

tooltipster - using one function on multiple tooltips - problem with origin.helper or one or more tooltips already exists

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

Answers (1)

WeAreDoomed
WeAreDoomed

Reputation: 270

Solved.

Needed to place another argument into the functions brackets.

function tooltipsterStuff() {
   
    function lookupArray(regexList, cursorOrigin){
        //etc

Upvotes: 0

Related Questions