Hi,
I am trying to implement a custom component and have some issues with getEl() returning an undefined reference. I am accessing the dom element from within afterRender() so I thought by that time the container has been added to the dom thus containing a valid reference to the dom element. But the following code causes the following error on chrome:
Uncaught TypeError: Cannot call method 'getWidth' of undefined
Can someone tell me what to do so this doesn't happen again? When can I be sure that the component has been added to the dom and that the references to the dom elements are valid?
Here is the code in a selfcontained index.html file (make sure there is a test.png file in the same directory where the html file is placed):
Code:
<html>
<head>
<title></title>
<style type="text/css">@import "libs/sencha-touch/resources/css/ext-touch.css";</style>
<style type="text/css">
.screen {
background-color: rgb(220,220,220);
background-image: none;
}
</style>
<script type="text/javascript" src="libs/sencha-touch/ext-touch-debug.js"></script>
<!-- <script type="text/javascript" src="js/sencha-touch.js"></script> -->
<script type="text/javascript">
String.prototype.isEmpty = function() {
return (this == '');
}
function getRandomColor() {
var min = 220; // don't set min to a value greate than 255
var ar = new Array();
for (var i = 0; i < 3; ++i) {
ar.push(min + parseInt(Math.random() * (255 - min)));
}
var color = 'rgb(' + ar.join(",") + ')';
return color;
}
Ext.setup({
fullscreen: true,
statusBarStyle: 'black-translucent',
icon: 'icon.png',
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
glossOnIcon: true,
onReady: function() {
VideoPlaybackWidget = Ext.extend(Ext.Panel, {
initComponent: function() {
var beforeVideoCnt = new VideoPreviewWidget({
height: 320,
style: {
border: '1px solid red'
}
});
beforeVideoCnt.setSource('test.png');
// Initializing component
Ext.apply(this, {
layout: {
type: 'fit'
},
defaults: {
layout: {
align: 'stretch'
}
},
items: [{
xtype: 'container',
items: [beforeVideoCnt]
}]
});
VideoPlaybackWidget.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('videoplayblackwidget', VideoPlaybackWidget);
VideoPreviewWidget = Ext.extend(Ext.Container, {
initComponent: function() {
this.source = '';
/**
* @param: s is the new source of the image
*/
this.setSource = function(s) {
if (s == undefined) {
// assign nothing to source
}
else if (typeof s != 'string') {
console.error('TypeError');
return;
}
else {
this.source = s;
}
function waitUntilLoaded(scope) {
if (!img.complete) {
console.log('scheduled for later');
setTimeout(waitUntilLoaded, 100, scope);
} else {
var w = img.width;
var h = img.height;
var aspectRatio = scope.getWidth() / scope.getHeight();
if (w == 0 || h == 0) {
w = scope.getWidth();
h = scope.getHeight();
} else {
var aspectRatio = w / h;
}
if (w > scope.getWidth()) {
w = scope.getWidth();
h = w / aspectRatio;
}
if (h > scope.getHeight()) {
h = scope.getHeight();
w = h * aspectRatio;
}
var el = scope.getEl();
if (el) {
var imgEl = el.down('img');
imgEl.set({
style: (scope.source == null || scope.source.isEmpty()) ? 'display:none;' : 'display: block;',
src: scope.source,
alt: 'image path:' + scope.source,
width: (w == undefined) ? 'auto' : w,
height: (h == undefined) ? 'auto' : h
});
repositionElements(imgEl, w, h, scope);
}
}
};
var img = new Image();
img.src = this.source;
waitUntilLoaded(this);
};
this.getSource = function() {
return this.source;
};
function repositionElements(el, w, h, scope) {
var xoffset = Math.floor((scope.width - w) / 2);
var yoffset = Math.floor((scope.height - h) / 2);
var el = scope.getEl();
if (el) {
var imgEl = el.down('img');
console.log('left:' + xoffset + 'px; top:' + yoffset + 'px;');
imgEl.set({
style: 'left:' + xoffset + 'px; top:' + yoffset + 'px;'
});
}
};
this.test = function(obj) { // DEBUG
console.log('on show');
};
/* Initializing component */
Ext.apply(this, {
html: '<div style="position:relative;"><img style="position: absolute;"/><div style="position: absolute;"></div></div>'
});
VideoPreviewWidget.superclass.initComponent.apply(this, arguments);
},
afterRender: function() {
VideoPreviewWidget.superclass.afterRender.apply(this, arguments);
setTimeout(this.setSource(), 10000);
}
});
Ext.reg('videopreviewwidget', VideoPreviewWidget);
var screen = new VideoPlaybackWidget({
fullscreen: true
});
screen.show();
}
});
</script>
</head>
<body>
</body>
</html>