0

I am using the official Cloudinary AngularJS directive to place images on my site. However, Chrome and IE 11 are behaving differently in terms of where they place a closing </img> tag. IE places it just before the parent element closes and Chrome properly places it after the transcluded element.

Here are snippets of the relevant Cloudinary directives (from their official plugin):

angularModule.directive('clTransformation', function() {
  return {
    restrict : 'E',
    transclude : false,
    require: '^clImage',
    link : function (scope, element, attrs, clImageCtrl) {
      var attributes = {};
      $.each(attrs, function(name,value){
        if (name[0] !== '$') {
          attributes[cloudinaryAttr(name)] = value;
        }
      });
      clImageCtrl.addTransformation(attributes);
    }
  }
});

angularModule.directive('clImage', function() {
  return {
    restrict : 'E',
    replace: true,
    transclude : true,
    template: "<img ng-transclude/>",
    scope: {},
    priority: 99,
    controller: function($scope) {
      this.addTransformation = function(ts){
        $scope.transformations = $scope.transformations || [];
        $scope.transformations.push(ts);
      }
    },
...

I've implemented these in my site with:

<figure>
  <cl-image
    ng-repeat='image in images'
    public_id='{{image.public_id}}'
    format='jpg'>
      <cl-transformation
        height='{{imgHeight}}'
        width='{{imgWidth}}'
        crop='{{crop}}'>
  </cl-image>
  <a href='' ...></a>
  <a href='' ...'></a>
  <div class='nav'>
    <div class='wrapper'>
      <ul>
        <li>
          <a href='' ...></a>
        </li>
        ...
      </ul>
    </div>
  </div>
  <figcaption><{{description}}></figcaption>
</figure>

Opening the site in Chrome, the DOM gets updated as

<figure>
  <img ng-transclude="" public_id="wide/image1" format="jpg" src="http://res.cloudinary.com/<account id>/image/upload/c_fill,h_370,w_1130/v1/wide/image1.jpg">
    <cl-transformation height="370" width="1130" crop="fill" class="ng-scope">
    </cl-transformation>
  </img>   <!---------------- img close tag is here ---------------------->
  <img ...>
    ...
  </img>
  <a href='' ...></a>
  <a href='' ...></a>
  ...
</figure>

However, in IE, the DOM gets updated as:

<figure>
  <img ng-transclude="" public_id="wide/image1" format="jpg" src="http://res.cloudinary.com/<account id>/image/upload/a_exif,c_fill,g_center,h_370,w_1130/v1/wide/image1.jpg">
    <cl-transformation height="370" width="1130" crop="fill" class="ng-scope">
    </cl-transformation>
  <a href='' ...></a>
  <a href='' ...></a>
    <div class='nav'>
      <div class='wrapper'>
        <ul>
          <li>
            <a href='' ...></a>
          </li>
          ...
        </ul>
      </div>
    </div>
    <figcaption><{{description}}></figcaption>
  </img>   <!---------------- img close tag is here :( ---------------------->
  <img ...>
     ...
  </img>
</figure>

This causes all of the <a>, <div>, <ul>, <li>, <figcaption> tags to not be rendered.

I've tried changing the clImage directive to use a template like <img ng-transclude></img> but I get the same results. What is happening to the </img> tag in IE and how can I resolve this?

drs
  • 5,679
  • 4
  • 42
  • 67
  • 3
    Is this some AngularJS idiom? `` is *never* supposed to have an end tag. – BoltClock Jul 11 '14 at 16:35
  • which also means the `` tag can never contain other elements; if it does, you can't expect it to behave the same way across all browsers. (Just don't do it.) – ps2goat Jul 11 '14 at 16:37
  • @ps2goat: The kicker here is that AngularJS appears to be relying on that to work, which this is not the first time I've seen it try to do. – BoltClock Jul 11 '14 at 16:40
  • @BoltClock I know. Neither the Cloudinary AngularJS template nor my own elements include ``. However when I inspect them with the browsers' debugging tools, they show the DOM as having an `` tag. It might be an AngularJS side effect of transclusion with `` – drs Jul 11 '14 at 16:41

1 Answers1

2

For non-chained transformations like the one you have shown putting the transformation parameters on the image tag itself should do the trick. In this case:

<cl-image
  ng-repeat='image in images'
  public_id='{{image.public_id}}'
  height='{{imgHeight}}'
  width='{{imgWidth}}'
  crop='{{crop}}'
  format='jpg'>

If you ever need to have chained transformations and would like to avoid using the internal transformation tags you can instead use the raw-transformation attribute on the cl-image tag:

<cl-image
  ng-repeat='image in images'
  public_id='{{image.public_id}}'
  raw-transformation='c_crop,h_100,w_150/a_45'
  format='jpg'>

The above example chains another rotation of 45 degrees on top of the cropping transformation found before.

Have a look in the sample project for a variety of image tag examples.

Itai Benari
  • 61
  • 1
  • 3