/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
Element.addMethods({
pngHack: function(element) {
element = $(element);
var transparentGifPath = 'clear.gif';
// If there is valid element, it is an image and the image file ends with png:
if (Object.isElement(element) && element.tagName === 'IMG' && element.src.endsWith('.png')) {
var alphaImgSrc = element.src;
var sizingMethod = 'scale';
element.src = transparentGifPath;
}
if (alphaImgSrc) {
element.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="#{alphaImgSrc}",sizingMethod="#{sizingMethod}")'.interpolate(
{
alphaImgSrc: alphaImgSrc,
sizingMethod: sizingMethod
});
}
return element;
}
});
var IECompatibility = Class.create({
/**
* initializes the compatibility class
*/
initialize: function() {
Event.observe(document, 'dom:loaded', function() {
$$('input[type="checkbox"]').invoke('addClassName', 'checkbox');
}.bind(this));
Event.observe(window, 'load', function() {
if (Prototype.Browser.IE) {
var version = parseFloat(navigator.appVersion.split(';')[1].strip().split(' ')[1]);
if (version === 6) {
$$('img').each(function(img) {
img.pngHack();
});
$$('#typo3-menu li ul li').each(function(li) {
li.setStyle({height: '21px'});
});
}
}
});
}
});
if (Prototype.Browser.IE) {
var TYPO3IECompatibilty = new IECompatibility();
}
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* Javascript functions regarding the clickmenu
* relies on the javascript library "prototype"
*/
/**
* new clickmenu code to make an AJAX call and render the
* AJAX result in a layer next to the mouse cursor
*/
var Clickmenu = {
clickURL: 'alt_clickmenu.php',
ajax: true, // \TYPO3\CMS\Backend\Template\DocumentTemplate::isCMLayers
mousePos: { X: null, Y: null },
delayClickMenuHide: false,
/**
* main function, called from most clickmenu links
* @param table table from where info should be fetched
* @param uid the UID of the item
* @param listFr list Frame?
* @param enDisItems Items to disable / enable
* @param backPath TYPO3 backPath
* @param addParams additional params
* @return nothing
*/
show: function(table, uid, listFr, enDisItems, backPath, addParams) {
var params = 'table=' + encodeURIComponent(table) +
'&uid=' + uid +
'&listFr=' + listFr +
'&enDisItems=' + enDisItems +
'&backPath=' + backPath +
'&addParams=' + addParams;
this.callURL(params);
},
/**
* switch function that either makes an AJAX call
* or loads the request in the top frame
*
* @param params parameters added to the URL
* @return nothing
*/
callURL: function(params) {
if (this.ajax && Ajax.getTransport()) { // run with AJAX
params += '&ajax=1';
var call = new Ajax.Request(this.clickURL, {
method: 'get',
parameters: params,
onComplete: function(xhr) {
var response = xhr.responseXML;
if (!response.getElementsByTagName('data')[0]) {
var res = params.match(/&reloadListFrame=(0|1|2)(&|$)/);
var reloadListFrame = parseInt(res[1], 0);
if (reloadListFrame) {
var doc = reloadListFrame != 2 ? top.content.list_frame : top.content;
doc.location.reload(true);
}
return;
}
var menu = response.getElementsByTagName('data')[0].getElementsByTagName('clickmenu')[0];
var data = menu.getElementsByTagName('htmltable')[0].firstChild.data;
var level = menu.getElementsByTagName('cmlevel')[0].firstChild.data;
this.populateData(data, level);
}.bind(this)
});
}
},
/**
* fills the clickmenu with content and displays it correctly
* depending on the mouse position
* @param data the data that will be put in the menu
* @param level the depth of the clickmenu
*/
populateData: function(data, level) {
if (!$('contentMenu0')) {
this.addClickmenuItem();
}
level = parseInt(level, 10) || 0;
var obj = $('contentMenu' + level);
if (obj && (level === 0 || Element.visible('contentMenu' + (level-1)))) {
obj.innerHTML = data;
var x = this.mousePos.X;
var y = this.mousePos.Y;
var dimsWindow = document.viewport.getDimensions();
dimsWindow.width = dimsWindow.width-20; // saving margin for scrollbars
var dims = Element.getDimensions(obj); // dimensions for the clickmenu
var offset = document.viewport.getScrollOffsets();
var relative = { X: this.mousePos.X - offset.left, Y: this.mousePos.Y - offset.top };
// adjusting the Y position of the layer to fit it into the window frame
// if there is enough space above then put it upwards,
// otherwise adjust it to the bottom of the window
if (dimsWindow.height - dims.height < relative.Y) {
if (relative.Y > dims.height) {
y -= (dims.height - 10);
} else {
y += (dimsWindow.height - dims.height - relative.Y);
}
}
// adjusting the X position like Y above, but align it to the left side of the viewport if it does not fit completely
if (dimsWindow.width - dims.width < relative.X) {
if (relative.X > dims.width) {
x -= (dims.width - 10);
} else if ((dimsWindow.width - dims.width - relative.X) < offset.left) {
x = offset.left;
} else {
x += (dimsWindow.width - dims.width - relative.X);
}
}
obj.style.left = x + 'px';
obj.style.top = y + 'px';
Element.show(obj);
}
if (/MSIE5/.test(navigator.userAgent)) {
this._toggleSelectorBoxes('hidden');
}
},
/**
* event handler function that saves the actual position of the mouse
* in the Clickmenu object
* @param event the event object
*/
calcMousePosEvent: function(event) {
if (!event) {
event = window.event;
}
this.mousePos.X = Event.pointerX(event);
this.mousePos.Y = Event.pointerY(event);
this.mouseOutFromMenu('contentMenu0');
this.mouseOutFromMenu('contentMenu1');
},
/**
* hides a visible menu if the mouse has moved outside
* of the object
* @param obj the object to hide
* @result nothing
*/
mouseOutFromMenu: function(obj) {
obj = $(obj);
if (obj && Element.visible(obj) && !Position.within(obj, this.mousePos.X, this.mousePos.Y)) {
this.hide(obj);
if (/MSIE5/.test(navigator.userAgent) && obj.id === 'contentMenu0') {
this._toggleSelectorBoxes('visible');
}
} else if (obj && Element.visible(obj)) {
this.delayClickMenuHide = true;
}
},
/**
* hides a clickmenu
*
* @param obj the clickmenu object to hide
* @result nothing
*/
hide: function(obj) {
this.delayClickMenuHide = false;
window.setTimeout(function() {
if (!Clickmenu.delayClickMenuHide) {
Element.hide(obj);
}
}, 500);
},
/**
* hides all clickmenus
*/
hideAll: function() {
this.hide('contentMenu0');
this.hide('contentMenu1');
},
/**
* hides / displays all selector boxes in a page, fixes an IE 5 selector problem
* originally by Michiel van Leening
*
* @param action hide (= "hidden") or show (= "visible")
* @result nothing
*/
_toggleSelectorBoxes: function(action) {
for (var i = 0; i < document.forms.length; i++) {
for (var j = 0; j < document.forms[i].elements.length; j++) {
if (document.forms[i].elements[j].type == 'select-one') {
document.forms[i].elements[j].style.visibility = action;
}
}
}
},
/**
* manipulates the DOM to add the divs needed for clickmenu at the bottom of the
-tag
*
* @return nothing
*/
addClickmenuItem: function() {
var code = '';
var insert = new Insertion.Bottom(document.getElementsByTagName('body')[0], code);
}
}
// register mouse movement inside the document
Event.observe(document, 'mousemove', Clickmenu.calcMousePosEvent.bindAsEventListener(Clickmenu), true);
// @deprecated: Deprecated functions since 4.2, here for compatibility, remove in 4.4+
// ## BEGIN ##
// Still used in Core: typo3/alt_clickmenu.php::linkItem()
function showClickmenu_raw(url) {
var parts = url.split('?');
if (parts.length === 2) {
Clickmenu.clickURL = parts[0];
Clickmenu.callURL(parts[1]);
} else {
Clickmenu.callURL(url);
}
}
function showClickmenu_noajax(url) {
Clickmenu.ajax = false; showClickmenu_raw(url);
}
function setLayerObj(tableData, cmLevel) {
Clickmenu.populateData(tableData, cmLevel);
}
function hideEmpty() {
Clickmenu.hideAll();
return false;
}
function hideSpecific(level) {
if (level === 0 || level === 1) {
Clickmenu.hide('contentMenu'+level);
}
}
function showHideSelectorBoxes(action) {
toggleSelectorBoxes(action);
}
// ## END ##
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
Ext.ns('TYPO3.Components', 'TYPO3.Components.Tree');
/**
* TYPO3window - General TYPO3 tree component
*/
TYPO3.Components.Tree = {};
TYPO3.Components.Tree.StandardTreeItemData = [];
TYPO3.Components.Tree.StandardTree = function(config) {
var conf = Ext.apply({
header: false,
width: 280,
rootVisible: false,
useArrows: false,
lines: true,
autoScroll: true,
containerScroll: true,
exclusiveSelectedKey: null,
stateful: true,
filterOptionStartsWith: true,
countSelectedNodes: 0,
loader: new Ext.tree.TreeLoader({
preloadChildren: true,
clearOnLoad: false
}),
root: new Ext.tree.AsyncTreeNode({
text: TYPO3.l10n.localize('tcatree'),
id: 'root',
expanded: true,
children: TYPO3.Components.Tree.StandardTreeItemData[config.id]
}),
collapseFirst: false,
listeners: {
'checkchange': function(checkedNode, checked) {
if (Ext.isFunction(this.checkChangeHandler)) {
this.checkChangeHandler.call(this, checkedNode, checked);
}
},
scope: this
}
}, config);
TYPO3.Components.Tree.StandardTree.superclass.constructor.call(this, conf);
};
Ext.extend(TYPO3.Components.Tree.StandardTree, Ext.tree.TreePanel, {
initComponent: function() {
Ext.apply(this, {
tbar: this.initialConfig.showHeader ? TYPO3.Components.Tree.Toolbar([], this) : null
});
TYPO3.Components.Tree.StandardTree.superclass.initComponent.call(this);
},
filterTree: function(filterText) {
var text = filterText.getValue();
Ext.each(this.hiddenNodes, function(node) {
node.ui.show();
node.ui.removeClass('bgColor6');
});
if (!text) {
this.filter.clear();
return;
}
this.expandAll();
var regText = (this.filterOptionStartsWith ? '^' : '') + Ext.escapeRe(text);
var re = new RegExp(regText, 'i');
// hide empty nodes that weren't filtered
this.hiddenNodes = [];
var me = this;
this.root.cascade(function(node) {
if (node.ui.ctNode.offsetHeight < 3) {
if (!re.test(node.text)) {
node.ui.hide();
me.hiddenNodes.push(node);
} else {
node.ui.addClass('bgColor6');
}
}
}, this);
}
});
TYPO3.Components.Tree.Toolbar = function(items, scope) {
items = items || [];
items.push([
' ',
{
iconCls: 't3-icon t3-icon-actions t3-icon-actions-system t3-icon-system-tree-search-open',
menu: {
items: [
{
text: TYPO3.l10n.localize('tcatree.filter.startsWith'),
checked: true,
group: 'searchStartsWith',
handler: function(item) {
scope.filterOptionStartsWith = true;
scope.filterTree(scope.getTopToolbar().getComponent('filterText'));
},
scope: scope
},
{
text: TYPO3.l10n.localize('tcatree.filter.contains'),
checked: false,
group: 'searchStartsWith',
handler: function(item) {
scope.filterOptionStartsWith = false;
scope.filterTree(scope.getTopToolbar().getComponent('filterText'));
},
scope: scope
}
]
}
},
new Ext.form.TextField({
width: 150,
emptyText: TYPO3.l10n.localize('tcatree.findItem'),
enableKeyEvents: true,
itemId: 'filterText',
listeners:{
render: function(f) {
this.filter = new Ext.tree.TreeFilter(this, {
clearBlank: true,
autoClear: true
});
},
keydown: {
fn: scope.filterTree,
buffer: 350,
scope: scope
},
scope: scope
}
}),
'->',
{
iconCls: 't3-icon t3-icon-apps t3-icon-apps-tcatree t3-icon-tcatree-select-recursive',
tooltip: TYPO3.lang['tcatree.enableRecursiveSelection'],
enableToggle: true,
disable: scope.tcaSelectRecursive,
toggleHandler: function(btn, state) {
this.tcaSelectRecursive = state;
},
scope: scope
},
{
iconCls: 'icon-expand-all',
tooltip: TYPO3.l10n.localize('tcatree.expandAll'),
handler: function() {
this.root.expand(true);
},
scope: scope
}, {
iconCls: 'icon-collapse-all',
tooltip: TYPO3.l10n.localize('tcatree.collapseAll'),
handler: function() {
this.root.collapse(true);
},
scope: scope
}
]);
return items;
};
TYPO3.Components.Tree.EmptySelectionModel = new Ext.tree.DefaultSelectionModel({
select: Ext.emptyFn
})
TYPO3.Components.Tree.TcaCheckChangeHandler = function(checkedNode, checked) {
var exclusiveKeys = this.tcaExclusiveKeys.split(','),
uid = '' + checkedNode.attributes.uid;
this.suspendEvents();
if (this.tcaExclusiveKeys.length) {
if (checked === true && exclusiveKeys.indexOf(uid) > -1) {
// this key is exclusive, so uncheck all others
this.root.cascade(function(node) {
if (node !== checkedNode && node.attributes.checked) {
node.attributes.checked = false;
node.ui.toggleCheck(false);
}
});
this.exclusiveSelectedKey = uid;
} else if (checked === true && exclusiveKeys.indexOf(uid) === -1 && !Ext.isEmpty(this.exclusiveSelectedKey)) {
// this key is exclusive, so uncheck all others
this.root.cascade(function(node) {
if (exclusiveKeys.indexOf('' + node.attributes.uid) > -1) {
node.attributes.checked = false;
node.ui.toggleCheck(false);
}
});
this.exclusiveSelectedKey = null;
}
}
if (checked === true && this.countSelectedNodes >= this.tcaMaxItems) {
checkedNode.attributes.checked = false;
checkedNode.getUI().toggleCheck(false);
this.resumeEvents();
return false;
}
if (checked) {
checkedNode.getUI().addClass('complete');
} else {
checkedNode.getUI().removeClass('complete');
}
// if recursive selection is asked, hand over selection
if(this.tcaSelectRecursive) {
checkedNode.cascade(function(node) {
node.attributes.checked = checkedNode.attributes.checked;
node.ui.toggleCheck(checkedNode.attributes.checked);
})
}
var selected = [];
this.root.cascade(function(node) {
if (node.ui.isChecked()) {
selected.push(node.attributes.uid);
}
});
this.countSelectedNodes = selected.length;
Ext.fly('treeinput' + this.id).dom.value = selected.join(',');
eval(this.onChange);
this.resumeEvents();
};
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* javascript functions regarding the "dyntabmenu" used throughout the TYPO3 backend
*/
var DTM_array = DTM_array || [];
// if tabs are used in a popup window the array might not exists
if (!top.DTM_currentTabs) {
top.DTM_currentTabs = [];
}
function DTM_activate(idBase,index,doToogle) {
// Check, whether the given index really exists
if (!document.getElementById(idBase+'-'+index+'-MENU')) {
// force the index to be the first one in case of saved settings are not valid anymore
index = 1;
}
// Hiding all:
if (DTM_array[idBase]) {
for(var cnt = 0; cnt < DTM_array[idBase].length; cnt++) {
if (DTM_array[idBase][cnt] !== idBase + '-' + index) {
document.getElementById(DTM_array[idBase][cnt]+'-DIV').style.display = 'none';
// Only Overriding when Tab not disabled
if (document.getElementById(DTM_array[idBase][cnt]+'-MENU').attributes.getNamedItem('class').nodeValue !== 'disabled') {
document.getElementById(DTM_array[idBase][cnt]+'-MENU').attributes.getNamedItem('class').nodeValue = 'tab';
}
}
}
}
// Showing one:
if (document.getElementById(idBase+'-'+index+'-DIV')) {
if (doToogle && document.getElementById(idBase+'-'+index+'-DIV').style.display === 'block') {
document.getElementById(idBase+'-'+index+'-DIV').style.display = 'none';
document.getElementById(idBase+'-'+index+'-MENU').attributes.getNamedItem('class').nodeValue = 'tab';
top.DTM_currentTabs[idBase] = -1;
} else {
document.getElementById(idBase+'-'+index+'-DIV').style.display = 'block';
document.getElementById(idBase+'-'+index+'-MENU').attributes.getNamedItem('class').nodeValue = 'tabact';
top.DTM_currentTabs[idBase] = index;
}
}
document.getElementById(idBase+'-'+index+'-MENU').attributes.getNamedItem('class').nodeValue = 'tabact';
}
function DTM_toggle(idBase,index,isInit) {
// Showing one:
if (document.getElementById(idBase+'-'+index+'-DIV')) {
if (document.getElementById(idBase+'-'+index+'-DIV').style.display === 'block') {
document.getElementById(idBase+'-'+index+'-DIV').style.display = 'none';
if (isInit) {
document.getElementById(idBase+'-'+index+'-MENU').attributes.getNamedItem('class').nodeValue = 'tab';
}
top.DTM_currentTabs[idBase+'-'+index] = 0;
} else {
document.getElementById(idBase+'-'+index+'-DIV').style.display = 'block';
if (isInit) {
document.getElementById(idBase+'-'+index+'-MENU').attributes.getNamedItem('class').nodeValue = 'tabact';
}
top.DTM_currentTabs[idBase+'-'+index] = 1;
}
}
}
/**
*
* MD5 (Message-Digest Algorithm)
* http://www.webtoolkit.info/
*
**/
function MD5(string) {
function RotateLeft(lValue, iShiftBits) {
return (lValue<>>(32-iShiftBits));
}
function AddUnsigned(lX,lY) {
var lX4,lY4,lX8,lY8,lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
}
function F(x,y,z) { return (x & y) | ((~x) & z); }
function G(x,y,z) { return (x & z) | (y & (~z)); }
function H(x,y,z) { return (x ^ y ^ z); }
function I(x,y,z) { return (y ^ (x | (~z))); }
function FF(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function GG(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function HH(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function II(a,b,c,d,x,s,ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};
function ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1=lMessageLength + 8;
var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
var lWordArray=Array(lNumberOfWords-1);
var lBytePosition = 0;
var lByteCount = 0;
while ( lByteCount < lMessageLength ) {
lWordCount = (lByteCount-(lByteCount % 4))/4;
lBytePosition = (lByteCount % 4)*8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
return lWordArray;
};
function WordToHex(lValue) {
var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
for (lCount = 0;lCount<=3;lCount++) {
lByte = (lValue>>>(lCount*8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
}
return WordToHexValue;
};
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
var x=Array();
var k,AA,BB,CC,DD,a,b,c,d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = Utf8Encode(string);
x = ConvertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k=0;kThis class implements a "virtual element" at a relative size and position
* within an existing element. It provides mouse events from a zone of an element of
* defined dimensions.
*
The zone is defined using top, right, bottom,
* left, width and height options which specify
* the bounds of the zone in a similar manner to the CSS style properties of those names.
* @cfg {String|HtmlElement} el The element in which to create the zone.
* @cfg {Array} points An Array of points within the element defining the event zone.
* @cfg {Number} top The top of the zone. If negative means an offset from the bottom.
* @cfg {Number} right The right of the zone. If negative means an offset from the right.
* @cfg {Number} left The left of the zone. If negative means an offset from the right.
* @cfg {Number} bottom The bottom of the zone. If negative means an offset from the bottom.
* @cfg {Number} width The width of the zone.
* @cfg {Number} height The height of the zone.
* @constructor
* Create a new EventZone
* @param {Object} config The config object.
*/
Ext.ux.EventZone = Ext.extend(Ext.util.Observable, {
constructor: function(config) {
this.initialConfig = config;
this.addEvents(
/**
* @event mouseenter
* This event fires when the mouse enters the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'mouseenter',
/**
* @event mousedown
* This event fires when the mouse button is depressed within the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'mousedown',
/**
* @event mousemove
* This event fires when the mouse moves within the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'mousemove',
/**
* @event mouseup
* This event fires when the mouse button is released within the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'mouseup',
/**
* @event mouseenter
* This event fires when the mouse is clicked within the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'click',
/**
* @event mouseleave
* This event fires when the mouse leaves the zone.
* @param {EventObject} e the underlying mouse event.
* @param {EventZone} this
*/
'mouseleave'
);
Ext.apply(this, config);
this.el = Ext.get(this.el);
// If a polygon within the element is specified...
if (this.points) {
this.polygon = new Ext.lib.Polygon(this.points);
this.points = this.polygon.points;
}
Ext.ux.EventZone.superclass.constructor.call(this);
this.el.on({
mouseenter: this.handleMouseEvent,
mousedown: this.handleMouseEvent,
mousemove: this.handleMouseEvent,
mouseup: this.handleMouseEvent,
click: this.handleMouseEvent,
mouseleave: this.handleMouseEvent,
scope: this
});
},
handleMouseEvent: function(e) {
var r = this.polygon ? this.getPolygon() : this.getRegion();
var inBounds = r.contains(e.getPoint());
switch (e.type) {
// mouseenter fires this
case 'mouseover':
if (inBounds) {
this.mouseIn = true;
this.fireEvent('mouseenter', e, this);
}
break;
// mouseleave fires this
case 'mouseout':
this.mouseIn = false;
this.fireEvent('mouseleave', e, this);
break;
case 'mousemove':
if (inBounds) {
if (this.mouseIn) {
this.fireEvent('mousemove', e, this);
} else {
this.mouseIn = true;
this.fireEvent('mouseenter', e, this);
}
} else {
if (this.mouseIn) {
this.mouseIn = false;
this.fireEvent('mouseleave', e, this);
}
}
break;
default:
if (inBounds) {
this.fireEvent(e.type, e, this);
}
}
},
getPolygon: function() {
var xy = this.el.getXY();
return this.polygon.translate(xy[0], xy[1]);
},
getRegion: function() {
var r = this.el.getRegion();
// Adjust left boundary of region
if (Ext.isNumber(this.left)) {
if (this.left < 0) {
r.left = r.right + this.left;
} else {
r.left += this.left;
}
}
// Adjust right boundary of region
if (Ext.isNumber(this.width)) {
r.right = r.left + this.width;
} else if (Ext.isNumber(this.right)) {
r.right = (this.right < 0) ? r.right + this.right : r.left + this.right;
}
// Adjust top boundary of region
if (Ext.isNumber(this.top)) {
if (this.top < 0) {
r.top = r.bottom + this.top;
} else {
r.top += this.top;
}
}
// Adjust bottom boundary of region
if (Ext.isNumber(this.height)) {
r.bottom = r.top + this.height;
} else if (Ext.isNumber(this.bottom)) {
r.bottom = (this.bottom < 0) ? r.bottom + this.bottom : r.top + this.bottom;
}
return r;
}
});
/**
* @class Ext.lib.Polygon
*
This class encapsulates an absolute area of the document bounded by a list of points.
* @constructor
* Create a new Polygon
* @param {Object} points An Array of [n,n] point specification Arrays, or
* an Array of Ext.lib.Points, or an HtmlElement, or an Ext.lib.Region.
*/
Ext.lib.Polygon = Ext.extend(Ext.lib.Region, {
constructor: function(points) {
var i, l, el;
if (l = points.length) {
if (points[0].x) {
for (i = 0; i < l; i++) {
points[i] = [ points[i].x, points[i].y ];
}
}
this.points = points;
} else {
if (el = Ext.get(points)) {
points = Ext.lib.Region.getRegion(el.dom);
}
if (points instanceof Ext.lib.Region) {
this.points = [
[points.left, points.top],
[points.right, points.top],
[points.right, points.bottom],
[points.left, points.bottom]
];
}
}
},
/**
* Returns a new Polygon translated by the specified X and Y increments.
* @param xDelta {Number} The X translation increment.
* @param xDelta {Number} The Y translation increment.
* @return {Polygon} The resulting Polygon.
*/
translate: function(xDelta, yDelta) {
var r = [], p = this.points, l = p.length, i;
for (i = 0; i < l; i++) {
r[i] = [ p[i][0] + xDelta, p[i][1] + yDelta ];
}
return new Ext.lib.Polygon(r);
},
/**
* Returns the area of this Polygon.
*/
getArea: function() {
var p = this.points, l = p.length, area = 0, i, j = 0;
for (i = 0; i < l; i++) {
j++;
if (j == l) {
j = 0;
}
area += (p[i][0] + p[j][0]) * (p[i][1] - p[j][1]);
}
return area * 0.5;
},
/**
* Returns true if this Polygon contains the specified point. Thanks
* to http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html for the algorithm.
* @param pt {Point|Number} Either an Ext.lib.Point object, or the X coordinate to test.
* @param py {Number} Optional. If the first parameter was an X coordinate, this is the Y coordinate.
*/
contains: function(pt, py) {
var f = (arguments.length == 1),
testX = f ? pt.x : pt,
testY = f ? pt.y : py,
p = this.points,
nvert = p.length,
j = nvert - 1,
i, j, c = false;
for (i = 0; i < nvert; j = i++) {
if ( ((p[i][1] > testY) != (p[j][1] > testY)) &&
(testX < (p[j][0]-p[i][0]) * (testY-p[i][1]) / (p[j][1]-p[i][1]) + p[i][0])) {
c = !c;
}
}
return c;
}
});
/**
* @class Ext.Resizable
* @extends Ext.util.Observable
* This is an override of Ext.Resizable to make usage of the Ex.ux.EventZone
*
Applies virtual drag handles to an element to make it resizable.
*
Here is the list of valid resize handles:
*
Value Description
------ -------------------
'n' north
's' south
'e' east
'w' west
'nw' northwest
'sw' southwest
'se' southeast
'ne' northeast
'all' all
*
Here's an example showing the creation of a typical Resizable:
To hide a particular handle, set its display to none in CSS, or through script:
* resizer.east.setDisplayed(false);
* @constructor
* Create a new resizable component
* @param {Mixed} el The id or element to resize
* @param {Object} config configuration options
*/
Ext.Resizable = function(el, config){
this.el = Ext.get(el);
/**
* The proxy Element that is resized in place of the real Element during the resize operation.
* This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.
* Read only.
* @type Ext.Element.
* @property proxy
*/
this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
this.proxy.unselectable();
this.proxy.enableDisplayMode('block');
Ext.apply(this, config);
if(this.pinned){
this.disableTrackOver = true;
this.el.addClass('x-resizable-pinned');
}
// if the element isn't positioned, make it relative
var position = this.el.getStyle('position');
if(position != 'absolute' && position != 'fixed'){
this.el.setStyle('position', 'relative');
}
if(!this.handles){ // no handles passed, must be legacy style
this.handles = 's,e,se';
if(this.multiDirectional){
this.handles += ',n,w';
}
}
if(this.handles == 'all'){
this.handles = 'n s e w ne nw se sw';
}
var hs = this.handles.split(/\s*?[,;]\s*?| /);
var ps = Ext.Resizable.positions;
for(var i = 0, len = hs.length; i < len; i++){
if(hs[i] && ps[hs[i]]){
var pos = ps[hs[i]];
this[pos] = new Ext.Resizable.Handle(this, pos);
}
}
// legacy
this.corner = this.southeast;
if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
this.updateBox = true;
}
this.activeHandle = null;
if(this.adjustments == 'auto'){
var hw = this.west, he = this.east, hn = this.north, hs = this.south;
this.adjustments = [
(he.el ? -he.el.getWidth() : 0) + (hw.el ? -hw.el.getWidth() : 0),
(hn.el ? -hn.el.getHeight() : 0) + (hs.el ? -hs.el.getHeight() : 0) -1
];
}
if(this.draggable){
this.dd = this.dynamic ?
this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
this.dd.setHandleElId(this.el.id);
}
this.addEvents(
/**
* @event beforeresize
* Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.
* @param {Ext.Resizable} this
* @param {Ext.EventObject} e The mousedown event
*/
'beforeresize',
/**
* @event resize
* Fired after a resize.
* @param {Ext.Resizable} this
* @param {Number} width The new width
* @param {Number} height The new height
* @param {Ext.EventObject} e The mouseup event
*/
'resize'
);
if(this.width !== null && this.height !== null){
this.resizeTo(this.width, this.height);
}
if(Ext.isIE){
this.el.dom.style.zoom = 1;
}
Ext.Resizable.superclass.constructor.call(this);
};
Ext.extend(Ext.Resizable, Ext.util.Observable, {
/**
* @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be added to the
* resize operation's new size (defaults to [0, 0])
*/
adjustments : [0, 0],
/**
* @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
*/
animate : false,
/**
* @cfg {Mixed} constrainTo Constrain the resize to a particular element
*/
/**
* @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
*/
draggable: false,
/**
* @cfg {Number} duration Animation duration if animate = true (defaults to 0.35)
*/
duration : 0.35,
/**
* @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
*/
dynamic : false,
/**
* @cfg {String} easing Animation easing if animate = true (defaults to 'easingOutStrong')
*/
easing : 'easeOutStrong',
/**
* @cfg {Boolean} enabled False to disable resizing (defaults to true)
*/
enabled : true,
/**
* @property enabled Writable. False if resizing is disabled.
* @type Boolean
*/
/**
* @cfg {String} handles String consisting of the resize handles to display (defaults to undefined).
* Specify either 'all' or any of 'n s e w ne nw se sw'.
*/
handles : false,
/**
* @cfg {Boolean} multiDirectional Deprecated. Deprecated style of adding multi-direction resize handles.
*/
multiDirectional : false,
/**
* @cfg {Number} height The height of the element in pixels (defaults to null)
*/
height : null,
/**
* @cfg {Number} width The width of the element in pixels (defaults to null)
*/
width : null,
/**
* @cfg {Number} heightIncrement The increment to snap the height resize in pixels
* (only applies if {@link #dynamic}==true). Defaults to 0.
*/
heightIncrement : 0,
/**
* @cfg {Number} widthIncrement The increment to snap the width resize in pixels
* (only applies if {@link #dynamic}==true). Defaults to 0.
*/
widthIncrement : 0,
/**
* @cfg {Number} minHeight The minimum height for the element (defaults to 5)
*/
minHeight : 5,
/**
* @cfg {Number} minWidth The minimum width for the element (defaults to 5)
*/
minWidth : 5,
/**
* @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
*/
maxHeight : 10000,
/**
* @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
*/
maxWidth : 10000,
/**
* @cfg {Number} minX The minimum x for the element (defaults to 0)
*/
minX: 0,
/**
* @cfg {Number} minY The minimum x for the element (defaults to 0)
*/
minY: 0,
/**
* @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
* user mouses over the resizable borders. This is only applied at config time. (defaults to false)
*/
pinned : false,
/**
* @cfg {Boolean} preserveRatio True to preserve the original ratio between height
* and width during resize (defaults to false)
*/
preserveRatio : false,
/**
* @cfg {Ext.lib.Region} resizeRegion Constrain the resize to a particular region
*/
/**
* Perform a manual resize and fires the 'resize' event.
* @param {Number} width
* @param {Number} height
*/
resizeTo : function(width, height){
this.el.setSize(width, height);
this.fireEvent('resize', this, width, height, null);
},
// private
startSizing : function(e, handle){
this.fireEvent('beforeresize', this, e);
if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
e.stopEvent();
Ext.getDoc().on({
scope: this,
mousemove: this.onMouseMove,
mouseup: {
fn: this.onMouseUp,
single: true,
scope: this
}
});
Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
this.resizing = true;
this.startBox = this.el.getBox();
this.startPoint = e.getXY();
this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
(this.startBox.y + this.startBox.height) - this.startPoint[1]];
if(this.constrainTo) {
var ct = Ext.get(this.constrainTo);
this.resizeRegion = ct.getRegion().adjust(
ct.getFrameWidth('t'),
ct.getFrameWidth('l'),
-ct.getFrameWidth('b'),
-ct.getFrameWidth('r')
);
}
this.proxy.setStyle('visibility', 'hidden'); // workaround display none
this.proxy.show();
this.proxy.setBox(this.startBox);
if(!this.dynamic){
this.proxy.setStyle('visibility', 'visible');
}
}
},
// private
onMouseDown : function(handle, e){
if(this.enabled && !this.activeHandle){
e.stopEvent();
this.activeHandle = handle;
this.startSizing(e, handle);
}
},
// private
onMouseUp : function(e){
Ext.getBody().removeClass('ux-resizable-handle-' + this.activeHandle.position)
.un('mousemove', this.onMouseMove, this);
var size = this.resizeElement();
this.resizing = false;
this.handleOut(this.activeHandle);
this.proxy.hide();
this.fireEvent('resize', this, size.width, size.height, e);
this.activeHandle = null;
},
// private
snap : function(value, inc, min){
if(!inc || !value){
return value;
}
var newValue = value;
var m = value % inc;
if(m > 0){
if(m > (inc/2)){
newValue = value + (inc-m);
}else{
newValue = value - m;
}
}
return Math.max(min, newValue);
},
/**
*
Performs resizing of the associated Element. This method is called internally by this
* class, and should not be called by user code.
*
If a Resizable is being used to resize an Element which encapsulates a more complex UI
* component such as a Panel, this method may be overridden by specifying an implementation
* as a config option to provide appropriate behaviour at the end of the resize operation on
* mouseup, for example resizing the Panel, and relaying the Panel's content.
*
The new area to be resized to is available by examining the state of the {@link #proxy}
* Element. Example:
*/
resizeElement : function(){
var box = this.proxy.getBox();
if(this.updateBox){
this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
}else{
this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
}
if(!this.dynamic){
this.proxy.hide();
}
return box;
},
// private
constrain : function(v, diff, m, mx){
if(v - diff < m){
diff = v - m;
}else if(v - diff > mx){
diff = v - mx;
}
return diff;
},
// private
onMouseMove : function(e){
if(this.enabled && this.activeHandle){
try{// try catch so if something goes wrong the user doesn't get hung
if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
return;
}
//var curXY = this.startPoint;
var curSize = this.curSize || this.startBox,
x = this.startBox.x, y = this.startBox.y,
ox = x,
oy = y,
w = curSize.width,
h = curSize.height,
ow = w,
oh = h,
mw = this.minWidth,
mh = this.minHeight,
mxw = this.maxWidth,
mxh = this.maxHeight,
wi = this.widthIncrement,
hi = this.heightIncrement,
eventXY = e.getXY(),
diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
pos = this.activeHandle.position,
tw,
th;
switch(pos){
case 'east':
w += diffX;
w = Math.min(Math.max(mw, w), mxw);
break;
case 'south':
h += diffY;
h = Math.min(Math.max(mh, h), mxh);
break;
case 'southeast':
w += diffX;
h += diffY;
w = Math.min(Math.max(mw, w), mxw);
h = Math.min(Math.max(mh, h), mxh);
break;
case 'north':
diffY = this.constrain(h, diffY, mh, mxh);
y += diffY;
h -= diffY;
break;
case 'west':
diffX = this.constrain(w, diffX, mw, mxw);
x += diffX;
w -= diffX;
break;
case 'northeast':
w += diffX;
w = Math.min(Math.max(mw, w), mxw);
diffY = this.constrain(h, diffY, mh, mxh);
y += diffY;
h -= diffY;
break;
case 'northwest':
diffX = this.constrain(w, diffX, mw, mxw);
diffY = this.constrain(h, diffY, mh, mxh);
y += diffY;
h -= diffY;
x += diffX;
w -= diffX;
break;
case 'southwest':
diffX = this.constrain(w, diffX, mw, mxw);
h += diffY;
h = Math.min(Math.max(mh, h), mxh);
x += diffX;
w -= diffX;
break;
}
var sw = this.snap(w, wi, mw);
var sh = this.snap(h, hi, mh);
if(sw != w || sh != h){
switch(pos){
case 'northeast':
y -= sh - h;
break;
case 'north':
y -= sh - h;
break;
case 'southwest':
x -= sw - w;
break;
case 'west':
x -= sw - w;
break;
case 'northwest':
x -= sw - w;
y -= sh - h;
break;
}
w = sw;
h = sh;
}
if(this.preserveRatio){
switch(pos){
case 'southeast':
case 'east':
h = oh * (w/ow);
h = Math.min(Math.max(mh, h), mxh);
w = ow * (h/oh);
break;
case 'south':
w = ow * (h/oh);
w = Math.min(Math.max(mw, w), mxw);
h = oh * (w/ow);
break;
case 'northeast':
w = ow * (h/oh);
w = Math.min(Math.max(mw, w), mxw);
h = oh * (w/ow);
break;
case 'north':
tw = w;
w = ow * (h/oh);
w = Math.min(Math.max(mw, w), mxw);
h = oh * (w/ow);
x += (tw - w) / 2;
break;
case 'southwest':
h = oh * (w/ow);
h = Math.min(Math.max(mh, h), mxh);
tw = w;
w = ow * (h/oh);
x += tw - w;
break;
case 'west':
th = h;
h = oh * (w/ow);
h = Math.min(Math.max(mh, h), mxh);
y += (th - h) / 2;
tw = w;
w = ow * (h/oh);
x += tw - w;
break;
case 'northwest':
tw = w;
th = h;
h = oh * (w/ow);
h = Math.min(Math.max(mh, h), mxh);
w = ow * (h/oh);
y += th - h;
x += tw - w;
break;
}
}
this.proxy.setBounds(x, y, w, h);
if(this.dynamic){
this.resizeElement();
}
}catch(ex){}
}
},
// private
handleOver : function(handle){
if(this.enabled){
Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
}
},
// private
handleOut : function(handle){
if(!this.resizing){
Ext.getBody().removeClass('ux-resizable-handle-' + handle.position);
}
},
/**
* Returns the element this component is bound to.
* @return {Ext.Element}
*/
getEl : function(){
return this.el;
},
/**
* Destroys this resizable. If the element was wrapped and
* removeEl is not true then the element remains.
* @param {Boolean} removeEl (optional) true to remove the element from the DOM
*/
destroy : function(removeEl){
Ext.destroy(this.dd, this.proxy);
this.proxy = null;
var ps = Ext.Resizable.positions;
for(var k in ps){
if(typeof ps[k] != 'function' && this[ps[k]]){
this[ps[k]].destroy();
}
}
if(removeEl){
this.el.update('');
Ext.destroy(this.el);
this.el = null;
}
this.purgeListeners();
},
syncHandleHeight : function(){
var h = this.el.getHeight(true);
if(this.west.el){
this.west.el.setHeight(h);
}
if(this.east.el){
this.east.el.setHeight(h);
}
}
});
// private
// hash to map config positions to true positions
Ext.Resizable.positions = {
n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
};
Ext.Resizable.cfg = {
north: {left: 7, right: -7, height: 7},
south: {left: 7, right: -7, top: -7},
east: {top: 7, bottom: -7, left: -7},
west: {top: 7, bottom: -7, width: 7},
southeast: {top: -7, left: -7},
southwest: {top: -7, width: 7},
northwest: {height: 7, width: 7},
northeast: {left: -7, height: 7}
};
// private
Ext.Resizable.Handle = function(rz, pos){
this.position = pos;
this.rz = rz;
var cfg = Ext.Resizable.cfg[pos] || Ext.Resizable.cfg[Ext.Resizable.positions[pos]];
this.ez = new Ext.ux.EventZone(Ext.apply({
position: pos,
el: rz.el
}, cfg));
this.ez.on({
mousedown: this.onMouseDown,
mouseenter: this.onMouseOver,
mouseleave: this.onMouseOut,
scope: this
});
};
// private
Ext.Resizable.Handle.prototype = {
cursor: 'move',
// private
afterResize : function(rz){
// do nothing
},
// private
onMouseDown : function(e){
this.rz.onMouseDown(this, e);
},
// private
onMouseOver : function(e){
this.rz.handleOver(this, e);
},
// private
onMouseOut : function(e){
this.rz.handleOut(this, e);
},
// private
destroy : function(){
Ext.destroy(this.el);
this.el = null;
}
};
/**
*
* Ext.ux.elasticTextArea Extension Class for Ext 3.x Library
*
* @author Steffen Kamper
*
* @license Ext.ux.elasticTextArea is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*
*/
Ext.ux.elasticTextArea = function(){
var defaultConfig = function(){
return {
minHeight : 0
,maxHeight : 0
,growBy: 12
}
}
var processOptions = function(config){
var o = defaultConfig();
var options = {};
Ext.apply(options, config, o);
return options;
}
return {
div : null
,applyTo: function(elementId, options){
var el = Ext.get(elementId);
var width = el.getWidth();
var height = el.getHeight();
var styles = el.getStyles('padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'line-height', 'font-size', 'font-family', 'font-weight');
if(! this.div){
var options = processOptions(options);
this.div = Ext.DomHelper.append(Ext.getBody() || document.body, {
'id':elementId + '-preview-div'
,'tag' : 'div'
,'background': 'red'
,'style' : 'position: absolute; top: -100000px; left: -100000px;'
}, true)
Ext.DomHelper.applyStyles(this.div, styles);
el.on('keyup', function() {
this.applyTo(elementId, options);
}, this);
}
this.div.setWidth(parseInt(el.getStyle('width')));
//replace \n with so that the enter key can trigger and height increase
//but first remove all previous entries, so that the height measurement can be as accurate as possible
this.div.update(
el.dom.value.replace(/ /, ' ')
.replace(/<|>/g, ' ')
.replace(/&/g,"&")
.replace(/\n/g, ' ')
);
var growBy = parseInt(el.getStyle('line-height'));
growBy = growBy ? growBy + 1 : 1;
if (growBy === 1) {
growBy = options.growBy;
}
var textHeight = this.div.getHeight();
textHeight = textHeight ? textHeight + growBy : growBy;
if ( (textHeight > options.maxHeight ) && (options.maxHeight > 0) ){
textHeight = options.maxHeight;
el.setStyle('overflow', 'auto');
}
if ( (textHeight < options.minHeight ) && (options.minHeight > 0) ) {
textHeight = options.minHeight;
el.setStyle('overflow', 'auto');
}
el.setHeight(textHeight , true);
}
}
}
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* Evaluation of TYPO3 form field content
*/
function evalFunc() {
this.input = evalFunc_input;
this.output = evalFunc_output;
this.parseInt = evalFunc_parseInt;
this.getNumChars = evalFunc_getNumChars;
this.parseDouble = evalFunc_parseDouble;
this.noSpace = evalFunc_noSpace;
this.getSecs = evalFunc_getSecs;
this.getYear = evalFunc_getYear;
this.getTimeSecs = evalFunc_getTimeSecs;
this.getTime = evalFunc_getTime;
this.getDate = evalFunc_getDate;
this.getTimestamp = evalFunc_getTimestamp;
this.caseSwitch = evalFunc_caseSwitch;
this.evalObjValue = evalFunc_evalObjValue;
this.outputObjValue = evalFunc_outputObjValue;
this.split = evalFunc_splitStr;
this.pol = evalFunc_pol;
this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC;
this.ltrim = evalFunc_ltrim;
this.btrim = evalFunc_btrim;
var today = new Date();
this.lastYear = this.getYear(today);
this.lastDate = this.getDate(today);
this.lastTime = 0;
this.refDate = today;
this.isInString = '';
this.USmode = 0;
}
function evalFunc_pol(foreign, value) {
return eval (((foreign=="-")?'-':'')+value);
}
function evalFunc_evalObjValue(FObj,value) {
var evallist = FObj.evallist;
this.isInString = (FObj.is_in) ? ''+FObj.is_in : '';
var index=1;
var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false;
var newValue=value;
while (theEvalType) {
if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') {
newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue);
} else {
newValue = evalFunc.input(theEvalType, newValue);
}
index++;
theEvalType = this.split(evallist, ",", index);
}
return newValue;
}
function evalFunc_outputObjValue(FObj,value) {
var evallist = FObj.evallist;
var index=1;
var theEvalType = this.split(evallist, ",", index);
var newValue=value;
while (theEvalType) {
if (theEvalType != 'required') {
newValue = evalFunc.output(theEvalType, value, FObj);
}
index++;
theEvalType = this.split(evallist, ",", index);
}
return newValue;
}
function evalFunc_caseSwitch(type,inVal) {
var theVal = ''+inVal;
var newString = '';
switch (type) {
case "alpha":
case "num":
case "alphanum":
case "alphanum_x":
for (var a=0;a= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
var num = (theChar>='0' && theChar<='9');
switch(type) {
case "alphanum": special=0; break;
case "alpha": num=0; special=0; break;
case "num": alpha=0; special=0; break;
}
if (alpha || num || theChar==' ' || special) {
newString+=theChar;
}
}
break;
case "is_in":
if (this.isInString) {
for (var a=0;a 0; a--) {
if (theVal.substr(a-1,1)!=' ') {
return theVal.substr(0,a);
}
}
return '';
}
function evalFunc_splitSingle(value) {
var theVal = ''+value;
this.values = new Array();
this.pointer = 3;
this.values[1]=theVal.substr(0,2);
this.values[2]=theVal.substr(2,2);
this.values[3]=theVal.substr(4,10);
}
function evalFunc_split(value) {
this.values = new Array();
this.valPol = new Array();
this.pointer = 0;
var numberMode = 0;
var theVal = "";
value+=" ";
for (var a=0;a"9") {
if (numberMode) {
this.pointer++;
this.values[this.pointer]=theVal;
theVal = "";
numberMode=0;
}
if (theChar=="+" || theChar=="-") {
this.valPol[this.pointer+1] = theChar;
}
} else {
theVal+=theChar;
numberMode=1;
}
}
}
function evalFunc_input(type,inVal) {
if (type=="md5") {
return MD5(inVal);
}
if (type=="trim") {
return this.ltrim(this.btrim(inVal));
}
if (type=="int") {
return this.parseInt(inVal);
}
if (type=="double2") {
return this.parseDouble(inVal);
}
var today = new Date();
var add=0;
var value = this.ltrim(inVal);
var values = new evalFunc_split(value);
var theCmd = value.substr(0,1);
value = this.caseSwitch(type,value);
if (value=="") {
return "";
return 0; // Why would I ever return a zero??? (20/12/01)
}
switch (type) {
case "datetime":
switch (theCmd) {
case "d":
case "t":
case "n":
this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
case "+":
case "-":
if (this.lastTime == 0) {
this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
}
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
default:
var index = value.indexOf(' ');
if (index!=-1) {
var dateVal = this.input("date",value.substr(index,value.length));
// set refDate so that evalFunc_input on time will work with correct DST information
this.refDate = new Date(dateVal*1000);
this.lastTime = dateVal + this.input("time",value.substr(0,index));
} else {
// only date, no time
this.lastTime = this.input("date", value);
}
}
this.lastTime+=add*24*60*60;
return this.lastTime;
break;
case "year":
switch (theCmd) {
case "d":
case "t":
case "n":
this.lastYear = this.getYear(today);
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
case "+":
case "-":
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
default:
if (values.valPol[2]) {
add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
}
var year = (values.values[1])?this.parseInt(values.values[1]):this.getYear(today);
if ((year >= 0 && year < 38) || (year >= 70 && year<100) || (year >= 1902 && year < 2038)) {
if (year<100) {
year = (year<38) ? year+=2000 : year+=1900;
}
} else {
year = this.getYear(today);
}
this.lastYear = year;
}
this.lastYear+=add;
return this.lastYear;
break;
case "date":
switch (theCmd) {
case "d":
case "t":
case "n":
this.lastDate = this.getTimestamp(today);
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
case "+":
case "-":
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
default:
var index = 4;
if (values.valPol[index]) {
add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
}
if (values.values[1] && values.values[1].length>2) {
if (values.valPol[2]) {
add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
}
var temp = values.values[1];
values = new evalFunc_splitSingle(temp);
}
var year = (values.values[3])?this.parseInt(values.values[3]):this.getYear(today);
if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year<2038)) {
if (year<100) {
year = (year<38) ? year+=2000 : year+=1900;
}
} else {
year = this.getYear(today);
}
var month = (values.values[this.USmode?1:2])?this.parseInt(values.values[this.USmode?1:2]):today.getUTCMonth()+1;
var day = (values.values[this.USmode?2:1])?this.parseInt(values.values[this.USmode?2:1]):today.getUTCDate();
var theTime = new Date(parseInt(year), parseInt(month)-1, parseInt(day));
// Substract timezone offset from client
this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0);
}
this.lastDate+=add*24*60*60;
return this.lastDate;
break;
case "time":
case "timesec":
switch (theCmd) {
case "d":
case "t":
case "n":
this.lastTime = this.getTimeSecs(today);
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
case "+":
case "-":
if (this.lastTime == 0) {
this.lastTime = this.getTimeSecs(today);
}
if (values.valPol[1]) {
add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
}
break;
default:
var index = (type=="timesec")?4:3;
if (values.valPol[index]) {
add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
}
if (values.values[1] && values.values[1].length>2) {
if (values.valPol[2]) {
add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
}
var temp = values.values[1];
values = new evalFunc_splitSingle(temp);
}
var sec = (values.values[3])?this.parseInt(values.values[3]):today.getUTCSeconds();
if (sec > 59) {sec=59;}
var min = (values.values[2])?this.parseInt(values.values[2]):today.getUTCMinutes();
if (min > 59) {min=59;}
var hour = (values.values[1])?this.parseInt(values.values[1]):today.getUTCHours();
if (hour >= 24) {hour=0;}
var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type=="timesec")?sec:0));
// Substract timezone offset from client
this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1);
}
this.lastTime+=add*60;
if (this.lastTime<0) {this.lastTime+=24*60*60;}
return this.lastTime;
break;
default:
return value;
}
}
function evalFunc_output(type,value,FObj) {
var theString = "";
switch (type) {
case "date":
if (!parseInt(value)) {return '';}
var theTime = new Date(parseInt(value) * 1000);
if (this.USmode) {
theString = (theTime.getUTCMonth()+1)+'-'+theTime.getUTCDate()+'-'+this.getYear(theTime);
} else {
theString = theTime.getUTCDate()+'-'+(theTime.getUTCMonth()+1)+'-'+this.getYear(theTime);
}
break;
case "datetime":
if (!parseInt(value)) {return '';}
theString = this.output("time",value)+' '+this.output("date",value);
break;
case "time":
case "timesec":
if (!parseInt(value)) {return '';}
var theTime = new Date(parseInt(value) * 1000);
var h = theTime.getUTCHours();
var m = theTime.getUTCMinutes();
var s = theTime.getUTCSeconds();
theString = h+':'+((m<10)?'0':'')+m + ((type=="timesec")?':'+((s<10)?'0':'')+s:'');
break;
case "password":
theString = (value) ? TS.passwordDummy : "";
break;
case "int":
theString = (FObj.checkbox && value==FObj.checkboxValue)?'':value;
break;
default:
theString = value;
}
return theString;
}
function evalFunc_getSecs(timeObj) {
return timeObj.getUTCSeconds();
}
// Seconds since midnight:
function evalFunc_getTime(timeObj) {
return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj);
}
function evalFunc_getYear(timeObj) {
return timeObj.getUTCFullYear();
}
// Seconds since midnight with client timezone offset:
function evalFunc_getTimeSecs(timeObj) {
return timeObj.getHours()*60*60+timeObj.getMinutes()*60+timeObj.getSeconds();
}
function evalFunc_getDate(timeObj) {
var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
return this.getTimestamp(theTime);
}
function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) {
this.evallist = evallist;
this.is_in = is_in;
this.checkboxValue = checkboxValue;
this.checkbox = checkbox;
}
function evalFunc_splitStr(theStr1, delim, index) {
var theStr = ''+theStr1;
var lengthOfDelim = delim.length;
sPos = -lengthOfDelim;
if (index<1) {index=1;}
for (a=1; a
* @coauthor Oliver Hader
*/
var TBE_EDITOR = {
/* Example:
elements: {
'data-parentPid-table-uid': {
'field': {
'range': [0, 100],
'rangeImg': '',
'required': true,
'requiredImg': ''
}
}
},
*/
elements: {},
nested: {'field':{}, 'level':{}},
ignoreElements: [],
recentUpdatedElements: {},
actionChecks: { submit: [] },
formname: '',
formnameUENC: '',
loadTime: 0,
isChanged: 0,
auth_timeout_field: 0,
backPath: '',
prependFormFieldNames: 'data',
prependFormFieldNamesUENC: 'data',
prependFormFieldNamesCnt: 0,
isPalettedoc: null,
doSaveFieldName: 0,
labels: {},
images: {
req: new Image(),
cm: new Image(),
sel: new Image(),
clear: new Image()
},
clearBeforeSettingFormValueFromBrowseWin: [],
// Handling of data structures:
addElements: function(elements) {
TBE_EDITOR.recentUpdatedElements = elements;
TBE_EDITOR.elements = $H(TBE_EDITOR.elements).merge(elements).toObject();
},
addNested: function(elements) {
// Merge data structures:
if (elements) {
$H(elements).each(function(element) {
var levelMax, i, currentLevel, subLevel;
var nested = element.value;
if (nested.level && nested.level.length) {
// If the first level is of type 'inline', it could be created by a AJAX request to IRRE.
// So, try to get the upper levels this dynamic level is nested in:
if (typeof inline!='undefined' && nested.level[0][0]=='inline') {
nested.level = inline.findContinuedNestedLevel(nested.level, nested.level[0][1]);
}
levelMax = nested.level.length-1;
for (i=0; i<=levelMax; i++) {
currentLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i]);
if (typeof TBE_EDITOR.nested.level[currentLevel] == 'undefined') {
TBE_EDITOR.nested.level[currentLevel] = { 'clean': true, 'item': {}, 'sub': {} };
}
// Add next sub level to the current level:
if (i=0; i--) {
TBE_EDITOR.removeElement(removeStack[i]);
}
TBE_EDITOR.ignoreElements = [];
}
},
getElement: function(record, field, type) {
var result = null;
var element;
if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) {
element = TBE_EDITOR.elements[record][field];
if (type) {
if (element[type]) result = element;
} else {
result = element;
}
}
return result;
},
checkElements: function(type, recentUpdated, record, field) {
var result = 1;
var elementName, elementData, elementRecord, elementField;
var source = (recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements);
if (TBE_EDITOR.ignoreElements.length && TBE_EDITOR.ignoreElements.indexOf(record)!=-1) {
return result;
}
if (type) {
if (record && field) {
elementName = record+'['+field+']';
elementData = TBE_EDITOR.getElement(record, field, type);
if (elementData) {
if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
result = 0;
}
}
} else {
var elementFieldList, elRecIndex, elRecCnt, elFldIndex, elFldCnt;
var elementRecordList = $H(source).keys();
for (elRecIndex=0, elRecCnt=elementRecordList.length; elRecIndex=0; i--) {
nestedLevelType = fieldLevels[i][0];
nestedLevelName = fieldLevels[i][1];
fieldLevelIdent = TBE_EDITOR.getNestedLevelIdent(fieldLevels[i]);
// Construct the CSS id strings of the image/icon tags showing the notification:
if (nestedLevelType == 'tab') {
element = nestedLevelName+'-REQ';
} else if (nestedLevelType == 'inline') {
element = nestedLevelName+'_req';
} else {
continue;
}
// Set the icons:
if (resolved) {
if (TBE_EDITOR.checkNested(fieldLevelIdent)) {
TBE_EDITOR.setImage(element, TBE_EDITOR.images.clear);
} else {
break;
}
} else {
if (TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[fieldLevelIdent]) {
TBE_EDITOR.nested.level[fieldLevelIdent].clean = false;
}
TBE_EDITOR.setImage(element, TBE_EDITOR.images.req);
}
}
}
},
// Check all the input fields on a given level of nesting - if only on is unfilled, the whole level is marked as required:
checkNested: function(nestedLevelIdent) {
var nestedLevel, isClean;
if (nestedLevelIdent && TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[nestedLevelIdent]) {
nestedLevel = TBE_EDITOR.nested.level[nestedLevelIdent];
if (!nestedLevel.clean) {
if (typeof nestedLevel.item == 'object') {
$H(nestedLevel.item).each(
function(pair) {
if (isClean || typeof isClean == 'undefined') {
isClean = (
TBE_EDITOR.checkElements('required', false, pair.value[0], pair.value[1]) &&
TBE_EDITOR.checkElements('range', false, pair.value[0], pair.value[1])
);
}
}
);
if (typeof isClean != 'undefined' && !isClean) {
return false;
}
}
if (typeof nestedLevel.sub == 'object') {
$H(nestedLevel.sub).each(
function(pair) {
if (isClean || typeof isClean == 'undefined') {
isClean = TBE_EDITOR.checkNested(pair.key);
}
}
);
if (typeof isClean != 'undefined' && !isClean) {
return false;
}
}
// Store the result, that this level (the fields on this and the sub levels) are clean:
nestedLevel.clean = true;
}
}
return true;
},
getNestedLevelIdent: function(level) {
return level.join('::');
},
addActionChecks: function(type, checks) {
TBE_EDITOR.actionChecks[type].push(checks);
},
// Regular TCEforms JSbottom scripts:
loginRefreshed: function() {
var date = new Date();
TBE_EDITOR.loadTime = Math.floor(date.getTime()/1000);
if (top.busy && top.busy.loginRefreshed) { top.busy.loginRefreshed(); }
},
checkLoginTimeout: function() {
var date = new Date();
var theTime = Math.floor(date.getTime()/1000);
if (theTime > TBE_EDITOR.loadTime+TBE_EDITOR.auth_timeout_field-10) {
return true;
}
},
fieldChanged_fName: function(fName,el) {
var idx=2+TBE_EDITOR.prependFormFieldNamesCnt;
var table = TBE_EDITOR.split(fName, "[", idx);
var uid = TBE_EDITOR.split(fName, "[", idx+1);
var field = TBE_EDITOR.split(fName, "[", idx+2);
table = table.substr(0,table.length-1);
uid = uid.substr(0,uid.length-1);
field = field.substr(0,field.length-1);
TBE_EDITOR.fieldChanged(table,uid,field,el);
},
fieldChanged: function(table,uid,field,el) {
var theField = TBE_EDITOR.prependFormFieldNames+'['+table+']['+uid+']['+field+']';
var theRecord = TBE_EDITOR.prependFormFieldNames+'['+table+']['+uid+']';
TBE_EDITOR.isChanged = 1;
// Set change image:
var imgObjName = "cm_"+table+"_"+uid+"_"+field;
TBE_EDITOR.setImage(imgObjName,TBE_EDITOR.images.cm);
// Set change image
if (document[TBE_EDITOR.formname][theField] && document[TBE_EDITOR.formname][theField].type=="select-one" && document[TBE_EDITOR.formname][theField+"_selIconVal"]) {
var imgObjName = "selIcon_"+table+"_"+uid+"_"+field+"_";
TBE_EDITOR.setImage(imgObjName+document[TBE_EDITOR.formname][theField+"_selIconVal"].value,TBE_EDITOR.images.clear);
document[TBE_EDITOR.formname][theField+"_selIconVal"].value = document[TBE_EDITOR.formname][theField].selectedIndex;
TBE_EDITOR.setImage(imgObjName+document[TBE_EDITOR.formname][theField+"_selIconVal"].value,TBE_EDITOR.images.sel);
}
// Set required flag:
var imgReqObjName = "req_"+table+"_"+uid+"_"+field;
if (TBE_EDITOR.getElement(theRecord,field,'required') && document[TBE_EDITOR.formname][theField]) {
if (TBE_EDITOR.checkElements('required', false, theRecord, field)) {
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
TBE_EDITOR.notifyNested(theField, true);
} else {
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
TBE_EDITOR.notifyNested(theField, false);
}
}
if (TBE_EDITOR.getElement(theRecord,field,'range') && document[TBE_EDITOR.formname][theField]) {
if (TBE_EDITOR.checkElements('range', false, theRecord, field)) {
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
TBE_EDITOR.notifyNested(theField, true);
} else {
TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
TBE_EDITOR.notifyNested(theField, false);
}
}
if (TBE_EDITOR.isPalettedoc) { TBE_EDITOR.setOriginalFormFieldValue(theField) };
},
setOriginalFormFieldValue: function(theField) {
if (TBE_EDITOR.isPalettedoc && (TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname] && (TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname][theField]) {
(TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname][theField].value = document[TBE_EDITOR.formname][theField].value;
}
},
isFormChanged: function(noAlert) {
if (TBE_EDITOR.isChanged && !noAlert && confirm(TBE_EDITOR.labels.fieldsChanged)) {
return 0;
}
return TBE_EDITOR.isChanged;
},
checkAndDoSubmit: function(sendAlert) {
if (TBE_EDITOR.checkSubmit(sendAlert)) { TBE_EDITOR.submitForm(); }
},
/**
* Checks if the form can be submitted according to any possible restrains like required values, item numbers etc.
* Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1)
* If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will).
* If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...)
*/
checkSubmit: function(sendAlert) {
var funcIndex, funcMax, funcRes;
var OK=1;
// $this->additionalJS_submit:
if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) {
for (funcIndex=0, funcMax=TBE_EDITOR.actionChecks.submit.length; funcIndex= lower && numberOfElements <= upper) {
return true;
} else {
return false;
}
},
initRequired: function() {
// $reqLinesCheck
TBE_EDITOR.checkElements('required', true);
// $reqRangeCheck
TBE_EDITOR.checkElements('range', true);
},
setImage: function(name,image) {
var object;
if (document[name]) {
object = document[name];
} else if (document.getElementById(name)) {
object = document.getElementById(name);
}
if (object) {
if (typeof image == 'object') {
document[name].src = image.src;
} else {
document[name].src = eval(image+'.src');
}
}
},
submitForm: function() {
if (TBE_EDITOR.doSaveFieldName) {
document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value=1;
}
// Set a short timeout to allow other JS processes to complete, in particular those from
// EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755).
// TODO: This should be solved in a better way when this script is refactored.
window.setTimeout('document[TBE_EDITOR.formname].submit()', 10);
},
split: function(theStr1, delim, index) {
var theStr = ""+theStr1;
var lengthOfDelim = delim.length;
sPos = -lengthOfDelim;
if (index<1) {index=1;}
for (var a=1; a i; i++) {
var el = split[i].replace(/ /g, '');
if (el == 'datetime' || el == 'date') {
var now = new Date();
checkSetValue = Date.parse(now)/1000 - now.getTimezoneOffset()*60;
break;
} else if (el == 'time' || el == 'timesec') {
checkSetValue = evalFunc_getTimeSecs(new Date());
break;
}
}
document[TBE_EDITOR.formname][theField].value=checkSetValue;
} else {
document[TBE_EDITOR.formname][theField].value=checkboxValue;
}
}else{
document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document[TBE_EDITOR.formname][theField+"_hr"].value);
}
typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue);
}
}
};
// backwards compatibility for extensions
var typo3FormFieldSet = typo3form.fieldSet;
var typo3FormFieldGet = typo3form.fieldGet;
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
Ext.onReady(function() {
// Only use placeholder JavaScript fallback in Internet Explorer
if (!Ext.isIE) {
return;
}
// TODO rewrite in ExtJS
$$('[placeholder]').each(function(el) {
if (el.getAttribute('placeholder') != "") {
el.observe('TYPO3:focus', function() {
var input = Ext.get(this);
if (this.getValue() == this.getAttribute('placeholder')) {
this.setValue('');
input.removeClass('placeholder');
}
});
el.observe('focus', function() { el.fire('TYPO3:focus'); });
el.observe('TYPO3:blur', function() {
var input = Ext.get(this);
if (input.getValue() == '' || this.getValue() == this.getAttribute('placeholder')) {
this.setValue(this.getAttribute('placeholder'));
input.addClass('placeholder');
}
});
el.observe('blur', function() { el.fire('TYPO3:blur'); });
el.fire('TYPO3:blur');
}
});
});
Ext.ns('Ext.ux', 'Ext.ux.menu', 'Ext.ux.form');
Ext.ux.DateTimePicker = Ext.extend(Ext.DatePicker, {
timeFormat: 'H:i',
initComponent: function() {
var t = this.timeFormat.split(':');
this.hourFormat = t[0];
this.minuteFormat = t[1];
Ext.ux.DateTimePicker.superclass.initComponent.call(this);
},
/**
* Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
* @param {Date} value The minimum date that can be selected
*/
setMinTime: function(dt) {
this.minTime = dt;
this.update(this.value, true);
},
/**
* Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
* @param {Date} value The maximum date that can be selected
*/
setMaxTime: function(dt) {
this.maxTime = dt;
this.update(this.value, true);
},
/**
* Returns the value of the date/time field
*/
getValue: function() {
return this.addTimeToValue(this.value);
},
/**
* Sets the value of the date/time field
* @param {Date} value The date to set
*/
setValue: function(value) {
var old = this.value;
this.value = value.clearTime(true);
if (this.el) {
this.update(this.value);
}
this.hourField.setValue(value.format(this.hourFormat));
this.minuteField.setValue(value.format(this.minuteFormat));
},
/**
* Sets the value of the time field
* @param {Date} value The date to set
*/
setTime: function(value) {
this.hourField.setValue(value.format(this.hourFormat));
this.minuteField.setValue(value.format(this.minuteFormat));
},
/**
* Updates the date value with the time entered
* @param {Date} value The date to which time should be added
*/
addTimeToValue: function(date) {
return date.clearTime().add(Date.HOUR, this.hourField.getValue()).add(Date.MINUTE, this.minuteField.getValue());
},
onRender: function(container, position) {
var m = [
'
',
'
',
'
'
];
var dn = this.dayNames;
for (var i = 0; i < 7; i++) {
var d = this.startDay + i;
if (d > 6) {
d = d - 7;
}
m.push('
', dn[d].substr(0, 1), '
');
}
m[m.length] = "
";
for (var i = 0; i < 42; i++) {
if (i % 7 == 0 && i != 0) {
m[m.length] = "
";
}
m[m.length] = '
';
}
m.push('
',
this.showToday ? '
' : '',
'
'
);
var el = document.createElement("div");
el.className = "x-date-picker";
el.innerHTML = m.join("");
container.dom.insertBefore(el, position);
this.el = Ext.get(el);
this.eventEl = Ext.get(el.firstChild);
new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
handler: this.showPrevMonth,
scope: this,
preventDefault:true,
stopDefault:true
});
new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
handler: this.showNextMonth,
scope: this,
preventDefault:true,
stopDefault:true
});
this.mon(this.eventEl, "mousewheel", this.handleMouseWheel, this);
this.monthPicker = this.el.down('div.x-date-mp');
this.monthPicker.enableDisplayMode('block');
var kn = new Ext.KeyNav(this.eventEl, {
"left": function(e) {
e.ctrlKey ?
this.showPrevMonth() :
this.update(this.activeDate.add("d", -1));
},
"right": function(e) {
e.ctrlKey ?
this.showNextMonth() :
this.update(this.activeDate.add("d", 1));
},
"up": function(e) {
e.ctrlKey ?
this.showNextYear() :
this.update(this.activeDate.add("d", -7));
},
"down": function(e) {
e.ctrlKey ?
this.showPrevYear() :
this.update(this.activeDate.add("d", 7));
},
"pageUp": function(e) {
this.showNextMonth();
},
"pageDown": function(e) {
this.showPrevMonth();
},
"enter": function(e) {
e.stopPropagation();
this.fireEvent("select", this, this.value);
return true;
},
scope : this
});
this.mon(this.eventEl, "click", this.handleDateClick, this, {delegate: "a.x-date-date"});
this.el.select("table.x-date-inner").unselectable();
this.cells = this.el.select("table.x-date-inner tbody td");
this.textNodes = this.el.query("table.x-date-inner tbody span");
this.mbtn = new Ext.Button({
text: " ",
tooltip: this.monthYearText,
renderTo: this.el.child("td.x-date-middle", true)
});
this.mon(this.mbtn, 'click', this.showMonthPicker, this);
this.mbtn.el.child('em').addClass("x-btn-arrow");
if (this.showToday) {
this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
var today = (new Date()).dateFormat(this.format);
this.todayBtn = new Ext.Button({
text: String.format(this.todayText, today),
tooltip: String.format(this.todayTip, today),
handler: this.selectToday,
scope: this
});
}
this.formPanel = new Ext.form.FormPanel({
layout: 'table',
layoutConfig: {
// The total column count must be specified here
columns: 3
},
renderTo: this.el.child("td.x-date-bottom", true),
baseCls: 'x-plain',
hideBorders: true,
labelAlign: 'left',
labelWidth: 10,
forceLayout: true,
items: [
{
columnWidth: .4,
layout: 'form',
baseCls: 'x-plain',
items: [
{
xtype: 'textfield',
id: this.getId() + '_hour',
maxLength: 2,
fieldLabel: '',
labelWidth: 30,
width: 30,
minValue: 0,
maxValue: 24,
allowBlank: false,
labelSeparator: '',
tabIndex: 1,
maskRe: /[0-9]/
}
]
},
{
columnWidth: .3,
layout: 'form',
baseCls: 'x-plain',
items: [
{
xtype: 'textfield',
id: this.getId() + '_minute',
maxLength: 2,
fieldLabel: ':',
labelWidth: 10,
width: 30,
minValue: 0,
maxValue: 59,
allowBlank: false,
labelSeparator: '',
tabIndex: 2,
maskRe: /[0-9]/
}
]
},
{
columnWidth: .3,
layout: 'form',
baseCls: 'x-plain',
items: [this.todayBtn]
}
]
});
this.hourField = Ext.getCmp(this.getId() + '_hour');
this.minuteField = Ext.getCmp(this.getId() + '_minute');
this.hourField.on('blur', function(field) {
var old = field.value;
var h = parseInt(field.getValue());
if (h > 23) {
field.setValue(old);
}
});
this.minuteField.on('blur', function(field) {
var old = field.value;
var h = parseInt(field.getValue());
if (h > 59) {
field.setValue(old);
}
});
if (Ext.isIE) {
this.el.repaint();
}
this.update(this.value);
},
// private
handleDateClick : function(e, t) {
e.stopEvent();
if (t.dateValue && !Ext.fly(t.parentNode).hasClass("x-date-disabled")) {
this.setValue(this.addTimeToValue(new Date(t.dateValue)));
this.fireEvent("select", this, this.value);
}
},
selectToday : function() {
if (this.todayBtn && !this.todayBtn.disabled) {
this.setValue(new Date());
this.fireEvent("select", this, this.value);
}
},
update : function(date, forceRefresh) {
Ext.ux.DateTimePicker.superclass.update.call(this, date, forceRefresh);
if (this.showToday) {
this.setTime(new Date());
}
}
});
Ext.reg('datetimepicker', Ext.ux.DateTimePicker);
Ext.ux.menu.DateTimeMenu = Ext.extend(Ext.menu.Menu, {
enableScrolling : false,
hideOnClick : true,
cls: 'x-date-menu x-datetime-menu',
initComponent : function() {
Ext.apply(this, {
plain: true,
showSeparator: false,
items: this.picker = new Ext.ux.DateTimePicker(Ext.apply({
internalRender: this.strict || !Ext.isIE,
ctCls: 'x-menu-datetime-item x-menu-date-item'
}, this.initialConfig))
});
this.picker.purgeListeners();
Ext.ux.menu.DateTimeMenu.superclass.initComponent.call(this);
this.relayEvents(this.picker, ['select']);
this.on('select', this.menuHide, this);
if (this.handler) {
this.on('select', this.handler, this.scope || this)
}
},
menuHide: function() {
if (this.hideOnClick) {
this.hide(true);
}
}
});
Ext.reg('datetimemenu', Ext.ux.menu.DateTimeMenu);
/**
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
Ext.ns('TYPO3');
// class to manipulate TCEFORMS
TYPO3.TCEFORMS = {
init: function() {
Ext.QuickTips.init();
this.update();
},
update: function() {
this.convertDateFieldsToDatePicker();
this.convertTextareasResizable();
},
convertDateFieldsToDatePicker: function() {
var dateFields = Ext.select("input[id^=tceforms-date]"), minDate, maxDate, lowerMatch, upperMatch;
dateFields.each(function(element) {
var index = element.dom.id.match(/tceforms-datefield-/) ? 0 : 1;
var format = TYPO3.settings.datePickerUSmode ? TYPO3.settings.dateFormatUS : TYPO3.settings.dateFormat;
var datepicker = element.next('span'), menu;
// check for daterange
var lowerMatch = element.dom.className.match(/lower-(\d+)\b/);
minDate = Ext.isArray(lowerMatch) ? new Date(lowerMatch[1] * 1000) : null;
var upperMatch = element.dom.className.match(/upper-(\d+)\b/);
maxDate = Ext.isArray(upperMatch) ? new Date(upperMatch[1] * 1000) : null;
if (index === 0) {
menu = new Ext.menu.DateMenu({
id: 'p' + element.dom.id,
format: format[index],
value: Date.parseDate(element.dom.value, format[index]),
minDate: minDate,
maxDate: maxDate,
handler: function(picker, date){
var relElement = Ext.getDom(picker.ownerCt.id.substring(1));
relElement.value = date.format(format[index]);
if (Ext.isFunction(relElement.onchange)) {
relElement.onchange.call(relElement);
}
},
listeners: {
beforeshow: function(obj) {
var relElement = Ext.getDom(obj.picker.ownerCt.id.substring(1));
if (relElement.value) {
obj.picker.setValue(Date.parseDate(relElement.value, format[index]));
}
}
}
});
} else {
menu = new Ext.ux.menu.DateTimeMenu({
id: 'p' + element.dom.id,
format: format[index],
value: Date.parseDate(element.dom.value, format[index]),
minDate: minDate,
maxDate: maxDate,
listeners: {
beforeshow: function(obj) {
var relElement = Ext.getDom(obj.picker.ownerCt.id.substring(1));
if (relElement.value) {
obj.picker.setValue(Date.parseDate(relElement.value, format[index]));
}
},
select: function(picker) {
var relElement = Ext.getDom(picker.ownerCt.id.substring(1));
relElement.value = picker.getValue().format(format[index]);
if (Ext.isFunction(relElement.onchange)) {
relElement.onchange.call(relElement);
}
}
}
});
}
datepicker.removeAllListeners();
datepicker.on('click', function(){
menu.show(datepicker);
});
});
},
convertTextareasResizable: function() {
var textAreas = Ext.select("textarea[id^=tceforms-textarea-]");
textAreas.each(function(element) {
if (TYPO3.settings.textareaFlexible) {
var elasticTextarea = new Ext.ux.elasticTextArea().applyTo(element.dom.id, {
minHeight: 50,
maxHeight: TYPO3.settings.textareaMaxHeight
});
}
if (TYPO3.settings.textareaResize) {
element.addClass('resizable');
var dwrapped = new Ext.Resizable(element.dom.id, {
minWidth: 300,
minHeight: 50,
dynamic: true
});
}
});
}
}
Ext.onReady(TYPO3.TCEFORMS.init, TYPO3.TCEFORMS);
// Fix for slider TCA control in IE9
Ext.override(Ext.dd.DragTracker, {
onMouseMove:function (e, target) {
var isIE9 = Ext.isIE && (/msie 9/.test(navigator.userAgent.toLowerCase())) && document.documentMode != 6;
if (this.active && Ext.isIE && !isIE9 && !e.browserEvent.button) {
e.preventDefault();
this.onMouseUp(e);
return;
}
e.preventDefault();
var xy = e.getXY(), s = this.startXY;
this.lastXY = xy;
if (!this.active) {
if (Math.abs(s[0] - xy[0]) > this.tolerance || Math.abs(s[1] - xy[1]) > this.tolerance) {
this.triggerStart(e);
} else {
return;
}
}
this.fireEvent('mousemove', this, e);
this.onDrag(e);
this.fireEvent('drag', this, e);
}
});
/*') {
inline.isLoading = true;
// add loading-indicator
if (TYPO3.jQuery('#' + escapedObjectId + '_loadingbar').length === 0) {
var loadingBar = '
';
TYPO3.jQuery('#' + escapedObjectId + '_header').after(loadingBar);
}
return this.getRecordDetails(objectId, returnURL);
}
var isCollapsed = currentObject.hasClass(this.classCollapsed);
var collapse = new Array();
var expand = new Array();
// if only a single record should be visibly for that set of records
// and the record clicked itself is no visible, collapse all others
if (expandSingle && currentObject.hasClass(this.classCollapsed)) {
collapse = this.collapseAllRecords(objectId, objectPrefix, currentUid);
}
inline.toggleElement(objectId);
if (this.isNewRecord(objectId)) {
this.updateExpandedCollapsedStateLocally(objectId, isCollapsed);
} else if (isCollapsed) {
expand.push(currentUid);
} else if (!isCollapsed) {
collapse.push(currentUid);
}
this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(','));
return false;
},
toggleElement: function(objectId) {
var escapedObjectId = this.escapeObjectId(objectId);
var jQueryObject = TYPO3.jQuery('#' + escapedObjectId + '_div');
if (jQueryObject.hasClass(this.classCollapsed)) {
jQueryObject.removeClass(this.classCollapsed).addClass(this.classVisible);
jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-collapsed').removeClass('t3-icon-irre-collapsed').addClass('t3-icon-irre-expanded');
} else {
jQueryObject.removeClass(this.classVisible).addClass(this.classCollapsed);
jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-expanded').addClass('t3-icon-irre-collapsed').removeClass('t3-icon-irre-expanded');
}
},
collapseAllRecords: function(objectId, objectPrefix, callingUid) {
// get the form field, where all records are stored
var objectName = this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 2, true);
var formObj = document.getElementsByName(objectName);
var collapse = [];
if (formObj.length) {
// the uid of the calling object (last part in objectId)
var recObjectId = '', escapedRecordObjectId;
var records = formObj[0].value.split(',');
for (var i=0; i tag (e.g. for RTEhtmlarea):
if (json.headData) {
var head = inline.getDomHeadTag();
var headTags = inline.getDomHeadChildren(head);
$A(json.headData).each(function(addTag) {
if (!restart) {
if (addTag && (addTag.innerHTML || !inline.searchInDomTags(headTags, addTag))) {
if (addTag.name=='SCRIPT' && addTag.innerHTML && processedCount) {
restart = true;
return false;
} else {
if (addTag.name=='SCRIPT' && addTag.innerHTML) {
try {
eval(addTag.innerHTML);
} catch(e) {
errorCatch.push(e);
}
} else {
element = inline.createNewDomElement(addTag);
// Set onload handler for external JS scripts:
if (addTag.name=='SCRIPT' && element.src) {
element.onload = inline.sourceLoadedHandler(element);
sourcesWaiting.push(element.src);
}
head.appendChild(element);
processedCount++;
}
json.headData.shift();
}
}
}
});
}
if (restart || processedCount) {
window.setTimeout(function() { inline.reprocessAjaxResponse(method, json, sourcesWaiting); }, 40);
} else {
if (method) {
inline.unlockAjaxMethod(method);
}
if (json.scriptCall && json.scriptCall.length) {
$A(json.scriptCall).each(function(value) { eval(value); });
}
TYPO3.TCEFORMS.convertDateFieldsToDatePicker();
}
},
// Check if dynamically added scripts are loaded and restart inline.processAjaxResponse():
reprocessAjaxResponse: function (method, json, sourcesWaiting) {
var sourcesLoaded = true;
if (sourcesWaiting && sourcesWaiting.length) {
$A(sourcesWaiting).each(function(source) {
if (!inline.sourcesLoaded[source]) {
sourcesLoaded = false;
return false;
}
});
}
if (sourcesLoaded) {
$A(sourcesWaiting).each(function(source) {
delete(inline.sourcesLoaded[source]);
});
window.setTimeout(function() { inline.processAjaxResponse(method, null, json); }, 80);
} else {
window.setTimeout(function() { inline.reprocessAjaxResponse(method, json, sourcesWaiting); }, 40);
}
},
sourceLoadedHandler: function(element) {
if (element && element.src) {
inline.sourcesLoaded[element.src] = true;
}
},
showAjaxFailure: function(method, xhr) {
inline.unlockAjaxMethod(method);
alert('Error: '+xhr.status+"\n"+xhr.statusText);
},
// foreign_selector: used by selector box (type='select')
importNewRecord: function(objectId) {
var selector = $(objectId+'_selector');
if (selector.selectedIndex != -1) {
var context = this.getContext(objectId);
var selectedValue = selector.options[selector.selectedIndex].value;
if (!this.data.unique || !this.data.unique[objectId]) {
selector.options[selector.selectedIndex].selected = false;
}
this.makeAjaxCall('createNewRecord', [this.getNumberOfRTE(), objectId, selectedValue], true, context);
}
return false;
},
// foreign_selector: used by element browser (type='group/db')
importElement: function(objectId, table, uid, type) {
var context = this.getContext(objectId);
inline.makeAjaxCall('createNewRecord', [inline.getNumberOfRTE(), objectId, uid], true, context);
},
importElementMultiple: function(objectId, table, uidArray, type) {
uidArray.each(function(uid) {
inline.delayedImportElement(objectId, table, uid, type);
});
},
delayedImportElement: function(objectId, table, uid, type) {
if (inline.lockedAjaxMethod['createNewRecord'] == true) {
window.setTimeout("inline.delayedImportElement('" + objectId + "','" + table + "'," + uid + ", null );", 300);
} else {
inline.importElement(objectId, table, uid, type);
}
},
// Check uniqueness for element browser:
checkUniqueElement: function(objectId, table, uid, type) {
if (this.checkUniqueUsed(objectId, uid, table)) {
return {passed: false,message: 'There is already a relation to the selected element!'};
} else {
return {passed: true};
}
},
// Checks if a record was used and should be unique:
checkUniqueUsed: function(objectId, uid, table) {
if (this.data.unique && this.data.unique[objectId]) {
var unique = this.data.unique[objectId];
var values = $H(unique.used).values();
// for select: only the uid is stored
if (unique['type'] == 'select') {
if (values.indexOf(uid) != -1) {
return true;
}
// for group/db: table and uid is stored in a assoc array
} else if (unique.type == 'groupdb') {
for (var i=values.length-1; i>=0; i--) {
// if the pair table:uid is already used:
if (values[i].table==table && values[i].uid==uid) {
return true;
}
}
}
}
return false;
},
setUniqueElement: function(objectId, table, uid, type, elName) {
var recordUid = this.parseFormElementName('none', elName, 1, 1);
// alert(objectId+'/'+table+'/'+uid+'/'+recordUid);
this.setUnique(objectId, recordUid, uid);
},
// Remove all select items already used
// from a newly retrieved/expanded record
removeUsed: function(objectId, recordUid) {
if (this.data.unique && this.data.unique[objectId]) {
var unique = this.data.unique[objectId];
if (unique.type == 'select') {
var formName = this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 1, true);
var formObj = document.getElementsByName(formName);
var recordObj = document.getElementsByName(this.prependFormFieldNames+'['+unique.table+']['+recordUid+']['+unique.field+']');
var values = $H(unique.used).values();
if (recordObj.length) {
if (recordObj[0].hasOwnProperty('options')) {
var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value;
for (var i=0; i') {
return;
}
var elName = this.parseObjectId('full', objectId, 2, 0, true);
var escapeSelectorObjectId = this.escapeSelectorObjectId(objectId);
formObj = $$('[name="' + elName + '[hidden]_0"]');
valueObj = $$('[name="' + elName + '[hidden]"]');
// It might be the case that a child record
// cannot be hidden at all (no hidden field)
if (formObj.length && valueObj.length) {
hiddenValue = formObj[0].checked;
formObj[0].remove();
valueObj[0].remove();
}
// Update DOM
objectDiv.update(htmlData);
formObj = document.getElementsByName(elName + '[hidden]_0');
valueObj = document.getElementsByName(elName + '[hidden]');
// Set the hidden value again
if (formObj.length && valueObj.length) {
valueObj[0].value = hiddenValue ? 1 : 0;
formObj[0].checked = hiddenValue;
}
// remove loading-indicator
TYPO3.jQuery('#' + escapeSelectorObjectId + '_loadingbar').remove();
// now that the content is loaded, set the expandState
this.expandCollapseRecord(objectId, expandSingle);
},
// Get script and link elements from head tag:
getDomHeadChildren: function(head) {
var headTags = [];
$$('head script', 'head link').each(function(tag) {
headTags.push(tag);
});
return headTags;
},
getDomHeadTag: function() {
if (document && document.head) {
return document.head;
} else {
var head = $$('head');
if (head.length) {
return head[0];
}
}
return false;
},
// Search whether elements exist in a given haystack:
searchInDomTags: function(haystack, needle) {
var result = false;
$A(haystack).each(function(element) {
if (element.nodeName.toUpperCase()==needle.name) {
var attributesCount = $H(needle.attributes).keys().length;
var attributesFound = 0;
$H(needle.attributes).each(function(attribute) {
if (element.getAttribute && element.getAttribute(attribute.key)==attribute.value) {
attributesFound++;
}
});
if (attributesFound==attributesCount) {
result = true;
return true;
}
}
});
return result;
},
// Create a new DOM element:
createNewDomElement: function(addTag) {
var element = document.createElement(addTag.name);
if (addTag.attributes) {
$H(addTag.attributes).each(function(attribute) {
element[attribute.key] = attribute.value;
});
}
return element;
},
changeSorting: function(objectId, direction) {
var objectName = this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 2, true);
var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
var formObj = document.getElementsByName(objectName);
if (formObj.length) {
// the uid of the calling object (last part in objectId)
var callingUid = this.parseObjectId('none', objectId, 1);
var records = formObj[0].value.split(',');
var current = records.indexOf(callingUid);
var changed = false;
// move up
if (direction > 0 && current > 0) {
records[current] = records[current-1];
records[current-1] = callingUid;
changed = true;
// move down
} else if (direction < 0 && current < records.length-1) {
records[current] = records[current+1];
records[current+1] = callingUid;
changed = true;
}
if (changed) {
formObj[0].value = records.join(',');
var cAdj = direction > 0 ? 1 : 0; // adjustment
$(objectId+'_div').parentNode.insertBefore(
$(objectPrefix + this.structureSeparator + records[current-cAdj] + '_div'),
$(objectPrefix + this.structureSeparator + records[current+1-cAdj] + '_div')
);
this.redrawSortingButtons(objectPrefix, records);
}
}
return false;
},
dragAndDropSorting: function(element) {
require(['jquery'], function($) {
var objectId = element.getAttribute('id').replace(/_records$/, '');
var objectName = inline.prependFormFieldNames+inline.parseObjectId('parts', objectId, 3, 0, true);
var formObj = document.getElementsByName(objectName);
var $element = $( element );
if (formObj.length) {
var checked = new Array();
var order = [];
$element.find('.sortableHandle').each(function(i,e) {
order.push($(e).data('id').toString());
});
var records = formObj[0].value.split(',');
// check if ordered uid is really part of the records
// virtually deleted items might still be there but ordering shouldn't saved at all on them
for (var i=0; i=0; i--) {
if (inlineRecords[i].value.length) {
records = inlineRecords[i].value.split(',');
childObjectId = this.data.map[inlineRecords[i].name];
childTable = this.data.config[childObjectId].table;
for (j=records.length-1; j>=0; j--) {
removeStack.push(this.prependFormFieldNames+'['+childTable+']['+records[j]+']');
}
}
}
removeStack.push(this.prependFormFieldNames+shortName);
TBE_EDITOR.removeElementArray(removeStack);
}
// Mark this container as deleted
var deletedRecordContainer = $(objectId + '_div');
if (deletedRecordContainer) {
deletedRecordContainer.addClassName('inlineIsDeletedRecord');
}
// If the record is new and was never saved before, just remove it from DOM:
if (this.isNewRecord(objectId) || options && options.forceDirectRemoval) {
this.fadeAndRemove(objectId+'_div');
// If the record already exists in storage, mark it to be deleted on clicking the save button:
} else {
document.getElementsByName('cmd'+shortName+'[delete]')[0].disabled = false;
new Effect.Fade(objectId+'_div');
}
var recordCount = this.memorizeRemoveRecord(
this.prependFormFieldNames+this.parseObjectId('parts', objectId, 3, 2, true),
recordUid
);
if (recordCount <= 1) {
this.destroyDragAndDropSorting(this.parseObjectId('full', objectId, 0 , 2)+'_records');
}
this.redrawSortingButtons(objectPrefix);
// if the NEW-button was hidden and now we can add again new children, show the button
if (!beforeDeleteIsBelowMax && this.isBelowMax(objectPrefix)) {
var objectParent = this.parseObjectId('full', objectPrefix, 0 , 1);
var md5 = this.getObjectMD5(objectParent);
this.showElementsWithClassName('.inlineNewButton'+(md5 ? '.'+md5 : ''), objectParent);
}
return false;
},
parsePath: function(path) {
var backSlash = path.lastIndexOf('\\');
var normalSlash = path.lastIndexOf('/');
if (backSlash > 0) {
path = path.substring(0,backSlash+1);
} else if (normalSlash > 0) {
path = path.substring(0,normalSlash+1);
} else {
path = '';
}
return path;
},
parseFormElementName: function(wrap, formElementName, rightCount, skipRight) {
var idParts = this.splitFormElementName(formElementName);
if (!wrap) {
wrap = 'full';
}
if (!skipRight) {
skipRight = 0;
}
var elParts = new Array();
for (var i=0; i 0) {
for (var i=0; i '...|...'
formElementName = formElementName.substr(0, formElementName.lastIndexOf(']')).substr(formElementName.indexOf('[')+1);
var parts = objectId.split('][');
return parts;
},
splitObjectId: function(objectId) {
objectId = objectId.substr(objectId.indexOf(this.structureSeparator)+1);
objectId = objectId.split(this.flexFormSeparator).join(this.flexFormSubstitute);
var parts = objectId.split(this.structureSeparator);
return parts;
},
constructFormElementName: function(wrap, parts) {
var elReturn;
if (wrap == 'full') {
elReturn = this.prependFormFieldNames+'['+parts.join('][')+']';
elReturn = elReturn.split(this.flexFormSubstitute).join('][');
} else if (wrap == 'parts') {
elReturn = '['+parts.join('][')+']';
elReturn = elReturn.split(this.flexFormSubstitute).join('][');
} else if (wrap == 'none') {
elReturn = parts.length > 1 ? parts : parts.join('');
}
return elReturn;
},
constructObjectId: function(wrap, parts) {
var elReturn;
if (wrap == 'full') {
elReturn = this.prependFormFieldNames+this.structureSeparator+parts.join(this.structureSeparator);
elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
} else if (wrap == 'parts') {
elReturn = this.structureSeparator+parts.join(this.structureSeparator);
elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
} else if (wrap == 'none') {
elReturn = parts.length > 1 ? parts : parts.join('');
}
return elReturn;
},
parseObjectId: function(wrap, objectId, rightCount, skipRight, returnAsFormElementName) {
var idParts = this.splitObjectId(objectId);
if (!wrap) {
wrap = 'full';
}
if (!skipRight) {
skipRight = 0;
}
var elParts = new Array();
for (var i=0; i 0) {
for (var i=0; i= this.data.config[objectPrefix].max) {
isBelowMax = false;
}
}
if (isBelowMax && this.data.unique && this.data.unique[objectPrefix]) {
var unique = this.data.unique[objectPrefix];
if (this.arrayAssocCount(unique.used) >= unique.max && unique.max >= 0) {
isBelowMax = false;
}
}
return isBelowMax;
},
getOptionsHash: function(selectObj) {
var optionsHash = {};
for (var i=0; i tag
var readdOption = document.createElement('option');
readdOption.text = unique.possible[value];
readdOption.value = value;
// add the