/** * 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 ## /* CodeMirror main module (http://codemirror.net/) * * Implements the CodeMirror constructor and prototype, which take care * of initializing the editor frame, and providing the outside interface. */ // The CodeMirrorConfig object is used to specify a default // configuration. If you specify such an object before loading this // file, the values you put into it will override the defaults given // below. You can also assign to it after loading. var CodeMirrorConfig = window.CodeMirrorConfig || {}; var CodeMirror = (function(){ function setDefaults(object, defaults) { for (var option in defaults) { if (!object.hasOwnProperty(option)) object[option] = defaults[option]; } } function forEach(array, action) { for (var i = 0; i < array.length; i++) action(array[i]); } function createHTMLElement(el) { if (document.createElementNS && document.documentElement.namespaceURI !== null) return document.createElementNS("http://www.w3.org/1999/xhtml", el) else return document.createElement(el) } // These default options can be overridden by passing a set of // options to a specific CodeMirror constructor. See manual.html for // their meaning. setDefaults(CodeMirrorConfig, { stylesheet: [], path: "", parserfile: [], basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"], iframeClass: null, passDelay: 200, passTime: 50, lineNumberDelay: 200, lineNumberTime: 50, continuousScanning: false, saveFunction: null, onLoad: null, onChange: null, undoDepth: 50, undoDelay: 800, disableSpellcheck: true, textWrapping: true, readOnly: false, width: "", height: "300px", minHeight: 100, autoMatchParens: false, markParen: null, unmarkParen: null, parserConfig: null, tabMode: "indent", // or "spaces", "default", "shift" enterMode: "indent", // or "keep", "flat" electricChars: true, reindentOnLoad: false, activeTokens: null, onCursorActivity: null, lineNumbers: false, firstLineNumber: 1, onLineNumberClick: null, indentUnit: 2, domain: null, noScriptCaching: false, incrementalLoading: false }); function addLineNumberDiv(container, firstNum) { var nums = createHTMLElement("div"), scroller = createHTMLElement("div"); nums.style.position = "absolute"; nums.style.height = "100%"; if (nums.style.setExpression) { try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");} catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions } nums.style.top = "0px"; nums.style.left = "0px"; nums.style.overflow = "hidden"; container.appendChild(nums); scroller.className = "CodeMirror-line-numbers"; nums.appendChild(scroller); scroller.innerHTML = "