summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Brachold <vdr07@deltab.de>2009-10-05 18:00:06 +0000
committerAndreas Brachold <vdr07@deltab.de>2009-10-05 18:00:06 +0000
commit6f21b40befb77303cc04415b675256b0ba098be3 (patch)
tree5b50a6017c6c086f2a9855076326ef1e3fabbd1e
parent728c070809470ec928cd23470c304463cf75e2e9 (diff)
downloadxxv-6f21b40befb77303cc04415b675256b0ba098be3.tar.gz
xxv-6f21b40befb77303cc04415b675256b0ba098be3.tar.bz2
* jason: refactoring view recordings
-rw-r--r--skins/jason/common.js65
-rw-r--r--skins/jason/files.lst1
-rw-r--r--skins/jason/fixes.js205
-rw-r--r--skins/jason/index.tmpl1
-rw-r--r--skins/jason/jason.css3
-rw-r--r--skins/jason/locale/lang-de.js1
-rw-r--r--skins/jason/locale/lang-en.js1
-rwxr-xr-xskins/jason/locale/lang-it.js1
-rw-r--r--skins/jason/pic/slide-left.pngbin0 -> 548 bytes
-rw-r--r--skins/jason/pic/slide-right.pngbin0 -> 603 bytes
-rw-r--r--skins/jason/recordings.js580
-rw-r--r--skins/jason/timers.js13
-rw-r--r--skins/jason/ux/Carousel.css67
-rw-r--r--skins/jason/ux/Carousel.js457
14 files changed, 1046 insertions, 349 deletions
diff --git a/skins/jason/common.js b/skins/jason/common.js
index 416f131..355c71a 100644
--- a/skins/jason/common.js
+++ b/skins/jason/common.js
@@ -113,5 +113,70 @@ Ext.xxv.Panel = Ext.extend(Ext.Panel, {
});
+/******************************************************************************/
+Ext.xxv.TagClouds = function(config){
+ Ext.xxv.TagClouds.superclass.constructor.call(this, config);
+ Ext.apply(this, config);
+};
+
+Ext.extend(Ext.xxv.TagClouds, Ext.Component, {
+
+ initComponent : function(){
+ Ext.xxv.TagClouds.superclass.initComponent.call(this);
+
+ this.addEvents({'selectKeyword' : true});
+ },
+
+ setvalue : function(keywords){
+
+ this.keywords = keywords;
+
+ if(this.cloudlist) {
+ this.cloudlist.remove();
+ delete this.cloudlist;
+ this.cloudlist = null;
+ }
+ },
+
+ render : function(ct, position){
+
+ if(!this.cloudlist && this.keywords && this.keywords.length) {
+ this.cloudlist = ct.createChild({tag: "ol", cls: "x-cloud-list"});
+ for(var i = 0, len = this.keywords.length; i < len; i++){
+ var child = this.cloudlist.createChild({
+ tag: "li",
+ cls: "x-cloud-item "+this.getWeight(this.keywords[i][1]),
+ html: '<a href="#">'+this.keywords[i][0]+'</a>'
+ });
+
+ child.on('click', this.onSelectKeyWord, this);
+ }
+ }
+ }
+ /**************************************************************************/
+ ,getWeight : function(weight){
+ var nmax = 100;
+ var nmin = 0;
+
+ var styles = new Array('smallest','smaller','small','medium','large','larger','largest');
+ var value = weight / (nmax - nmin) * 6;
+ if(value >= 6.0)
+ return styles[6];
+ if(value <= 0.0)
+ return styles[0];
+
+ return styles[Math.round(value)];
+ }
+ /**************************************************************************/
+ ,onSelectKeyWord : function(e, t){
+
+ var tag = t.firstChild.data;
+ this.fireEvent('selectKeyword', tag);
+
+ // Prevent the link href from being followed
+ Ext.EventObject.stopEvent(e);
+ }
+});
+Ext.reg('TagClouds', Ext.xxv.TagClouds);
diff --git a/skins/jason/files.lst b/skins/jason/files.lst
index 73847c8..79524f9 100644
--- a/skins/jason/files.lst
+++ b/skins/jason/files.lst
@@ -2,6 +2,7 @@ FILES = \
extjs/adapter/ext/ext-base.js \
extjs/ext-all.js \
fixes.js \
+ux/Carousel.js \
ux/DDView.js \
ux/Multiselect.js \
ux/TabCloseMenu.js \
diff --git a/skins/jason/fixes.js b/skins/jason/fixes.js
index da74e25..5fb77b8 100644
--- a/skins/jason/fixes.js
+++ b/skins/jason/fixes.js
@@ -71,3 +71,208 @@ Ext.override(Ext.form.TimeField, {
return v;
}
});
+
+
+/* http://www.extjs.com/forum/showthread.php?t=78223 */
+Ext.override(Ext.layout.VBoxLayout, {
+ onLayout : function(ct, target){
+ Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
+ var cs = this.getItems(ct), cm, ch, margin,
+ size = this.getTargetSize(target),
+ w = size.width - target.getPadding('lr'),
+ h = size.height - target.getPadding('tb') - this.scrollOffset,
+ l = this.padding.left, t = this.padding.top,
+ isStart = this.pack == 'start',
+ isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
+ stretchWidth = w - (this.padding.left + this.padding.right),
+ extraHeight = 0,
+ maxWidth = 0,
+ totalFlex = 0,
+ flexHeight = 0,
+ usedHeight = 0;
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ totalFlex += c.flex || 0;
+ ch = c.getHeight();
+ margin = cm.top + cm.bottom;
+ extraHeight += ch + margin;
+ flexHeight += margin + (c.flex ? 0 : ch);
+ maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
+ });
+ extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
+ var th = flexHeight + this.padding.top + this.padding.bottom;
+ if(h < th){
+ h = th;
+ w -= this.scrollOffset;
+ stretchWidth -= this.scrollOffset;
+ }
+ var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
+ switch(this.align){
+ case 'stretch':
+ this.innerCt.setSize(w, h);
+ break;
+ case 'stretchmax':
+ case 'left':
+ this.innerCt.setSize(innerCtWidth, h);
+ break;
+ case 'center':
+ this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
+ break;
+ }
+ var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
+ leftOver = availHeight,
+ heights = [],
+ restore = [],
+ idx = 0,
+ availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
+ Ext.each(cs, function(c){
+ if(isStart && c.flex){
+ ch = Math.floor(availHeight * (c.flex / totalFlex));
+ leftOver -= ch;
+ heights.push(ch);
+ }
+ });
+ if(this.pack == 'center'){
+ t += extraHeight ? extraHeight / 2 : 0;
+ }else if(this.pack == 'end'){
+ t += extraHeight;
+ }
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ t += cm.top;
+ c.setPosition(l + cm.left, t);
+ if(isStart && c.flex){
+ ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
+ if(isRestore){
+ restore.push(c.getWidth());
+ }
+ c.setSize(availableWidth, ch);
+ }else{
+ ch = c.getHeight();
+ }
+ t += ch + cm.bottom;
+ });
+ idx = 0;
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ if(this.align == 'stretch'){
+ c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
+ c.minWidth || 0, c.maxWidth || 1000000));
+ }else if(this.align == 'stretchmax'){
+ c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
+ c.minWidth || 0, c.maxWidth || 1000000));
+ }else{
+ if(this.align == 'center'){
+ var diff = availableWidth - (c.getWidth() + cm.left + cm.right);
+ if(diff > 0){
+ c.setPosition(l + cm.left + (diff/2), c.y);
+ }
+ }
+ if(isStart && c.flex){
+ c.setWidth(restore[idx++]);
+ }
+ }
+ }, this);
+ }
+});
+Ext.override(Ext.layout.HBoxLayout, {
+ onLayout : function(ct, target){
+ Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
+ var cs = this.getItems(ct), cm, cw, margin,
+ size = this.getTargetSize(target),
+ w = size.width - target.getPadding('lr') - this.scrollOffset,
+ h = size.height - target.getPadding('tb'),
+ l = this.padding.left, t = this.padding.top,
+ isStart = this.pack == 'start',
+ isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
+ stretchHeight = h - (this.padding.top + this.padding.bottom),
+ extraWidth = 0,
+ maxHeight = 0,
+ totalFlex = 0,
+ flexWidth = 0,
+ usedWidth = 0;
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ totalFlex += c.flex || 0;
+ cw = c.getWidth();
+ margin = cm.left + cm.right;
+ extraWidth += cw + margin;
+ flexWidth += margin + (c.flex ? 0 : cw);
+ maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
+ });
+ extraWidth = w - extraWidth - this.padding.left - this.padding.right;
+ var tw = flexWidth + this.padding.left + this.padding.right;
+ if(w < tw){
+ w = tw;
+ h -= this.scrollOffset;
+ stretchHeight -= this.scrollOffset;
+ }
+ var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
+ switch(this.align){
+ case 'stretch':
+ this.innerCt.setSize(w, h);
+ break;
+ case 'stretchmax':
+ case 'top':
+ this.innerCt.setSize(w, innerCtHeight);
+ break;
+ case 'middle':
+ this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
+ break;
+ }
+ var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
+ leftOver = availWidth,
+ widths = [],
+ restore = [],
+ idx = 0,
+ availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
+ Ext.each(cs, function(c){
+ if(isStart && c.flex){
+ cw = Math.floor(availWidth * (c.flex / totalFlex));
+ leftOver -= cw;
+ widths.push(cw);
+ }
+ });
+ if(this.pack == 'center'){
+ l += extraWidth ? extraWidth / 2 : 0;
+ }else if(this.pack == 'end'){
+ l += extraWidth;
+ }
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ l += cm.left;
+ c.setPosition(l, t + cm.top);
+ if(isStart && c.flex){
+ cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
+ if(isRestore){
+ restore.push(c.getHeight());
+ }
+ c.setSize(cw, availableHeight);
+ }else{
+ cw = c.getWidth();
+ }
+ l += cw + cm.right;
+ });
+ idx = 0;
+ Ext.each(cs, function(c){
+ var cm = c.margins;
+ if(this.align == 'stretch'){
+ c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
+ c.minHeight || 0, c.maxHeight || 1000000));
+ }else if(this.align == 'stretchmax'){
+ c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
+ c.minHeight || 0, c.maxHeight || 1000000));
+ }else{
+ if(this.align == 'middle'){
+ var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);
+ if(diff > 0){
+ c.setPosition(c.x, t + cm.top + (diff/2));
+ }
+ }
+ if(isStart && c.flex){
+ c.setHeight(restore[idx++]);
+ }
+ }
+ }, this);
+ }
+});
diff --git a/skins/jason/index.tmpl b/skins/jason/index.tmpl
index e2fa6fe..f073515 100644
--- a/skins/jason/index.tmpl
+++ b/skins/jason/index.tmpl
@@ -10,6 +10,7 @@
<link rel="stylesheet" type="text/css" href="extjs/resources/css/xtheme-default.css" id="theme" />
<link rel="stylesheet" type="text/css" href="jason.css" />
<link rel="stylesheet" type="text/css" href="ux/multiselect.css" />
+ <link rel="stylesheet" type="text/css" href="ux/Carousel.css" />
<script language="javascript" type="text/javascript">
var configuration = {
periods : [ "<?% getModule('EPG').periods.replace(',','","') %?>" ]
diff --git a/skins/jason/jason.css b/skins/jason/jason.css
index 1ecbfc0..9571803 100644
--- a/skins/jason/jason.css
+++ b/skins/jason/jason.css
@@ -228,7 +228,8 @@ padding:5px;
border-bottom:1px solid #dadadb;
}
.preview .x-panel-body div.preview-body {
-padding:10px;
+padding:10px;
+overflow: auto;
}
.reading-menu .x-menu-item-checked {
diff --git a/skins/jason/locale/lang-de.js b/skins/jason/locale/lang-de.js
index 46e0cf4..d1e5b4f 100644
--- a/skins/jason/locale/lang-de.js
+++ b/skins/jason/locale/lang-de.js
@@ -182,6 +182,7 @@ Ext.xxv.timerGrid.prototype.szColDay = "Tag";
Ext.xxv.timerGrid.prototype.szColChannel = "Kanal";
Ext.xxv.timerGrid.prototype.szColStart = "Beginn";
Ext.xxv.timerGrid.prototype.szColStop = "Ende";
+Ext.xxv.timerGrid.prototype.szColDuration = "Dauer";
Ext.xxv.timerGrid.prototype.szSelChEmptyText = "Kanal wählen...";
Ext.xxv.timerGrid.prototype.szColDayFormat = "l, d.m.Y";
Ext.xxv.timerGrid.prototype.szLoadException = "Konnte keine Daten über Timer holen!\r\n{0}";
diff --git a/skins/jason/locale/lang-en.js b/skins/jason/locale/lang-en.js
index f39fed8..6c63039 100644
--- a/skins/jason/locale/lang-en.js
+++ b/skins/jason/locale/lang-en.js
@@ -182,6 +182,7 @@ Ext.xxv.timerGrid.prototype.szColDay = "Day";
Ext.xxv.timerGrid.prototype.szColChannel = "Channel";
Ext.xxv.timerGrid.prototype.szColStart = "Start";
Ext.xxv.timerGrid.prototype.szColStop = "Stop";
+Ext.xxv.timerGrid.prototype.szColDuration = "Duration";
Ext.xxv.timerGrid.prototype.szHost = "Host";
Ext.xxv.timerGrid.prototype.szColDayFormat = "l, m/d/Y";
Ext.xxv.timerGrid.prototype.szSelChEmptyText = "Select a channel...";
diff --git a/skins/jason/locale/lang-it.js b/skins/jason/locale/lang-it.js
index 5199ef5..6dc1615 100755
--- a/skins/jason/locale/lang-it.js
+++ b/skins/jason/locale/lang-it.js
@@ -182,6 +182,7 @@ Ext.xxv.timerGrid.prototype.szColDay = "Giorno";
Ext.xxv.timerGrid.prototype.szColChannel = "Canale";
Ext.xxv.timerGrid.prototype.szColStart = "Inizio";
Ext.xxv.timerGrid.prototype.szColStop = "Fine";
+Ext.xxv.timerGrid.prototype.szColDuration = "Durata";
Ext.xxv.timerGrid.prototype.szHost = "Nome sistema";
Ext.xxv.timerGrid.prototype.szColDayFormat = "l, m/d/Y";
Ext.xxv.timerGrid.prototype.szSelChEmptyText = "Seleziona un canale...";
diff --git a/skins/jason/pic/slide-left.png b/skins/jason/pic/slide-left.png
new file mode 100644
index 0000000..27ab7f2
--- /dev/null
+++ b/skins/jason/pic/slide-left.png
Binary files differ
diff --git a/skins/jason/pic/slide-right.png b/skins/jason/pic/slide-right.png
new file mode 100644
index 0000000..3da357c
--- /dev/null
+++ b/skins/jason/pic/slide-right.png
Binary files differ
diff --git a/skins/jason/recordings.js b/skins/jason/recordings.js
index cc12d72..84aea21 100644
--- a/skins/jason/recordings.js
+++ b/skins/jason/recordings.js
@@ -33,35 +33,101 @@ HMSToSeconds = function(s) {
}
/******************************************************************************/
-Ext.xxv.slide = function(config){
- Ext.xxv.slide.superclass.constructor.call(this, config);
+Ext.xxv.slider = function(config){
+ Ext.xxv.slider.superclass.constructor.call(this, config);
Ext.apply(this, config);
-
- this.addEvents({
- 'selectKeyword' : true
- });
};
-Ext.extend(Ext.xxv.slide, Ext.Component, {
+Ext.extend(Ext.xxv.slider, Ext.Component, {
+
+ slider: null
+
+ ,initComponent : function(){
+ Ext.xxv.slider.superclass.initComponent.call(this);
+ this.addEvents({'MoveSlider' : true});
+ },
+
+ setvalue : function(marks, duration){
+ this.marks = marks;
+ this.duration = duration;
+ this.modified = 1;
+ },
+
+ render : function(ct, position){
+ if(!this.modified)
+ return;
+ this.modified = 0;
+ if(this.slider) {
+ //this.slider.remove();
+ ct.dom.innerHTML = '';
+ delete this.slider;
+ this.slider = null;
+
+ //this.slider.sliders.clear();
+ //this.slider.maxValue = this.duration;
+ } //else
+ {
+ this.slider = new Ext.ux.SlideZone(ct.id, {
+ type: 'horizontal'
+ ,size: ct.getWidth()
+ ,sliderWidth: 16
+ ,sliderHeight: 24
+ ,minValue: 0
+ ,maxValue: this.duration
+ //,sliderSnap: 1
+ ,allowSliderCrossing: true
+ });
+ this.ts = new Ext.ux.ThumbSlider({
+ value: 0
+ ,name: 'cutpoint_thumb'
+ ,cls: 'x-slide-zone-bottom'
+ ,allowMove: true
+ });
+ this.ts.on('drag',
+ function() {
+ var v = parseInt(this.ts.value * 1000);
+ this.fireEvent('MoveSlider', this, new Date((minTime().getTime())+v), null, null);
+ },this);
+ }
+
+ if(this.marks && this.marks.length) {
+ var cutpoint = this.marks.split(",");
+ for(var i = 0, len = cutpoint.length; i < len; i += 2){
+ var first = HMSToSeconds(cutpoint[i]);
+ var second;
+ if(i+1 < cutpoint.length) {
+ second = HMSToSeconds(cutpoint[i+1]);
+ } else {
+ second = this.duration;
+ }
+ var rs = new Ext.ux.RangeSlider({
+ value: [first,second]
+ ,name: 'cutpoint_'+i
+ ,cls: 'x-slide-zone-top'
+ ,allowMove: false
+ });
+ this.slider.add(rs);
+ }
+ }
+ this.slider.add(this.ts);
+ }
+});
- baseCls : 'x-slide',
+Ext.reg('MarksSlider', Ext.xxv.slider);
+
+/******************************************************************************/
+Ext.xxv.RecHeader = function(config){
+ Ext.xxv.RecHeader.superclass.constructor.call(this, config); Ext.apply(this, config);
+};
- setSize : Ext.emptyFn,
- setWidth : Ext.emptyFn,
- setHeight : Ext.emptyFn,
- setPosition : Ext.emptyFn,
- setPagePosition : Ext.emptyFn,
- slider: null,
+Ext.extend(Ext.xxv.RecHeader, Ext.Component, {
initComponent : function(){
- Ext.xxv.slide.superclass.initComponent.call(this);
+ Ext.xxv.RecHeader.superclass.initComponent.call(this);
- this.addEvents({'selected' : true});
- if (typeof(this.imageGap)=='undefined') { this.imageGap = 10 }
this.tpl = new Ext.Template(
- '<span id="preview-recordings-frame">',
- '<div class="preview-header">',
+ '<div class="preview-header">',
'<h3 class="preview-title">{title}</h3>',
'<div class="preview-channel">',
'<tpl if="channel != 0">',
@@ -73,38 +139,22 @@ Ext.extend(Ext.xxv.slide, Ext.Component, {
'</tpl>',
'</div>',
'<h4 class="preview-shorttitle">{subtitle}&nbsp;</h4>',
- '<div class="preview-date">{day:date} {start} - {stop}</div>',
- '</div>',
- '<div class="{cls}-wrap">',
- '<div id="images-inner" class="{cls}-inner">',
- '<div class="{cls}-images-wrap">',
- '<div class="{cls}-images"></div>',
- '</div>',
- '</div>',
- '</div>',
- '<div id="slider"><div id="slider-inner"></div></div>',
- '<div class="preview-body">{content}</div>',
- '</span>'
+ '<div class="preview-date">{day:date} {start} - {stop}</div>'
+ ,'</div>'
);
this.tpl.compile();
-
- this.tplimg = new Ext.Template('{day:date} - {start} ({period})');
- this.tplimg.compile();
-
},
- setvalue : function(data, first){
+ setvalue : function(data){
this.param = {
- data: data
- ,title: data.fulltitle
+ title: data.fulltitle
,subtitle: ''
,channel: data.channel
,day: data.day
,duration: data.duration
,start: data.day.dateFormat('H:i')
,stop: new Date(data.day.getTime() + (data.duration * 1000)).dateFormat('H:i')
- ,content: data.description.replace(/\r\n/g, '<br />')
,cutlength: data.cutlength == data.duration ? null : SecondsToHMS(data.cutlength)
,period: SecondsToHMS(data.duration)
};
@@ -117,244 +167,16 @@ Ext.extend(Ext.xxv.slide, Ext.Component, {
this.param.subtitle = title.pop();
this.param.title = title.join("~");
}
-
- if(first === true) {
- var images = [];
- if(!data.preview || data.preview == '') {
- /*var day = new Date(data.day.getTime());
- images.push(
- {
- src: (data.type == 'RADIO') ? 'pic/radio.png' : 'pic/movie.png'
- ,day: day
- ,start: day.dateFormat('H:i')
- ,frame: 0
- ,period: SecondsToHMS(0)
- }
- );*/
- } else {
- var frames = data.preview.split(",");
- Ext.each(frames, function(frame){
- var url = "?cmd=ri&data="+data.id+"_"+frame;
- var day = new Date(data.day.getTime() + (frame * 40));
- images.push(
- {
- src: url
- ,day: day
- ,start: day.dateFormat('H:i')
- ,frame: frame
- ,period: SecondsToHMS((frame * 40)/1000)
- }
- );
- },this);
- }
- this.images = images;
- }
},
-
- render : function(ct, position){
-
- if(!this.param) return;
- /** add preview images ************************************************/
-
- var inner= Ext.get("images-inner");
- if(!inner) {
- this.param.cls = this.baseCls;
- if(position){
- this.el = this.tpl.insertBefore(position, this.param, true);
- }else{
- this.el = this.tpl.append(ct, this.param, true);
- }
- if(this.id){
- this.el.dom.id = this.id;
- }
-
- inner= Ext.get("images-inner");
- if(this.slider) {
- delete this.slider;
- this.slider = null;
- }
- if(this.cloudlist) {
- delete this.cloudlist;
- this.cloudlist = null;
- }
+ render : function(ct, position){
+ if(this.param) {
+ this.tpl.overwrite(ct, this.param);
}
- var imagesWrap = Ext.get(inner.dom.firstChild);
- this.divImages = Ext.get(imagesWrap.dom.firstChild);
-
- var size = inner.getSize();
- this.width = size.width;
- this.height = size.height;
-
- inner.setStyle({
- height:(this.imageHeight + (2*this.wrapMarginY)) + 'px',
- width:(this.width-this.wrapMarginX)+'px'
- });
-
- var totalImageWidth=this.imageWidth+this.imageGap;
- var usableWidth=this.width-(this.wrapMarginX*2);
- var maxPicsOnce=Math.floor(usableWidth/totalImageWidth);
- var usedWidth=maxPicsOnce*totalImageWidth-this.imageGap;
- var offsetLeft=Math.floor((usableWidth-usedWidth)/2);
- this.pageSize=usedWidth+this.imageGap;
- this.maxPages=Math.round(this.images.length/maxPicsOnce+.04999);
- this.curPage=0;
-
- if (!Ext.isIE){
- offsetLeft+=this.wrapMarginX;
- }
-
- imagesWrap.setStyle({
- position: 'absolute',
- clip:'rect(0,'+(usedWidth*1)+','+(this.imageHeight)+',0)',
- 'margin-top':this.wrapMarginY+'px',
- width:this.width+'px',
- height:this.imageHeight+'px',
- 'margin-left':offsetLeft+'px'
- });
-
- /*this.divImages.setStyle({
- position: 'absolute'
- });*/
-
- Ext.each(this.images, function(image){
-
- if (typeof(image)=='string'){
- image={src:image}
- }
- var qtip = this.tplimg.applyTemplate(image);
-
- thisImage = this.divImages.createChild({tag:"img", src:image.src,
- 'ext:qtip':qtip,
- style:{
- 'margin-right': this.imageGap+'px',
- width: this.imageWidth+'px'
- // height: this.imageHeight+'px'
- }
- });
-
- thisImage.on("click", function(e, ele){
- if (!image.onSelected || !(image.onSelected.call(this, image, e, ele )===false)){
- this.fireEvent('selected', this, new Date(minTime().getTime()+(image.frame * 40)), e, ele);
-
- var slider = this.slider.getSlider('cutpoint_thumb');
- slider.value = image.frame/25;
- this.slider.initSliderPosition(slider);
- }
- },this);
- },this);
-
- /** add cutmark slider **************************************************/
- if(this.slider) {
- this.slider.sliders.clear();
- } else {
-
- this.slider = new Ext.ux.SlideZone('slider-inner', {
- type: 'horizontal',
- size: usableWidth-32,
- sliderWidth: 16,
- sliderHeight: 24,
- maxValue: this.param.data.duration,
- minValue: 0,
- //sliderSnap: 1,
- allowSliderCrossing: true
- });
- this.ts = new Ext.ux.ThumbSlider({
- value: 0
- ,name: 'cutpoint_thumb'
- ,cls: 'x-slide-zone-bottom'
- ,allowMove: true
- });
- this.ts.on('drag',
- function() {
- var v = parseInt(this.ts.value * 1000);
- this.fireEvent('selected', this, new Date((minTime().getTime())+v), null, null);
- },this);
- }
-
- if(this.param.data.marks && this.param.data.marks.length) {
- var cutpoint = this.param.data.marks.split(",");
- for(var i = 0, len = cutpoint.length; i < len; i += 2){
- var first = HMSToSeconds(cutpoint[i]);
- var second;
- if(i+1 < cutpoint.length) {
- second = HMSToSeconds(cutpoint[i+1]);
- } else {
- second = this.param.data.duration;
- }
- var rs = new Ext.ux.RangeSlider({
- value: [first,second]
- ,name: 'cutpoint_'+i
- ,cls: 'x-slide-zone-top'
- ,allowMove: false
- });
- this.slider.add(rs);
- }
- }
- this.slider.add(this.ts);
- /** add keywords tagcloud ***********************************************/
- if(!this.cloudlist && this.param.data.keywords && this.param.data.keywords.length) {
- var cont = Ext.get(ct.dom.lastChild);
- this.cloudlist = cont.createChild({tag: "ol", cls: "x-cloud-list"});
- for(var i = 0, len = this.param.data.keywords.length; i < len; i++){
- var child = this.cloudlist.createChild({
- tag: "li",
- cls: "x-cloud-item "+this.getWeight(this.param.data.keywords[i][1]),
- html: '<a href="#">'+this.param.data.keywords[i][0]+'</a>'
- });
-
- child.on('click', this.onSelectKeyWord, this);
- }
- }
}
- /**************************************************************************/
- ,onSelectKeyWord : function(e, t){
-
- var item = t.parentNode;
- var tag = item.firstChild.innerHTML;
-
- this.fireEvent('selectKeyword', tag);
-
- // Prevent the link href from being followed
- Ext.EventObject.stopEvent(e);
- }
- /**************************************************************************/
- ,getWeight : function(weight){
- var nmax = 100;
- var nmin = 0;
-
- var styles = new Array('smallest','smaller','small','medium','large','larger','largest');
- var value = weight / (nmax - nmin) * 6;
- if(value >= 6.0)
- return styles[6];
- if(value <= 0.0)
- return styles[0];
-
- return styles[Math.round(value)];
- }
- /**************************************************************************/
- ,CanShift: function(direction) {
- if (!this.curPage){
- this.offsetLeft=this.divImages.getLeft();
- }
- var newPage=(direction=='right' ? this.curPage+1 : this.curPage-1 );
- if (newPage<0 || newPage >= this.maxPages){
- return -1;
- }
- return newPage;
- }
-
- ,Shift: function(direction) {
- var newPage = this.CanShift(direction);
- if (newPage<0 || newPage >= this.maxPages){
- return;
- }
- this.curPage=newPage;
- var newLocation=(this.pageSize*this.curPage)*-1+this.offsetLeft;
- this.divImages.shift({ x:newLocation, duration: this.duration || .7 });
- }
});
-Ext.reg('slide', Ext.xxv.slide);
+Ext.reg('RecHeader', Ext.xxv.RecHeader);
+
/******************************************************************************/
@@ -846,8 +668,11 @@ Ext.extend(Ext.xxv.recordingsDataView, Ext.DataView, {
},
DetailsItem : function(record) {
- if(record.data.priority
- || record.data.id == 'up') {
+ if(record.data.id == 'up') {
+ return;
+ }
+ if(record.data.priority) { //use cached data
+ this.preview.update(record);
return;
}
var toDetails = '';
@@ -1276,34 +1101,58 @@ function createRecordingsView(viewer,id) {
}
}
});
-
+
var preview = new Ext.Panel({
id: 'preview-recordings',
region: 'south',
cls:'preview',
autoScroll: true,
stateful:true,
- timefield : timefield,
- items: [
- {
- id: 'preview-recordings-frame',
- xtype:'slide',
- wrapMarginY:0,
- wrapMarginX:0,
- imageHeight:120,
- imageWidth:160,
- autoWidth: true,
- listeners:{
- selected: function(slide, time, e, ele){
- this.ownerCt.timefield.setValue(time);
- }
- ,'selectKeyword': function(tag) {
- viewer.gridRecordings.doSelectKeyword(tag);
- }
- },
- images:[]
- }],
-
+ timefield : timefield,
+ layout: {
+ type:'vbox'
+ ,padding:'0'
+ ,align:'stretch'
+ ,autoScroll: true
+ }
+ ,defaults:{margins:'0 0 0 0'}
+ ,items: [
+ { //header
+ xtype:'container'
+ ,height: 50
+ ,items: [{
+ autoWidth: true,
+ xtype:'RecHeader'}
+ ]
+ },{ //images
+ id: 'preview-recordings-images'
+ ,xtype: 'box'
+ ,height: 130
+ ,listeners:{ 'SelectImage': function(slide, time, e, ele){ viewer.gridRecordings.preview.timefield.setValue(time); } }
+ },{ //timeslide
+ id:'preview-recordings-slide'
+ ,margins:'0 16 0 16'
+ ,height: 32
+ ,baseCls : 'x-slide'
+ ,items: [{
+ xtype:'MarksSlider'
+ ,duration: 100
+ ,listeners:{ 'MoveSlider': function(slide, time, e, ele){ viewer.gridRecordings.preview.timefield.setValue(time); } }
+ }]
+ },{ //content
+ id: 'preview-recordings-frame'
+ ,cls: 'preview-body'
+ ,xtype: 'box'
+ ,flex: 3
+ },{ // keywords
+ xtype:'container'
+ ,height: 80
+ ,items: [{
+ autoWidth: true
+ ,xtype:'TagClouds'
+ ,listeners:{ 'selectKeyword': function(tag) { viewer.gridRecordings.doSelectKeyword(tag); } }
+ }]
+ }],
tbar: [
{
id:'s'
@@ -1356,52 +1205,18 @@ function createRecordingsView(viewer,id) {
,handler: function(){ this.gridRecordings.onPlay(this.gridRecordings.preview.record, this.gridRecordings.preview.timefield.getValue() ); }
}
, timefield
- ,{
- id:'recordings-shift-left'
- ,iconCls: 'x-tbar-page-prev'
- ,scope: viewer
- ,disabled:false
- ,handler: function() {
- this.gridRecordings.preview.items.items[0].Shift('left');
- this.gridRecordings.preview.canshift();
- }
- }
- ,{
- id:'recordings-shift-right'
- ,iconCls: 'x-tbar-page-next'
- ,scope: viewer
- ,disabled:false
- ,handler: function(){
- this.gridRecordings.preview.items.items[0].Shift('right');
- this.gridRecordings.preview.canshift();
- }
- }
]
- ,canshift : function(){
- var items = this.topToolbar.items;
- if(items) {
- if(this.items.items[0].CanShift('right') != -1) {
- items.get('recordings-shift-right').enable();
- } else {
- items.get('recordings-shift-right').disable();
- }
- if(this.items.items[0].CanShift('left') != -1) {
- items.get('recordings-shift-left').enable();
- } else {
- items.get('recordings-shift-left').disable();
- }
- }
- }
,content : function(record){
if(record && this.record != record
&& record.data.isrecording
- && this.body
- && this.ownerCt.isVisible()) {
- this.body.update('');
- this.items.items[0].setvalue(record.data,true);
- this.doLayout();
+ //&& this.body
+ //&& this.ownerCt.isVisible()
+ ) {
this.record = record;
+ //header
+ this.get(0).get(0).setvalue(record.data);
+
this.timefield.maxValue = new Date((this.timefield.minValue.getTime())+(record.data.duration * 1000));
this.timefield.setValue(this.timefield.minValue);
@@ -1409,9 +1224,21 @@ function createRecordingsView(viewer,id) {
// Enable all toolbar buttons
var items = this.topToolbar.items;
if(items) {
- items.eachKey(function(key, f){if(XXV.help.cmdAllowed(key) || -1 == key.search(/shift/)) f.enable();},items);
+ items.eachKey(function(key, f)
+ {
+ if(key == 'timeline'
+ && (XXV.help.cmdAllowed('pre') || XXV.help.cmdAllowed('rpv'))) {
+ f.enable();
+ } else if(XXV.help.cmdAllowed(key))
+ f.enable();
+ }
+ ,items);
}
- this.canshift();
+
+ var content = Ext.get("preview-recordings-frame");
+ content.dom.innerHTML = record.data.description.replace(/\r\n/g, '<br />');
+
+ this.doLayout();
}
}
,update : function(record) {
@@ -1419,20 +1246,85 @@ function createRecordingsView(viewer,id) {
&& record.data.isrecording
&& this.body
&& this.ownerCt.isVisible()) {
- this.body.update('');
- this.items.items[0].setvalue(record.data,false);
- this.doLayout();
this.record = record;
+
+ this.get(0).get(0).setvalue(record.data);
+
+ if(!this.tplimg) {
+ this.tplimg = new Ext.Template('{day:date} - {start} ({period})');
+ this.tplimg.compile();
+ }
+
+ var frames = record.data.preview.split(",");
+ if(frames && frames.length > 0) {
+ this.remove(1);
+ var pic = new Array();
+ var frames = record.data.preview.split(",");
+ Ext.each(frames, function(frame){
+ var u = "?cmd=ri&data="+record.data.id+"_"+frame;
+ var d = new Date(record.data.day.getTime() + (frame * 40));
+ var t = SecondsToHMS((frame * 40)/1000);
+ var q = this.tplimg.applyTemplate({
+ day: d
+ ,start: d.dateFormat('H:i')
+ ,period: t
+ });
+ pic.push({
+ frame: frame
+ ,width: 160
+ ,html: "<img width='160px' src='"+ u + "' 'ext:qtip='" + q + "'>"
+ });
+ },this);
+
+ this.insert(1,new Ext.Container( {
+ id: 'preview-recordings-images'
+ ,height: 130
+ ,layoutConfig: {
+ scrollButtonPosition:'split',
+ marginScrollButtons: 1,
+ pagedScroll: false
+ }
+ ,layout: 'carousel'
+ ,items: pic
+ }));
+
+ }
+
+ this.get(2).get(0).setvalue(record.data.marks,record.data.duration);
+ // Keywords
+ this.get(4).get(0).setvalue(record.data.keywords);
+ var height = record.data.keywords && record.data.keywords.length ? 80 : 0;
+ if(this.get(4).getHeight() != height) {
+ this.get(4).suspendEvents(false);
+ this.get(4).setHeight(height);
+ this.get(4).resumeEvents();
+ }
+ this.doLayout();
+/*
+ var root = Ext.getCmp('preview-recordings-images');
+ var images = root.select('img');
+ Ext.each(images, function(image){
+ this.get(1).on("click", function(e, ele){
+ if (!image.onSelected || !(image.onSelected.call(this, image, e, ele )===false)){
+ this.fireEvent('selected', this, new Date(minTime().getTime()+(image.frame * 40)), e, ele);
+
+ var slider = this.get(2).get(0).getSlider('cutpoint_thumb');
+ slider.value = pic.frame/25;
+ this.get(2).get(0).slider.initSliderPosition(slider);
+ }
+ },this);
+ });
+*/
}
}
,clear: function(){
if(this) {
- if(this.body)
- this.body.update('');
+ //if(this.body)
+ // this.body.update('');
this.record = null;
// Disable all toolbar buttons
var items = this.topToolbar.items;
- if(items) {
+ if(items) {
items.eachKey(function(key, f){f.disable();},items);
}
diff --git a/skins/jason/timers.js b/skins/jason/timers.js
index 46c5c1c..71473d7 100644
--- a/skins/jason/timers.js
+++ b/skins/jason/timers.js
@@ -108,7 +108,6 @@ Ext.xxv.timerGrid = function(viewer) {
,dataIndex: 'title'
,width: 250
,renderer: this.formatTitle
- //,editor: new Ext.form.TextField({allowBlank: false})
},
this.activeColumn,
this.vpsColumn,
@@ -118,18 +117,20 @@ Ext.xxv.timerGrid = function(viewer) {
,dataIndex: 'day'
,width: 50
,renderer: Ext.util.Format.dateRenderer(this.szColDayFormat)
- //,editor: new Ext.form.DateField({ minValue: Ext.util.Format.date(new Date()) })
,hidden: true
},{
header: this.szColStart
,dataIndex: 'start'
,width: 50
- //,editor: new Ext.form.TimeField()
},{
header: this.szColStop
,dataIndex: 'stop'
,width: 50
- //,editor: new Ext.form.TimeField()
+ },{
+ header: this.szColDuration
+ ,dataIndex: 'duration'
+ ,width: 50
+ ,renderer: this.formatDuration
},{
header: this.szHost
,dataIndex: 'host'
@@ -207,6 +208,7 @@ Ext.extend(Ext.xxv.timerGrid, Ext.grid.GridPanel, { // Ext.grid.EditorGridPanel
,szColChannel : "Channel"
,szColStart : "Start"
,szColStop : "Stop"
+ ,szColDuration : "Duration"
,szHost : "Host"
,szColDayFormat : "l, m/d/Y"
,szSelChEmptyText: "Select a channel..."
@@ -323,6 +325,9 @@ Ext.extend(Ext.xxv.timerGrid, Ext.grid.GridPanel, { // Ext.grid.EditorGridPanel
'<div class="topic{1}"><b>{0}</b></div>',
title, style
);
+ }
+ ,formatDuration: function(value, p, record) {
+ return new Date(minTime().getTime()+(value * 1000)).dateFormat('H:i');
}
/******************************************************************************/
,onToggleSuccess : function( response,options )
diff --git a/skins/jason/ux/Carousel.css b/skins/jason/ux/Carousel.css
new file mode 100644
index 0000000..36c7e2d
--- /dev/null
+++ b/skins/jason/ux/Carousel.css
@@ -0,0 +1,67 @@
+ .x-carousel-layout {
+ overflow: hidden;
+ position: relative;
+ zoom: 1;
+ }
+
+ .x-carousel-left-scrollbutton {
+ width: 10px;
+ position: absolute;
+ top: 0px;
+ background: url(../pic/slide-left.png) no-repeat 0px center;
+ height: 100%;
+ cursor:hand;
+ }
+
+ .x-carousel-layout.x-scroll-button-position-right .x-carousel-left-scrollbutton {
+ right: 5px;
+ }
+ .x-carousel-layout.x-scroll-button-position-left .x-carousel-left-scrollbutton,
+ .x-carousel-layout.x-scroll-button-position-split .x-carousel-left-scrollbutton {
+ left: 0px;
+ }
+
+ .x-carousel-right-scrollbutton {
+ width: 10px;
+ position: absolute;
+ top:0px;
+ background: url(../pic/slide-right.png) no-repeat 0px center;
+ height:100%;
+ cursor:hand;
+ }
+
+ .x-carousel-layout.x-scroll-button-position-right .x-carousel-right-scrollbutton,
+ .x-carousel-layout.x-scroll-button-position-split .x-carousel-right-scrollbutton {
+ right: 0px;
+ }
+
+ .x-carousel-layout.x-scroll-button-position-left .x-carousel-right-scrollbutton {
+ left: 23px;
+ }
+
+ .x-carousel-scroller {
+ overflow: hidden;
+ position: relative;
+ left: 5px
+ }
+
+ .x-carousel-layout.x-scroll-button-position-left .x-carousel-scroller {
+ left: 41px;
+ }
+
+ .x-carousel-layout.x-scroll-button-position-split .x-carousel-scroller {
+ left: 10px;
+ }
+
+ .x-carousel-body {
+ width: 10000px;
+ overflow: hidden;
+ zoom: 1;
+ }
+
+ .x-carousel-scroller .x-carousel-body .x-carousel-item {
+ float: left;
+ overflow: hidden;
+ zoom: 1
+ }
+
diff --git a/skins/jason/ux/Carousel.js b/skins/jason/ux/Carousel.js
new file mode 100644
index 0000000..bd1626d
--- /dev/null
+++ b/skins/jason/ux/Carousel.js
@@ -0,0 +1,457 @@
+/*(c) Copyright 2008 Licensed under LGPL3. See details below*/
+var o = Ext.Container.prototype.lookupComponent;
+Ext.override(Ext.Container, {
+
+ // Override of our container's method to allow raw Elements to be added.
+ // This is called in the context of the container.
+ lookupComponent: function(comp) {
+ if (comp instanceof Ext.Element) {
+ return comp;
+ } else if (comp.nodeType && (comp.nodeType == 1)) {
+ return Ext.get(comp);
+ } else {
+ return o.call(this, comp);
+ }
+ }
+});
+
+Ext.namespace('Ext.ux.layout');
+
+/**
+ * Carousel Layout.
+ * <br>
+ * <br>See the following for a <a href="http://extjs-ux.org/repo/authors/jerrybrown5/trunk/Ext/ux/layout/Carousel/Demo.html">demo</a>
+ * <br>
+ * <br> Example Usage
+ * <pre>
+ * margins: '5 5 5 0',
+ * title: 'Photos',
+ * layoutConfig: {
+ * pagedScroll: true
+ * },
+ * layout: '<b>carousel</b>',
+ * items: [{
+ * title: "First",
+ * style: {
+ * margin: '5px 5px 5px 5px'
+ * },
+ * width: 120,
+ * html: "&lt;img src='../view/images/thumbs/dance_fever.jpg'>"
+ * }]
+ * </pre>
+ * <br>Forum thread: <a href="http://extjs.com/forum/showthread.php?t=47672">http://extjs.com/forum/showthread.php?t=47672</a>
+ * @class Ext.ux.layout.Carousel
+ * @author Nigel White aka Animal; updated by Jerry Brown, published by SamuraiJack
+ * @license Ext.ux.layout.Carousel is licensed under the terms of
+ * the Open Source <a href="http://www.gnu.org/licenses/lgpl.html">LGPL 3.0 license</a>. Commercial use is permitted to the extent
+ * that the code/component(s) do NOT become part of another Open Source or Commercially
+ * licensed development library or toolkit without explicit permission.
+ * @version 0.2
+ */
+Ext.ux.layout.Carousel = Ext.extend(Ext.layout.ContainerLayout, {
+ constructor: function(config) {
+ config = config || {};
+
+// Non-chunked, then animation makes no sense.
+ if (!(config.chunkedScroll || config.pagedScroll)) {
+ Ext.applyIf(config, {
+ scrollIncrement: 10,
+ scrollRepeatInterval: 10,
+ marginScrollButtons: 12,
+ animScroll: false
+ });
+ }
+ Ext.ux.layout.Carousel.superclass.constructor.call(this, config);
+
+// Set up animation config depending upon animation requirements.
+ if (this.chunkedScroll || this.pagedScroll) {
+ this.scrollRepeatInterval = this.scrollDuration * 1000;
+ this.scrollAnimationConfig = {
+ duration: this.chunkedScroll ? this.scrollDuration : this.scrollDuration * 2,
+ callback: this.updateScrollButtons,
+ scope: this
+ }
+ } else {
+ this.scrollAnimationConfig = this.animScroll ? {
+ duration: this.scrollDuration,
+ callback: this.updateScrollButtons,
+ scope: this
+ } : false;
+ }
+
+// if (Ext.isIE){
+// if (!this.defaults) { this.defaults={} }
+// if (!this.defaults.bodyStyle) { this.defaults.bodyStyle={} }
+// this.defaults.bodyStyle.position='static';
+// }
+
+ },
+
+ /**
+ * @cfg {Number} marginScrollButtons This is to set aside space for the left and right navigation buttons.
+ */
+
+ marginScrollButtons : 10,
+ /**
+ * @cfg scrollElementTag {String} The tag name of the carousel item container. If each item's main Element
+ * is an &lt;LI> then this could be specified as '&lt;UL>. Defaults to '&lt;DIV>'.
+ /**
+ * @cfg {Number} scrollIncrement The number of pixels to scroll each time a tab scroll button is pressed (defaults
+ * to 10, or if {@link #Ext.ux.layout.Carousel-resizeTabs} = true, the calculated tab width).
+ */
+ scrollIncrement : 10,
+ /**
+ * @cfg {Number} scrollRepeatInterval Number of milliseconds between each scroll while a scroll button is
+ * continuously pressed (defaults to 10).
+ */
+ scrollRepeatInterval : 10,
+ /**
+ * @cfg {Float} scrollDuration The number of seconds that each scroll animation should last (defaults to .35).
+ * Only applies when {@link #Ext.ux.layout.Carousel-animScroll} = true.
+ */
+ scrollDuration : .35,
+ /**
+ * @cfg {Boolean} animScroll True to animate tab scrolling so that hidden items slide smoothly into view (defaults
+ * to true). Only applies when {@link #Ext.ux.layout.Carousel-enableTabScroll} = true.
+ */
+ animScroll : true,
+
+ /**
+ * @cfg {Boolean} chunkedScroll To control scrolling more than one image at a time
+ */
+
+ chunkedScroll: false,
+
+ /**
+ * @cfg {Boolean} pageScroll Scroll full pages
+ */
+ pagedScroll: false,
+
+ /**
+ * @cfg {Boolean} loopCount This does an intro page loop this many times after render
+ */
+ loopCount: 0,
+ /**
+ * @cfg {Boolean} loopPictureDelay This controls the delay on each picture during the intro page loop
+ */
+ loopPictureDelay: 5,
+
+ // private
+ monitorResize: true,
+
+ /**
+ * @cfg scrollButtonPosition (split or right) This determines where the scroll bar buttons will be. Matching style elements need to be in place.
+ */
+ scrollButtonPosition: 'right',
+
+
+
+ loopImages: function(){
+
+ if (this.loopCount <= 0){ return }
+
+ var s = this.getScrollTo(1);
+ if (s) {
+ s = Math.min(this.getMaxScrollPos(), s);
+ if(s != this.getScrollPos()) {
+ this.scrollTo(s);
+ }else{
+ return; /*it should not get here*/
+ }
+ }else{
+ this.scrollTo(0);
+ this.loopCount--;
+ if (this.loopCount <= 0){ return }
+ }
+
+ this.loopImages.defer(this.loopPictureDelay * 1000, this);
+ },
+
+
+ // private
+ onLayout : function(ct, target){
+ var cs = ct.items.items, len = cs.length, c, i;
+
+ if(!this.scrollWrap){
+ this.scrollWrap = target.createChild({
+ cls: 'x-carousel-layout',
+ cn: [
+ {
+ tag: this.scrollElementTag || 'div',
+ cls: 'x-carousel-scroller',
+ cn: {
+ cls: 'x-carousel-body'
+ }
+ }, {
+ cls: 'x-carousel-left-scrollbutton',
+ style: {
+ height: '100%'
+ }
+ }, {
+ cls: 'x-carousel-right-scrollbutton',
+ style: {
+ height: '100%'
+ }
+ }]
+ });
+
+// Add the class that defines element positions
+ this.scrollWrap.addClass('x-scroll-button-position-' + this.scrollButtonPosition);
+
+ this.scrollLeft = this.scrollWrap.child('.x-carousel-left-scrollbutton');
+ this.scrollRight = this.scrollWrap.child('.x-carousel-right-scrollbutton');
+ this.scroller = this.scrollWrap.child('.x-carousel-scroller');
+ this.strip = this.scroller.child('.x-carousel-body');
+
+ if (this.pagedScroll) {
+ this.scrollLeft.on('click',this.onScrollLeftClick, this);
+ this.scrollRight.on('click',this.onScrollRightClick, this);
+ } else {
+ this.leftRepeater = new Ext.util.ClickRepeater(this.scrollLeft, {
+ interval : this.pagedScroll ? 10000 : this.scrollRepeatInterval,
+ delay: 0,
+ handler: this.onScrollLeftClick,
+ scope: this
+ });
+ this.rightRepeater = new Ext.util.ClickRepeater(this.scrollRight, {
+ interval : this.pagedScroll ? 10000 : this.scrollRepeatInterval,
+ delay: 0,
+ handler: this.onScrollRightClick,
+ scope: this
+ });
+ }
+ this.renderAll(ct, this.strip);
+ }
+ this.scroller.setWidth(this.container.getLayoutTarget().getWidth() - (this.scrollLeft.getWidth() + this.scrollRight.getWidth() + this.marginScrollButtons));
+ this.updateScrollButtons.defer(10, this);
+
+
+ if (this.loopCount > 0 && (this.chunkedScroll || this.pagedScroll) && !this.startedLoop){
+ this.startedLoop=true; /*this var is important since onLayout can be called more than once*/
+ this.loopImages.defer(this.loopPictureDelay * 1000, this);
+ }
+
+ },
+
+ // private
+ renderItem : function(c, position, target){
+ if(c) {
+ if (c.initialConfig) {
+ if (c.rendered){
+ if(typeof position == 'number'){
+ position = target.dom.childNodes[position];
+ }
+ target.dom.insertBefore(c.getEl().dom, position || null);
+ } else {
+ c.render(target, position);
+ }
+ } else if (c instanceof Ext.Element) {
+ c.el = c;
+ if(typeof position == 'number'){
+ position = target.dom.childNodes[position];
+ }
+ target.dom.insertBefore(c.dom, position || null);
+ }
+ }
+ c.el.addClass('x-carousel-item');
+ },
+
+ // private
+ onResize : function(c, position, target){
+ Ext.ux.layout.Carousel.superclass.onResize.apply(this, arguments);
+ if (Ext.isIE) {
+ this.scrollLeft.setHeight(this.scroller.getHeight());
+ this.scrollRight.setHeight(this.scroller.getHeight());
+ }
+
+ this.setItemsEdges();
+
+// If width increase has introduced spare space to the right, close it up.
+ var r = this.getMaxScrollPos();
+ if (this.getScrollPos() > r) {
+ this.scrollTo(r);
+ }
+
+
+ },
+
+ setItemsEdges:function(){
+// Register strip-relative left/right edges for easy chunked scrolling
+ var stripLeft = this.strip.getLeft();
+ var t = this.container.items.items;
+ var lt = t.length;
+ for (var i = 0; i < lt; i++) {
+ var c = t[i];
+ var e = c.el;
+ var b = e.getBox();
+ var l = b.x - stripLeft;
+ var r = b.right - stripLeft;
+
+// "left" is the leftmost visible pixel.
+// "leftAnchor" is the postition to scroll to to bring the
+// item correctly into view with half the inter-item gap visible.
+// Same principle applies to "right"
+ c.edges = {
+ left: l,
+ leftAnchor: l,
+ right: r,
+ rightAnchor: r
+ };
+
+// Adjust anchors to be halfway between items.
+ if (i == 0) {
+ e.setStyle({'margin-left': '0px'});
+ } else {
+ if (i == t.length - 1) {
+ e.setStyle({'margin-right': '0px'});
+ }
+ var prev = t[i - 1];
+ var halfGap = ((l - prev.edges.right) / 2);
+ prev.edges.rightAnchor += halfGap;
+ c.edges.leftAnchor -= halfGap;
+ }
+ }
+
+// Work out average item width
+ this.itemWidth = t[lt - 1].edges.rightAnchor / lt;
+
+ },
+ getNextOnLeft: function() {
+ var t = this.container.items.items;
+ if (t.length) {
+ for (var i = t.length - 1; i > -1; i--) {
+ if (t[i].edges.left < this.getScrollPos()) {
+ return t[i];
+ }
+ }
+ }
+ },
+
+ getNextOnRight: function() {
+ var t = this.container.items.items;
+ if (t.length) {
+ var scrollRight = this.scroller.dom.scrollLeft + this.getClientWidth();
+ for (var i = 0, l = t.length; i < l; i++) {
+ if (t[i].edges.right > scrollRight) {
+ return t[i];
+ }
+ }
+ }
+ },
+
+/**
+ * Called when a click event is fired by the right scroll button.
+ * May also be used to programatically trigger a right scroll event.
+ */
+
+ onScrollRightClick : function(){
+ this.loopCount=0;
+ var s = this.getScrollTo(1);
+ if (s) {
+ s = Math.min(this.getMaxScrollPos(), s);
+ if(s != this.getScrollPos()) {
+ this.scrollTo(s);
+ }
+ }
+ },
+
+/**
+ * Called when a click event is fired by the right scroll button.
+ * May also be used to programatically trigger a left scroll event.
+ */
+
+ onScrollLeftClick : function(){
+ this.loopCount=0;
+ var s = Math.max(0, this.getScrollTo(-1));
+ if(s != this.getScrollPos()) {
+ this.scrollTo(s);
+ }
+ },
+
+ // private
+ scrollTo : function(pos){
+
+// Calculate scroll duration based on how far we have to scroll.
+ if (this.scrollAnimationConfig) {
+ var distance = Math.abs(this.getScrollPos() - pos);
+ this.scrollAnimationConfig.duration = this.scrollDuration * (distance / this.itemWidth);
+ }
+
+ this.scroller.scrollTo('left', pos, this.scrollAnimationConfig);
+
+// Scroll animation will have called this in its callback.
+ if(!this.scrollAnimationConfig){
+ this.updateScrollButtons();
+ }
+ },
+
+ // private
+ updateScrollButtons : function(){
+ var pos = this.getScrollPos();
+ this.scrollLeft[(pos == 0) ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
+ this.scrollRight[(pos >= this.getMaxScrollPos()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
+ },
+
+ getScrollWidth : function(){
+ var t = this.container.items.items;
+
+ if (t.length && ! t[0].edges){
+ this.setItemsEdges();
+ }
+
+ return t.length ? t[t.length - 1].edges.rightAnchor : 0;
+ },
+
+ // private
+ getScrollPos : function(){
+ return this.scroller.dom.scrollLeft || 0;
+ },
+
+ getMaxScrollPos: function() {
+ return this.getScrollWidth() - this.getClientWidth();
+ },
+
+ // private
+ getClientWidth : function(){
+ return this.scroller.dom.clientWidth || 0;
+ },
+
+ // private
+ getScrollTo : function(dir){
+ var pos = this.getScrollPos();
+
+ if (this.chunkedScroll || this.pagedScroll) {
+// -1 for left, 1 for right
+ if (dir == -1) {
+ var nextLeft = this.getNextOnLeft();
+ if (nextLeft) {
+ if (this.pagedScroll) {
+ return nextLeft.edges.rightAnchor - this.getClientWidth();
+ } else {
+ return nextLeft.edges.leftAnchor;
+ }
+ }
+ } else {
+ var nextRight = this.getNextOnRight();
+ if (nextRight) {
+ if (this.pagedScroll) {
+ return nextRight.edges.leftAnchor;
+ } else {
+ return (nextRight.edges.rightAnchor - this.getClientWidth());
+ }
+ }
+ }
+ } else {
+ return (dir == -1) ? pos - this.scrollIncrement : pos + this.scrollIncrement;
+ }
+ },
+
+ // private
+ isValidParent : function(c, target){
+ return true;
+ }
+
+});
+
+Ext.Container.LAYOUTS['carousel'] = Ext.ux.layout.Carousel;
+