0

I've got a function set up to grab metadata from a provided URL on focusout, then use elements of that metadata (e.g. an image URL) to populate the next input in the DOM with a particular class (e.g. article_url). Using jQuery's index function to find the next input with a class, but it only seems to work once, e.g:

  • Paste URL into input with class article_id, the function runs and populates another input with class article_url with image URL.
  • Paste URL into second input with class article_id, the function runs, but does not populate second input with image URL.

Tried various permutations of next(), nextAll() and closest() with no luck.

$('#articles-wrapper').on('focusout', '.article_id', function(events) {
  metadata_url = $(this).val();
  $.get('https://cors-anywhere.herokuapp.com/' + metadata_url)
    .done(function(data, textStatus, jqXHR) {
      meta_title = $(data).filter('meta[property="og:title"]').attr("content");
      meta_image = $(data).filter('meta[property="og:image"]').attr("content");
      meta_desc = $(data).filter('meta[property="og:description"]').attr("content");
      meta_author = $(data).filter('meta[property="og:author"]').attr("content");
      meta_date = $(data).filter('meta[property="article:published_time"]').attr("content");
      console.log(meta_title);
      console.log(meta_image);
      console.log(meta_desc);
      console.log(meta_author);
      console.log(meta_date);
      currIndex = $(this).index();
      console.log(currIndex);
      $('.article_url').eq(currIndex + 1).val(meta_image);
      $('.article_title').eq(currIndex + 1).val(meta_title);
      $('.article_desc').eq(currIndex + 1).val(meta_desc);
    })
    .fail(function(jqXHR, textStatus, errorThrown) {
      console.log(jqXHR);
      console.log(textStatus);
      console.log(errorThrown);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="articles-wrapper">
  <div class="article-item">
    <div class="article-header-wrapper">
      <div class="article-item-header">
        <h4>Article 1</h4>
      </div>
    </div>
    <input class="lastarticle" id="lastarticle" type="checkbox" name="lastarticle">
    <label for="lastarticle" style="padding-bottom:10px;">Last article?</label>
    <label>
        Article Link
        <input type="text" class="article_id">
    </label>
    <label>
        Title
        <input type="text" class="article_title">
    </label>
    <label>
        Description
        <input type="text" class="article_desc" value="bundle://">
    </label>
    <div class="article-url-wrapper">
      <label>
          Image
          <input type="text" name="articleurl[]" class="article_url">
      </label>
    </div>
    <hr>
  </div>
</div>

I'd expect the function to always populate the next input in the DOM with class article_url with variable meta_image.

msg
  • 7,863
  • 3
  • 14
  • 33
mjones87
  • 11
  • 2

1 Answers1

0

Inside of your done callback this doesn't reference the element that was triggered, but the config of the ajax request itself. You have to either bind the element manually by:

$.get('https://cors-anywhere.herokuapp.com/' + metadata_url)
    .done(function(data, textStatus, jqXHR) {
        // Implementation
    }.bind(this))

Or you can use the context option in the jQuery.ajax() method:

$.get({
  url: 'https://cors-anywhere.herokuapp.com/' + metadata_url,
  context: this
})

However, $(this).index() will always return 0, since index() returns

an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

and there are no other elements in the collection. For it to work as you expect you'll have to use

currIndex = $('.article_id').index(this);
// No need to add one, this will find the element inside the same .article_item
$('.article_url').eq(currIndex).val(meta_image);
$('.article_title').eq(currIndex).val(meta_title);
$('.article_desc').eq(currIndex).val(meta_desc);

Alternatively, you can search for the elements inside the same .article_item by restricting the selector search scope:

$article = $(this).closest('.article-item');
$('.article_url', $article).val(meta_image);
// ...

Finally, I'd advise you to cache your jQuery objects:

const $data = $(data);

And use the $data variable to extract your elements, since you are constantly recreating the object every time you access it.

msg
  • 7,863
  • 3
  • 14
  • 33