/*
* Copyright 2010 Anyware Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Simple text layout
*/
Ext.define('Ametys.plugins.forms.content.layout.SimpleText', {
singleton: true,
/**
* Unlock the simple text layout : label, linefeed, field
* @param {Ametys.ribbon.element.ui.ButtonController} controller the controller calling this function
*/
act: function(controller)
{
if (!Ametys.plugins.forms.content.Layout._setLayoutOnNode(controller.getInitialConfig('value'), controller.getInitialConfig('css-class')))
{
return;
}
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
var me = this;
// first cleanup
Ametys.plugins.forms.content.Layout._cleanLayout();
// then rebuild
function macrorefactor(parentNode)
{
var br = tinyMCE.activeEditor.dom.doc.createElement("br");
br.setAttribute("class", "_mce_marker");
parentNode.appendChild(br)
while (true)
{
var element = parentNode.childNodes[0];
if (/^br$/i.test(element.tagName) && element.className == "_mce_marker")
{
// the first element is a refactored one: end of the loop
element.parentNode.removeChild(element);
break;
}
// refactor
else if (/^label$/i.test(element.tagName))
{
// does not handle now, but ensure it will be
var id = element.htmlFor;
var input = null;
if (id != null)
{
input = tinyMCE.activeEditor.dom.get(id);
if (input != null)
{
var inputform = Ametys.plugins.forms.content.Forms._getForm(controller.getCurrentField().getEditor(), input);
var labelform = Ametys.plugins.forms.content.Forms._getForm(controller.getCurrentField().getEditor(), element);
if (inputform != labelform)
{
input = null;
}
else
{
// move label after input
input.parentNode.appendChild(element);
}
}
}
if (input == null)
{
element.parentNode.removeChild(element);
}
}
else if (/^fieldset$/i.test(element.tagName))
{
element.parentNode.appendChild(element);
macrorefactor(element);
}
else if (/^legend$/i.test(element.tagName))
{
element.parentNode.appendChild(element);
}
else if (/^img$/i.test(element.tagName))
{
var label = Ametys.plugins.forms.content.Components._getLabel(element);
me._refactor(label, element);
}
else
{
Ametys.Msg.show({
title: "{{i18n PLUGINS_FORMS_FORMS_EDITOR_LAYOUT_GALLERY_SIMPLETEXT_ERROR_TITLE}}",
msg: "{{i18n PLUGINS_FORMS_FORMS_EDITOR_LAYOUT_GALLERY_SIMPLETEXT_ERROR_DESCRIPTION}} <br />"
+ "{{i18n PLUGINS_FORMS_FORMS_EDITOR_LAYOUT_GALLERY_SIMPLETEXT_ERROR_DETAILS}}<" + element.tagName + ">",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
throw "Unsupported element " + element.tagName + " during refactor"
}
}
}
macrorefactor(Ametys.plugins.forms.content.Forms._currentNode);
if (Ametys.plugins.forms.content.Forms._currentNode.childNodes.length == 0)
{
this.create();
}
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
tinyMCE.activeEditor.focus();
},
/**
* Create the simple text layout
*/
create: function()
{
Ametys.plugins.forms.content.Forms._currentNode.innerHTML = '<p><br _moz_dirty=""/></p>';
},
/**
* Insert an input text in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputText: function(name, id, inputHTML, labelHTML, more)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
// is there an empty place to remove
function isGood(node)
{
return /^(h1|h2|h3|h4|h5|h6|p|div)$/i.test(node.tagName);
}
var e = tinyMCE.activeEditor.selection.getNode();
if (/^div$/i.test(e.tagName) && e.getAttribute("form") == "form")
{
e = e.firstChild;
tinyMCE.activeEditor.selection.select(e);
}
while (!isGood(e)
&& !(/^div$/i.test(e.tagName) && e.getAttribute("form") == "form"))
{
e = e.parentNode;
}
var willRemove = null;
if (isGood(e))
{
if (e.childNodes.length == 0
|| (e.childNodes.length == 1 && /^br$/i.test(e.childNodes[0].tagName)))
{
willRemove = e;
e = e.parentNode;
}
}
var html = this._factor(labelHTML, inputHTML, more);
tinyMCE.insertHTMLAtRoot(html, 'after');
if (willRemove)
{
e.removeChild(willRemove);
}
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
if (id != null)
{
tinyMCE.activeEditor.execCommand('mceSelectNode', false, tinyMCE.activeEditor.dom.doc.getElementById(id));
}
},
/**
* Insert an text area in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertTextarea: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a select input in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertSelect: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a captcha in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertCaptcha: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a checkbox in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputCheckbox: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert an input radio in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputRadio: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a password input in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputPassword: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a cost field in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputCost: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert a file in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
* @param {String} labelHTML the html for the label
* @param {String} more additional html
*/
insertInputFile: function (name, id, inputHTML, labelHTML, more)
{
this.insertInputText(name, id, inputHTML, labelHTML, more);
},
/**
* Insert an hidden input in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
*/
insertInputHidden: function(name, id, inputHTML)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
tinyMCE.activeEditor.execCommand('mceInsertContent', false, inputHTML);
tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
tinyMCE.activeEditor.execCommand('mceSelectNode', false, tinyMCE.activeEditor.dom.doc.getElementById(id));
},
/**
* Insert a fieldset in the layout
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
*/
insertFieldset: function(id, inputHTML)
{
this.insertInputText(null, id, inputHTML, null);
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
var fieldset = tinyMCE.activeEditor.dom.doc.getElementById(id);
tinyMCE.activeEditor.execCommand('mceSelectNode', false, fieldset.childNodes[fieldset.childNodes.length - 1]);
},
/**
* Insert a submit input in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
*/
insertInputSubmit: function(name, id, inputHTML)
{
this.insertInputText(name, id, inputHTML, null, ' style="text-align: center"');
},
/**
* Insert a submit input in the layout
* @param {String} name the name of the input
* @param {String} id the id of the input
* @param {String} inputHTML the html for the input
*/
insertInputReset: function(name, id, inputHTML)
{
this.insertInputSubmit(name, id, inputHTML);
},
/**
* Move the selected input up
* @param {HTMLElement} input the input to move
*/
moveUp: function(input)
{
var e = input;
function isGood(node)
{
return /^(h1|h2|h3|h4|h5|h6|p|div)$/i.test(node.tagName);
}
while (!isGood(e)
&& !(/^div$/i.test(e.tagName) && e.getAttribute("form") == "form"))
{
e = e.parentNode;
}
if (isGood(e))
{
var p = e.previousSibling;
if (p != null && /^legend$/i.test(p.tagName))
{
p = p.previousSibling;
}
if (p == null)
{
if (/^fieldset$/i.test(e.parentNode.tagName))
{
p = e.parentNode;
}
}
else if (/^fieldset$/i.test(p.tagName))
{
p.appendChild(e);
return;
}
if (p != null)
{
p.parentNode.insertBefore(e, p);
}
}
},
/**
* Move the selected input down
* @param {HTMLElement} input the input to move
*/
moveDown: function(input)
{
var e = input;
function isGood(node)
{
return /^(h1|h2|h3|h4|h5|h6|p|div)$/i.test(node.tagName);
}
while (!isGood(e)
&& !(/^div$/i.test(e.tagName) && e.getAttribute("form") == "form"))
{
e = e.parentNode;
}
if (isGood(e))
{
var p = e.nextSibling;
if (p != null && /^legend$/i.test(p.tagName))
{
p = p.nextSibling;
}
if (p == null)
{
if (/^fieldset$/i.test(e.parentNode.tagName))
{
p = e.parentNode;
}
}
else if (/^fieldset$/i.test(p.tagName))
{
p.insertBefore(e, p.childNodes.length > 0 ? p.childNodes[0] : null);
return;
}
if (p != null)
{
p.parentNode.insertBefore(e, p.nextSibling);
}
}
},
/**
* Remove the selected input
* @param {HTMLElement} input the input
*/
remove: function(input)
{
if (Ametys.plugins.forms.content.Components._currentMovableNode != null)
{
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
function isGood(node)
{
return /^(h1|h2|h3|h4|h5|h6|p|div)$/i.test(node.tagName);
}
var e = Ametys.plugins.forms.content.Components._currentMovableNode;
while (!isGood(e) && !(/^div$/i.test(e.tagName) && e.getAttribute("form") == "form"))
{
e = e.parentNode;
}
if (isGood(e))
{
var a = e.previousSibling || e.nextSibling || e.parentNode;
e.parentNode.removeChild(e);
if (Ametys.plugins.forms.content.Forms._currentNode.childNodes.length == 0)
{
this.create();
a = Ametys.plugins.forms.content.Forms._currentNode.childNodes[0];
}
tinyMCE.activeEditor.execCommand('mceSelectNode', false, a);
}
}
},
/**
* Create the html based upon the parameters
* @param {String} labelHTML the html for the label
* @param {String} inputHTML the html for the input
* @param {String} more additional html
*/
_factor: function (labelHTML, inputHTML, more)
{
return "<p" + (more != null ? more : "") + ">"
+ (labelHTML != null && labelHTML != "" ? labelHTML + '<br _moz_dirty=""/>' : '')
+ inputHTML
+ "</p>";
},
/**
* Insert a p as the last sibling of input
* Moves label and input in it (br separated)
* @param {String} label the label
* @param {HTMLElement} input the input
*/
_refactor: function (label, input)
{
// create a new paragraph
// FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
var newP = tinyMCE.activeEditor.dom.doc.createElement("p");
input.parentNode.appendChild(newP);
if (label)
{
newP.appendChild(label);
var br = tinyMCE.activeEditor.dom.doc.createElement("br");
br.setAttribute("_moz_dirty", "");
newP.appendChild(br);
}
newP.appendChild(input);
},
});