Hi!

First, I want to apologise for having pasted all this code in this post, but
tinyurl said "414 Request-URI Too Large"

In order to hack a bit the qx.ui.basic.Image code.. I had to copy the source
in the playgground into a new class "kreimer.MyImage2"

inserting  a few lines in the __checkForContentElementReplacement private
method:
          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer

I don't know for sure if its the best solution, it's not fully tested, but
it seems to solve the issue. Can somebody try this? Thanks everybody in the
community!

Here, the code to paste into the playground: 

qx.Class.define("kreimer.MyImage2", {
 extend : qx.ui.core.Widget,



  /*
 
*****************************************************************************
     CONSTRUCTOR
 
*****************************************************************************
  */

  /**
   * @param source {String?null} The URL of the image to display.
   */
  construct : function(source)
  {
    this.__contentElements = {};

    this.base(arguments);

    if (source) {
      this.setSource(source);
    }
  },




  /*
 
*****************************************************************************
     PROPERTIES
 
*****************************************************************************
  */

  properties :
  {
    /** The URL of the image. Setting it will possibly abort loading of
current image. */
    source :
    {
      check : "String",
      init : null,
      nullable : true,
      event : "changeSource",
      apply : "_applySource",
      themeable : true
    },


    /**
     * Whether the image should be scaled to the given dimensions
     *
     * This is disabled by default because it prevents the usage
     * of image clipping when enabled.
     */
    scale :
    {
      check : "Boolean",
      init : false,
      themeable : true,
      apply : "_applyScale"
    },


    // overridden
    appearance :
    {
      refine : true,
      init : "image"
    },


    // overridden
    allowShrinkX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowShrinkY :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowX :
    {
      refine : true,
      init : false
    },


    // overridden
    allowGrowY :
    {
      refine : true,
      init : false
    }
  },


  /*
 
*****************************************************************************
     EVENTS
 
*****************************************************************************
  */

  events :
  {
    /**
     * Fired if the image source can not be loaded. This event can only be
     * fired for the first loading of an unmanaged resource (external
image).
     */
    loadingFailed : "qx.event.type.Event",


    /**
     * Fired if the image has been loaded. This is even true for managed
     * resources (images known by generator).
     */
    loaded : "qx.event.type.Event",


    /** Fired when the pending request has been aborted. */
    aborted : "qx.event.type.Event"
  },


  statics:
  {
    PLACEHOLDER_IMAGE:
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
  },

  /*
 
*****************************************************************************
     MEMBERS
 
*****************************************************************************
  */

  members :
  {
    __width : null,
    __height : null,
    __mode : null,
    __contentElements : null,
    __currentContentElement : null,
    __wrapper : null,
    __requestId : 0,


    //overridden
    _onChangeTheme : function() {
      this.base(arguments);
      // restyle source (theme change might have changed the resolved url)
      this._styleSource();
    },

    /*
   
---------------------------------------------------------------------------
      WIDGET API
   
---------------------------------------------------------------------------
    */

    // overridden
    getContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _createContentElement : function() {
      return this.__getSuitableContentElement();
    },


    // overridden
    _getContentHint : function()
    {
      return {
        width : this.__width || 0,
        height : this.__height || 0
      };
    },

    // overridden
    _applyDecorator : function(value, old) {
      this.base(arguments, value, old);

      var source = this.getSource();
      source = qx.util.AliasManager.getInstance().resolve(source);
      var el = this.getContentElement();
      if (this.__wrapper) {
        el = el.getChild(0);
      }
      this.__setSource(el, source);
    },


    // overridden
    _applyPadding : function(value, old, name)
    {
      this.base(arguments, value, old, name);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      } else {
        element.setPadding(
          this.getPaddingLeft() || 0, this.getPaddingTop() || 0
        );
      }

    },

    renderLayout : function(left, top, width, height) {
      this.base(arguments, left, top, width, height);

      var element = this.getContentElement();
      if (this.__wrapper) {
        element.getChild(0).setStyles({
          width: width - (this.getPaddingLeft() || 0) -
(this.getPaddingRight() || 0),
          height: height - (this.getPaddingTop() || 0) -
(this.getPaddingBottom() || 0),
          top: this.getPaddingTop() || 0,
          left: this.getPaddingLeft() || 0
        });
      }
    },




    /*
   
---------------------------------------------------------------------------
      IMAGE API
   
---------------------------------------------------------------------------
    */

    // property apply, overridden
    _applyEnabled : function(value, old)
    {
      this.base(arguments, value, old);

      if (this.getSource()) {
        this._styleSource();
      }
    },


    // property apply
    _applySource : function(value, old)
    {
      // abort loading current image
      if (old) {
        if (qx.io.ImageLoader.isLoading(old)) {
          qx.io.ImageLoader.abort(old);
        }
      }

      this._styleSource();
    },


    // property apply
    _applyScale : function(value) {
      this._styleSource();
    },


    /**
     * Remembers the mode to keep track which contentElement is currently in
use.
     * @param mode {String} internal mode (alphaScaled|scaled|nonScaled)
     */
    __setMode : function(mode) {
      this.__mode = mode;
    },


    /**
     * Returns the current mode if set. Otherwise checks the current source
and
     * the current scaling to determine the current mode.
     *
     * @return {String} current internal mode
     */
    __getMode : function()
    {
      if (this.__mode == null)
      {
        var source = this.getSource();
        var isPng = false;
        if (source != null) {
          isPng = qx.lang.String.endsWith(source, ".png");
        }

        if (this.getScale() && isPng &&
qx.core.Environment.get("css.alphaimageloaderneeded")) {
          this.__mode = "alphaScaled";
        } else if (this.getScale()) {
          this.__mode = "scaled";
        } else {
          this.__mode = "nonScaled";
        }
      }

      return this.__mode;
    },


    /**
     * Creates a contentElement suitable for the current mode
     *
     * @param mode {String} internal mode
     * @return {qx.html.Image} suitable image content element
     */
    __createSuitableContentElement : function(mode)
    {
      var scale;
      var tagName;
      if (mode == "alphaScaled")
      {
        scale = true;
        tagName = "div";
      }
      else if (mode == "nonScaled")
      {
        scale = false;
        tagName = "div";
      }
      else
      {
        scale = true;
        tagName = "img";
      }

      var element = new qx.html.Image(tagName);
      element.setAttribute("$$widget", this.toHashCode());
      element.setScale(scale);
      element.setStyles({
        "overflowX": "hidden",
        "overflowY": "hidden",
        "boxSizing": "border-box"
      });

      if (qx.core.Environment.get("css.alphaimageloaderneeded")) {
        var wrapper = this.__wrapper = new qx.html.Element("div");
        wrapper.setAttribute("$$widget", this.toHashCode());
        wrapper.setStyle("position", "absolute");
        wrapper.add(element);
        return wrapper;
      }

      return element;
    },


    /**
     * Returns a contentElement suitable for the current mode
     *
     * @return {qx.html.Image} suitable image contentElement
     */
    __getSuitableContentElement : function()
    {
      if (this.$$disposed) {
        return null;
      }

      var mode = this.__getMode();

      if (this.__contentElements[mode] == null) {
        this.__contentElements[mode] =
this.__createSuitableContentElement(mode);
      }

      var element = this.__contentElements[mode];

      if (!this.__currentContentElement) {
        this.__currentContentElement = element;
      }

      return element;
    },


    /**
     * Applies the source to the clipped image instance or preload
     * an image to detect sizes and apply it afterwards.
     *
     */
    _styleSource : function()
    {
      var AliasManager = qx.util.AliasManager.getInstance();
      var ResourceManager = qx.util.ResourceManager.getInstance();

      var source = AliasManager.resolve(this.getSource());

      var element = this.getContentElement();
      if (this.__wrapper) {
        element = element.getChild(0);
      }

      if (!source)
      {
        element.resetSource();
        return;
      }

      this.__checkForContentElementSwitch(source);

      if ((qx.core.Environment.get("engine.name") == "mshtml") &&
        (parseInt(qx.core.Environment.get("engine.version"), 10) < 9 ||
         qx.core.Environment.get("browser.documentmode") < 9))
      {
        var repeat = this.getScale() ? "scale" : "no-repeat";
        element.tagNameHint = qx.bom.element.Decoration.getTagName(repeat,
source);
      }

      var contentEl = this.__getContentElement();

      // Detect if the image registry knows this image
      if (qx.util.ResourceManager.getInstance().has(source)) {
        var highResolutionSource = this._findHighResolutionSource(source);
        if (highResolutionSource) {
          var imageWidth = ResourceManager.getImageHeight(source);
          var imageHeight = ResourceManager.getImageWidth(source);
          this.setWidth(imageWidth);
          this.setHeight(imageHeight);
          
          // set backgroud size on current element (div or img)
          var backgroundSize = imageWidth + "px, " + imageHeight + "px";
          this.__currentContentElement.setStyle("background-size",
backgroundSize);

          this.setSource(highResolutionSource);
          source = highResolutionSource;
        }
        this.__setManagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else if (qx.io.ImageLoader.isLoaded(source)) {
        this.__setUnmanagedImage(contentEl, source);
        this.__fireLoadEvent();
      } else {
        this.__loadUnmanagedImage(contentEl, source);
      }
    },


    /**
     * Helper function, which fires <code>loaded</code> event
asynchronously.
     * It emulates native <code>loaded</code> event of an image object. This
     * helper will be called, if you try to load a managed image or an
     * previously loaded unmanaged image.
     */
    __fireLoadEvent : function()
    {
      this.__requestId++;
      qx.bom.AnimationFrame.request(function(rId){
        // prevent firing of the event if source changed in the meantime
        if (rId === this.__requestId) {
          this.fireEvent("loaded");
        } else {
          this.fireEvent("aborted");
        }
      }.bind(this, this.__requestId));
    },


    /**
     * Returns the content element.
     * @return {qx.html.Image} content element
     */
    __getContentElement : function()
    {
      var contentEl = this.__currentContentElement;
      if (this.__wrapper) {
        contentEl = contentEl.getChild(0);
      }

      return contentEl;
    },


    /**
     * Checks if the current content element is capable to display the image
     * with the current settings (scaling, alpha PNG)
     *
     * @param source {String} source of the image
     */
    __checkForContentElementSwitch :
qx.core.Environment.select("engine.name",
    {
      "mshtml" : function(source)
      {
        var alphaImageLoader =
qx.core.Environment.get("css.alphaimageloaderneeded");
        var isPng = qx.lang.String.endsWith(source, ".png");

        if (alphaImageLoader && isPng)
        {
          if (this.getScale() && this.__getMode() != "alphaScaled") {
            this.__setMode("alphaScaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }
        else
        {
          if (this.getScale() && this.__getMode() != "scaled") {
            this.__setMode("scaled");
          } else if (!this.getScale() && this.__getMode() != "nonScaled") {
            this.__setMode("nonScaled");
          }
        }

       
this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      },

      "default" : function(source)
      {
        if (this.getScale() && this.__getMode() != "scaled") {
          this.__setMode("scaled");
        } else if (!this.getScale() && this.__getMode("nonScaled")) {
          this.__setMode("nonScaled");
        }

       
this.__checkForContentElementReplacement(this.__getSuitableContentElement());
      }
    }),


    /**
     * Checks the current child and replaces it if necessary
     *
     * @param elementToAdd {qx.html.Image} content element to add
     */
    __checkForContentElementReplacement : function(elementToAdd)
    {
      
      var currentContentElement = this.__currentContentElement;

      if (currentContentElement != elementToAdd)
      {
        if (currentContentElement != null)
        {
          var pixel = "px";
          var styles = {};
          
          // kreimer
          var currentStyles = currentContentElement.getAllStyles();
          this.info("currentStyles" + currentStyles);
          for(var prop in currentStyles) {
              styles[prop] = currentStyles[prop];
          }
          //kreimer
          
          // Copy dimension and location of the current content element
          var bounds = this.getBounds();
          if (bounds != null)
          {
            styles.width = bounds.width + pixel;
            styles.height = bounds.height + pixel;
          }

          var insets = this.getInsets();
          styles.left = parseInt(currentContentElement.getStyle("left") ||
insets.left) + pixel;
          styles.top = parseInt(currentContentElement.getStyle("top") ||
insets.top) + pixel;

          styles.zIndex = 10;

          var newEl = this.__wrapper ? elementToAdd.getChild(0) :
elementToAdd;
          newEl.setStyles(styles, true);
          newEl.setSelectable(this.getSelectable());

          if (!currentContentElement.isVisible()) {
            elementToAdd.hide();
          }

          if (!currentContentElement.isIncluded()) {
            elementToAdd.exclude();
          }

          var container = currentContentElement.getParent();

          if (container) {
            var index =
container.getChildren().indexOf(currentContentElement);
            container.removeAt(index);
            container.addAt(elementToAdd, index);
          }
          // force re-application of source so __setSource is called again
          var hint = newEl.getNodeName();
          newEl.setSource(null);
          var currentEl = this.__getContentElement();
          newEl.tagNameHint = hint;
          newEl.setAttribute("class", currentEl.getAttribute("class"));

          // Flush elements to make sure the DOM elements are created.
          qx.html.Element.flush();
          var currentDomEl = currentEl.getDomElement();
          var newDomEl = elementToAdd.getDomElement();

          // copy event listeners
          var listeners = currentContentElement.getListeners() || [];
          listeners.forEach(function(listenerData) {
            elementToAdd.addListener(listenerData.type,
listenerData.handler, listenerData.self, listenerData.capture);
          });

          if (currentDomEl && newDomEl) {
            // Switch the DOM elements' hash codes. This is required for the
event
            // layer to work [BUG #7447]
            var currentHash = currentDomEl.$$hash;
            currentDomEl.$$hash = newDomEl.$$hash;
            newDomEl.$$hash = currentHash;
          }

          this.__currentContentElement = elementToAdd;
        }
      }
    },


    /**
     * Use the ResourceManager to set a managed image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setManagedImage : function(el, source)
    {
      var ResourceManager = qx.util.ResourceManager.getInstance();

      // Try to find a disabled image in registry
      if (!this.getEnabled())
      {
        var disabled = source.replace(/\.([a-z]+)$/, "-disabled.$1");
        if (ResourceManager.has(disabled))
        {
          source = disabled;
          this.addState("replacement");
        }
        else
        {
          this.removeState("replacement");
        }
      }

      // Optimize case for enabled changes when no disabled image was found
      if (el.getSource() === source) {
        return;
      }

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      this.__updateContentHint(
        ResourceManager.getImageWidth(source),
        ResourceManager.getImageHeight(source)
      );
    },


    /**
     * Use the infos of the ImageLoader to set an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      // Apply source
      this.__setSource(el, source);

      // Compare with old sizes and relayout if necessary
      var width = ImageLoader.getWidth(source);
      var height = ImageLoader.getHeight(source);
      this.__updateContentHint(width, height);
    },


    /**
     * Use the ImageLoader to load an unmanaged image
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __loadUnmanagedImage : function(el, source)
    {
      var ImageLoader = qx.io.ImageLoader;

      if (qx.core.Environment.get("qx.debug"))
      {
        // loading external images via HTTP/HTTPS is a common usecase, as is
        // using data URLs.
        var sourceLC = source.toLowerCase();
        var startsWith = qx.lang.String.startsWith;
        if (!startsWith(sourceLC, "http") &&
            !startsWith(sourceLC, "data:image/"))
        {
          var self = this.self(arguments);

          if (!self.__warned) {
            self.__warned = {};
          }

          if (!self.__warned[source])
          {
            this.debug("try to load an unmanaged relative image: " +
source);
            self.__warned[source] = true;
          }
        }
      }

      // only try to load the image if it not already failed
      if(!ImageLoader.isFailed(source)) {
        ImageLoader.load(source, this.__loaderCallback, this);
      } else {
        if (el != null) {
          el.resetSource();
        }
      }
    },


    /**
     * Combines the decorator's image styles with our own image to make sure
     * gradient and backgroundImage decorators work on Images.
     *
     * @param el {Element} image DOM element
     * @param source {String} source path
     */
    __setSource: function (el, source) {
      if (el.getNodeName() == "div") {

        // checks if a decorator already set.
        // In this case we have to merge background styles
        var decorator =
qx.theme.manager.Decoration.getInstance().resolve(this.getDecorator());
        if (decorator) {
          var hasGradient = (decorator.getStartColor() &&
decorator.getEndColor());
          var hasBackground = decorator.getBackgroundImage();
          if (hasGradient || hasBackground) {
            var repeat = this.getScale() ? "scale" : "no-repeat";

            // get the style attributes for the given source
            var attr = qx.bom.element.Decoration.getAttributes(source,
repeat);
            // get the background image(s) defined by the decorator
            var decoratorStyle = decorator.getStyles(true);

            var combinedStyles = {
              "backgroundImage": attr.style.backgroundImage,
              "backgroundPosition": (attr.style.backgroundPosition || "0
0"),
              "backgroundRepeat": (attr.style.backgroundRepeat ||
"no-repeat")
            };

            if (hasBackground) {
              combinedStyles["backgroundPosition"] += "," +
decoratorStyle["background-position"] || "0 0";
              combinedStyles["backgroundRepeat"] += ", " +
decorator.getBackgroundRepeat();
            }

            if (hasGradient) {
              combinedStyles["backgroundPosition"] += ", 0 0";
              combinedStyles["backgroundRepeat"] += ", no-repeat";
            }

            combinedStyles["backgroundImage"] += "," +
decoratorStyle["background-image"];

            // apply combined background images
            el.setStyles(combinedStyles);

            return;
          }
        } else {
          // force re-apply to remove old decorator styles
          el.setSource(null);
        }
      }

      el.setSource(source);
    },

    /**
     * Detects whether there is a high-resolution image available.
     * A high-resolution image is assumed to have the same file name as
     * the parameter source, but with a pixelRatio identifier before the
file
     * extension, like "@2x".
     * Medium Resolution: "example.png", high-resolution: "exam...@2x.png"
     *
     * @param lowResImgSrc {String} source of the low resolution image.
     * @return {String|Boolean} If a high-resolution image source.
     */
    _findHighResolutionSource: function(lowResImgSrc) {
      var pixelRatioCandidates = ["3", "2", "1.5"];

      // Calculate the optimal ratio, based on the rem scale factor of the
application and the device pixel ratio.
      var factor =
parseFloat(qx.bom.client.Device.getDevicePixelRatio().toFixed(2));
      if (factor <= 1) {
        return false;
      }

      var i = pixelRatioCandidates.length;
      while (i > 0 && factor > pixelRatioCandidates[--i]) {}

      var hiResImgSrc;
      var k;

      // Search for best img with a higher resolution.
      for (k = i; k >= 0; k--) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      // Search for best img with a lower resolution.
      for (k = i + 1; k < pixelRatioCandidates.length; k++) {
        hiResImgSrc = this._getHighResolutionSource(lowResImgSrc,
pixelRatioCandidates[k]);
        if (hiResImgSrc) {
          return hiResImgSrc;
        }
      }

      return null;
    },

    /**
     * Returns the source name for the high-resolution image based on the
passed
     * parameters.
     * @param source {String} the source of the medium resolution image.
     * @param pixelRatio {Number} the pixel ratio of the high-resolution
image.
     * @return {String} the high-resolution source name or null if no source
could be found.
     */
    _getHighResolutionSource : function(source, pixelRatio) {
      var fileExtIndex = source.lastIndexOf('.');
      if (fileExtIndex > -1) {
        var pixelRatioIdentifier = "@" + pixelRatio + "x";
        var candidate = source.slice(0, fileExtIndex) + pixelRatioIdentifier
+ source.slice(fileExtIndex);

        if(qx.util.ResourceManager.getInstance().has(candidate)) {
          return candidate;
        }
      }
      return null;
    },

    /**
     * Event handler fired after the preloader has finished loading the icon
     *
     * @param source {String} Image source which was loaded
     * @param imageInfo {Map} Dimensions of the loaded image
     */
    __loaderCallback : function(source, imageInfo)
    {
      // Ignore the callback on already disposed images
      if (this.$$disposed === true) {
        return;
      }

      // Ignore when the source has already been modified
      if (source !==
qx.util.AliasManager.getInstance().resolve(this.getSource())) {
        this.fireEvent("aborted");
        return;
      }

      /// Output a warning if the image could not loaded and quit
      if (imageInfo.failed) {
        this.warn("Image could not be loaded: " + source);
        this.fireEvent("loadingFailed");
      } else if (imageInfo.aborted) {
        this.fireEvent("aborted");
        return;
      } else {
        this.fireEvent("loaded");
      }

      // Update image
      this.__setUnmanagedImage(this.__getContentElement(), source);
    },


    /**
     * Updates the content hint when the image size has been changed
     *
     * @param width {Integer} width of the image
     * @param height {Integer} height of the image
     */
    __updateContentHint : function(width, height)
    {
      // Compare with old sizes and relayout if necessary
      if (width !== this.__width || height !== this.__height)
      {
        this.__width = width;
        this.__height = height;

        qx.ui.core.queue.Layout.add(this);
      }
    }
  },


  /*
 
*****************************************************************************
     DESTRUCTOR
 
*****************************************************************************
  */

  destruct : function() {
    for (var mode in this.__contentElements) {
      if (this.__contentElements.hasOwnProperty(mode)) {
        this.__contentElements[mode].setAttribute("$$widget", null, true);
      }
    }

    delete this.__currentContentElement;
    if (this.__wrapper) {
      delete this.__wrapper;
    }

    this._disposeMap("__contentElements");
  }
});




var btn = new qx.ui.form.CheckBox("Image#scale").set({ value : true});
var setSrcBtn = new qx.ui.form.Button("setGreen");
setSrcBtn.addListener("execute", function(e) {
    img.setBackgroundColor("green");
}, this);

var img = new 
kreimer.MyImage2("http://support.showreelfinder.com/hc/en-us/article_attachments/201500876/reset.png";).set({
    cursor : "pointer",
    backgroundColor : "orange",
    height : 64,
    width : 64,
    scale : true
});

var doc = this.getRoot();
doc.add(btn, { left: 10, top: 10 });
doc.add(setSrcBtn, { left: 150, top: 10 });
doc.add(img, { left: 10, top: 50 });
btn.bind("value", img, "scale");




--
View this message in context: 
http://qooxdoo.678.n2.nabble.com/cursor-on-images-with-scale-true-tp7588002p7588101.html
Sent from the qooxdoo mailing list archive at Nabble.com.

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
qooxdoo-devel mailing list
qooxdoo-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel

Reply via email to