Question

In Safari on iPhone and iPad the selector I have in place for the conditional statement isn't working and results in duplicate content with each ajax request. It works fine on android, chrome, firefox, ie and the desktop version of safari.

$('li.micropost').each(function() {
  var nlform, nlid;
  nlid = $(this).data('url');
  if ($("li#post" + nlid + " div.nl-field").length === 0) {
    nlform = new NLForm(document.getElementById("post" + nlid));
  }
});

here's the html

<li id="post<%= feed_item.id %>" class="micropost" data-url="<%= feed_item.id %>">...</li>

When the nlform variable is present it adds the following div to its respective list item

<div class="nl-field">...</div>

Without the nlform variable set this is what the html looks like inside of the <li> tag

<%= form_for((@micropost), :html => { :id => "nl-form", :class => "nl-form" }, :url => microposts_path, :authenticity_token => true) do |f| %>
    <!-- div will be added here if nlform variable is set -->
    <input type="text" value="" placeholder="type here" id="micropost_content1" name="micropost[content1]">
    <button id="btn<%= feed_item.id %>" class="nl-submit" type="submit" name="commit">Post</button>
<% end %>

My selector for Safari fails to recognize that my #nl-field class isn't equal to 0 so it creates a duplicate form variable resulting in duplicate nl-field divs with each ajax request.

I've also tried adding a letter to the beginning of the data-url attribute but that didn't help either.

This is the javascript that adds the dynamic content https://github.com/codrops/NaturalLanguageForm/blob/master/js/nlform.js

Update This has been very difficult to debug since I'm on a pc. If anyone can help with debugging this on mobile safari I can link to a live demo of the app, I would really appreciate it. I tried adding $('li.micropost').attr('class', 'micropos'); to the end of the loop so that when I loop on li.micropost it won't revisit the .micropos class but somehow safari still loops over each list item and duplicates content.

I've also tried iterating over each list item and removing duplicate divs

var seen = {};
$("li#post" + nlid + " .nl-field").each(function() {
   var txt = $(this).text();
   if (seen[txt])
      $(this).remove();
   else
      seen[txt] = true;
});

This hack almost works by limiting the amount of created duplicates to 2.

  • I've also tried removing the duplicate div thru the Jquery hierarchy like so

    $("li#post" + nlid + " .prompt + div").remove()

  • As well as only iterating over newly added list items which are all populated after a div with an id of 'infscr-loading' like this

    $( "#infscr-loading ~ li" )

  • I've tried appending a new element based on the presence of the nl-field div and giving that an id which I then run my condition against and that doesn't do the trick either.

All of these approaches work fine on chrome to prevent duplication. Idk what I'm doing wrong for safari to behave like this. FYI i'm running this code as a callback on jquery infinite scroll each time new objects are added to the page. It's written in javacript but for my app I'm converting it to coffeescript. Here's what the coffeescript looks like

$( "#infscr-loading ~ li" ).each ->
        nlid = $(this).data('url')
        nlform = new NLForm(document.getElementById "post" + nlid ) if $("li#post" + nlid + " .nl-field").length is 0
return

Here is a gist of the javascript used to create the dynamic nl-field div https://gist.github.com/anonymous/8cc2f09b2045f8f0d6c8

Was it helpful?

Solution

After over 50 commits to the live app I finally found the culprit. In my javascript file that creates the dynamic elements I had

Array.prototype.slice.call( this.el.querySelectorAll( 'input#micropost_content1' ) ).forEach( function( el, i ) {
  self.fldOpen++;
  self.fields.push( new NLField( self, el, 'input', self.fldOpen ) );
} );

I had to change 'input#micropost_content1' to use a class instead of an id and everything began working as intended.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top