*/
/**
* @class Roo.data.MemoryProxy
+ * @extends Roo.data.DataProxy
* An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
* to the Reader when its load method is called.
* @constructor
- * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ * @param {Object} config A config object containing the objects needed for the Store to access data,
*/
-Roo.data.MemoryProxy = function(data){
- if (data.data) {
- data = data.data;
+Roo.data.MemoryProxy = function(config){
+ var data = config;
+ if (typeof(config) != 'undefined' && typeof(config.data) != 'undefined') {
+ data = config.data;
}
Roo.data.MemoryProxy.superclass.constructor.call(this);
this.data = data;
Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
+ /**
+ * @cfg {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ */
/**
* Load data from the requested source (in this case an in-memory
* data object passed to the constructor), read the data object into
this.hexStore.push(cmd);
},
cmderror : function(cmd) {
- throw new Exception (cmd.value);
+ throw cmd.value;
},
/*
{
this.emitText();
if (this.controlWord === '') {
- this.emitError('empty control word');
+ // do we want to track this - it seems just to cause problems.
+ //this.emitError('empty control word');
} else {
this.push({
type: 'controlword',
return;
case this.tag === true: // everything
+ case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1:
+ case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":":
case typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1: // array and it matches.
case typeof(this.tag) == 'string' && this.tag == e.tagName: // array and it matches.
if (this.replaceTag && false === this.replaceTag(e)) {
}, this);
+ },
+
+
+ removeNodeKeepChildren : function( node)
+ {
+
+ ar = Array.from(node.childNodes);
+ for (var i = 0; i < ar.length; i++) {
+
+ node.removeChild(ar[i]);
+ // what if we need to walk these???
+ node.parentNode.insertBefore(ar[i], node);
+
+ }
+ node.parentNode.removeChild(node);
}
};
if (this.tag === false) {
return; // dont walk.. (you can use this to use this just to do a child removal on a single tag )
}
+ // hacky?
+ if ((typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)) {
+ this.cleanNamespace = true;
+ }
+
this.walk(cfg.node);
}
Roo.extend(Roo.htmleditor.FilterKeepChildren, Roo.htmleditor.FilterBlack,
{
-
+ cleanNamespace : false, // should really be an option, rather than using ':' inside of this tag.
replaceTag : function(node)
{
// walk children...
- //Roo.log(node);
+ //Roo.log(node.tagName);
var ar = Array.from(node.childNodes);
//remove first..
+
for (var i = 0; i < ar.length; i++) {
- if (ar[i].nodeType == 1) {
+ var e = ar[i];
+ if (e.nodeType == 1) {
if (
- (typeof(this.tag) == 'object' && this.tag.indexOf(ar[i].tagName) > -1)
+ (typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1)
|| // array and it matches
- (typeof(this.tag) == 'string' && this.tag == ar[i].tagName)
+ (typeof(this.tag) == 'string' && this.tag == e.tagName)
+ ||
+ (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1)
+ ||
+ (e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":")
) {
this.replaceTag(ar[i]); // child is blacklisted as well...
continue;
}
}
+ //Roo.log("REMOVE:" + node.tagName);
node.parentNode.removeChild(node);
return false; // don't walk children
Roo.htmleditor.FilterWord = function(cfg)
{
// no need to apply config.
- this.walk(cfg.node);
+ this.replaceDocBullets(cfg.node);
+
+ this.replaceAname(cfg.node);
+ // this is disabled as the removal is done by other filters;
+ // this.walk(cfg.node);
+
+
}
Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
node.removeChild(cn);
node.parentNode.insertBefore(cn, node);
// move node to parent - and clean it..
- this.replaceTag(cn);
+ if (cn.nodeType == 1) {
+ this.replaceTag(cn);
+ }
+
}
node.parentNode.removeChild(node);
/// no need to iterate chidlren = it's got none..
+ },
+
+ styleToObject: function(node)
+ {
+ var styles = (node.getAttribute("style") || '').split(";");
+ var ret = {};
+ Roo.each(styles, function(s) {
+ if (!s.match(/:/)) {
+ return;
+ }
+ var kv = s.split(":");
+
+ // what ever is left... we allow.
+ ret[kv[0].trim()] = kv[1];
+ });
+ return ret;
+ },
+
+
+ replaceAname : function (doc)
+ {
+ // replace all the a/name without..
+ var aa = Array.from(doc.getElementsByTagName('a'));
+ for (var i = 0; i < aa.length; i++) {
+ var a = aa[i];
+ if (a.hasAttribute("name")) {
+ a.removeAttribute("name");
+ }
+ if (a.hasAttribute("href")) {
+ continue;
+ }
+ // reparent children.
+ this.removeNodeKeepChildren(a);
+
+ }
+
+
+
+ },
+
+
+
+ replaceDocBullets : function(doc)
+ {
+ // this is a bit odd - but it appears some indents use ql-indent-1
+ //Roo.log(doc.innerHTML);
+
+ var listpara = doc.getElementsByClassName('MsoListParagraphCxSpFirst');
+ for( var i = 0; i < listpara.length; i ++) {
+ listpara.item(i).className = "MsoListParagraph";
+ }
+ // this is a bit hacky - we had one word document where h2 had a miso-list attribute.
+ var htwo = doc.getElementsByTagName('h2');
+ for( var i = 0; i < htwo.length; i ++) {
+ if (htwo.item(i).hasAttribute('style') && htwo.item(i).getAttribute('style').match(/mso-list:/)) {
+ htwo.item(i).className = "MsoListParagraph";
+ }
+ }
+ listpara = doc.getElementsByClassName('MsoNormal');
+ while(listpara.length) {
+ if (listpara.item(0).hasAttribute('style') && listpara.item(0).getAttribute('style').match(/mso-list:/)) {
+ listpara.item(0).className = "MsoListParagraph";
+ } else {
+ listpara.item(0).className = "MsoNormalx";
+ }
+ }
+ listpara = doc.getElementsByClassName('ql-indent-1');
+ while(listpara.length) {
+ this.replaceDocBullet(listpara.item(0));
+ }
+ listpara = doc.getElementsByClassName('MsoListParagraph');
+ while(listpara.length) {
+
+ this.replaceDocBullet(listpara.item(0));
+ }
+
+ },
+
+
+
+ replaceDocBullet : function(p)
+ {
+ // gather all the siblings.
+ var ns = p,
+ parent = p.parentNode,
+ doc = parent.ownerDocument,
+ items = [];
+
+
+ while (ns) {
+ if (ns.nodeType != 1) {
+ ns = ns.nextSibling;
+ continue;
+ }
+ if (!ns.className.match(/(MsoListParagraph|ql-indent-1)/i)) {
+ break;
+ }
+ if (ns.hasAttribute('style') && ns.getAttribute('style').match(/mso-list/)) {
+ items.push(ns);
+ ns = ns.nextSibling;
+ has_list = true;
+ continue;
+ }
+ var spans = ns.getElementsByTagName('span');
+ if (!spans.length) {
+ break;
+ }
+ var has_list = false;
+ for(var i = 0; i < spans.length; i++) {
+ if (spans[i].hasAttribute('style') && spans[i].getAttribute('style').match(/mso-list/)) {
+ has_list = true;
+ break;
+ }
+ }
+ if (!has_list) {
+ break;
+ }
+ items.push(ns);
+ ns = ns.nextSibling;
+
+
+ }
+ if (!items.length) {
+ ns.className = "";
+ return;
+ }
+
+ var ul = parent.ownerDocument.createElement('ul'); // what about number lists...
+ parent.insertBefore(ul, p);
+ var lvl = 0;
+ var stack = [ ul ];
+ var last_li = false;
+
+ var margin_to_depth = {};
+ max_margins = -1;
+
+ items.forEach(function(n, ipos) {
+ //Roo.log("got innertHMLT=" + n.innerHTML);
+
+ var spans = n.getElementsByTagName('span');
+ if (!spans.length) {
+ //Roo.log("No spans found");
+
+ parent.removeChild(n);
+
+
+ return; // skip it...
+ }
+
+
+
+ var style = {};
+ for(var i = 0; i < spans.length; i++) {
+
+ style = this.styleToObject(spans[i]);
+ if (typeof(style['mso-list']) == 'undefined') {
+ continue;
+ }
+
+ spans[i].parentNode.removeChild(spans[i]); // remove the fake bullet.
+ break;
+ }
+ //Roo.log("NOW GOT innertHMLT=" + n.innerHTML);
+ style = this.styleToObject(n); // mo-list is from the parent node.
+ if (typeof(style['mso-list']) == 'undefined') {
+ //Roo.log("parent is missing level");
+
+ parent.removeChild(n);
+
+ return;
+ }
+
+ var margin = style['margin-left'];
+ if (typeof(margin_to_depth[margin]) == 'undefined') {
+ max_margins++;
+ margin_to_depth[margin] = max_margins;
+ }
+ nlvl = margin_to_depth[margin] ;
+
+ if (nlvl > lvl) {
+ //new indent
+ var nul = doc.createElement('ul'); // what about number lists...
+ if (!last_li) {
+ last_li = doc.createElement('li');
+ stack[lvl].appendChild(last_li);
+ }
+ last_li.appendChild(nul);
+ stack[nlvl] = nul;
+
+ }
+ lvl = nlvl;
+
+ var nli = stack[nlvl].appendChild(doc.createElement('li'));
+ last_li = nli;
+ nli.innerHTML = n.innerHTML;
+ //Roo.log("innerHTML = " + n.innerHTML);
+ parent.removeChild(n);
+
+
+
+
+ },this);
+
+
+
+
}
+
+
+
});
/**
* @class Roo.htmleditor.FilterStyleToTag
* @param {String} text String to write out.
* @param {Boolean} raw Optional raw state if true the contents wont get encoded.
*/
- text: function(text, node)
+ text: function(in_text, node)
{
// if not in whitespace critical
- if (text.length < 1) {
+ if (in_text.length < 1) {
return;
}
+ var text = new XMLSerializer().serializeToString(document.createTextNode(in_text)); // escape it properly?
+
if (this.in_pre) {
this.html[this.html.length] = text;
return;
var pc = range.closest([ 'ol', 'ul']);
var pli = range.closest('li');
if (!pc || e.ctrlKey) {
- sel.insertNode('br', 'after');
+ // on it list, or ctrl pressed.
+ if (!e.ctrlKey) {
+ sel.insertNode('br', 'after');
+ } else {
+ // only do this if we have ctrl key..
+ var br = doc.createElement('br');
+ br.className = 'clear';
+ br.setAttribute('style', 'clear: both');
+ sel.insertNode(br, 'after');
+ }
+
this.core.undoManager.addEvent();
this.core.fireEditorEvent(e);
store : {
xtype : 'SimpleStore',
data : [
- ['auto'],
- ['50%'],
+ ['100%'],
['80%'],
- ['100%']
+ ['50%'],
+ ['20%'],
+ ['10%']
],
fields : [ 'val'],
xns : Roo.data
var ret = {
tag: 'figure',
'data-block' : 'Figure',
-
+ 'data-width' : this.width,
contenteditable : 'false',
style : {
fontSize : '16px',
lineHeight : '24px',
display : this.caption_display,
- maxWidth : this.width + ' !important',
+ maxWidth : (this.align == 'center' ? this.width : '100%' ) + ' !important',
margin: m,
- width: this.width
+ width: this.align == 'center' ? this.width : '100%'
},
this.align = this.getVal(node, 'figure', 'align');
var figcaption = this.getVal(node, 'figcaption', false);
- this.caption = this.getVal(figcaption, 'i', 'html');
+ if (figcaption !== '') {
+ this.caption = this.getVal(figcaption, 'i', 'html');
+ }
+
this.caption_display = this.getVal(node, 'figcaption', 'data-display');
//this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
- this.width = this.getVal(node, 'figcaption', 'style', 'width');
+ this.width = this.getVal(node, true, 'data-width');
//this.margin = this.getVal(node, 'figure', 'style', 'margin');
},
*/
toObject : function()
{
-
var ret = {
tag : 'td',
contenteditable : 'true', // this stops cell selection from picking the table.
c.col = cn;
}
- if (typeof(this.colWidths[cn]) == 'undefined') {
+ if (typeof(this.colWidths[cn]) == 'undefined' && c.colspan < 2) {
this.colWidths[cn] = ce.style.width;
if (this.colWidths[cn] != '') {
all_auto = false;
this.colspan += rc.colspan;
this.node.setAttribute('colspan', this.colspan);
+ var table = this.toTableArray();
+ this.normalizeWidths(table);
+ this.updateWidths(table);
},
this.colspan = 1;
for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
-
-
+
for(var c = cd.col; c < cd.col + cd.colspan; c++) {
if (r == cd.row && c == cd.col) {
this.node.removeAttribute('rowspan');
this.node.removeAttribute('colspan');
- continue;
}
var ntd = this.node.cloneNode(); // which col/row should be 0..
- ntd.removeAttribute('id'); //
- //ntd.style.width = '';
+ ntd.removeAttribute('id');
+ ntd.style.width = this.colWidths[c];
ntd.innerHTML = '';
table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1 };
}
}
this.redrawAllCells(table);
-
-
},
el.width = Math.floor(this.colWidths[c]) +'%';
el.updateElement(el.node);
}
+ if (this.colWidths[0] != false && table[r][c].colspan > 1) {
+ var el = Roo.htmleditor.Block.factory(table[r][c].cell);
+ var width = 0;
+ for(var i = 0; i < table[r][c].colspan; i ++) {
+ width += Math.floor(this.colWidths[c + i]);
+ }
+ el.width = width +'%';
+ el.updateElement(el.node);
+ }
table[r][c].cell = false; // done
}
}
},
normalizeWidths : function(table)
{
-
if (this.colWidths[0] === false) {
var nw = 100.0 / this.colWidths.length;
this.colWidths.forEach(function(w,i) {
//Roo.log("HtmlEditorCore:syncValue (EDITOR->TEXT)");
if(this.initialized){
- this.undoManager.addEvent();
+ if (this.undoManager) {
+ this.undoManager.addEvent();
+ }
var bd = (this.doc.body || this.doc.documentElement);
var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
images = parser.doc ? parser.doc.getElementsByType('pict') : [];
}
- Roo.log(images);
+ //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(); })
.filter(function(g) { return g != 'about:blank'; });
-
+ //Roo.log(html);
html = this.cleanWordChars(html);
var d = (new DOMParser().parseFromString(html, 'text/html')).body;
return false;
}
+
+
if (images.length > 0) {
+ // replace all v:imagedata - with img.
+ Roo.each(d.getElementsByTagName('v:imagedata'), function(node) {
+ node.parentNode.insertBefore(node, d.createElement('img'));
+ node.parentNode.removeChild(node);
+ });
+
+
Roo.each(d.getElementsByTagName('img'), function(img, i) {
img.setAttribute('src', images[i]);
});
}
if (this.autoClean) {
+ new Roo.htmleditor.FilterWord({ node : d });
+
new Roo.htmleditor.FilterStyleToTag({ node : d });
new Roo.htmleditor.FilterAttributes({
node : d,
- attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display'],
+ attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display', 'data-width'],
attrib_clean : ['href', 'src' ]
});
new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
// should be fonts..
- new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', 'O:P' ]} );
+ new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', ':' ]} );
new Roo.htmleditor.FilterParagraph({ node : d });
new Roo.htmleditor.FilterSpan({ node : d });
new Roo.htmleditor.FilterLongBr({ node : d });
+ new Roo.htmleditor.FilterComment({ node : d });
+
+
}
if (this.enableBlocks) {
if (this.enableBlocks) {
Roo.htmleditor.Block.initAll(this.doc.body);
}
-
+
e.preventDefault();
return false;
cleanWord : function(node)
{
new Roo.htmleditor.FilterWord({ node : node ? node : this.doc.body });
+ new Roo.htmleditor.FilterKeepChildren({node : node ? node : this.doc.body, tag : [ 'FONT', ':' ]} );
},
* a function which returns such a specification.
*/
/**
- * @cfg {String} labelAlign
+ * @cfg {String} labelAlign (left|top|right)
* Valid values are "left," "top" and "right" (defaults to "left")
*/
/**
}
});
+
/**
* @class Roo.form.Column
* @extends Roo.form.Layout
}
});
-
/**
* @class Roo.form.Row
* @extends Roo.form.Layout