X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=roojs-bootstrap-debug.js;h=3f835e47c4f93aeecf6efd1021955d8e425df69a;hb=640731308cafbadde457d2589528ec53b90ad306;hp=9e4408ba209cdb6a47c1fcbcfbf99ddcaaad5d8f;hpb=c1f99594ad1f43184d6549be9abca23901063aec;p=roojs1
diff --git a/roojs-bootstrap-debug.js b/roojs-bootstrap-debug.js
index 9e4408ba20..3f835e47c4 100644
--- a/roojs-bootstrap-debug.js
+++ b/roojs-bootstrap-debug.js
@@ -17,7 +17,10 @@ Roo.bootstrap.version = ( function() {
})(); Roo.bootstrap.menu = Roo.bootstrap.menu || {};
Roo.bootstrap.nav = {};
-Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {};/*
+Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {};
+Roo.htmleditor = {};
+Roo.namespace('Roo.bootstrap.form.HtmlEditorToolbar');
+/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
@@ -4545,10 +4548,16 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component, {
: this.el.select('.modal-footer div',true).first();
},
+
+ closeClick : function()
+ {
+ this.hide();
+ },
+
initEvents : function()
{
if (this.allow_close) {
- this.closeEl.on('click', this.hide, this);
+ this.closeEl.on('click', this.closeClick, this);
}
Roo.EventManager.onWindowResize(this.resize, this, true);
if (this.editableTitle) {
@@ -9157,6 +9166,7 @@ Currently the Table uses multiple headers to try and handle XL / Medium etc...
* also adds table-responsive (see bootstrap docs for details)
* @cfg {Boolean} loadMask (true|false) default false
* @cfg {Boolean} footerShow (true|false) generate tfoot, default true
+ * @cfg {Boolean} footerRow (true|false) generate tfoot with columns of values, default false
* @cfg {Boolean} headerShow (true|false) generate thead, default true
* @cfg {Boolean} rowSelection (true|false) default false
* @cfg {Boolean} cellSelection (true|false) default false
@@ -9165,6 +9175,7 @@ Currently the Table uses multiple headers to try and handle XL / Medium etc...
* @cfg {Boolean} lazyLoad auto load data while scrolling to the end (default false)
* @cfg {Boolean} auto_hide_footer auto hide footer if only one page (default false)
* @cfg {Boolean} enableColumnResize default true if columns can be resized = needs scrollBody to be set to work (drag/drop)
+ * @cfg {Boolean} disableAutoSize disable autoSize() and initCSS()
*
*
* @cfg {Number} minColumnWidth default 50 pixels minimum column width
@@ -9340,8 +9351,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
store : false,
loadMask : false,
footerShow : true,
+ footerRow : false,
headerShow : true,
enableColumnResize: true,
+ disableAutoSize: false,
rowSelection : false,
cellSelection : false,
@@ -9414,9 +9427,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
cfg.cn.push(this.renderBody());
- if(this.footerShow){
+ if(this.footerShow || this.footerRow){
cfg.cn.push(this.renderFooter());
}
+
// where does this come from?
//cfg.cls+= ' TableGrid';
}
@@ -9503,7 +9517,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
initCSS : function()
{
-
+ if(this.disableAutoSize) {
+ return;
+ }
var cm = this.cm, styles = [];
this.CSS.removeStyleSheet(this.id + '-cssrules');
@@ -9975,8 +9991,6 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
return footer;
},
-
-
onLoad : function()
{
// Roo.log('ds onload');
@@ -10023,7 +10037,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
var tfoot = this.el.select('tfoot', true).first();
- if(this.footerShow && this.auto_hide_footer && this.mainFoot){
+ if(this.footerShow && !this.footerRow && this.auto_hide_footer && this.mainFoot){
this.mainFoot.setVisibilityMode(Roo.Element.DISPLAY).hide();
@@ -10033,6 +10047,30 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
this.mainFoot.show();
}
}
+
+ if(!this.footerShow && this.footerRow) {
+
+ var tr = {
+ tag : 'tr',
+ cn : []
+ };
+
+ for(var i = 0, len = cm.getColumnCount(); i < len; i++){
+ var footer = typeof(cm.config[i].footer) == "function" ? cm.config[i].footer(ds, cm.config[i]) : cm.config[i].footer;
+ var td = {
+ tag: 'td',
+ cls : ' x-fcol-' + i,
+ html: footer
+ };
+
+ tr.cn.push(td);
+
+ }
+
+ tfoot.dom.innerHTML = '';
+
+ tfoot.createChild(tr);
+ }
Roo.each(this.el.select('tbody td', true).elements, function(e){
e.on('mouseover', _this.onMouseover, _this);
@@ -10300,7 +10338,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
var id = false;
if(typeof(renderer) !== 'undefined'){
- value = renderer(d.data[cm.getDataIndex(i)], false, d);
+ value = renderer.call(config, d.data[cm.getDataIndex(i)], false, d);
}
// if object are returned, then they are expected to be Roo.bootstrap.Component instances
// and are rendered into the cells after the row is rendered - using the id for the element.
@@ -10507,6 +10545,9 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, {
*/
autoSize : function()
{
+ if(this.disableAutoSize) {
+ return;
+ }
//var ctr = Roo.get(this.container.dom.parentElement);
var ctr = Roo.get(this.el.dom);
@@ -11277,7 +11318,13 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
}
var ret = false;
try {
- ret = Roo.decode(response.responseText);
+ var rt = response.responseText;
+ if (rt.match(/^\.
+ *
+ * @method cdata
+ * @param {String} text String to write out inside the comment.
+ */
+ comment: function(text) {
+ this.html.push('');
+ },
+ /**
+ * Writes a PI node such as .
+ *
+ * @method pi
+ * @param {String} name Name of the pi.
+ * @param {String} text String to write out inside the pi.
+ */
+ pi: function(name, text) {
+ text ? this.html.push('', name, ' ', this.encode(text), '?>') : this.html.push('', name, '?>');
+ this.indent != '' && this.html.push('\n');
+ },
+ /**
+ * Writes a doctype node such as .
+ *
+ * @method doctype
+ * @param {String} text String to write out inside the doctype.
+ */
+ doctype: function(text) {
+ this.html.push('', this.indent != '' ? '\n' : '');
+ },
+ /**
+ * Resets the internal buffer if one wants to reuse the writer.
+ *
+ * @method reset
+ */
+ reset: function() {
+ this.html.length = 0;
+ this.state = [];
+ this.pushState({
+ indentstr : '',
+ in_pre : false,
+ in_inline : false
+ })
+ },
+ /**
+ * Returns the contents that got serialized.
+ *
+ * @method getContent
+ * @return {String} HTML contents that got written down.
+ */
+ getContent: function() {
+ return this.html.join('').replace(/\n$/, '');
+ },
+
+ pushState : function(cfg)
+ {
+ this.state.push(cfg);
+ Roo.apply(this, cfg);
+ },
+
+ popState : function()
+ {
+ if (this.state.length < 1) {
+ return; // nothing to push
+ }
+ var cfg = {
+ in_pre: false,
+ indentstr : ''
+ };
+ this.state.pop();
+ if (this.state.length > 0) {
+ cfg = this.state[this.state.length-1];
+ }
+ Roo.apply(this, cfg);
+ },
+
+ addLine: function()
+ {
+ if (this.html.length < 1) {
+ return;
+ }
+
+
+ var value = this.html[this.html.length - 1];
+ if (value.length > 0 && '\n' !== value) {
+ this.html.push('\n');
+ }
+ }
+
+
+//'pre script noscript style textarea video audio iframe object code'
+// shortended... 'area base basefont br col frame hr img input isindex link meta param embed source wbr track');
+// inline
+};
+
+Roo.htmleditor.TidyWriter.inline_elements = [
+ 'SPAN','STRONG','B','EM','I','FONT','STRIKE','U','VAR',
+ 'CITE','DFN','CODE','MARK','Q','SUP','SUB','SAMP', 'A'
+];
+Roo.htmleditor.TidyWriter.shortend_elements = [
+ 'AREA','BASE','BASEFONT','BR','COL','FRAME','HR','IMG','INPUT',
+ 'ISINDEX','LINK','','META','PARAM','EMBED','SOURCE','WBR','TRACK'
+];
+
+Roo.htmleditor.TidyWriter.whitespace_elements = [
+ 'PRE','SCRIPT','NOSCRIPT','STYLE','TEXTAREA','VIDEO','AUDIO','IFRAME','OBJECT','CODE'
+];/***
+ * This is based loosely on tinymce
+ * @class Roo.htmleditor.TidyEntities
+ * @static
+ * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
+ *
+ * Not 100% sure this is actually used or needed.
+ */
+
+Roo.htmleditor.TidyEntities = {
+
+ /**
+ * initialize data..
+ */
+ init : function (){
+
+ this.namedEntities = this.buildEntitiesLookup(this.namedEntitiesData, 32);
+
+ },
+
+
+ buildEntitiesLookup: function(items, radix) {
+ var i, chr, entity, lookup = {};
+ if (!items) {
+ return {};
+ }
+ items = typeof(items) == 'string' ? items.split(',') : items;
+ radix = radix || 10;
+ // Build entities lookup table
+ for (i = 0; i < items.length; i += 2) {
+ chr = String.fromCharCode(parseInt(items[i], radix));
+ // Only add non base entities
+ if (!this.baseEntities[chr]) {
+ entity = '&' + items[i + 1] + ';';
+ lookup[chr] = entity;
+ lookup[entity] = chr;
+ }
+ }
+ return lookup;
+
+ },
+
+ asciiMap : {
+ 128: 'â¬',
+ 130: 'â',
+ 131: 'Æ',
+ 132: 'â',
+ 133: 'â¦',
+ 134: 'â ',
+ 135: 'â¡',
+ 136: 'Ë',
+ 137: 'â°',
+ 138: 'Å ',
+ 139: 'â¹',
+ 140: 'Å',
+ 142: 'Ž',
+ 145: 'â',
+ 146: 'â',
+ 147: 'â',
+ 148: 'â',
+ 149: 'â¢',
+ 150: 'â',
+ 151: 'â',
+ 152: 'Ë',
+ 153: 'â¢',
+ 154: 'Å¡',
+ 155: 'âº',
+ 156: 'Å',
+ 158: 'ž',
+ 159: 'Ÿ'
+ },
+ // Raw entities
+ baseEntities : {
+ '"': '"',
+ // Needs to be escaped since the YUI compressor would otherwise break the code
+ '\'': ''',
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '`': '`'
+ },
+ // Reverse lookup table for raw entities
+ reverseEntities : {
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '"': '"',
+ ''': '\''
+ },
+
+ attrsCharsRegExp : /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ textCharsRegExp : /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+ rawCharsRegExp : /[<>&\"\']/g,
+ entityRegExp : /([a-z0-9]+);?|&([a-z0-9]+);/gi,
+ namedEntities : false,
+ namedEntitiesData : [
+ '50',
+ 'nbsp',
+ '51',
+ 'iexcl',
+ '52',
+ 'cent',
+ '53',
+ 'pound',
+ '54',
+ 'curren',
+ '55',
+ 'yen',
+ '56',
+ 'brvbar',
+ '57',
+ 'sect',
+ '58',
+ 'uml',
+ '59',
+ 'copy',
+ '5a',
+ 'ordf',
+ '5b',
+ 'laquo',
+ '5c',
+ 'not',
+ '5d',
+ 'shy',
+ '5e',
+ 'reg',
+ '5f',
+ 'macr',
+ '5g',
+ 'deg',
+ '5h',
+ 'plusmn',
+ '5i',
+ 'sup2',
+ '5j',
+ 'sup3',
+ '5k',
+ 'acute',
+ '5l',
+ 'micro',
+ '5m',
+ 'para',
+ '5n',
+ 'middot',
+ '5o',
+ 'cedil',
+ '5p',
+ 'sup1',
+ '5q',
+ 'ordm',
+ '5r',
+ 'raquo',
+ '5s',
+ 'frac14',
+ '5t',
+ 'frac12',
+ '5u',
+ 'frac34',
+ '5v',
+ 'iquest',
+ '60',
+ 'Agrave',
+ '61',
+ 'Aacute',
+ '62',
+ 'Acirc',
+ '63',
+ 'Atilde',
+ '64',
+ 'Auml',
+ '65',
+ 'Aring',
+ '66',
+ 'AElig',
+ '67',
+ 'Ccedil',
+ '68',
+ 'Egrave',
+ '69',
+ 'Eacute',
+ '6a',
+ 'Ecirc',
+ '6b',
+ 'Euml',
+ '6c',
+ 'Igrave',
+ '6d',
+ 'Iacute',
+ '6e',
+ 'Icirc',
+ '6f',
+ 'Iuml',
+ '6g',
+ 'ETH',
+ '6h',
+ 'Ntilde',
+ '6i',
+ 'Ograve',
+ '6j',
+ 'Oacute',
+ '6k',
+ 'Ocirc',
+ '6l',
+ 'Otilde',
+ '6m',
+ 'Ouml',
+ '6n',
+ 'times',
+ '6o',
+ 'Oslash',
+ '6p',
+ 'Ugrave',
+ '6q',
+ 'Uacute',
+ '6r',
+ 'Ucirc',
+ '6s',
+ 'Uuml',
+ '6t',
+ 'Yacute',
+ '6u',
+ 'THORN',
+ '6v',
+ 'szlig',
+ '70',
+ 'agrave',
+ '71',
+ 'aacute',
+ '72',
+ 'acirc',
+ '73',
+ 'atilde',
+ '74',
+ 'auml',
+ '75',
+ 'aring',
+ '76',
+ 'aelig',
+ '77',
+ 'ccedil',
+ '78',
+ 'egrave',
+ '79',
+ 'eacute',
+ '7a',
+ 'ecirc',
+ '7b',
+ 'euml',
+ '7c',
+ 'igrave',
+ '7d',
+ 'iacute',
+ '7e',
+ 'icirc',
+ '7f',
+ 'iuml',
+ '7g',
+ 'eth',
+ '7h',
+ 'ntilde',
+ '7i',
+ 'ograve',
+ '7j',
+ 'oacute',
+ '7k',
+ 'ocirc',
+ '7l',
+ 'otilde',
+ '7m',
+ 'ouml',
+ '7n',
+ 'divide',
+ '7o',
+ 'oslash',
+ '7p',
+ 'ugrave',
+ '7q',
+ 'uacute',
+ '7r',
+ 'ucirc',
+ '7s',
+ 'uuml',
+ '7t',
+ 'yacute',
+ '7u',
+ 'thorn',
+ '7v',
+ 'yuml',
+ 'ci',
+ 'fnof',
+ 'sh',
+ 'Alpha',
+ 'si',
+ 'Beta',
+ 'sj',
+ 'Gamma',
+ 'sk',
+ 'Delta',
+ 'sl',
+ 'Epsilon',
+ 'sm',
+ 'Zeta',
+ 'sn',
+ 'Eta',
+ 'so',
+ 'Theta',
+ 'sp',
+ 'Iota',
+ 'sq',
+ 'Kappa',
+ 'sr',
+ 'Lambda',
+ 'ss',
+ 'Mu',
+ 'st',
+ 'Nu',
+ 'su',
+ 'Xi',
+ 'sv',
+ 'Omicron',
+ 't0',
+ 'Pi',
+ 't1',
+ 'Rho',
+ 't3',
+ 'Sigma',
+ 't4',
+ 'Tau',
+ 't5',
+ 'Upsilon',
+ 't6',
+ 'Phi',
+ 't7',
+ 'Chi',
+ 't8',
+ 'Psi',
+ 't9',
+ 'Omega',
+ 'th',
+ 'alpha',
+ 'ti',
+ 'beta',
+ 'tj',
+ 'gamma',
+ 'tk',
+ 'delta',
+ 'tl',
+ 'epsilon',
+ 'tm',
+ 'zeta',
+ 'tn',
+ 'eta',
+ 'to',
+ 'theta',
+ 'tp',
+ 'iota',
+ 'tq',
+ 'kappa',
+ 'tr',
+ 'lambda',
+ 'ts',
+ 'mu',
+ 'tt',
+ 'nu',
+ 'tu',
+ 'xi',
+ 'tv',
+ 'omicron',
+ 'u0',
+ 'pi',
+ 'u1',
+ 'rho',
+ 'u2',
+ 'sigmaf',
+ 'u3',
+ 'sigma',
+ 'u4',
+ 'tau',
+ 'u5',
+ 'upsilon',
+ 'u6',
+ 'phi',
+ 'u7',
+ 'chi',
+ 'u8',
+ 'psi',
+ 'u9',
+ 'omega',
+ 'uh',
+ 'thetasym',
+ 'ui',
+ 'upsih',
+ 'um',
+ 'piv',
+ '812',
+ 'bull',
+ '816',
+ 'hellip',
+ '81i',
+ 'prime',
+ '81j',
+ 'Prime',
+ '81u',
+ 'oline',
+ '824',
+ 'frasl',
+ '88o',
+ 'weierp',
+ '88h',
+ 'image',
+ '88s',
+ 'real',
+ '892',
+ 'trade',
+ '89l',
+ 'alefsym',
+ '8cg',
+ 'larr',
+ '8ch',
+ 'uarr',
+ '8ci',
+ 'rarr',
+ '8cj',
+ 'darr',
+ '8ck',
+ 'harr',
+ '8dl',
+ 'crarr',
+ '8eg',
+ 'lArr',
+ '8eh',
+ 'uArr',
+ '8ei',
+ 'rArr',
+ '8ej',
+ 'dArr',
+ '8ek',
+ 'hArr',
+ '8g0',
+ 'forall',
+ '8g2',
+ 'part',
+ '8g3',
+ 'exist',
+ '8g5',
+ 'empty',
+ '8g7',
+ 'nabla',
+ '8g8',
+ 'isin',
+ '8g9',
+ 'notin',
+ '8gb',
+ 'ni',
+ '8gf',
+ 'prod',
+ '8gh',
+ 'sum',
+ '8gi',
+ 'minus',
+ '8gn',
+ 'lowast',
+ '8gq',
+ 'radic',
+ '8gt',
+ 'prop',
+ '8gu',
+ 'infin',
+ '8h0',
+ 'ang',
+ '8h7',
+ 'and',
+ '8h8',
+ 'or',
+ '8h9',
+ 'cap',
+ '8ha',
+ 'cup',
+ '8hb',
+ 'int',
+ '8hk',
+ 'there4',
+ '8hs',
+ 'sim',
+ '8i5',
+ 'cong',
+ '8i8',
+ 'asymp',
+ '8j0',
+ 'ne',
+ '8j1',
+ 'equiv',
+ '8j4',
+ 'le',
+ '8j5',
+ 'ge',
+ '8k2',
+ 'sub',
+ '8k3',
+ 'sup',
+ '8k4',
+ 'nsub',
+ '8k6',
+ 'sube',
+ '8k7',
+ 'supe',
+ '8kl',
+ 'oplus',
+ '8kn',
+ 'otimes',
+ '8l5',
+ 'perp',
+ '8m5',
+ 'sdot',
+ '8o8',
+ 'lceil',
+ '8o9',
+ 'rceil',
+ '8oa',
+ 'lfloor',
+ '8ob',
+ 'rfloor',
+ '8p9',
+ 'lang',
+ '8pa',
+ 'rang',
+ '9ea',
+ 'loz',
+ '9j0',
+ 'spades',
+ '9j3',
+ 'clubs',
+ '9j5',
+ 'hearts',
+ '9j6',
+ 'diams',
+ 'ai',
+ 'OElig',
+ 'aj',
+ 'oelig',
+ 'b0',
+ 'Scaron',
+ 'b1',
+ 'scaron',
+ 'bo',
+ 'Yuml',
+ 'm6',
+ 'circ',
+ 'ms',
+ 'tilde',
+ '802',
+ 'ensp',
+ '803',
+ 'emsp',
+ '809',
+ 'thinsp',
+ '80c',
+ 'zwnj',
+ '80d',
+ 'zwj',
+ '80e',
+ 'lrm',
+ '80f',
+ 'rlm',
+ '80j',
+ 'ndash',
+ '80k',
+ 'mdash',
+ '80o',
+ 'lsquo',
+ '80p',
+ 'rsquo',
+ '80q',
+ 'sbquo',
+ '80s',
+ 'ldquo',
+ '80t',
+ 'rdquo',
+ '80u',
+ 'bdquo',
+ '810',
+ 'dagger',
+ '811',
+ 'Dagger',
+ '81g',
+ 'permil',
+ '81p',
+ 'lsaquo',
+ '81q',
+ 'rsaquo',
+ '85c',
+ 'euro'
+ ],
+
+
+ /**
+ * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
+ *
+ * @method encodeRaw
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @return {String} Entity encoded text.
+ */
+ encodeRaw: function(text, attr)
+ {
+ var t = this;
+ return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+ return t.baseEntities[chr] || chr;
+ });
+ },
+ /**
+ * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
+ * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
+ * and is exposed as the DOMUtils.encode function.
+ *
+ * @method encodeAllRaw
+ * @param {String} text Text to encode.
+ * @return {String} Entity encoded text.
+ */
+ encodeAllRaw: function(text) {
+ var t = this;
+ return ('' + text).replace(this.rawCharsRegExp, function(chr) {
+ return t.baseEntities[chr] || chr;
+ });
+ },
+ /**
+ * Encodes the specified string using numeric entities. The core entities will be
+ * encoded as named ones but all non lower ascii characters will be encoded into numeric entities.
+ *
+ * @method encodeNumeric
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @return {String} Entity encoded text.
+ */
+ encodeNumeric: function(text, attr) {
+ var t = this;
+ return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+ // Multi byte sequence convert it to a single entity
+ if (chr.length > 1) {
+ return '' + (1024 * (chr.charCodeAt(0) - 55296) + (chr.charCodeAt(1) - 56320) + 65536) + ';';
+ }
+ return t.baseEntities[chr] || '' + chr.charCodeAt(0) + ';';
+ });
+ },
+ /**
+ * Encodes the specified string using named entities. The core entities will be encoded
+ * as named ones but all non lower ascii characters will be encoded into named entities.
+ *
+ * @method encodeNamed
+ * @param {String} text Text to encode.
+ * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
+ * @param {Object} entities Optional parameter with entities to use.
+ * @return {String} Entity encoded text.
+ */
+ encodeNamed: function(text, attr, entities) {
+ var t = this;
+ entities = entities || this.namedEntities;
+ return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
+ return t.baseEntities[chr] || entities[chr] || chr;
+ });
+ },
+ /**
+ * Returns an encode function based on the name(s) and it's optional entities.
+ *
+ * @method getEncodeFunc
+ * @param {String} name Comma separated list of encoders for example named,numeric.
+ * @param {String} entities Optional parameter with entities to use instead of the built in set.
+ * @return {function} Encode function to be used.
+ */
+ getEncodeFunc: function(name, entities) {
+ entities = this.buildEntitiesLookup(entities) || this.namedEntities;
+ var t = this;
+ function encodeNamedAndNumeric(text, attr) {
+ return text.replace(attr ? t.attrsCharsRegExp : t.textCharsRegExp, function(chr) {
+ return t.baseEntities[chr] || entities[chr] || '' + chr.charCodeAt(0) + ';' || chr;
+ });
+ }
+
+ function encodeCustomNamed(text, attr) {
+ return t.encodeNamed(text, attr, entities);
+ }
+ // Replace + with , to be compatible with previous TinyMCE versions
+ name = this.makeMap(name.replace(/\+/g, ','));
+ // Named and numeric encoder
+ if (name.named && name.numeric) {
+ return this.encodeNamedAndNumeric;
+ }
+ // Named encoder
+ if (name.named) {
+ // Custom names
+ if (entities) {
+ return encodeCustomNamed;
+ }
+ return this.encodeNamed;
+ }
+ // Numeric
+ if (name.numeric) {
+ return this.encodeNumeric;
+ }
+ // Raw encoder
+ return this.encodeRaw;
+ },
+ /**
+ * Decodes the specified string, this will replace entities with raw UTF characters.
+ *
+ * @method decode
+ * @param {String} text Text to entity decode.
+ * @return {String} Entity decoded string.
+ */
+ decode: function(text)
+ {
+ var t = this;
+ return text.replace(this.entityRegExp, function(all, numeric) {
+ if (numeric) {
+ numeric = 'x' === numeric.charAt(0).toLowerCase() ? parseInt(numeric.substr(1), 16) : parseInt(numeric, 10);
+ // Support upper UTF
+ if (numeric > 65535) {
+ numeric -= 65536;
+ return String.fromCharCode(55296 + (numeric >> 10), 56320 + (1023 & numeric));
+ }
+ return t.asciiMap[numeric] || String.fromCharCode(numeric);
+ }
+ return t.reverseEntities[all] || t.namedEntities[all] || t.nativeDecode(all);
+ });
+ },
+ nativeDecode : function (text) {
+ return text;
+ },
+ makeMap : function (items, delim, map) {
+ var i;
+ items = items || [];
+ delim = delim || ',';
+ if (typeof items == "string") {
+ items = items.split(delim);
+ }
+ map = map || {};
+ i = items.length;
+ while (i--) {
+ map[items[i]] = {};
+ }
+ return map;
+ }
+};
+
+
+
+Roo.htmleditor.TidyEntities.init();
/**
* @class Roo.htmleditor.KeyEnter
* Handle Enter press..
@@ -27492,7 +29330,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
}
},
-
+
{
xtype : 'Button',
text: 'Hide Caption',
@@ -27587,7 +29425,8 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
var ret = {
tag: 'figure',
'data-block' : 'Figure',
- 'data-width' : this.width,
+ 'data-width' : this.width,
+ 'data-caption' : this.caption,
contenteditable : 'false',
style : {
@@ -27660,6 +29499,8 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
this.image_src = this.getVal(node, 'img', 'src');
this.align = this.getVal(node, 'figure', 'align');
+
+ /// not really used - as hidden captions do not store the content here..
var figcaption = this.getVal(node, 'figcaption', false);
if (figcaption !== '') {
this.caption = this.getVal(figcaption, 'i', 'html');
@@ -27667,6 +29508,10 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
this.caption_display = this.getVal(node, 'figcaption', 'data-display');
+ var dc = this.getVal(node, 'figcaption', 'data-caption');
+ if (dc && dc.length) {
+ this.caption = dc;
+ }
//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');
@@ -29007,7 +30852,7 @@ Roo.HtmlEditorCore = function(config){
* @param {Roo.HtmlEditorCore} this
*/
editorevent: true
-
+
});
@@ -29031,10 +30876,9 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
owner : false,
/**
- * @cfg {String} resizable 's' or 'se' or 'e' - wrapps the element in a
- * Roo.resizable.
+ * @cfg {String} css styling for resizing. (used on bootstrap only)
*/
- resizable : false,
+ resize : false,
/**
* @cfg {Number} height (in pixels)
*/
@@ -29167,17 +31011,19 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
this.frameId = Roo.id();
-
-
- var iframe = this.owner.wrap.createChild({
+ var ifcfg = {
tag: 'iframe',
cls: 'form-control', // bootstrap..
id: this.frameId,
name: this.frameId,
frameBorder : 'no',
'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL : "javascript:false"
- }, this.el
- );
+ };
+ if (this.resize) {
+ ifcfg.style = { resize : this.resize };
+ }
+
+ var iframe = this.owner.wrap.createChild(ifcfg, this.el);
this.iframe = iframe.dom;
@@ -29312,12 +31158,40 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
if (this.enableBlocks) {
new Roo.htmleditor.FilterBlock({ node : div });
}
+
+ var html = div.innerHTML;
+
//?? tidy?
if (this.autoClean) {
+
+ new Roo.htmleditor.FilterAttributes({
+ node : div,
+ attrib_white : [
+ 'href',
+ 'src',
+ 'name',
+ 'align',
+ 'colspan',
+ 'rowspan',
+ 'data-display',
+ 'data-width',
+ 'start' ,
+ 'style',
+ // youtube embed.
+ 'class',
+ 'allowfullscreen',
+ 'frameborder',
+ 'width',
+ 'height',
+ 'alt'
+ ],
+ attrib_clean : ['href', 'src' ]
+ });
+
var tidy = new Roo.htmleditor.TidySerializer({
inner: true
});
- var html = tidy.serialize(div);
+ html = tidy.serialize(div);
}
@@ -29507,14 +31381,39 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
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('');
+
+ var r = new FileReader();
+ var t = this;
+ r.addEventListener('load',function()
+ {
+
+ var d = (new DOMParser().parseFromString('', '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 ) {
@@ -29607,6 +31506,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
e.preventDefault();
+ this.owner.fireEvent('paste', this);
return false;
// default behaveiour should be our local cleanup paste? (optional?)
// for simple editor - we want to hammer the paste and get rid of everything... - so over-rideable..
@@ -29683,6 +31583,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
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 &&
@@ -29785,6 +31687,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component, {
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;
@@ -30569,31 +32472,26 @@ Roo.HtmlEditorCore.cblack= [
*/
Roo.bootstrap.form.HtmlEditor = function(config){
- Roo.bootstrap.form.HtmlEditor.superclass.constructor.call(this, config);
- if (!this.toolbars) {
- this.toolbars = [];
- }
-
- this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
+
this.addEvents({
/**
* @event initialize
* Fires when the editor is fully initialized (including the iframe)
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
initialize: true,
/**
* @event activate
* Fires when the editor is first receives the focus. Any insertion must wait
* until after this event.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
activate: true,
/**
* @event beforesync
* Fires before the textarea is updated with content from the editor iframe. Return false
* to cancel the sync.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
* @param {String} html
*/
beforesync: true,
@@ -30601,56 +32499,95 @@ Roo.bootstrap.form.HtmlEditor = function(config){
* @event beforepush
* Fires before the iframe editor is updated with content from the textarea. Return false
* to cancel the push.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
* @param {String} html
*/
beforepush: true,
/**
* @event sync
* Fires when the textarea is updated with content from the editor iframe.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
* @param {String} html
*/
sync: true,
/**
* @event push
* Fires when the iframe editor is updated with content from the textarea.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
* @param {String} html
*/
push: true,
/**
* @event editmodechange
* Fires when the editor switches edit modes
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
* @param {Boolean} sourceEdit True if source edit, false if standard editing.
*/
editmodechange: true,
/**
* @event editorevent
* Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
editorevent: true,
/**
* @event firstfocus
* Fires when on first focus - needed by toolbars..
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
firstfocus: true,
/**
* @event autosave
* Auto save the htmlEditor value as a file into Events
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
autosave: true,
/**
* @event savedpreview
* preview the saved version of htmlEditor
- * @param {HtmlEditor} this
+ * @param {Roo.bootstrap.form.HtmlEditor} this
*/
- savedpreview: true
- });
+ savedpreview: true,
+ /**
+ * @event stylesheetsclick
+ * Fires when press the Sytlesheets button
+ * @param {Roo.HtmlEditorCore} this
+ */
+ stylesheetsclick: true,
+ /**
+ * @event paste
+ * Fires when press user pastes into the editor
+ * @param {Roo.HtmlEditorCore} this
+ */
+ paste: true,
+ /**
+ * @event imageadd
+ * Fires when on any editor when an image is added (excluding paste)
+ * @param {Roo.bootstrap.form.HtmlEditor} this
+ */
+ imageadd: true ,
+ /**
+ * @event imageupdated
+ * Fires when on any editor when an image is changed (excluding paste)
+ * @param {Roo.bootstrap.form.HtmlEditor} this
+ * @param {HTMLElement} img could also be a figure if blocks are enabled
+ */
+ imageupdate: true ,
+ /**
+ * @event imagedelete
+ * Fires when on any editor when an image is deleted
+ * @param {Roo.bootstrap.form.HtmlEditor} this
+ * @param {HTMLElement} img could also be a figure if blocks are enabled
+ */
+ imagedelete: true
+ });
+ Roo.bootstrap.form.HtmlEditor.superclass.constructor.call(this, config);
+ if (!this.toolbars) {
+ this.toolbars = [];
+ }
+
+ this.editorcore = new Roo.HtmlEditorCore(Roo.apply({ owner : this} , config));
+
};
@@ -30658,9 +32595,9 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
/**
- * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
+ * @cfg {Array|boolean} toolbars Array of toolbars, or names of toolbars. - true for standard, and false for none.
*/
- toolbars : false,
+ toolbars : true,
/**
* @cfg {Array} buttons Array of toolbar's buttons. - defaults to empty
@@ -30668,10 +32605,9 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
btns : [],
/**
- * @cfg {String} resizable 's' or 'se' or 'e' - wrapps the element in a
- * Roo.resizable.
+ * @cfg {String} resize (none|both|horizontal|vertical) - css resize of element
*/
- resizable : false,
+ resize : false,
/**
* @cfg {Number} height (in pixels)
*/
@@ -30714,26 +32650,35 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
* add custom toolbar buttons.
* @param {HtmlEditor} editor
*/
- createToolbar : function(){
- Roo.log('renewing');
- Roo.log("create toolbars");
+ createToolbar : function()
+ {
+ //Roo.log('renewing');
+ //Roo.log("create toolbars");
+ if (this.toolbars === false) {
+ return;
+ }
+ if (this.toolbars === true) {
+ this.toolbars = [ 'Standard' ];
+ }
- this.toolbars = [ new Roo.bootstrap.form.HtmlEditorToolbarStandard({editor: this} ) ];
- this.toolbars[0].render(this.toolbarContainer());
+ var ar = Array.from(this.toolbars);
+ this.toolbars = [];
+ ar.forEach(function(t,i) {
+ if (typeof(t) == 'string') {
+ t = {
+ xtype : t
+ };
+ }
+ if (typeof(t) == 'object' && typeof(t.xtype) == 'string') {
+ t.editor = this;
+ t.xns = t.xns || Roo.bootstrap.form.HtmlEditorToolbar;
+ t = Roo.factory(t);
+ }
+ this.toolbars[i] = t;
+ this.toolbars[i].render(this.toolbarContainer());
+ }, this);
- return;
-// if (!editor.toolbars || !editor.toolbars.length) {
-// editor.toolbars = [ new Roo.bootstrap.form.HtmlEditorToolbarStandard() ]; // 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.form.HtmlEditor);
-// editor.toolbars[i].init(editor);
-// }
},
@@ -30750,33 +32695,11 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
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..
- }
+
},
@@ -30847,9 +32770,9 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
//this.deferFocus();
}
- if(this.resizable){
- this.setSize(this.wrap.getSize());
- }
+ //if(this.resizable){
+ // this.setSize(this.wrap.getSize());
+ //}
this.fireEvent('editmodechange', this, this.editorcore.sourceEditMode);
},
@@ -30986,9 +32909,8 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea, {
-Roo.namespace('Roo.bootstrap.form.HtmlEditor');
/**
- * @class Roo.bootstrap.form.HtmlEditorToolbarStandard
+ * @class Roo.bootstrap.form.HtmlEditorToolbar.Standard
* @parent Roo.bootstrap.form.HtmlEditor
* @extends Roo.bootstrap.nav.Simplebar
* Basic Toolbar
@@ -30999,7 +32921,7 @@ Roo.namespace('Roo.bootstrap.form.HtmlEditor');
new Roo.bootstrap.form.HtmlEditor({
....
toolbars : [
- new Roo.bootstrap.form.HtmlEditorToolbarStandard({
+ new Roo.bootstrap.form.HtmlEditorToolbar.Standard({
disable : { fonts: 1 , format: 1, ..., ... , ...],
btns : [ .... ]
})
@@ -31014,7 +32936,7 @@ Roo.namespace('Roo.bootstrap.form.HtmlEditor');
* .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
*/
-Roo.bootstrap.form.HtmlEditorToolbarStandard = function(config)
+Roo.bootstrap.form.HtmlEditorToolbar.Standard = function(config)
{
Roo.apply(this, config);
@@ -31026,17 +32948,17 @@ Roo.bootstrap.form.HtmlEditorToolbarStandard = function(config)
colors : true,
specialElements : true
});
- Roo.bootstrap.form.HtmlEditorToolbarStandard.superclass.constructor.call(this, config);
+ Roo.bootstrap.form.HtmlEditorToolbar.Standard.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; });
+ this.buttons = new Roo.util.MixedCollection(false, function(o) { return o.btnid; });
//Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
// dont call parent... till later.
}
-Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simplebar, {
+Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simplebar, {
bar : true,
@@ -31052,11 +32974,14 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
'div','span'
],
+
+ deleteBtn: false,
+
onRender : function(ct, position)
{
// Roo.log("Call onRender: " + this.xtype);
- Roo.bootstrap.form.HtmlEditorToolbarStandard.superclass.onRender.call(this, ct, position);
+ Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.onRender.call(this, ct, position);
Roo.log(this.el);
this.el.dom.style.marginBottom = '0';
var _this = this;
@@ -31064,7 +32989,7 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
var editor= this.editor;
var children = [];
- var btn = function(id,cmd , toggle, handler, html){
+ var btn = function(id, cmd , toggle, handler, html){
var event = toggle ? 'toggle' : 'click';
@@ -31073,9 +32998,11 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
xtype: 'Button',
xns: Roo.bootstrap,
//glyphicon : id,
+ btnid : id,
fa: id,
- cmd : id || cmd,
- enableToggle:toggle !== false,
+ cls : 'roo-html-editor-btn-' + id,
+ cmd : cmd, // why id || cmd
+ enableToggle: toggle !== false,
html : html || '',
pressed : toggle ? false : null,
listeners : {}
@@ -31094,6 +33021,7 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
size : 'sm',
xns: Roo.bootstrap,
fa : 'font',
+ cls : 'roo-html-editor-font-chooser',
//html : 'submit'
menu : {
xtype: 'Menu',
@@ -31119,19 +33047,19 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
});
children.push(style);
- btn('bold',false,true);
- btn('italic',false,true);
- btn('align-left', 'justifyleft',true);
+ btn('bold', 'bold',true);
+ btn('italic', 'italic',true);
+ btn('underline', 'underline',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('link', false, true, this.onLinkClick);
+
+
+ btn('image', false, true, this.onImageClick);
btn('list','insertunorderedlist',true);
+ btn('list-ol','insertorderedlist',true);
+
btn('pencil', false,true, function(btn){
Roo.log(this);
this.toggleSourceEdit(btn.pressed);
@@ -31143,58 +33071,176 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
}
}
- /*
- 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';
+ this.xtype = 'NavSimplebar'; // why?
for(var i=0;i< children.length;i++) {
this.buttons.add(this.addxtypeChild(children[i]));
}
-
+ this.buildToolbarDelete();
+
editor.on('editorevent', this.updateToolbar, this);
},
+
+ buildToolbarDelete : function()
+ {
+
+ /* this.addxtypeChild({
+ xtype : 'Element',
+ xns : Roo.bootstrap,
+ cls : 'roo-htmleditor-fill'
+ });
+ */
+ this.deleteBtn = this.addxtypeChild({
+ size : 'sm',
+ xtype: 'Button',
+ xns: Roo.bootstrap,
+ fa: 'trash',
+ listeners : {
+ click : this.onDelete.createDelegate(this)
+ }
+ });
+ this.deleteBtn.hide();
+
+ },
+
+ onImageClick : function()
+ {
+ if (this.input) {
+ this.input.un('change', this.onFileSelected, this);
+ }
+ this.input = Roo.get(document.body).createChild({
+ tag: 'input',
+ type : 'file',
+ style : 'display:none',
+ multiple: 'multiple'
+ });
+ this.input.on('change', this.onFileSelected, this);
+ this.input.dom.click();
+ },
+
+ onFileSelected : function(e)
+ {
+ e.preventDefault();
+
+ if(typeof(this.input.dom.files) == 'undefined' || !this.input.dom.files.length){
+ return;
+ }
+
+
+ this.addFiles(Array.prototype.slice.call(this.input.dom.files), false);
+ },
+
+ addFiles : function(far, fire_add) {
+
+
+ var editor = this.editorcore;
+
+ if (!far.length) {
+ if (fire_add) {
+ this.editor.syncValue();
+ editor.owner.fireEvent('editorevent', editor.owner, false);
+ editor.owner.fireEvent('imageadd', editor.owner, false);
+ }
+ return;
+ }
+
+ var f = far.pop();
+
+ if (!f.type.match(/^image/)) {
+ this.addFiles(far, fire_add);
+ return;
+ }
+
+ var sn = this.selectedNode;
+
+ var bl = sn && this.editorcore.enableBlocks ? Roo.htmleditor.Block.factory(sn) : false;
+
+
+ var reader = new FileReader();
+ reader.addEventListener('load', (function() {
+ if (bl) {
+ bl.image_src = reader.result;
+ //bl.caption = f.name;
+ bl.updateElement(sn);
+ this.editor.syncValue();
+ editor.owner.fireEvent('editorevent', editor.owner, false);
+ editor.owner.fireEvent('imageupdate', editor.owner, sn);
+ // we only do the first file!! and replace.
+ return;
+ }
+ if (this.editorcore.enableBlocks) {
+ var fig = new Roo.htmleditor.BlockFigure({
+ image_src : reader.result,
+ caption : '',
+ caption_display : 'none' //default to hide captions..
+ });
+ editor.insertAtCursor(fig.toHTML());
+ this.addFiles(far, true);
+ return;
+ }
+ // just a standard img..
+ if (sn && sn.tagName.toUpperCase() == 'IMG') {
+ sn.src = reader.result;
+ this.editor.syncValue();
+ editor.owner.fireEvent('editorevent', editor.owner, false);
+ editor.owner.fireEvent('imageupdate', editor.owner, sn);
+ return;
+ }
+ editor.insertAtCursor('');
+ this.addFiles(far, true);
+
+ }).createDelegate(this));
+ reader.readAsDataURL(f);
+
+
+ },
+
+
onBtnClick : function(id)
{
this.editorcore.relayCmd(id);
this.editorcore.focus();
},
+ onLinkClick : function(btn) {
+ var url = this.selectedNode && this.selectedNode.tagName.toUpperCase() == 'A' ?
+ this.selectedNode.getAttribute('href') : '';
+
+ Roo.bootstrap.MessageBox.show({
+ title : "Add / Edit Link URL",
+ msg : "Enter the URL for the link",
+ buttons: Roo.bootstrap.MessageBox.OKCANCEL,
+ minWidth: 250,
+ scope : this,
+ prompt:true,
+ multiline: false,
+ modal : true,
+ value : url,
+ fn: function(pressed, newurl) {
+ if (pressed != 'ok') {
+ this.editorcore.focus();
+ return;
+ }
+ if (url != '') {
+ this.selectedNode.setAttribute('href', newurl);
+ return;
+ }
+ if(newurl && newurl .match(/http(s):\/\/.+/)) {
+ this.editorcore.relayCmd('createlink', newurl);
+ }
+ 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(){
+ updateToolbar: function(editor ,ev, sel){
if(!this.editorcore.activated){
this.editor.onFirstFocus(); // is this neeed?
@@ -31203,39 +33249,89 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
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'));
+ var hasToggle = false;
+ btns.each(function(e) {
+ if (e.enableToggle && e.cmd) {
+ hasToggle = hasToggle || (['align-left', 'align-right', 'align-center', 'image' , 'link', 'underline'].indexOf(e.btnid) < 0 && doc.queryCommandState(e.cmd));
+ e.setActive(doc.queryCommandState(e.cmd));
+ }
+ }, this);
- 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'));
- /*
+ if (ev &&
+ (ev.type == 'mouseup' || ev.type == 'click' ) &&
+ ev.target && ev.target.tagName != 'BODY' ) { // && ev.target.tagName == 'IMG') {
+ // they have click on an image...
+ // let's see if we can change the selection...
+ sel = ev.target;
+
+ }
var ans = this.editorcore.getAllAncestors();
- if (this.formatCombo) {
+ if (!sel) {
+ sel = ans.length ? (ans[0] ? ans[0] : ans[1]) : this.editorcore.doc.body;
+ sel = sel ? sel : this.editorcore.doc.body;
+ sel = sel.tagName.length ? sel : this.editorcore.doc.body;
+ }
+
+ var lastSel = this.selectedNode;
+ this.selectedNode = sel;
+
+ // ok see if we are editing a block?
+
+ var db = false;
+ // you are not actually selecting the block.
+ if (sel && sel.hasAttribute('data-block')) {
+ db = sel;
+ } else if (sel && sel.closest('[data-block]')) {
+ db = sel.closest('[data-block]');
+ }
+
+ Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
+ e.classList.remove('roo-ed-selection');
+ });
+
+ var block = false;
+ if (db && this.editorcore.enableBlocks) {
+ block = Roo.htmleditor.Block.factory(db);
- 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 (block) {
+ db.className = (db.classList.length > 0 ? db.className + ' ' : '') +
+ ' roo-ed-selection';
+ sel = this.selectedNode = db;
}
}
+ // highlight the 'a'..
+ var tn = sel && sel.tagName.toUpperCase() || '';
+ if (!block && sel && tn != 'A') {
+ var asel = sel.closest('A');
+ if (asel) {
+ sel = asel;
+ }
+ }
+
+ btns.get('link').setActive(tn == 'A' && this.selectedNode.hasAttribute('href'));
+ btns.get('image').setActive(tn == 'IMG' || this.editorcore.enableBlocks && tn == 'FIGURE');
+ btns.get('underline').setActive(tn == 'U' || sel.closest('u') ? true : false);
-
- // hides menus... - so this cant be on a menu...
- Roo.bootstrap.MenuMgr.hideAll();
- */
Roo.bootstrap.menu.Manager.hideAll();
+
+
+
+
+
+ // handle delete button..
+ if (hasToggle || (tn.length && tn == 'BODY')) {
+ this.deleteBtn.hide();
+ return;
+
+ }
+ this.deleteBtn.show();
+
+
+
//this.editorsyncValue();
},
onFirstFocus: function() {
@@ -31243,6 +33339,61 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbarStandard, Roo.bootstrap.nav.Simpl
item.enable();
});
},
+
+ onDelete : function()
+ {
+ var range = this.editorcore.createRange();
+ var selection = this.editorcore.getSelection();
+ var sn = this.selectedNode;
+ range.setStart(sn,0);
+ range.setEnd(sn,0);
+
+
+ if (sn.hasAttribute('data-block')) {
+ var block = Roo.htmleditor.Block.factory(this.selectedNode);
+ if (block) {
+ sn = block.removeNode();
+ sn.parentNode.removeChild(sn);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ this.updateToolbar(null, null, null);
+ if (sn.tagName.toUpperCase() == 'FIGURE') {
+ this.editor.syncValue();
+ this.editor.fireEvent('imagedelete', this.editor, sn);
+ }
+
+ this.selectedNode = false;
+ this.editorcore.fireEditorEvent(false);
+ return;
+ }
+
+ }
+ if (!sn) {
+ return; // should not really happen..
+ }
+ if (sn && sn.tagName == 'BODY') {
+ return;
+ }
+ var stn = sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+
+ // remove and keep parents.
+ a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+ a.replaceTag(sn);
+
+ selection.removeAllRanges();
+ selection.addRange(range);
+ if (sn.tagName.toUpperCase() == 'IMG"') {
+ this.editor.syncValue();
+ this.editor.fireEvent('imagedelete', this.editor, sn);
+ }
+
+ this.selectedNode = false;
+ this.editorcore.fireEditorEvent(false);
+
+
+ },
+
+
toggleSourceEdit : function(sourceEditMode){
@@ -32741,10 +34892,18 @@ Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, {
this.el.removeClass(['fade','top','bottom', 'left', 'right','in',
'bs-tooltip-top','bs-tooltip-bottom', 'bs-tooltip-left', 'bs-tooltip-right']);
+
+ if(this.bindEl.attr('tooltip-class')) {
+ this.el.addClass(this.bindEl.attr('tooltip-class'));
+ }
var placement = typeof this.placement == 'function' ?
this.placement.call(this, this.el, on_el) :
this.placement;
+
+ if(this.bindEl.attr('tooltip-placement')) {
+ placement = this.bindEl.attr('tooltip-placement');
+ }
var autoToken = /\s?auto?\s?/i;
var autoPlace = autoToken.test(placement);
@@ -32834,6 +34993,9 @@ Roo.extend(Roo.bootstrap.Tooltip, Roo.bootstrap.Component, {
return;
}
//this.el.setXY([0,0]);
+ if(this.bindEl.attr('tooltip-class')) {
+ this.el.removeClass(this.bindEl.attr('tooltip-class'));
+ }
this.el.removeClass(['show', 'in']);
//this.el.hide();