简体   繁体   中英

Accessing variables from a parent function within a jQuery click() event (Word add-in)

The code for my add-in takes a search term, then displays a list of matching links on a table. Each link is supposed to insert itself into a word document when it's clicked, but I can't figure out how to pass variables in to a jQuery .click() function.

Currently, no matter what option I click, the URL of the link that gets inserted into the word document is always the URL of the last item on the list. So for example, if I had 3 results in the table: Facebook, Instagram and Yahoo, then whatever option I click, the URL that gets inserted is always http://www.yahoo.com

function displayLinks() {

    // Empty pre-existing results
    $('#linksTable').empty();
    var filteredLinks = [];

    // Grab value from search box
    var searchTerm = document.getElementById('linksSearchField').value;

    // Separate all links containing search term and put them in a filtered list
    for (var i = 0; i < numberOfLinks; i++) {
        if (sortedLinks[i].linkName.toLowerCase().includes(searchTerm.toLowerCase())){
            filteredLinks.push(sortedLinks[i]);
        }
    }

    // Get length of filtered links array
    var numberOfSearchResults = filteredLinks.length;

    // Populate table with loop
    if (searchTerm != '') {
        for (var x = 0; x < numberOfSearchResults; x++) {

            var table = document.getElementById('linksTable');
            var row = table.insertRow(x);
            var nameCell = row.insertCell(0);

            var linkName = filteredLinks[x].linkName;
            var linkNameFormattedForID = linkName.replace(/([ &/!*^%$#@+_-])+/g);
            var linkURL = filteredLinks[x].linkURL;

            // Add link to table
            nameCell.innerHTML = "<a href='javascript:void(0);' id='" + linkNameFormattedForID + "'>" + linkName + "</a>";

            // Code to add link to word document
            $('#' + linkNameFormattedForID).click(linkName, function (linkName) {

                Word.run(function (context) {
                    const doc = context.document;
                    const originalRange = doc.getSelection();
                    originalRange.insertHtml("<a href='" + linkURL + "'>" + linkName.currentTarget.innerText + "</a>", "Start");
                    originalRange.insertText("Refer to ", "Start");
                    originalRange.load("text");
                    return context.sync()
                })
                    .catch(function (error) {
                        console.log("Error: " + error);
                        if (error instanceof OfficeExtension.Error) {
                            console.log("Debug info: " + JSON.stringify(error.debugInfo));
                        }
                    });
            });
        }
    }
}

I think I could maybe fix the problem by defining the linkURL variable within the click function itself, but the issue is that I can't access filteredLinks[x] inside of it. I can access the filteredLinks array on its own, but it can't read x , even though the click function is contained within the loop?

As a last-resort super hacky fix, I think I could just change the ID of each item to include it's URL, then extract it from linkName.currentTarget.innerText , but I'd rather not do that unless I really have to.

Thanks in advance!

The problem is that var in JavaScript is function scoped, and because the click event gets invoked after the for loop ends, the value of x will always be the final value of x . There's more information in pleanty of blog posts like this one: https://medium.com/front-end-developers/es6-variable-scopes-in-loops-with-closure-9cde7a198744

The solution:

Use let or const instead of var

A slightly worse solution:

wrap the contents of the for loop inside an IIFE

for (var x = 0; x < numberOfSearchResults; x++) {
  (function(x){
       ...
   })(x);
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM