* @cfg {String} icon (info-sign|check|...) glyphicon name
* @cfg {Boolean} hidden (true|false) hide the element
* @cfg {Boolean} expandable (true|false) default false
+ * @cfg {Boolean} expanded (true|false) default true
* @cfg {String} rheader contet on the right of header
*
h.push({
tag: 'i',
- cls: 'fa fa-minus'
+ cls: (this.expanded ? 'fa fa-minus' : 'fa fa-plus')
});
+
}
h.push(
{
tag: 'span',
cls : 'panel-title',
- html : this.header
+ html : (this.expandable ? ' ' : '') + this.header
},
{
tag: 'span',
cfg.cn.push({
cls : 'panel-heading',
+ style : this.expandable ? 'cursor: pointer' : '',
cn : h
});
body = false;
cfg.cn.push({
- cls : 'panel-body',
+ cls : 'panel-body' + (this.expanded ? '' : ' hide'),
html : this.html
});
this.expanded = true;
- this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
-
+ //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
+
+ this.el.select('.panel-body',true).first().removeClass('hide');
+
var toggleEl = this.toggleEl();
if(!toggleEl){
this.expanded = false;
- this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+ //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+ this.el.select('.panel-body',true).first().addClass('hide');
var toggleEl = this.toggleEl();
var s = ['xs', 'sm', 'md', 'lg'];
- Roo.each(s.splice(s.indexOf(size), 1), function(ss){
+ s.splice(s.indexOf(size), 1);
+
+ Roo.each(s, function(ss){
img.cls += ' hidden-' + ss;
});
if (this.buttons.length) {
Roo.each(this.buttons, function(bb) {
- b = Roo.apply({}, bb);
+ var b = Roo.apply({}, bb);
b.xns = b.xns || Roo.bootstrap;
b.xtype = b.xtype || 'Button';
if (typeof(b.listeners) == 'undefined') {
//this.el.addClass([this.fieldClass, this.cls]);
},
+
getAutoCreate : function(){
if (this.allow_close) {
this.closeEl.on('click', this.hide, this);
}
+
+ var _this = this;
+
+ window.addEventListener("resize", function() { _this.resize(); } );
},
+
+ resize : function()
+ {
+ this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+ },
+
show : function() {
if (!this.rendered) {
},
setActive : function(state, fire, is_was_active)
{
- if (this.active && !state & this.navId) {
+ if (this.active && !state && this.navId) {
this.was_active = true;
var nv = Roo.bootstrap.NavGroup.get(this.navId);
if (nv) {
* @cfg {boolean} condensed Format condensed
* @cfg {boolean} responsive Format condensed
* @cfg {Boolean} loadMask (true|false) default false
- * @cfg {Boolean} tfoot (true|false) generate tfoot, default true
- * @cfg {Boolean} thead (true|false) generate thead, default true
- * @cfg {Boolean} RowSelection (true|false) default false
- * @cfg {Boolean} CellSelection (true|false) default false
+ * @cfg {Boolean} footerShow (true|false) generate tfoot, default true
+ * @cfg {Boolean} headerShow (true|false) generate thead, default true
+ * @cfg {Boolean} rowSelection (true|false) default false
+ * @cfg {Boolean} cellSelection (true|false) default false
* @cfg {Roo.bootstrap.PagingToolbar} footer a paging toolbar
*
Roo.bootstrap.Table = function(config){
Roo.bootstrap.Table.superclass.constructor.call(this, config);
+ // BC...
+ this.rowSelection = (typeof(config.RowSelection) != 'undefined') ? config.RowSelection : this.rowSelection;
+ this.cellSelection = (typeof(config.CellSelection) != 'undefined') ? config.CellSelection : this.cellSelection;
+ this.headerShow = (typeof(config.thead) != 'undefined') ? config.thead : this.headerShow;
+ this.footerShow = (typeof(config.tfoot) != 'undefined') ? config.tfoot : this.footerShow;
+
+
if (this.sm) {
this.selModel = Roo.factory(this.sm, Roo.bootstrap.Table);
this.sm = this.selModel;
cm : false,
store : false,
loadMask : false,
- tfoot : true,
- thead : true,
- RowSelection : false,
- CellSelection : false,
+ footerShow : true,
+ headerShow : true,
+
+ rowSelection : false,
+ cellSelection : false,
layout : false,
// Roo.Element - the tbody
}
if(this.store || this.cm){
- if(this.thead){
+ if(this.headerShow){
cfg.cn.push(this.renderHeader());
}
cfg.cn.push(this.renderBody());
- if(this.tfoot){
+ if(this.footerShow){
cfg.cn.push(this.renderFooter());
}
{
var cell = Roo.get(el);
- if(!cell || (!this.CellSelection && !this.RowSelection)){
+ if(!cell || (!this.cellSelection && !this.rowSelection)){
return;
}
var cellIndex = cell.dom.cellIndex;
var rowIndex = this.getRowIndex(row);
- if(this.CellSelection){
+ // why??? - should these not be based on SelectionModel?
+ if(this.cellSelection){
this.fireEvent('cellclick', this, cell, rowIndex, cellIndex, e);
}
- if(this.RowSelection){
+ if(this.rowSelection){
this.fireEvent('rowclick', this, row, rowIndex, e);
}
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
var config = cm.config[i];
-
+
var c = {
tag: 'th',
style : '',
html: cm.getColumnHeader(i)
};
+ var hh = '';
+
+ if(typeof(config.lgHeader) != 'undefined'){
+ hh += '<span class="hidden-xs hidden-sm hidden-md">' + config.lgHeader + '</span>';
+ }
+
+ if(typeof(config.mdHeader) != 'undefined'){
+ hh += '<span class="hidden-xs hidden-sm hidden-lg">' + config.mdHeader + '</span>';
+ }
+
+ if(typeof(config.smHeader) != 'undefined'){
+ hh += '<span class="hidden-xs hidden-md hidden-lg">' + config.smHeader + '</span>';
+ }
+
+ if(typeof(config.xsHeader) != 'undefined'){
+ hh += '<span class="hidden-sm hidden-md hidden-lg">' + config.xsHeader + '</span>';
+ }
+
+ if(hh.length){
+ c.html = hh;
+ }
+
if(typeof(config.tooltip) != 'undefined'){
c.tooltip = config.tooltip;
}
* @cfg {String} autocomplete - default is new-password see: https://developers.google.com/web/fundamentals/input/form/label-and-name-inputs?hl=en
* @cfg {String} align (left|center|right) Default left
+ * @cfg {Boolean} forceFeedback (true|false) Default false
+ *
*
*
*
readOnly : false,
align : false,
formatedValue : false,
+ forceFeedback : false,
parentLabelAlign : function()
{
this.inputEl().on("blur", this.onBlur, this);
this.inputEl().relayEvent('keyup', this);
-
+
// reference to original value for reset
this.originalValue = this.getValue();
//Roo.form.TextField.superclass.initEvents.call(this);
this.el.removeClass([this.invalidClass, this.validClass]);
+ var feedback = this.el.select('.form-control-feedback', true).first();
+
+ if(feedback){
+ this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+ }
+
if(this.disabled || this.allowBlank){
return;
}
this.el.addClass(this.validClass);
- if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && this.getValue().length){
+ if(this.hasFeedback && this.inputType != 'hidden' && !this.allowBlank && (this.getValue().length || this.forceFeedback)){
var feedback = this.el.select('.form-control-feedback', true).first();
this.el.removeClass([this.invalidClass, this.validClass]);
+ var feedback = this.el.select('.form-control-feedback', true).first();
+
+ if(feedback){
+ this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
+ }
+
if(this.disabled || this.allowBlank){
return;
}
if(feedback){
this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
- if(this.getValue().length){
+ if(this.getValue().length || this.forceFeedback){
this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
}
]
};
}
-
+
} else {
if(this.removable && !this.editable && !this.tickable){
inputblock = {
cfg.cls += ' col-' + size + '-' + settings[size];
}
});
-
+ Roo.log(cfg);
return cfg;
},
var close = this.closeTriggerEl();
if(close){
- close.setVisibilityMode(Roo.Element.DISPALY).hide();
+ close.setVisibilityMode(Roo.Element.DISPLAY).hide();
close.on('click', this.removeBtnClick, this, close);
}
}
{
e.preventDefault();
- this.fireEvent("remove", this);
+ if(this.fireEvent("remove", this) !== false){
+ this.reset();
+ }
},
createList : function()
* @cfg {Boolean} triggerList trigger show the list or not (true|false) default true
* @cfg {Boolean} showToggleBtn show toggle button or not (true|false) default true
* @cfg {String} btnPosition set the position of the trigger button (left | right) default right
+ * @cfg {Boolean} animate default true
+ * @cfg {Boolean} emptyResultText only for touch device
* @constructor
* Create a new ComboBox.
* @param {Object} config Configuration options
*/
specialFilter : false,
+ /**
+ * @cfg {Boolean} mobileTouchView (true|false) show mobile touch view when using a mobile default true
+ */
+ mobileTouchView : true,
+
//private
addicon : false,
editicon: false,
btnPosition : 'right',
triggerList : true,
showToggleBtn : true,
+ animate : true,
+ emptyResultText: 'Empty',
// element that contains real text value.. (when hidden is used..)
getAutoCreate : function()
{
var cfg = false;
+ /*
+ * Touch Devices
+ */
+
+ if(Roo.isTouch && this.mobileTouchView){
+ cfg = this.getAutoCreateTouchView();
+ return cfg;;
+ }
+
/*
* Normal ComboBox
*/
if (!this.store) {
throw "can not find store for combo";
}
+
this.store = Roo.factory(this.store, Roo.data);
+ /*
+ * Touch Devices
+ */
+
+ if(Roo.isTouch && this.mobileTouchView){
+ this.initTouchView();
+ return;
+ }
+
if(this.tickable){
this.initTickableEvents();
return;
var close = this.closeTriggerEl();
if(close){
- (v.length || v * 1 > 0) ? close.show() : close.hide();
+ (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
}
},
/**
this.syncValue();
this.validate();
+
+ if(this.tickable && !Roo.isTouch){
+ this.view.refresh();
+ }
},
inputEl: function ()
{
+ if(Roo.isTouch && this.mobileTouchView){
+ return this.el.select('input.form-control',true).first();
+ }
+
if(this.tickable){
return this.searchField;
}
+
return this.el.select('input.form-control',true).first();
},
}
return this.inputEl().select('.select2-search-field-input', true).first();
- }
+ },
+ getAutoCreateTouchView : function()
+ {
+ var id = Roo.id();
+
+ var cfg = {
+ cls: 'form-group' //input-group
+ };
+
+ var input = {
+ tag: 'input',
+ id : id,
+ type : this.inputType,
+ cls : 'form-control x-combo-noedit',
+ autocomplete: 'new-password',
+ placeholder : this.placeholder || '',
+ readonly : true
+ };
+
+ if (this.name) {
+ input.name = this.name;
+ }
+
+ if (this.size) {
+ input.cls += ' input-' + this.size;
+ }
+
+ if (this.disabled) {
+ input.disabled = true;
+ }
+
+ var inputblock = {
+ cls : '',
+ cn : [
+ input
+ ]
+ };
+
+ if(this.before){
+ inputblock.cls += ' input-group';
+
+ inputblock.cn.unshift({
+ tag :'span',
+ cls : 'input-group-addon',
+ html : this.before
+ });
+ }
+
+ if(this.removable && !this.multiple){
+ inputblock.cls += ' roo-removable';
+
+ inputblock.cn.push({
+ tag: 'button',
+ html : 'x',
+ cls : 'roo-combo-removable-btn close'
+ });
+ }
- /**
- * @cfg {Boolean} grow
- * @hide
- */
- /**
- * @cfg {Number} growMin
- * @hide
- */
- /**
- * @cfg {Number} growMax
- * @hide
- */
- /**
- * @hide
- * @method autoSize
- */
-});
-/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
- *
- * Fork - LGPL
- * <script type="text/javascript">
- */
-
-/**
- * @class Roo.View
- * @extends Roo.util.Observable
- * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
- * This class also supports single and multi selection modes. <br>
- * Create a data model bound view:
- <pre><code>
- var store = new Roo.data.Store(...);
+ if(this.hasFeedback && !this.allowBlank){
+
+ inputblock.cls += ' has-feedback';
+
+ inputblock.cn.push({
+ tag: 'span',
+ cls: 'glyphicon form-control-feedback'
+ });
+
+ }
+
+ if (this.after) {
+
+ inputblock.cls += (this.before) ? '' : ' input-group';
+
+ inputblock.cn.push({
+ tag :'span',
+ cls : 'input-group-addon',
+ html : this.after
+ });
+ }
- var view = new Roo.View({
- el : "my-element",
- tpl : '<div id="{0}">{2} - {1}</div>', // auto create template
-
- singleSelect: true,
- selectedClass: "ydataview-selected",
- store: store
- });
+ var box = {
+ tag: 'div',
+ cn: [
+ {
+ tag: 'input',
+ type : 'hidden',
+ cls: 'form-hidden-field'
+ },
+ inputblock
+ ]
+
+ };
+
+ if(this.multiple){
+ box = {
+ tag: 'div',
+ cn: [
+ {
+ tag: 'input',
+ type : 'hidden',
+ cls: 'form-hidden-field'
+ },
+ {
+ tag: 'ul',
+ cls: 'select2-choices',
+ cn:[
+ {
+ tag: 'li',
+ cls: 'select2-search-field',
+ cn: [
- // listen for node click?
- view.on("click", function(vw, index, node, e){
- alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
- });
+ inputblock
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ };
+
+ var combobox = {
+ cls: 'select2-container input-group',
+ cn: [
+ box
+ ]
+ };
+
+ if(this.multiple){
+ combobox.cls += ' select2-container-multi';
+ }
+
+ var align = this.labelAlign || this.parentLabelAlign();
+
+ cfg.cn = combobox;
+
+ if(this.fieldLabel.length){
+
+ var lw = align === 'left' ? ('col-sm' + this.labelWidth) : '';
+ var cw = align === 'left' ? ('col-sm' + (12 - this.labelWidth)) : '';
+
+ cfg.cn = [
+ {
+ tag: 'label',
+ cls : 'control-label ' + lw,
+ html : this.fieldLabel
- // load XML data
- dataModel.load("foobar.xml");
- </code></pre>
- For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
- * <br><br>
- * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
- * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
- *
- * Note: old style constructor is still suported (container, template, config)
- *
- * @constructor
- * Create a new View
- * @param {Object} config The config object
- *
- */
-Roo.View = function(config, depreciated_tpl, depreciated_config){
-
- this.parent = false;
-
- if (typeof(depreciated_tpl) == 'undefined') {
- // new way.. - universal constructor.
- Roo.apply(this, config);
- this.el = Roo.get(this.el);
- } else {
- // old format..
- this.el = Roo.get(config);
- this.tpl = depreciated_tpl;
- Roo.apply(this, depreciated_config);
- }
- this.wrapEl = this.el.wrap().wrap();
- ///this.el = this.wrapEla.appendChild(document.createElement("div"));
-
-
- if(typeof(this.tpl) == "string"){
- this.tpl = new Roo.Template(this.tpl);
- } else {
- // support xtype ctors..
- this.tpl = new Roo.factory(this.tpl, Roo);
- }
-
+ },
+ {
+ cls : cw,
+ cn: [
+ combobox
+ ]
+ }
+ ];
+ }
+
+ var settings = this;
+
+ ['xs','sm','md','lg'].map(function(size){
+ if (settings[size]) {
+ cfg.cls += ' col-' + size + '-' + settings[size];
+ }
+ });
+
+ return cfg;
+ },
- this.tpl.compile();
+ initTouchView : function()
+ {
+ this.renderTouchView();
+
+ this.touchViewEl.on('scroll', function(){
+ this.el.dom.scrollTop = 0;
+ }, this);
+
+ this.inputEl().on("click", this.showTouchView, this);
+ this.touchViewFooterEl.select('.roo-touch-view-cancel', true).first().on('click', this.hideTouchView, this);
+ this.touchViewFooterEl.select('.roo-touch-view-ok', true).first().on('click', this.setTouchViewValue, this);
+
+ this.maskEl = new Roo.LoadMask(this.touchViewEl, { store : this.store, msgCls: 'roo-el-mask-msg' });
+
+ this.store.on('beforeload', this.onTouchViewBeforeLoad, this);
+ this.store.on('load', this.onTouchViewLoad, this);
+ this.store.on('loadexception', this.onTouchViewLoadException, this);
+
+ if(this.hiddenName){
+
+ this.hiddenField = this.el.select('input.form-hidden-field',true).first();
+
+ this.hiddenField.dom.value =
+ this.hiddenValue !== undefined ? this.hiddenValue :
+ this.value !== undefined ? this.value : '';
+
+ this.el.dom.removeAttribute('name');
+ this.hiddenField.dom.setAttribute('name', this.hiddenName);
+ }
+
+ if(this.multiple){
+ this.choices = this.el.select('ul.select2-choices', true).first();
+ this.searchField = this.el.select('ul li.select2-search-field', true).first();
+ }
+
+ if(this.removable && !this.multiple){
+ var close = this.closeTriggerEl();
+ if(close){
+ close.setVisibilityMode(Roo.Element.DISPLAY).hide();
+ close.on('click', this.removeBtnClick, this, close);
+ }
+ }
+
+ return;
+
+
+ },
- /** @private */
- this.addEvents({
- /**
- * @event beforeclick
- * Fires before a click is processed. Returns false to cancel the default action.
- * @param {Roo.View} this
- * @param {Number} index The index of the target node
- * @param {HTMLElement} node The target node
- * @param {Roo.EventObject} e The raw event object
- */
- "beforeclick" : true,
- /**
- * @event click
- * Fires when a template node is clicked.
- * @param {Roo.View} this
- * @param {Number} index The index of the target node
- * @param {HTMLElement} node The target node
- * @param {Roo.EventObject} e The raw event object
- */
- "click" : true,
- /**
- * @event dblclick
- * Fires when a template node is double clicked.
- * @param {Roo.View} this
- * @param {Number} index The index of the target node
- * @param {HTMLElement} node The target node
- * @param {Roo.EventObject} e The raw event object
- */
- "dblclick" : true,
- /**
- * @event contextmenu
- * Fires when a template node is right clicked.
- * @param {Roo.View} this
- * @param {Number} index The index of the target node
- * @param {HTMLElement} node The target node
- * @param {Roo.EventObject} e The raw event object
- */
- "contextmenu" : true,
- /**
- * @event selectionchange
- * Fires when the selected nodes change.
- * @param {Roo.View} this
- * @param {Array} selections Array of the selected nodes
- */
- "selectionchange" : true,
+ renderTouchView : function()
+ {
+ this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.ComboBox.touchViewTemplate);
+ this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
+ this.touchViewHeaderEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewBodyEl = this.touchViewEl.select('.modal-body', true).first();
+ this.touchViewBodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.touchViewBodyEl.setStyle('overflow', 'auto');
+
+ this.touchViewListGroup = this.touchViewBodyEl.select('.list-group', true).first();
+ this.touchViewListGroup.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewFooterEl = this.touchViewEl.select('.modal-footer', true).first();
+ this.touchViewFooterEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ },
- /**
- * @event beforeselect
- * Fires before a selection is made. If any handlers return false, the selection is cancelled.
- * @param {Roo.View} this
- * @param {HTMLElement} node The node to be selected
- * @param {Array} selections Array of currently selected nodes
- */
- "beforeselect" : true,
- /**
- * @event preparedata
- * Fires on every row to render, to allow you to change the data.
- * @param {Roo.View} this
- * @param {Object} data to be rendered (change this)
- */
- "preparedata" : true
-
-
- });
+ showTouchView : function()
+ {
+ this.touchViewHeaderEl.hide();
+ if(this.fieldLabel.length){
+ this.touchViewHeaderEl.dom.innerHTML = this.fieldLabel;
+ this.touchViewHeaderEl.show();
+ }
+ this.touchViewEl.show();
- this.el.on({
- "click": this.onClick,
- "dblclick": this.onDblClick,
- "contextmenu": this.onContextMenu,
- scope:this
- });
+ this.touchViewEl.select('.modal-dialog', true).first().setStyle('margin', '0px');
+ this.touchViewEl.select('.modal-dialog > .modal-content', true).first().setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
- this.selections = [];
- this.nodes = [];
- this.cmp = new Roo.CompositeElementLite([]);
- if(this.store){
- this.store = Roo.factory(this.store, Roo.data);
- this.setStore(this.store, true);
- }
-
- if ( this.footer && this.footer.xtype) {
-
- var fctr = this.wrapEl.appendChild(document.createElement("div"));
+ var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+ if(this.fieldLabel.length){
+ bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+ }
- this.footer.dataSource = this.store
- this.footer.container = fctr;
- this.footer = Roo.factory(this.footer, Roo);
- fctr.insertFirst(this.el);
+ this.touchViewBodyEl.setHeight(bodyHeight);
+
+ if(this.animate){
+ var _this = this;
+ (function(){ _this.touchViewEl.addClass('in'); }).defer(50);
+ }else{
+ this.touchViewEl.addClass('in');
+ }
+
+ this.doTouchViewQuery();
- // this is a bit insane - as the paging toolbar seems to detach the el..
-// dom.parentNode.parentNode.parentNode
- // they get detached?
- }
+ },
+ hideTouchView : function()
+ {
+ this.touchViewEl.removeClass('in');
+
+ if(this.animate){
+ var _this = this;
+ (function(){ _this.touchViewEl.setStyle('display', 'none'); }).defer(150);
+ }else{
+ this.touchViewEl.setStyle('display', 'none');
+ }
+
+ },
- Roo.View.superclass.constructor.call(this);
+ setTouchViewValue : function()
+ {
+ if(this.multiple){
+ this.clearItem();
+
+ var _this = this;
+
+ Roo.each(this.tickItems, function(o){
+ this.addItem(o);
+ }, this);
+ }
+
+ this.hideTouchView();
+ },
+ doTouchViewQuery : function()
+ {
+ var qe = {
+ query: '',
+ forceAll: true,
+ combo: this,
+ cancel:false
+ };
+
+ if(this.fireEvent('beforequery', qe) ===false || qe.cancel){
+ return false;
+ }
+
+ if(!this.alwaysQuery || this.mode == 'local'){
+ this.onTouchViewLoad();
+ return;
+ }
+
+ this.store.load();
+ },
-};
+ onTouchViewBeforeLoad : function(combo,opts)
+ {
+ return;
+ },
-Roo.extend(Roo.View, Roo.util.Observable, {
+ // private
+ onTouchViewLoad : function()
+ {
+ if(this.store.getCount() < 1){
+ this.onTouchViewEmptyResults();
+ return;
+ }
+
+ this.clearTouchView();
+
+ var rawValue = this.getRawValue();
+
+ var template = (this.multiple) ? Roo.bootstrap.ComboBox.listItemCheckbox : Roo.bootstrap.ComboBox.listItemRadio;
+
+ this.tickItems = [];
+
+ this.store.data.each(function(d, rowIndex){
+ var row = this.touchViewListGroup.createChild(template);
+
+ if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
+ row.select('.roo-combobox-list-group-item-value', true).first().dom.innerHTML = d.data[this.displayField];
+ }
+
+ if(!this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue()){
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ }
+
+ if(this.multiple && this.valueField && typeof(d.data[this.valueField]) != 'undefined' && this.getValue().indexOf(d.data[this.valueField]) != -1){
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ this.tickItems.push(d.data);
+ }
+
+ row.on('click', this.onTouchViewClick, this, {row : row, rowIndex : rowIndex});
+
+ }, this);
+
+ var firstChecked = this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).first();
+
+ var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+ if(this.fieldLabel.length){
+ bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+ }
+
+ var listHeight = this.touchViewListGroup.getHeight();
+
+ var _this = this;
+
+ if(firstChecked && listHeight > bodyHeight){
+ (function() { firstChecked.findParent('li').scrollIntoView(_this.touchViewListGroup.dom); }).defer(500);
+ }
+
+ },
- /**
- * @cfg {Roo.data.Store} store Data store to load data from.
- */
- store : false,
+ onTouchViewLoadException : function()
+ {
+ this.hideTouchView();
+ },
- /**
- * @cfg {String|Roo.Element} el The container element.
- */
- el : '',
+ onTouchViewEmptyResults : function()
+ {
+ this.clearTouchView();
+
+ this.touchViewListGroup.createChild(Roo.bootstrap.ComboBox.emptyResult);
+
+ this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
+
+ },
- /**
- * @cfg {String|Roo.Template} tpl The template used by this View
- */
- tpl : false,
- /**
- * @cfg {String} dataName the named area of the template to use as the data area
- * Works with domtemplates roo-name="name"
- */
- dataName: false,
- /**
- * @cfg {String} selectedClass The css class to add to selected nodes
- */
- selectedClass : "x-view-selected",
- /**
- * @cfg {String} emptyText The empty text to show when nothing is loaded.
- */
- emptyText : "",
-
- /**
- * @cfg {String} text to display on mask (default Loading)
- */
- mask : false,
- /**
- * @cfg {Boolean} multiSelect Allow multiple selection
- */
- multiSelect : false,
- /**
- * @cfg {Boolean} singleSelect Allow single selection
- */
- singleSelect: false,
-
- /**
- * @cfg {Boolean} toggleSelect - selecting
- */
- toggleSelect : false,
-
- /**
- * @cfg {Boolean} tickable - selecting
- */
- tickable : false,
-
- /**
- * Returns the element this view is bound to.
- * @return {Roo.Element}
- */
- getEl : function(){
- return this.wrapEl;
+ clearTouchView : function()
+ {
+ this.touchViewListGroup.dom.innerHTML = '';
},
-
-
- /**
- * Refreshes the view. - called by datachanged on the store. - do not call directly.
- */
- refresh : function(){
- //Roo.log('refresh');
- var t = this.tpl;
-
- // if we are using something like 'domtemplate', then
- // the what gets used is:
- // t.applySubtemplate(NAME, data, wrapping data..)
- // the outer template then get' applied with
- // the store 'extra data'
- // and the body get's added to the
- // roo-name="data" node?
- // <span class='roo-tpl-{name}'></span> ?????
+ onTouchViewClick : function(e, el, o)
+ {
+ e.preventDefault();
+ var row = o.row;
+ var rowIndex = o.rowIndex;
+ var r = this.store.getAt(rowIndex);
- this.clearSelections();
- this.el.update("");
- var html = [];
- var records = this.store.getRange();
- if(records.length < 1) {
-
- // is this valid?? = should it render a template??
+ if(!this.multiple){
+ Roo.each(this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).elements, function(c){
+ c.dom.removeAttribute('checked');
+ }, this);
- this.el.update(this.emptyText);
- return;
- }
- var el = this.el;
- if (this.dataName) {
- this.el.update(t.apply(this.store.meta)); //????
- el = this.el.child('.roo-tpl-' + this.dataName);
- }
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
- for(var i = 0, len = records.length; i < len; i++){
- var data = this.prepareData(records[i].data, i, records[i]);
- this.fireEvent("preparedata", this, data, i, records[i]);
-
- var d = Roo.apply({}, data);
-
- if(this.tickable){
- Roo.apply(d, {'roo-id' : Roo.id()});
-
- var _this = this;
+ this.setFromData(r.data);
- Roo.each(this.parent.item, function(item){
- if(item[_this.parent.valueField] != data[_this.parent.valueField]){
- return;
- }
- Roo.apply(d, {'roo-data-checked' : 'checked'});
- });
+ var close = this.closeTriggerEl();
+
+ if(close){
+ close.show();
}
+
+ this.hideTouchView();
- html[html.length] = Roo.util.Format.trim(
- this.dataName ?
- t.applySubtemplate(this.dataName, d, this.store.meta) :
- t.apply(d)
- );
+ this.fireEvent('select', this, r, rowIndex);
+
+ return;
}
+ if(this.valueField && typeof(r.data[this.valueField]) != 'undefined' && this.getValue().indexOf(r.data[this.valueField]) != -1){
+ row.select('.roo-combobox-list-group-item-box > input', true).first().dom.removeAttribute('checked');
+ this.tickItems.splice(this.tickItems.indexOf(r.data), 1);
+ return;
+ }
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ this.addItem(r.data);
+ this.tickItems.push(r.data);
- el.update(html.join(""));
- this.nodes = el.dom.childNodes;
- this.updateIndexes(0);
- },
+ }
+ /**
+ * @cfg {Boolean} grow
+ * @hide
+ */
+ /**
+ * @cfg {Number} growMin
+ * @hide
+ */
+ /**
+ * @cfg {Number} growMax
+ * @hide
+ */
/**
- * Function to override to reformat the data that is sent to
- * the template for each node.
- * DEPRICATED - use the preparedata event handler.
- * @param {Array/Object} data The raw data (array of colData for a data model bound view or
- * a JSON object for an UpdateManager bound view).
+ * @hide
+ * @method autoSize
*/
- prepareData : function(data, index, record)
- {
- this.fireEvent("preparedata", this, data, index, record);
- return data;
- },
+});
- onUpdate : function(ds, record){
- // Roo.log('on update');
- this.clearSelections();
- var index = this.store.indexOf(record);
- var n = this.nodes[index];
- this.tpl.insertBefore(n, this.prepareData(record.data, index, record));
- n.parentNode.removeChild(n);
- this.updateIndexes(index, index);
+Roo.apply(Roo.bootstrap.ComboBox, {
+
+ header : {
+ tag: 'div',
+ cls: 'modal-header',
+ cn: [
+ {
+ tag: 'h4',
+ cls: 'modal-title'
+ }
+ ]
},
-
+ body : {
+ tag: 'div',
+ cls: 'modal-body',
+ cn: [
+ {
+ tag: 'ul',
+ cls: 'list-group'
+ }
+ ]
+ },
-// --------- FIXME
- onAdd : function(ds, records, index)
- {
- //Roo.log(['on Add', ds, records, index] );
- this.clearSelections();
- if(this.nodes.length == 0){
- this.refresh();
- return;
- }
- var n = this.nodes[index];
- for(var i = 0, len = records.length; i < len; i++){
- var d = this.prepareData(records[i].data, i, records[i]);
- if(n){
- this.tpl.insertBefore(n, d);
- }else{
-
- this.tpl.append(this.el, d);
+ listItemRadio : {
+ tag: 'li',
+ cls: 'list-group-item',
+ cn: [
+ {
+ tag: 'span',
+ cls: 'roo-combobox-list-group-item-value'
+ },
+ {
+ tag: 'div',
+ cls: 'roo-combobox-list-group-item-box pull-xs-right radio-inline radio radio-info',
+ cn: [
+ {
+ tag: 'input',
+ type: 'radio'
+ },
+ {
+ tag: 'label'
+ }
+ ]
}
- }
- this.updateIndexes(index);
+ ]
},
-
- onRemove : function(ds, record, index){
- // Roo.log('onRemove');
- this.clearSelections();
- var el = this.dataName ?
- this.el.child('.roo-tpl-' + this.dataName) :
- this.el;
-
- el.dom.removeChild(this.nodes[index]);
- this.updateIndexes(index);
+
+ listItemCheckbox : {
+ tag: 'li',
+ cls: 'list-group-item',
+ cn: [
+ {
+ tag: 'span',
+ cls: 'roo-combobox-list-group-item-value'
+ },
+ {
+ tag: 'div',
+ cls: 'roo-combobox-list-group-item-box pull-xs-right checkbox-inline checkbox checkbox-info',
+ cn: [
+ {
+ tag: 'input',
+ type: 'checkbox'
+ },
+ {
+ tag: 'label'
+ }
+ ]
+ }
+ ]
},
-
- /**
- * Refresh an individual node.
- * @param {Number} index
- */
- refreshNode : function(index){
- this.onUpdate(this.store, this.store.getAt(index));
+
+ emptyResult : {
+ tag: 'div',
+ cls: 'alert alert-danger roo-combobox-touch-view-empty-result'
},
+
+ footer : {
+ tag: 'div',
+ cls: 'modal-footer',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'row',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'col-xs-6 text-left',
+ cn: {
+ tag: 'button',
+ cls: 'btn btn-danger roo-touch-view-cancel',
+ html: 'Cancel'
+ }
+ },
+ {
+ tag: 'div',
+ cls: 'col-xs-6 text-right',
+ cn: {
+ tag: 'button',
+ cls: 'btn btn-success roo-touch-view-ok',
+ html: 'OK'
+ }
+ }
+ ]
+ }
+ ]
+
+ }
+});
- updateIndexes : function(startIndex, endIndex){
- var ns = this.nodes;
- startIndex = startIndex || 0;
- endIndex = endIndex || ns.length - 1;
- for(var i = startIndex; i <= endIndex; i++){
- ns[i].nodeIndex = i;
- }
- },
+Roo.apply(Roo.bootstrap.ComboBox, {
+
+ touchViewTemplate : {
+ tag: 'div',
+ cls: 'modal fade roo-combobox-touch-view',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'modal-dialog',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'modal-content',
+ cn: [
+ Roo.bootstrap.ComboBox.header,
+ Roo.bootstrap.ComboBox.body,
+ Roo.bootstrap.ComboBox.footer
+ ]
+ }
+ ]
+ }
+ ]
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
- /**
- * Changes the data store this view uses and refresh the view.
- * @param {Store} store
- */
- setStore : function(store, initial){
- if(!initial && this.store){
- this.store.un("datachanged", this.refresh);
- this.store.un("add", this.onAdd);
- this.store.un("remove", this.onRemove);
- this.store.un("update", this.onUpdate);
- this.store.un("clear", this.refresh);
- this.store.un("beforeload", this.onBeforeLoad);
- this.store.un("load", this.onLoad);
- this.store.un("loadexception", this.onLoad);
- }
- if(store){
+/**
+ * @class Roo.View
+ * @extends Roo.util.Observable
+ * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
+ * This class also supports single and multi selection modes. <br>
+ * Create a data model bound view:
+ <pre><code>
+ var store = new Roo.data.Store(...);
+
+ var view = new Roo.View({
+ el : "my-element",
+ tpl : '<div id="{0}">{2} - {1}</div>', // auto create template
+
+ singleSelect: true,
+ selectedClass: "ydataview-selected",
+ store: store
+ });
+
+ // listen for node click?
+ view.on("click", function(vw, index, node, e){
+ alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
+ });
+
+ // load XML data
+ dataModel.load("foobar.xml");
+ </code></pre>
+ For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
+ * <br><br>
+ * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
+ * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
+ *
+ * Note: old style constructor is still suported (container, template, config)
+ *
+ * @constructor
+ * Create a new View
+ * @param {Object} config The config object
+ *
+ */
+Roo.View = function(config, depreciated_tpl, depreciated_config){
+
+ this.parent = false;
+
+ if (typeof(depreciated_tpl) == 'undefined') {
+ // new way.. - universal constructor.
+ Roo.apply(this, config);
+ this.el = Roo.get(this.el);
+ } else {
+ // old format..
+ this.el = Roo.get(config);
+ this.tpl = depreciated_tpl;
+ Roo.apply(this, depreciated_config);
+ }
+ this.wrapEl = this.el.wrap().wrap();
+ ///this.el = this.wrapEla.appendChild(document.createElement("div"));
+
+
+ if(typeof(this.tpl) == "string"){
+ this.tpl = new Roo.Template(this.tpl);
+ } else {
+ // support xtype ctors..
+ this.tpl = new Roo.factory(this.tpl, Roo);
+ }
+
+
+ this.tpl.compile();
+
+ /** @private */
+ this.addEvents({
+ /**
+ * @event beforeclick
+ * Fires before a click is processed. Returns false to cancel the default action.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "beforeclick" : true,
+ /**
+ * @event click
+ * Fires when a template node is clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "click" : true,
+ /**
+ * @event dblclick
+ * Fires when a template node is double clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "dblclick" : true,
+ /**
+ * @event contextmenu
+ * Fires when a template node is right clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "contextmenu" : true,
+ /**
+ * @event selectionchange
+ * Fires when the selected nodes change.
+ * @param {Roo.View} this
+ * @param {Array} selections Array of the selected nodes
+ */
+ "selectionchange" : true,
+
+ /**
+ * @event beforeselect
+ * Fires before a selection is made. If any handlers return false, the selection is cancelled.
+ * @param {Roo.View} this
+ * @param {HTMLElement} node The node to be selected
+ * @param {Array} selections Array of currently selected nodes
+ */
+ "beforeselect" : true,
+ /**
+ * @event preparedata
+ * Fires on every row to render, to allow you to change the data.
+ * @param {Roo.View} this
+ * @param {Object} data to be rendered (change this)
+ */
+ "preparedata" : true
- store.on("datachanged", this.refresh, this);
- store.on("add", this.onAdd, this);
- store.on("remove", this.onRemove, this);
- store.on("update", this.onUpdate, this);
- store.on("clear", this.refresh, this);
- store.on("beforeload", this.onBeforeLoad, this);
- store.on("load", this.onLoad, this);
- store.on("loadexception", this.onLoad, this);
- }
+
+ });
+
+
+
+ this.el.on({
+ "click": this.onClick,
+ "dblclick": this.onDblClick,
+ "contextmenu": this.onContextMenu,
+ scope:this
+ });
+
+ this.selections = [];
+ this.nodes = [];
+ this.cmp = new Roo.CompositeElementLite([]);
+ if(this.store){
+ this.store = Roo.factory(this.store, Roo.data);
+ this.setStore(this.store, true);
+ }
+
+ if ( this.footer && this.footer.xtype) {
+
+ var fctr = this.wrapEl.appendChild(document.createElement("div"));
- if(store){
- this.refresh();
- }
- },
+ this.footer.dataSource = this.store
+ this.footer.container = fctr;
+ this.footer = Roo.factory(this.footer, Roo);
+ fctr.insertFirst(this.el);
+
+ // this is a bit insane - as the paging toolbar seems to detach the el..
+// dom.parentNode.parentNode.parentNode
+ // they get detached?
+ }
+
+
+ Roo.View.superclass.constructor.call(this);
+
+
+};
+
+Roo.extend(Roo.View, Roo.util.Observable, {
+
+ /**
+ * @cfg {Roo.data.Store} store Data store to load data from.
+ */
+ store : false,
+
/**
- * onbeforeLoad - masks the loading area.
- *
+ * @cfg {String|Roo.Element} el The container element.
*/
- onBeforeLoad : function(store,opts)
- {
- //Roo.log('onBeforeLoad');
- if (!opts.add) {
- this.el.update("");
- }
- this.el.mask(this.mask ? this.mask : "Loading" );
- },
- onLoad : function ()
- {
- this.el.unmask();
- },
+ el : '',
-
/**
- * Returns the template node the passed child belongs to or null if it doesn't belong to one.
- * @param {HTMLElement} node
- * @return {HTMLElement} The template node
+ * @cfg {String|Roo.Template} tpl The template used by this View
*/
- findItemFromChild : function(node){
- var el = this.dataName ?
- this.el.child('.roo-tpl-' + this.dataName,true) :
- this.el.dom;
-
- if(!node || node.parentNode == el){
+ tpl : false,
+ /**
+ * @cfg {String} dataName the named area of the template to use as the data area
+ * Works with domtemplates roo-name="name"
+ */
+ dataName: false,
+ /**
+ * @cfg {String} selectedClass The css class to add to selected nodes
+ */
+ selectedClass : "x-view-selected",
+ /**
+ * @cfg {String} emptyText The empty text to show when nothing is loaded.
+ */
+ emptyText : "",
+
+ /**
+ * @cfg {String} text to display on mask (default Loading)
+ */
+ mask : false,
+ /**
+ * @cfg {Boolean} multiSelect Allow multiple selection
+ */
+ multiSelect : false,
+ /**
+ * @cfg {Boolean} singleSelect Allow single selection
+ */
+ singleSelect: false,
+
+ /**
+ * @cfg {Boolean} toggleSelect - selecting
+ */
+ toggleSelect : false,
+
+ /**
+ * @cfg {Boolean} tickable - selecting
+ */
+ tickable : false,
+
+ /**
+ * Returns the element this view is bound to.
+ * @return {Roo.Element}
+ */
+ getEl : function(){
+ return this.wrapEl;
+ },
+
+
+
+ /**
+ * Refreshes the view. - called by datachanged on the store. - do not call directly.
+ */
+ refresh : function(){
+ //Roo.log('refresh');
+ var t = this.tpl;
+
+ // if we are using something like 'domtemplate', then
+ // the what gets used is:
+ // t.applySubtemplate(NAME, data, wrapping data..)
+ // the outer template then get' applied with
+ // the store 'extra data'
+ // and the body get's added to the
+ // roo-name="data" node?
+ // <span class='roo-tpl-{name}'></span> ?????
+
+
+
+ this.clearSelections();
+ this.el.update("");
+ var html = [];
+ var records = this.store.getRange();
+ if(records.length < 1) {
+
+ // is this valid?? = should it render a template??
+
+ this.el.update(this.emptyText);
+ return;
+ }
+ var el = this.el;
+ if (this.dataName) {
+ this.el.update(t.apply(this.store.meta)); //????
+ el = this.el.child('.roo-tpl-' + this.dataName);
+ }
+
+ for(var i = 0, len = records.length; i < len; i++){
+ var data = this.prepareData(records[i].data, i, records[i]);
+ this.fireEvent("preparedata", this, data, i, records[i]);
+
+ var d = Roo.apply({}, data);
+
+ if(this.tickable){
+ Roo.apply(d, {'roo-id' : Roo.id()});
+
+ var _this = this;
+
+ Roo.each(this.parent.item, function(item){
+ if(item[_this.parent.valueField] != data[_this.parent.valueField]){
+ return;
+ }
+ Roo.apply(d, {'roo-data-checked' : 'checked'});
+ });
+ }
+
+ html[html.length] = Roo.util.Format.trim(
+ this.dataName ?
+ t.applySubtemplate(this.dataName, d, this.store.meta) :
+ t.apply(d)
+ );
+ }
+
+
+
+ el.update(html.join(""));
+ this.nodes = el.dom.childNodes;
+ this.updateIndexes(0);
+ },
+
+
+ /**
+ * Function to override to reformat the data that is sent to
+ * the template for each node.
+ * DEPRICATED - use the preparedata event handler.
+ * @param {Array/Object} data The raw data (array of colData for a data model bound view or
+ * a JSON object for an UpdateManager bound view).
+ */
+ prepareData : function(data, index, record)
+ {
+ this.fireEvent("preparedata", this, data, index, record);
+ return data;
+ },
+
+ onUpdate : function(ds, record){
+ // Roo.log('on update');
+ this.clearSelections();
+ var index = this.store.indexOf(record);
+ var n = this.nodes[index];
+ this.tpl.insertBefore(n, this.prepareData(record.data, index, record));
+ n.parentNode.removeChild(n);
+ this.updateIndexes(index, index);
+ },
+
+
+
+// --------- FIXME
+ onAdd : function(ds, records, index)
+ {
+ //Roo.log(['on Add', ds, records, index] );
+ this.clearSelections();
+ if(this.nodes.length == 0){
+ this.refresh();
+ return;
+ }
+ var n = this.nodes[index];
+ for(var i = 0, len = records.length; i < len; i++){
+ var d = this.prepareData(records[i].data, i, records[i]);
+ if(n){
+ this.tpl.insertBefore(n, d);
+ }else{
+
+ this.tpl.append(this.el, d);
+ }
+ }
+ this.updateIndexes(index);
+ },
+
+ onRemove : function(ds, record, index){
+ // Roo.log('onRemove');
+ this.clearSelections();
+ var el = this.dataName ?
+ this.el.child('.roo-tpl-' + this.dataName) :
+ this.el;
+
+ el.dom.removeChild(this.nodes[index]);
+ this.updateIndexes(index);
+ },
+
+ /**
+ * Refresh an individual node.
+ * @param {Number} index
+ */
+ refreshNode : function(index){
+ this.onUpdate(this.store, this.store.getAt(index));
+ },
+
+ updateIndexes : function(startIndex, endIndex){
+ var ns = this.nodes;
+ startIndex = startIndex || 0;
+ endIndex = endIndex || ns.length - 1;
+ for(var i = startIndex; i <= endIndex; i++){
+ ns[i].nodeIndex = i;
+ }
+ },
+
+ /**
+ * Changes the data store this view uses and refresh the view.
+ * @param {Store} store
+ */
+ setStore : function(store, initial){
+ if(!initial && this.store){
+ this.store.un("datachanged", this.refresh);
+ this.store.un("add", this.onAdd);
+ this.store.un("remove", this.onRemove);
+ this.store.un("update", this.onUpdate);
+ this.store.un("clear", this.refresh);
+ this.store.un("beforeload", this.onBeforeLoad);
+ this.store.un("load", this.onLoad);
+ this.store.un("loadexception", this.onLoad);
+ }
+ if(store){
+
+ store.on("datachanged", this.refresh, this);
+ store.on("add", this.onAdd, this);
+ store.on("remove", this.onRemove, this);
+ store.on("update", this.onUpdate, this);
+ store.on("clear", this.refresh, this);
+ store.on("beforeload", this.onBeforeLoad, this);
+ store.on("load", this.onLoad, this);
+ store.on("loadexception", this.onLoad, this);
+ }
+
+ if(store){
+ this.refresh();
+ }
+ },
+ /**
+ * onbeforeLoad - masks the loading area.
+ *
+ */
+ onBeforeLoad : function(store,opts)
+ {
+ //Roo.log('onBeforeLoad');
+ if (!opts.add) {
+ this.el.update("");
+ }
+ this.el.mask(this.mask ? this.mask : "Loading" );
+ },
+ onLoad : function ()
+ {
+ this.el.unmask();
+ },
+
+
+ /**
+ * Returns the template node the passed child belongs to or null if it doesn't belong to one.
+ * @param {HTMLElement} node
+ * @return {HTMLElement} The template node
+ */
+ findItemFromChild : function(node){
+ var el = this.dataName ?
+ this.el.child('.roo-tpl-' + this.dataName,true) :
+ this.el.dom;
+
+ if(!node || node.parentNode == el){
return node;
}
var p = node.parentNode;
},
setTitle: function(str)
{
+ this.title = str;
this.el.select('.popover-title',true).first().dom.innerHTML = str;
},
setContent: function(str)
{
+ this.html = str;
this.el.select('.popover-content',true).first().dom.innerHTML = str;
},
// as it get's added to the bottom of the page.
// set content.
this.el.select('.popover-title',true).first().dom.innerHtml = this.title;
if (this.html !== false) {
- this.el.select('.popover-content',true).first().dom.innerHtml = this.title;
+ this.el.select('.popover-content',true).first().dom.innerHtml = this.html;
}
this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
if (!this.title.length) {
//arrow.set(align[2],
this.el.addClass('in');
- this.hoverState = null;
+
if (this.el.hasClass('fade')) {
// fade it?
this.el.setXY([0,0]);
this.el.removeClass('in');
this.el.hide();
+ this.hoverState = null;
}
// id of frame..
frameId: false,
- // private properties
- validationEvent : false,
- deferHeight: true,
- initialized : false,
- activated : false,
+ // private properties
+ validationEvent : false,
+ deferHeight: true,
+ initialized : false,
+ activated : false,
+
+ onFocus : Roo.emptyFn,
+ iframePad:3,
+ hideMode:'offsets',
+
+
+ tbContainer : false,
+
+ toolbarContainer :function() {
+ return this.wrap.select('.x-html-editor-tb',true).first();
+ },
+
+ /**
+ * Protected method that will not generally be called directly. It
+ * is called when the editor creates its toolbar. Override this method if you need to
+ * add custom toolbar buttons.
+ * @param {HtmlEditor} editor
+ */
+ createToolbar : function(){
+
+ Roo.log("create toolbars");
+
+ this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
+ this.toolbars[0].render(this.toolbarContainer());
+
+ return;
+
+// if (!editor.toolbars || !editor.toolbars.length) {
+// editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
+// }
+//
+// for (var i =0 ; i < editor.toolbars.length;i++) {
+// editor.toolbars[i] = Roo.factory(
+// typeof(editor.toolbars[i]) == 'string' ?
+// { xtype: editor.toolbars[i]} : editor.toolbars[i],
+// Roo.bootstrap.HtmlEditor);
+// editor.toolbars[i].init(editor);
+// }
+ },
+
+
+ // private
+ onRender : function(ct, position)
+ {
+ // Roo.log("Call onRender: " + this.xtype);
+ var _t = this;
+ Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
+
+ this.wrap = this.inputEl().wrap({
+ cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+ });
+
+ this.editorcore.onRender(ct, position);
+
+ if (this.resizable) {
+ this.resizeEl = new Roo.Resizable(this.wrap, {
+ pinned : true,
+ wrap: true,
+ dynamic : true,
+ minHeight : this.height,
+ height: this.height,
+ handles : this.resizable,
+ width: this.width,
+ listeners : {
+ resize : function(r, w, h) {
+ _t.onResize(w,h); // -something
+ }
+ }
+ });
+
+ }
+ this.createToolbar(this);
+
+
+ if(!this.width && this.resizable){
+ this.setSize(this.wrap.getSize());
+ }
+ if (this.resizeEl) {
+ this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
+ // should trigger onReize..
+ }
+
+ },
+
+ // private
+ onResize : function(w, h)
+ {
+ Roo.log('resize: ' +w + ',' + h );
+ Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
+ var ew = false;
+ var eh = false;
+
+ if(this.inputEl() ){
+ if(typeof w == 'number'){
+ var aw = w - this.wrap.getFrameWidth('lr');
+ this.inputEl().setWidth(this.adjustWidth('textarea', aw));
+ ew = aw;
+ }
+ if(typeof h == 'number'){
+ var tbh = -11; // fixme it needs to tool bar size!
+ for (var i =0; i < this.toolbars.length;i++) {
+ // fixme - ask toolbars for heights?
+ tbh += this.toolbars[i].el.getHeight();
+ //if (this.toolbars[i].footer) {
+ // tbh += this.toolbars[i].footer.el.getHeight();
+ //}
+ }
+
+
+
+
+
+ var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
+ ah -= 5; // knock a few pixes off for look..
+ this.inputEl().setHeight(this.adjustWidth('textarea', ah));
+ var eh = ah;
+ }
+ }
+ Roo.log('onResize:' + [w,h,ew,eh].join(',') );
+ this.editorcore.onResize(ew,eh);
+
+ },
+
+ /**
+ * Toggles the editor between standard and source edit mode.
+ * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+ */
+ toggleSourceEdit : function(sourceEditMode)
+ {
+ this.editorcore.toggleSourceEdit(sourceEditMode);
+
+ if(this.editorcore.sourceEditMode){
+ Roo.log('editor - showing textarea');
+
+// Roo.log('in');
+// Roo.log(this.syncValue());
+ this.syncValue();
+ this.inputEl().removeClass(['hide', 'x-hidden']);
+ this.inputEl().dom.removeAttribute('tabIndex');
+ this.inputEl().focus();
+ }else{
+ Roo.log('editor - hiding textarea');
+// Roo.log('out')
+// Roo.log(this.pushValue());
+ this.pushValue();
+
+ this.inputEl().addClass(['hide', 'x-hidden']);
+ this.inputEl().dom.setAttribute('tabIndex', -1);
+ //this.deferFocus();
+ }
+
+ if(this.resizable){
+ this.setSize(this.wrap.getSize());
+ }
+
+ this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
+ },
+
+ // private (for BoxComponent)
+ adjustSize : Roo.BoxComponent.prototype.adjustSize,
+
+ // private (for BoxComponent)
+ getResizeEl : function(){
+ return this.wrap;
+ },
+
+ // private (for BoxComponent)
+ getPositionEl : function(){
+ return this.wrap;
+ },
+
+ // private
+ initEvents : function(){
+ this.originalValue = this.getValue();
+ },
+
+// /**
+// * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+// * @method
+// */
+// markInvalid : Roo.emptyFn,
+// /**
+// * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+// * @method
+// */
+// clearInvalid : Roo.emptyFn,
+
+ setValue : function(v){
+ Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
+ this.editorcore.pushValue();
+ },
+
+
+ // private
+ deferFocus : function(){
+ this.focus.defer(10, this);
+ },
+
+ // doc'ed in Field
+ focus : function(){
+ this.editorcore.focus();
+
+ },
+
+
+ // private
+ onDestroy : function(){
+
+
+
+ if(this.rendered){
+
+ for (var i =0; i < this.toolbars.length;i++) {
+ // fixme - ask toolbars for heights?
+ this.toolbars[i].onDestroy();
+ }
+
+ this.wrap.dom.innerHTML = '';
+ this.wrap.remove();
+ }
+ },
+
+ // private
+ onFirstFocus : function(){
+ //Roo.log("onFirstFocus");
+ this.editorcore.onFirstFocus();
+ for (var i =0; i < this.toolbars.length;i++) {
+ this.toolbars[i].onFirstFocus();
+ }
+
+ },
+
+ // private
+ syncValue : function()
+ {
+ this.editorcore.syncValue();
+ },
+
+ pushValue : function()
+ {
+ this.editorcore.pushValue();
+ }
+
+
+ // hide stuff that is not compatible
+ /**
+ * @event blur
+ * @hide
+ */
+ /**
+ * @event change
+ * @hide
+ */
+ /**
+ * @event focus
+ * @hide
+ */
+ /**
+ * @event specialkey
+ * @hide
+ */
+ /**
+ * @cfg {String} fieldClass @hide
+ */
+ /**
+ * @cfg {String} focusClass @hide
+ */
+ /**
+ * @cfg {String} autoCreate @hide
+ */
+ /**
+ * @cfg {String} inputType @hide
+ */
+ /**
+ * @cfg {String} invalidClass @hide
+ */
+ /**
+ * @cfg {String} invalidText @hide
+ */
+ /**
+ * @cfg {String} msgFx @hide
+ */
+ /**
+ * @cfg {String} validateOnBlur @hide
+ */
+});
+
+
+
+
+
+
+Roo.namespace('Roo.bootstrap.htmleditor');
+/**
+ * @class Roo.bootstrap.HtmlEditorToolbar1
+ * Basic Toolbar
+ *
+ * Usage:
+ *
+ new Roo.bootstrap.HtmlEditor({
+ ....
+ toolbars : [
+ new Roo.bootstrap.HtmlEditorToolbar1({
+ disable : { fonts: 1 , format: 1, ..., ... , ...],
+ btns : [ .... ]
+ })
+ }
+
+ *
+ * @cfg {Object} disable List of elements to disable..
+ * @cfg {Array} btns List of additional buttons.
+ *
+ *
+ * NEEDS Extra CSS?
+ * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ */
+
+Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
+{
+
+ Roo.apply(this, config);
+
+ // default disabled, based on 'good practice'..
+ this.disable = this.disable || {};
+ Roo.applyIf(this.disable, {
+ fontSize : true,
+ colors : true,
+ specialElements : true
+ });
+ Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
+
+ this.editor = config.editor;
+ this.editorcore = config.editor.editorcore;
+
+ this.buttons = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+
+ //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
+ // dont call parent... till later.
+}
+Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar, {
+
+ bar : true,
+
+ editor : false,
+ editorcore : false,
+
+
+ formats : [
+ "p" ,
+ "h1","h2","h3","h4","h5","h6",
+ "pre", "code",
+ "abbr", "acronym", "address", "cite", "samp", "var",
+ 'div','span'
+ ],
+
+ onRender : function(ct, position)
+ {
+ // Roo.log("Call onRender: " + this.xtype);
+
+ Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
+ Roo.log(this.el);
+ this.el.dom.style.marginBottom = '0';
+ var _this = this;
+ var editorcore = this.editorcore;
+ var editor= this.editor;
+
+ var children = [];
+ var btn = function(id,cmd , toggle, handler){
+
+ var event = toggle ? 'toggle' : 'click';
+
+ var a = {
+ size : 'sm',
+ xtype: 'Button',
+ xns: Roo.bootstrap,
+ glyphicon : id,
+ cmd : id || cmd,
+ enableToggle:toggle !== false,
+ //html : 'submit'
+ pressed : toggle ? false : null,
+ listeners : {}
+ };
+ a.listeners[toggle ? 'toggle' : 'click'] = function() {
+ handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd || id);
+ };
+ children.push(a);
+ return a;
+ }
+
+ var style = {
+ xtype: 'Button',
+ size : 'sm',
+ xns: Roo.bootstrap,
+ glyphicon : 'font',
+ //html : 'submit'
+ menu : {
+ xtype: 'Menu',
+ xns: Roo.bootstrap,
+ items: []
+ }
+ };
+ Roo.each(this.formats, function(f) {
+ style.menu.items.push({
+ xtype :'MenuItem',
+ xns: Roo.bootstrap,
+ html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
+ tagname : f,
+ listeners : {
+ click : function()
+ {
+ editorcore.insertTag(this.tagname);
+ editor.focus();
+ }
+ }
+
+ });
+ });
+ children.push(style);
+
+
+ btn('bold',false,true);
+ btn('italic',false,true);
+ btn('align-left', 'justifyleft',true);
+ btn('align-center', 'justifycenter',true);
+ btn('align-right' , 'justifyright',true);
+ btn('link', false, false, function(btn) {
+ //Roo.log("create link?");
+ var url = prompt(this.createLinkText, this.defaultLinkValue);
+ if(url && url != 'http:/'+'/'){
+ this.editorcore.relayCmd('createlink', url);
+ }
+ }),
+ btn('list','insertunorderedlist',true);
+ btn('pencil', false,true, function(btn){
+ Roo.log(this);
+
+ this.toggleSourceEdit(btn.pressed);
+ });
+ /*
+ var cog = {
+ xtype: 'Button',
+ size : 'sm',
+ xns: Roo.bootstrap,
+ glyphicon : 'cog',
+ //html : 'submit'
+ menu : {
+ xtype: 'Menu',
+ xns: Roo.bootstrap,
+ items: []
+ }
+ };
+
+ cog.menu.items.push({
+ xtype :'MenuItem',
+ xns: Roo.bootstrap,
+ html : Clean styles,
+ tagname : f,
+ listeners : {
+ click : function()
+ {
+ editorcore.insertTag(this.tagname);
+ editor.focus();
+ }
+ }
+
+ });
+ */
+
+
+ this.xtype = 'NavSimplebar';
+
+ for(var i=0;i< children.length;i++) {
+
+ this.buttons.add(this.addxtypeChild(children[i]));
+
+ }
+
+ editor.on('editorevent', this.updateToolbar, this);
+ },
+ onBtnClick : function(id)
+ {
+ this.editorcore.relayCmd(id);
+ this.editorcore.focus();
+ },
+
+ /**
+ * Protected method that will not generally be called directly. It triggers
+ * a toolbar update by reading the markup state of the current selection in the editor.
+ */
+ updateToolbar: function(){
+
+ if(!this.editorcore.activated){
+ this.editor.onFirstFocus(); // is this neeed?
+ return;
+ }
+
+ var btns = this.buttons;
+ var doc = this.editorcore.doc;
+ btns.get('bold').setActive(doc.queryCommandState('bold'));
+ btns.get('italic').setActive(doc.queryCommandState('italic'));
+ //btns.get('underline').setActive(doc.queryCommandState('underline'));
+
+ btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
+ btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
+ btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
+
+ //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
+ btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
+ /*
+
+ var ans = this.editorcore.getAllAncestors();
+ if (this.formatCombo) {
+
+
+ var store = this.formatCombo.store;
+ this.formatCombo.setValue("");
+ for (var i =0; i < ans.length;i++) {
+ if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
+ // select it..
+ this.formatCombo.setValue(ans[i].tagName.toLowerCase());
+ break;
+ }
+ }
+ }
+
+
+
+ // hides menus... - so this cant be on a menu...
+ Roo.bootstrap.MenuMgr.hideAll();
+ */
+ Roo.bootstrap.MenuMgr.hideAll();
+ //this.editorsyncValue();
+ },
+ onFirstFocus: function() {
+ this.buttons.each(function(item){
+ item.enable();
+ });
+ },
+ toggleSourceEdit : function(sourceEditMode){
+
+
+ if(sourceEditMode){
+ Roo.log("disabling buttons");
+ this.buttons.each( function(item){
+ if(item.cmd != 'pencil'){
+ item.disable();
+ }
+ });
+
+ }else{
+ Roo.log("enabling buttons");
+ if(this.editorcore.initialized){
+ this.buttons.each( function(item){
+ item.enable();
+ });
+ }
+
+ }
+ Roo.log("calling toggole on editor");
+ // tell the editor that it's been pressed..
+ this.editor.toggleSourceEdit(sourceEditMode);
+
+ }
+});
+
+
+
+
+
+/**
+ * @class Roo.bootstrap.Table.AbstractSelectionModel
+ * @extends Roo.util.Observable
+ * Abstract base class for grid SelectionModels. It provides the interface that should be
+ * implemented by descendant classes. This class should not be directly instantiated.
+ * @constructor
+ */
+Roo.bootstrap.Table.AbstractSelectionModel = function(){
+ this.locked = false;
+ Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
+};
+
+
+Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable, {
+ /** @ignore Called by the grid automatically. Do not call directly. */
+ init : function(grid){
+ this.grid = grid;
+ this.initEvents();
+ },
+
+ /**
+ * Locks the selections.
+ */
+ lock : function(){
+ this.locked = true;
+ },
+
+ /**
+ * Unlocks the selections.
+ */
+ unlock : function(){
+ this.locked = false;
+ },
+
+ /**
+ * Returns true if the selections are locked.
+ * @return {Boolean}
+ */
+ isLocked : function(){
+ return this.locked;
+ }
+});
+/**
+ * @extends Roo.bootstrap.Table.AbstractSelectionModel
+ * @class Roo.bootstrap.Table.RowSelectionModel
+ * The default SelectionModel used by {@link Roo.bootstrap.Table}.
+ * It supports multiple selections and keyboard selection/navigation.
+ * @constructor
+ * @param {Object} config
+ */
+
+Roo.bootstrap.Table.RowSelectionModel = function(config){
+ Roo.apply(this, config);
+ this.selections = new Roo.util.MixedCollection(false, function(o){
+ return o.id;
+ });
+
+ this.last = false;
+ this.lastActive = false;
+
+ this.addEvents({
+ /**
+ * @event selectionchange
+ * Fires when the selection changes
+ * @param {SelectionModel} this
+ */
+ "selectionchange" : true,
+ /**
+ * @event afterselectionchange
+ * Fires after the selection changes (eg. by key press or clicking)
+ * @param {SelectionModel} this
+ */
+ "afterselectionchange" : true,
+ /**
+ * @event beforerowselect
+ * Fires when a row is selected being selected, return false to cancel.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ * @param {Boolean} keepExisting False if other selections will be cleared
+ */
+ "beforerowselect" : true,
+ /**
+ * @event rowselect
+ * Fires when a row is selected.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ * @param {Roo.data.Record} r The record
+ */
+ "rowselect" : true,
+ /**
+ * @event rowdeselect
+ * Fires when a row is deselected.
+ * @param {SelectionModel} this
+ * @param {Number} rowIndex The selected index
+ */
+ "rowdeselect" : true
+ });
+ Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
+ this.locked = false;
+};
+
+Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel, {
+ /**
+ * @cfg {Boolean} singleSelect
+ * True to allow selection of only one row at a time (defaults to false)
+ */
+ singleSelect : false,
+
+ // private
+ initEvents : function(){
+
+ if(!this.grid.enableDragDrop && !this.grid.enableDrag){
+ this.grid.on("mousedown", this.handleMouseDown, this);
+ }else{ // allow click to work like normal
+ this.grid.on("rowclick", this.handleDragableRowClick, this);
+ }
+
+ this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
+ "up" : function(e){
+ if(!e.shiftKey){
+ this.selectPrevious(e.shiftKey);
+ }else if(this.last !== false && this.lastActive !== false){
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive-1);
+ this.grid.getView().focusRow(this.lastActive);
+ if(last !== false){
+ this.last = last;
+ }
+ }else{
+ this.selectFirstRow();
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ "down" : function(e){
+ if(!e.shiftKey){
+ this.selectNext(e.shiftKey);
+ }else if(this.last !== false && this.lastActive !== false){
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive+1);
+ this.grid.getView().focusRow(this.lastActive);
+ if(last !== false){
+ this.last = last;
+ }
+ }else{
+ this.selectFirstRow();
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ scope: this
+ });
+
+ var view = this.grid.view;
+ view.on("refresh", this.onRefresh, this);
+ view.on("rowupdated", this.onRowUpdated, this);
+ view.on("rowremoved", this.onRemove, this);
+ },
+
+ // private
+ onRefresh : function(){
+ var ds = this.grid.dataSource, i, v = this.grid.view;
+ var s = this.selections;
+ s.each(function(r){
+ if((i = ds.indexOfId(r.id)) != -1){
+ v.onRowSelect(i);
+ }else{
+ s.remove(r);
+ }
+ });
+ },
+
+ // private
+ onRemove : function(v, index, r){
+ this.selections.remove(r);
+ },
+
+ // private
+ onRowUpdated : function(v, index, r){
+ if(this.isSelected(r)){
+ v.onRowSelect(index);
+ }
+ },
+
+ /**
+ * Select records.
+ * @param {Array} records The records to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectRecords : function(records, keepExisting){
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ var ds = this.grid.dataSource;
+ for(var i = 0, len = records.length; i < len; i++){
+ this.selectRow(ds.indexOf(records[i]), true);
+ }
+ },
+
+ /**
+ * Gets the number of selected rows.
+ * @return {Number}
+ */
+ getCount : function(){
+ return this.selections.length;
+ },
+
+ /**
+ * Selects the first row in the grid.
+ */
+ selectFirstRow : function(){
+ this.selectRow(0);
+ },
+
+ /**
+ * Select the last row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectLastRow : function(keepExisting){
+ this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
+ },
+
+ /**
+ * Selects the row immediately following the last selected row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectNext : function(keepExisting){
+ if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){
+ this.selectRow(this.last+1, keepExisting);
+ this.grid.getView().focusRow(this.last);
+ }
+ },
+
+ /**
+ * Selects the row that precedes the last selected row.
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectPrevious : function(keepExisting){
+ if(this.last){
+ this.selectRow(this.last-1, keepExisting);
+ this.grid.getView().focusRow(this.last);
+ }
+ },
+
+ /**
+ * Returns the selected records
+ * @return {Array} Array of selected records
+ */
+ getSelections : function(){
+ return [].concat(this.selections.items);
+ },
+
+ /**
+ * Returns the first selected record.
+ * @return {Record}
+ */
+ getSelected : function(){
+ return this.selections.itemAt(0);
+ },
+
+
+ /**
+ * Clears all selections.
+ */
+ clearSelections : function(fast){
+ if(this.locked) return;
+ if(fast !== true){
+ var ds = this.grid.dataSource;
+ var s = this.selections;
+ s.each(function(r){
+ this.deselectRow(ds.indexOfId(r.id));
+ }, this);
+ s.clear();
+ }else{
+ this.selections.clear();
+ }
+ this.last = false;
+ },
+
+
+ /**
+ * Selects all rows.
+ */
+ selectAll : function(){
+ if(this.locked) return;
+ this.selections.clear();
+ for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
+ this.selectRow(i, true);
+ }
+ },
+
+ /**
+ * Returns True if there is a selection.
+ * @return {Boolean}
+ */
+ hasSelection : function(){
+ return this.selections.length > 0;
+ },
+
+ /**
+ * Returns True if the specified row is selected.
+ * @param {Number/Record} record The record or index of the record to check
+ * @return {Boolean}
+ */
+ isSelected : function(index){
+ var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index;
+ return (r && this.selections.key(r.id) ? true : false);
+ },
+
+ /**
+ * Returns True if the specified record id is selected.
+ * @param {String} id The id of record to check
+ * @return {Boolean}
+ */
+ isIdSelected : function(id){
+ return (this.selections.key(id) ? true : false);
+ },
+
+ // private
+ handleMouseDown : function(e, t){
+ var view = this.grid.getView(), rowIndex;
+ if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){
+ return;
+ };
+ if(e.shiftKey && this.last !== false){
+ var last = this.last;
+ this.selectRange(last, rowIndex, e.ctrlKey);
+ this.last = last; // reset the last
+ view.focusRow(rowIndex);
+ }else{
+ var isSelected = this.isSelected(rowIndex);
+ if(e.button !== 0 && isSelected){
+ view.focusRow(rowIndex);
+ }else if(e.ctrlKey && isSelected){
+ this.deselectRow(rowIndex);
+ }else if(!isSelected){
+ this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
+ view.focusRow(rowIndex);
+ }
+ }
+ this.fireEvent("afterselectionchange", this);
+ },
+ // private
+ handleDragableRowClick : function(grid, rowIndex, e)
+ {
+ if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
+ this.selectRow(rowIndex, false);
+ grid.view.focusRow(rowIndex);
+ this.fireEvent("afterselectionchange", this);
+ }
+ },
+
+ /**
+ * Selects multiple rows.
+ * @param {Array} rows Array of the indexes of the row to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectRows : function(rows, keepExisting){
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ for(var i = 0, len = rows.length; i < len; i++){
+ this.selectRow(rows[i], true);
+ }
+ },
+
+ /**
+ * Selects a range of rows. All rows in between startRow and endRow are also selected.
+ * @param {Number} startRow The index of the first row in the range
+ * @param {Number} endRow The index of the last row in the range
+ * @param {Boolean} keepExisting (optional) True to retain existing selections
+ */
+ selectRange : function(startRow, endRow, keepExisting){
+ if(this.locked) return;
+ if(!keepExisting){
+ this.clearSelections();
+ }
+ if(startRow <= endRow){
+ for(var i = startRow; i <= endRow; i++){
+ this.selectRow(i, true);
+ }
+ }else{
+ for(var i = startRow; i >= endRow; i--){
+ this.selectRow(i, true);
+ }
+ }
+ },
+
+ /**
+ * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
+ * @param {Number} startRow The index of the first row in the range
+ * @param {Number} endRow The index of the last row in the range
+ */
+ deselectRange : function(startRow, endRow, preventViewNotify){
+ if(this.locked) return;
+ for(var i = startRow; i <= endRow; i++){
+ this.deselectRow(i, preventViewNotify);
+ }
+ },
+
+ /**
+ * Selects a row.
+ * @param {Number} row The index of the row to select
+ * @param {Boolean} keepExisting (optional) True to keep existing selections
+ */
+ selectRow : function(index, keepExisting, preventViewNotify){
+ if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
+ if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
+ if(!keepExisting || this.singleSelect){
+ this.clearSelections();
+ }
+ var r = this.grid.dataSource.getAt(index);
+ this.selections.add(r);
+ this.last = this.lastActive = index;
+ if(!preventViewNotify){
+ this.grid.getView().onRowSelect(index);
+ }
+ this.fireEvent("rowselect", this, index, r);
+ this.fireEvent("selectionchange", this);
+ }
+ },
+
+ /**
+ * Deselects a row.
+ * @param {Number} row The index of the row to deselect
+ */
+ deselectRow : function(index, preventViewNotify){
+ if(this.locked) return;
+ if(this.last == index){
+ this.last = false;
+ }
+ if(this.lastActive == index){
+ this.lastActive = false;
+ }
+ var r = this.grid.dataSource.getAt(index);
+ this.selections.remove(r);
+ if(!preventViewNotify){
+ this.grid.getView().onRowDeselect(index);
+ }
+ this.fireEvent("rowdeselect", this, index);
+ this.fireEvent("selectionchange", this);
+ },
+
+ // private
+ restoreLast : function(){
+ if(this._last){
+ this.last = this._last;
+ }
+ },
+
+ // private
+ acceptsNav : function(row, col, cm){
+ return !cm.isHidden(col) && cm.isCellEditable(col, row);
+ },
+
+ // private
+ onEditorKey : function(field, e){
+ var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
+ if(k == e.TAB){
+ e.stopEvent();
+ ed.completeEdit();
+ if(e.shiftKey){
+ newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
+ }else{
+ newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
+ }
+ }else if(k == e.ENTER && !e.ctrlKey){
+ e.stopEvent();
+ ed.completeEdit();
+ if(e.shiftKey){
+ newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
+ }else{
+ newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
+ }
+ }else if(k == e.ESC){
+ ed.cancelEdit();
+ }
+ if(newCell){
+ g.startEditing(newCell[0], newCell[1]);
+ }
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.bootstrap.PagingToolbar
+ * @extends Roo.bootstrap.NavSimplebar
+ * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @constructor
+ * Create a new PagingToolbar
+ * @param {Object} config The config object
+ * @param {Roo.data.Store} store
+ */
+Roo.bootstrap.PagingToolbar = function(config)
+{
+ // old args format still supported... - xtype is prefered..
+ // created from xtype...
+
+ var ds = config.dataSource;
+
+ Roo.log(ds);
+ Roo.log(this.store);
- onFocus : Roo.emptyFn,
- iframePad:3,
- hideMode:'offsets',
+ if (this.store && !ds) {
+ Roo.log('run??');
+ this.store= Roo.factory(this.store, Roo.data);
+ ds = this.store;
+ ds.xmodule = this.xmodule || false;
+ }
+ this.toolbarItems = [];
+ if (config.items) {
+ this.toolbarItems = config.items;
+// config.items = [];
+ }
- tbContainer : false,
+ Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
+ this.ds = ds;
+ this.cursor = 0;
+ if (ds) {
+ this.bind(ds);
+ }
+ Roo.log('ds??');
+ Roo.log(this.ds);
+ this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
- toolbarContainer :function() {
- return this.wrap.select('.x-html-editor-tb',true).first();
- },
+};
+Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
/**
- * Protected method that will not generally be called directly. It
- * is called when the editor creates its toolbar. Override this method if you need to
- * add custom toolbar buttons.
- * @param {HtmlEditor} editor
+ * @cfg {Roo.data.Store} dataSource
+ * The underlying data store providing the paged data
*/
- createToolbar : function(){
-
- Roo.log("create toolbars");
-
- this.toolbars = [ new Roo.bootstrap.htmleditor.ToolbarStandard({editor: this} ) ];
- this.toolbars[0].render(this.toolbarContainer());
-
- return;
-
-// if (!editor.toolbars || !editor.toolbars.length) {
-// editor.toolbars = [ new Roo.bootstrap.HtmlEditor.ToolbarStandard() ]; // can be empty?
-// }
-//
-// for (var i =0 ; i < editor.toolbars.length;i++) {
-// editor.toolbars[i] = Roo.factory(
-// typeof(editor.toolbars[i]) == 'string' ?
-// { xtype: editor.toolbars[i]} : editor.toolbars[i],
-// Roo.bootstrap.HtmlEditor);
-// editor.toolbars[i].init(editor);
-// }
- },
+ /**
+ * @cfg {String/HTMLElement/Element} container
+ * container The id or element that will contain the toolbar
+ */
+ /**
+ * @cfg {Boolean} displayInfo
+ * True to display the displayMsg (defaults to false)
+ */
+ /**
+ * @cfg {Number} pageSize
+ * The number of records to display per page (defaults to 20)
+ */
+ pageSize: 20,
+ /**
+ * @cfg {String} displayMsg
+ * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
+ */
+ displayMsg : 'Displaying {0} - {1} of {2}',
+ /**
+ * @cfg {String} emptyMsg
+ * The message to display when no records are found (defaults to "No data to display")
+ */
+ emptyMsg : 'No data to display',
+ /**
+ * Customizable piece of the default paging text (defaults to "Page")
+ * @type String
+ */
+ beforePageText : "Page",
+ /**
+ * Customizable piece of the default paging text (defaults to "of %0")
+ * @type String
+ */
+ afterPageText : "of {0}",
+ /**
+ * Customizable piece of the default paging text (defaults to "First Page")
+ * @type String
+ */
+ firstText : "First Page",
+ /**
+ * Customizable piece of the default paging text (defaults to "Previous Page")
+ * @type String
+ */
+ prevText : "Previous Page",
+ /**
+ * Customizable piece of the default paging text (defaults to "Next Page")
+ * @type String
+ */
+ nextText : "Next Page",
+ /**
+ * Customizable piece of the default paging text (defaults to "Last Page")
+ * @type String
+ */
+ lastText : "Last Page",
+ /**
+ * Customizable piece of the default paging text (defaults to "Refresh")
+ * @type String
+ */
+ refreshText : "Refresh",
-
+ buttons : false,
// private
- onRender : function(ct, position)
+ onRender : function(ct, position)
{
- // Roo.log("Call onRender: " + this.xtype);
- var _t = this;
- Roo.bootstrap.HtmlEditor.superclass.onRender.call(this, ct, position);
-
- this.wrap = this.inputEl().wrap({
- cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
- });
+ Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
+ this.navgroup.parentId = this.id;
+ this.navgroup.onRender(this.el, null);
+ // add the buttons to the navgroup
- this.editorcore.onRender(ct, position);
-
- if (this.resizable) {
- this.resizeEl = new Roo.Resizable(this.wrap, {
- pinned : true,
- wrap: true,
- dynamic : true,
- minHeight : this.height,
- height: this.height,
- handles : this.resizable,
- width: this.width,
- listeners : {
- resize : function(r, w, h) {
- _t.onResize(w,h); // -something
- }
- }
- });
-
+ if(this.displayInfo){
+ Roo.log(this.el.select('ul.navbar-nav',true).first());
+ this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
+ this.displayEl = this.el.select('.x-paging-info', true).first();
+// var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
+// this.displayEl = navel.el.select('span',true).first();
}
- this.createToolbar(this);
-
- if(!this.width && this.resizable){
- this.setSize(this.wrap.getSize());
- }
- if (this.resizeEl) {
- this.resizeEl.resizeTo.defer(100, this.resizeEl,[ this.width,this.height ] );
- // should trigger onReize..
+ var _this = this;
+
+ if(this.buttons){
+ Roo.each(_this.buttons, function(e){
+ Roo.factory(e).onRender(_this.el, null);
+ });
}
+
+ Roo.each(_this.toolbarItems, function(e) {
+ _this.navgroup.addItem(e);
+ });
- },
-
- // private
- onResize : function(w, h)
- {
- Roo.log('resize: ' +w + ',' + h );
- Roo.bootstrap.HtmlEditor.superclass.onResize.apply(this, arguments);
- var ew = false;
- var eh = false;
- if(this.inputEl() ){
- if(typeof w == 'number'){
- var aw = w - this.wrap.getFrameWidth('lr');
- this.inputEl().setWidth(this.adjustWidth('textarea', aw));
- ew = aw;
- }
- if(typeof h == 'number'){
- var tbh = -11; // fixme it needs to tool bar size!
- for (var i =0; i < this.toolbars.length;i++) {
- // fixme - ask toolbars for heights?
- tbh += this.toolbars[i].el.getHeight();
- //if (this.toolbars[i].footer) {
- // tbh += this.toolbars[i].footer.el.getHeight();
- //}
- }
-
-
-
-
-
- var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
- ah -= 5; // knock a few pixes off for look..
- this.inputEl().setHeight(this.adjustWidth('textarea', ah));
- var eh = ah;
- }
- }
- Roo.log('onResize:' + [w,h,ew,eh].join(',') );
- this.editorcore.onResize(ew,eh);
+ this.first = this.navgroup.addItem({
+ tooltip: this.firstText,
+ cls: "prev",
+ icon : 'fa fa-backward',
+ disabled: true,
+ preventDefault: true,
+ listeners : { click : this.onClick.createDelegate(this, ["first"]) }
+ });
+
+ this.prev = this.navgroup.addItem({
+ tooltip: this.prevText,
+ cls: "prev",
+ icon : 'fa fa-step-backward',
+ disabled: true,
+ preventDefault: true,
+ listeners : { click : this.onClick.createDelegate(this, ["prev"]) }
+ });
+ //this.addSeparator();
- },
-
- /**
- * Toggles the editor between standard and source edit mode.
- * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
- */
- toggleSourceEdit : function(sourceEditMode)
- {
- this.editorcore.toggleSourceEdit(sourceEditMode);
- if(this.editorcore.sourceEditMode){
- Roo.log('editor - showing textarea');
-
-// Roo.log('in');
-// Roo.log(this.syncValue());
- this.syncValue();
- this.inputEl().removeClass(['hide', 'x-hidden']);
- this.inputEl().dom.removeAttribute('tabIndex');
- this.inputEl().focus();
- }else{
- Roo.log('editor - hiding textarea');
-// Roo.log('out')
-// Roo.log(this.pushValue());
- this.pushValue();
+ var field = this.navgroup.addItem( {
+ tagtype : 'span',
+ cls : 'x-paging-position',
- this.inputEl().addClass(['hide', 'x-hidden']);
- this.inputEl().dom.setAttribute('tabIndex', -1);
- //this.deferFocus();
- }
-
- if(this.resizable){
- this.setSize(this.wrap.getSize());
- }
+ html : this.beforePageText +
+ '<input type="text" size="3" value="1" class="x-grid-page-number">' +
+ '<span class="x-paging-after">' + String.format(this.afterPageText, 1) + '</span>'
+ } ); //?? escaped?
+
+ this.field = field.el.select('input', true).first();
+ this.field.on("keydown", this.onPagingKeydown, this);
+ this.field.on("focus", function(){this.dom.select();});
+
+
+ this.afterTextEl = field.el.select('.x-paging-after',true).first();
+ //this.field.setHeight(18);
+ //this.addSeparator();
+ this.next = this.navgroup.addItem({
+ tooltip: this.nextText,
+ cls: "next",
+ html : ' <i class="fa fa-step-forward">',
+ disabled: true,
+ preventDefault: true,
+ listeners : { click : this.onClick.createDelegate(this, ["next"]) }
+ });
+ this.last = this.navgroup.addItem({
+ tooltip: this.lastText,
+ icon : 'fa fa-forward',
+ cls: "next",
+ disabled: true,
+ preventDefault: true,
+ listeners : { click : this.onClick.createDelegate(this, ["last"]) }
+ });
+ //this.addSeparator();
+ this.loading = this.navgroup.addItem({
+ tooltip: this.refreshText,
+ icon: 'fa fa-refresh',
+ preventDefault: true,
+ listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
+ });
- this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
- },
-
- // private (for BoxComponent)
- adjustSize : Roo.BoxComponent.prototype.adjustSize,
-
- // private (for BoxComponent)
- getResizeEl : function(){
- return this.wrap;
- },
-
- // private (for BoxComponent)
- getPositionEl : function(){
- return this.wrap;
},
// private
- initEvents : function(){
- this.originalValue = this.getValue();
+ updateInfo : function(){
+ if(this.displayEl){
+ var count = (typeof(this.getCount) == 'undefined') ? this.ds.getCount() : this.getCount();
+ var msg = count == 0 ?
+ this.emptyMsg :
+ String.format(
+ this.displayMsg,
+ this.cursor+1, this.cursor+count, this.ds.getTotalCount()
+ );
+ this.displayEl.update(msg);
+ }
},
-// /**
-// * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-// * @method
-// */
-// markInvalid : Roo.emptyFn,
-// /**
-// * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-// * @method
-// */
-// clearInvalid : Roo.emptyFn,
-
- setValue : function(v){
- Roo.bootstrap.HtmlEditor.superclass.setValue.call(this, v);
- this.editorcore.pushValue();
+ // private
+ onLoad : function(ds, r, o){
+ this.cursor = o.params ? o.params.start : 0;
+ var d = this.getPageData(),
+ ap = d.activePage,
+ ps = d.pages;
+
+ this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
+ this.field.dom.value = ap;
+ this.first.setDisabled(ap == 1);
+ this.prev.setDisabled(ap == 1);
+ this.next.setDisabled(ap == ps);
+ this.last.setDisabled(ap == ps);
+ this.loading.enable();
+ this.updateInfo();
},
-
// private
- deferFocus : function(){
- this.focus.defer(10, this);
+ getPageData : function(){
+ var total = this.ds.getTotalCount();
+ return {
+ total : total,
+ activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
+ pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
+ };
},
- // doc'ed in Field
- focus : function(){
- this.editorcore.focus();
-
+ // private
+ onLoadError : function(){
+ this.loading.enable();
},
-
// private
- onDestroy : function(){
-
-
-
- if(this.rendered){
-
- for (var i =0; i < this.toolbars.length;i++) {
- // fixme - ask toolbars for heights?
- this.toolbars[i].onDestroy();
+ onPagingKeydown : function(e){
+ var k = e.getKey();
+ var d = this.getPageData();
+ if(k == e.RETURN){
+ var v = this.field.dom.value, pageNum;
+ if(!v || isNaN(pageNum = parseInt(v, 10))){
+ this.field.dom.value = d.activePage;
+ return;
}
-
- this.wrap.dom.innerHTML = '';
- this.wrap.remove();
+ pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
+ this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+ e.stopEvent();
+ }
+ else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
+ {
+ var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
+ this.field.dom.value = pageNum;
+ this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
+ e.stopEvent();
+ }
+ else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+ {
+ var v = this.field.dom.value, pageNum;
+ var increment = (e.shiftKey) ? 10 : 1;
+ if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
+ increment *= -1;
+ if(!v || isNaN(pageNum = parseInt(v, 10))) {
+ this.field.dom.value = d.activePage;
+ return;
+ }
+ else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
+ {
+ this.field.dom.value = parseInt(v, 10) + increment;
+ pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
+ this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
+ }
+ e.stopEvent();
}
},
// private
- onFirstFocus : function(){
- //Roo.log("onFirstFocus");
- this.editorcore.onFirstFocus();
- for (var i =0; i < this.toolbars.length;i++) {
- this.toolbars[i].onFirstFocus();
+ beforeLoad : function(){
+ if(this.loading){
+ this.loading.disable();
}
-
},
-
- // private
- syncValue : function()
- {
- this.editorcore.syncValue();
- },
-
- pushValue : function()
- {
- this.editorcore.pushValue();
- }
-
-
- // hide stuff that is not compatible
- /**
- * @event blur
- * @hide
- */
- /**
- * @event change
- * @hide
- */
- /**
- * @event focus
- * @hide
- */
- /**
- * @event specialkey
- * @hide
- */
- /**
- * @cfg {String} fieldClass @hide
- */
- /**
- * @cfg {String} focusClass @hide
- */
- /**
- * @cfg {String} autoCreate @hide
- */
- /**
- * @cfg {String} inputType @hide
- */
- /**
- * @cfg {String} invalidClass @hide
- */
- /**
- * @cfg {String} invalidText @hide
- */
+
+ // private
+ onClick : function(which){
+
+ var ds = this.ds;
+ if (!ds) {
+ return;
+ }
+
+ switch(which){
+ case "first":
+ ds.load({params:{start: 0, limit: this.pageSize}});
+ break;
+ case "prev":
+ ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
+ break;
+ case "next":
+ ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
+ break;
+ case "last":
+ var total = ds.getTotalCount();
+ var extra = total % this.pageSize;
+ var lastStart = extra ? (total - extra) : total-this.pageSize;
+ ds.load({params:{start: lastStart, limit: this.pageSize}});
+ break;
+ case "refresh":
+ ds.load({params:{start: this.cursor, limit: this.pageSize}});
+ break;
+ }
+ },
+
/**
- * @cfg {String} msgFx @hide
+ * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
+ * @param {Roo.data.Store} store The data store to unbind
*/
+ unbind : function(ds){
+ ds.un("beforeload", this.beforeLoad, this);
+ ds.un("load", this.onLoad, this);
+ ds.un("loadexception", this.onLoadError, this);
+ ds.un("remove", this.updateInfo, this);
+ ds.un("add", this.updateInfo, this);
+ this.ds = undefined;
+ },
+
/**
- * @cfg {String} validateOnBlur @hide
+ * Binds the paging toolbar to the specified {@link Roo.data.Store}
+ * @param {Roo.data.Store} store The data store to bind
*/
-});
-
-
-
-
-
-
-Roo.namespace('Roo.bootstrap.htmleditor');
-/**
- * @class Roo.bootstrap.HtmlEditorToolbar1
- * Basic Toolbar
- *
- * Usage:
- *
- new Roo.bootstrap.HtmlEditor({
- ....
- toolbars : [
- new Roo.bootstrap.HtmlEditorToolbar1({
- disable : { fonts: 1 , format: 1, ..., ... , ...],
- btns : [ .... ]
- })
+ bind : function(ds){
+ ds.on("beforeload", this.beforeLoad, this);
+ ds.on("load", this.onLoad, this);
+ ds.on("loadexception", this.onLoadError, this);
+ ds.on("remove", this.updateInfo, this);
+ ds.on("add", this.updateInfo, this);
+ this.ds = ds;
}
-
- *
- * @cfg {Object} disable List of elements to disable..
- * @cfg {Array} btns List of additional buttons.
+});/*
+ * - LGPL
+ *
+ * element
*
+ */
+
+/**
+ * @class Roo.bootstrap.MessageBar
+ * @extends Roo.bootstrap.Component
+ * Bootstrap MessageBar class
+ * @cfg {String} html contents of the MessageBar
+ * @cfg {String} weight (info | success | warning | danger) default info
+ * @cfg {String} beforeClass insert the bar before the given class
+ * @cfg {Boolean} closable (true | false) default false
+ * @cfg {Boolean} fixed (true | false) default false, fix the bar at the top
*
- * NEEDS Extra CSS?
- * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
+ * @constructor
+ * Create a new Element
+ * @param {Object} config The config object
*/
-
-Roo.bootstrap.htmleditor.ToolbarStandard = function(config)
-{
-
- Roo.apply(this, config);
-
- // default disabled, based on 'good practice'..
- this.disable = this.disable || {};
- Roo.applyIf(this.disable, {
- fontSize : true,
- colors : true,
- specialElements : true
- });
- Roo.bootstrap.htmleditor.ToolbarStandard.superclass.constructor.call(this, config);
-
- this.editor = config.editor;
- this.editorcore = config.editor.editorcore;
-
- this.buttons = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
-
- //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
- // dont call parent... till later.
-}
-Roo.extend(Roo.bootstrap.htmleditor.ToolbarStandard, Roo.bootstrap.NavSimplebar, {
-
- bar : true,
-
- editor : false,
- editorcore : false,
-
+
+Roo.bootstrap.MessageBar = function(config){
+ Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component, {
- formats : [
- "p" ,
- "h1","h2","h3","h4","h5","h6",
- "pre", "code",
- "abbr", "acronym", "address", "cite", "samp", "var",
- 'div','span'
- ],
+ html: '',
+ weight: 'info',
+ closable: false,
+ fixed: false,
+ beforeClass: 'bootstrap-sticky-wrap',
- onRender : function(ct, position)
- {
- // Roo.log("Call onRender: " + this.xtype);
-
- Roo.bootstrap.htmleditor.ToolbarStandard.superclass.onRender.call(this, ct, position);
- Roo.log(this.el);
- this.el.dom.style.marginBottom = '0';
- var _this = this;
- var editorcore = this.editorcore;
- var editor= this.editor;
-
- var children = [];
- var btn = function(id,cmd , toggle, handler){
-
- var event = toggle ? 'toggle' : 'click';
-
- var a = {
- size : 'sm',
- xtype: 'Button',
- xns: Roo.bootstrap,
- glyphicon : id,
- cmd : id || cmd,
- enableToggle:toggle !== false,
- //html : 'submit'
- pressed : toggle ? false : null,
- listeners : {}
- }
- a.listeners[toggle ? 'toggle' : 'click'] = function() {
- handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd || id);
- }
- children.push(a);
- return a;
- }
-
- var style = {
- xtype: 'Button',
- size : 'sm',
- xns: Roo.bootstrap,
- glyphicon : 'font',
- //html : 'submit'
- menu : {
- xtype: 'Menu',
- xns: Roo.bootstrap,
- items: []
- }
- };
- Roo.each(this.formats, function(f) {
- style.menu.items.push({
- xtype :'MenuItem',
- xns: Roo.bootstrap,
- html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
- tagname : f,
- listeners : {
- click : function()
- {
- editorcore.insertTag(this.tagname);
- editor.focus();
- }
- }
-
- });
- });
- children.push(style);
-
-
- btn('bold',false,true);
- btn('italic',false,true);
- btn('align-left', 'justifyleft',true);
- btn('align-center', 'justifycenter',true);
- btn('align-right' , 'justifyright',true);
- btn('link', false, false, function(btn) {
- //Roo.log("create link?");
- var url = prompt(this.createLinkText, this.defaultLinkValue);
- if(url && url != 'http:/'+'/'){
- this.editorcore.relayCmd('createlink', url);
- }
- }),
- btn('list','insertunorderedlist',true);
- btn('pencil', false,true, function(btn){
- Roo.log(this);
-
- this.toggleSourceEdit(btn.pressed);
- });
- /*
- var cog = {
- xtype: 'Button',
- size : 'sm',
- xns: Roo.bootstrap,
- glyphicon : 'cog',
- //html : 'submit'
- menu : {
- xtype: 'Menu',
- xns: Roo.bootstrap,
- items: []
- }
- };
+ getAutoCreate : function(){
- cog.menu.items.push({
- xtype :'MenuItem',
- xns: Roo.bootstrap,
- html : Clean styles,
- tagname : f,
- listeners : {
- click : function()
+ var cfg = {
+ tag: 'div',
+ cls: 'alert alert-dismissable alert-' + this.weight,
+ cn: [
{
- editorcore.insertTag(this.tagname);
- editor.focus();
+ tag: 'span',
+ cls: 'message',
+ html: this.html || ''
}
- }
-
- });
- */
+ ]
+ }
-
- this.xtype = 'NavSimplebar';
+ if(this.fixed){
+ cfg.cls += ' alert-messages-fixed';
+ }
- for(var i=0;i< children.length;i++) {
+ if(this.closable){
+ cfg.cn.push({
+ tag: 'button',
+ cls: 'close',
+ html: 'x'
+ });
+ }
+
+ return cfg;
+ },
+
+ onRender : function(ct, position)
+ {
+ Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
+
+ if(!this.el){
+ var cfg = Roo.apply({}, this.getAutoCreate());
+ cfg.id = Roo.id();
- this.buttons.add(this.addxtypeChild(children[i]));
+ if (this.cls) {
+ cfg.cls += ' ' + this.cls;
+ }
+ if (this.style) {
+ cfg.style = this.style;
+ }
+ this.el = Roo.get(document.body).createChild(cfg, Roo.select('.'+this.beforeClass, true).first());
+ this.el.setVisibilityMode(Roo.Element.DISPLAY);
}
- editor.on('editorevent', this.updateToolbar, this);
+ this.el.select('>button.close').on('click', this.hide, this);
+
},
- onBtnClick : function(id)
+
+ show : function()
{
- this.editorcore.relayCmd(id);
- this.editorcore.focus();
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.el.show();
+
+ this.fireEvent('show', this);
+
},
- /**
- * Protected method that will not generally be called directly. It triggers
- * a toolbar update by reading the markup state of the current selection in the editor.
- */
- updateToolbar: function(){
+ hide : function()
+ {
+ if (!this.rendered) {
+ this.render();
+ }
+
+ this.el.hide();
+
+ this.fireEvent('hide', this);
+ },
+
+ update : function()
+ {
+// var e = this.el.dom.firstChild;
+//
+// if(this.closable){
+// e = e.nextSibling;
+// }
+//
+// e.data = this.html || '';
+
+ this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
+ }
+
+});
+
+
+
+ /*
+ * - LGPL
+ *
+ * Graph
+ *
+ */
+
+
+/**
+ * @class Roo.bootstrap.Graph
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Graph class
+> Prameters
+ -sm {number} sm 4
+ -md {number} md 5
+ @cfg {String} graphtype bar | vbar | pie
+ @cfg {number} g_x coodinator | centre x (pie)
+ @cfg {number} g_y coodinator | centre y (pie)
+ @cfg {number} g_r radius (pie)
+ @cfg {number} g_height height of the chart (respected by all elements in the set)
+ @cfg {number} g_width width of the chart (respected by all elements in the set)
+ @cfg {Object} title The title of the chart
+
+ -{Array} values
+ -opts (object) options for the chart
+ o {
+ o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
+ o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
+ o vgutter (number)
+ o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
+ o stacked (boolean) whether or not to tread values as in a stacked bar chart
+ o to
+ o stretch (boolean)
+ o }
+ -opts (object) options for the pie
+ o{
+ o cut
+ o startAngle (number)
+ o endAngle (number)
+ }
+ *
+ * @constructor
+ * Create a new Input
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.Graph = function(config){
+ Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+
+ this.addEvents({
+ // img events
+ /**
+ * @event click
+ * The img click event for the img.
+ * @param {Roo.EventObject} e
+ */
+ "click" : true
+ });
+};
+
+Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component, {
+
+ sm: 4,
+ md: 5,
+ graphtype: 'bar',
+ g_height: 250,
+ g_width: 400,
+ g_x: 50,
+ g_y: 50,
+ g_r: 30,
+ opts:{
+ //g_colors: this.colors,
+ g_type: 'soft',
+ g_gutter: '20%'
+
+ },
+ title : false,
+
+ getAutoCreate : function(){
+
+ var cfg = {
+ tag: 'div',
+ html : null
+ }
+
+
+ return cfg;
+ },
+
+ onRender : function(ct,position){
+ Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
+ this.raphael = Raphael(this.el.dom);
+
+ // data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+ // data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+ // data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
+ // txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
+ /*
+ r.text(160, 10, "Single Series Chart").attr(txtattr);
+ r.text(480, 10, "Multiline Series Chart").attr(txtattr);
+ r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
+ r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
+
+ r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
+ r.barchart(330, 10, 300, 220, data1);
+ r.barchart(10, 250, 300, 220, data2, {stacked: true});
+ r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
+ */
+
+ // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+ // r.barchart(30, 30, 560, 250, xdata, {
+ // labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
+ // axis : "0 0 1 1",
+ // axisxlabels : xdata
+ // //yvalues : cols,
+
+ // });
+// var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
+//
+// this.load(null,xdata,{
+// axis : "0 0 1 1",
+// axisxlabels : xdata
+// });
+
+ },
+
+ load : function(graphtype,xdata,opts){
+ this.raphael.clear();
+ if(!graphtype) {
+ graphtype = this.graphtype;
+ }
+ if(!opts){
+ opts = this.opts;
+ }
+ var r = this.raphael,
+ fin = function () {
+ this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
+ },
+ fout = function () {
+ this.flag.animate({opacity: 0}, 300, function () {this.remove();});
+ },
+ pfin = function() {
+ this.sector.stop();
+ this.sector.scale(1.1, 1.1, this.cx, this.cy);
+
+ if (this.label) {
+ this.label[0].stop();
+ this.label[0].attr({ r: 7.5 });
+ this.label[1].attr({ "font-weight": 800 });
+ }
+ },
+ pfout = function() {
+ this.sector.animate({ transform: 's1 1 ' + this.cx + ' ' + this.cy }, 500, "bounce");
+
+ if (this.label) {
+ this.label[0].animate({ r: 5 }, 500, "bounce");
+ this.label[1].attr({ "font-weight": 400 });
+ }
+ };
+
+ switch(graphtype){
+ case 'bar':
+ this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
+ break;
+ case 'hbar':
+ this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
+ break;
+ case 'pie':
+// opts = { legend: ["%% - Enterprise Users", "% - ddd","Chrome Users"], legendpos: "west",
+// href: ["http://raphaeljs.com", "http://g.raphaeljs.com"]};
+//
+ this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,opts).hover(pfin, pfout);
+
+ break;
- if(!this.editorcore.activated){
- this.editor.onFirstFocus(); // is this neeed?
- return;
}
-
- var btns = this.buttons;
- var doc = this.editorcore.doc;
- btns.get('bold').setActive(doc.queryCommandState('bold'));
- btns.get('italic').setActive(doc.queryCommandState('italic'));
- //btns.get('underline').setActive(doc.queryCommandState('underline'));
-
- btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
- btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
- btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
-
- //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
- btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
- /*
- var ans = this.editorcore.getAllAncestors();
- if (this.formatCombo) {
-
-
- var store = this.formatCombo.store;
- this.formatCombo.setValue("");
- for (var i =0; i < ans.length;i++) {
- if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
- // select it..
- this.formatCombo.setValue(ans[i].tagName.toLowerCase());
- break;
- }
- }
+ if(this.title){
+ this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
}
-
-
- // hides menus... - so this cant be on a menu...
- Roo.bootstrap.MenuMgr.hideAll();
- */
- Roo.bootstrap.MenuMgr.hideAll();
- //this.editorsyncValue();
},
- onFirstFocus: function() {
- this.buttons.each(function(item){
- item.enable();
- });
+
+ setTitle: function(o)
+ {
+ this.title = o;
},
- toggleSourceEdit : function(sourceEditMode){
+
+ initEvents: function() {
-
- if(sourceEditMode){
- Roo.log("disabling buttons");
- this.buttons.each( function(item){
- if(item.cmd != 'pencil'){
- item.disable();
- }
- });
-
- }else{
- Roo.log("enabling buttons");
- if(this.editorcore.initialized){
- this.buttons.each( function(item){
- item.enable();
- });
- }
-
+ if(!this.href){
+ this.el.on('click', this.onClick, this);
}
- Roo.log("calling toggole on editor");
- // tell the editor that it's been pressed..
- this.editor.toggleSourceEdit(sourceEditMode);
-
+ },
+
+ onClick : function(e)
+ {
+ Roo.log('img onclick');
+ this.fireEvent('click', this, e);
}
+
});
-
-
-
+
+/*
+ * - LGPL
+ *
+ * numberBox
+ *
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
/**
- * @class Roo.bootstrap.Table.AbstractSelectionModel
- * @extends Roo.util.Observable
- * Abstract base class for grid SelectionModels. It provides the interface that should be
- * implemented by descendant classes. This class should not be directly instantiated.
+ * @class Roo.bootstrap.dash.NumberBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap NumberBox class
+ * @cfg {String} headline Box headline
+ * @cfg {String} content Box content
+ * @cfg {String} icon Box icon
+ * @cfg {String} footer Footer text
+ * @cfg {String} fhref Footer href
+ *
* @constructor
+ * Create a new NumberBox
+ * @param {Object} config The config object
*/
-Roo.bootstrap.Table.AbstractSelectionModel = function(){
- this.locked = false;
- Roo.bootstrap.Table.AbstractSelectionModel.superclass.constructor.call(this);
+
+
+Roo.bootstrap.dash.NumberBox = function(config){
+ Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+
};
+Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component, {
+
+ headline : '',
+ content : '',
+ icon : '',
+ footer : '',
+ fhref : '',
+ ficon : '',
+
+ getAutoCreate : function(){
+
+ var cfg = {
+ tag : 'div',
+ cls : 'small-box ',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'inner',
+ cn :[
+ {
+ tag : 'h3',
+ cls : 'roo-headline',
+ html : this.headline
+ },
+ {
+ tag : 'p',
+ cls : 'roo-content',
+ html : this.content
+ }
+ ]
+ }
+ ]
+ }
+
+ if(this.icon){
+ cfg.cn.push({
+ tag : 'div',
+ cls : 'icon',
+ cn :[
+ {
+ tag : 'i',
+ cls : 'ion ' + this.icon
+ }
+ ]
+ });
+ }
+
+ if(this.footer){
+ var footer = {
+ tag : 'a',
+ cls : 'small-box-footer',
+ href : this.fhref || '#',
+ html : this.footer
+ };
+
+ cfg.cn.push(footer);
+
+ }
+
+ return cfg;
+ },
+
+ onRender : function(ct,position){
+ Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
-Roo.extend(Roo.bootstrap.Table.AbstractSelectionModel, Roo.util.Observable, {
- /** @ignore Called by the grid automatically. Do not call directly. */
- init : function(grid){
- this.grid = grid;
- this.initEvents();
+
+
+
},
- /**
- * Locks the selections.
- */
- lock : function(){
- this.locked = true;
+ setHeadline: function (value)
+ {
+ this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+ },
+
+ setFooter: function (value, href)
+ {
+ this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
+
+ if(href){
+ this.el.select('a.small-box-footer',true).first().attr('href', href);
+ }
+
},
- /**
- * Unlocks the selections.
- */
- unlock : function(){
- this.locked = false;
+ setContent: function (value)
+ {
+ this.el.select('.roo-content',true).first().dom.innerHTML = value;
},
- /**
- * Returns true if the selections are locked.
- * @return {Boolean}
- */
- isLocked : function(){
- return this.locked;
+ initEvents: function()
+ {
+
}
+
});
+
+
+/*
+ * - LGPL
+ *
+ * TabBox
+ *
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+
/**
- * @extends Roo.bootstrap.Table.AbstractSelectionModel
- * @class Roo.bootstrap.Table.RowSelectionModel
- * The default SelectionModel used by {@link Roo.bootstrap.Table}.
- * It supports multiple selections and keyboard selection/navigation.
+ * @class Roo.bootstrap.dash.TabBox
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabBox class
+ * @cfg {String} title Title of the TabBox
+ * @cfg {String} icon Icon of the TabBox
+ * @cfg {Boolean} showtabs (true|false) show the tabs default true
+ * @cfg {Boolean} tabScrollable (true|false) tab scrollable when mobile view default false
+ *
* @constructor
- * @param {Object} config
+ * Create a new TabBox
+ * @param {Object} config The config object
*/
-Roo.bootstrap.Table.RowSelectionModel = function(config){
- Roo.apply(this, config);
- this.selections = new Roo.util.MixedCollection(false, function(o){
- return o.id;
- });
-
- this.last = false;
- this.lastActive = false;
+Roo.bootstrap.dash.TabBox = function(config){
+ Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
this.addEvents({
+ // raw events
/**
- * @event selectionchange
- * Fires when the selection changes
- * @param {SelectionModel} this
- */
- "selectionchange" : true,
- /**
- * @event afterselectionchange
- * Fires after the selection changes (eg. by key press or clicking)
- * @param {SelectionModel} this
- */
- "afterselectionchange" : true,
- /**
- * @event beforerowselect
- * Fires when a row is selected being selected, return false to cancel.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- * @param {Boolean} keepExisting False if other selections will be cleared
- */
- "beforerowselect" : true,
- /**
- * @event rowselect
- * Fires when a row is selected.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- * @param {Roo.data.Record} r The record
- */
- "rowselect" : true,
+ * @event addpane
+ * When a pane is added
+ * @param {Roo.bootstrap.dash.TabPane} pane
+ */
+ "addpane" : true,
/**
- * @event rowdeselect
- * Fires when a row is deselected.
- * @param {SelectionModel} this
- * @param {Number} rowIndex The selected index
- */
- "rowdeselect" : true
+ * @event activatepane
+ * When a pane is activated
+ * @param {Roo.bootstrap.dash.TabPane} pane
+ */
+ "activatepane" : true
+
+
});
- Roo.bootstrap.Table.RowSelectionModel.superclass.constructor.call(this);
- this.locked = false;
+
+ this.panes = [];
};
-Roo.extend(Roo.bootstrap.Table.RowSelectionModel, Roo.bootstrap.Table.AbstractSelectionModel, {
- /**
- * @cfg {Boolean} singleSelect
- * True to allow selection of only one row at a time (defaults to false)
- */
- singleSelect : false,
-
- // private
- initEvents : function(){
+Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component, {
- if(!this.grid.enableDragDrop && !this.grid.enableDrag){
- this.grid.on("mousedown", this.handleMouseDown, this);
- }else{ // allow click to work like normal
- this.grid.on("rowclick", this.handleDragableRowClick, this);
+ title : '',
+ icon : false,
+ showtabs : true,
+ tabScrollable : false,
+
+ getChildContainer : function()
+ {
+ return this.el.select('.tab-content', true).first();
+ },
+
+ getAutoCreate : function(){
+
+ var header = {
+ tag: 'li',
+ cls: 'pull-left header',
+ html: this.title,
+ cn : []
+ };
+
+ if(this.icon){
+ header.cn.push({
+ tag: 'i',
+ cls: 'fa ' + this.icon
+ });
}
-
- this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
- "up" : function(e){
- if(!e.shiftKey){
- this.selectPrevious(e.shiftKey);
- }else if(this.last !== false && this.lastActive !== false){
- var last = this.last;
- this.selectRange(this.last, this.lastActive-1);
- this.grid.getView().focusRow(this.lastActive);
- if(last !== false){
- this.last = last;
- }
- }else{
- this.selectFirstRow();
- }
- this.fireEvent("afterselectionchange", this);
- },
- "down" : function(e){
- if(!e.shiftKey){
- this.selectNext(e.shiftKey);
- }else if(this.last !== false && this.lastActive !== false){
- var last = this.last;
- this.selectRange(this.last, this.lastActive+1);
- this.grid.getView().focusRow(this.lastActive);
- if(last !== false){
- this.last = last;
+
+ var h = {
+ tag: 'ul',
+ cls: 'nav nav-tabs pull-right',
+ cn: [
+ header
+ ]
+ };
+
+ if(this.tabScrollable){
+ h = {
+ tag: 'div',
+ cls: 'tab-header',
+ cn: [
+ {
+ tag: 'ul',
+ cls: 'nav nav-tabs pull-right',
+ cn: [
+ header
+ ]
}
- }else{
- this.selectFirstRow();
- }
- this.fireEvent("afterselectionchange", this);
- },
- scope: this
- });
-
- var view = this.grid.view;
- view.on("refresh", this.onRefresh, this);
- view.on("rowupdated", this.onRowUpdated, this);
- view.on("rowremoved", this.onRemove, this);
- },
-
- // private
- onRefresh : function(){
- var ds = this.grid.dataSource, i, v = this.grid.view;
- var s = this.selections;
- s.each(function(r){
- if((i = ds.indexOfId(r.id)) != -1){
- v.onRowSelect(i);
- }else{
- s.remove(r);
+ ]
}
- });
- },
+ }
+
+ var cfg = {
+ tag: 'div',
+ cls: 'nav-tabs-custom',
+ cn: [
+ h,
+ {
+ tag: 'div',
+ cls: 'tab-content no-padding',
+ cn: []
+ }
+ ]
+ }
- // private
- onRemove : function(v, index, r){
- this.selections.remove(r);
+ return cfg;
},
-
- // private
- onRowUpdated : function(v, index, r){
- if(this.isSelected(r)){
- v.onRowSelect(index);
- }
+ initEvents : function()
+ {
+ //Roo.log('add add pane handler');
+ this.on('addpane', this.onAddPane, this);
},
-
- /**
- * Select records.
- * @param {Array} records The records to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
+ /**
+ * Updates the box title
+ * @param {String} html to set the title to.
*/
- selectRecords : function(records, keepExisting){
- if(!keepExisting){
- this.clearSelections();
+ setTitle : function(value)
+ {
+ this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+ },
+ onAddPane : function(pane)
+ {
+ this.panes.push(pane);
+ //Roo.log('addpane');
+ //Roo.log(pane);
+ // tabs are rendere left to right..
+ if(!this.showtabs){
+ return;
}
- var ds = this.grid.dataSource;
- for(var i = 0, len = records.length; i < len; i++){
- this.selectRow(ds.indexOf(records[i]), true);
+
+ var ctr = this.el.select('.nav-tabs', true).first();
+
+
+ var existing = ctr.select('.nav-tab',true);
+ var qty = existing.getCount();;
+
+
+ var tab = ctr.createChild({
+ tag : 'li',
+ cls : 'nav-tab' + (qty ? '' : ' active'),
+ cn : [
+ {
+ tag : 'a',
+ href:'#',
+ html : pane.title
+ }
+ ]
+ }, qty ? existing.first().dom : ctr.select('.header', true).first().dom );
+ pane.tab = tab;
+
+ tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
+ if (!qty) {
+ pane.el.addClass('active');
}
+
+
+ },
+ onTabClick : function(ev,un,ob,pane)
+ {
+ //Roo.log('tab - prev default');
+ ev.preventDefault();
+
+
+ this.el.select('.nav-tabs li.nav-tab', true).removeClass('active');
+ pane.tab.addClass('active');
+ //Roo.log(pane.title);
+ this.getChildContainer().select('.tab-pane',true).removeClass('active');
+ // technically we should have a deactivate event.. but maybe add later.
+ // and it should not de-activate the selected tab...
+ this.fireEvent('activatepane', pane);
+ pane.el.addClass('active');
+ pane.fireEvent('activate');
+
+
},
+
+ getActivePane : function()
+ {
+ var r = false;
+ Roo.each(this.panes, function(p) {
+ if(p.el.hasClass('active')){
+ r = p;
+ return false;
+ }
+
+ return;
+ });
+
+ return r;
+ }
+
+
+});
- /**
- * Gets the number of selected rows.
- * @return {Number}
- */
- getCount : function(){
- return this.selections.length;
- },
+
+/*
+ * - LGPL
+ *
+ * Tab pane
+ *
+ */
+Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+/**
+ * @class Roo.bootstrap.TabPane
+ * @extends Roo.bootstrap.Component
+ * Bootstrap TabPane class
+ * @cfg {Boolean} active (false | true) Default false
+ * @cfg {String} title title of panel
- /**
- * Selects the first row in the grid.
- */
- selectFirstRow : function(){
- this.selectRow(0);
- },
+ *
+ * @constructor
+ * Create a new TabPane
+ * @param {Object} config The config object
+ */
- /**
- * Select the last row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectLastRow : function(keepExisting){
- this.selectRow(this.grid.dataSource.getCount() - 1, keepExisting);
- },
+Roo.bootstrap.dash.TabPane = function(config){
+ Roo.bootstrap.dash.TabPane.superclass.constructor.call(this, config);
+
+ this.addEvents({
+ // raw events
+ /**
+ * @event activate
+ * When a pane is activated
+ * @param {Roo.bootstrap.dash.TabPane} pane
+ */
+ "activate" : true
+
+ });
+};
- /**
- * Selects the row immediately following the last selected row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectNext : function(keepExisting){
- if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){
- this.selectRow(this.last+1, keepExisting);
- this.grid.getView().focusRow(this.last);
+Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component, {
+
+ active : false,
+ title : '',
+
+ // the tabBox that this is attached to.
+ tab : false,
+
+ getAutoCreate : function()
+ {
+ var cfg = {
+ tag: 'div',
+ cls: 'tab-pane'
}
- },
-
- /**
- * Selects the row that precedes the last selected row.
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectPrevious : function(keepExisting){
- if(this.last){
- this.selectRow(this.last-1, keepExisting);
- this.grid.getView().focusRow(this.last);
+
+ if(this.active){
+ cfg.cls += ' active';
}
+
+ return cfg;
},
-
- /**
- * Returns the selected records
- * @return {Array} Array of selected records
- */
- getSelections : function(){
- return [].concat(this.selections.items);
- },
-
- /**
- * Returns the first selected record.
- * @return {Record}
- */
- getSelected : function(){
- return this.selections.itemAt(0);
+ initEvents : function()
+ {
+ //Roo.log('trigger add pane handler');
+ this.parent().fireEvent('addpane', this)
},
-
-
- /**
- * Clears all selections.
+
+ /**
+ * Updates the tab title
+ * @param {String} html to set the title to.
*/
- clearSelections : function(fast){
- if(this.locked) return;
- if(fast !== true){
- var ds = this.grid.dataSource;
- var s = this.selections;
- s.each(function(r){
- this.deselectRow(ds.indexOfId(r.id));
- }, this);
- s.clear();
- }else{
- this.selections.clear();
+ setTitle: function(str)
+ {
+ if (!this.tab) {
+ return;
}
- this.last = false;
- },
+ this.title = str;
+ this.tab.select('a', true).first().dom.innerHTML = str;
+
+ }
+
+
+
+});
+
- /**
- * Selects all rows.
- */
- selectAll : function(){
- if(this.locked) return;
- this.selections.clear();
- for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
- this.selectRow(i, true);
- }
- },
- /**
- * Returns True if there is a selection.
- * @return {Boolean}
- */
- hasSelection : function(){
- return this.selections.length > 0;
- },
+ /*
+ * - LGPL
+ *
+ * menu
+ *
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
- /**
- * Returns True if the specified row is selected.
- * @param {Number/Record} record The record or index of the record to check
- * @return {Boolean}
- */
- isSelected : function(index){
- var r = typeof index == "number" ? this.grid.dataSource.getAt(index) : index;
- return (r && this.selections.key(r.id) ? true : false);
- },
+/**
+ * @class Roo.bootstrap.menu.Menu
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Menu class - container for Menu
+ * @cfg {String} html Text of the menu
+ * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
+ * @cfg {String} icon Font awesome icon
+ * @cfg {String} pos Menu align to (top | bottom) default bottom
+ *
+ *
+ * @constructor
+ * Create a new Menu
+ * @param {Object} config The config object
+ */
- /**
- * Returns True if the specified record id is selected.
- * @param {String} id The id of record to check
- * @return {Boolean}
- */
- isIdSelected : function(id){
- return (this.selections.key(id) ? true : false);
- },
- // private
- handleMouseDown : function(e, t){
- var view = this.grid.getView(), rowIndex;
- if(this.isLocked() || (rowIndex = view.findRowIndex(t)) === false){
- return;
- };
- if(e.shiftKey && this.last !== false){
- var last = this.last;
- this.selectRange(last, rowIndex, e.ctrlKey);
- this.last = last; // reset the last
- view.focusRow(rowIndex);
- }else{
- var isSelected = this.isSelected(rowIndex);
- if(e.button !== 0 && isSelected){
- view.focusRow(rowIndex);
- }else if(e.ctrlKey && isSelected){
- this.deselectRow(rowIndex);
- }else if(!isSelected){
- this.selectRow(rowIndex, e.button === 0 && (e.ctrlKey || e.shiftKey));
- view.focusRow(rowIndex);
- }
- }
- this.fireEvent("afterselectionchange", this);
- },
- // private
- handleDragableRowClick : function(grid, rowIndex, e)
- {
- if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
- this.selectRow(rowIndex, false);
- grid.view.focusRow(rowIndex);
- this.fireEvent("afterselectionchange", this);
- }
- },
+Roo.bootstrap.menu.Menu = function(config){
+ Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
+
+ this.addEvents({
+ /**
+ * @event beforeshow
+ * Fires before this menu is displayed
+ * @param {Roo.bootstrap.menu.Menu} this
+ */
+ beforeshow : true,
+ /**
+ * @event beforehide
+ * Fires before this menu is hidden
+ * @param {Roo.bootstrap.menu.Menu} this
+ */
+ beforehide : true,
+ /**
+ * @event show
+ * Fires after this menu is displayed
+ * @param {Roo.bootstrap.menu.Menu} this
+ */
+ show : true,
+ /**
+ * @event hide
+ * Fires after this menu is hidden
+ * @param {Roo.bootstrap.menu.Menu} this
+ */
+ hide : true,
+ /**
+ * @event click
+ * Fires when this menu is clicked (or when the enter key is pressed while it is active)
+ * @param {Roo.bootstrap.menu.Menu} this
+ * @param {Roo.EventObject} e
+ */
+ click : true
+ });
+
+};
+
+Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component, {
- /**
- * Selects multiple rows.
- * @param {Array} rows Array of the indexes of the row to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectRows : function(rows, keepExisting){
- if(!keepExisting){
- this.clearSelections();
- }
- for(var i = 0, len = rows.length; i < len; i++){
- this.selectRow(rows[i], true);
+ submenu : false,
+ html : '',
+ weight : 'default',
+ icon : false,
+ pos : 'bottom',
+
+
+ getChildContainer : function() {
+ if(this.isSubMenu){
+ return this.el;
}
+
+ return this.el.select('ul.dropdown-menu', true).first();
},
-
- /**
- * Selects a range of rows. All rows in between startRow and endRow are also selected.
- * @param {Number} startRow The index of the first row in the range
- * @param {Number} endRow The index of the last row in the range
- * @param {Boolean} keepExisting (optional) True to retain existing selections
- */
- selectRange : function(startRow, endRow, keepExisting){
- if(this.locked) return;
- if(!keepExisting){
- this.clearSelections();
- }
- if(startRow <= endRow){
- for(var i = startRow; i <= endRow; i++){
- this.selectRow(i, true);
- }
- }else{
- for(var i = startRow; i >= endRow; i--){
- this.selectRow(i, true);
+
+ getAutoCreate : function()
+ {
+ var text = [
+ {
+ tag : 'span',
+ cls : 'roo-menu-text',
+ html : this.html
}
+ ];
+
+ if(this.icon){
+ text.unshift({
+ tag : 'i',
+ cls : 'fa ' + this.icon
+ })
}
- },
-
- /**
- * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
- * @param {Number} startRow The index of the first row in the range
- * @param {Number} endRow The index of the last row in the range
- */
- deselectRange : function(startRow, endRow, preventViewNotify){
- if(this.locked) return;
- for(var i = startRow; i <= endRow; i++){
- this.deselectRow(i, preventViewNotify);
+
+
+ var cfg = {
+ tag : 'div',
+ cls : 'btn-group',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'dropdown-button btn btn-' + this.weight,
+ cn : text
+ },
+ {
+ tag : 'button',
+ cls : 'dropdown-toggle btn btn-' + this.weight,
+ cn : [
+ {
+ tag : 'span',
+ cls : 'caret'
+ }
+ ]
+ },
+ {
+ tag : 'ul',
+ cls : 'dropdown-menu'
+ }
+ ]
+
+ };
+
+ if(this.pos == 'top'){
+ cfg.cls += ' dropup';
}
- },
-
- /**
- * Selects a row.
- * @param {Number} row The index of the row to select
- * @param {Boolean} keepExisting (optional) True to keep existing selections
- */
- selectRow : function(index, keepExisting, preventViewNotify){
- if(this.locked || (index < 0 || index >= this.grid.dataSource.getCount())) return;
- if(this.fireEvent("beforerowselect", this, index, keepExisting) !== false){
- if(!keepExisting || this.singleSelect){
- this.clearSelections();
- }
- var r = this.grid.dataSource.getAt(index);
- this.selections.add(r);
- this.last = this.lastActive = index;
- if(!preventViewNotify){
- this.grid.getView().onRowSelect(index);
+
+ if(this.isSubMenu){
+ cfg = {
+ tag : 'ul',
+ cls : 'dropdown-menu'
}
- this.fireEvent("rowselect", this, index, r);
- this.fireEvent("selectionchange", this);
}
+
+ return cfg;
},
-
- /**
- * Deselects a row.
- * @param {Number} row The index of the row to deselect
- */
- deselectRow : function(index, preventViewNotify){
- if(this.locked) return;
- if(this.last == index){
- this.last = false;
- }
- if(this.lastActive == index){
- this.lastActive = false;
- }
- var r = this.grid.dataSource.getAt(index);
- this.selections.remove(r);
- if(!preventViewNotify){
- this.grid.getView().onRowDeselect(index);
+
+ onRender : function(ct, position)
+ {
+ this.isSubMenu = ct.hasClass('dropdown-submenu');
+
+ Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+ },
+
+ initEvents : function()
+ {
+ if(this.isSubMenu){
+ return;
}
- this.fireEvent("rowdeselect", this, index);
- this.fireEvent("selectionchange", this);
+
+ this.hidden = true;
+
+ this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
+ this.triggerEl.on('click', this.onTriggerPress, this);
+
+ this.buttonEl = this.el.select('button.dropdown-button', true).first();
+ this.buttonEl.on('click', this.onClick, this);
+
},
-
- // private
- restoreLast : function(){
- if(this._last){
- this.last = this._last;
+
+ list : function()
+ {
+ if(this.isSubMenu){
+ return this.el;
}
+
+ return this.el.select('ul.dropdown-menu', true).first();
},
-
- // private
- acceptsNav : function(row, col, cm){
- return !cm.isHidden(col) && cm.isCellEditable(col, row);
+
+ onClick : function(e)
+ {
+ this.fireEvent("click", this, e);
},
-
- // private
- onEditorKey : function(field, e){
- var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
- if(k == e.TAB){
- e.stopEvent();
- ed.completeEdit();
- if(e.shiftKey){
- newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
- }else{
- newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
- }
- }else if(k == e.ENTER && !e.ctrlKey){
- e.stopEvent();
- ed.completeEdit();
- if(e.shiftKey){
- newCell = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
- }else{
- newCell = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
- }
- }else if(k == e.ESC){
- ed.cancelEdit();
- }
- if(newCell){
- g.startEditing(newCell[0], newCell[1]);
+
+ onTriggerPress : function(e)
+ {
+ if (this.isVisible()) {
+ this.hide();
+ } else {
+ this.show();
}
+ },
+
+ isVisible : function(){
+ return !this.hidden;
+ },
+
+ show : function()
+ {
+ this.fireEvent("beforeshow", this);
+
+ this.hidden = false;
+ this.el.addClass('open');
+
+ Roo.get(document).on("mouseup", this.onMouseUp, this);
+
+ this.fireEvent("show", this);
+
+
+ },
+
+ hide : function()
+ {
+ this.fireEvent("beforehide", this);
+
+ this.hidden = true;
+ this.el.removeClass('open');
+
+ Roo.get(document).un("mouseup", this.onMouseUp);
+
+ this.fireEvent("hide", this);
+ },
+
+ onMouseUp : function()
+ {
+ this.hide();
}
-});/*
- * Based on:
- * Ext JS Library 1.1.1
- * Copyright(c) 2006-2007, Ext JS, LLC.
- *
- * Originally Released Under LGPL - original licence link has changed is not relivant.
+
+});
+
+
+ /*
+ * - LGPL
*
- * Fork - LGPL
- * <script type="text/javascript">
+ * menu item
+ *
*/
-
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+
/**
- * @class Roo.bootstrap.PagingToolbar
- * @extends Roo.Row
- * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
+ * @class Roo.bootstrap.menu.Item
+ * @extends Roo.bootstrap.Component
+ * Bootstrap MenuItem class
+ * @cfg {Boolean} submenu (true | false) default false
+ * @cfg {String} html text of the item
+ * @cfg {String} href the link
+ * @cfg {Boolean} disable (true | false) default false
+ * @cfg {Boolean} preventDefault (true | false) default true
+ * @cfg {String} icon Font awesome icon
+ * @cfg {String} pos Submenu align to (left | right) default right
+ *
+ *
* @constructor
- * Create a new PagingToolbar
+ * Create a new Item
* @param {Object} config The config object
*/
-Roo.bootstrap.PagingToolbar = function(config)
-{
- // old args format still supported... - xtype is prefered..
- // created from xtype...
- var ds = config.dataSource;
- this.toolbarItems = [];
- if (config.items) {
- this.toolbarItems = config.items;
-// config.items = [];
- }
-
- Roo.bootstrap.PagingToolbar.superclass.constructor.call(this, config);
- this.ds = ds;
- this.cursor = 0;
- if (ds) {
- this.bind(ds);
- }
-
- this.navgroup = new Roo.bootstrap.NavGroup({ cls: 'pagination' });
-
-};
-Roo.extend(Roo.bootstrap.PagingToolbar, Roo.bootstrap.NavSimplebar, {
- /**
- * @cfg {Roo.data.Store} dataSource
- * The underlying data store providing the paged data
- */
- /**
- * @cfg {String/HTMLElement/Element} container
- * container The id or element that will contain the toolbar
- */
- /**
- * @cfg {Boolean} displayInfo
- * True to display the displayMsg (defaults to false)
- */
- /**
- * @cfg {Number} pageSize
- * The number of records to display per page (defaults to 20)
- */
- pageSize: 20,
- /**
- * @cfg {String} displayMsg
- * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
- */
- displayMsg : 'Displaying {0} - {1} of {2}',
- /**
- * @cfg {String} emptyMsg
- * The message to display when no records are found (defaults to "No data to display")
- */
- emptyMsg : 'No data to display',
- /**
- * Customizable piece of the default paging text (defaults to "Page")
- * @type String
- */
- beforePageText : "Page",
- /**
- * Customizable piece of the default paging text (defaults to "of %0")
- * @type String
- */
- afterPageText : "of {0}",
- /**
- * Customizable piece of the default paging text (defaults to "First Page")
- * @type String
- */
- firstText : "First Page",
- /**
- * Customizable piece of the default paging text (defaults to "Previous Page")
- * @type String
- */
- prevText : "Previous Page",
- /**
- * Customizable piece of the default paging text (defaults to "Next Page")
- * @type String
- */
- nextText : "Next Page",
- /**
- * Customizable piece of the default paging text (defaults to "Last Page")
- * @type String
- */
- lastText : "Last Page",
- /**
- * Customizable piece of the default paging text (defaults to "Refresh")
- * @type String
- */
- refreshText : "Refresh",
- buttons : false,
- // private
- onRender : function(ct, position)
+Roo.bootstrap.menu.Item = function(config){
+ Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
+ this.addEvents({
+ /**
+ * @event mouseover
+ * Fires when the mouse is hovering over this menu
+ * @param {Roo.bootstrap.menu.Item} this
+ * @param {Roo.EventObject} e
+ */
+ mouseover : true,
+ /**
+ * @event mouseout
+ * Fires when the mouse exits this menu
+ * @param {Roo.bootstrap.menu.Item} this
+ * @param {Roo.EventObject} e
+ */
+ mouseout : true,
+ // raw events
+ /**
+ * @event click
+ * The raw click event for the entire grid.
+ * @param {Roo.EventObject} e
+ */
+ click : true
+ });
+};
+
+Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component, {
+
+ submenu : false,
+ href : '',
+ html : '',
+ preventDefault: true,
+ disable : false,
+ icon : false,
+ pos : 'right',
+
+ getAutoCreate : function()
{
- Roo.bootstrap.PagingToolbar.superclass.onRender.call(this, ct, position);
- this.navgroup.parentId = this.id;
- this.navgroup.onRender(this.el, null);
- // add the buttons to the navgroup
-
- if(this.displayInfo){
- Roo.log(this.el.select('ul.navbar-nav',true).first());
- this.el.select('ul.navbar-nav',true).first().createChild({cls:'x-paging-info'});
- this.displayEl = this.el.select('.x-paging-info', true).first();
-// var navel = this.navgroup.addItem( { tagtype : 'span', html : '', cls : 'x-paging-info', preventDefault : true } );
-// this.displayEl = navel.el.select('span',true).first();
- }
-
- var _this = this;
+ var text = [
+ {
+ tag : 'span',
+ cls : 'roo-menu-item-text',
+ html : this.html
+ }
+ ];
- if(this.buttons){
- Roo.each(_this.buttons, function(e){
- Roo.factory(e).onRender(_this.el, null);
- });
+ if(this.icon){
+ text.unshift({
+ tag : 'i',
+ cls : 'fa ' + this.icon
+ })
}
-
- Roo.each(_this.toolbarItems, function(e) {
- _this.navgroup.addItem(e);
- });
-
-
- this.first = this.navgroup.addItem({
- tooltip: this.firstText,
- cls: "prev",
- icon : 'fa fa-backward',
- disabled: true,
- preventDefault: true,
- listeners : { click : this.onClick.createDelegate(this, ["first"]) }
- });
- this.prev = this.navgroup.addItem({
- tooltip: this.prevText,
- cls: "prev",
- icon : 'fa fa-step-backward',
- disabled: true,
- preventDefault: true,
- listeners : { click : this.onClick.createDelegate(this, ["prev"]) }
- });
- //this.addSeparator();
+ var cfg = {
+ tag : 'li',
+ cn : [
+ {
+ tag : 'a',
+ href : this.href || '#',
+ cn : text
+ }
+ ]
+ };
+ if(this.disable){
+ cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
+ }
- var field = this.navgroup.addItem( {
- tagtype : 'span',
- cls : 'x-paging-position',
+ if(this.submenu){
+ cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
- html : this.beforePageText +
- '<input type="text" size="3" value="1" class="x-grid-page-number">' +
- '<span class="x-paging-after">' + String.format(this.afterPageText, 1) + '</span>'
- } ); //?? escaped?
+ if(this.pos == 'left'){
+ cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
+ }
+ }
- this.field = field.el.select('input', true).first();
- this.field.on("keydown", this.onPagingKeydown, this);
- this.field.on("focus", function(){this.dom.select();});
-
+ return cfg;
+ },
- this.afterTextEl = field.el.select('.x-paging-after',true).first();
- //this.field.setHeight(18);
- //this.addSeparator();
- this.next = this.navgroup.addItem({
- tooltip: this.nextText,
- cls: "next",
- html : ' <i class="fa fa-step-forward">',
- disabled: true,
- preventDefault: true,
- listeners : { click : this.onClick.createDelegate(this, ["next"]) }
- });
- this.last = this.navgroup.addItem({
- tooltip: this.lastText,
- icon : 'fa fa-forward',
- cls: "next",
- disabled: true,
- preventDefault: true,
- listeners : { click : this.onClick.createDelegate(this, ["last"]) }
- });
- //this.addSeparator();
- this.loading = this.navgroup.addItem({
- tooltip: this.refreshText,
- icon: 'fa fa-refresh',
- preventDefault: true,
- listeners : { click : this.onClick.createDelegate(this, ["refresh"]) }
- });
-
+ initEvents : function()
+ {
+ this.el.on('mouseover', this.onMouseOver, this);
+ this.el.on('mouseout', this.onMouseOut, this);
+
+ this.el.select('a', true).first().on('click', this.onClick, this);
+
},
-
- // private
- updateInfo : function(){
- if(this.displayEl){
- var count = (typeof(this.getCount) == 'undefined') ? this.ds.getCount() : this.getCount();
- var msg = count == 0 ?
- this.emptyMsg :
- String.format(
- this.displayMsg,
- this.cursor+1, this.cursor+count, this.ds.getTotalCount()
- );
- this.displayEl.update(msg);
+
+ onClick : function(e)
+ {
+ if(this.preventDefault){
+ e.preventDefault();
}
+
+ this.fireEvent("click", this, e);
},
-
- // private
- onLoad : function(ds, r, o){
- this.cursor = o.params ? o.params.start : 0;
- var d = this.getPageData(),
- ap = d.activePage,
- ps = d.pages;
+
+ onMouseOver : function(e)
+ {
+ if(this.submenu && this.pos == 'left'){
+ this.el.select('ul.dropdown-menu', true).first().setLeft(this.el.select('ul.dropdown-menu', true).first().getWidth() * -1);
+ }
- this.afterTextEl.dom.innerHTML = String.format(this.afterPageText, d.pages);
- this.field.dom.value = ap;
- this.first.setDisabled(ap == 1);
- this.prev.setDisabled(ap == 1);
- this.next.setDisabled(ap == ps);
- this.last.setDisabled(ap == ps);
- this.loading.enable();
- this.updateInfo();
+ this.fireEvent("mouseover", this, e);
},
+
+ onMouseOut : function(e)
+ {
+ this.fireEvent("mouseout", this, e);
+ }
+});
- // private
- getPageData : function(){
- var total = this.ds.getTotalCount();
- return {
- total : total,
- activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
- pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
- };
- },
+
- // private
- onLoadError : function(){
- this.loading.enable();
- },
+ /*
+ * - LGPL
+ *
+ * menu separator
+ *
+ */
+Roo.bootstrap.menu = Roo.bootstrap.menu || {};
- // private
- onPagingKeydown : function(e){
- var k = e.getKey();
- var d = this.getPageData();
- if(k == e.RETURN){
- var v = this.field.dom.value, pageNum;
- if(!v || isNaN(pageNum = parseInt(v, 10))){
- this.field.dom.value = d.activePage;
- return;
- }
- pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
- this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
- e.stopEvent();
- }
- else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
- {
- var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
- this.field.dom.value = pageNum;
- this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
- e.stopEvent();
- }
- else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
- {
- var v = this.field.dom.value, pageNum;
- var increment = (e.shiftKey) ? 10 : 1;
- if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
- increment *= -1;
- if(!v || isNaN(pageNum = parseInt(v, 10))) {
- this.field.dom.value = d.activePage;
- return;
- }
- else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
- {
- this.field.dom.value = parseInt(v, 10) + increment;
- pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
- this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
- }
- e.stopEvent();
- }
- },
+/**
+ * @class Roo.bootstrap.menu.Separator
+ * @extends Roo.bootstrap.Component
+ * Bootstrap Separator class
+ *
+ * @constructor
+ * Create a new Separator
+ * @param {Object} config The config object
+ */
- // private
- beforeLoad : function(){
- if(this.loading){
- this.loading.disable();
- }
- },
- // private
- onClick : function(which){
-
- var ds = this.ds;
- if (!ds) {
- return;
- }
+Roo.bootstrap.menu.Separator = function(config){
+ Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component, {
+
+ getAutoCreate : function(){
+ var cfg = {
+ tag : 'li',
+ cls: 'divider'
+ };
- switch(which){
- case "first":
- ds.load({params:{start: 0, limit: this.pageSize}});
- break;
- case "prev":
- ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
- break;
- case "next":
- ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
- break;
- case "last":
- var total = ds.getTotalCount();
- var extra = total % this.pageSize;
- var lastStart = extra ? (total - extra) : total-this.pageSize;
- ds.load({params:{start: lastStart, limit: this.pageSize}});
- break;
- case "refresh":
- ds.load({params:{start: this.cursor, limit: this.pageSize}});
- break;
- }
- },
+ return cfg;
+ }
+
+});
- /**
- * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
- * @param {Roo.data.Store} store The data store to unbind
- */
- unbind : function(ds){
- ds.un("beforeload", this.beforeLoad, this);
- ds.un("load", this.onLoad, this);
- ds.un("loadexception", this.onLoadError, this);
- ds.un("remove", this.updateInfo, this);
- ds.un("add", this.updateInfo, this);
- this.ds = undefined;
- },
+
- /**
- * Binds the paging toolbar to the specified {@link Roo.data.Store}
- * @param {Roo.data.Store} store The data store to bind
- */
- bind : function(ds){
- ds.on("beforeload", this.beforeLoad, this);
- ds.on("load", this.onLoad, this);
- ds.on("loadexception", this.onLoadError, this);
- ds.on("remove", this.updateInfo, this);
- ds.on("add", this.updateInfo, this);
- this.ds = ds;
- }
-});/*
+ /*
* - LGPL
*
- * element
+ * Tooltip
*
*/
/**
- * @class Roo.bootstrap.MessageBar
- * @extends Roo.bootstrap.Component
- * Bootstrap MessageBar class
- * @cfg {String} html contents of the MessageBar
- * @cfg {String} weight (info | success | warning | danger) default info
- * @cfg {String} beforeClass insert the bar before the given class
- * @cfg {Boolean} closable (true | false) default false
- * @cfg {Boolean} fixed (true | false) default false, fix the bar at the top
+ * @class Roo.bootstrap.Tooltip
+ * Bootstrap Tooltip class
+ * This is basic at present - all componets support it by default, however they should add tooltipEl() method
+ * to determine which dom element triggers the tooltip.
+ *
+ * It needs to add support for additional attributes like tooltip-position
*
* @constructor
- * Create a new Element
+ * Create a new Toolti
* @param {Object} config The config object
*/
-Roo.bootstrap.MessageBar = function(config){
- Roo.bootstrap.MessageBar.superclass.constructor.call(this, config);
+Roo.bootstrap.Tooltip = function(config){
+ Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.MessageBar, Roo.bootstrap.Component, {
+Roo.apply(Roo.bootstrap.Tooltip, {
+ /**
+ * @function init initialize tooltip monitoring.
+ * @static
+ */
+ currentEl : false,
+ currentTip : false,
+ currentRegion : false,
- html: '',
- weight: 'info',
- closable: false,
- fixed: false,
- beforeClass: 'bootstrap-sticky-wrap',
+ // init : delay?
- getAutoCreate : function(){
+ init : function()
+ {
+ Roo.get(document).on('mouseover', this.enter ,this);
+ Roo.get(document).on('mouseout', this.leave, this);
+
+
+ this.currentTip = new Roo.bootstrap.Tooltip();
+ },
+
+ enter : function(ev)
+ {
+ var dom = ev.getTarget();
+
+ //Roo.log(['enter',dom]);
+ var el = Roo.fly(dom);
+ if (this.currentEl) {
+ //Roo.log(dom);
+ //Roo.log(this.currentEl);
+ //Roo.log(this.currentEl.contains(dom));
+ if (this.currentEl == el) {
+ return;
+ }
+ if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
+ return;
+ }
+
+ }
+
+
+
+ if (this.currentTip.el) {
+ this.currentTip.el.hide(); // force hiding...
+ }
+ //Roo.log(ev);
+ var bindEl = el;
+
+ // you can not look for children, as if el is the body.. then everythign is the child..
+ if (!el.attr('tooltip')) { //
+ if (!el.select("[tooltip]").elements.length) {
+ return;
+ }
+ // is the mouse over this child...?
+ bindEl = el.select("[tooltip]").first();
+ var xy = ev.getXY();
+ if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
+ //Roo.log("not in region.");
+ return;
+ }
+ //Roo.log("child element over..");
+
+ }
+ this.currentEl = bindEl;
+ this.currentTip.bind(bindEl);
+ this.currentRegion = Roo.lib.Region.getRegion(dom);
+ this.currentTip.enter();
+
+ },
+ leave : function(ev)
+ {
+ var dom = ev.getTarget();
+ //Roo.log(['leave',dom]);
+ if (!this.currentEl) {
+ return;
+ }
+
+
+ if (dom != this.currentEl.dom) {
+ return;
+ }
+ var xy = ev.getXY();
+ if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0] ))) {
+ return;
+ }
+ // only activate leave if mouse cursor is outside... bounding box..
+
+
+
+
+ if (this.currentTip) {
+ this.currentTip.leave();
+ }
+ //Roo.log('clear currentEl');
+ this.currentEl = false;
+
+ },
+ alignment : {
+ 'left' : ['r-l', [-2,0], 'right'],
+ 'right' : ['l-r', [2,0], 'left'],
+ 'bottom' : ['t-b', [0,2], 'top'],
+ 'top' : [ 'b-t', [0,-2], 'bottom']
+ }
+
+});
+
+
+Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, {
+
+
+ bindEl : false,
+
+ delay : null, // can be { show : 300 , hide: 500}
+
+ timeout : null,
+
+ hoverState : null, //???
+
+ placement : 'bottom',
+
+ getAutoCreate : function(){
+
var cfg = {
- tag: 'div',
- cls: 'alert alert-dismissable alert-' + this.weight,
- cn: [
+ cls : 'tooltip',
+ role : 'tooltip',
+ cn : [
{
- tag: 'span',
- cls: 'message',
- html: this.html || ''
+ cls : 'tooltip-arrow'
+ },
+ {
+ cls : 'tooltip-inner'
}
- ]
+ ]
+ };
+
+ return cfg;
+ },
+ bind : function(el)
+ {
+ this.bindEl = el;
+ },
+
+
+ enter : function () {
+
+ if (this.timeout != null) {
+ clearTimeout(this.timeout);
}
- if(this.fixed){
- cfg.cls += ' alert-messages-fixed';
+ this.hoverState = 'in';
+ //Roo.log("enter - show");
+ if (!this.delay || !this.delay.show) {
+ this.show();
+ return;
+ }
+ var _t = this;
+ this.timeout = setTimeout(function () {
+ if (_t.hoverState == 'in') {
+ _t.show();
+ }
+ }, this.delay.show);
+ },
+ leave : function()
+ {
+ clearTimeout(this.timeout);
+
+ this.hoverState = 'out';
+ if (!this.delay || !this.delay.hide) {
+ this.hide();
+ return;
+ }
+
+ var _t = this;
+ this.timeout = setTimeout(function () {
+ //Roo.log("leave - timeout");
+
+ if (_t.hoverState == 'out') {
+ _t.hide();
+ Roo.bootstrap.Tooltip.currentEl = false;
+ }
+ }, delay);
+ },
+
+ show : function ()
+ {
+ if (!this.el) {
+ this.render(document.body);
}
+ // set content.
+ //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
- if(this.closable){
- cfg.cn.push({
- tag: 'button',
- cls: 'close',
- html: 'x'
- });
+ var tip = this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
+
+ this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
+
+ this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
+
+ var placement = typeof this.placement == 'function' ?
+ this.placement.call(this, this.el, on_el) :
+ this.placement;
+
+ var autoToken = /\s?auto?\s?/i;
+ var autoPlace = autoToken.test(placement);
+ if (autoPlace) {
+ placement = placement.replace(autoToken, '') || 'top';
}
- return cfg;
- },
-
- onRender : function(ct, position)
- {
- Roo.bootstrap.Component.superclass.onRender.call(this, ct, position);
+ //this.el.detach()
+ //this.el.setXY([0,0]);
+ this.el.show();
+ //this.el.dom.style.display='block';
+
+ //this.el.appendTo(on_el);
+
+ var p = this.getPosition();
+ var box = this.el.getBox();
+
+ if (autoPlace) {
+ // fixme..
+ }
+
+ var align = Roo.bootstrap.Tooltip.alignment[placement];
+
+ var xy = this.el.getAlignToXY(this.bindEl, align[0], align[1]);
- if(!this.el){
- var cfg = Roo.apply({}, this.getAutoCreate());
- cfg.id = Roo.id();
-
- if (this.cls) {
- cfg.cls += ' ' + this.cls;
+ if(placement == 'top' || placement == 'bottom'){
+ if(xy[0] < 0){
+ placement = 'right';
}
- if (this.style) {
- cfg.style = this.style;
- }
- this.el = Roo.get(document.body).createChild(cfg, Roo.select('.'+this.beforeClass, true).first());
- this.el.setVisibilityMode(Roo.Element.DISPLAY);
+ if(xy[0] + this.el.getWidth() > Roo.lib.Dom.getViewWidth()){
+ placement = 'left';
+ }
}
- this.el.select('>button.close').on('click', this.hide, this);
+ align = Roo.bootstrap.Tooltip.alignment[placement];
- },
-
- show : function()
- {
- if (!this.rendered) {
- this.render();
- }
+ this.el.alignTo(this.bindEl, align[0],align[1]);
+ //var arrow = this.el.select('.arrow',true).first();
+ //arrow.set(align[2],
- this.el.show();
+ this.el.addClass(placement);
- this.fireEvent('show', this);
+ this.el.addClass('in fade');
+
+ this.hoverState = null;
+
+ if (this.el.hasClass('fade')) {
+ // fade it?
+ }
},
-
hide : function()
{
- if (!this.rendered) {
- this.render();
+
+ if (!this.el) {
+ return;
}
+ //this.el.setXY([0,0]);
+ this.el.removeClass('in');
+ //this.el.hide();
- this.el.hide();
-
- this.fireEvent('hide', this);
- },
-
- update : function()
- {
-// var e = this.el.dom.firstChild;
-//
-// if(this.closable){
-// e = e.nextSibling;
-// }
-//
-// e.data = this.html || '';
-
- this.el.select('>.message', true).first().dom.innerHTML = this.html || '';
}
-
+
});
-
- /*
+ /*
* - LGPL
*
- * Graph
+ * Location Picker
*
*/
-
/**
- * @class Roo.bootstrap.Graph
+ * @class Roo.bootstrap.LocationPicker
* @extends Roo.bootstrap.Component
- * Bootstrap Graph class
-> Prameters
- -sm {number} sm 4
- -md {number} md 5
- @cfg {String} graphtype bar | vbar | pie
- @cfg {number} g_x coodinator | centre x (pie)
- @cfg {number} g_y coodinator | centre y (pie)
- @cfg {number} g_r radius (pie)
- @cfg {number} g_height height of the chart (respected by all elements in the set)
- @cfg {number} g_width width of the chart (respected by all elements in the set)
- @cfg {Object} title The title of the chart
-
- -{Array} values
- -opts (object) options for the chart
- o {
- o type (string) type of endings of the bar. Default: 'square'. Other options are: 'round', 'sharp', 'soft'.
- o gutter (number)(string) default '20%' (WHAT DOES IT DO?)
- o vgutter (number)
- o colors (array) colors be used repeatedly to plot the bars. If multicolumn bar is used each sequence of bars with use a different color.
- o stacked (boolean) whether or not to tread values as in a stacked bar chart
- o to
- o stretch (boolean)
- o }
- -opts (object) options for the pie
- o{
- o cut
- o startAngle (number)
- o endAngle (number)
- }
- *
+ * Bootstrap LocationPicker class
+ * @cfg {Number} latitude Position when init default 0
+ * @cfg {Number} longitude Position when init default 0
+ * @cfg {Number} zoom default 15
+ * @cfg {String} mapTypeId default google.maps.MapTypeId.ROADMAP
+ * @cfg {Boolean} mapTypeControl default false
+ * @cfg {Boolean} disableDoubleClickZoom default false
+ * @cfg {Boolean} scrollwheel default true
+ * @cfg {Boolean} streetViewControl default false
+ * @cfg {Number} radius default 0
+ * @cfg {String} locationName
+ * @cfg {Boolean} draggable default true
+ * @cfg {Boolean} enableAutocomplete default false
+ * @cfg {Boolean} enableReverseGeocode default true
+ * @cfg {String} markerTitle
+ *
* @constructor
- * Create a new Input
+ * Create a new LocationPicker
* @param {Object} config The config object
*/
-Roo.bootstrap.Graph = function(config){
- Roo.bootstrap.Graph.superclass.constructor.call(this, config);
+
+Roo.bootstrap.LocationPicker = function(config){
+
+ Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
this.addEvents({
- // img events
/**
- * @event click
- * The img click event for the img.
- * @param {Roo.EventObject} e
+ * @event initial
+ * Fires when the picker initialized.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Google Location} location
*/
- "click" : true
+ initial : true,
+ /**
+ * @event positionchanged
+ * Fires when the picker position changed.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Google Location} location
+ */
+ positionchanged : true,
+ /**
+ * @event resize
+ * Fires when the map resize.
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ resize : true,
+ /**
+ * @event show
+ * Fires when the map show.
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ show : true,
+ /**
+ * @event hide
+ * Fires when the map hide.
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ hide : true,
+ /**
+ * @event mapClick
+ * Fires when click the map.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Map event} e
+ */
+ mapClick : true,
+ /**
+ * @event mapRightClick
+ * Fires when right click the map.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Map event} e
+ */
+ mapRightClick : true,
+ /**
+ * @event markerClick
+ * Fires when click the marker.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Map event} e
+ */
+ markerClick : true,
+ /**
+ * @event markerRightClick
+ * Fires when right click the marker.
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Map event} e
+ */
+ markerRightClick : true,
+ /**
+ * @event OverlayViewDraw
+ * Fires when OverlayView Draw
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ OverlayViewDraw : true,
+ /**
+ * @event OverlayViewOnAdd
+ * Fires when OverlayView Draw
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ OverlayViewOnAdd : true,
+ /**
+ * @event OverlayViewOnRemove
+ * Fires when OverlayView Draw
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ OverlayViewOnRemove : true,
+ /**
+ * @event OverlayViewShow
+ * Fires when OverlayView Draw
+ * @param {Roo.bootstrap.LocationPicker} this
+ * @param {Pixel} cpx
+ */
+ OverlayViewShow : true,
+ /**
+ * @event OverlayViewHide
+ * Fires when OverlayView Draw
+ * @param {Roo.bootstrap.LocationPicker} this
+ */
+ OverlayViewHide : true
});
+
};
-Roo.extend(Roo.bootstrap.Graph, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component, {
- sm: 4,
- md: 5,
- graphtype: 'bar',
- g_height: 250,
- g_width: 400,
- g_x: 50,
- g_y: 50,
- g_r: 30,
- opts:{
- //g_colors: this.colors,
- g_type: 'soft',
- g_gutter: '20%'
-
- },
- title : false,
+ gMapContext: false,
+
+ latitude: 0,
+ longitude: 0,
+ zoom: 15,
+ mapTypeId: false,
+ mapTypeControl: false,
+ disableDoubleClickZoom: false,
+ scrollwheel: true,
+ streetViewControl: false,
+ radius: 0,
+ locationName: '',
+ draggable: true,
+ enableAutocomplete: false,
+ enableReverseGeocode: true,
+ markerTitle: '',
+
+ getAutoCreate: function()
+ {
- getAutoCreate : function(){
-
var cfg = {
tag: 'div',
- html : null
+ cls: 'roo-location-picker'
+ };
+
+ return cfg
+ },
+
+ initEvents: function(ct, position)
+ {
+ if(!this.el.getWidth() || this.isApplied()){
+ return;
}
+ this.el.setVisibilityMode(Roo.Element.DISPLAY);
- return cfg;
+ this.initial();
},
-
- onRender : function(ct,position){
- Roo.bootstrap.Graph.superclass.onRender.call(this,ct,position);
- this.raphael = Raphael(this.el.dom);
+
+ initial: function()
+ {
+ if(!this.mapTypeId){
+ this.mapTypeId = google.maps.MapTypeId.ROADMAP;
+ }
- // data1 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
- // data2 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
- // data3 = [[55, 20, 13, 32, 5, 1, 2, 10], [10, 2, 1, 5, 32, 13, 20, 55], [12, 20, 30]],
- // txtattr = { font: "12px 'Fontin Sans', Fontin-Sans, sans-serif" };
- /*
- r.text(160, 10, "Single Series Chart").attr(txtattr);
- r.text(480, 10, "Multiline Series Chart").attr(txtattr);
- r.text(160, 250, "Multiple Series Stacked Chart").attr(txtattr);
- r.text(480, 250, 'Multiline Series Stacked Vertical Chart. Type "round"').attr(txtattr);
-
- r.barchart(10, 10, 300, 220, [[55, 20, 13, 32, 5, 1, 2, 10]], 0, {type: "sharp"});
- r.barchart(330, 10, 300, 220, data1);
- r.barchart(10, 250, 300, 220, data2, {stacked: true});
- r.barchart(330, 250, 300, 220, data3, {stacked: true, type: "round"});
- */
+ this.gMapContext = this.GMapContext();
+
+ this.initOverlayView();
+
+ this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+
+ var _this = this;
- // var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
- // r.barchart(30, 30, 560, 250, xdata, {
- // labels : [55, 20, 13, 32, 5, 1, 2, 10,5 , 10],
- // axis : "0 0 1 1",
- // axisxlabels : xdata
- // //yvalues : cols,
-
- // });
-// var xdata = [55, 20, 13, 32, 5, 1, 2, 10,5 , 10];
-//
-// this.load(null,xdata,{
-// axis : "0 0 1 1",
-// axisxlabels : xdata
-// });
+ google.maps.event.addListener(this.gMapContext.marker, "dragend", function(event) {
+ _this.setPosition(_this.gMapContext.marker.position);
+ });
+
+ google.maps.event.addListener(this.gMapContext.map, 'click', function(event){
+ _this.fireEvent('mapClick', this, event);
+
+ });
- },
+ google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
+ _this.fireEvent('mapRightClick', this, event);
+
+ });
+
+ google.maps.event.addListener(this.gMapContext.marker, 'click', function(event){
+ _this.fireEvent('markerClick', this, event);
+
+ });
- load : function(graphtype,xdata,opts){
- this.raphael.clear();
- if(!graphtype) {
- graphtype = this.graphtype;
- }
- if(!opts){
- opts = this.opts;
- }
- var r = this.raphael,
- fin = function () {
- this.flag = r.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this);
+ google.maps.event.addListener(this.gMapContext.marker, 'rightclick', function(event){
+ _this.fireEvent('markerRightClick', this, event);
+
+ });
+
+ this.setPosition(this.gMapContext.location);
+
+ this.fireEvent('initial', this, this.gMapContext.location);
+ },
+
+ initOverlayView: function()
+ {
+ var _this = this;
+
+ Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
+
+ draw: function()
+ {
+ _this.fireEvent('OverlayViewDraw', _this);
},
- fout = function () {
- this.flag.animate({opacity: 0}, 300, function () {this.remove();});
+
+ onAdd: function()
+ {
+ _this.fireEvent('OverlayViewOnAdd', _this);
},
- pfin = function() {
- this.sector.stop();
- this.sector.scale(1.1, 1.1, this.cx, this.cy);
-
- if (this.label) {
- this.label[0].stop();
- this.label[0].attr({ r: 7.5 });
- this.label[1].attr({ "font-weight": 800 });
- }
+
+ onRemove: function()
+ {
+ _this.fireEvent('OverlayViewOnRemove', _this);
},
- pfout = function() {
- this.sector.animate({ transform: 's1 1 ' + this.cx + ' ' + this.cy }, 500, "bounce");
-
- if (this.label) {
- this.label[0].animate({ r: 5 }, 500, "bounce");
- this.label[1].attr({ "font-weight": 400 });
- }
- };
-
- switch(graphtype){
- case 'bar':
- this.raphael.barchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
- break;
- case 'hbar':
- this.raphael.hbarchart(this.g_x,this.g_y,this.g_width,this.g_height,xdata,opts).hover(fin,fout);
- break;
- case 'pie':
-// opts = { legend: ["%% - Enterprise Users", "% - ddd","Chrome Users"], legendpos: "west",
-// href: ["http://raphaeljs.com", "http://g.raphaeljs.com"]};
-//
- this.raphael.piechart(this.g_x,this.g_y,this.g_r,xdata,opts).hover(pfin, pfout);
+
+ show: function(cpx)
+ {
+ _this.fireEvent('OverlayViewShow', _this, cpx);
+ },
+
+ hide: function()
+ {
+ _this.fireEvent('OverlayViewHide', _this);
+ }
+
+ });
+ },
+
+ fromLatLngToContainerPixel: function(event)
+ {
+ return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
+ },
+
+ isApplied: function()
+ {
+ return this.getGmapContext() == false ? false : true;
+ },
+
+ getGmapContext: function()
+ {
+ return this.gMapContext
+ },
+
+ GMapContext: function()
+ {
+ var position = new google.maps.LatLng(this.latitude, this.longitude);
+
+ var _map = new google.maps.Map(this.el.dom, {
+ center: position,
+ zoom: this.zoom,
+ mapTypeId: this.mapTypeId,
+ mapTypeControl: this.mapTypeControl,
+ disableDoubleClickZoom: this.disableDoubleClickZoom,
+ scrollwheel: this.scrollwheel,
+ streetViewControl: this.streetViewControl,
+ locationName: this.locationName,
+ draggable: this.draggable,
+ enableAutocomplete: this.enableAutocomplete,
+ enableReverseGeocode: this.enableReverseGeocode
+ });
+
+ var _marker = new google.maps.Marker({
+ position: position,
+ map: _map,
+ title: this.markerTitle,
+ draggable: this.draggable
+ });
+
+ return {
+ map: _map,
+ marker: _marker,
+ circle: null,
+ location: position,
+ radius: this.radius,
+ locationName: this.locationName,
+ addressComponents: {
+ formatted_address: null,
+ addressLine1: null,
+ addressLine2: null,
+ streetName: null,
+ streetNumber: null,
+ city: null,
+ district: null,
+ state: null,
+ stateOrProvince: null
+ },
+ settings: this,
+ domContainer: this.el.dom,
+ geodecoder: new google.maps.Geocoder()
+ };
+ },
+
+ drawCircle: function(center, radius, options)
+ {
+ if (this.gMapContext.circle != null) {
+ this.gMapContext.circle.setMap(null);
+ }
+ if (radius > 0) {
+ radius *= 1;
+ options = Roo.apply({}, options, {
+ strokeColor: "#0000FF",
+ strokeOpacity: .35,
+ strokeWeight: 2,
+ fillColor: "#0000FF",
+ fillOpacity: .2
+ });
+
+ options.map = this.gMapContext.map;
+ options.radius = radius;
+ options.center = center;
+ this.gMapContext.circle = new google.maps.Circle(options);
+ return this.gMapContext.circle;
+ }
+
+ return null;
+ },
+
+ setPosition: function(location)
+ {
+ this.gMapContext.location = location;
+ this.gMapContext.marker.setPosition(location);
+ this.gMapContext.map.panTo(location);
+ this.drawCircle(location, this.gMapContext.radius, {});
+
+ var _this = this;
+
+ if (this.gMapContext.settings.enableReverseGeocode) {
+ this.gMapContext.geodecoder.geocode({
+ latLng: this.gMapContext.location
+ }, function(results, status) {
- break;
-
+ if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
+ _this.gMapContext.locationName = results[0].formatted_address;
+ _this.gMapContext.addressComponents = _this.address_component_from_google_geocode(results[0].address_components);
+
+ _this.fireEvent('positionchanged', this, location);
+ }
+ });
+
+ return;
}
- if(this.title){
- this.raphael.text(this.title.x, this.title.y, this.title.text).attr(this.title.attr);
- }
+ this.fireEvent('positionchanged', this, location);
+ },
+
+ resize: function()
+ {
+ google.maps.event.trigger(this.gMapContext.map, "resize");
+
+ this.gMapContext.map.setCenter(this.gMapContext.marker.position);
+ this.fireEvent('resize', this);
},
- setTitle: function(o)
+ setPositionByLatLng: function(latitude, longitude)
{
- this.title = o;
+ this.setPosition(new google.maps.LatLng(latitude, longitude));
},
- initEvents: function() {
+ getCurrentPosition: function()
+ {
+ return {
+ latitude: this.gMapContext.location.lat(),
+ longitude: this.gMapContext.location.lng()
+ };
+ },
+
+ getAddressName: function()
+ {
+ return this.gMapContext.locationName;
+ },
+
+ getAddressComponents: function()
+ {
+ return this.gMapContext.addressComponents;
+ },
+
+ address_component_from_google_geocode: function(address_components)
+ {
+ var result = {};
- if(!this.href){
- this.el.on('click', this.onClick, this);
+ for (var i = 0; i < address_components.length; i++) {
+ var component = address_components[i];
+ if (component.types.indexOf("postal_code") >= 0) {
+ result.postalCode = component.short_name;
+ } else if (component.types.indexOf("street_number") >= 0) {
+ result.streetNumber = component.short_name;
+ } else if (component.types.indexOf("route") >= 0) {
+ result.streetName = component.short_name;
+ } else if (component.types.indexOf("neighborhood") >= 0) {
+ result.city = component.short_name;
+ } else if (component.types.indexOf("locality") >= 0) {
+ result.city = component.short_name;
+ } else if (component.types.indexOf("sublocality") >= 0) {
+ result.district = component.short_name;
+ } else if (component.types.indexOf("administrative_area_level_1") >= 0) {
+ result.stateOrProvince = component.short_name;
+ } else if (component.types.indexOf("country") >= 0) {
+ result.country = component.short_name;
+ }
}
+
+ result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
+ result.addressLine2 = "";
+ return result;
},
- onClick : function(e)
+ setZoomLevel: function(zoom)
{
- Roo.log('img onclick');
- this.fireEvent('click', this, e);
+ this.gMapContext.map.setZoom(zoom);
+ },
+
+ show: function()
+ {
+ if(!this.el){
+ return;
+ }
+
+ this.el.show();
+
+ this.resize();
+
+ this.fireEvent('show', this);
+ },
+
+ hide: function()
+ {
+ if(!this.el){
+ return;
+ }
+
+ this.el.hide();
+
+ this.fireEvent('hide', this);
}
-
+
});
-
-/*
+Roo.apply(Roo.bootstrap.LocationPicker, {
+
+ OverlayView : function(map, options)
+ {
+ options = options || {};
+
+ this.setMap(map);
+ }
+
+
+});/*
* - LGPL
*
- * numberBox
+ * Alert
*
*/
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
/**
- * @class Roo.bootstrap.dash.NumberBox
+ * @class Roo.bootstrap.Alert
* @extends Roo.bootstrap.Component
- * Bootstrap NumberBox class
- * @cfg {String} headline Box headline
- * @cfg {String} content Box content
- * @cfg {String} icon Box icon
- * @cfg {String} footer Footer text
- * @cfg {String} fhref Footer href
+ * Bootstrap Alert class
+ * @cfg {String} title The title of alert
+ * @cfg {String} html The content of alert
+ * @cfg {String} weight ( success | info | warning | danger )
+ * @cfg {String} faicon font-awesomeicon
*
* @constructor
- * Create a new NumberBox
+ * Create a new alert
* @param {Object} config The config object
*/
-Roo.bootstrap.dash.NumberBox = function(config){
- Roo.bootstrap.dash.NumberBox.superclass.constructor.call(this, config);
+Roo.bootstrap.Alert = function(config){
+ Roo.bootstrap.Alert.superclass.constructor.call(this, config);
};
-Roo.extend(Roo.bootstrap.dash.NumberBox, Roo.bootstrap.Component, {
+Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, {
- headline : '',
- content : '',
- icon : '',
- footer : '',
- fhref : '',
- ficon : '',
+ title: '',
+ html: '',
+ weight: false,
+ faicon: false,
- getAutoCreate : function(){
+ getAutoCreate : function()
+ {
var cfg = {
tag : 'div',
- cls : 'small-box ',
+ cls : 'alert',
cn : [
{
- tag : 'div',
- cls : 'inner',
- cn :[
- {
- tag : 'h3',
- cls : 'roo-headline',
- html : this.headline
- },
- {
- tag : 'p',
- cls : 'roo-content',
- html : this.content
- }
- ]
+ tag : 'i',
+ cls : 'roo-alert-icon'
+
+ },
+ {
+ tag : 'b',
+ cls : 'roo-alert-title',
+ html : this.title
+ },
+ {
+ tag : 'span',
+ cls : 'roo-alert-text',
+ html : this.html
}
]
- }
+ };
- if(this.icon){
- cfg.cn.push({
- tag : 'div',
- cls : 'icon',
- cn :[
- {
- tag : 'i',
- cls : 'ion ' + this.icon
- }
- ]
- });
+ if(this.faicon){
+ cfg.cn[0].cls += ' fa ' + this.faicon;
}
- if(this.footer){
- var footer = {
- tag : 'a',
- cls : 'small-box-footer',
- href : this.fhref || '#',
- html : this.footer
- };
-
- cfg.cn.push(footer);
-
+ if(this.weight){
+ cfg.cls += ' alert-' + this.weight;
}
- return cfg;
+ return cfg;
},
-
- onRender : function(ct,position){
- Roo.bootstrap.dash.NumberBox.superclass.onRender.call(this,ct,position);
-
-
-
-
+
+ initEvents: function()
+ {
+ this.el.setVisibilityMode(Roo.Element.DISPLAY);
},
-
- setHeadline: function (value)
+
+ setTitle : function(str)
{
- this.el.select('.roo-headline',true).first().dom.innerHTML = value;
+ this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
+ },
+
+ setText : function(str)
+ {
+ this.el.select('.roo-alert-text',true).first().dom.innerHTML = str;
+ },
+
+ setWeight : function(weight)
+ {
+ if(this.weight){
+ this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
+ }
+
+ this.weight = weight;
+
+ this.el.select('.alert',true).first().addClass('alert-' + this.weight);
},
- setFooter: function (value, href)
+ setIcon : function(icon)
{
- this.el.select('a.small-box-footer',true).first().dom.innerHTML = value;
-
- if(href){
- this.el.select('a.small-box-footer',true).first().attr('href', href);
+ if(this.faicon){
+ this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
}
+ this.faicon = icon
+
+ this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
},
-
- setContent: function (value)
+
+ hide: function()
{
- this.el.select('.roo-content',true).first().dom.innerHTML = value;
+ this.el.hide();
},
-
- initEvents: function()
- {
-
+
+ show: function()
+ {
+ this.el.show();
}
});
/*
- * - LGPL
- *
- * TabBox
- *
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
+* Licence: LGPL
+*/
/**
- * @class Roo.bootstrap.dash.TabBox
+ * @class Roo.bootstrap.UploadCropbox
* @extends Roo.bootstrap.Component
- * Bootstrap TabBox class
- * @cfg {String} title Title of the TabBox
- * @cfg {String} icon Icon of the TabBox
- * @cfg {Boolean} showtabs (true|false) show the tabs default true
- * @cfg {Boolean} tabScrollable (true|false) tab scrollable when mobile view default false
+ * Bootstrap UploadCropbox class
+ * @cfg {String} emptyText show when image has been loaded
+ * @cfg {String} rotateNotify show when image too small to rotate
+ * @cfg {Number} errorTimeout default 3000
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Array} buttons default ['rotateLeft', 'pictureBtn', 'rotateRight']
+ * @cfg {Boolean} isDocument (true|false) default false
*
* @constructor
- * Create a new TabBox
+ * Create a new UploadCropbox
* @param {Object} config The config object
*/
-
-Roo.bootstrap.dash.TabBox = function(config){
- Roo.bootstrap.dash.TabBox.superclass.constructor.call(this, config);
+Roo.bootstrap.UploadCropbox = function(config){
+ Roo.bootstrap.UploadCropbox.superclass.constructor.call(this, config);
+
this.addEvents({
- // raw events
/**
- * @event addpane
- * When a pane is added
- * @param {Roo.bootstrap.dash.TabPane} pane
+ * @event beforeselectfile
+ * Fire before select file
+ * @param {Roo.bootstrap.UploadCropbox} this
*/
- "addpane" : true,
+ "beforeselectfile" : true,
/**
- * @event activatepane
- * When a pane is activated
- * @param {Roo.bootstrap.dash.TabPane} pane
+ * @event initial
+ * Fire after initEvent
+ * @param {Roo.bootstrap.UploadCropbox} this
*/
- "activatepane" : true
-
-
+ "initial" : true,
+ /**
+ * @event crop
+ * Fire after initEvent
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {String} data
+ */
+ "crop" : true,
+ /**
+ * @event prepare
+ * Fire when preparing the file data
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {Object} file
+ */
+ "prepare" : true,
+ /**
+ * @event exception
+ * Fire when get exception
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {Object} options
+ */
+ "exception" : true,
+ /**
+ * @event beforeloadcanvas
+ * Fire before load the canvas
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {String} src
+ */
+ "beforeloadcanvas" : true,
+ /**
+ * @event trash
+ * Fire when trash image
+ * @param {Roo.bootstrap.UploadCropbox} this
+ */
+ "trash" : true,
+ /**
+ * @event download
+ * Fire when download the image
+ * @param {Roo.bootstrap.UploadCropbox} this
+ */
+ "download" : true,
+ /**
+ * @event footerbuttonclick
+ * Fire when footerbuttonclick
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {String} type
+ */
+ "footerbuttonclick" : true,
+ /**
+ * @event resize
+ * Fire when resize
+ * @param {Roo.bootstrap.UploadCropbox} this
+ */
+ "resize" : true,
+ /**
+ * @event rotate
+ * Fire when rotate the image
+ * @param {Roo.bootstrap.UploadCropbox} this
+ * @param {String} pos
+ */
+ "rotate" : true
});
- this.panes = [];
+ this.buttons = this.buttons || Roo.bootstrap.UploadCropbox.footer.STANDARD;
};
-Roo.extend(Roo.bootstrap.dash.TabBox, Roo.bootstrap.Component, {
-
- title : '',
- icon : false,
- showtabs : true,
- tabScrollable : false,
+Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component, {
+
+ emptyText : 'Click to upload image',
+ rotateNotify : 'Image is too small to rotate',
+ errorTimeout : 3000,
+ scale : 0,
+ baseScale : 1,
+ rotate : 0,
+ dragable : false,
+ pinching : false,
+ mouseX : 0,
+ mouseY : 0,
+ cropData : false,
+ minWidth : 300,
+ minHeight : 300,
+ file : false,
+ exif : {},
+ baseRotate : 1,
+ cropType : 'image/jpeg',
+ buttons : false,
+ canvasLoaded : false,
+ isDocument : false,
- getChildContainer : function()
+ getAutoCreate : function()
{
- return this.el.select('.tab-content', true).first();
+ var cfg = {
+ tag : 'div',
+ cls : 'roo-upload-cropbox',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-body',
+ style : 'cursor:pointer',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-preview'
+ },
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-thumb'
+ },
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-empty-notify',
+ html : this.emptyText
+ },
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-error-notify alert alert-danger',
+ html : this.rotateNotify
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'roo-upload-cropbox-footer',
+ cn : {
+ tag : 'div',
+ cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
+ cn : []
+ }
+ }
+ ]
+ };
+
+ return cfg;
},
- getAutoCreate : function(){
-
- var header = {
- tag: 'li',
- cls: 'pull-left header',
- html: this.title,
- cn : []
- };
+ onRender : function(ct, position)
+ {
+ Roo.bootstrap.UploadCropbox.superclass.onRender.call(this, ct, position);
- if(this.icon){
- header.cn.push({
- tag: 'i',
- cls: 'fa ' + this.icon
- });
+ if (this.buttons.length) {
+
+ Roo.each(this.buttons, function(bb) {
+
+ var btn = this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb);
+
+ btn.on('click', this.onFooterButtonClick.createDelegate(this, [bb.action], true));
+
+ }, this);
}
+ },
+
+ initEvents : function()
+ {
+ this.urlAPI = (window.createObjectURL && window) ||
+ (window.URL && URL.revokeObjectURL && URL) ||
+ (window.webkitURL && webkitURL);
+
+ this.bodyEl = this.el.select('.roo-upload-cropbox-body', true).first();
+ this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
- var h = {
- tag: 'ul',
- cls: 'nav nav-tabs pull-right',
- cn: [
- header
- ]
- };
+ this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first();
+ this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
- if(this.tabScrollable){
- h = {
- tag: 'div',
- cls: 'tab-header',
- cn: [
- {
- tag: 'ul',
- cls: 'nav nav-tabs pull-right',
- cn: [
- header
- ]
- }
- ]
- }
+ this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first();
+ this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.thumbEl.hide();
+
+ this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
+ this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.errorEl = this.el.select('.roo-upload-cropbox-error-notify', true).first();
+ this.errorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.errorEl.hide();
+
+ this.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first();
+ this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.footerEl.hide();
+
+ this.setThumbBoxSize();
+
+ this.bind();
+
+ this.resize();
+
+ this.fireEvent('initial', this);
+ },
+
+ bind : function()
+ {
+ var _this = this;
+
+ window.addEventListener("resize", function() { _this.resize(); } );
+
+ this.bodyEl.on('click', this.beforeSelectFile, this);
+
+ if(Roo.isTouch){
+ this.bodyEl.on('touchstart', this.onTouchStart, this);
+ this.bodyEl.on('touchmove', this.onTouchMove, this);
+ this.bodyEl.on('touchend', this.onTouchEnd, this);
}
- var cfg = {
- tag: 'div',
- cls: 'nav-tabs-custom',
- cn: [
- h,
- {
- tag: 'div',
- cls: 'tab-content no-padding',
- cn: []
- }
- ]
+ if(!Roo.isTouch){
+ this.bodyEl.on('mousedown', this.onMouseDown, this);
+ this.bodyEl.on('mousemove', this.onMouseMove, this);
+ var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
+ this.bodyEl.on(mousewheel, this.onMouseWheel, this);
+ Roo.get(document).on('mouseup', this.onMouseUp, this);
}
-
- return cfg;
},
- initEvents : function()
+
+ reset : function()
+ {
+ this.scale = 0;
+ this.baseScale = 1;
+ this.rotate = 0;
+ this.baseRotate = 1;
+ this.dragable = false;
+ this.pinching = false;
+ this.mouseX = 0;
+ this.mouseY = 0;
+ this.cropData = false;
+ this.notifyEl.dom.innerHTML = this.emptyText;
+
+ },
+
+ resize : function()
{
- //Roo.log('add add pane handler');
- this.on('addpane', this.onAddPane, this);
+ if(this.fireEvent('resize', this) != false){
+ this.setThumbBoxPosition();
+ this.setCanvasPosition();
+ }
},
- /**
- * Updates the box title
- * @param {String} html to set the title to.
- */
- setTitle : function(value)
+
+ onFooterButtonClick : function(e, el, o, type)
{
- this.el.select('.nav-tabs .header', true).first().dom.innerHTML = value;
+ switch (type) {
+ case 'rotate-left' :
+ this.onRotateLeft(e);
+ break;
+ case 'rotate-right' :
+ this.onRotateRight(e);
+ break;
+ case 'picture' :
+ this.beforeSelectFile(e);
+ break;
+ case 'trash' :
+ this.trash(e);
+ break;
+ case 'crop' :
+ this.crop(e);
+ break;
+ case 'download' :
+ this.download(e);
+ break;
+ default :
+ break;
+ }
+
+ this.fireEvent('footerbuttonclick', this, type);
},
- onAddPane : function(pane)
+
+ beforeSelectFile : function(e)
{
- this.panes.push(pane);
- //Roo.log('addpane');
- //Roo.log(pane);
- // tabs are rendere left to right..
- if(!this.showtabs){
+ this.fireEvent('beforeselectfile', this);
+ },
+
+ trash : function(e)
+ {
+ this.fireEvent('trash', this);
+ },
+
+ download : function(e)
+ {
+ this.fireEvent('download', this);
+ },
+
+ loadCanvas : function(src)
+ {
+ if(this.fireEvent('beforeloadcanvas', this, src) != false){
+
+ this.reset();
+
+ this.imageEl = document.createElement('img');
+
+ var _this = this;
+
+ this.imageEl.addEventListener("load", function(){ _this.onLoadCanvas(); });
+
+ this.imageEl.src = src;
+ }
+ },
+
+ onLoadCanvas : function()
+ {
+ this.bodyEl.un('click', this.beforeSelectFile, this);
+
+ this.notifyEl.hide();
+ this.thumbEl.show();
+ this.footerEl.show();
+
+ this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width;
+ this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height;
+
+ this.baseRotateLevel();
+
+ if(this.isDocument){
+ this.setThumbBoxSize();
+ }
+
+ this.setThumbBoxPosition();
+
+ this.baseScaleLevel();
+
+ this.draw();
+
+ this.resize();
+
+ this.canvasLoaded = true;
+
+ },
+
+ setCanvasPosition : function()
+ {
+ if(!this.canvasEl){
return;
}
- var ctr = this.el.select('.nav-tabs', true).first();
-
-
- var existing = ctr.select('.nav-tab',true);
- var qty = existing.getCount();;
+ var pw = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+ var ph = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
+ this.previewEl.setLeft(pw);
+ this.previewEl.setTop(ph);
- var tab = ctr.createChild({
- tag : 'li',
- cls : 'nav-tab' + (qty ? '' : ' active'),
- cn : [
- {
- tag : 'a',
- href:'#',
- html : pane.title
- }
- ]
- }, qty ? existing.first().dom : ctr.select('.header', true).first().dom );
- pane.tab = tab;
+ },
+
+ onMouseDown : function(e)
+ {
+ e.stopEvent();
- tab.on('click', this.onTabClick.createDelegate(this, [pane], true));
- if (!qty) {
- pane.el.addClass('active');
+ this.dragable = true;
+ this.pinching = false;
+
+ if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){
+ this.dragable = false;
+ return;
}
-
+ this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+ this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+
},
- onTabClick : function(ev,un,ob,pane)
- {
- //Roo.log('tab - prev default');
- ev.preventDefault();
+
+ onMouseMove : function(e)
+ {
+ e.stopEvent();
+ if(!this.canvasLoaded){
+ return;
+ }
- this.el.select('.nav-tabs li.nav-tab', true).removeClass('active');
- pane.tab.addClass('active');
- //Roo.log(pane.title);
- this.getChildContainer().select('.tab-pane',true).removeClass('active');
- // technically we should have a deactivate event.. but maybe add later.
- // and it should not de-activate the selected tab...
- this.fireEvent('activatepane', pane);
- pane.el.addClass('active');
- pane.fireEvent('activate');
+ if (!this.dragable){
+ return;
+ }
+
+ var minX = Math.ceil(this.thumbEl.getLeft(true));
+ var minY = Math.ceil(this.thumbEl.getTop(true));
+
+ var maxX = Math.ceil(minX + this.thumbEl.getWidth() - this.canvasEl.width);
+ var maxY = Math.ceil(minY + this.thumbEl.getHeight() - this.canvasEl.height);
+
+ var x = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+ var y = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
+ x = x - this.mouseX;
+ y = y - this.mouseY;
+ var bgX = Math.ceil(x + this.previewEl.getLeft(true));
+ var bgY = Math.ceil(y + this.previewEl.getTop(true));
+
+ bgX = (minX < bgX) ? minX : ((maxX > bgX) ? maxX : bgX);
+ bgY = (minY < bgY) ? minY : ((maxY > bgY) ? maxY : bgY);
+
+ this.previewEl.setLeft(bgX);
+ this.previewEl.setTop(bgY);
+
+ this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
+ this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
},
- getActivePane : function()
- {
- var r = false;
- Roo.each(this.panes, function(p) {
- if(p.el.hasClass('active')){
- r = p;
- return false;
- }
-
- return;
- });
+ onMouseUp : function(e)
+ {
+ e.stopEvent();
- return r;
- }
-
-
-});
-
-
-/*
- * - LGPL
- *
- * Tab pane
- *
- */
-Roo.bootstrap.dash = Roo.bootstrap.dash || {};
-/**
- * @class Roo.bootstrap.TabPane
- * @extends Roo.bootstrap.Component
- * Bootstrap TabPane class
- * @cfg {Boolean} active (false | true) Default false
- * @cfg {String} title title of panel
-
- *
- * @constructor
- * Create a new TabPane
- * @param {Object} config The config object
- */
-
-Roo.bootstrap.dash.TabPane = function(config){
- Roo.bootstrap.dash.TabPane.superclass.constructor.call(this, config);
-
- this.addEvents({
- // raw events
- /**
- * @event activate
- * When a pane is activated
- * @param {Roo.bootstrap.dash.TabPane} pane
- */
- "activate" : true
-
- });
-};
-
-Roo.extend(Roo.bootstrap.dash.TabPane, Roo.bootstrap.Component, {
-
- active : false,
- title : '',
+ this.dragable = false;
+ },
- // the tabBox that this is attached to.
- tab : false,
-
- getAutoCreate : function()
- {
- var cfg = {
- tag: 'div',
- cls: 'tab-pane'
- }
+ onMouseWheel : function(e)
+ {
+ e.stopEvent();
- if(this.active){
- cfg.cls += ' active';
+ this.startScale = this.scale;
+
+ this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
+
+ if(!this.zoomable()){
+ this.scale = this.startScale;
+ return;
}
- return cfg;
- },
- initEvents : function()
- {
- //Roo.log('trigger add pane handler');
- this.parent().fireEvent('addpane', this)
+ this.draw();
+
+ return;
},
- /**
- * Updates the tab title
- * @param {String} html to set the title to.
- */
- setTitle: function(str)
+ zoomable : function()
{
- if (!this.tab) {
- return;
+ var minScale = this.thumbEl.getWidth() / this.minWidth;
+
+ if(this.minWidth < this.minHeight){
+ minScale = this.thumbEl.getHeight() / this.minHeight;
}
- this.title = str;
- this.tab.select('a', true).first().dom.innerHTML = str;
- }
-
-
+ var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale);
+ var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale);
+
+ if(
+ this.isDocument &&
+ (this.rotate == 0 || this.rotate == 180) &&
+ (
+ width > this.imageEl.OriginWidth ||
+ height > this.imageEl.OriginHeight ||
+ (width < this.minWidth && height < this.minHeight)
+ )
+ ){
+ return false;
+ }
+
+ if(
+ this.isDocument &&
+ (this.rotate == 90 || this.rotate == 270) &&
+ (
+ width > this.imageEl.OriginWidth ||
+ height > this.imageEl.OriginHeight ||
+ (width < this.minHeight && height < this.minWidth)
+ )
+ ){
+ return false;
+ }
+
+ if(
+ !this.isDocument &&
+ (this.rotate == 0 || this.rotate == 180) &&
+ (
+ width < this.minWidth ||
+ width > this.imageEl.OriginWidth ||
+ height < this.minHeight ||
+ height > this.imageEl.OriginHeight
+ )
+ ){
+ return false;
+ }
+
+ if(
+ !this.isDocument &&
+ (this.rotate == 90 || this.rotate == 270) &&
+ (
+ width < this.minHeight ||
+ width > this.imageEl.OriginWidth ||
+ height < this.minWidth ||
+ height > this.imageEl.OriginHeight
+ )
+ ){
+ return false;
+ }
+
+ return true;
+
+ },
-});
-
-
-
-
- /*
- * - LGPL
- *
- * menu
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Menu
- * @extends Roo.bootstrap.Component
- * Bootstrap Menu class - container for Menu
- * @cfg {String} html Text of the menu
- * @cfg {String} weight (default | primary | success | info | warning | danger | inverse)
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Menu align to (top | bottom) default bottom
- *
- *
- * @constructor
- * Create a new Menu
- * @param {Object} config The config object
- */
-
+ onRotateLeft : function(e)
+ {
+ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+
+ var minScale = this.thumbEl.getWidth() / this.minWidth;
+
+ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+
+ this.startScale = this.scale;
+
+ while (this.getScaleLevel() < minScale){
+
+ this.scale = this.scale + 1;
+
+ if(!this.zoomable()){
+ break;
+ }
+
+ if(
+ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+ ){
+ continue;
+ }
+
+ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
-Roo.bootstrap.menu.Menu = function(config){
- Roo.bootstrap.menu.Menu.superclass.constructor.call(this, config);
-
- this.addEvents({
- /**
- * @event beforeshow
- * Fires before this menu is displayed
- * @param {Roo.bootstrap.menu.Menu} this
- */
- beforeshow : true,
- /**
- * @event beforehide
- * Fires before this menu is hidden
- * @param {Roo.bootstrap.menu.Menu} this
- */
- beforehide : true,
- /**
- * @event show
- * Fires after this menu is displayed
- * @param {Roo.bootstrap.menu.Menu} this
- */
- show : true,
- /**
- * @event hide
- * Fires after this menu is hidden
- * @param {Roo.bootstrap.menu.Menu} this
- */
- hide : true,
- /**
- * @event click
- * Fires when this menu is clicked (or when the enter key is pressed while it is active)
- * @param {Roo.bootstrap.menu.Menu} this
- * @param {Roo.EventObject} e
- */
- click : true
- });
-
-};
+ this.draw();
+
+ return;
+ }
+
+ this.scale = this.startScale;
+
+ this.onRotateFail();
+
+ return false;
+ }
+
+ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
-Roo.extend(Roo.bootstrap.menu.Menu, Roo.bootstrap.Component, {
-
- submenu : false,
- html : '',
- weight : 'default',
- icon : false,
- pos : 'bottom',
-
-
- getChildContainer : function() {
- if(this.isSubMenu){
- return this.el;
+ if(this.isDocument){
+ this.setThumbBoxSize();
+ this.setThumbBoxPosition();
+ this.setCanvasPosition();
}
- return this.el.select('ul.dropdown-menu', true).first();
+ this.draw();
+
+ this.fireEvent('rotate', this, 'left');
+
},
- getAutoCreate : function()
+ onRotateRight : function(e)
{
- var text = [
- {
- tag : 'span',
- cls : 'roo-menu-text',
- html : this.html
- }
- ];
-
- if(this.icon){
- text.unshift({
- tag : 'i',
- cls : 'fa ' + this.icon
- })
- }
-
+ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){
+
+ var minScale = this.thumbEl.getWidth() / this.minWidth;
- var cfg = {
- tag : 'div',
- cls : 'btn-group',
- cn : [
- {
- tag : 'button',
- cls : 'dropdown-button btn btn-' + this.weight,
- cn : text
- },
- {
- tag : 'button',
- cls : 'dropdown-toggle btn btn-' + this.weight,
- cn : [
- {
- tag : 'span',
- cls : 'caret'
- }
- ]
- },
- {
- tag : 'ul',
- cls : 'dropdown-menu'
+ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel());
+ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel());
+
+ this.startScale = this.scale;
+
+ while (this.getScaleLevel() < minScale){
+
+ this.scale = this.scale + 1;
+
+ if(!this.zoomable()){
+ break;
}
- ]
+
+ if(
+ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() ||
+ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth()
+ ){
+ continue;
+ }
+
+ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+ this.draw();
+
+ return;
+ }
- };
-
- if(this.pos == 'top'){
- cfg.cls += ' dropup';
+ this.scale = this.startScale;
+
+ this.onRotateFail();
+
+ return false;
}
- if(this.isSubMenu){
- cfg = {
- tag : 'ul',
- cls : 'dropdown-menu'
- }
+ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+ if(this.isDocument){
+ this.setThumbBoxSize();
+ this.setThumbBoxPosition();
+ this.setCanvasPosition();
}
-
- return cfg;
+
+ this.draw();
+
+ this.fireEvent('rotate', this, 'right');
},
- onRender : function(ct, position)
+ onRotateFail : function()
{
- this.isSubMenu = ct.hasClass('dropdown-submenu');
+ this.errorEl.show(true);
- Roo.bootstrap.menu.Menu.superclass.onRender.call(this, ct, position);
+ var _this = this;
+
+ (function() { _this.errorEl.hide(true); }).defer(this.errorTimeout);
},
- initEvents : function()
+ draw : function()
{
- if(this.isSubMenu){
- return;
+ this.previewEl.dom.innerHTML = '';
+
+ var canvasEl = document.createElement("canvas");
+
+ var contextEl = canvasEl.getContext("2d");
+
+ canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+ canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+ var center = this.imageEl.OriginWidth / 2;
+
+ if(this.imageEl.OriginWidth < this.imageEl.OriginHeight){
+ canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+ canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+ center = this.imageEl.OriginHeight / 2;
}
- this.hidden = true;
+ contextEl.scale(this.getScaleLevel(), this.getScaleLevel());
- this.triggerEl = this.el.select('button.dropdown-toggle', true).first();
- this.triggerEl.on('click', this.onTriggerPress, this);
+ contextEl.translate(center, center);
+ contextEl.rotate(this.rotate * Math.PI / 180);
+
+ contextEl.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
- this.buttonEl = this.el.select('button.dropdown-button', true).first();
- this.buttonEl.on('click', this.onClick, this);
+ this.canvasEl = document.createElement("canvas");
- },
-
- list : function()
- {
- if(this.isSubMenu){
- return this.el;
+ this.contextEl = this.canvasEl.getContext("2d");
+
+ switch (this.rotate) {
+ case 0 :
+
+ this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+ this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+
+ this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+
+ break;
+ case 90 :
+
+ this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+ this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+
+ if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+ this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+ break;
+ }
+
+ this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+
+ break;
+ case 180 :
+
+ this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+ this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+
+ if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+ this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+ break;
+ }
+
+ this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+
+ break;
+ case 270 :
+
+ this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+ this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+
+ if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+ this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+ break;
+ }
+
+ this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+
+ break;
+ default :
+ break;
}
- return this.el.select('ul.dropdown-menu', true).first();
+ this.previewEl.appendChild(this.canvasEl);
+
+ this.setCanvasPosition();
},
- onClick : function(e)
+ crop : function()
{
- this.fireEvent("click", this, e);
- },
-
- onTriggerPress : function(e)
- {
- if (this.isVisible()) {
- this.hide();
- } else {
- this.show();
+ if(!this.canvasLoaded){
+ return;
}
- },
-
- isVisible : function(){
- return !this.hidden;
- },
-
- show : function()
- {
- this.fireEvent("beforeshow", this);
- this.hidden = false;
- this.el.addClass('open');
+ var imageCanvas = document.createElement("canvas");
- Roo.get(document).on("mouseup", this.onMouseUp, this);
+ var imageContext = imageCanvas.getContext("2d");
- this.fireEvent("show", this);
+ imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+ imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight;
+ var center = imageCanvas.width / 2;
- },
-
- hide : function()
- {
- this.fireEvent("beforehide", this);
+ imageContext.translate(center, center);
- this.hidden = true;
- this.el.removeClass('open');
+ imageContext.rotate(this.rotate * Math.PI / 180);
- Roo.get(document).un("mouseup", this.onMouseUp);
+ imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
- this.fireEvent("hide", this);
- },
-
- onMouseUp : function()
- {
- this.hide();
- }
-
-});
+ var canvas = document.createElement("canvas");
+
+ var context = canvas.getContext("2d");
+
+ canvas.width = this.minWidth;
+ canvas.height = this.minHeight;
-
- /*
- * - LGPL
- *
- * menu item
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
+ switch (this.rotate) {
+ case 0 :
+
+ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+
+ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+
+ var targetWidth = this.minWidth - 2 * x;
+ var targetHeight = this.minHeight - 2 * y;
+
+ var scale = 1;
+
+ if((x == 0 && y == 0) || (x == 0 && y > 0)){
+ scale = targetWidth / width;
+ }
+
+ if(x > 0 && y == 0){
+ scale = targetHeight / height;
+ }
+
+ if(x > 0 && y > 0){
+ scale = targetWidth / width;
+
+ if(width < height){
+ scale = targetHeight / height;
+ }
+ }
+
+ context.scale(scale, scale);
+
+ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
-/**
- * @class Roo.bootstrap.menu.Item
- * @extends Roo.bootstrap.Component
- * Bootstrap MenuItem class
- * @cfg {Boolean} submenu (true | false) default false
- * @cfg {String} html text of the item
- * @cfg {String} href the link
- * @cfg {Boolean} disable (true | false) default false
- * @cfg {Boolean} preventDefault (true | false) default true
- * @cfg {String} icon Font awesome icon
- * @cfg {String} pos Submenu align to (left | right) default right
- *
- *
- * @constructor
- * Create a new Item
- * @param {Object} config The config object
- */
+ sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+ sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+
+ break;
+ case 90 :
+
+ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+
+ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+
+ var targetWidth = this.minWidth - 2 * x;
+ var targetHeight = this.minHeight - 2 * y;
+
+ var scale = 1;
+
+ if((x == 0 && y == 0) || (x == 0 && y > 0)){
+ scale = targetWidth / width;
+ }
+
+ if(x > 0 && y == 0){
+ scale = targetHeight / height;
+ }
+
+ if(x > 0 && y > 0){
+ scale = targetWidth / width;
+
+ if(width < height){
+ scale = targetHeight / height;
+ }
+ }
+
+ context.scale(scale, scale);
+
+ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+
+ sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+ sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+
+ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+
+ break;
+ case 180 :
+
+ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel());
+ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel());
+
+ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+
+ var targetWidth = this.minWidth - 2 * x;
+ var targetHeight = this.minHeight - 2 * y;
+
+ var scale = 1;
+
+ if((x == 0 && y == 0) || (x == 0 && y > 0)){
+ scale = targetWidth / width;
+ }
+
+ if(x > 0 && y == 0){
+ scale = targetHeight / height;
+ }
+
+ if(x > 0 && y > 0){
+ scale = targetWidth / width;
+
+ if(width < height){
+ scale = targetHeight / height;
+ }
+ }
+
+ context.scale(scale, scale);
+
+ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
+ sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+ sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
-Roo.bootstrap.menu.Item = function(config){
- Roo.bootstrap.menu.Item.superclass.constructor.call(this, config);
- this.addEvents({
- /**
- * @event mouseover
- * Fires when the mouse is hovering over this menu
- * @param {Roo.bootstrap.menu.Item} this
- * @param {Roo.EventObject} e
- */
- mouseover : true,
- /**
- * @event mouseout
- * Fires when the mouse exits this menu
- * @param {Roo.bootstrap.menu.Item} this
- * @param {Roo.EventObject} e
- */
- mouseout : true,
- // raw events
- /**
- * @event click
- * The raw click event for the entire grid.
- * @param {Roo.EventObject} e
- */
- click : true
- });
-};
+ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0;
+
+ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+
+ break;
+ case 270 :
+
+ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel());
+ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel());
+
+ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel());
+ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel());
+
+ var targetWidth = this.minWidth - 2 * x;
+ var targetHeight = this.minHeight - 2 * y;
+
+ var scale = 1;
+
+ if((x == 0 && y == 0) || (x == 0 && y > 0)){
+ scale = targetWidth / width;
+ }
+
+ if(x > 0 && y == 0){
+ scale = targetHeight / height;
+ }
+
+ if(x > 0 && y > 0){
+ scale = targetWidth / width;
+
+ if(width < height){
+ scale = targetHeight / height;
+ }
+ }
+
+ context.scale(scale, scale);
+
+ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true));
+ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true));
-Roo.extend(Roo.bootstrap.menu.Item, Roo.bootstrap.Component, {
-
- submenu : false,
- href : '',
- html : '',
- preventDefault: true,
- disable : false,
- icon : false,
- pos : 'right',
+ sx = sx < 0 ? 0 : (sx / this.getScaleLevel());
+ sy = sy < 0 ? 0 : (sy / this.getScaleLevel());
+
+ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight);
+
+ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height);
+
+ break;
+ default :
+ break;
+ }
+
+ this.cropData = canvas.toDataURL(this.cropType);
+
+ this.fireEvent('crop', this, this.cropData);
+
+ },
- getAutoCreate : function()
+ setThumbBoxSize : function()
{
- var text = [
- {
- tag : 'span',
- cls : 'roo-menu-item-text',
- html : this.html
- }
- ];
+ var width, height;
- if(this.icon){
- text.unshift({
- tag : 'i',
- cls : 'fa ' + this.icon
- })
+ if(this.isDocument && typeof(this.imageEl) != 'undefined'){
+ width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight);
+ height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight);
+
+ this.minWidth = width;
+ this.minHeight = height;
+
+ if(this.rotate == 90 || this.rotate == 270){
+ this.minWidth = height;
+ this.minHeight = width;
+ }
}
- var cfg = {
- tag : 'li',
- cn : [
- {
- tag : 'a',
- href : this.href || '#',
- cn : text
- }
- ]
- };
+ height = 300;
+ width = Math.ceil(this.minWidth * height / this.minHeight);
- if(this.disable){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'disabled' : (cfg.cls + ' disabled');
+ if(this.minWidth > this.minHeight){
+ width = 300;
+ height = Math.ceil(this.minHeight * width / this.minWidth);
}
- if(this.submenu){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'dropdown-submenu' : (cfg.cls + ' dropdown-submenu');
+ this.thumbEl.setStyle({
+ width : width + 'px',
+ height : height + 'px'
+ });
+
+ return;
- if(this.pos == 'left'){
- cfg.cls = (typeof(cfg.cls) == 'undefined') ? 'pull-left' : (cfg.cls + ' pull-left');
- }
- }
-
- return cfg;
},
- initEvents : function()
+ setThumbBoxPosition : function()
{
- this.el.on('mouseover', this.onMouseOver, this);
- this.el.on('mouseout', this.onMouseOut, this);
+ var x = Math.ceil((this.bodyEl.getWidth() - this.thumbEl.getWidth()) / 2 );
+ var y = Math.ceil((this.bodyEl.getHeight() - this.thumbEl.getHeight()) / 2);
- this.el.select('a', true).first().on('click', this.onClick, this);
+ this.thumbEl.setLeft(x);
+ this.thumbEl.setTop(y);
},
- onClick : function(e)
+ baseRotateLevel : function()
{
- if(this.preventDefault){
- e.preventDefault();
- }
+ this.baseRotate = 1;
- this.fireEvent("click", this, e);
- },
-
- onMouseOver : function(e)
- {
- if(this.submenu && this.pos == 'left'){
- this.el.select('ul.dropdown-menu', true).first().setLeft(this.el.select('ul.dropdown-menu', true).first().getWidth() * -1);
+ if(
+ typeof(this.exif) != 'undefined' &&
+ typeof(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != 'undefined' &&
+ [1, 3, 6, 8].indexOf(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != -1
+ ){
+ this.baseRotate = this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']];
}
- this.fireEvent("mouseover", this, e);
+ this.rotate = Roo.bootstrap.UploadCropbox['Orientation'][this.baseRotate];
+
},
- onMouseOut : function(e)
+ baseScaleLevel : function()
{
- this.fireEvent("mouseout", this, e);
- }
-});
-
-
-
- /*
- * - LGPL
- *
- * menu separator
- *
- */
-Roo.bootstrap.menu = Roo.bootstrap.menu || {};
-
-/**
- * @class Roo.bootstrap.menu.Separator
- * @extends Roo.bootstrap.Component
- * Bootstrap Separator class
- *
- * @constructor
- * Create a new Separator
- * @param {Object} config The config object
- */
-
-
-Roo.bootstrap.menu.Separator = function(config){
- Roo.bootstrap.menu.Separator.superclass.constructor.call(this, config);
-};
-
-Roo.extend(Roo.bootstrap.menu.Separator, Roo.bootstrap.Component, {
-
- getAutoCreate : function(){
- var cfg = {
- tag : 'li',
- cls: 'divider'
- };
+ var width, height;
- return cfg;
- }
-
-});
+ if(this.isDocument){
+
+ if(this.baseRotate == 6 || this.baseRotate == 8){
+
+ height = this.thumbEl.getHeight();
+ this.baseScale = height / this.imageEl.OriginWidth;
-
+ if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){
+ width = this.thumbEl.getWidth();
+ this.baseScale = width / this.imageEl.OriginHeight;
+ }
- /*
- * - LGPL
- *
- * Tooltip
- *
- */
+ return;
+ }
-/**
- * @class Roo.bootstrap.Tooltip
- * Bootstrap Tooltip class
- * This is basic at present - all componets support it by default, however they should add tooltipEl() method
- * to determine which dom element triggers the tooltip.
- *
- * It needs to add support for additional attributes like tooltip-position
- *
- * @constructor
- * Create a new Toolti
- * @param {Object} config The config object
- */
+ height = this.thumbEl.getHeight();
+ this.baseScale = height / this.imageEl.OriginHeight;
-Roo.bootstrap.Tooltip = function(config){
- Roo.bootstrap.Tooltip.superclass.constructor.call(this, config);
-};
+ if(this.imageEl.OriginWidth * this.baseScale > this.thumbEl.getWidth()){
+ width = this.thumbEl.getWidth();
+ this.baseScale = width / this.imageEl.OriginWidth;
+ }
-Roo.apply(Roo.bootstrap.Tooltip, {
- /**
- * @function init initialize tooltip monitoring.
- * @static
- */
- currentEl : false,
- currentTip : false,
- currentRegion : false,
-
- // init : delay?
+ return;
+ }
+
+ if(this.baseRotate == 6 || this.baseRotate == 8){
+
+ width = this.thumbEl.getHeight();
+ this.baseScale = width / this.imageEl.OriginHeight;
+
+ if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getWidth()){
+ height = this.thumbEl.getWidth();
+ this.baseScale = height / this.imageEl.OriginHeight;
+ }
+
+ if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+ height = this.thumbEl.getWidth();
+ this.baseScale = height / this.imageEl.OriginHeight;
+
+ if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getHeight()){
+ width = this.thumbEl.getHeight();
+ this.baseScale = width / this.imageEl.OriginWidth;
+ }
+ }
+
+ return;
+ }
+
+ width = this.thumbEl.getWidth();
+ this.baseScale = width / this.imageEl.OriginWidth;
+
+ if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getHeight()){
+ height = this.thumbEl.getHeight();
+ this.baseScale = height / this.imageEl.OriginHeight;
+ }
+
+ if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+
+ height = this.thumbEl.getHeight();
+ this.baseScale = height / this.imageEl.OriginHeight;
+
+ if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getWidth()){
+ width = this.thumbEl.getWidth();
+ this.baseScale = width / this.imageEl.OriginWidth;
+ }
+
+ }
+
+ return;
+ },
- init : function()
+ getScaleLevel : function()
{
- Roo.get(document).on('mouseover', this.enter ,this);
- Roo.get(document).on('mouseout', this.leave, this);
-
-
- this.currentTip = new Roo.bootstrap.Tooltip();
+ return this.baseScale * Math.pow(1.1, this.scale);
},
- enter : function(ev)
+ onTouchStart : function(e)
{
- var dom = ev.getTarget();
-
- //Roo.log(['enter',dom]);
- var el = Roo.fly(dom);
- if (this.currentEl) {
- //Roo.log(dom);
- //Roo.log(this.currentEl);
- //Roo.log(this.currentEl.contains(dom));
- if (this.currentEl == el) {
- return;
- }
- if (dom != this.currentEl.dom && this.currentEl.contains(dom)) {
- return;
- }
-
+ if(!this.canvasLoaded){
+ this.beforeSelectFile(e);
+ return;
}
+ var touches = e.browserEvent.touches;
+ if(!touches){
+ return;
+ }
- if (this.currentTip.el) {
- this.currentTip.el.hide(); // force hiding...
- }
- //Roo.log(ev);
- var bindEl = el;
+ if(touches.length == 1){
+ this.onMouseDown(e);
+ return;
+ }
- // you can not look for children, as if el is the body.. then everythign is the child..
- if (!el.attr('tooltip')) { //
- if (!el.select("[tooltip]").elements.length) {
- return;
- }
- // is the mouse over this child...?
- bindEl = el.select("[tooltip]").first();
- var xy = ev.getXY();
- if (!bindEl.getRegion().contains( { top : xy[1] ,right : xy[0] , bottom : xy[1], left : xy[0]})) {
- //Roo.log("not in region.");
- return;
- }
- //Roo.log("child element over..");
-
+ if(touches.length != 2){
+ return;
+ }
+
+ var coords = [];
+
+ for(var i = 0, finger; finger = touches[i]; i++){
+ coords.push(finger.pageX, finger.pageY);
}
- this.currentEl = bindEl;
- this.currentTip.bind(bindEl);
- this.currentRegion = Roo.lib.Region.getRegion(dom);
- this.currentTip.enter();
+
+ var x = Math.pow(coords[0] - coords[2], 2);
+ var y = Math.pow(coords[1] - coords[3], 2);
+
+ this.startDistance = Math.sqrt(x + y);
+
+ this.startScale = this.scale;
+
+ this.pinching = true;
+ this.dragable = false;
},
- leave : function(ev)
+
+ onTouchMove : function(e)
{
- var dom = ev.getTarget();
- //Roo.log(['leave',dom]);
- if (!this.currentEl) {
+ if(!this.pinching && !this.dragable){
return;
}
+ var touches = e.browserEvent.touches;
- if (dom != this.currentEl.dom) {
+ if(!touches){
return;
}
- var xy = ev.getXY();
- if (this.currentRegion.contains( new Roo.lib.Region( xy[1], xy[0] ,xy[1], xy[0] ))) {
+
+ if(this.dragable){
+ this.onMouseMove(e);
return;
}
- // only activate leave if mouse cursor is outside... bounding box..
+ var coords = [];
+ for(var i = 0, finger; finger = touches[i]; i++){
+ coords.push(finger.pageX, finger.pageY);
+ }
+ var x = Math.pow(coords[0] - coords[2], 2);
+ var y = Math.pow(coords[1] - coords[3], 2);
- if (this.currentTip) {
- this.currentTip.leave();
+ this.endDistance = Math.sqrt(x + y);
+
+ this.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
+
+ if(!this.zoomable()){
+ this.scale = this.startScale;
+ return;
}
- //Roo.log('clear currentEl');
- this.currentEl = false;
+ this.draw();
},
- alignment : {
- 'left' : ['r-l', [-2,0], 'right'],
- 'right' : ['l-r', [2,0], 'left'],
- 'bottom' : ['t-b', [0,2], 'top'],
- 'top' : [ 'b-t', [0,-2], 'bottom']
- }
-
-});
-
-
-Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, {
-
-
- bindEl : false,
-
- delay : null, // can be { show : 300 , hide: 500}
-
- timeout : null,
- hoverState : null, //???
-
- placement : 'bottom',
-
- getAutoCreate : function(){
-
- var cfg = {
- cls : 'tooltip',
- role : 'tooltip',
- cn : [
- {
- cls : 'tooltip-arrow'
- },
- {
- cls : 'tooltip-inner'
- }
- ]
- };
-
- return cfg;
- },
- bind : function(el)
+ onTouchEnd : function(e)
{
- this.bindEl = el;
+ this.pinching = false;
+ this.dragable = false;
+
},
-
- enter : function () {
-
- if (this.timeout != null) {
- clearTimeout(this.timeout);
+ prepare : function(file)
+ {
+ this.file = false;
+ this.exif = {};
+
+ if(typeof(file) === 'string'){
+ this.loadCanvas(file);
+ return;
}
- this.hoverState = 'in';
- //Roo.log("enter - show");
- if (!this.delay || !this.delay.show) {
- this.show();
+ if(!file || !this.urlAPI){
return;
}
- var _t = this;
- this.timeout = setTimeout(function () {
- if (_t.hoverState == 'in') {
- _t.show();
+
+ this.file = file;
+ this.cropType = file.type;
+
+ var _this = this;
+
+ if(this.fireEvent('prepare', this, this.file) != false){
+
+ var reader = new FileReader();
+
+ reader.onload = function (e) {
+ if (e.target.error) {
+ Roo.log(e.target.error);
+ return;
+ }
+
+ var buffer = e.target.result,
+ dataView = new DataView(buffer),
+ offset = 2,
+ maxOffset = dataView.byteLength - 4,
+ markerBytes,
+ markerLength;
+
+ if (dataView.getUint16(0) === 0xffd8) {
+ while (offset < maxOffset) {
+ markerBytes = dataView.getUint16(offset);
+
+ if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || markerBytes === 0xfffe) {
+ markerLength = dataView.getUint16(offset + 2) + 2;
+ if (offset + markerLength > dataView.byteLength) {
+ Roo.log('Invalid meta data: Invalid segment size.');
+ break;
+ }
+
+ if(markerBytes == 0xffe1){
+ _this.parseExifData(
+ dataView,
+ offset,
+ markerLength
+ );
+ }
+
+ offset += markerLength;
+
+ continue;
+ }
+
+ break;
+ }
+
+ }
+
+ var url = _this.urlAPI.createObjectURL(_this.file);
+
+ _this.loadCanvas(url);
+
+ return;
}
- }, this.delay.show);
+
+ reader.readAsArrayBuffer(this.file);
+
+ }
+
},
- leave : function()
+
+ parseExifData : function(dataView, offset, length)
{
- clearTimeout(this.timeout);
+ var tiffOffset = offset + 10,
+ littleEndian,
+ dirOffset;
- this.hoverState = 'out';
- if (!this.delay || !this.delay.hide) {
- this.hide();
+ if (dataView.getUint32(offset + 4) !== 0x45786966) {
+ // No Exif data, might be XMP data instead
return;
}
-
- var _t = this;
- this.timeout = setTimeout(function () {
- //Roo.log("leave - timeout");
-
- if (_t.hoverState == 'out') {
- _t.hide();
- Roo.bootstrap.Tooltip.currentEl = false;
- }
- }, delay);
+
+ // Check for the ASCII code for "Exif" (0x45786966):
+ if (dataView.getUint32(offset + 4) !== 0x45786966) {
+ // No Exif data, might be XMP data instead
+ return;
+ }
+ if (tiffOffset + 8 > dataView.byteLength) {
+ Roo.log('Invalid Exif data: Invalid segment size.');
+ return;
+ }
+ // Check for the two null bytes:
+ if (dataView.getUint16(offset + 8) !== 0x0000) {
+ Roo.log('Invalid Exif data: Missing byte alignment offset.');
+ return;
+ }
+ // Check the byte alignment:
+ switch (dataView.getUint16(tiffOffset)) {
+ case 0x4949:
+ littleEndian = true;
+ break;
+ case 0x4D4D:
+ littleEndian = false;
+ break;
+ default:
+ Roo.log('Invalid Exif data: Invalid byte alignment marker.');
+ return;
+ }
+ // Check for the TIFF tag marker (0x002A):
+ if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
+ Roo.log('Invalid Exif data: Missing TIFF marker.');
+ return;
+ }
+ // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
+ dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
+
+ this.parseExifTags(
+ dataView,
+ tiffOffset,
+ tiffOffset + dirOffset,
+ littleEndian
+ );
},
- show : function ()
+ parseExifTags : function(dataView, tiffOffset, dirOffset, littleEndian)
{
- if (!this.el) {
- this.render(document.body);
+ var tagsNumber,
+ dirEndOffset,
+ i;
+ if (dirOffset + 6 > dataView.byteLength) {
+ Roo.log('Invalid Exif data: Invalid directory offset.');
+ return;
}
- // set content.
- //Roo.log([this.bindEl, this.bindEl.attr('tooltip')]);
-
- var tip = this.bindEl.attr('tooltip') || this.bindEl.select("[tooltip]").first().attr('tooltip');
-
- this.el.select('.tooltip-inner',true).first().dom.innerHTML = tip;
-
- this.el.removeClass(['fade','top','bottom', 'left', 'right','in']);
-
- var placement = typeof this.placement == 'function' ?
- this.placement.call(this, this.el, on_el) :
- this.placement;
-
- var autoToken = /\s?auto?\s?/i;
- var autoPlace = autoToken.test(placement);
- if (autoPlace) {
- placement = placement.replace(autoToken, '') || 'top';
+ tagsNumber = dataView.getUint16(dirOffset, littleEndian);
+ dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
+ if (dirEndOffset + 4 > dataView.byteLength) {
+ Roo.log('Invalid Exif data: Invalid directory size.');
+ return;
}
-
- //this.el.detach()
- //this.el.setXY([0,0]);
- this.el.show();
- //this.el.dom.style.display='block';
- this.el.addClass(placement);
-
- //this.el.appendTo(on_el);
-
- var p = this.getPosition();
- var box = this.el.getBox();
-
- if (autoPlace) {
- // fixme..
+ for (i = 0; i < tagsNumber; i += 1) {
+ this.parseExifTag(
+ dataView,
+ tiffOffset,
+ dirOffset + 2 + 12 * i, // tag offset
+ littleEndian
+ );
}
- var align = Roo.bootstrap.Tooltip.alignment[placement];
- this.el.alignTo(this.bindEl, align[0],align[1]);
- //var arrow = this.el.select('.arrow',true).first();
- //arrow.set(align[2],
+ // Return the offset to the next directory:
+ return dataView.getUint32(dirEndOffset, littleEndian);
+ },
+
+ parseExifTag : function (dataView, tiffOffset, offset, littleEndian)
+ {
+ var tag = dataView.getUint16(offset, littleEndian);
- this.el.addClass('in fade');
- this.hoverState = null;
+ this.exif[tag] = this.getExifValue(
+ dataView,
+ tiffOffset,
+ offset,
+ dataView.getUint16(offset + 2, littleEndian), // tag type
+ dataView.getUint32(offset + 4, littleEndian), // tag length
+ littleEndian
+ );
+ },
+
+ getExifValue : function (dataView, tiffOffset, offset, type, length, littleEndian)
+ {
+ var tagType = Roo.bootstrap.UploadCropbox.exifTagTypes[type],
+ tagSize,
+ dataOffset,
+ values,
+ i,
+ str,
+ c;
+
+ if (!tagType) {
+ Roo.log('Invalid Exif data: Invalid tag type.');
+ return;
+ }
- if (this.el.hasClass('fade')) {
- // fade it?
+ tagSize = tagType.size * length;
+ // Determine if the value is contained in the dataOffset bytes,
+ // or if the value at the dataOffset is a pointer to the actual data:
+ dataOffset = tagSize > 4 ?
+ tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
+ if (dataOffset + tagSize > dataView.byteLength) {
+ Roo.log('Invalid Exif data: Invalid data offset.');
+ return;
+ }
+ if (length === 1) {
+ return tagType.getValue(dataView, dataOffset, littleEndian);
+ }
+ values = [];
+ for (i = 0; i < length; i += 1) {
+ values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
}
+ if (tagType.ascii) {
+ str = '';
+ // Concatenate the chars:
+ for (i = 0; i < values.length; i += 1) {
+ c = values[i];
+ // Ignore the terminating NULL byte(s):
+ if (c === '\u0000') {
+ break;
+ }
+ str += c;
+ }
+ return str;
+ }
+ return values;
+ }
+
+});
+
+Roo.apply(Roo.bootstrap.UploadCropbox, {
+ tags : {
+ 'Orientation': 0x0112
},
- hide : function()
- {
-
- if (!this.el) {
- return;
+
+ Orientation: {
+ 1: 0, //'top-left',
+// 2: 'top-right',
+ 3: 180, //'bottom-right',
+// 4: 'bottom-left',
+// 5: 'left-top',
+ 6: 90, //'right-top',
+// 7: 'right-bottom',
+ 8: 270 //'left-bottom'
+ },
+
+ exifTagTypes : {
+ // byte, 8-bit unsigned int:
+ 1: {
+ getValue: function (dataView, dataOffset) {
+ return dataView.getUint8(dataOffset);
+ },
+ size: 1
+ },
+ // ascii, 8-bit byte:
+ 2: {
+ getValue: function (dataView, dataOffset) {
+ return String.fromCharCode(dataView.getUint8(dataOffset));
+ },
+ size: 1,
+ ascii: true
+ },
+ // short, 16 bit int:
+ 3: {
+ getValue: function (dataView, dataOffset, littleEndian) {
+ return dataView.getUint16(dataOffset, littleEndian);
+ },
+ size: 2
+ },
+ // long, 32 bit int:
+ 4: {
+ getValue: function (dataView, dataOffset, littleEndian) {
+ return dataView.getUint32(dataOffset, littleEndian);
+ },
+ size: 4
+ },
+ // rational = two long values, first is numerator, second is denominator:
+ 5: {
+ getValue: function (dataView, dataOffset, littleEndian) {
+ return dataView.getUint32(dataOffset, littleEndian) /
+ dataView.getUint32(dataOffset + 4, littleEndian);
+ },
+ size: 8
+ },
+ // slong, 32 bit signed int:
+ 9: {
+ getValue: function (dataView, dataOffset, littleEndian) {
+ return dataView.getInt32(dataOffset, littleEndian);
+ },
+ size: 4
+ },
+ // srational, two slongs, first is numerator, second is denominator:
+ 10: {
+ getValue: function (dataView, dataOffset, littleEndian) {
+ return dataView.getInt32(dataOffset, littleEndian) /
+ dataView.getInt32(dataOffset + 4, littleEndian);
+ },
+ size: 8
}
- //this.el.setXY([0,0]);
- this.el.removeClass('in');
- //this.el.hide();
-
- }
+ },
+ footer : {
+ STANDARD : [
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-left',
+ action : 'rotate-left',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-picture',
+ action : 'picture',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-picture-o"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ],
+ DOCUMENT : [
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-left',
+ action : 'rotate-left',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-download',
+ action : 'download',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-download"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-crop',
+ action : 'crop',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-crop"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-trash',
+ action : 'trash',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-trash"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ],
+ ROTATOR : [
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-left',
+ action : 'rotate-left',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ]
+ }
});
-
- /*
- * - LGPL
- *
- * Location Picker
- *
- */
+/*
+* Licence: LGPL
+*/
/**
- * @class Roo.bootstrap.LocationPicker
+ * @class Roo.bootstrap.DocumentManager
* @extends Roo.bootstrap.Component
- * Bootstrap LocationPicker class
- * @cfg {Number} latitude Position when init default 0
- * @cfg {Number} longitude Position when init default 0
- * @cfg {Number} zoom default 15
- * @cfg {String} mapTypeId default google.maps.MapTypeId.ROADMAP
- * @cfg {Boolean} mapTypeControl default false
- * @cfg {Boolean} disableDoubleClickZoom default false
- * @cfg {Boolean} scrollwheel default true
- * @cfg {Boolean} streetViewControl default false
- * @cfg {Number} radius default 0
- * @cfg {String} locationName
- * @cfg {Boolean} draggable default true
- * @cfg {Boolean} enableAutocomplete default false
- * @cfg {Boolean} enableReverseGeocode default true
- * @cfg {String} markerTitle
+ * Bootstrap DocumentManager class
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * @cfg {String} url action url
+ * @cfg {Number} boxes number of boxes default 12
+ * @cfg {Boolean} multiple multiple upload default true
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Number} thumbSize default 300
+ * @cfg {String} fieldLabel
+ * @cfg {Number} labelWidth default 4
+ * @cfg {String} labelAlign (left|top) default left
+ * @cfg {Boolean} editable (true|false) allow edit when upload a image default true
*
* @constructor
- * Create a new LocationPicker
+ * Create a new DocumentManager
* @param {Object} config The config object
*/
-
-Roo.bootstrap.LocationPicker = function(config){
-
- Roo.bootstrap.LocationPicker.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentManager = function(config){
+ Roo.bootstrap.DocumentManager.superclass.constructor.call(this, config);
this.addEvents({
/**
* @event initial
- * Fires when the picker initialized.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Google Location} location
- */
- initial : true,
- /**
- * @event positionchanged
- * Fires when the picker position changed.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Google Location} location
- */
- positionchanged : true,
- /**
- * @event resize
- * Fires when the map resize.
- * @param {Roo.bootstrap.LocationPicker} this
- */
- resize : true,
- /**
- * @event show
- * Fires when the map show.
- * @param {Roo.bootstrap.LocationPicker} this
- */
- show : true,
- /**
- * @event hide
- * Fires when the map hide.
- * @param {Roo.bootstrap.LocationPicker} this
- */
- hide : true,
- /**
- * @event mapClick
- * Fires when click the map.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Map event} e
+ * Fire when initial the DocumentManager
+ * @param {Roo.bootstrap.DocumentManager} this
*/
- mapClick : true,
- /**
- * @event mapRightClick
- * Fires when right click the map.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Map event} e
- */
- mapRightClick : true,
+ "initial" : true,
/**
- * @event markerClick
- * Fires when click the marker.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Map event} e
+ * @event inspect
+ * inspect selected file
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {File} file
*/
- markerClick : true,
+ "inspect" : true,
/**
- * @event markerRightClick
- * Fires when right click the marker.
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Map event} e
+ * @event exception
+ * Fire when xhr load exception
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {XMLHttpRequest} xhr
*/
- markerRightClick : true,
+ "exception" : true,
/**
- * @event OverlayViewDraw
- * Fires when OverlayView Draw
- * @param {Roo.bootstrap.LocationPicker} this
+ * @event prepare
+ * prepare the form data
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {Object} formData
*/
- OverlayViewDraw : true,
+ "prepare" : true,
/**
- * @event OverlayViewOnAdd
- * Fires when OverlayView Draw
- * @param {Roo.bootstrap.LocationPicker} this
+ * @event remove
+ * Fire when remove the file
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {Object} file
*/
- OverlayViewOnAdd : true,
+ "remove" : true,
/**
- * @event OverlayViewOnRemove
- * Fires when OverlayView Draw
- * @param {Roo.bootstrap.LocationPicker} this
+ * @event refresh
+ * Fire after refresh the file
+ * @param {Roo.bootstrap.DocumentManager} this
*/
- OverlayViewOnRemove : true,
+ "refresh" : true,
/**
- * @event OverlayViewShow
- * Fires when OverlayView Draw
- * @param {Roo.bootstrap.LocationPicker} this
- * @param {Pixel} cpx
+ * @event click
+ * Fire after click the image
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {Object} file
*/
- OverlayViewShow : true,
+ "click" : true,
/**
- * @event OverlayViewHide
- * Fires when OverlayView Draw
- * @param {Roo.bootstrap.LocationPicker} this
+ * @event edit
+ * Fire when upload a image and editable set to true
+ * @param {Roo.bootstrap.DocumentManager} this
+ * @param {Object} file
*/
- OverlayViewHide : true
- });
+ "edit" : true
+ });
};
-Roo.extend(Roo.bootstrap.LocationPicker, Roo.bootstrap.Component, {
-
- gMapContext: false,
+Roo.extend(Roo.bootstrap.DocumentManager, Roo.bootstrap.Component, {
- latitude: 0,
- longitude: 0,
- zoom: 15,
- mapTypeId: false,
- mapTypeControl: false,
- disableDoubleClickZoom: false,
- scrollwheel: true,
- streetViewControl: false,
- radius: 0,
- locationName: '',
- draggable: true,
- enableAutocomplete: false,
- enableReverseGeocode: true,
- markerTitle: '',
+ boxes : 12,
+ inputName : '',
+ minWidth : 300,
+ minHeight : 300,
+ thumbSize : 300,
+ multiple : true,
+ files : [],
+ method : 'POST',
+ url : '',
+ paramName : 'imageUpload',
+ fieldLabel : '',
+ labelWidth : 4,
+ labelAlign : 'left',
+ editable : true,
+ delegates : [],
- getAutoCreate: function()
- {
+ getAutoCreate : function()
+ {
+ var managerWidget = {
+ tag : 'div',
+ cls : 'roo-document-manager',
+ cn : [
+ {
+ tag : 'input',
+ cls : 'roo-document-manager-selector',
+ type : 'file'
+ },
+ {
+ tag : 'div',
+ cls : 'roo-document-manager-uploader',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'roo-document-manager-upload-btn',
+ html : '<i class="fa fa-plus"></i>'
+ }
+ ]
+
+ }
+ ]
+ };
+
+ var content = [
+ {
+ tag : 'div',
+ cls : 'column col-md-12',
+ cn : managerWidget
+ }
+ ];
+
+ if(this.fieldLabel.length){
+
+ content = [
+ {
+ tag : 'div',
+ cls : 'column col-md-12',
+ html : this.fieldLabel
+ },
+ {
+ tag : 'div',
+ cls : 'column col-md-12',
+ cn : managerWidget
+ }
+ ];
+ if(this.labelAlign == 'left'){
+ content = [
+ {
+ tag : 'div',
+ cls : 'column col-md-' + this.labelWidth,
+ html : this.fieldLabel
+ },
+ {
+ tag : 'div',
+ cls : 'column col-md-' + (12 - this.labelWidth),
+ cn : managerWidget
+ }
+ ];
+
+ }
+ }
+
var cfg = {
- tag: 'div',
- cls: 'roo-location-picker'
+ tag : 'div',
+ cls : 'row clearfix',
+ cn : content
};
- return cfg
- },
-
- initEvents: function(ct, position)
- {
- if(!this.el.getWidth() || this.isApplied()){
- return;
- }
-
- this.el.setVisibilityMode(Roo.Element.DISPLAY);
+ return cfg;
- this.initial();
},
- initial: function()
+ initEvents : function()
{
- if(!this.mapTypeId){
- this.mapTypeId = google.maps.MapTypeId.ROADMAP;
+ this.managerEl = this.el.select('.roo-document-manager', true).first();
+ this.managerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.selectorEl = this.el.select('.roo-document-manager-selector', true).first();
+ this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.selectorEl.hide();
+
+ if(this.multiple){
+ this.selectorEl.attr('multiple', 'multiple');
}
- this.gMapContext = this.GMapContext();
+ this.selectorEl.on('change', this.onFileSelected, this);
- this.initOverlayView();
+ this.uploader = this.el.select('.roo-document-manager-uploader', true).first();
+ this.uploader.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
- this.OverlayView = new Roo.bootstrap.LocationPicker.OverlayView(this.gMapContext.map);
+ this.uploader.on('click', this.onUploaderClick, this);
+
+ this.renderProgressDialog();
var _this = this;
-
- google.maps.event.addListener(this.gMapContext.marker, "dragend", function(event) {
- _this.setPosition(_this.gMapContext.marker.position);
- });
- google.maps.event.addListener(this.gMapContext.map, 'click', function(event){
- _this.fireEvent('mapClick', this, event);
-
+ window.addEventListener("resize", function() { _this.refresh(); } );
+
+ this.fireEvent('initial', this);
+ },
+
+ renderProgressDialog : function()
+ {
+ var _this = this;
+
+ this.progressDialog = new Roo.bootstrap.Modal({
+ cls : 'roo-document-manager-progress-dialog',
+ allow_close : false,
+ title : '',
+ buttons : [
+ {
+ name :'cancel',
+ weight : 'danger',
+ html : 'Cancel'
+ }
+ ],
+ listeners : {
+ btnclick : function() {
+ _this.uploadCancel();
+ this.hide();
+ }
+ }
});
-
- google.maps.event.addListener(this.gMapContext.map, 'rightclick', function(event){
- _this.fireEvent('mapRightClick', this, event);
-
+
+ this.progressDialog.render(Roo.get(document.body));
+
+ this.progress = new Roo.bootstrap.Progress({
+ cls : 'roo-document-manager-progress',
+ active : true,
+ striped : true
});
- google.maps.event.addListener(this.gMapContext.marker, 'click', function(event){
- _this.fireEvent('markerClick', this, event);
-
- });
-
- google.maps.event.addListener(this.gMapContext.marker, 'rightclick', function(event){
- _this.fireEvent('markerRightClick', this, event);
-
+ this.progress.render(this.progressDialog.getChildContainer());
+
+ this.progressBar = new Roo.bootstrap.ProgressBar({
+ cls : 'roo-document-manager-progress-bar',
+ aria_valuenow : 0,
+ aria_valuemin : 0,
+ aria_valuemax : 12,
+ panel : 'success'
});
- this.setPosition(this.gMapContext.location);
+ this.progressBar.render(this.progress.getChildContainer());
+ },
+
+ onUploaderClick : function(e)
+ {
+ e.preventDefault();
+ this.selectorEl.dom.click();
+ },
+
+ onFileSelected : function(e)
+ {
+ e.preventDefault();
+
+ if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+ return;
+ }
+
+ Roo.each(this.selectorEl.dom.files, function(file){
+ if(this.fireEvent('inspect', this, file) != false){
+ this.files.push(file);
+ }
+ }, this);
+
+ this.queue();
- this.fireEvent('initial', this, this.gMapContext.location);
},
- initOverlayView: function()
+ queue : function()
{
+ this.selectorEl.dom.value = '';
+
+ if(!this.files.length){
+ return;
+ }
+
+ if(this.files.length > this.boxes){
+ this.files = this.files.slice(0, this.boxes);
+ }
+
+ this.uploader.show();
+
+ if(this.files.length > this.boxes - 1){
+ this.uploader.hide();
+ }
+
var _this = this;
- Roo.bootstrap.LocationPicker.OverlayView.prototype = Roo.apply(new google.maps.OverlayView(), {
-
- draw: function()
- {
- _this.fireEvent('OverlayViewDraw', _this);
- },
-
- onAdd: function()
- {
- _this.fireEvent('OverlayViewOnAdd', _this);
- },
-
- onRemove: function()
- {
- _this.fireEvent('OverlayViewOnRemove', _this);
- },
-
- show: function(cpx)
- {
- _this.fireEvent('OverlayViewShow', _this, cpx);
- },
+ var files = [];
+
+ Roo.each(this.files, function(file){
- hide: function()
- {
- _this.fireEvent('OverlayViewHide', _this);
+ if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+ var f = this.renderPreview(file);
+ files.push(f);
+ return;
}
- });
+ this.delegates.push(
+ (function(){
+ _this.process(file);
+ }).createDelegate(this)
+ );
+
+ }, this);
+
+ this.files = files;
+
+ if(!this.delegates.length){
+ this.refresh();
+ return;
+ }
+
+ this.progressBar.aria_valuemax = this.delegates.length;
+
+ this.arrange();
+
+ return;
},
- fromLatLngToContainerPixel: function(event)
+ arrange : function()
{
- return this.OverlayView.getProjection().fromLatLngToContainerPixel(event.latLng);
+ if(!this.delegates.length){
+ this.progressDialog.hide();
+ this.refresh();
+ return;
+ }
+
+ var delegate = this.delegates.shift();
+
+ this.progressDialog.show();
+
+ this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
+
+ this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
+
+ delegate();
},
- isApplied: function()
+ refresh : function()
{
- return this.getGmapContext() == false ? false : true;
+ this.uploader.show();
+
+ if(this.files.length > this.boxes - 1){
+ this.uploader.hide();
+ }
+
+ Roo.isTouch ? this.closable(false) : this.closable(true);
+
+ this.fireEvent('refresh', this);
},
- getGmapContext: function()
+ onRemove : function(e, el, o)
{
- return this.gMapContext
+ e.preventDefault();
+
+ this.fireEvent('remove', this, o);
+
},
- GMapContext: function()
+ remove : function(o)
{
- var position = new google.maps.LatLng(this.latitude, this.longitude);
+ var files = [];
- var _map = new google.maps.Map(this.el.dom, {
- center: position,
- zoom: this.zoom,
- mapTypeId: this.mapTypeId,
- mapTypeControl: this.mapTypeControl,
- disableDoubleClickZoom: this.disableDoubleClickZoom,
- scrollwheel: this.scrollwheel,
- streetViewControl: this.streetViewControl,
- locationName: this.locationName,
- draggable: this.draggable,
- enableAutocomplete: this.enableAutocomplete,
- enableReverseGeocode: this.enableReverseGeocode
- });
+ Roo.each(this.files, function(file){
+ if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
+ files.push(file);
+ return;
+ }
+
+ o.target.remove();
+
+ }, this);
- var _marker = new google.maps.Marker({
- position: position,
- map: _map,
- title: this.markerTitle,
- draggable: this.draggable
- });
+ this.files = files;
- return {
- map: _map,
- marker: _marker,
- circle: null,
- location: position,
- radius: this.radius,
- locationName: this.locationName,
- addressComponents: {
- formatted_address: null,
- addressLine1: null,
- addressLine2: null,
- streetName: null,
- streetNumber: null,
- city: null,
- district: null,
- state: null,
- stateOrProvince: null
- },
- settings: this,
- domContainer: this.el.dom,
- geodecoder: new google.maps.Geocoder()
- };
+ this.refresh();
},
- drawCircle: function(center, radius, options)
+ onClick : function(e, el, o)
{
- if (this.gMapContext.circle != null) {
- this.gMapContext.circle.setMap(null);
- }
- if (radius > 0) {
- radius *= 1;
- options = Roo.apply({}, options, {
- strokeColor: "#0000FF",
- strokeOpacity: .35,
- strokeWeight: 2,
- fillColor: "#0000FF",
- fillOpacity: .2
- });
-
- options.map = this.gMapContext.map;
- options.radius = radius;
- options.center = center;
- this.gMapContext.circle = new google.maps.Circle(options);
- return this.gMapContext.circle;
- }
+ e.preventDefault();
+
+ this.fireEvent('click', this, o);
- return null;
},
- setPosition: function(location)
+ closable : function(closable)
{
- this.gMapContext.location = location;
- this.gMapContext.marker.setPosition(location);
- this.gMapContext.map.panTo(location);
- this.drawCircle(location, this.gMapContext.radius, {});
+ Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
+
+ el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ if(closable){
+ el.show();
+ return;
+ }
+
+ el.hide();
+
+ }, this);
+ },
+
+ xhrOnLoad : function(xhr)
+ {
+ Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+ el.remove();
+ }, this);
- var _this = this;
+ if (xhr.readyState !== 4) {
+ this.arrange();
+ this.fireEvent('exception', this, xhr);
+ return;
+ }
+
+ var response = Roo.decode(xhr.responseText);
- if (this.gMapContext.settings.enableReverseGeocode) {
- this.gMapContext.geodecoder.geocode({
- latLng: this.gMapContext.location
- }, function(results, status) {
-
- if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
- _this.gMapContext.locationName = results[0].formatted_address;
- _this.gMapContext.addressComponents = _this.address_component_from_google_geocode(results[0].address_components);
-
- _this.fireEvent('positionchanged', this, location);
- }
- });
-
+ if(!response.success){
+ this.arrange();
+ this.fireEvent('exception', this, xhr);
return;
}
- this.fireEvent('positionchanged', this, location);
+ var file = this.renderPreview(response.data);
+
+ this.files.push(file);
+
+ this.arrange();
+
},
- resize: function()
+ xhrOnError : function()
{
- google.maps.event.trigger(this.gMapContext.map, "resize");
+ Roo.log('xhr on error');
- this.gMapContext.map.setCenter(this.gMapContext.marker.position);
+ var response = Roo.decode(xhr.responseText);
+
+ Roo.log(response);
- this.fireEvent('resize', this);
+ this.arrange();
},
- setPositionByLatLng: function(latitude, longitude)
+ process : function(file)
{
- this.setPosition(new google.maps.LatLng(latitude, longitude));
+ if(this.editable && file.type.indexOf('image') != -1){
+ this.fireEvent('edit', this, file);
+ return;
+ }
+
+ this.uploadStart(file, false);
+
+ return;
},
- getCurrentPosition: function()
+ uploadStart : function(file, crop)
{
- return {
- latitude: this.gMapContext.location.lat(),
- longitude: this.gMapContext.location.lng()
+ this.xhr = new XMLHttpRequest();
+
+ if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+ this.arrange();
+ return;
+ }
+
+ file.xhr = this.xhr;
+
+ this.managerEl.createChild({
+ tag : 'div',
+ cls : 'roo-document-manager-loading',
+ cn : [
+ {
+ tag : 'div',
+ tooltip : file.name,
+ cls : 'roo-document-manager-thumb',
+ html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
+ }
+ ]
+
+ });
+
+ this.xhr.open(this.method, this.url, true);
+
+ var headers = {
+ "Accept": "application/json",
+ "Cache-Control": "no-cache",
+ "X-Requested-With": "XMLHttpRequest"
};
- },
-
- getAddressName: function()
- {
- return this.gMapContext.locationName;
- },
-
- getAddressComponents: function()
- {
- return this.gMapContext.addressComponents;
- },
-
- address_component_from_google_geocode: function(address_components)
- {
- var result = {};
- for (var i = 0; i < address_components.length; i++) {
- var component = address_components[i];
- if (component.types.indexOf("postal_code") >= 0) {
- result.postalCode = component.short_name;
- } else if (component.types.indexOf("street_number") >= 0) {
- result.streetNumber = component.short_name;
- } else if (component.types.indexOf("route") >= 0) {
- result.streetName = component.short_name;
- } else if (component.types.indexOf("neighborhood") >= 0) {
- result.city = component.short_name;
- } else if (component.types.indexOf("locality") >= 0) {
- result.city = component.short_name;
- } else if (component.types.indexOf("sublocality") >= 0) {
- result.district = component.short_name;
- } else if (component.types.indexOf("administrative_area_level_1") >= 0) {
- result.stateOrProvince = component.short_name;
- } else if (component.types.indexOf("country") >= 0) {
- result.country = component.short_name;
+ for (var headerName in headers) {
+ var headerValue = headers[headerName];
+ if (headerValue) {
+ this.xhr.setRequestHeader(headerName, headerValue);
}
}
- result.addressLine1 = [ result.streetNumber, result.streetName ].join(" ").trim();
- result.addressLine2 = "";
- return result;
+ var _this = this;
+
+ this.xhr.onload = function()
+ {
+ _this.xhrOnLoad(_this.xhr);
+ }
+
+ this.xhr.onerror = function()
+ {
+ _this.xhrOnError(_this.xhr);
+ }
+
+ var formData = new FormData();
+
+ formData.append('returnHTML', 'NO');
+
+ if(crop){
+ formData.append('crop', crop);
+ }
+
+ formData.append(this.paramName, file, file.name);
+
+ if(this.fireEvent('prepare', this, formData) != false){
+ this.xhr.send(formData);
+ };
},
- setZoomLevel: function(zoom)
+ uploadCancel : function()
{
- this.gMapContext.map.setZoom(zoom);
+ this.xhr.abort();
+
+ this.delegates = [];
+
+ Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+ el.remove();
+ }, this);
+
+ this.arrange();
},
- show: function()
+ renderPreview : function(file)
{
- if(!this.el){
- return;
+ if(typeof(file.target) != 'undefined' && file.target){
+ return file;
}
- this.el.show();
+ var previewEl = this.managerEl.createChild({
+ tag : 'div',
+ cls : 'roo-document-manager-preview',
+ cn : [
+ {
+ tag : 'div',
+ tooltip : file.filename,
+ cls : 'roo-document-manager-thumb',
+ html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
+ },
+ {
+ tag : 'button',
+ cls : 'close',
+ html : '<i class="fa fa-times-circle"></i>'
+ }
+ ]
+ });
+
+ var close = previewEl.select('button.close', true).first();
+
+ close.on('click', this.onRemove, this, file);
+
+ file.target = previewEl;
+
+ var image = previewEl.select('img', true).first();
- this.resize();
+ var _this = this;
+
+ image.dom.addEventListener("load", function(){ _this.onPreviewLoad(file, image); });
+
+ image.on('click', this.onClick, this, file);
+
+ return file;
- this.fireEvent('show', this);
},
- hide: function()
+ onPreviewLoad : function(file, image)
{
- if(!this.el){
+ if(typeof(file.target) == 'undefined' || !file.target){
return;
}
- this.el.hide();
+ var width = image.dom.naturalWidth || image.dom.width;
+ var height = image.dom.naturalHeight || image.dom.height;
+
+ if(width > height){
+ file.target.addClass('wide');
+ return;
+ }
+
+ file.target.addClass('tall');
+ return;
- this.fireEvent('hide', this);
}
-
});
-Roo.apply(Roo.bootstrap.LocationPicker, {
-
- OverlayView : function(map, options)
- {
- options = options || {};
-
- this.setMap(map);
- }
-
-
-});/*
- * - LGPL
- *
- * Alert
- *
- */
+/*
+* Licence: LGPL
+*/
/**
- * @class Roo.bootstrap.Alert
+ * @class Roo.bootstrap.DocumentViewer
* @extends Roo.bootstrap.Component
- * Bootstrap Alert class
- * @cfg {String} title The title of alert
- * @cfg {String} html The content of alert
- * @cfg {String} weight ( success | info | warning | danger )
- * @cfg {String} faicon font-awesomeicon
+ * Bootstrap DocumentViewer class
*
* @constructor
- * Create a new alert
+ * Create a new DocumentViewer
* @param {Object} config The config object
*/
-
-Roo.bootstrap.Alert = function(config){
- Roo.bootstrap.Alert.superclass.constructor.call(this, config);
+Roo.bootstrap.DocumentViewer = function(config){
+ Roo.bootstrap.DocumentViewer.superclass.constructor.call(this, config);
+ this.addEvents({
+ /**
+ * @event initial
+ * Fire after initEvent
+ * @param {Roo.bootstrap.DocumentViewer} this
+ */
+ "initial" : true,
+ /**
+ * @event click
+ * Fire after click
+ * @param {Roo.bootstrap.DocumentViewer} this
+ */
+ "click" : true,
+ /**
+ * @event trash
+ * Fire after trash button
+ * @param {Roo.bootstrap.DocumentViewer} this
+ */
+ "trash" : true
+
+ });
};
-Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component, {
-
- title: '',
- html: '',
- weight: false,
- faicon: false,
+Roo.extend(Roo.bootstrap.DocumentViewer, Roo.bootstrap.Component, {
getAutoCreate : function()
{
-
var cfg = {
tag : 'div',
- cls : 'alert',
+ cls : 'roo-document-viewer',
cn : [
{
- tag : 'i',
- cls : 'roo-alert-icon'
-
- },
- {
- tag : 'b',
- cls : 'roo-alert-title',
- html : this.title
+ tag : 'div',
+ cls : 'roo-document-viewer-body',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'roo-document-viewer-thumb',
+ cn : [
+ {
+ tag : 'img',
+ cls : 'roo-document-viewer-image'
+ }
+ ]
+ }
+ ]
},
{
- tag : 'span',
- cls : 'roo-alert-text',
- html : this.html
+ tag : 'div',
+ cls : 'roo-document-viewer-footer',
+ cn : {
+ tag : 'div',
+ cls : 'btn-group btn-group-justified roo-document-viewer-btn-group',
+ cn : [
+ {
+ tag : 'div',
+ cls : 'btn-group',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default roo-document-viewer-trash',
+ html : '<i class="fa fa-trash"></i>'
+ }
+ ]
+ }
+ ]
+ }
}
]
};
- if(this.faicon){
- cfg.cn[0].cls += ' fa ' + this.faicon;
- }
-
- if(this.weight){
- cfg.cls += ' alert-' + this.weight;
- }
-
return cfg;
},
- initEvents: function()
- {
- this.el.setVisibilityMode(Roo.Element.DISPLAY);
- },
-
- setTitle : function(str)
- {
- this.el.select('.roo-alert-title',true).first().dom.innerHTML = str;
- },
-
- setText : function(str)
- {
- this.el.select('.roo-alert-text',true).first().dom.innerHTML = str;
- },
-
- setWeight : function(weight)
+ initEvents : function()
{
- if(this.weight){
- this.el.select('.alert',true).first().removeClass('alert-' + this.weight);
- }
- this.weight = weight;
+ this.bodyEl = this.el.select('.roo-document-viewer-body', true).first();
+ this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.thumbEl = this.el.select('.roo-document-viewer-thumb', true).first();
+ this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.imageEl = this.el.select('.roo-document-viewer-image', true).first();
+ this.imageEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.footerEl = this.el.select('.roo-document-viewer-footer', true).first();
+ this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.trashBtn = this.el.select('.roo-document-viewer-trash', true).first();
+ this.trashBtn.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.bodyEl.on('click', this.onClick, this);
+
+ this.trashBtn.on('click', this.onTrash, this);
- this.el.select('.alert',true).first().addClass('alert-' + this.weight);
},
- setIcon : function(icon)
+ initial : function()
{
- if(this.faicon){
- this.el.select('.roo-alert-icon',true).first().removeClass(['fa', 'fa-' + this.faicon]);
- }
+// this.thumbEl.setStyle('line-height', this.thumbEl.getHeight(true) + 'px');
- this.faicon = icon
- this.el.select('.roo-alert-icon',true).first().addClass(['fa', 'fa-' + this.faicon]);
+ this.fireEvent('initial', this);
+
},
- hide: function()
+ onClick : function(e)
{
- this.el.hide();
+ e.preventDefault();
+
+ this.fireEvent('click', this);
},
- show: function()
- {
- this.el.show();
+ onTrash : function(e)
+ {
+ e.preventDefault();
+
+ this.fireEvent('trash', this);
}
});
-
-
\ No newline at end of file