work in progress: wysiwyg editing with dojo - preparing node macros

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1297 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-08-12 22:11:47 +00:00
parent e05caedc38
commit 4c48396c13
10 changed files with 109 additions and 44 deletions

View file

@ -465,6 +465,14 @@ Node Views
... print item.url, view.selected(item) ... print item.url, view.selected(item)
http://127.0.0.1/loops/views/m1/m11 True http://127.0.0.1/loops/views/m1/m11 True
A NodeView provides an itemNum attribute that may be used to count elements
appearing on a page. Thus a template may construct unique ids for elements.
>>> view.itemNum
1
>>> view.itemNum
2
There is an openEditWindow() method that returns a JavaScript call for There is an openEditWindow() method that returns a JavaScript call for
opening a new browser window for editing; but only if the view is opening a new browser window for editing; but only if the view is
editable: editable:

View file

@ -169,7 +169,6 @@ class BaseView(object):
@Lazy @Lazy
def uniqueId(self): def uniqueId(self):
return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context) return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
#return zapi.getUtility(IIntIds).getId(self.context)
@Lazy @Lazy
def editable(self): def editable(self):
@ -182,7 +181,8 @@ class BaseView(object):
@Lazy @Lazy
def xeditable(self): def xeditable(self):
return getattr(self.context, 'contentType', '').startswith('text/') return self.request.principal.id == 'rootadmin'
#return getattr(self.context, 'contentType', '').startswith('text/')
class LoopsTerms(object): class LoopsTerms(object):

View file

@ -13,8 +13,7 @@
<metal:fields use-macro="item/template/macros/conceptchildren" /> <metal:fields use-macro="item/template/macros/conceptchildren" />
</div> </div>
</div> </div>
<div class="subcolumn" <div class="subcolumn" style="margin-top: 60px">
style="position: relative; top: 60px">
<metal:fields use-macro="item/template/macros/conceptresources" /> <metal:fields use-macro="item/template/macros/conceptresources" />
</div> </div>
</div> </div>

View file

@ -1,4 +1,4 @@
<tal:show i18n:domain="loops"> <tal:show i18n:domain="zope">
<html metal:use-macro="context/@@skin_macros/page"> <html metal:use-macro="context/@@skin_macros/page">
<head></head> <head></head>
<body> <body>
@ -13,6 +13,14 @@
controller.macros.register('js', resourceName='ajax.dojo/dojo.js');" /> controller.macros.register('js', resourceName='ajax.dojo/dojo.js');" />
<metal:block fill-slot="ecmascript_slot"
tal:condition="nothing">
<script>
dojo.require("dojo.widget.Editor");
</script>
</metal:block>
<metal:block fill-slot="actions" /> <metal:block fill-slot="actions" />

View file

@ -31,7 +31,7 @@ from zope.app.container.browser.contents import JustContents
from zope.app.container.browser.adding import ContentAdding from zope.app.container.browser.adding import ContentAdding
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.app.intid.interfaces import IIntIds #from zope.app.intid.interfaces import IIntIds
from zope.dottedname.resolve import resolve from zope.dottedname.resolve import resolve
from zope.event import notify from zope.event import notify
from zope.formlib.namedtemplate import NamedTemplate from zope.formlib.namedtemplate import NamedTemplate
@ -51,15 +51,13 @@ from loops.browser.concept import ConceptView
class NodeView(BaseView): class NodeView(BaseView):
_itemNum = 0
template = NamedTemplate('loops.node_macros') template = NamedTemplate('loops.node_macros')
@Lazy @Lazy
def macro(self): def macro(self):
return self.template.macros['content'] return self.template.macros['content']
#macroName = self.request.get('loops.viewName')
#if not macroName:
# macroName = self.context.viewName or 'content'
#return self.template.macros[macroName]
@Lazy @Lazy
def view(self): def view(self):
@ -95,6 +93,11 @@ class NodeView(BaseView):
return [NodeView(child, self.request) return [NodeView(child, self.request)
for child in self.context.getPageItems()] for child in self.context.getPageItems()]
@property
def itemNum(self):
self._itemNum += 1
return self._itemNum
@Lazy @Lazy
def nodeType(self): def nodeType(self):
return self.context.nodeType return self.context.nodeType
@ -139,13 +142,13 @@ class NodeView(BaseView):
@Lazy @Lazy
def bodyMacro(self): def bodyMacro(self):
# ?TODO: replace by: return self.target.macroName # TODO: replace by: return self.target.macroName
target = self.targetObject target = self.targetObject
if target is None or IDocument.providedBy(target): if target is None or IDocument.providedBy(target):
return 'textbody' return 'textbody'
if IConcept.providedBy(target): if IConcept.providedBy(target):
return 'conceptbody' return 'conceptbody'
if IMediaAsset.providedBy(target) and target.contentType.startswith('image/'): if IResource.providedBy(target) and target.contentType.startswith('image/'):
return 'imagebody' return 'imagebody'
return 'filebody' return 'filebody'
@ -223,12 +226,39 @@ class NodeView(BaseView):
return targetView() return targetView()
return u'' return u''
def targetId(self): @Lazy
def virtualTarget(self):
target = self.request.annotations.get('loops.view', {}).get('target') target = self.request.annotations.get('loops.view', {}).get('target')
if target is None: if target is None:
target = self.targetObject target = self.targetObject
return target
@Lazy
def targetId(self):
target = self.virtualTarget
if target is not None: if target is not None:
return zapi.getUtility(IIntIds).getId(target) return BaseView(target, self.request).uniqueId
#return target.uniqueId
#return zapi.getUtility(IIntIds).getId(target)
@Lazy
def virtualTargetUrl(self):
targetId = self.targetId
if targetId is not None:
return '%s/.target%s' % (self.url, targetId)
@Lazy
def realTargetUrl(self):
target = self.virtualTarget
if target is not None:
return BaseView(target, self.request).url
@Lazy
def richEditable(self):
target = self.virtualTarget
if target is None:
return False
return canWrite(target, 'title')
class ListPages(NodeView): class ListPages(NodeView):

View file

@ -5,28 +5,45 @@
<metal:body use-macro="views/node_macros/?bodyMacro" /> <metal:body use-macro="views/node_macros/?bodyMacro" />
<tal:sub define="level python:level+1"> <tal:sub define="level python:level+1">
<tal:items repeat="item item/textItems"> <tal:items repeat="item item/textItems">
<metal:content use-macro="views/node_macros/content" /> <metal:content use-macro="views/node_macros/content" />
</tal:items> </tal:items>
</tal:sub> </tal:sub>
</metal:block> </metal:block>
<!-- dojoType="Editor"
items="formatblock;|;insertunorderedlist;insertorderedlist;|;bold;italic;|;createLink;"
-->
<metal:body define-macro="textbody"> <metal:body define-macro="textbody">
<tal:body define="body item/body"> <tal:body define="body item/body;
<div class="content-1" id string:${view/itemNum}.body">
<div class="content-1" id="1.body"
tal:condition="body" tal:condition="body"
tal:attributes="class string:content-$level; tal:attributes="class string:content-$level;
id string:${view/itemNum}.body;
ondblclick item/openEditWindow" ondblclick item/openEditWindow"
tal:content="structure body"> tal:content="structure body">
The body The body
</div> </div>
<div class="content-1" <div>
tal:define="target item/target" <div class="subcolumn"
tal:condition="target" tal:condition="item/xeditable | nothing">
tal:attributes="class string:content-$level; <a href="#" title="Edit" style="padding: 5px"
ondblclick python: item.openEditWindow('configure.html')" tal:attributes="href string:${item/realTargetUrl}/external_edit;
tal:content="structure item/renderTarget"> title string:Edit ${item/title}"><img
The body src="edit.gif" alt="Edit"
tal:attributes="src context/++resource++edit.gif" /></a>
</div>
<div class="content-1 subcolumn" id="1.body"
tal:define="target item/target"
tal:condition="target"
tal:attributes="class string:content-$level;
id id;
ondblclick python: item.openEditWindow('configure.html')"
tal:content="structure item/renderTarget">
The body
</div>
</div> </div>
</tal:body> </tal:body>
</metal:body> </metal:body>
@ -34,8 +51,9 @@
<metal:body define-macro="conceptbody"> <metal:body define-macro="conceptbody">
<tal:body define="body item/body;"> <tal:body define="body item/body;">
<div class="content-1" <div class="content-1" id="1"
tal:attributes="class string:content-$level; tal:attributes="class string:content-$level;
id string:${view/itemNum}.body;
ondblclick python: item.openEditWindow('configure.html')"> ondblclick python: item.openEditWindow('configure.html')">
<span tal:content="structure body">Node Body</span> <span tal:content="structure body">Node Body</span>
</div> </div>
@ -50,8 +68,9 @@
<metal:body define-macro="filebody"> <metal:body define-macro="filebody">
<tal:body define="body item/body"> <tal:body define="body item/body">
<div class="content-1" <div class="content-1" id="1"
tal:attributes="class string:content-$level; tal:attributes="class string:content-$level;
id string:${view/itemNum}.body;
ondblclick python: item.openEditWindow('edit_target.html')"> ondblclick python: item.openEditWindow('edit_target.html')">
<a href="#" <a href="#"
tal:attributes="href string:${item/url}/.target/view" tal:attributes="href string:${item/url}/.target/view"
@ -65,6 +84,7 @@
<tal:body define="body item/body"> <tal:body define="body item/body">
<div class="content-1" style="margin-top: 12px" <div class="content-1" style="margin-top: 12px"
tal:attributes="class string:content-$level; tal:attributes="class string:content-$level;
id string:${view/itemNum}.body;
ondblclick python: item.openEditWindow('edit_target.html')"> ondblclick python: item.openEditWindow('edit_target.html')">
<img src="target" <img src="target"
tal:attributes="src string:${item/url}/.target/view" /> tal:attributes="src string:${item/url}/.target/view" />
@ -84,11 +104,12 @@
<metal:body define-macro="listpages"> <metal:body define-macro="listpages">
<div class="content-1" <div class="content-1"
tal:content="structure view/body" tal:content="structure item/body"
tal:attributes="ondblclick view/openEditWindow"> tal:attributes="ondblclick view/openEditWindow;
id string:${view/itemNum}.body;">
Listing Listing
</div><br /> </div><br />
<div tal:repeat="item view/pageItems"> <div tal:repeat="item item/pageItems">
<a href="#" <a href="#"
tal:attributes="href item/url" tal:attributes="href item/url"
tal:content="item/title">Item</a> tal:content="item/title">Item</a>
@ -97,13 +118,18 @@
<metal:resources define-macro="listresources" <metal:resources define-macro="listresources"
tal:define="item view/target"> tal:define="target item/target">
<div class="content-1" <div class="content-1"
tal:content="structure view/body" tal:content="structure item/body"
tal:attributes="ondblclick python: item.openEditWindow('resources.html')"> tal:attributes="ondblclick python:
target and target.openEditWindow('resources.html')
or item.openEditWindow();
id string:${view/itemNum}.body;">
Listing Listing
</div><br /> </div><br />
<div tal:attributes="ondblclick python: item.openEditWindow('resources.html')"> <div tal:attributes="ondblclick python: target.openEditWindow('resources.html')"
tal:define="item item/target"
tal:condition="nocall:target">
<div tal:repeat="related item/resources"> <div tal:repeat="related item/resources">
<a href="#" <a href="#"
tal:attributes="href string:${view/url}/.target${related/uniqueId}" tal:attributes="href string:${view/url}/.target${related/uniqueId}"

View file

@ -78,6 +78,8 @@ class Resource(Image, Contained):
# TODO (?): check for multiple types (->Error) # TODO (?): check for multiple types (->Error)
return concepts and concepts[0] or cm.get('file', None) return concepts and concepts[0] or cm.get('file', None)
def setResourceType(self, concept): def setResourceType(self, concept):
if concept is None:
return
current = self.getResourceType() current = self.getResourceType()
if current != concept: if current != concept:
typePred = self.getLoopsRoot().getConceptManager().getTypePredicate() typePred = self.getLoopsRoot().getConceptManager().getTypePredicate()

View file

@ -59,8 +59,6 @@ The search view provides values for identifying the search form itself
and the parameter rows; the rowNum is auto-incremented, so it should be and the parameter rows; the rowNum is auto-incremented, so it should be
accessed exactly once per row: accessed exactly once per row:
>>> searchView.itemNum
1
>>> searchView.rowNum >>> searchView.rowNum
1 1
>>> searchView.rowNum >>> searchView.rowNum

View file

@ -48,16 +48,10 @@ class Search(BaseView):
def macro(self): def macro(self):
return self.template.macros['search'] return self.template.macros['search']
@Lazy
def itemNum(self):
""" Return a number identifying the item (the current search form)
on the page.
"""
return self.request.get('loops.itemNum', 1)
@property @property
def rowNum(self): def rowNum(self):
""" Return the rowNum to be used for identifying the current row. """ Return the rowNum to be used for identifying the current search
parameter row.
""" """
n = self.request.get('loops.rowNum', 0) n = self.request.get('loops.rowNum', 0)
if n: # if given directly we don't use the calculation if n: # if given directly we don't use the calculation

View file

@ -7,7 +7,7 @@
</h3> </h3>
<div metal:define-macro="search_form" class="searchForm" <div metal:define-macro="search_form" class="searchForm"
tal:define="idPrefix string:${item/itemNum}.search; tal:define="idPrefix string:${view/itemNum}.search;
formId string:$idPrefix.form"> formId string:$idPrefix.form">
<fieldset class="box"> <fieldset class="box">
<form action="." method="post" id="1.search.form" <form action="." method="post" id="1.search.form"