From 57a4d385a1d2806d5877f53b1fdb0bd94efa2dbb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Beno=C3=AEt=20Pin?= Date: Sun, 7 Nov 2010 03:08:56 +0100 Subject: [PATCH] Importation initiale. --- HistoryAdapters.py | 41 +++ PlinnDocument.py | 273 ++++++++++++++++ __init__.py | 35 +++ configure.zcml | 32 ++ graphics/delete_rectangle.psd | Bin 0 -> 24724 bytes graphics/layer_status.psd | Bin 0 -> 21548 bytes graphics/resize_handle.psd | Bin 0 -> 23898 bytes interfaces.py | 5 + license.txt | 340 ++++++++++++++++++++ profiles/default/types.xml | 4 + profiles/default/types/Plinn_Document.xml | 42 +++ skins/color_utils.js | 117 +++++++ skins/color_utils.js.metadata | 2 + skins/dd_trigger.js | 69 ++++ skins/dd_trigger.js.metadata | 2 + skins/degrad_rectangle_header.gif | Bin 0 -> 92 bytes skins/delete_rectangle.gif | Bin 0 -> 305 bytes skins/delete_rectangle_hover.gif | Bin 0 -> 304 bytes skins/layout_controlers.js | 365 ++++++++++++++++++++++ skins/layout_controlers.js.metadata | 2 + skins/layout_objects.js | 269 ++++++++++++++++ skins/layout_objects.js.metadata | 2 + skins/plinn_attachment_form.py | 28 ++ skins/plinn_attachment_template.pt | 56 ++++ skins/plinn_blank_iframe.html.pt | 43 +++ skins/plinn_doc.gif | Bin 0 -> 135 bytes skins/plinn_doc.thumb.gif | Bin 0 -> 1054 bytes skins/plinn_file_upload.gif | Bin 0 -> 386 bytes skins/plinn_icons/hidden_layer.gif | Bin 0 -> 333 bytes skins/plinn_icons/imagebox.gif | Bin 0 -> 301 bytes skins/plinn_icons/layer.gif | Bin 0 -> 257 bytes skins/plinn_icons/textarea.gif | Bin 0 -> 239 bytes skins/plinn_icons/visible_layer.gif | Bin 0 -> 536 bytes skins/plinn_image_upload.gif | Bin 0 -> 1046 bytes skins/plinn_init_javascript_code.dtml | 8 + skins/plinn_macros.pt | 66 ++++ skins/plinn_multilingual.js.pt | 17 + skins/plinn_multilingual.js.pt.metadata | 2 + skins/plinndocument_edit_control.py | 15 + skins/plinndocument_edit_form.py | 13 + skins/plinndocument_edit_template.pt | 69 ++++ skins/plinndocument_view.pt | 13 + skins/resize_handle.png | Bin 0 -> 184 bytes skins/xml_io.js | 132 ++++++++ skins/xml_io.js.metadata | 2 + 45 files changed, 2064 insertions(+) create mode 100755 HistoryAdapters.py create mode 100644 PlinnDocument.py create mode 100644 __init__.py create mode 100644 configure.zcml create mode 100644 graphics/delete_rectangle.psd create mode 100644 graphics/layer_status.psd create mode 100644 graphics/resize_handle.psd create mode 100755 interfaces.py create mode 100755 license.txt create mode 100644 profiles/default/types.xml create mode 100644 profiles/default/types/Plinn_Document.xml create mode 100644 skins/color_utils.js create mode 100644 skins/color_utils.js.metadata create mode 100644 skins/dd_trigger.js create mode 100644 skins/dd_trigger.js.metadata create mode 100644 skins/degrad_rectangle_header.gif create mode 100644 skins/delete_rectangle.gif create mode 100644 skins/delete_rectangle_hover.gif create mode 100644 skins/layout_controlers.js create mode 100644 skins/layout_controlers.js.metadata create mode 100644 skins/layout_objects.js create mode 100644 skins/layout_objects.js.metadata create mode 100644 skins/plinn_attachment_form.py create mode 100644 skins/plinn_attachment_template.pt create mode 100755 skins/plinn_blank_iframe.html.pt create mode 100644 skins/plinn_doc.gif create mode 100644 skins/plinn_doc.thumb.gif create mode 100644 skins/plinn_file_upload.gif create mode 100644 skins/plinn_icons/hidden_layer.gif create mode 100644 skins/plinn_icons/imagebox.gif create mode 100644 skins/plinn_icons/layer.gif create mode 100644 skins/plinn_icons/textarea.gif create mode 100644 skins/plinn_icons/visible_layer.gif create mode 100644 skins/plinn_image_upload.gif create mode 100644 skins/plinn_init_javascript_code.dtml create mode 100644 skins/plinn_macros.pt create mode 100644 skins/plinn_multilingual.js.pt create mode 100644 skins/plinn_multilingual.js.pt.metadata create mode 100644 skins/plinndocument_edit_control.py create mode 100644 skins/plinndocument_edit_form.py create mode 100644 skins/plinndocument_edit_template.pt create mode 100644 skins/plinndocument_view.pt create mode 100644 skins/resize_handle.png create mode 100644 skins/xml_io.js create mode 100644 skins/xml_io.js.metadata diff --git a/HistoryAdapters.py b/HistoryAdapters.py new file mode 100755 index 0000000..add0e8b --- /dev/null +++ b/HistoryAdapters.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +####################################################################################### +# Plinn - http://plinn.org # +# Copyright © 2005-2009 Benoît PIN # +# # +# This program is free software; you can redistribute it and/or # +# modify it under the terms of the GNU General Public License # +# as published by the Free Software Foundation; either version 2 # +# of the License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # +####################################################################################### +""" +Adapter to plug PlinnDocument to historycal interface. + +$Id: HistoryAdapters.py 647 2009-06-30 12:55:44Z pin $ +$URL: http://svn.cri.ensmp.fr/svn/PlinnDocument/branches/CMF-2.1/HistoryAdapters.py $ +""" + +from Globals import InitializeClass +from AccessControl import ClassSecurityInfo +from Products.CMFCore.permissions import ModifyPortalContent +from Products.Plinn.HistoryAdapters import DocumentHistory + +class PlinnDocumentHistory(DocumentHistory) : + + security = ClassSecurityInfo() + + security.declareProtected(ModifyPortalContent, 'restore') + def restore(self, key): + rev = self.getHistoricalRevisionByKey(key)[0] + self._content.edit(rev.Format(), rev.XMLBody()) + +InitializeClass(PlinnDocumentHistory) diff --git a/PlinnDocument.py b/PlinnDocument.py new file mode 100644 index 0000000..3267069 --- /dev/null +++ b/PlinnDocument.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +####################################################################################### +# Plinn - http://plinn.org # +# Copyright (C) 2005-2007 Benoît PIN # +# # +# This program is free software; you can redistribute it and/or # +# modify it under the terms of the GNU General Public License # +# as published by the Free Software Foundation; either version 2 # +# of the License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # +####################################################################################### + +from Globals import InitializeClass +from AccessControl import ClassSecurityInfo +from Products.CMFCore.permissions import View, ModifyPortalContent +from Products.CMFCore.utils import getToolByName +from Products.CMFDefault.Document import Document +from OFS.PropertyManager import PropertyManager +from OFS.Folder import Folder +from OFS.Image import File, cookId +from zope.component.factory import Factory +from zope.interface import implements +from Products.Photo import Photo +from Products.Plinn.utils import makeValidId +from interfaces import IPlinnDocument +from cStringIO import StringIO +from sets import Set +import xml.dom.minidom as minidom +import re + +imgPattern = re.compile('', re.IGNORECASE) +imgWidthPattern = re.compile('style\s*=\s*".*width\s*:\s*([0-9]+)px') +imgHeightPattern = re.compile('style\s*=\s*".*height\s*:\s*([0-9]+)px') +imgSrcPattern = re.compile('src\s*=\s*"(.*)"') + +imgOrLinkPattern = re.compile('(.*?))"(.*?)>|(.*?))"(.*?)>', re.IGNORECASE) +EMPTY_PLINN_DOCUMENT = '' + + +def addPlinnDocument(self, id, title='', description='', text=''): + """ Add a Plinn Document """ + o = PlinnDocument(id, title, description, text) + self._setObject(id,o) + +class PlinnDocument(Document) : + """ Plinn document - WYSIWYG editor + based on XML and javascript + """ + implements(IPlinnDocument) + + security = ClassSecurityInfo() + + _cookedTexts = {} + + def __init__(self, id, title='', description='', text='') : + self.attachments = Folder('attachments') + Document.__init__(self, id, title=title, description=description, text_format='html', text=text) + + security.declareProtected(View, 'EditableBody') + def EditableBody(self, mergeLayers=True): + """ Transforms XML to HTML """ + + if self.text : + if not self._cookedTexts.has_key(self.absolute_url()) : + plinnElement = minidom.parseString(self.text).documentElement + + htmlDom = minidom.parseString('
') + htmlDomDoc = htmlDom.documentElement + + self._transformRectangles(plinnElement, htmlDomDoc) + firstChildStyle = htmlDomDoc.firstChild.getAttribute('style') + htmlDomDoc.setAttribute('style', firstChildStyle.replace('absolute', 'relative')) + + if mergeLayers : + mergedDom = minidom.parseString('
') + mergedDomDoc = mergedDom.documentElement + for layer in htmlDomDoc.childNodes : + for foreignchild in layer.childNodes : + child = mergedDom.importNode(foreignchild, True) + mergedDomDoc.appendChild(child) + + mergedDomDoc.setAttribute('style', htmlDomDoc.getAttribute('style')) + htmlDom = mergedDom + + htmlText = htmlDom.toprettyxml().replace('<', '<').replace('>', '>').replace('"', '"').replace('&', '&') + htmlText = htmlText.encode('utf8') + htmlText = htmlText.split('\n', 1)[1] + + htmlText = imgOrLinkPattern.sub(self._convertSrcOrHref, htmlText) + self._cookedTexts[self.absolute_url()] = htmlText + return htmlText + else : + return self._cookedTexts[self.absolute_url()] + else : + return '' + + def _convertSrcOrHref(self, m) : + dict = m.groupdict() + if dict['src'] : + tag = m.group().replace(dict['src'], self._genAbsoluteUrl(dict['src'])) + if not tag.endswith('/>') : + tag = tag[:-1] + '/>' + return tag + elif dict['href'] : + return m.group().replace(dict['href'], self._genAbsoluteUrl(dict['href'])) + else: + return m.group() + + def _genAbsoluteUrl(self, relUrl) : + if relUrl.find('attachments/') >=0 : + return self.absolute_url() + '/' + relUrl[relUrl.rindex('attachments/'):] + else : + return relUrl + + + security.declareProtected(ModifyPortalContent, 'XMLBody') + def XMLBody(self, REQUEST=None) : + """ return raw xml text """ + + if REQUEST is not None : + RESPONSE = REQUEST['RESPONSE'] + RESPONSE.setHeader('content-type', 'text/xml; charset=utf-8') + + manager = getToolByName(self, 'caching_policy_manager', None) + if manager is not None: + view_name = 'XMLBody' + headers = manager.getHTTPCachingHeaders( + self, view_name, {} + ) + + for key, value in headers: + if key == 'ETag': + RESPONSE.setHeader(key, value, literal=1) + else: + RESPONSE.setHeader(key, value) + if headers: + RESPONSE.setHeader('X-Cache-Headers-Set-By', + 'CachingPolicyManager: %s' % + '/'.join(manager.getPhysicalPath())) + + + return Document.EditableBody(self) or EMPTY_PLINN_DOCUMENT + + + security.declareProtected(ModifyPortalContent, 'addAttachment') + def addAttachment(self, file, formId) : + """ Add attachment """ + id, title = cookId('', '', file) + + id = makeValidId(self.attachments, id) + + if formId == 'ImageUploadForm': + fileOb = Photo(id, title, file, thumb_height=300, thumb_width=300) + else : + fileOb = File(id, title, '') + fileOb.manage_upload(file) + + self.attachments._setObject(id, fileOb) + fileOb = getattr(self.attachments, id) + return fileOb + + + def _transformRectangles(self, inNode, outNode) : + + for node in [ node for node in inNode.childNodes if node.nodeName == 'rectangle' ] : + if node.getAttribute('visibility') == 'hidden' : + continue + + divRect = outNode.ownerDocument.createElement('div') + outNode.appendChild(divRect) + + styleAttr = 'position:absolute' + styleAttr += ';width:%spx' % node.getAttribute('width') + styleAttr += ';height:%spx' % node.getAttribute('height') + + for subNode in node.childNodes : + if subNode.nodeName == 'upperLeftCorner' : + for point in subNode.childNodes : + if point.nodeName == 'point' : + styleAttr += ';left:%spx' % point.getAttribute('x') + styleAttr += ';top:%spx' % point.getAttribute('y') + divRect.setAttribute('style', styleAttr) + break + + elif subNode.nodeName == 'rawData' : + rawData = subNode.firstChild + if rawData : + textNode = outNode.ownerDocument.createTextNode(self.getElementTransform(node.getAttribute('elementKey'))(node, rawData.nodeValue)) + divRect.appendChild(textNode) + + self._transformRectangles(node, divRect) + + + security.declarePrivate('renderImg') + def renderImg(self, node, raw) : + width = int(node.getAttribute('width')) + height = int(node.getAttribute('height')) + + photoId = raw.split('/')[-2] + photo = self._resizePhoto(photoId, width, height) + + alt = 'image' + return '%(alt)s' % \ + {'src' : photo.absolute_url(), 'width' : width, 'height' : height, 'alt' : alt} + + + security.declarePrivate('renderEpozImg') + def renderEpozImg(self, node, raw): + for img in imgPattern.findall(raw) : + width = imgWidthPattern.findall(img) + if width : width = int(width[0]) + + height = imgHeightPattern.findall(img) + if height : height = int(height[0]) + + if not (width or height) : continue # default size + + photoId = imgSrcPattern.findall(img)[0].split('/')[-2] + self._resizePhoto(photoId, width, height) + + return raw + + + def _resizePhoto(self, photoId, width, height): + photo = getattr(self.attachments, photoId) + + nts = [width, height] + landscape = width > height + if landscape : + nts.reverse() + + thumbSize = {'width': photo.thumb_width, 'height': photo.thumb_height} + + if thumbSize['width'] != nts[0] or thumbSize['height'] != nts[1] > 1 : + photo.manage_editProperties(thumb_width=nts[0], thumb_height=nts[1]) + + return photo + + + security.declarePrivate('getElementTransform') + def getElementTransform(self, elementKey) : + transforms = {'IMG_ELEMENT': self.renderImg, + 'EPOZ_ELEMENT': self.renderEpozImg} + return transforms.get(elementKey, lambda node, raw : raw) + + def _edit(self, text): + """ Edit the Document and cook the body. + """ + Document._edit(self, text) + self._removeUnusedAttachments() + self._cookedTexts = {} + + + def _removeUnusedAttachments(self) : + if not(self.attachments.objectIds() and self.XMLBody()) : return + + reAttachments = re.compile('|'.join( [r'\b%s\b' % id for id in self.attachments.objectIds()] )) + xml = self.XMLBody() + attSet = Set(self.attachments.objectIds()) + useSet = Set(reAttachments.findall(xml)) + self.attachments.manage_delObjects([att for att in attSet - useSet]) + + +InitializeClass(PlinnDocument) +PlinnDocumentFactory = Factory(PlinnDocument) \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..a2dc2a1 --- /dev/null +++ b/__init__.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +####################################################################################### +# Plinn - http://plinn.org # +# Copyright (C) 2005-2007 Benoît PIN # +# # +# This program is free software; you can redistribute it and/or # +# modify it under the terms of the GNU General Public License # +# as published by the Free Software Foundation; either version 2 # +# of the License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # +####################################################################################### + +from Products.CMFCore import utils +from Products.CMFCore.permissions import AddPortalContent + +import PlinnDocument + +contentClasses = (PlinnDocument.PlinnDocument,) +contentConstructors = (PlinnDocument.addPlinnDocument,) + +def initialize(registrar) : + utils.ContentInit( + 'Plinn Content', + content_types = contentClasses, + permission = AddPortalContent, + extra_constructors = contentConstructors, + ).initialize(registrar) \ No newline at end of file diff --git a/configure.zcml b/configure.zcml new file mode 100644 index 0000000..e72308a --- /dev/null +++ b/configure.zcml @@ -0,0 +1,32 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/graphics/delete_rectangle.psd b/graphics/delete_rectangle.psd new file mode 100644 index 0000000000000000000000000000000000000000..8a6823c8b40188de90c889682e5842a37a50ac50 GIT binary patch literal 24724 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 literal 0 HcmV?d00001 diff --git a/graphics/layer_status.psd b/graphics/layer_status.psd new file mode 100644 index 0000000000000000000000000000000000000000..5725cb700aa1f2e2fe0364d89390890818fb7a6e GIT binary patch literal 21548 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 YIe?=G7=;5uBe9P>Ae%*7HpnpfzvMI#K>z>% literal 0 HcmV?d00001 diff --git a/graphics/resize_handle.psd b/graphics/resize_handle.psd new file mode 100644 index 0000000000000000000000000000000000000000..2baf5c073d21cb754249d74ef06f69be560be8b9 GIT binary patch literal 23898 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 + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/profiles/default/types.xml b/profiles/default/types.xml new file mode 100644 index 0000000..04e5f83 --- /dev/null +++ b/profiles/default/types.xml @@ -0,0 +1,4 @@ + + + + diff --git a/profiles/default/types/Plinn_Document.xml b/profiles/default/types/Plinn_Document.xml new file mode 100644 index 0000000..bce5392 --- /dev/null +++ b/profiles/default/types/Plinn_Document.xml @@ -0,0 +1,42 @@ + + + Plinn Document + Plinn Documents contain text and images that can be layout with WYSIWYG and drag&drop editor. + plinn_doc.gif + Plinn Document + + plinndocument + object/edit + True + True + + False + + + + + + + + + + + + + + + + + + diff --git a/skins/color_utils.js b/skins/color_utils.js new file mode 100644 index 0000000..7c70d07 --- /dev/null +++ b/skins/color_utils.js @@ -0,0 +1,117 @@ +// (c) Benoît PIN 2006-2007 +// http://plinn.org +// Licence GPL + +function HSVColor(h, s, v) { + this.h = h; // 0-360° + this.s = s; // 0-100% + this.v = v; // 0-100% +} + +HSVColor.prototype.toRGBString = function() { + var rgb = this.toRGB(); + return "rgb(" + String(rgb[0]) + ", " + String(rgb[1]) + ", " + String(rgb[2]) + ")"; +}; + +HSVColor.prototype.toRGB = function () { + var h = this.h; var s = this.s/100.0; + var v = this.v/100.0; + if( s == 0 ) // achromatic (grey) + r = g = b = v; + + h = h/60; // sector 0 to 5 + var i = Math.floor( h ); + var f = h - i; // factorial part of h + var p = v * ( 1 - s ); + var q = v * ( 1 - s * f ); + var t = v * ( 1 - s * ( 1 - f ) ); + switch( i ) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + default: // case 5: + r = v; + g = p; + b = q; + break; + } + + r = Math.round(r*255); + g = Math.round(g*255); + b = Math.round(b*255); + return [r, g, b]; +}; + + +function ColorIterator(baseH, baseS, baseV, step) { + this.baseColor = new HSVColor(baseH, baseS, baseV); + this.currentH = baseH; + this.step = step; +} + +ColorIterator.prototype.next = function() { + var c = new HSVColor(this.currentH, this.baseColor.s, this.baseColor.v); + this.currentH += this.step; + + if (this.currentH >= 360) + this.currentH -= 360; + + return c; +}; + +function setBorderColor(ob, colorString) { + var s = ob.style; + s.borderBottomColor = colorString; + s.borderLeftColor = colorString; + s.borderRightColor = colorString; + s.borderTopColor = colorString; +} + + +function setBorderStyle(ob, borderStyle) { + var s= ob.style; + s.borderBottomStyle = borderStyle; + s.borderLeftStyle = borderStyle; + s.borderRightStyle = borderStyle; + s.borderTopStyle = borderStyle; +} + + +function setBorderWidth(ob, borderWidth) { + var s= ob.style; + s.borderBottomWidth = borderWidth; + s.borderLeftWidth = borderWidth; + s.borderRightWidth = borderWidth; + s.borderTopWidth = borderWidth; +} + +function zfill(number, digits) { + number = Math.floor(number); + var nStr = String(number); + while (nStr.length < digits) + nStr = "0" + nStr; + return nStr; +} + diff --git a/skins/color_utils.js.metadata b/skins/color_utils.js.metadata new file mode 100644 index 0000000..855fecc --- /dev/null +++ b/skins/color_utils.js.metadata @@ -0,0 +1,2 @@ +[default] +cache=HTTPCache diff --git a/skins/dd_trigger.js b/skins/dd_trigger.js new file mode 100644 index 0000000..b79f37e --- /dev/null +++ b/skins/dd_trigger.js @@ -0,0 +1,69 @@ +// (c) Benoît PIN 2006-2007 +// http://plinn.org +// Licence GPL + +function ddEventDispatch() { + addListener(document, 'mousedown', raisemousedown); + addListener(document, 'mousemove', raisemousemove); + addListener(document, 'mouseup', raisemouseup); +} + + +function getRectangleNode() { + var docid = document.id; + docid = document.id.slice(DocPrefixLength); + var frameId = IFramePrefix + docid; + iframe = window.parent.document.getElementById(frameId); + if (!iframe) + iframe = window.parent.document.getElementById("EpozEditor"); + return iframe.parentNode; +} + +var raisemousedown, raisemousemove, raisemouseup; + +if (browser.isIE55 || browser.isIE6up) { + raisemousedown = function() { + var rect = getRectangleNode(); + rect.fireEvent('onmousedown', window.event); + }; + + raisemousemove = function() { + var rect = getRectangleNode(); + rect.fireEvent('onmousemove', window.event); + rect.fireEvent('onmouseover', window.event); + }; + + raisemouseup = function() { + var rect = getRectangleNode(); + rect.fireEvent('onmouseup', window.event); + }; +} +else if (browser.isDOM2Event) { + // initMouseEvent("eventType", bubblesFlas, cancelableFlag, view, detailVal, screenX, screenY, clientX, clientY, ctrlKeyFlag, altKeyFlag, shiftKeyFlag, metaKeyFlag, buttonCode, relatedTargetNodeRef) + + raisemousedown = function(e) { + var event = document.createEvent("MouseEvents"); + var rect = getRectangleNode() + event.initMouseEvent("mousedown", true, true, window.parent, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, rect); + rect.dispatchEvent(event); + }; + + + raisemousemove = function(e) { + var overEvent = document.createEvent("MouseEvents"); + overEvent.initMouseEvent("mouseover", true, true, window.parent, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, rect); + var event = document.createEvent("MouseEvents"); + var rect = getRectangleNode() + event.initMouseEvent("mousemove", true, true, window.parent, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, rect); + rect.dispatchEvent(event); + rect.dispatchEvent(overEvent); + }; + + + raisemouseup = function(e) { + var event = document.createEvent("MouseEvents"); + var rect = getRectangleNode() + event.initMouseEvent("mouseup", true, true, window.parent, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, rect); + rect.dispatchEvent(event); + }; +} diff --git a/skins/dd_trigger.js.metadata b/skins/dd_trigger.js.metadata new file mode 100644 index 0000000..855fecc --- /dev/null +++ b/skins/dd_trigger.js.metadata @@ -0,0 +1,2 @@ +[default] +cache=HTTPCache diff --git a/skins/degrad_rectangle_header.gif b/skins/degrad_rectangle_header.gif new file mode 100644 index 0000000000000000000000000000000000000000..721dc3571638bff4cda185476305264b4f08e92f GIT binary patch literal 92 zcmZ?wbhEHbWMtrG*v!E2`0=9$5AMHw_2Sme8?Ro!eE#Cu)2B~fzj^ij`}aF{Zr{9l fg8>yN{$v3Q=zvI&84N6(0_s*)-tJ>Py_V3&O z^5ygIKfX_&KKgCH9tAV=O z+x7v$-n|bWK4@=mI{^g8k2f_nZQr)-?3puHu3Uce=JnmXw`WYB{_Xp>*4CEKpFiEY zb#uXj`4cAe-@A8r#mW_FX(?w;pMLu6$;($SzJLGr`t_^t-@o6wdE@5I8~^|RXFvst zKUu&6Iv^6{Ck8e@hhuNUR^JUW?RhKI&FizxmFd}s17?D~TnCaESvn4Qgv~m^wWwcZ vbJRtRX>CsK*9!yKoY<49Lp<0Ob@lXg71S;CjZI99^(`$eCQi0+WUvMRp*^Rj literal 0 HcmV?d00001 diff --git a/skins/delete_rectangle_hover.gif b/skins/delete_rectangle_hover.gif new file mode 100644 index 0000000000000000000000000000000000000000..fba2ab657c7e8ed46c15983441b3208ffb827b4a GIT binary patch literal 304 zcmV-00nh$NNk%w1VF&;V0M!5hZag}KYiD~#L)zNegllNXnwW)zgP@_HgmQ7NcW8uh zaLLHX@4~m~>geg|=-H{8-rn8c-`%r>gRH8m#$;0K?CPyVIqdA}iBL_(Wm0ZCI@ze2 zdqqR7c4+ta_n@GlkBf_|si|5mEX|gWr>Lj*`1jo0+oq?c$jHdu-Q13gimXF9@4~i3 z7#4Wn-F-joR7RmywX@=;!S0>%Lt{<>utf%*%U5L`4}F_xJYM+1LO8 z00000A^8LV00000EC2ui00;mJ000I}K%P+ODe)?{Q!GZZU23iu4E8eACYs$yumgk? ztJ_X=vmgSQolerC5NI3>i&4#}u Cq?f+{ literal 0 HcmV?d00001 diff --git a/skins/layout_controlers.js b/skins/layout_controlers.js new file mode 100644 index 0000000..c0a383e --- /dev/null +++ b/skins/layout_controlers.js @@ -0,0 +1,365 @@ +// (c) Benoît PIN 2006-2007 +// http://plinn.org +// Licence GPL + +// Global variables +var CURRENT_LAYER; +var LAYER_MANAGER; +var XML_OUTPUT; +var PLINN_DOCUMENT_URL; +var GLOBAL_DD_CONTROLER; + +function initPlinn(root_container, xmlDataUrl) { + PLINN_DOCUMENT_URL = document.getElementById("PlinnDocumentUrl").innerHTML; + form_path = PLINN_DOCUMENT_URL+'/'; // for epoz + initElementsPool(); + initWidgets(); + var imp = new XMLImport(xmlDataUrl, root_container); + GLOBAL_DD_CONTROLER = new GlobalPlinnDDControler(root_container); +} + + +function initWidgets() { + // Global control widgets + XML_OUTPUT = document.getElementById("xml_output") +} + +function initLayerManager(root_container) { + LAYER_MANAGER = new LayerManager(root_container, new ColorIterator(240, 80, 60, 83)); // todo : move in config file +} + +function Point(x, y) { + this.x = x; + this.y = y; +} +Point.prototype.difference = function(point) { return new Point(this.x - point.x, this.y - point.y); }; +Point.prototype.addition = function(point) { return new Point(this.x + point.x, this.y + point.y); }; +Point.prototype.toString = function() { return "(" + String(this.x) + ", " + String(this.y) + ")"; }; + + +function GlobalPlinnDDControler(root_container) { + this.root_container = root_container; + this.dragInProgress = false; + + this.currentRect = null; + this.dragAllowed = null; + this.resizeAllowed = null; + this.scalable = null; + this.deleteAllowed = null; + + + //Constants + this.DRAG_MODE = 0; + this.RESIZE_MODE = 1; + + this.mode = this.DRAG_MODE; + this.ddEventCaptureElmt = document; + + // event listeners + var thisControler = this; + with (this.root_container) { + onmouseover = function(evt){thisControler.onmouseover(evt);}; + onmouseout = function(evt){thisControler.onmouseout(evt);}; + } + with (this.ddEventCaptureElmt) { + onmousedown = function(evt){thisControler.onmousedown(evt);}; + onmousemove = function(evt){thisControler.onmousemove(evt);}; + onmouseup = function(evt){thisControler.onmouseup(evt);}; + } +} + +GlobalPlinnDDControler.prototype.onmouseover = function(evt) { + if (this.dragInProgress) return; + var ob = getTargetedObject(evt); + var rect = ob.rectangle; + if (!rect) return; + rect.showHandles(); +}; + +GlobalPlinnDDControler.prototype.onmouseout = function(evt) { + if (this.dragInProgress) return; + var ob = getTargetedObject(evt); + var rect = ob.rectangle; + if (!rect) return; + rect.hideHandles(); +}; + +GlobalPlinnDDControler.prototype.onmousedown = function(evt) { + var ob = getTargetedObject(evt); + var rect = ob.rectangle; + + if (!rect) return; + + this.currentRect = rect; + this.setDDOptions(rect.ddOptions); + + var evt = getEventObject(evt); + if (this.deleteAllowed && ( + (evt.shiftKey && evt.altKey) || + (ob.tagName == "IMG" && ob.className=="rectangle_delimg")) ) { + if (confirm(PlinnLang["Do you realy want to delete ?"])) { + var hostDiv = rect.hostDiv; + hostDiv.parentNode.removeChild(hostDiv); + } + return; + } + + this.originalClickPoint = new Point(evt.screenX, evt.screenY); + this.originalSize = new Point(rect.width, rect.height); + this.offsetPoint = rect.upperLeftCorner.difference(this.originalClickPoint); + + if (evt.shiftKey || (ob.tagName == "SPAN" && ob.className=="resize_handle")) { + this.mode = this.RESIZE_MODE; + this.startDrag(evt, rect); + } + else if(evt.altKey || (ob.tagName == "DIV" && ob.className=="rectangle_header")){ + this.mode = this.DRAG_MODE; + this.startDrag(evt, rect); + } +}; + +GlobalPlinnDDControler.prototype.onmousemove = function(evt) { + var evt = getEventObject(evt); + if (this.dragInProgress) { + var rectangle = this.currentRect; + if (this.dragAllowed && (this.mode == this.DRAG_MODE)) { + var relativeEvtPoint = new Point(evt.screenX, evt.screenY).addition(this.offsetPoint); + rectangle.moveTo(relativeEvtPoint); + } + else if (this.resizeAllowed && (this.mode == this.RESIZE_MODE)) { + var delta = new Point(evt.screenX, evt.screenY).difference(this.originalClickPoint); + var size = this.originalSize.addition(delta); + if (this.scalable) { + size = new Point(size.x, Math.round(size.x * rectangle.ratio)); + } + + rectangle.resizeTo(size); + } + if (browser.isIE) { + try {document.selection.clear();} + catch (e){return;} + } + } +}; + +GlobalPlinnDDControler.prototype.onmouseup = function(evt) { + this.drop() + var rectangle = this.currentRect; + if (rectangle && rectangle.ondrop) + rectangle.ondrop(); +}; + + +GlobalPlinnDDControler.prototype.startDrag = function(evt, rect) { + disablePropagation(evt); + disableDefault(evt); + this.dragInProgress = true; +}; + +GlobalPlinnDDControler.prototype.drop = function() {this.dragInProgress = false;}; + +GlobalPlinnDDControler.prototype.setDDOptions = function(options){ + this.dragAllowed = (options & 1) == 1; + this.resizeAllowed = (options & 2) == 2; + this.scalable = (options & 4) == 4; + this.deleteAllowed = (options & 8) == 8; +}; + + + +function LayerManager(main_space, colorIterator) { + this.space = main_space; + this.layers = new Array(); + this.defaultLayerWidth = 800; + this.defaultLayerHeight = 600; + this.colorIterator = colorIterator; + this.layerSelector = document.getElementById('layerSelector'); + var thisManager = this; + + // add layer selector commands + // separator between layers list and layer commandes + var sepOpt = document.createElement("option"); + sepOpt.innerHTML = "--------"; + sepOpt.disabled = "disabled"; + sepOpt.style.color = "#888"; + + // new layer command + var addLayerOpt = document.createElement("option"); + addLayerOpt.value = "add"; + addLayerOpt.innerHTML = PlinnLang["New layer"]; + addLayerOpt.style.color = "#000"; + + // remove layer command + var removeLayerOpt = document.createElement("option"); + removeLayerOpt.value = "rm"; + removeLayerOpt.innerHTML = PlinnLang["Remove layer"]; + removeLayerOpt.disabled = "disabled"; + + with (this.layerSelector) { + appendChild(sepOpt); + appendChild(addLayerOpt); + appendChild(removeLayerOpt); + } + addListener(this.layerSelector, 'change', function(){thisManager.activateLayer();}); +} + +LayerManager.prototype.addLayer = function(position) { + var color = this.colorIterator.next(); + var mode = 6; // resize and delete + if (this.layers.length <= 1) + mode = 2; // resize only + var l = new Rectangle(new Point(0, 0), this.defaultLayerWidth, this.defaultLayerHeight, "DIV_ELEMENT", 2); + setBorderColor(l, color.toRGBString()); + l.onresize = resizeOnMouseMove; + l.ondrop = resizeOnDrop; + l.style.overflow = "hidden"; + l.draw(this.space, position); + var index = this.layers.push(l) - 1; + + var opt = document.createElement("option"); + strId = String(index); + opt.value = strId; + opt.id = "layer_" + strId; + opt.innerHTML = PlinnLang["Layer "] + strId; + opt.style.color = color.toRGBString(); + this.layerSelector.insertBefore(opt, this.layerSelector.childNodes[this.layers.length-1]); + + // If there's only one layer, the remove command is disabled. + if (this.layers.length > 1) { + var rmCommand = this.layerSelector.childNodes[this.layerSelector.length -1] + rmCommand.removeAttribute("disabled"); + rmCommand.style.color="#000"; + } + this.activateLayer(index); +}; + +LayerManager.prototype.activateLayer = function(index) { + var layerSelector = this.layerSelector; + var index = (index != null) ? index : layerSelector.value; + // handle commands + index = ( Number(index) || Number(index ) == 0 ) ? Number(index) : index + + if (typeof(index) == typeof('')) { + switch (index) { + case "add" : + this.addLayer(); + break; + case "rm" : + this.removeCurrentLayer(); + break; + }; + return; + } + + CURRENT_LAYER = this.layers[index]; + this._syncLayerStatusImage(); + var opt = document.getElementById("layer_" + String(index)); + layerSelector.selectedIndex = opt.index; + layerSelector.style.color = opt.style.color; + this.putCurrentLayerOnTop(); +}; + + +LayerManager.prototype.putCurrentLayerOnTop = function() { + for(var i = 0 ; i < this.layers.length ; i++) { + layer = this.layers[i]; + if (layer == CURRENT_LAYER) + layer.style.zIndex = String(this.layers.length); + else + layer.style.zIndex = String(i); + } +}; + +LayerManager.prototype.toggleLayerVisibility = function(){ + var currentVisibility = CURRENT_LAYER.style.visibility; + if (currentVisibility == "hidden") + CURRENT_LAYER.style.visibility = "visible"; + else + CURRENT_LAYER.style.visibility = "hidden"; + + this._syncLayerStatusImage(); +}; + +LayerManager.prototype._syncLayerStatusImage = function() { + var layerStatusImage = document.getElementById("layer_status"); + if (CURRENT_LAYER.style.visibility == "hidden") { + layerStatusImage.src = "plinn_icons/hidden_layer.gif"; + layerStatusImage.title = PlinnLang["Show layer"]; + } + else { + layerStatusImage.src = "plinn_icons/visible_layer.gif"; + layerStatusImage.title = PlinnLang["Hide layer"]; + } +}; + +LayerManager.prototype.removeCurrentLayer = function() { + var layersLength = this.layers.length; + var layerSelector = this.layerSelector; + var layer, deletedLayerIndex; + for (var i = 0 ; i < layersLength ; i++) { + layer = this.layers[i]; + if (layer == CURRENT_LAYER) { + if (confirm(PlinnLang["confirm_layer_delete"] + i + "\" ?")) { + this.space.removeChild(layer.hostDiv); + this.layers.splice(i, 1); + layerSelector.removeChild(layerSelector.childNodes[i]); + deletedLayerIndex = i; + break; + } + else { + this.activateLayer(i); + return; + } + } + } + + // update layer indexes + for (var i = 0 ; i < this.layers.length ; i++) { + layerSelector.childNodes[i].value = String(i); + layerSelector.childNodes[i].id = "layer_" + String(i); + layerSelector.childNodes[i].innerHTML = PlinnLang["Layer "] + String(i); + } + + if (this.layers.length == 1) { + var removeCmdOpt = layerSelector.childNodes[layerSelector.childNodes.length - 1]; + removeCmdOpt.disabled = "disabled"; + removeCmdOpt.style.color = "#888"; + } + + if (deletedLayerIndex == 0) + this.layers[0].style.position = "relative"; + + // activate previous layer + this.activateLayer((deletedLayerIndex > 0) ? --deletedLayerIndex : 0); + +}; + +function resizeOnMouseMove() { + if (LAYER_MANAGER.layers.length > 5) + return; // to expensive + else + _resizeAllLayers(this); +} + +function resizeOnDrop() { _resizeAllLayers(this);} + +function _resizeAllLayers(layer) { + var layers = LAYER_MANAGER.layers; + var size = new Point(layer.width, layer.height); + var l; + for(var i = 0 ; i < layers.length ; i++) { + l = layers[i]; + if (layer != l) + l.resizeTo(size, true); + } + LAYER_MANAGER.defaultLayerWidth = size.x; + LAYER_MANAGER.defaultLayerHeight = size.y; +} + +function CreateAttachmentLink(data) { + // data like that : "title[attachment/a_file] + var title = data.split("\[", 1)[0]; + var url =data.match(/\[(.*)\]/)[1]; + var link ="" + title + ""; + InsertHTML(link); +} \ No newline at end of file diff --git a/skins/layout_controlers.js.metadata b/skins/layout_controlers.js.metadata new file mode 100644 index 0000000..855fecc --- /dev/null +++ b/skins/layout_controlers.js.metadata @@ -0,0 +1,2 @@ +[default] +cache=HTTPCache diff --git a/skins/layout_objects.js b/skins/layout_objects.js new file mode 100644 index 0000000..2d4ca89 --- /dev/null +++ b/skins/layout_objects.js @@ -0,0 +1,269 @@ +// (c) Benoît PIN 2006-2007 +// http://plinn.org +// Licence GPL + +var ELEMENTS_POOL = {}; + +function initElementsPool() { + // Element pool (for cloning) + ELEMENTS_POOL["DIV_ELEMENT"] = {"node" : document.getElementById("div"), + "beforeDraw" : null, + "getRawData" : null, + "putData" : null }; + + imgBeforeDraw = function() { + if (!this.node.src) { + var dispatch = document.getElementById("ImgDispatcher"); + var strRatio = dispatch.value.split("_", 1)[0]; + var src = dispatch.value.substring(strRatio.length+1); + this.ratio = new Number(strRatio).valueOf(); + this.node.src = PLINN_DOCUMENT_URL + '/' + src; + var w = this.width; + var size = (this.ratio > 1) ? + new Point(w, Math.round(w * this.ratio)) : + new Point(Math.round(w / this.ratio), w); + + this.resizeTo(size); + } + } + + ELEMENTS_POOL["IMG_ELEMENT"] = {"node" : document.getElementById("img"), + "beforeDraw" : imgBeforeDraw, + "getRawData" : function() { + var src = this.node.src; + src = src.split('/'); + return "attachments/" + src[src.length - 2] + "/getThumbnail"; + }, + "putData" : function(raw) { + this.node.src = PLINN_DOCUMENT_URL+"/attachments/"+raw; + } + }; + + epozBeforeDraw = function() { + var rect = this + var iframe = this.node.childNodes[0]; + var name = String(Math.floor(Math.random() * 10000)); + addListener(iframe, 'load', function(){initTextRectangle(iframe, name, rect);}); + + var ta = this.node.childNodes[1]; + ta.name = name; + ta.id = name; + } + + ELEMENTS_POOL["EPOZ_ELEMENT"] = {"node" : document.getElementById("epoz"), + "beforeDraw" : epozBeforeDraw, + "getRawData" : function() { + return this.node.childNodes[0].contentWindow.document.body.innerHTML; + }, + "putData" : function(raw) { + this.node.childNodes[1].value = raw; + } + }; + + for (var i = 0 ; i < ELEMENTS_POOL.length ; i++) + ELEMENTS_POOL[i].removeAttribute("id"); +} + +function Rectangle(upperLeftCorner, width, height, elementKey, ddOptions, ratio) { + this.meta_type = "Rectangle"; // ;-) + this.upperLeftCorner = upperLeftCorner; + this.width = width; + this.height = height; + this.elementKey = elementKey; + this.node = ELEMENTS_POOL[elementKey]["node"].cloneNode(true); + with (this.node.style) { + width="100%"; + height="100%"; + } + this.beforeDraw = ELEMENTS_POOL[elementKey]["beforeDraw"]; + this.getRawData = ELEMENTS_POOL[elementKey]["getRawData"]; + this.ddOptions = (!ddOptions) ? 11 : ddOptions; // 11-> drag, resize, delete + this.ratio = ratio; + + this.hostDiv = document.createElement("div"); + this.hostDiv.appendChild(this.node); + + this.resizeHandle = document.createElement("span"); + this.resizeHandle.className = "resize_handle"; + this.hostDiv.appendChild(this.resizeHandle); + + if((this.ddOptions & 8) == 8) { // move allowed + this.movDelHandle = document.createElement("div"); + this.movDelHandle.className = "rectangle_header"; + var delImg = document.createElement("img"); + delImg.src = "delete_rectangle.gif"; + delImg.className = "rectangle_delimg"; + delImg.onmouseover=function(){this.src="delete_rectangle_hover.gif";} + delImg.onmouseout=function(){this.src="delete_rectangle.gif";} + this.movDelHandle.appendChild(delImg); + this.hostDiv.appendChild(this.movDelHandle); + this.movDelHandle.rectangle = this; + delImg.rectangle = this; + + } + + // backward references + this.style = this.hostDiv.style; + this.node.rectangle = this; + this.hostDiv.rectangle = this; + this.resizeHandle.rectangle = this; +} + +Rectangle.prototype.showHandles = function() { + if (this.resizeHandle) + this.resizeHandle.style.visibility = "visible"; + if (this.movDelHandle) + this.movDelHandle.style.visibility = "visible"; +}; + +Rectangle.prototype.hideHandles = function() { + if (this.resizeHandle) + this.resizeHandle.style.visibility = "hidden"; + if (this.movDelHandle) + this.movDelHandle.style.visibility = "hidden"; +}; + +Rectangle.prototype._mac_moveDelHandle = function() { + // fix height + var epozWindow = this.node.childNodes[0].contentWindow; + if (epozWindow.scrollMaxY) + this.resizeHandle.style.right = "15px"; + else + this.resizeHandle.style.right = "0px"; + + // fix width + if (epozWindow.scrollMaxX) + this.resizeHandle.style.bottom = "15px"; + else + this.resizeHandle.style.bottom = "0px"; +}; + + +Rectangle.prototype.draw = function(container, position) { + if (this.beforeDraw) + this.beforeDraw(); + var style = this.style; + style.left = String(this.upperLeftCorner.x) + "px"; + style.top = String(this.upperLeftCorner.y) + "px"; + style.width = String(this.width) + "px"; + style.height = String(this.height) + "px"; + + style.display="block"; + var pos; + if (!position) + pos = "absolute"; + else + pos = position; + style.position = pos; + setBorderStyle(this, "solid"); + setBorderWidth(this, "1px"); + style.visibility = "inherit"; +/* style.overflow = "hidden";*/ + if (container.meta_type == "Rectangle") + setBorderColor(this, container.style.borderTopColor); + + container.appendChild(this.hostDiv); +}; + + +Rectangle.prototype.moveTo = function(upperLeftCorner) { + this.upperLeftCorner = upperLeftCorner; + var style = this.style; + style.left = String(this.upperLeftCorner.x) + "px"; + style.top = String(this.upperLeftCorner.y) + "px"; +}; + +Rectangle.prototype.resizeTo = function(size, cancelOnresize) { + if (size.x >= 10) + this.width = size.x; + if (size.y >= 10) + this.height = size.y; + + var style = this.style; + style.width = String(this.width) + "px"; + style.height = String(this.height) + "px"; + if (this.onresize && !cancelOnresize) + this.onresize(); +}; + +Rectangle.prototype.appendChild = function(node) { + this.node.appendChild(node); +}; + +Rectangle.prototype.setId = function(id) { + this.node.id = id; +}; + + + +function initTextRectangle(iframe, name, rect) { + var ta = iframe.nextSibling; // ta -> textarea + var data = ta.value; + + if (browser.isGecko) { + // Just a few cleanups for Mozilla + data = data.replace(//ig,''); + data = data.replace(/]*)>/ig,''); + data = data.replace(/<\/strong>/ig,''); + + data = data.replace(//ig,''); + data = data.replace(/]*)>/ig,''); + data = data.replace(/<\/em>/ig,''); + } + + // change iframe id + iframe.id = IFramePrefix + name; + iframe.style.border = "0px none transparent"; + + + iframe.contentWindow.document.body.innerHTML = data; + iframe.contentWindow.document.id = DocPrefix + name; + addListener(iframe, "click", handlePlinnEpozRedirect); + if (browser.isMac) { + addListener(iframe.contentWindow.document, 'overflow', function(){rect._mac_moveDelHandle();}); + addListener(iframe.contentWindow.document, 'underflow', function(){rect._mac_moveDelHandle();}); + } + + if (browser.isGecko) { + scriptExpr = 'EnableDesignMode("' + iframe.id + '");'; + window.setTimeout(scriptExpr, 10); + } +} + +// « overloads » + +function handlePlinnEpozRedirect(evt) { + redirectPlinnEpoz(getTargetedObject(evt)); +} + +function redirectPlinnEpoz(iframe) { + if(EpozElement) { + if (EpozElement == iframe) + return; + unwrapPlinnEpozVariables(); + } + + // update Epoz variables + wrapPlinnEpozVariables(iframe); + EpozElement.contentWindow.focus(); +} + +function wrapPlinnEpozVariables(iframe) { + fieldId = iframe.contentWindow.document.id.slice(DocPrefixLength); + + iframe.id = Epoz ; + EpozElement=iframe; + EpozTextArea = document.getElementById(fieldId); +} + + +function unwrapPlinnEpozVariables() { + if (!EpozElement) // no redirection happens yet. + return; + try { + fieldId = EpozElement.contentWindow.document.id.slice(DocPrefixLength); + } + catch (e) { } + + EpozElement.id = IFramePrefix + fieldId; +} diff --git a/skins/layout_objects.js.metadata b/skins/layout_objects.js.metadata new file mode 100644 index 0000000..855fecc --- /dev/null +++ b/skins/layout_objects.js.metadata @@ -0,0 +1,2 @@ +[default] +cache=HTTPCache diff --git a/skins/plinn_attachment_form.py b/skins/plinn_attachment_form.py new file mode 100644 index 0000000..090c57b --- /dev/null +++ b/skins/plinn_attachment_form.py @@ -0,0 +1,28 @@ +##parameters= +form = context.REQUEST.form +formId = form.get('formId') +epozInsert = form.get('epozInsert', False) +file = form.get('file', None) +fileOb = None + +if file : fileOb = context.addAttachment(file, formId) + +onload = None +if fileOb is not None : + if fileOb.meta_type == 'Photo' : + fileUrl = 'attachments/%s/getThumbnail' % fileOb.getId() + if epozInsert : + onload = "dispatchImageAndHideUploadForm('%s', '%s', true);" % (fileUrl, formId) + else : + ratio = float(fileOb.height)/fileOb.width + dispatchValue = "%f_%s" % (ratio, fileUrl) + onload = "dispatchImageAndHideUploadForm('%s','%s', false);" % (dispatchValue, formId) + else : + dispatchValue = '%s[%s]' % (fileOb.getId(), 'attachments/'+fileOb.getId()) + onload = "dispatchFileAndHideUploadForm('%s', '%s');" % (dispatchValue, formId) + +hideFormCode = "hideUploadForm('%s');" % formId + +return context.plinn_attachment_template(onload=onload, + hideFormCode=hideFormCode, + formId=formId) \ No newline at end of file diff --git a/skins/plinn_attachment_template.pt b/skins/plinn_attachment_template.pt new file mode 100644 index 0000000..062bfdc --- /dev/null +++ b/skins/plinn_attachment_template.pt @@ -0,0 +1,56 @@ + + + + + + + + + + + + + Image upload form + + + +

    Insert image

    +

    Insert file

    +
    + +
    + +
    + + + + \ No newline at end of file diff --git a/skins/plinn_blank_iframe.html.pt b/skins/plinn_blank_iframe.html.pt new file mode 100755 index 0000000..7029a91 --- /dev/null +++ b/skins/plinn_blank_iframe.html.pt @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/skins/plinn_doc.gif b/skins/plinn_doc.gif new file mode 100644 index 0000000000000000000000000000000000000000..a92c9aec8c5c990ebad6df4a6c85d9def42a5fa0 GIT binary patch literal 135 zcmV;20C@jLNk%w1VGsZi0FeU#V`_28*W~~J0RR90A^sRVLr+jyK0;+~Z|-y;P)SZ8 zEg(>AX>M)+A^8LW00093EC2ui01yBW0006!oQ{dZ5)Xl523omVP!0>~IFN{enAX>M)+A^8LW00093EC2ui0Du6100092oNuDb?GK}zv{r<(PPY3GhRjB4;)$kU z$sXzp$4cAE_WjW;&i9aB@(G1N((s5YZXkiC^9hYgr&K2Z8Bv-Z)votz#XhtdCiskg zUd1Ca!kmtS*KC3N&6VrDbn)GlwH0oBC98q#2-R8l^rdnSf?NYgDegL(2wI)(UcC8B4NmpuMFn#X`d`kr}%Qk)u26a4i z@1VkN4iEmKcxKnTfF*yt?1eHJ%bvA@c3ahO$JHnnPpF%^GV8o%TWh8O+d*8UDqKs* zy}5D4&a`{qel1uxXRN$a_>KUavFhg3PdryDS_|po&X5029(+3Y>LRYo&8}qoU*@!* zy9X~_HhIXz*H=+bAGLDfB=Oq+uic(^{neM>eX)%;+ke<4SYToYYRBMk?EUxNV-gy; zpLhyJIG}#x1!$oi%Y8N9g$|b3A%@|}_u+=65oqFq8M5eNiw#!j-;Dz9W}}HX!kFTT zD=Y;f^B$h@_4o8mVG@MD`e@j8sNP){^-7C?J$VN(o_+UBcI(m0+gFp_g8o znI(Vbq3D5{O1dfFmLJF&B9FM$*#Vw8&Y)$Vd|Kcqka{8)Vw__V_8^*Ya;WH&WCBWO zqL2zIDWfw^+2nVY61pg6jTV7eW|@k*X_z3Qx@uVGjS57mr$y=HpCVRj+KXuEO5%{J zCaGzwy9(RunWWCjWUa2#@|rBA8Y+7vv~jTMERE8Bc`cS)=DDP{LGtx#s*Vzi?Y6m+ zi{7!!7CJ1jwwC2>EY#lmthu2f%Wko4*8A#w}w`Z}(=_m<-? z!ofasaJT-7Q8BK|T9Yxq;6gm{zSi0sZ5Pu)5^V9E`v^ z6pS;#H4nUQ&kBocv%^B?4C~JL9__QSK;O)CWIrn%bkrCT{d7E9i_GcPT5sdEHDHH* Y%-CeJVfNWrq^^`1bSXpHH8@fA{X|$B#c=z54v%!JDsN|GaG{Qdj?)2E-8FF(9`^~v??Pfwn_b>__N8#kVv zJ9qcnx4*xB{eSZ0-K9$pZrytR^5v%=KmOgj_xi<)kGF5XxNzbAoH^V6g8>6IfZ|UU zMg|5A1|5)LAU`p%&3Bkm;GrYce_}~dr;g=(KjGjAt4L-}fdwk5VQYH=QoLVk?N<+W zU^Liy)_1ja0)vi@_z%I{Bp)t$DTyk#_WY_en%WT}tuExT&HbkA1S&f%9|G*ArVO}ml_PM9h ad6=2ma@hIzAJoXd{~-9$<0nrY8LR;* literal 0 HcmV?d00001 diff --git a/skins/plinn_icons/hidden_layer.gif b/skins/plinn_icons/hidden_layer.gif new file mode 100644 index 0000000000000000000000000000000000000000..8b85acb848f08e9403a7498b3600f8d4d6bc6e37 GIT binary patch literal 333 zcmZ?wbhEHbK78fMmCKhe-??+=#fukPwrp9wdiAwy*XGWhyKddOt5>g{ zK7D%U&YjDbFTZ{J_Q#JOFI>3r>({Txj~^dBdUVd5Ih!_ZTDEN2%9ShU&!4|y#fn|K zcAYtMX2XUJd-v|$w{PFKZ{Hq1e0cx<{bR?Defjcb)~s2xXV3l*1`N1?;!hSv1_m<* z9gq@`pBUJ(9A+1Is9Y1<;F2@5k~eFc)T4chP09011bN~PV literal 0 HcmV?d00001 diff --git a/skins/plinn_icons/imagebox.gif b/skins/plinn_icons/imagebox.gif new file mode 100644 index 0000000000000000000000000000000000000000..cb90831781b1b33991862325e7aa45a51ddccffc GIT binary patch literal 301 zcmV+|0n+|QNk%w1VHp4!0J8u9h=_H-FJ6)s;a8HySwi0 z?wOgH%*@PYW@Z2Y0RR90A^8LV00000EC2ui02u%o000Eq@X1N5y;vER&=Oc^8Ac$U z&jy$%W+XrYww40hY|9*y!W6*5pk*jD9tsU7kr*Z7z8Y@0#s&zm z07%PJB-hZeJk?d$B+p-MhQHnVFf0h=?L0BFxOpL_|dM^YhWs z(W5!y(U7<-50N`Q} zj?t;Ie12xtRAvDkjw9yo^wti`hcf^aRS11pdNU1yA{h>ZbRCcx2nYda5`C916_b>f zOfR6IoTG|{69)$a0}BfT1O){z0Rdy4N>osaw-<&6k-r;I4hx~h#>ERj5(2Ev&d<*R H0ucZ^3|VFS literal 0 HcmV?d00001 diff --git a/skins/plinn_icons/textarea.gif b/skins/plinn_icons/textarea.gif new file mode 100644 index 0000000000000000000000000000000000000000..21822d6d23da9ab95edde575269768ad443b81ff GIT binary patch literal 239 zcmZ?wbhEHblw^=(*v!Ci_Uzfackia9otZs*c6oXEs#U9Q-u%zN!0`V+h{ObnKUu(n zIv^5c1_R3+fs>xA*Q&oh`+MenRV8_WNgWH<<#;n44)mCxmQtQKSxRuh&IOJetX2f5 z9C{;sgtM0|#D}xRsr~5V^j$uYy~jelx*sq_r=*osFPP_&pSj!Gsp(X)wM=vQ^{+*B zrG+_7)%mR@^&*`O-MxkVwcc`5rI^!HCn_;>sO1^3&se-OWE5nu1^_rh5%Wj%lXeB;KACr_SSxpHN6baZTNY;|>YU0q#fX6B3;GcqzVu3o+B>+4%oRJ35h zf)y)PoH%i!qM~By(xo$J&b)W;UT<%2a&q#E7cUwb8ft56o0^&e0s?mL-o0bTj?bSz z-@0{c!h{JP9vS88`7Ti<_+zwy|N6YqA#8X1XfNARuAg%xY=QudHIlGoj6pi;MYf IQzL^l0Ga8TlmGw# literal 0 HcmV?d00001 diff --git a/skins/plinn_image_upload.gif b/skins/plinn_image_upload.gif new file mode 100644 index 0000000000000000000000000000000000000000..9020ace866925f229563524ce23385584906356b GIT binary patch literal 1046 zcmZ?wbhEHb6lV})_}*!a>(vu2bfC#+bpB5=#CSFb+A?7Fw&)XmcBs)Mz~Gp@dRdgbcbv$witt-XHz z`k_M?Pn@{6r(^P!D-Rybnoz#H$acoD+YcUYDM(&8f5E}MdzLI-GS9*1OHaYgn~#%r zM?WixnSXuSvW*+|@4w(5RF<2U*VotYU9mVmp>+Gf!~4vQ_Fp~Rd+teFTidZ?M~@u2 zeDB`#Gf4>-F5EeN`sRY8vl<#2T%x+-;}e&ySm{vfd+^fz&!4~LoqgSN&m*i z^-+;8S1+D;wD0r8yvw^cO_?&qqSEiEnU=*uvvcQepFDYe>eQ*nk00N%4G6dT7Q_}6 z6`e~@+`MVil&;R%^B13*KIilM_x^!tU%q^gPbfR&U|q8(ee2dOCapW}-@pI)&%d|P zR&V<2*E_pkymZcz&c6G{>wg3PBXBY)^2?52QEQ|~c z?F>2~+dz4Of#Wj+Kc|exh6M+kIfS)hR&1DXxSfyJP$Z(mq0y4xNk=fiL+NlAtAxyg z2Mx)R{k*zeH47XX7EagTHClO@iMvCvY1bDI1BTZA87$iq4qQCm(!t?Yk@MrC%So;U z%-$6ziZdcgny literal 0 HcmV?d00001 diff --git a/skins/plinn_init_javascript_code.dtml b/skins/plinn_init_javascript_code.dtml new file mode 100644 index 0000000..f83f7e8 --- /dev/null +++ b/skins/plinn_init_javascript_code.dtml @@ -0,0 +1,8 @@ + diff --git a/skins/plinn_macros.pt b/skins/plinn_macros.pt new file mode 100644 index 0000000..fd79963 --- /dev/null +++ b/skins/plinn_macros.pt @@ -0,0 +1,66 @@ + + + + + + + Plinn macros + + + +
    + +BoldItalicUnderlineStrikethrough SubscriptSuperscript RemoveFormat TextColorBackColor AlignLeftCenterAlignRight OrderedListUnorderedListOutdentIndent + +InsertImage
    +
    +
    + +InsertFile
    +
    +
    + +InsertLinkInsertAnchor +InsertRuleInsertTable UndoRedo +
    + + \ No newline at end of file diff --git a/skins/plinn_multilingual.js.pt b/skins/plinn_multilingual.js.pt new file mode 100644 index 0000000..bd0d5c7 --- /dev/null +++ b/skins/plinn_multilingual.js.pt @@ -0,0 +1,17 @@ +var PlinnLang=[]; + +PlinnLang[""]=""; + \ No newline at end of file diff --git a/skins/plinn_multilingual.js.pt.metadata b/skins/plinn_multilingual.js.pt.metadata new file mode 100644 index 0000000..855fecc --- /dev/null +++ b/skins/plinn_multilingual.js.pt.metadata @@ -0,0 +1,2 @@ +[default] +cache=HTTPCache diff --git a/skins/plinndocument_edit_control.py b/skins/plinndocument_edit_control.py new file mode 100644 index 0000000..a2e55b6 --- /dev/null +++ b/skins/plinndocument_edit_control.py @@ -0,0 +1,15 @@ +## Script (Python) "plinndocument_edit" +##parameters=text='', file='', SafetyBelt='', **kw +##title=Edit a document +## + +from Products.CMFDefault.exceptions import EditingConflict, ResourceLockedError + +if text != context.text : + try: + context.edit( 'html', text, file, safety_belt = SafetyBelt) + return context.setStatus(True, 'Document changed.') + except (ResourceLockedError, EditingConflict), msg: + return context.setStatus(False, msg) +else : + return context.setStatus(False, 'Nothing to change.') diff --git a/skins/plinndocument_edit_form.py b/skins/plinndocument_edit_form.py new file mode 100644 index 0000000..5484bcf --- /dev/null +++ b/skins/plinndocument_edit_form.py @@ -0,0 +1,13 @@ +##parameters=change='', change_and_view='', ajax='' + +form = context.REQUEST.form +if change and \ + context.plinndocument_edit_control(**form) and \ + context.setRedirect(context, 'object/edit', ajax=ajax) : + return +elif change_and_view and \ + context.plinndocument_edit_control(**form) and \ + context.setRedirect(context, 'object/view', ajax=ajax) : + return + +return context.plinndocument_edit_template() diff --git a/skins/plinndocument_edit_template.pt b/skins/plinndocument_edit_template.pt new file mode 100644 index 0000000..ef54386 --- /dev/null +++ b/skins/plinndocument_edit_template.pt @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + +
    +
    generic_header macro
    +
    + +
    + + + Add text    + + + + + Toggle layer visibility + +
    + + +
    + + + +
    + + +
    +
    + +
    + + diff --git a/skins/plinndocument_view.pt b/skins/plinndocument_view.pt new file mode 100644 index 0000000..c14b64d --- /dev/null +++ b/skins/plinndocument_view.pt @@ -0,0 +1,13 @@ + + + + + Plinn document edit + + + +

    + + + \ No newline at end of file diff --git a/skins/resize_handle.png b/skins/resize_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..2ecfaa1917db89c0f0e51de86f3931edea24d6a5 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kmUKs7M+Sy#H?H_c7y