return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
},
- // internal
- callback : function(cb, scope, args, delay){
- if(typeof cb == "function"){
- if(delay){
- cb.defer(delay, scope, args || []);
- }else{
- cb.apply(scope, args || []);
- }
+ // internal (non-delayed, will get a return value..)
+ callback : function(cb, scope, args, delay)
+ {
+ if(typeof cb != "function"){
+ return false;
+ }
+ if(delay){
+ cb.defer(delay, scope, args || []);
+ return false
}
+ return cb.apply(scope, args || []);
+
},
/**
* If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
*
* @param {Proxy}
- * @param {Object} return from JsonData.reader() - success, totalRecords, records
- * @param {Object} load options
+ * @param {Object} ret return data from JsonData.reader() - success, totalRecords, records
+ * @param {Object} opts - load Options
* @param {Object} jsonData from your request (normally this contains the Exception)
*/
loadexception : true
// thse are take from connection...
/**
- * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
+ * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
*/
/**
- * @cfg {Object} extraParams (Optional) An object containing properties which are used as
+ * @cfg {Object} extraParams An object containing properties which are used as
* extra parameters to each request made by this object. (defaults to undefined)
*/
/**
- * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
+ * @cfg {Object} defaultHeaders An object containing request headers which are added
* to each request made by this object. (defaults to undefined)
*/
/**
- * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
+ * @cfg {String} method (GET|POST) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
*/
/**
- * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
+ * @cfg {Number} timeout The timeout in milliseconds to be used for requests. (defaults to 30000)
*/
/**
- * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
+ * @cfg {Boolean} autoAbort Whether this request should abort any pending requests. (defaults to false)
* @type Boolean
*/
Roo.extend(Roo.form.Field, Roo.BoxComponent, {
/**
* @cfg {String} fieldLabel Label to use when rendering a form.
+ */
+ /**
+ * @cfg {String} labelSeparator the ':' after a field label (default :) = set it to empty string to hide the field label.
*/
/**
* @cfg {String} qtip Mouse over tip
{
Roo.form.ComboBox.superclass.onRender.call(this, ct, position);
- if(this.hiddenName){
+ if(this.hiddenName){
this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
'before', true);
this.hiddenField.value =
*/
seperator : ',',
- // private the array of items that are displayed..
+
+ // private the array of items that are displayed..
items : false,
// private - the hidden field el.
hiddenEl : false,
// add to list
}, this);
-
-
+
+
+
+
},
cb: false,
displayField : false,
tipField : false,
-
+
defaultAutoCreate : {
tag: 'div',
this.replaceAname(cfg.node);
// this is disabled as the removal is done by other filters;
// this.walk(cfg.node);
-
+ this.replaceImageTable(cfg.node);
}
if (!spans.length) {
continue;
}
- var ff = spans[0].style.fontFamily;
- if (!spans[0].hasAttribute('style') && spans.length > 1 && spans[1].hasAttribute('style')) {
-
- ff = spans[1].style.fontFamily;
+ var ff = '';
+ var se = spans[0];
+ for (var i = 0; i < spans.length;i++) {
+ se = spans[i];
+ if (se.hasAttribute('style') && se.hasAttribute('style') && se.style.fontFamily != '') {
+ ff = se.style.fontFamily;
+ break;
+ }
}
- //var style = this.styleToObject(spans[0]);
+
+
//Roo.log("got font family: " + ff);
- if (typeof(ff) != 'undefined' && !ff.match(/Symbol/)) {
+ if (typeof(ff) != 'undefined' && !ff.match(/(Symbol|Wingdings)/) && "·o".indexOf(se.innerText.trim()) < 0) {
listtype = 'ol';
}
- }
-
+ },
+ replaceImageTable : function(doc)
+ {
+ /*
+ <table cellpadding=0 cellspacing=0 align=left>
+ <tr>
+ <td width=423 height=0></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><img width=601 height=401
+ src="file:///C:/Users/Alan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg"
+ v:shapes="Picture_x0020_2"></td>
+ </tr>
+ </table>
+ */
+ var imgs = Array.from(doc.getElementsByTagName('img'));
+ Roo.each(imgs, function(img) {
+ var td = img.parentNode;
+ if (td.nodeName != 'TD') {
+ return;
+ }
+ var tr = td.parentNode;
+ if (tr.nodeName != 'TR') {
+ return;
+ }
+ var tbody = tr.parentNode;
+ if (tbody.nodeName != 'TBODY') {
+ return;
+ }
+ var table = tbody.parentNode;
+ if (table.nodeName != 'TABLE') {
+ return;
+ }
+ // first row..
+
+ if (table.getElementsByTagName('tr').length != 2) {
+ return;
+ }
+ if (table.getElementsByTagName('td').length != 3) {
+ return;
+ }
+ if (table.innerText.trim() != '') {
+ return;
+ }
+ var p = table.parentNode;
+ img.parentNode.removeChild(img);
+ p.insertBefore(img, table);
+ p.removeChild(table);
+
+
+
+ });
+
+
+ }
});
/**
}
},
-
+
{
xtype : 'Button',
text: 'Hide Caption',
]
};
}
- // we remove caption totally if its hidden... - will delete data.. but otherwise we end up with fake caption
- var captionhtml = this.caption_display == 'none' ? '' : (this.caption.length ? this.caption : "Caption");
-
+
+
var ret = {
tag: 'figure',
'data-block' : 'Figure',
- 'data-width' : this.width,
+ 'data-width' : this.width,
+ 'data-caption' : this.caption,
+ 'data-caption-display' : this.caption_display,
contenteditable : 'false',
style : {
textAlign : this.align // seems to work for email..
},
-
align : this.align,
cn : [
- img,
-
- {
- tag: 'figcaption',
- 'data-display' : this.caption_display,
- style : {
- textAlign : 'left',
- fontSize : '16px',
- lineHeight : '24px',
- display : this.caption_display,
- maxWidth : (this.align == 'center' ? this.width : '100%' ) + ' !important',
- margin: m,
- width: this.align == 'center' ? this.width : '100%'
-
-
- },
- cls : this.cls.length > 0 ? (this.cls + '-thumbnail' ) : '',
- cn : [
- {
- tag: 'div',
- style : {
- marginTop : '16px',
- textAlign : 'left'
- },
- align: 'left',
- cn : [
- {
- // we can not rely on yahoo syndication to use CSS elements - so have to use '<i>' to encase stuff.
- tag : 'i',
- contenteditable : true,
- html : captionhtml
- }
-
- ]
- }
-
- ]
-
- }
+ img
]
};
+
+ // show figcaption only if caption_display is 'block'
+ if(this.caption_display == 'block') {
+ ret['cn'].push({
+ tag: 'figcaption',
+ style : {
+ textAlign : 'left',
+ fontSize : '16px',
+ lineHeight : '24px',
+ display : this.caption_display,
+ maxWidth : (this.align == 'center' ? this.width : '100%' ) + ' !important',
+ margin: m,
+ width: this.align == 'center' ? this.width : '100%'
+
+
+ },
+ cls : this.cls.length > 0 ? (this.cls + '-thumbnail' ) : '',
+ cn : [
+ {
+ tag: 'div',
+ style : {
+ marginTop : '16px',
+ textAlign : 'left'
+ },
+ align: 'left',
+ cn : [
+ {
+ // we can not rely on yahoo syndication to use CSS elements - so have to use '<i>' to encase stuff.
+ tag : 'i',
+ contenteditable : Roo.htmleditor.BlockFigure.caption_edit,
+ html : this.caption.length ? this.caption : "Caption" // fake caption
+ }
+
+ ]
+ }
+
+ ]
+
+ });
+ }
return ret;
},
this.image_src = this.getVal(node, 'img', 'src');
this.align = this.getVal(node, 'figure', 'align');
+
+ // caption display is stored in figure
+ this.caption_display = this.getVal(node, true, 'data-caption-display');
+
+ // backward compatible
+ // it was stored in figcaption
+ if(this.caption_display == '') {
+ this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+ }
+
+ // read caption from figcaption
var figcaption = this.getVal(node, 'figcaption', false);
+
if (figcaption !== '') {
this.caption = this.getVal(figcaption, 'i', 'html');
}
-
+
+
+ // read caption from data-caption in figure if no caption from figcaption
+ var dc = this.getVal(node, true, 'data-caption');
+
+ if(this.caption_display == 'none' && this.caption == '' && dc && dc.length){
+ this.caption = dc;
+ }
- this.caption_display = this.getVal(node, 'figcaption', 'data-display');
//this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
this.width = this.getVal(node, true, 'data-width');
//this.margin = this.getVal(node, 'figure', 'style', 'margin');
-})
+});
+
+Roo.apply(Roo.htmleditor.BlockFigure, {
+ caption_edit : true
+});
* @param {Roo.HtmlEditorCore} this
*/
editorevent: true
-
+
});
'align',
'colspan',
'rowspan',
- 'data-display',
+ 'data-caption-display',
'data-width',
+ 'data-caption',
'start' ,
'style',
// youtube embed.
var cd = (e.browserEvent.clipboardData || window.clipboardData);
// check what type of paste - if it's an image, then handle it differently.
- if (cd.files && cd.files.length > 0) {
- // pasting images?
+ if (cd.files && cd.files.length > 0 && cd.types.indexOf('text/html') < 0) {
+ // pasting images?
var urlAPI = (window.createObjectURL && window) ||
(window.URL && URL.revokeObjectURL && URL) ||
(window.webkitURL && webkitURL);
-
- var url = urlAPI.createObjectURL( cd.files[0]);
- this.insertAtCursor('<img src=" + url + ">');
+
+ var r = new FileReader();
+ var t = this;
+ r.addEventListener('load',function()
+ {
+
+ var d = (new DOMParser().parseFromString('<img src="' + r.result+ '">', 'text/html')).body;
+ // is insert asycn?
+ if (t.enableBlocks) {
+
+ Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+ if (img.closest('figure')) { // assume!! that it's aready
+ return;
+ }
+ var fig = new Roo.htmleditor.BlockFigure({
+ image_src : img.src
+ });
+ fig.updateElement(img); // replace it..
+
+ });
+ }
+ t.insertAtCursor(d.innerHTML.replace(/ /g,' '));
+ t.owner.fireEvent('paste', this);
+ });
+ r.readAsDataURL(cd.files[0]);
+
+ e.preventDefault();
+
return false;
}
if (cd.types.indexOf('text/html') < 0 ) {
var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
images = parser.doc ? parser.doc.getElementsByType('pict') : [];
}
- //Roo.log(images);
- //Roo.log(imgs);
+ // Roo.log(images);
+ // Roo.log(imgs);
// fixme..
images = images.filter(function(g) { return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/); }) // ignore headers/footers etc.
.map(function(g) { return g.toDataURL(); })
if (e && (e.ctrlKey || e.metaKey) && e.keyCode === 90) {
return; // we do not handle this.. (undo manager does..)
}
+ // clicking a 'block'?
+
// in theory this detects if the last element is not a br, then we try and do that.
// its so clicking in space at bottom triggers adding a br and moving the cursor.
if (e &&
break;
case 'bold':
case 'italic':
+ case 'underline':
// if there is no selection, then we insert, and set the curson inside it..
this.execCmd('styleWithCSS', false);
break;
* @param {Roo.HtmlEditorCore} this
*/
paste: true
+
});
this.defaultAutoCreate = {
tag: "textarea",
// closure these in so they are only created once.
var alpha = /^[a-zA-Z_]+$/;
var alphanum = /^[a-zA-Z0-9_]+$/;
- var email = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
- var url = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+ var email = /^([\w-]+)(\.[\w-]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
+ var url = /^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+ var urlWeb = /^((https?):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
// All these messages and functions are configurable
return {
url : function(v){
return url.test(v);
},
+ /**
+ * The funciton used to validate URLs (only allow schemes 'https' and 'http')
+ * @param {String} v The URL
+ */
+ urlWeb : function(v) {
+ return urlWeb.test(v);
+ },
/**
* The error text to display when the url validation function returns false
* @type String
this.view.singleSelect = false;
this.view.multiSelect = true;
this.view.toggleSelect = true;
- this.pageTb.add(new Roo.Toolbar.Fill(), {
+ this.pageTb.add(new Roo.Toolbar.Fill(),{
+ text: 'Select All',
+ handler: function() {
+ _t.selectAll();
+ }
+ },
+ {
text: 'Done',
- handler: function()
- {
+ handler: function() {
_t.collapse();
}
});
},
+ cleanLeadingSpace : function(e)
+ {
+ // this is disabled, as it retriggers setvalue on blur
+ return;
+ },
+ doForce : function() {
+ // no idea what this did, but it blanks out our values.
+ return;
+ },
onViewOver : function(e, t){
// do nothing...
return;
return false;
},
-
+ selectAll : function()
+ {
+ var sels = [];
+ this.store.each(function(r,i) {
+ sels.push(i);
+ });
+ this.view.select(sels);
+ this.collapse();
+ return false;
+
+ },
onSelect : function(record, index){
// Roo.log("onselect Called");
/**
* @cfg {Roo.Toolbar} toolbar a toolbar for buttons etc.
*/
+
+ /**
+ * @cfg {Roo.PagingToolbar} footer the paging toolbar
+ */
+
/**
* @cfg {String} ddGroup - drag drop group.
*/