|
/
Zope
/
gocept svn checkins
/
Archive
/
2008
/
2008-11
/
SVN: r6981 - gocept.pagewithimage/trunk/gocept/pagewithimage
[
SVN: r6980 - in gocept.infrastructure/testing/pupp... ]
[
SVN: r6983 - in CMFWebmail/trunk: . gocept ... ]
SVN: r6981 - gocept.pagewithimage/trunk/gocept/pagewithimage
Daniel Havlik <dh(at)gocept.com> |
2008-11-04 08:53:50 |
[ FULL ]
|
Author: nilo
Date: Tue Nov 4 08:53:47 2008
New Revision: 6981
Log:
moved viewlet html js and css stuff into a template
Added:
gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.pt
Modified:
gocept.pagewithimage/trunk/gocept/pagewithimage/configure.zcml
gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.py
Modified: gocept.pagewithimage/trunk/gocept/pagewithimage/configure.zcml
==============================================================================
--- gocept.pagewithimage/trunk/gocept/pagewithimage/configure.zcml (original)
+++ gocept.pagewithimage/trunk/gocept/pagewithimage/configure.zcml Tue Nov 4
08:53:47 2008
(at)(at) -18,7 +18,8 (at)(at)
<browser:viewlet
name="gocept.pagewithimageviewlet"
manager="plone.app.layout.viewlets.interfaces.IAboveContentBody"
- class=".viewlet.PageWithImageViewlet"
+ template="viewlet.pt"
+ class=".viewlet.PageWithImageViewlet"
permission="zope2.View"
/>
Added: gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.pt
==============================================================================
--- (empty file)
+++ gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.pt Tue Nov 4
08:53:47 2008
(at)(at) -0,0 +1,407 (at)(at)
+<script type="text/javascript">
+// If you would like to use a custom loading image or close button reference
them in the next two lines.
+var loadingImage = 'loading.gif';
+var closeButton = 'close.gif';
+
+// getPageScroll()
+// Returns array with x,y page scroll values.
+// Core code from - quirksmode.org
+function getPageScroll(){
+
+ var yScroll;
+
+ if (self.pageYOffset) {
+ yScroll = self.pageYOffset;
+ } else if (document.documentElement &&
document.documentElement.scrollTop){ // Explorer 6 Strict
+ yScroll = document.documentElement.scrollTop;
+ } else if (document.body) {// all other Explorers
+ yScroll = document.body.scrollTop;
+ }
+
+ arrayPageScroll = new Array('',yScroll)
+ return arrayPageScroll;
+}
+
+// getPageSize()
+// Returns array with page width, height and window width, height
+// Core code from - quirksmode.org
+// Edit for Firefox by pHaez
+function getPageSize(){
+
+ var xScroll, yScroll;
+
+ if (window.innerHeight && window.scrollMaxY) {
+ xScroll = document.body.scrollWidth;
+ yScroll = window.innerHeight + window.scrollMaxY;
+ } else if (document.body.scrollHeight > document.body.offsetHeight){ //
all but Explorer Mac
+ xScroll = document.body.scrollWidth;
+ yScroll = document.body.scrollHeight;
+ } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and
Safari
+ xScroll = document.body.offsetWidth;
+ yScroll = document.body.offsetHeight;
+ }
+
+ var windowWidth, windowHeight;
+ if (self.innerHeight) { // all except Explorer
+ windowWidth = self.innerWidth;
+ windowHeight = self.innerHeight;
+ } else if (document.documentElement &&
document.documentElement.clientHeight) { // Explorer 6 Strict Mode
+ windowWidth = document.documentElement.clientWidth;
+ windowHeight = document.documentElement.clientHeight;
+ } else if (document.body) { // other Explorers
+ windowWidth = document.body.clientWidth;
+ windowHeight = document.body.clientHeight;
+ }
+
+ // for small pages with total height less then height of the viewport
+ if(yScroll < windowHeight){
+ pageHeight = windowHeight;
+ } else {
+ pageHeight = yScroll;
+ }
+
+ // for small pages with total width less then width of the viewport
+ if(xScroll < windowWidth){
+ pageWidth = windowWidth;
+ } else {
+ pageWidth = xScroll;
+ }
+
+
+ arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
+ return arrayPageSize;
+}
+
+
+//
+// pause(numberMillis)
+// Pauses code execution for specified time. Uses busy code, not good.
+// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
+//
+function pause(numberMillis) {
+ var now = new Date();
+ var exitTime = now.getTime() + numberMillis;
+ while (true) {
+ now = new Date();
+ if (now.getTime() > exitTime)
+ return;
+ }
+}
+
+//
+// getKey(key)
+// Gets keycode. If 'x' is pressed then it hides the lightbox.
+//
+
+function getKey(e){
+ if (e == null) { // ie
+ keycode = event.keyCode;
+ } else { // mozilla
+ keycode = e.which;
+ }
+ key = String.fromCharCode(keycode).toLowerCase();
+
+ if(key == 'x'){ hideLightbox(); }
+}
+
+
+//
+// listenKey()
+//
+function listenKey () { document.onkeypress = getKey; }
+
+
+//
+// showLightbox()
+// Preloads images. Pleaces new image in lightbox then centers and displays.
+//
+function showLightbox(objLink)
+{
+ // prep objects
+ var objOverlay = document.getElementById('overlay');
+ var objLightbox = document.getElementById('lightbox');
+ var objCaption = document.getElementById('lightboxCaption');
+ var objImage = document.getElementById('lightboxImage');
+ var objLoadingImage = document.getElementById('loadingImage');
+ var objLightboxDetails = document.getElementById('lightboxDetails');
+
+
+ var arrayPageSize = getPageSize();
+ var arrayPageScroll = getPageScroll();
+
+ // center loadingImage if it exists
+ if (objLoadingImage) {
+ objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 -
objLoadingImage.height) / 2) + 'px');
+ objLoadingImage.style.left = (((arrayPageSize[0] - 20 -
objLoadingImage.width) / 2) + 'px');
+ objLoadingImage.style.display = 'block';
+ }
+
+ // set height of Overlay to take up whole page and show
+ objOverlay.style.height = (arrayPageSize[1] + 'px');
+ objOverlay.style.display = 'block';
+
+ // preload image
+ imgPreload = new Image();
+
+ imgPreload.onload=function(){
+ objImage.src = objLink.href;
+
+ // center lightbox and make sure that the top and left values are not
negative
+ // and the image placed outside the viewport
+ var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 -
imgPreload.height) / 2);
+ var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2);
+
+ objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px";
+ objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft +
"px";
+
+
+ objLightboxDetails.style.width = imgPreload.width + 'px';
+
+ if(objLink.getAttribute('title')){
+ objCaption.style.display = 'block';
+ //objCaption.style.width = imgPreload.width + 'px';
+ objCaption.innerHTML = objLink.getAttribute('title');
+ } else {
+ objCaption.style.display = 'none';
+ }
+
+ // A small pause between the image loading and displaying is required with
IE,
+ // this prevents the previous image displaying for a short burst causing
flicker.
+ if (navigator.appVersion.indexOf("MSIE")!=-1){
+ pause(250);
+ }
+
+ if (objLoadingImage) { objLoadingImage.style.display = 'none'; }
+
+ // Hide select boxes as they will 'peek' through the image in IE
+ selects = document.getElementsByTagName("select");
+ for (i = 0; i != selects.length; i++) {
+ selects[i].style.visibility = "hidden";
+ }
+
+
+ objLightbox.style.display = 'block';
+
+ // After image is loaded, update the overlay height as the new image might
have
+ // increased the overall page height.
+ arrayPageSize = getPageSize();
+ objOverlay.style.height = (arrayPageSize[1] + 'px');
+
+ // Check for 'x' keypress
+ listenKey();
+
+ return false;
+ }
+
+ imgPreload.src = objLink.href;
+
+}
+
+
+
+
+
+//
+// hideLightbox()
+//
+function hideLightbox()
+{
+ // get objects
+ objOverlay = document.getElementById('overlay');
+ objLightbox = document.getElementById('lightbox');
+
+ // hide lightbox and overlay
+ objOverlay.style.display = 'none';
+ objLightbox.style.display = 'none';
+
+ // make select boxes visible
+ selects = document.getElementsByTagName("select");
+ for (i = 0; i != selects.length; i++) {
+ selects[i].style.visibility = "visible";
+ }
+
+ // disable keypress listener
+ document.onkeypress = '';
+}
+
+
+
+
+//
+// initLightbox()
+// Function runs on window load, going through link tags looking for
rel="lightbox".
+// These links receive onclick events that enable the lightbox display for
their targets.
+// The function also inserts html markup at the top of the page which will be
used as a
+// container for the overlay pattern and the inline image.
+//
+function initLightbox()
+{
+
+ if (!document.getElementsByTagName){ return; }
+ var anchors = document.getElementsByTagName("a");
+
+ // loop through all anchor tags
+ for (var i=0; i<anchors.length; i++){
+ var anchor = anchors[i];
+
+ if (anchor.getAttribute("href") && (anchor.getAttribute("rel") ==
"lightbox")){
+ anchor.onclick = function () {showLightbox(this); return false;}
+ }
+ }
+
+ var objBody = document.getElementsByTagName("body").item(0);
+
+ // create overlay div and hardcode some functional styles (aesthetic styles
are in CSS file)
+ var objOverlay = document.createElement("div");
+ objOverlay.setAttribute('id','overlay');
+ objOverlay.onclick = function () {hideLightbox(); return false;}
+ objOverlay.style.display = 'none';
+ objOverlay.style.position = 'absolute';
+ objOverlay.style.top = '0';
+ objOverlay.style.left = '0';
+ objOverlay.style.zIndex = '90';
+ objOverlay.style.width = '100%';
+ objBody.insertBefore(objOverlay, objBody.firstChild);
+
+ var arrayPageSize = getPageSize();
+ var arrayPageScroll = getPageScroll();
+
+ // preload and create loader image
+ var imgPreloader = new Image();
+
+ // if loader image found, create link to hide lightbox and create
loadingimage
+ imgPreloader.onload=function(){
+
+ var objLoadingImageLink = document.createElement("a");
+ objLoadingImageLink.setAttribute('href','#');
+ objLoadingImageLink.onclick = function () {hideLightbox(); return false;}
+ objOverlay.appendChild(objLoadingImageLink);
+
+ var objLoadingImage = document.createElement("img");
+ objLoadingImage.src = loadingImage;
+ objLoadingImage.setAttribute('id','loadingImage');
+ objLoadingImage.style.position = 'absolute';
+ objLoadingImage.style.zIndex = '150';
+ objLoadingImageLink.appendChild(objLoadingImage);
+
+ imgPreloader.onload=function(){}; // clear onLoad, as IE will flip out
w/animated gifs
+
+ return false;
+ }
+
+ imgPreloader.src = loadingImage;
+
+ // create lightbox div, same note about styles as above
+ var objLightbox = document.createElement("div");
+ objLightbox.setAttribute('id','lightbox');
+ objLightbox.style.display = 'none';
+ objLightbox.style.position = 'absolute';
+ objLightbox.style.zIndex = '100';
+ objBody.insertBefore(objLightbox, objOverlay.nextSibling);
+
+ // create link
+ var objLink = document.createElement("a");
+ objLink.setAttribute('href','#');
+ objLink.setAttribute('title','Click to close');
+ objLink.onclick = function () {hideLightbox(); return false;}
+ objLightbox.appendChild(objLink);
+
+ // preload and create close button image
+ var imgPreloadCloseButton = new Image();
+
+ // if close button image found,
+ imgPreloadCloseButton.onload=function(){
+
+ var objCloseButton = document.createElement("img");
+ objCloseButton.src = closeButton;
+ objCloseButton.setAttribute('id','closeButton');
+ objCloseButton.style.position = 'absolute';
+ objCloseButton.style.zIndex = '200';
+ objLink.appendChild(objCloseButton);
+
+ return false;
+ }
+
+ imgPreloadCloseButton.src = closeButton;
+
+ // create image
+ var objImage = document.createElement("img");
+ objImage.setAttribute('id','lightboxImage');
+ objLink.appendChild(objImage);
+
+ // create details div, a container for the caption and keyboard message
+ var objLightboxDetails = document.createElement("div");
+ objLightboxDetails.setAttribute('id','lightboxDetails');
+ objLightbox.appendChild(objLightboxDetails);
+
+ // create caption
+ var objCaption = document.createElement("div");
+ objCaption.setAttribute('id','lightboxCaption');
+ objCaption.style.display = 'none';
+ objLightboxDetails.appendChild(objCaption);
+
+ // create keyboard message
+ var objKeyboardMsg = document.createElement("div");
+ objKeyboardMsg.setAttribute('id','keyboardMsg');
+ objKeyboardMsg.innerHTML = ''
+ objLightboxDetails.appendChild(objKeyboardMsg);
+}
+
+//
+// addLoadEvent()
+// Adds event to window.onload without overwriting currently assigned onload
functions.
+// Function found at Simon Willison's weblog - http://simon.incutio.com/
+//
+function addLoadEvent(func)
+{
+ var oldonload = window.onload;
+ if (typeof window.onload != 'function'){
+ window.onload = func;
+ } else {
+ window.onload = function(){
+ oldonload();
+ func();
+ }
+ }
+
+}
+
+
+
+addLoadEvent(initLightbox); // run initLightbox onLoad
+
+
+
+</script>
+<style type="text/css">
+
+#lightbox{
+ background-color:#eee;
+ padding: 10px;
+ border-bottom: 2px solid #666;
+ border-right: 2px solid #666;
+ }
+#lightboxDetails{
+ font-size: 0.8em;
+ padding-top: 0.4em;
+ }
+#lightboxCaption{ float: left; }
+#keyboardMsg{ float: right; }
+#closeButton{ top: 5px; right: 5px; }
+
+#lightbox img{ border: none; clear: both;}
+#overlay img{ border: none; }
+
+#overlay{ background-image: url(overlay.png); }
+
+* html #overlay{
+ background-color: #333;
+ back\ground-color: transparent;
+ background-image: url(blank.gif);
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="overlay.png",
sizingMethod="scale");
+ }
+</style>
+<a href="%s" rel="lightbox" title="%s" class="docimage_link"
+ tal:attributes="href python:context.absolute_url() + '/docimage_large';
+ title context/getImageCaption">
+<div style="float:right; margin-left:20px; margin-bottom:20px;"><img
src="%s/docimage_mini2" tal:attributes="src python:context.absolute_url() +
'/docimage_mini2'"/><p style="font-weight: bold;"
tal:content="context/getImageCaption">%s</p></div></a>
Modified: gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.py
==============================================================================
--- gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.py (original)
+++ gocept.pagewithimage/trunk/gocept/pagewithimage/viewlet.py Tue Nov 4
08:53:47 2008
(at)(at) -1,488 +1,17 (at)(at)
+# -*- coding: utf-8 -*-
+
from plone.app.layout.viewlets.common import ViewletBase
import Products.ATContentTypes.interface.document
-
-JS = u'''
-/*
- Lightbox JS: Fullsize Image Overlays
- by Lokesh Dhakar - http://www.huddletogether.com
-
- For more information on this script, visit:
- http://huddletogether.com/projects/lightbox/
-
- Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
- (basically, do anything you want, just leave my name and link)
-
- Table of Contents
- -----------------
- Configuration
-
- Functions
- - getPageScroll()
- - getPageSize()
- - pause()
- - getKey()
- - listenKey()
- - showLightbox()
- - hideLightbox()
- - initLightbox()
- - addLoadEvent()
-
- Function Calls
- - addLoadEvent(initLightbox)
-
-*/
-
-
-
-//
-// Configuration
-//
-
-// If you would like to use a custom loading image or close button reference
them in the next two lines.
-var loadingImage = 'loading.gif';
-var closeButton = 'close.gif';
-
-
-
-
-
-//
-// getPageScroll()
-// Returns array with x,y page scroll values.
-// Core code from - quirksmode.org
-//
-function getPageScroll(){
-
- var yScroll;
-
- if (self.pageYOffset) {
- yScroll = self.pageYOffset;
- } else if (document.documentElement &&
document.documentElement.scrollTop){ // Explorer 6 Strict
- yScroll = document.documentElement.scrollTop;
- } else if (document.body) {// all other Explorers
- yScroll = document.body.scrollTop;
- }
-
- arrayPageScroll = new Array('',yScroll)
- return arrayPageScroll;
-}
-
-
-
-//
-// getPageSize()
-// Returns array with page width, height and window width, height
-// Core code from - quirksmode.org
-// Edit for Firefox by pHaez
-//
-function getPageSize(){
-
- var xScroll, yScroll;
-
- if (window.innerHeight && window.scrollMaxY) {
- xScroll = document.body.scrollWidth;
- yScroll = window.innerHeight + window.scrollMaxY;
- } else if (document.body.scrollHeight > document.body.offsetHeight){ //
all but Explorer Mac
- xScroll = document.body.scrollWidth;
- yScroll = document.body.scrollHeight;
- } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and
Safari
- xScroll = document.body.offsetWidth;
- yScroll = document.body.offsetHeight;
- }
-
- var windowWidth, windowHeight;
- if (self.innerHeight) { // all except Explorer
- windowWidth = self.innerWidth;
- windowHeight = self.innerHeight;
- } else if (document.documentElement &&
document.documentElement.clientHeight) { // Explorer 6 Strict Mode
- windowWidth = document.documentElement.clientWidth;
- windowHeight = document.documentElement.clientHeight;
- } else if (document.body) { // other Explorers
- windowWidth = document.body.clientWidth;
- windowHeight = document.body.clientHeight;
- }
-
- // for small pages with total height less then height of the viewport
- if(yScroll < windowHeight){
- pageHeight = windowHeight;
- } else {
- pageHeight = yScroll;
- }
-
- // for small pages with total width less then width of the viewport
- if(xScroll < windowWidth){
- pageWidth = windowWidth;
- } else {
- pageWidth = xScroll;
- }
-
-
- arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
- return arrayPageSize;
-}
-
-
-//
-// pause(numberMillis)
-// Pauses code execution for specified time. Uses busy code, not good.
-// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
-//
-function pause(numberMillis) {
- var now = new Date();
- var exitTime = now.getTime() + numberMillis;
- while (true) {
- now = new Date();
- if (now.getTime() > exitTime)
- return;
- }
-}
-
-//
-// getKey(key)
-// Gets keycode. If 'x' is pressed then it hides the lightbox.
-//
-
-function getKey(e){
- if (e == null) { // ie
- keycode = event.keyCode;
- } else { // mozilla
- keycode = e.which;
- }
- key = String.fromCharCode(keycode).toLowerCase();
-
- if(key == 'x'){ hideLightbox(); }
-}
-
-
-//
-// listenKey()
-//
-function listenKey () { document.onkeypress = getKey; }
-
-
-//
-// showLightbox()
-// Preloads images. Pleaces new image in lightbox then centers and displays.
-//
-function showLightbox(objLink)
-{
- // prep objects
- var objOverlay = document.getElementById('overlay');
- var objLightbox = document.getElementById('lightbox');
- var objCaption = document.getElementById('lightboxCaption');
- var objImage = document.getElementById('lightboxImage');
- var objLoadingImage = document.getElementById('loadingImage');
- var objLightboxDetails = document.getElementById('lightboxDetails');
-
-
- var arrayPageSize = getPageSize();
- var arrayPageScroll = getPageScroll();
-
- // center loadingImage if it exists
- if (objLoadingImage) {
- objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 -
objLoadingImage.height) / 2) + 'px');
- objLoadingImage.style.left = (((arrayPageSize[0] - 20 -
objLoadingImage.width) / 2) + 'px');
- objLoadingImage.style.display = 'block';
- }
-
- // set height of Overlay to take up whole page and show
- objOverlay.style.height = (arrayPageSize[1] + 'px');
- objOverlay.style.display = 'block';
-
- // preload image
- imgPreload = new Image();
-
- imgPreload.onload=function(){
- objImage.src = objLink.href;
-
- // center lightbox and make sure that the top and left values are not
negative
- // and the image placed outside the viewport
- var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 -
imgPreload.height) / 2);
- var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2);
-
- objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px";
- objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft +
"px";
-
-
- objLightboxDetails.style.width = imgPreload.width + 'px';
-
- if(objLink.getAttribute('title')){
- objCaption.style.display = 'block';
- //objCaption.style.width = imgPreload.width + 'px';
- objCaption.innerHTML = objLink.getAttribute('title');
- } else {
- objCaption.style.display = 'none';
- }
-
- // A small pause between the image loading and displaying is required with
IE,
- // this prevents the previous image displaying for a short burst causing
flicker.
- if (navigator.appVersion.indexOf("MSIE")!=-1){
- pause(250);
- }
-
- if (objLoadingImage) { objLoadingImage.style.display = 'none'; }
-
- // Hide select boxes as they will 'peek' through the image in IE
- selects = document.getElementsByTagName("select");
- for (i = 0; i != selects.length; i++) {
- selects[i].style.visibility = "hidden";
- }
-
-
- objLightbox.style.display = 'block';
-
- // After image is loaded, update the overlay height as the new image might
have
- // increased the overall page height.
- arrayPageSize = getPageSize();
- objOverlay.style.height = (arrayPageSize[1] + 'px');
-
- // Check for 'x' keypress
- listenKey();
-
- return false;
- }
-
- imgPreload.src = objLink.href;
-
-}
-
-
-
-
-
-//
-// hideLightbox()
-//
-function hideLightbox()
-{
- // get objects
- objOverlay = document.getElementById('overlay');
- objLightbox = document.getElementById('lightbox');
-
- // hide lightbox and overlay
- objOverlay.style.display = 'none';
- objLightbox.style.display = 'none';
-
- // make select boxes visible
- selects = document.getElementsByTagName("select");
- for (i = 0; i != selects.length; i++) {
- selects[i].style.visibility = "visible";
- }
-
- // disable keypress listener
- document.onkeypress = '';
-}
-
-
-
-
-//
-// initLightbox()
-// Function runs on window load, going through link tags looking for
rel="lightbox".
-// These links receive onclick events that enable the lightbox display for
their targets.
-// The function also inserts html markup at the top of the page which will be
used as a
-// container for the overlay pattern and the inline image.
-//
-function initLightbox()
-{
-
- if (!document.getElementsByTagName){ return; }
- var anchors = document.getElementsByTagName("a");
-
- // loop through all anchor tags
- for (var i=0; i<anchors.length; i++){
- var anchor = anchors[i];
-
- if (anchor.getAttribute("href") && (anchor.getAttribute("rel") ==
"lightbox")){
- anchor.onclick = function () {showLightbox(this); return false;}
- }
- }
-
- // the rest of this code inserts html at the top of the page that looks like
this:
- //
- // <div id="overlay">
- // <a href="#" onclick="hideLightbox(); return false;"><img
id="loadingImage" /></a>
- // </div>
- // <div id="lightbox">
- // <a href="#" onclick="hideLightbox(); return false;" title="Click
anywhere to close image">
- // <img id="closeButton" />
- // <img id="lightboxImage" />
- // </a>
- // <div id="lightboxDetails">
- // <div id="lightboxCaption"></div>
- // <div id="keyboardMsg"></div>
- // </div>
- // </div>
-
- var objBody = document.getElementsByTagName("body").item(0);
-
- // create overlay div and hardcode some functional styles (aesthetic styles
are in CSS file)
- var objOverlay = document.createElement("div");
- objOverlay.setAttribute('id','overlay');
- objOverlay.onclick = function () {hideLightbox(); return false;}
- objOverlay.style.display = 'none';
- objOverlay.style.position = 'absolute';
- objOverlay.style.top = '0';
- objOverlay.style.left = '0';
- objOverlay.style.zIndex = '90';
- objOverlay.style.width = '100%';
- objBody.insertBefore(objOverlay, objBody.firstChild);
-
- var arrayPageSize = getPageSize();
- var arrayPageScroll = getPageScroll();
-
- // preload and create loader image
- var imgPreloader = new Image();
-
- // if loader image found, create link to hide lightbox and create
loadingimage
- imgPreloader.onload=function(){
-
- var objLoadingImageLink = document.createElement("a");
- objLoadingImageLink.setAttribute('href','#');
- objLoadingImageLink.onclick = function () {hideLightbox(); return false;}
- objOverlay.appendChild(objLoadingImageLink);
-
- var objLoadingImage = document.createElement("img");
- objLoadingImage.src = loadingImage;
- objLoadingImage.setAttribute('id','loadingImage');
- objLoadingImage.style.position = 'absolute';
- objLoadingImage.style.zIndex = '150';
- objLoadingImageLink.appendChild(objLoadingImage);
-
- imgPreloader.onload=function(){}; // clear onLoad, as IE will flip out
w/animated gifs
-
- return false;
- }
-
- imgPreloader.src = loadingImage;
-
- // create lightbox div, same note about styles as above
- var objLightbox = document.createElement("div");
- objLightbox.setAttribute('id','lightbox');
- objLightbox.style.display = 'none';
- objLightbox.style.position = 'absolute';
- objLightbox.style.zIndex = '100';
- objBody.insertBefore(objLightbox, objOverlay.nextSibling);
-
- // create link
- var objLink = document.createElement("a");
- objLink.setAttribute('href','#');
- objLink.setAttribute('title','Click to close');
- objLink.onclick = function () {hideLightbox(); return false;}
- objLightbox.appendChild(objLink);
-
- // preload and create close button image
- var imgPreloadCloseButton = new Image();
-
- // if close button image found,
- imgPreloadCloseButton.onload=function(){
-
- var objCloseButton = document.createElement("img");
- objCloseButton.src = closeButton;
- objCloseButton.setAttribute('id','closeButton');
- objCloseButton.style.position = 'absolute';
- objCloseButton.style.zIndex = '200';
- objLink.appendChild(objCloseButton);
-
- return false;
- }
-
- imgPreloadCloseButton.src = closeButton;
-
- // create image
- var objImage = document.createElement("img");
- objImage.setAttribute('id','lightboxImage');
- objLink.appendChild(objImage);
-
- // create details div, a container for the caption and keyboard message
- var objLightboxDetails = document.createElement("div");
- objLightboxDetails.setAttribute('id','lightboxDetails');
- objLightbox.appendChild(objLightboxDetails);
-
- // create caption
- var objCaption = document.createElement("div");
- objCaption.setAttribute('id','lightboxCaption');
- objCaption.style.display = 'none';
- objLightboxDetails.appendChild(objCaption);
-
- // create keyboard message
- var objKeyboardMsg = document.createElement("div");
- objKeyboardMsg.setAttribute('id','keyboardMsg');
- objKeyboardMsg.innerHTML = 'press <a href="#" onclick="hideLightbox();
return false;"><kbd>x</kbd></a> to close';
- objLightboxDetails.appendChild(objKeyboardMsg);
-
-
-}
-
-
-
-
-//
-// addLoadEvent()
-// Adds event to window.onload without overwriting currently assigned onload
functions.
-// Function found at Simon Willison's weblog - http://simon.incutio.com/
-//
-function addLoadEvent(func)
-{
- var oldonload = window.onload;
- if (typeof window.onload != 'function'){
- window.onload = func;
- } else {
- window.onload = function(){
- oldonload();
- func();
- }
- }
-
-}
-
-
-
-addLoadEvent(initLightbox); // run initLightbox onLoad '''
-
-
-CSS = u'''
-#lightbox{
- background-color:#eee;
- padding: 10px;
- border-bottom: 2px solid #666;
- border-right: 2px solid #666;
- }
-#lightboxDetails{
- font-size: 0.8em;
- padding-top: 0.4em;
- }
-#lightboxCaption{ float: left; }
-#keyboardMsg{ float: right; }
-#closeButton{ top: 5px; right: 5px; }
-
-#lightbox img{ border: none; clear: both;}
-#overlay img{ border: none; }
-
-#overlay{ background-image: url(overlay.png); }
-
-* html #overlay{
- background-color: #333;
- back\ground-color: transparent;
- background-image: url(blank.gif);
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="overlay.png",
sizingMethod="scale");
- }
-'''
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class PageWithImageViewlet(ViewletBase):
"""viewlet which displays the image of a page"""
+ template = ViewPageTemplateFile('viewlet.pt')
def render(self):
if Products.ATContentTypes.interface.document.IATDocument.providedBy(
self.context):
if self.context.getDocimage():
- return u'<script
type="text/javascript">%s</script><style
type="text/css">%s</style><a href="%s" rel="lightbox" title="%s"
class="docimage_link"><div style="float:right; margin-left:20px;
margin-bottom:20px;"><img src="%s/docimage_mini2" />'\
- '<p style="font-weight:
bold;">%s</p></div></a>' % (
- JS,
- CSS,
- self.context.absolute_url() + '/docimage_large',
- self.context.getImageCaption(),
- self.context.absolute_url(),
- self.context.getImageCaption(),)
+ return self.template()
return u''
|
SVN: r6984 - gocept.pagewithimage/trunk/gocept/pagewithimage
Daniel Havlik <dh(at)gocept.com> |
2008-11-05 11:25:21 |
[ FULL ]
|
Author: nilo
Date: Wed Nov 5 11:25:20 2008
New Revision: 6984
Log:
replacing reference browser widget of the document with alternative, which
allows sorting of references
Modified:
gocept.pagewithimage/trunk/gocept/pagewithimage/__init__.py
Modified: gocept.pagewithimage/trunk/gocept/pagewithimage/__init__.py
==============================================================================
--- gocept.pagewithimage/trunk/gocept/pagewithimage/__init__.py (original)
+++ gocept.pagewithimage/trunk/gocept/pagewithimage/__init__.py Wed Nov 5
11:25:20 2008
(at)(at) -9,6 +9,20 (at)(at)
def initialize(context):
"""Initializer called when used as a Zope 2 product."""
from Products.ATContentTypes.content import document
+ import archetypes.referencebrowserwidget
+ document.ATDocument.schema._fields['relatedItems'].widget =\
+ archetypes.referencebrowserwidget.widget.ReferenceBrowserWidget(
+ allow_search = True,
+ allow_browse = True,
+ allow_sorting = True,
+ show_indexes = False,
+ force_close_on_insert = True,
+ label = _(u'label_related_items', default=u'Related Items'),
+ description = '',
+ visible = {'edit' : 'visible', 'view' : 'invisible' }
+ )
+
+
from Products.ATContentTypes.content import folder
image_field = ImageField('docimage',
required = False,
|
SVN: r6986 - gocept.restmail/trunk
Christian Zagrodnick <cz(at)gocept.com> |
2008-11-05 13:02:03 |
[ FULL ]
|
Author: zagy
Date: Wed Nov 5 13:02:02 2008
New Revision: 6986
Log:
require setuptools
Modified:
gocept.restmail/trunk/setup.py
Modified: gocept.restmail/trunk/setup.py
==============================================================================
--- gocept.restmail/trunk/setup.py (original)
+++ gocept.restmail/trunk/setup.py Wed Nov 5 13:02:02 2008
(at)(at) -18,5 +18,6 (at)(at)
install_requires=['lxml',
'python-cjson',
'uuid',
+ 'setuptools',
],
)
|
SVN: r6987 - gocept.restmail/trunk/gocept/restmail
Christian Zagrodnick <cz(at)gocept.com> |
2008-11-05 13:02:09 |
[ FULL ]
|
Author: zagy
Date: Wed Nov 5 13:02:08 2008
New Revision: 6987
Log:
add mailhost in tests
Modified:
gocept.restmail/trunk/gocept/restmail/tests.py
Modified: gocept.restmail/trunk/gocept/restmail/tests.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/tests.py (original)
+++ gocept.restmail/trunk/gocept/restmail/tests.py Wed Nov 5 13:02:08 2008
(at)(at) -32,7 +32,7 (at)(at)
globs = {}
- products = ['SiteAccess', 'BTreeFolder2', 'ZCatalog', 'Five']
+ products = ['SiteAccess', 'BTreeFolder2', 'ZCatalog', 'Five', 'MailHost']
def setUp(self):
for product in self.products:
|
SVN: r6988 - CMFWebmail/trunk/gocept/webmail
Thomas Lotze <tl(at)gocept.com> |
2008-11-05 13:16:24 |
[ FULL ]
|
Author: thomas
Date: Wed Nov 5 13:16:23 2008
New Revision: 6988
Log:
close the composer window when done with it
Modified:
CMFWebmail/trunk/gocept/webmail/README.txt
Modified: CMFWebmail/trunk/gocept/webmail/README.txt
==============================================================================
--- CMFWebmail/trunk/gocept/webmail/README.txt (original)
+++ CMFWebmail/trunk/gocept/webmail/README.txt Wed Nov 5 13:16:23 2008
(at)(at) -263,7 +263,7 (at)(at)
Subject: The quick brown fox jumped over the lazy dog.
<BLANKLINE>
<p><strong>blub</strong></p>
->>> go_home()
+>>> close_window()
>>> time.sleep(1)
|
SVN: r6990 - in gocept.imapapi/trunk/gocept/imapapi: . testmessages
Thomas Lotze <tl(at)gocept.com> |
2008-11-05 18:00:16 |
[ FULL ]
|
Author: thomas
Date: Wed Nov 5 18:00:14 2008
New Revision: 6990
Log:
read test messages from files
Added:
gocept.imapapi/trunk/gocept/imapapi/testmessages/
gocept.imapapi/trunk/gocept/imapapi/testmessages/00-header-encoding
gocept.imapapi/trunk/gocept/imapapi/testmessages/01-everything-is-ok
Modified:
gocept.imapapi/trunk/gocept/imapapi/tests.py
Added: gocept.imapapi/trunk/gocept/imapapi/testmessages/00-header-encoding
==============================================================================
--- (empty file)
+++ gocept.imapapi/trunk/gocept/imapapi/testmessages/00-header-encoding Wed Nov
5 18:00:14 2008
(at)(at) -0,0 +1,10 (at)(at)
+From: test(at)localhost
+X-IMAPAPI-Test: 1
+X-No-Encoding-Header: Text ü or not
+X-Wrong-Encoding-Header: =?ascii?q?Text_=C3=BC?=
+X-Unknown-Encoding-Header: =?foobarschnappeldiwutz?q?Text_=C3=BC?=
+X-Correct-Encoding-Header: =?utf-8?q?Text_=C3=BC?=
+Date: 02-Jul-2008 03:05:00 +0200
+Subject: Mail 1
+
+Everything is ok!
\ No newline at end of file
Added: gocept.imapapi/trunk/gocept/imapapi/testmessages/01-everything-is-ok
==============================================================================
--- (empty file)
+++ gocept.imapapi/trunk/gocept/imapapi/testmessages/01-everything-is-ok Wed
Nov 5 18:00:14 2008
(at)(at) -0,0 +1,6 (at)(at)
+From: test(at)localhost
+X-IMAPAPI-Test: 2
+Date: 02-Jul-2008 03:06:00 +0200
+Subject: Mail 2
+
+Everything is ok!
Modified: gocept.imapapi/trunk/gocept/imapapi/tests.py
==============================================================================
--- gocept.imapapi/trunk/gocept/imapapi/tests.py (original)
+++ gocept.imapapi/trunk/gocept/imapapi/tests.py Wed Nov 5 18:00:14 2008
(at)(at) -4,6 +4,10 (at)(at)
# $Id$
"""Test harness for gocept.imapapi."""
+import imaplib
+import os
+import os.path
+import time
import unittest
from zope.testing import doctest
(at)(at) -17,6 +21,41 (at)(at)
return data
+def clear_inbox(server):
+ data = callIMAP(server, 'select', 'INBOX')
+ if int(data[0]) >= 1:
+ data = callIMAP(server, 'store', '1:*', '+FLAGS', '\\Deleted')
+ callIMAP(server, 'expunge')
+
+
+def load_messages(path, folder_name):
+ server = imaplib.IMAP4('localhost', 10143)
+ server.login('test', 'bsdf')
+ # Clean up the test folder from previous runs. We do not delete at the
+ # end of a run to preserve data for debugging purposes.
+ if folder_name == 'INBOX':
+ clear_inbox(server)
+ else:
+ callIMAP(server, 'delete', folder_name)
+ callIMAP(server, 'create', folder_name)
+
+ # Create messages in the test folder.
+ path = os.path.join(os.path.dirname(__file__), path)
+ for filename in sorted(os.listdir(path)):
+ if filename.startswith('.') or filename.endswith('~'):
+ continue
+ filepath = os.path.join(path, filename)
+ timestamp = os.path.getmtime(filepath)
+ localtime = time.localtime(timestamp)
+ date = time.strftime('"%d-%b-%Y %H:%M:%S +0200"', localtime)
+ message = open(filepath).read()
+ callIMAP(server, 'append', folder_name, '', date, message)
+
+ # Done.
+ status, data = server.logout()
+ assert status == 'BYE'
+
+
def setUp(self):
server = imaplib.IMAP4('localhost', 10143)
server.login('test', 'bsdf')
(at)(at) -34,26 +73,10 (at)(at)
callIMAP(server, 'delete', name)
# Clear the INBOX from messages as we couldn't delete it earlier.
- data = callIMAP(server, 'select', 'INBOX')
- if int(data[0]) >= 1:
- data = callIMAP(server, 'store', '1:*', '+FLAGS', '\\Deleted')
- callIMAP(server, 'expunge')
+ clear_inbox(server)
# Create a message in the INBOX
- message = ('From: test(at)localhost\nX-IMAPAPI-Test: 1\n'
- 'X-No-Encoding-Header: Text \xFC or not\n'
- 'X-Wrong-Encoding-Header: =?ascii?q?Text_=C3=BC?=\n'
- 'X-Unknown-Encoding-Header:
=?foobarschnappeldiwutz?q?Text_=C3=BC?=\n'
- 'X-Correct-Encoding-Header: =?utf-8?q?Text_=C3=BC?=\n'
- 'Date: 02-Jul-2008 03:05:00 +0200\n'
- 'Subject: Mail 1\n\nEverything is ok!')
- callIMAP(server, 'append', 'INBOX', '', '"02-Jul-2008 03:05:00 +0200"',
- message)
- message = ('From: test(at)localhost\nX-IMAPAPI-Test: 2\n'
- 'Date: 02-Jul-2008 03:06:00 +0200\n'
- 'Subject: Mail 2\n\nEverything is ok!')
- callIMAP(server, 'append', 'INBOX', '', '"02-Jul-2008 03:06:00 +0200"',
- message)
+ load_messages('testmessages', 'INBOX')
# Create the standard hierarchy for tests
callIMAP(server, 'create', 'INBOX/Baz')
|
SVN: r6995 - gocept.restmail/trunk/gocept/restmail
Sebastian Wehrmann <sw(at)gocept.com> |
2008-11-06 09:30:47 |
[ FULL ]
|
Author: sweh
Date: Thu Nov 6 09:30:45 2008
New Revision: 6995
Log:
refactor quoting of message parts to user adapter lookups instead of eval()
Modified:
gocept.restmail/trunk/gocept/restmail/configure.zcml
gocept.restmail/trunk/gocept/restmail/draft.py
gocept.restmail/trunk/gocept/restmail/draft.txt
Modified: gocept.restmail/trunk/gocept/restmail/configure.zcml
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/configure.zcml (original)
+++ gocept.restmail/trunk/gocept/restmail/configure.zcml Thu Nov 6 09:30:45
2008
(at)(at) -46,4 +46,17 (at)(at)
<adapter factory=".profile.lookup_profile" />
+ <adapter
+ for="gocept.imapapi.interfaces.IBodyPart"
+ provides="gocept.imapapi.interfaces.IBodyPart"
+ name="convert_text"
+ factory=".draft.convert_text"
+ />
+
+ <adapter
+ for="gocept.imapapi.interfaces.IBodyPart"
+ provides="gocept.imapapi.interfaces.IBodyPart"
+ name="convert_default"
+ factory=".draft.convert_default"
+ />
</configure>
Modified: gocept.restmail/trunk/gocept/restmail/draft.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/draft.py (original)
+++ gocept.restmail/trunk/gocept/restmail/draft.py Thu Nov 6 09:30:45 2008
(at)(at) -151,26 +151,25 (at)(at)
def get_body_text(part):
- """ XXX use adapters."""
content_type = part['content_type']
if content_type:
major, minor = content_type.split('/')
- try:
- html_factory = eval('convert_%s_%s' % (major, minor))
- except NameError:
- html_factory = eval('convert_default')
- return html_factory(part)
+ output = zope.component.queryAdapter(
+ part, name='convert_%s_%s' % (major, minor))
+ if not output:
+ output = zope.component.queryAdapter(
+ part, name='convert_%s' % major)
+ if not output:
+ output = zope.component.getAdapter(
+ part, name='convert_default')
+ return output
def convert_default(part):
return "Message body part with content type %s." % part['content_type']
-def convert_text_plain(part):
- return part.fetch()
-
-
-def convert_text_html(part):
+def convert_text(part):
return part.fetch()
Modified: gocept.restmail/trunk/gocept/restmail/draft.txt
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/draft.txt (original)
+++ gocept.restmail/trunk/gocept/restmail/draft.txt Thu Nov 6 09:30:45 2008
(at)(at) -329,10 +329,9 (at)(at)
.. [#gettextpart]
>>> def get_text_part(message):
- ... for content_type in ('text/html', 'text/plain'):
- ... part = message.body().find_one(content_type)
- ... if part:
- ... return part
+ ... part = message.body()
+ ... if part['content_type'] in ('text/html', 'text/plain'):
+ ... return part
.. [#createprofile]
|
SVN: r6997 - in gocept.imapapi/trunk/gocept/imapapi: . testmessages
Sebastian Wehrmann <sw(at)gocept.com> |
2008-11-06 11:03:57 |
[ FULL ]
|
Author: sweh
Date: Thu Nov 6 11:03:56 2008
New Revision: 6997
Log:
add a checker for memory-adresses
add tests for messages of type multipart-alternative
Added:
gocept.imapapi/trunk/gocept/imapapi/testmessages/01-multipart-alternative
Removed:
gocept.imapapi/trunk/gocept/imapapi/testmessages/01-everything-is-ok
Modified:
gocept.imapapi/trunk/gocept/imapapi/account.txt
gocept.imapapi/trunk/gocept/imapapi/folder.txt
gocept.imapapi/trunk/gocept/imapapi/message.txt
gocept.imapapi/trunk/gocept/imapapi/tests.py
Modified: gocept.imapapi/trunk/gocept/imapapi/account.txt
==============================================================================
--- gocept.imapapi/trunk/gocept/imapapi/account.txt (original)
+++ gocept.imapapi/trunk/gocept/imapapi/account.txt Thu Nov 6 11:03:56 2008
(at)(at) -33,8 +33,8 (at)(at)
>>> from pprint import pprint
>>> pprint(dict(account.folders))
-{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x...>,
- 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x...>}
+{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x2615309>,
+ 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x2631278>}
>>> account.messages
Traceback (most recent call last):
(at)(at) -43,7 +43,7 (at)(at)
Individual folders can be retrieved by specifying their name:
>>> account.folders['INBOX']
-<gocept.imapapi.folder.Folder object 'INBOX' at 0x...>
+<gocept.imapapi.folder.Folder object 'INBOX' at 0x2176287>
>>> account.folders['nofolder']
Traceback (most recent call last):
Modified: gocept.imapapi/trunk/gocept/imapapi/folder.txt
==============================================================================
--- gocept.imapapi/trunk/gocept/imapapi/folder.txt (original)
+++ gocept.imapapi/trunk/gocept/imapapi/folder.txt Thu Nov 6 11:03:56 2008
(at)(at) -12,8 +12,8 (at)(at)
>>> from pprint import pprint
>>> account = Account('localhost', 10143, 'test', 'bsdf')
>>> pprint(account.folders)
-{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x...>,
- 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x...>}
+{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x2612732>,
+ 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x2134232>}
A folder knows about its name, path, separator, and depth in the hierarchy:
(at)(at) -30,7 +30,7 (at)(at)
Folders also provide access to their direct sub-folders:
>>> INBOX.folders
-{'Baz': <gocept.imapapi.folder.Folder object 'INBOX/Baz' at 0x...>}
+{'Baz': <gocept.imapapi.folder.Folder object 'INBOX/Baz' at 0x2318293>}
Here's a folder that's a bit deeper in the hierarchy:
(at)(at) -53,9 +53,9 (at)(at)
>>> from gocept.imapapi.folder import Folder
>>> account.folders['Top level'] = Folder()
>>> pprint(dict(account.folders))
-{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x...>,
- 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x...>,
- 'Top level': <gocept.imapapi.folder.Folder object 'Top level' at
0x...>}
+{'Bar': <gocept.imapapi.folder.Folder object 'Bar' at 0x2142346>,
+ 'INBOX': <gocept.imapapi.folder.Folder object 'INBOX' at 0x2762352>,
+ 'Top level': <gocept.imapapi.folder.Folder object 'Top level' at
0x2123423>}
>>> top_level = account.folders['Top level']
>>> top_level.name
'Top level'
(at)(at) -64,7 +64,7 (at)(at)
>>> top_level.folders['Subfolder'] = subfolder = Folder()
>>> top_level.folders
-{'Subfolder': <gocept.imapapi.folder.Folder object 'Top level/Subfolder' at
0x...>}
+{'Subfolder': <gocept.imapapi.folder.Folder object 'Top level/Subfolder' at
0x2132423>}
>>> subfolder.name
'Subfolder'
>>> subfolder.path
(at)(at) -77,8 +77,8 (at)(at)
Messages can be retrieved from a folder using its `messages` attribute:
>>> pprint(dict(INBOX.messages))
-{'...-...': <gocept.imapapi.message.Message object 'INBOX/...-...' at
0x...>,
- '...-...': <gocept.imapapi.message.Message object 'INBOX/...-...' at
0x...>}
+{'...-...': <gocept.imapapi.message.Message object 'INBOX/...-...' at
0x2162537>,
+ '...-...': <gocept.imapapi.message.Message object 'INBOX/...-...' at
0x2138986>}
Individual messages have a name attribute which can be used to uniquely
identify a message within a folder. We can use it to retrieve an individual
Modified: gocept.imapapi/trunk/gocept/imapapi/message.txt
==============================================================================
--- gocept.imapapi/trunk/gocept/imapapi/message.txt (original)
+++ gocept.imapapi/trunk/gocept/imapapi/message.txt Thu Nov 6 11:03:56 2008
(at)(at) -28,7 +28,8 (at)(at)
>>> message = INBOX.messages.values()[0]
>>> message
-<gocept.imapapi.message.Message object 'INBOX/...' at 0x...>
+<gocept.imapapi.message.Message object 'INBOX/...' at 0x2312872>
+
Headers
=======
(at)(at) -51,6 +52,17 (at)(at)
>>> message.headers['X-No-Encoding-Header']
u'Text \ufffd or not'
+Other popular headers like From, Date and Subject can be accessed by using the
+dictionary API, too. They are also decoded into unicode automatically:
+
+>>> message.headers['From']
+u'test(at)localhost'
+>>> message.headers['Date']
+u'02-Jul-2008 03:05:00 +0200'
+>>> message.headers['Subject']
+u'Mail 1'
+
+
Raw
===
(at)(at) -61,11 +73,54 (at)(at)
>>> message.raw
'From: test(at)localhost\r\nX-IMAPAPI-Test: 1\r\nX-No-Encoding-Header: Text
\xfc or not\r\nX-Wrong-Encoding-Header:
=?ascii?q?Text_=C3=BC?=\r\nX-Unknown-Encoding-Header:
=?foobarschnappeldiwutz?q?Text_=C3=BC?=\r\nX-Correct-Encoding-Header:
=?utf-8?q?Text_=C3=BC?=\r\nDate: 02-Jul-2008 03:05:00 +0200\r\nSubject: Mail
1\r\n\r\nEverything is ok!'
+
+Message body
+============
+
Plain text
-===========
+----------
The message body itself can also be retrieved in a plain text version (which
might include encoded mime parts):
>>> print message.text
Everything is ok!
+
+Multipart/alternative
+---------------------
+
+Messages with the type ``multipart-alternative`` contain of several parts,
+which contain the same content in differnt types (e.g. plain text and html).
+The mailer has to choose the proper part and display it.
+
+>>> message = INBOX.messages.values()[1]
+>>> message.body
+<gocept.imapapi.message.BodyPart object at 0x2428811>
+
+This testmessage contains of two parts. One contains plain text, the other one
+html quoted text:
+
+>>> from pprint import pprint
+>>> parts = message.body.parts
+>>> pprint(parts)
+[<gocept.imapapi.message.BodyPart object at 0x2428819>,
+ <gocept.imapapi.message.BodyPart object at 0x2428212>]
+>>> print parts[0]['content_type']
+text/plain
+>>> print parts[1]['content_type']
+text/html
+
+The parts content can be retrieved with the ``fetch`` method:
+
+>>> print parts[0].fetch()
+Everything is ok!
+
+>>> print parts[1].fetch()
+<html>
+ <head>
+ <title>Mail 2</title>
+ </head>
+ <body>
+ Everything is ok!
+ </body>
+</html>
Added:
gocept.imapapi/trunk/gocept/imapapi/testmessages/01-multipart-alternative
==============================================================================
--- (empty file)
+++
gocept.imapapi/trunk/gocept/imapapi/testmessages/01-multipart-alternative Thu
Nov 6 11:03:56 2008
(at)(at) -0,0 +1,24 (at)(at)
+To: Thomas Lotze <tl(at)gocept.com>
+Message-Id: <18EE7CC0-44FB-4802-BA8E-58F7BE1F7274(at)gocept.com>
+Content-Type: multipart/alternative; boundary=gocept-0123456789
+Subject: Mail 2
+Date: Thu, 25 Sep 2008 13:50:58 +0200
+
+--gocept-0123456789
+Content-Type: text/plain; charset=US-ASCII;
+Content-Transfer-Encoding: 7bit
+
+Everything is ok!
+
+--gocept-0123456789
+Content-Type: text/html; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+
+<html>
+ <head>
+ <title>Mail 2</title>
+ </head>
+ <body>
+ Everything is ok!
+ </body>
+</html>
Modified: gocept.imapapi/trunk/gocept/imapapi/tests.py
==============================================================================
--- gocept.imapapi/trunk/gocept/imapapi/tests.py (original)
+++ gocept.imapapi/trunk/gocept/imapapi/tests.py Thu Nov 6 11:03:56 2008
(at)(at) -7,13 +7,17 (at)(at)
import imaplib
import os
import os.path
+import re
import time
import unittest
from zope.testing import doctest
+import zope.testing.renormalizing
import imaplib
import gocept.imapapi.parser
+checker = zope.testing.renormalizing.RENormalizing([
+ (re.compile('0x[0-9a-f]{7}'), "<MEM ADDRESS>")])
def callIMAP(server, function, *args, **kw):
status, data = getattr(server, function)(*args, **kw)
(at)(at) -95,7 +99,8 (at)(at)
'folder.txt',
'message.txt',
setUp=setUp,
- optionflags=optionflags))
+ optionflags=optionflags,
+ checker=checker))
suite.addTest(doctest.DocTestSuite(
'gocept.imapapi.parser',
optionflags=optionflags))
|
SVN: r7000 - gocept.webmail/trunk/gocept/webmail
Christian Zagrodnick <cz(at)gocept.com> |
2008-11-06 11:06:24 |
[ FULL ]
|
Author: zagy
Date: Thu Nov 6 11:06:22 2008
New Revision: 7000
Log:
tests beschleunigt durch wait_for_text
Modified:
gocept.webmail/trunk/gocept/webmail/README.txt
Modified: gocept.webmail/trunk/gocept/webmail/README.txt
==============================================================================
--- gocept.webmail/trunk/gocept/webmail/README.txt (original)
+++ gocept.webmail/trunk/gocept/webmail/README.txt Thu Nov 6 11:06:22 2008
(at)(at) -23,7 +23,6 (at)(at)
short-cut for logging into that account:
>>> wait_for_text('Return to homepage')
->>> time.sleep(0.5)
>>> browser.getControl(name='login').click()
Accessing the profile
(at)(at) -43,7 +42,7 (at)(at)
The account management UI allows us to create, delete and edit accounts
with identities. The UI can be accessed in a popup window:
->>> time.sleep(2)
+>>> time.sleep(1)
>>> browser.getLink('Manage accounts').click()
>>> time.sleep(3)
>>> follow_window()
(at)(at) -51,7 +50,7 (at)(at)
To add an account, you have to click on the `Add account` button:
>>> browser.getLink('New').click()
->>> time.sleep(2)
+>>> wait_for_text('identitySave')
A form appears, where you can fill in your account details. The port is
predefined with the default imap port:
(at)(at) -70,7 +69,7 (at)(at)
account list:
>>> browser.getControl(name='identitySave').click()
->>> time.sleep(2)
+>>> wait_for_text('>ok</div>')
>>> print_html(browser.contents)
<html>...
<title>Manage accounts</title>...
(at)(at) -134,7 +133,7 (at)(at)
If you click on a folder the list of messages from that folder is displayed:
>>> browser.getLink('INBOX').click()
->>> time.sleep(1)
+>>> wait_for_text('test(at)localhost')
>>> tree = lxml.html.fromstring(browser.contents)
The table has a `From` column and the INBOX contains two messages from
(at)(at) -164,7 +163,7 (at)(at)
====================
>>> click_listing('Mail 1')
->>> time.sleep(1)
+>>> wait_for_text('Everything is ok!')
>>> print_html(browser.contents)
<html>
...
(at)(at) -207,7 +206,7 (at)(at)
The draft is accessible through the draft folder:
>>> browser.getLink('Drafts').click()
->>> time.sleep(2)
+>>> wait_for_text('lazy dog')
>>> print_html(browser.contents)
<html>...
<thead><tr ...>
(at)(at) -224,7 +223,7 (at)(at)
Drafts can be re-edited:
>>> click_listing('The quick brown fox jumped over the lazy dog')
->>> time.sleep(1)
+>>> wait_for_text('blub')
>>> browser.getLink('Edit').click()
>>> time.sleep(2)
>>> follow_window()
(at)(at) -238,7 +237,7 (at)(at)
>>> go_home()
>>> browser.getLink('Drafts').click()
->>> time.sleep(2)
+>>> wait_for_text('mailothertest')
>>> print_html(browser.contents)
<html>...
<tbody ...><tr ...>
(at)(at) -274,7 +273,7 (at)(at)
>>> click_tree('ben(at)example.com')
>>> browser.getLink('INBOX').click()
->>> time.sleep(1)
+>>> wait_for_text('Mail 1')
>>> click_listing('Mail 1')
>>> browser.getLink('Reply').click()
>>> time.sleep(4)
(at)(at) -295,7 +294,7 (at)(at)
... </blockquote>
... """
>>> browser.js.set_editor_value('composeBody', example_text)
->>> time.sleep(4)
+>>> time.sleep(1)
When the cursor is positioned in a quoted area, pressing enter results in the
quoting being split. All HTML elements inside the body which contain the text
(at)(at) -371,6 +370,7 (at)(at)
>>> follow_window()
>>> click_listing('ben(at)example.com')
+>>> wait_for_text('identitySave')
>>> browser.js.get_control_value('accountHost')
'localhost'
>>> browser.js.get_control_value('accountPort')
(at)(at) -390,7 +390,7 (at)(at)
>>> browser.js.set_control_value('identityName', 'Ben Atzer')
>>> browser.getControl(name='identitySave').click()
->>> time.sleep(2)
+>>> wait_for_text('>Ben Atzer')
>>> print_html(browser.contents)
<html>...
<title>Manage accounts</title>...
(at)(at) -407,7 +407,7 (at)(at)
--------------------------------
>>> click_listing('ben(at)example.com')
->>> time.sleep(1)
+>>> wait_for_text('identitySave')
>>> browser.getLink('Delete').click()
This code is b0rked:
(at)(at) -456,7 +456,7 (at)(at)
>>> import sys
>>> def wait_for_text(string):
- ... print >> sys.stderr, string
+ ... print >> sys.stderr, string,
... for i in xrange(100):
... if string in browser.contents:
... break
(at)(at) -465,6 +465,7 (at)(at)
... time.sleep(0.1)
... else:
... print >> sys.stderr, 'Did not find', string
+ ... print >>sys.stderr, ""
Define a helper function to expand/collapse entries in the mail folder
tree:
|
SVN: r7047 - gocept.restmail/trunk/gocept/restmail/browser
Thomas Lotze <tl(at)gocept.com> |
2008-11-18 14:23:02 |
[ FULL ]
|
Author: thomas
Date: Tue Nov 18 14:23:01 2008
New Revision: 7047
Log:
cannot reproduce the decoding error anymore that caused us to mangle HTML
bodies
Modified:
gocept.restmail/trunk/gocept/restmail/browser/draft.py
Modified: gocept.restmail/trunk/gocept/restmail/browser/draft.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/browser/draft.py (original)
+++ gocept.restmail/trunk/gocept/restmail/browser/draft.py Tue Nov 18 14:23:01
2008
(at)(at) -24,7 +24,7 (at)(at)
'date': self.context.date.isoformat(),
'to': self.context.to,
'subject': self.context.subject,
- 'body': self.context.body.replace('%', '%p').replace('<',
'%l')}
+ 'body': self.context.body}
(at)gocept.restmail.browser.json.view
def save(self, account, to, subject, body):
|
SVN: r7048 - gocept.webmail/trunk/gocept/webmail/browser/resources
Thomas Lotze <tl(at)gocept.com> |
2008-11-18 14:23:26 |
[ FULL ]
|
Author: thomas
Date: Tue Nov 18 14:23:25 2008
New Revision: 7048
Log:
cannot reproduce the decoding error anymore that caused us to mangle HTML
bodies
Modified:
gocept.webmail/trunk/gocept/webmail/browser/resources/composer.js
Modified: gocept.webmail/trunk/gocept/webmail/browser/resources/composer.js
==============================================================================
---
gocept.webmail/trunk/gocept/webmail/browser/resources/composer.js (original)
+++ gocept.webmail/trunk/gocept/webmail/browser/resources/composer.js Tue Nov
18 14:23:25 2008
(at)(at) -203,8 +203,6 (at)(at)
};
};
var body = draft['body'];
- body = body.replace('%l', '<', 'g');
- body = body.replace('%p', '%', 'g');
composer.getControl('Body').value = body;
composer.editor.setEditorHTML(body);
});
|
SVN: r7059 - gocept.restmail/trunk/gocept/restmail/browser
Sebastian Wehrmann <sw(at)gocept.com> |
2008-11-22 05:42:24 |
[ FULL ]
|
Author: sweh
Date: Fri Nov 21 15:36:43 2008
New Revision: 7059
Log:
fix tests cause of changes in the json API for use with YUI 2.6.0
add a text/json header to json responses to prevent zope from adding stupid
html tags to html mails
Modified:
gocept.restmail/trunk/gocept/restmail/browser/README.txt
gocept.restmail/trunk/gocept/restmail/browser/draft.py
gocept.restmail/trunk/gocept/restmail/browser/json.py
gocept.restmail/trunk/gocept/restmail/browser/message.py
Modified: gocept.restmail/trunk/gocept/restmail/browser/README.txt
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/browser/README.txt (original)
+++ gocept.restmail/trunk/gocept/restmail/browser/README.txt Fri Nov 21
15:36:43 2008
(at)(at) -98,7 +98,7 (at)(at)
... port=10143,
... user='test',
... password='bsdf'))
-{'url': 'http://localhost/profile/ben-example.com'}
+{'Response': {'url': 'http://localhost/profile/ben-example.com'}}
XXX This needs to go to ``add-account``:
(at)(at) -113,17 +113,17 (at)(at)
>>> import pprint
>>> pprint.pprint(json_request('http://localhost/profile/(at)(at)accounts'))
-[{'address': 'ben(at)example.com',
- 'from': 'Ben Utzer <ben(at)example.com>',
- 'host': 'localhost',
- 'name': 'Ben Utzer',
- 'password': 'bsdf',
- 'port': 10143,
- 'sent_folder': '',
- 'smtp_server': 'default-smtp',
- 'status': 'ok',
- 'url': 'http://localhost/profile/ben-example.com',
- 'user': 'test'}]
+{'Response': [{'address': 'ben(at)example.com',
+ 'from': 'Ben Utzer <ben(at)example.com>',
+ 'host': 'localhost',
+ 'name': 'Ben Utzer',
+ 'password': 'bsdf',
+ 'port': 10143,
+ 'sent_folder': '',
+ 'smtp_server': 'default-smtp',
+ 'status': 'ok',
+ 'url': 'http://localhost/profile/ben-example.com',
+ 'user': 'test'}]}
Account API
(at)(at) -135,19 +135,19 (at)(at)
Accounts contain folders which can be browsed using the ``(at)(at)folders``
view:
>>> pprint.pprint(json_request('http://localhost/profile/ben-example.com/(at)(at)folders'))
-[{'children': 0,
- 'name': 'Bar',
- 'url': 'http://localhost/profile/ben-example.com/+Bar'},
- {'children': 1,
- 'name': 'INBOX',
- 'url': 'http://localhost/profile/ben-example.com/+INBOX'}]
+{'Response': [{'children': 0,
+ 'name': 'Bar',
+ 'url': 'http://localhost/profile/ben-example.com/+Bar'},
+ {'children': 1,
+ 'name': 'INBOX',
+ 'url': 'http://localhost/profile/ben-example.com/+INBOX'}]}
The ``(at)(at)folders`` view can be applied on folders as well:
>>> pprint.pprint(json_request('http://localhost/profile/ben-example.com/+INBOX/(at)(at)folders'))
-[{'children': 0,
- 'name': 'Baz',
- 'url': 'http://localhost/profile/ben-example.com/+INBOX/+Baz'}]
+{'Response': [{'children': 0,
+ 'name': 'Baz',
+ 'url': 'http://localhost/profile/ben-example.com/+INBOX/+Baz'}]}
Create new folders
(at)(at) -157,11 +157,11 (at)(at)
>>> json_request('http://localhost/profile/ben-example.com/(at)(at)create_folder',
... name="Sent")
-{'url': 'http://localhost/profile/ben-example.com/+Sent'}
+{'Response': {'url': 'http://localhost/profile/ben-example.com/+Sent'}}
>>> json_request('http://localhost/profile/ben-example.com/+Sent/(at)(at)create_folder',
... name="Old")
-{'url': 'http://localhost/profile/ben-example.com/+Sent/+Old'}
+{'Response': {'url': 'http://localhost/profile/ben-example.com/+Sent/+Old'}}
(at)(at) -173,14 +173,14 (at)(at)
>>> messages = json_request('http://localhost/profile/ben-example.com/+INBOX/(at)(at)messages')
>>> pprint.pprint(messages)
-[{'date': '02-Jul-2008 03:05:00 +0200',
- 'from': 'test(at)localhost',
- 'subject': 'Mail 1',
- 'url': 'http://localhost/profile/ben-example.com/+INBOX/*...'},
- {'date': '02-Jul-2008 03:06:00 +0200',
- 'from': 'test(at)localhost',
- 'subject': 'Mail 2',
- 'url': 'http://localhost/profile/ben-example.com/+INBOX/*...'}]
+{'Response': [{'date': '02-Jul-2008 03:05:00 +0200',
+ 'from': 'test(at)localhost',
+ 'subject': 'Mail 1',
+ 'url': 'http://localhost/profile/ben-example.com/+INBOX/*...'},
+ {'date': '02-Jul-2008 03:06:00 +0200',
+ 'from': 'test(at)localhost',
+ 'subject': 'Mail 2',
+ 'url': 'http://localhost/profile/ben-example.com/+INBOX/*...'}]}
Please note that only `url` is promised to have a reasonable value.
Messages might not provide the date, subject or from header in which
(at)(at) -204,17 +204,17 (at)(at)
... user='test',
... password='bsdf'))
>>> pprint.pprint(json_request('http://localhost/profile/(at)(at)accounts'))
-[{'address': 'ben(at)example.com',
- 'from': 'Ben Utzer <ben(at)example.com>',
- 'host': 'localhost',
- 'name': 'Ben Utzer',
- 'password': 'bsdf',
- 'port': 10143,
- 'sent_folder': '+Sent',
- 'smtp_server': 'default-smtp',
- 'status': 'ok',
- 'url': 'http://localhost/profile/ben-example.com',
- 'user': 'test'}]
+{'Response': [{'address': 'ben(at)example.com',
+ 'from': 'Ben Utzer <ben(at)example.com>',
+ 'host': 'localhost',
+ 'name': 'Ben Utzer',
+ 'password': 'bsdf',
+ 'port': 10143,
+ 'sent_folder': '+Sent',
+ 'smtp_server': 'default-smtp',
+ 'status': 'ok',
+ 'url': 'http://localhost/profile/ben-example.com',
+ 'user': 'test'}]}
Delete an account: (at)(at)delete
---------------------------
(at)(at) -232,8 +232,9 (at)(at)
... port=10143,
... user='test',
... password='bsdf'))
-{'url': 'http://localhost/profile/john.doe-example.com'}
->>> accounts = json_request('http://localhost/profile/(at)(at)accounts')
+{'Response': {'url': 'http://localhost/profile/john.doe-example.com'}}
+>>> response = json_request('http://localhost/profile/(at)(at)accounts')
+>>> accounts = response['Response']
>>> [x['url'] for x in accounts]
['http://localhost/profile/ben-example.com',
'http://localhost/profile/john.doe-example.com']
(at)(at) -241,7 +242,8 (at)(at)
>>> json_request('http://localhost/profile/john.doe-example.com/(at)(at)delete',
post=True)
->>> accounts = json_request('http://localhost/profile/(at)(at)accounts')
+>>> response = json_request('http://localhost/profile/(at)(at)accounts')
+>>> accounts = response['Response']
>>> [x['url'] for x in accounts]
['http://localhost/profile/ben-example.com']
(at)(at) -256,7 +258,7 (at)(at)
lists all headers of the message as well as its hierarchical
structure:
->>> message = json_request(messages[0]['url']+'/(at)(at)metadata')
+>>> message =
json_request(messages['Response'][0]['url']+'/(at)(at)metadata')
>>> pprint.pprint(message)
{'headers': {'Date': '02-Jul-2008 03:05:00 +0200',
'From': 'test(at)localhost',
(at)(at) -314,21 +316,21 (at)(at)
After a message was created, its data is empty:
>>> pprint.pprint(json_request(draft['url']+'/(at)(at)data'))
-{'account': '',
- 'body': '',
- 'date': '<ISO DATE>',
- 'subject': '',
- 'to': ''}
+{'Response': {'account': '',
+ 'body': '',
+ 'date': '<ISO DATE>',
+ 'subject': '',
+ 'to': ''}}
Getting a list of existing draft messages
-----------------------------------------
>>> pprint.pprint(json_request('http://localhost/profile/(at)(at)drafts'))
-[{'date': '<ISO DATE>',
- 'subject': '',
- 'to': '',
- 'url': 'http://localhost/profile/drafts/<GUID>'}]
+{'Response': [{'date': '<ISO DATE>',
+ 'subject': '',
+ 'to': '',
+ 'url': 'http://localhost/profile/drafts/<GUID>'}]}
Updating draft messages
(at)(at) -342,11 +344,11 (at)(at)
... subject=u'asdf\xe4',
... body='HelloHello')
>>> pprint.pprint(json_request(draft['url']+'/(at)(at)data'))
-{'account': 'http://localhost/profile/ben-example.com',
- 'body': 'HelloHello',
- 'date': '<ISO DATE>',
- 'subject': u'asdf\xe4',
- 'to': 'ct(at)gocept.com'}
+{'Response': {'account': 'http://localhost/profile/ben-example.com',
+ 'body': 'HelloHello',
+ 'date': '<ISO DATE>',
+ 'subject': u'asdf\xe4',
+ 'to': 'ct(at)gocept.com'}}
>>> json_request(draft['url']+'/(at)(at)save',
... to='ct(at)gocept.com',
(at)(at) -354,11 +356,11 (at)(at)
... subject=u'asdf',
... body='HelloHello')
>>> pprint.pprint(json_request(draft['url']+'/(at)(at)data'))
-{'account': 'http://localhost/profile/ben-example.com',
- 'body': 'HelloHello',
- 'date': '<ISO DATE>',
- 'subject': 'asdf',
- 'to': 'ct(at)gocept.com'}
+{'Response': {'account': 'http://localhost/profile/ben-example.com',
+ 'body': 'HelloHello',
+ 'date': '<ISO DATE>',
+ 'subject': 'asdf',
+ 'to': 'ct(at)gocept.com'}}
Sending draft messages
(at)(at) -385,10 +387,10 (at)(at)
HTTPError: HTTP Error 404: Not Found
>>> pprint.pprint(json_request('http://localhost/profile/ben-example.com/+Sent/(at)(at)messages'))
-[{'date': None,
- 'from': 'Ben Utzer <ben(at)example.com>',
- 'subject': 'asdf',
- 'url': 'http://localhost/profile/ben-example.com/+Sent/*...'}]
+{'Response': [{'date': None,
+ 'from': 'Ben Utzer <ben(at)example.com>',
+ 'subject': 'asdf',
+ 'url': 'http://localhost/profile/ben-example.com/+Sent/*...'}]}
Replying to messages
(at)(at) -398,17 +400,17 (at)(at)
data pre-filled such as the quoted message body, the subject line and the
recipient:
->>> reply = json_request(messages[0]['url']+'/(at)(at)reply',
post=True)
+>>> reply =
json_request(messages['Response'][0]['url']+'/(at)(at)reply', post=True)
>>> pprint.pprint(reply)
-{'url': 'http://localhost/profile/drafts/<GUID>'}
->>> pprint.pprint(json_request(reply['url']+'/(at)(at)data'))
-{'account': 'http://localhost/profile/ben-example.com',
- 'body':
'%lhtml>\n%lhead>%l/head>\n%lbody>\n%lblockquote>%lpre>Everything
is ok!\n%l/pre>%l/blockquote>\n%l/body>\n%l/html>\n',
- 'date': '<ISO DATE>',
- 'subject': 'Re: Mail 1',
- 'to': 'test(at)localhost'}
+{'Response': {'url': 'http://localhost/profile/drafts/<GUID>'}}
+>>>
pprint.pprint(json_request(reply['Response']['url']+'/(at)(at)data'))
+{'Response': {'account': 'http://localhost/profile/ben-example.com',
+ 'body':
'<html>\n<head></head>\n<body>\n<blockquote><pre>Everything
is ok!\n</pre></blockquote>\n</body>\n</html>\n',
+ 'date': '<ISO DATE>',
+ 'subject': 'Re: Mail 1',
+ 'to': 'test(at)localhost'}}
->>> json_request(reply['url']+'/(at)(at)send', post=True)
+>>> json_request(reply['Response']['url']+'/(at)(at)send', post=True)
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Modified: gocept.restmail/trunk/gocept/restmail/browser/draft.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/browser/draft.py (original)
+++ gocept.restmail/trunk/gocept/restmail/browser/draft.py Fri Nov 21 15:36:43
2008
(at)(at) -24,7 +24,7 (at)(at)
'date': self.context.date.isoformat(),
'to': self.context.to,
'subject': self.context.subject,
- 'body': self.context.body.strip()}
+ 'body': self.context.body}
(at)gocept.restmail.browser.json.view
def save(self, account, to, subject, body):
Modified: gocept.restmail/trunk/gocept/restmail/browser/json.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/browser/json.py (original)
+++ gocept.restmail/trunk/gocept/restmail/browser/json.py Fri Nov 21 15:36:43
2008
(at)(at) -17,9 +17,11 (at)(at)
"""
def decorated(self):
body = self.request.get('BODY', NULL_BODY)
+ self.request.RESPONSE.setHeader('Content-Type', 'text/json')
args = cjson.decode(body.decode('utf-8'))
result = func(self, **args)
- result = {'Response': result}
+ if result:
+ result = {'Response': result}
return cjson.encode(result)
decorated.__name__ = func.__name__
return decorated
Modified: gocept.restmail/trunk/gocept/restmail/browser/message.py
==============================================================================
--- gocept.restmail/trunk/gocept/restmail/browser/message.py (original)
+++ gocept.restmail/trunk/gocept/restmail/browser/message.py Fri Nov 21
15:36:43 2008
(at)(at) -58,11 +58,12 (at)(at)
return data
+ (at)gocept.restmail.browser.json.view
def reply(self):
"""Create a new draft message."""
profile = gocept.restmail.interfaces.IProfile(self.context)
draft = profile.new_draft(self.context)
- return cjson.encode({'url': zope.app.zapi.absoluteURL(draft,
self.request)})
+ return {'url': zope.app.zapi.absoluteURL(draft, self.request)}
class BodyPartWebAPI(object):
|
|