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:
parent
e05caedc38
commit
4c48396c13
10 changed files with 109 additions and 44 deletions
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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}"
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue