-1

I'm using an ajax request to display a loop of drupal posts.

    $( document ).ready(function() {
$.ajax({
    type:"GET",
    url:"https://www.nba.com/api/1.1/json/?type=photo_gallery&tags=community&size=4",
    success: function(data) {
    let galleriesWrapper = document.getElementById("wrapper--community-galleries");
    function create(tagName, props) {
      return Object.assign(document.createElement(tagName), (props || {}));
    }
    function ac(p, c) {
      if (c) p.appendChild(c);
      return p;
   }
for (var i=0; i< data.content.length; i++) {
var link = create("a", {
  className: "wrapper--single-gallery",
  href: data.content[i].url,
  style: "background-image:url(" + data.content[i].images.large + ")"
});
var videoTitle = create("div", {
  className: "single-gallery--title",
  src: data.content[i].title
});
videoTitle.textContent = data.content[i].title;
ac(galleriesWrapper, ac(link, videoTitle));
      } 
    },
    dataType: "jsonp",
  });
});

I'm pulling the post's image from the .json file and injecting it as the css background-image for that particular item in the loop.

This all works perfectly fine in Chrome and Firefox but fails in IE.

I'm using the helper function "create" which uses obect.assign to easily create and append DOM elements.

My first failure it IE was because I needed an object.asign polyfill. No items were showing up.

The Polyfill:

if (typeof Object.assign != 'function') {
Object.assign = function(target) {
'use strict';
if (target == null) {
  throw new TypeError('Cannot convert undefined or null to object');
}

target = Object(target);
for (var index = 1; index < arguments.length; index++) {
  var source = arguments[index];
  if (source != null) {
    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
}
  return target;
  };
}

Once I added this to the top of my JS, the loop items get displayed in IE, but the code I am using to inject the background-image style inline fails (I see an item with the proper post title from the ajax request, but the background is blank).

EDIT: Seems the issue is with trying to append the style property. When I use this:

var link = create("a", {
  className: "wrapper--single-gallery",
  href: data.content[i].url,
  style: "background-image:url(" + data.content[i].images.large + ")"
});

The link is created with the class name and the href, but the style property is not appended.

Thinking it had something to do with how I spliced in the url from the json request data, I tried just using the style "color:red". This created the same result of not appending the style tag to the link.

JS FIDDLE EXAMPLE: https://jsfiddle.net/nolaandy/w3gfawcg/

4ndy
  • 446
  • 7
  • 26
  • Does this actually have anything to do with object.assign? – Kevin B Nov 29 '17 at 20:33
  • Well it's an IE issue if you happened to look at the JS Fiddle on both browsers. Since IE cannot use object.asign, I had to use the polyfill. The code works perfectly on other browsers. Do you know what kind of issue this is? – 4ndy Nov 29 '17 at 20:35
  • One thing that jumps out at me is your object that you passed to `create` seems to be setting properties, and the style property's value is a bit different from what you'd put in the attribute. but maybe `create` is doing something different based on which property is passed. Dunno, cuz i can't see a `create` method in your question and the fiddle isn't loading. – Kevin B Nov 29 '17 at 20:35
  • yeah that's very likely the problem. You're treating the style property as if it were an attribute. Not really related to object.assign at all, other than it just being the wrong tool. – Kevin B Nov 29 '17 at 20:37
  • In my edit I said I tried "color:red" for simplicity and it still didn't work.The JS Fiddle does load. I have tried it on an incognito tab. The create function is listed in the question as this: function create(tagName, props) { return Object.assign(document.createElement(tagName), (props || {})); } – 4ndy Nov 29 '17 at 20:39
  • `color: red` is also an invalid value for the style property. – Kevin B Nov 29 '17 at 20:39
  • Because of the missing trailing semi-colon? Is not the value of an inline-style property that colors text red "color:red;"? – 4ndy Nov 29 '17 at 20:41
  • 1
    https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style *"Styles should not be set by assigning a string directly to the style property (as in elt.style = "color: blue;"), since it is considered read-only, as the style attribute returns a CSSStyleDeclaration object which is also read-only. Instead, styles can be set by assigning values to the properties of style."* – Kevin B Nov 29 '17 at 20:41
  • Thanks Kevin. I'll look into that more for a potential solution. – 4ndy Nov 29 '17 at 20:43

2 Answers2

2

The problem is not Object.assign itselt. The problem is how you're setting the styles.

You have two options:

  1. Set every style to the style property of the element

    link.style.backgroundImage = "url(" + data.content[i].images.large + ")"
    
  2. Replace Object.assign by _.merge and set the styles as an object (https://lodash.com/)

    function create(tagName, props) {
        // Replace Object.assign by _.merge (https://lodash.com/)
        return _.merge(document.createElement(tagName), (props || {}));
    }
    
    // ....
    
    var link = create("a", {
       className: "wrapper--single-gallery",
       href: data.content[i].url,
       // Update the styles to be an object
       style: {
           backgroundImage: "url(" + data.content[i].images.large + ")"
      }
    });
    

I would go for the second one since it's cleaner: https://jsfiddle.net/w3gfawcg/7/

lleon
  • 2,615
  • 1
  • 20
  • 14
1

Blake's responses led me to the solution. Thank you Blake.

This is the easy solution:

for (var i=0; i< data.content.length; i++) {
var link = create("a", {
  className: "wrapper--single-gallery",
  href: data.content[i].url,
});
$(link).css("background-image", "url(" + data.content[i].images.large + ")");
}

From Blake/Mozilla: "Styles should not be set by assigning a string directly to the style property (as in elt.style = "color: blue;"), since it is considered read-only, as the style attribute returns a CSSStyleDeclaration object which is also read-only. Instead, styles can be set by assigning values to the properties of style."

This is weird seeing as Firefox ran the original code properly even though I was doing it wrong.

4ndy
  • 446
  • 7
  • 26