/**
* Simple helper class for easily creating image components. This renders an image tag to
* the DOM with the configured src.
*
* {@img Ext.Img/Ext.Img.png Ext.Img component}
*
* ## Example usage:
*
* var changingImage = Ext.create('Ext.Img', {
* src: 'http://www.sencha.com/img/20110215-feat-html5.png',
* width: 184,
* height: 90,
* renderTo: Ext.getBody()
* });
*
* // change the src of the image programmatically
* changingImage.setSrc('http://www.sencha.com/img/20110215-feat-perf.png');
*
* By default, only an img element is rendered and that is this component's primary
* {@link Ext.Component#getEl element}. If the {@link Ext.Component#autoEl} property
* is other than 'img' (the default), the a child img element will be added to the primary
* element. This can be used to create a wrapper element around the img.
*
* ## Wrapping the img in a div:
*
* var wrappedImage = Ext.create('Ext.Img', {
* src: 'http://www.sencha.com/img/20110215-feat-html5.png',
* autoEl: 'div', // wrap in a div
* renderTo: Ext.getBody()
* });
*
* ## Using a glyph
*
* var glyphImage = Ext.create('Ext.Img', {
* glyph: 'xf015@FontAwesome', // the "home" icon
* renderTo: Ext.getBody()
* });
*
* ## Image Dimensions
*
* You should include height and width dimensions for any image owned by a parent
* container. By omitting dimensions, an owning container will not know how to
* size and position the image in the initial layout.
*/
Ext.define('Ext.Img', {
extend: 'Ext.Component',
alias: ['widget.image', 'widget.imagecomponent'],
requires: [
'Ext.Glyph'
],
/**
* @cfg autoEl
* @inheritdoc
*/
autoEl: 'img',
/**
* @cfg baseCls
* @inheritdoc
*/
baseCls: Ext.baseCSSPrefix + 'img',
config: {
/**
* @cfg {String} src
* The source of this image. See {@link Ext#resolveResource} for details on
* locating application resources.
* @accessor
*/
src: null,
/**
* @cfg glyphorig
* @inheritdoc Ext.panel.Header#cfg-glyph
*/
/**
* @cfg {Number/String} glyph
* A numeric unicode character code to serve as the image. If this option is used
* The image will be rendered using a div with innerHTML set to the html entity
* for the given character code. The default font-family for glyphs can be set
* globally using {@link Ext#setGlyphFontFamily Ext.setGlyphFontFamily()}. Alternatively,
* this config option accepts a string with the charCode and font-family separated by
* the `@` symbol. For example '65@My Font Family'.
*/
glyph: null
},
/**
* @cfg {String} alt
* The descriptive text for non-visual UI description.
*/
alt: '',
/**
* @cfg {String} title
* Specifies additional information about the image.
*/
title: '',
/**
* @cfg {String} imgCls
* Optional CSS classes to add to the img element.
*/
imgCls: '',
/**
* @property maskOnDisable
* @inheritdoc
*/
maskOnDisable: false,
applySrc: function(src) {
return src && Ext.resolveResource(src);
},
getElConfig: function() {
var me = this,
autoEl = me.autoEl,
config = me.callParent(),
glyph = me.glyph,
img;
// We were configured with a glyph, then this is a div with a single char content
if (glyph) {
config.tag = 'div';
config.html = glyph.character;
config.style = config.style || {};
config.style.fontFamily = glyph.fontFamily;
// A glyph is a graphic which is not an <img> tag so it should have
// the corresponding role for Accessibility interface to recognize
config.role = 'img';
}
// The default; an img element
else if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) {
img = config;
}
// It is sometimes helpful (like in a panel header icon) to have the img wrapped
// by a div. If our autoEl is not 'img' then we just add an img child to the el.
else {
config.cn = [img = {
tag: 'img',
id: me.id + '-img'
}];
}
if (img) {
if (me.imgCls) {
img.cls = (img.cls ? img.cls + ' ' : '') + me.imgCls;
}
img.src = me.src || Ext.BLANK_IMAGE_URL;
}
if (me.alt) {
(img || config).alt = me.alt;
}
else {
// Images that do not have alt attribute can't be properly announced
// by screen readers. In best case they will be silently skipped;
// in worst case screen reader will announce data url. Yes, that very long
// base-64 encoded string. :/
// That will make the application totally unusable for blind people.
(img || config).alt = '';
//<debug>
Ext.log.warn('For WAI-ARIA compliance, IMG elements SHOULD have an alt attribute.');
//</debug>
}
if (me.title) {
(img || config).title = me.title;
}
return config;
},
onRender: function() {
var me = this,
autoEl = me.autoEl,
el;
me.callParent(arguments);
el = me.el;
if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) {
me.imgEl = el;
}
else {
me.imgEl = el.getById(me.id + '-img');
}
},
doDestroy: function() {
var me = this,
imgEl = me.imgEl;
// Only clean up when the img is a child, otherwise it will get handled
// by the element destruction in the parent
if (imgEl && me.el !== imgEl) {
imgEl.destroy();
}
me.imgEl = null;
me.callParent();
},
getTitle: function() {
return this.title;
},
/**
* Updates the {@link #title} of the image.
* @param {String} title
*/
setTitle: function(title) {
var me = this,
imgEl = me.imgEl;
me.title = title || '';
if (imgEl) {
imgEl.dom.title = title || '';
}
},
afterComponentLayout: function(width, height, oldWidth, oldHeight) {
var heightModel = this.getSizeModel().height,
h;
// If we have our height set, then size the glyph as requested to make image scalable.
if ((heightModel.calculated || heightModel.configured) && height && this.glyph) {
h = height + 'px';
this.setStyle({
'line-height': h,
'font-size': h
});
}
this.callParent([width, height, oldWidth, oldHeight]);
},
getAlt: function() {
return this.alt;
},
/**
* Updates the {@link #alt} of the image.
* @param {String} alt
*/
setAlt: function(alt) {
var me = this,
imgEl = me.imgEl;
me.alt = alt || '';
if (imgEl) {
imgEl.dom.alt = alt || '';
}
},
_naturalSize: null,
/**
* Returns the size of the image as an object.
* @return {Object} The size and aspect ratio of the image.
* @return {Number} return.aspect The aspect ration of the image (`width / height`).
* @return {Number} return.height The height of the image.
* @return {Number} return.width The width of the image.
* @since 6.2.0
*/
getNaturalSize: function() {
var me = this,
img = me.imgEl,
naturalSize = me._naturalSize,
style, w, h;
if (img && !naturalSize) {
img = img.dom;
me._naturalSize = naturalSize = {
width: w = img.naturalWidth,
height: img.naturalHeight
};
if (!w) {
style = img.style;
w = style.width;
h = style.height;
// As long as the width/height styles are "auto", the IMG dom element
// will have "width" and "height" properties that are the natural size.
style.width = style.height = 'auto';
naturalSize.width = img.width;
naturalSize.height = img.height;
style.width = w;
style.height = h;
}
naturalSize.aspect = naturalSize.width / naturalSize.height;
}
return naturalSize;
},
updateSrc: function(src) {
var imgEl = this.imgEl;
if (imgEl) {
imgEl.dom.src = src || Ext.BLANK_IMAGE_URL;
}
},
applyGlyph: function(glyph, oldGlyph) {
if (glyph) {
if (!glyph.isGlyph) {
glyph = new Ext.Glyph(glyph);
}
if (glyph.isEqual(oldGlyph)) {
glyph = undefined;
}
}
return glyph;
},
updateGlyph: function(glyph, oldGlyph) {
var el = this.el;
if (el) {
el.dom.innerHTML = glyph.character;
el.setStyle(glyph.getStyle());
}
}
});