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)
|
||||
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
|
||||
opening a new browser window for editing; but only if the view is
|
||||
editable:
|
||||
|
|
|
@ -169,7 +169,6 @@ class BaseView(object):
|
|||
@Lazy
|
||||
def uniqueId(self):
|
||||
return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
|
||||
#return zapi.getUtility(IIntIds).getId(self.context)
|
||||
|
||||
@Lazy
|
||||
def editable(self):
|
||||
|
@ -182,7 +181,8 @@ class BaseView(object):
|
|||
|
||||
@Lazy
|
||||
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):
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
<metal:fields use-macro="item/template/macros/conceptchildren" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="subcolumn"
|
||||
style="position: relative; top: 60px">
|
||||
<div class="subcolumn" style="margin-top: 60px">
|
||||
<metal:fields use-macro="item/template/macros/conceptresources" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<tal:show i18n:domain="loops">
|
||||
<tal:show i18n:domain="zope">
|
||||
<html metal:use-macro="context/@@skin_macros/page">
|
||||
<head></head>
|
||||
<body>
|
||||
|
@ -13,6 +13,14 @@
|
|||
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" />
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ from zope.app.container.browser.contents import JustContents
|
|||
from zope.app.container.browser.adding import ContentAdding
|
||||
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||
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.event import notify
|
||||
from zope.formlib.namedtemplate import NamedTemplate
|
||||
|
@ -51,15 +51,13 @@ from loops.browser.concept import ConceptView
|
|||
|
||||
class NodeView(BaseView):
|
||||
|
||||
_itemNum = 0
|
||||
|
||||
template = NamedTemplate('loops.node_macros')
|
||||
|
||||
@Lazy
|
||||
def macro(self):
|
||||
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
|
||||
def view(self):
|
||||
|
@ -95,6 +93,11 @@ class NodeView(BaseView):
|
|||
return [NodeView(child, self.request)
|
||||
for child in self.context.getPageItems()]
|
||||
|
||||
@property
|
||||
def itemNum(self):
|
||||
self._itemNum += 1
|
||||
return self._itemNum
|
||||
|
||||
@Lazy
|
||||
def nodeType(self):
|
||||
return self.context.nodeType
|
||||
|
@ -139,13 +142,13 @@ class NodeView(BaseView):
|
|||
|
||||
@Lazy
|
||||
def bodyMacro(self):
|
||||
# ?TODO: replace by: return self.target.macroName
|
||||
# TODO: replace by: return self.target.macroName
|
||||
target = self.targetObject
|
||||
if target is None or IDocument.providedBy(target):
|
||||
return 'textbody'
|
||||
if IConcept.providedBy(target):
|
||||
return 'conceptbody'
|
||||
if IMediaAsset.providedBy(target) and target.contentType.startswith('image/'):
|
||||
if IResource.providedBy(target) and target.contentType.startswith('image/'):
|
||||
return 'imagebody'
|
||||
return 'filebody'
|
||||
|
||||
|
@ -223,12 +226,39 @@ class NodeView(BaseView):
|
|||
return targetView()
|
||||
return u''
|
||||
|
||||
def targetId(self):
|
||||
@Lazy
|
||||
def virtualTarget(self):
|
||||
target = self.request.annotations.get('loops.view', {}).get('target')
|
||||
if target is None:
|
||||
target = self.targetObject
|
||||
return target
|
||||
|
||||
@Lazy
|
||||
def targetId(self):
|
||||
target = self.virtualTarget
|
||||
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):
|
||||
|
|
|
@ -5,28 +5,45 @@
|
|||
<metal:body use-macro="views/node_macros/?bodyMacro" />
|
||||
<tal:sub define="level python:level+1">
|
||||
<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:sub>
|
||||
</metal:block>
|
||||
|
||||
|
||||
<!-- dojoType="Editor"
|
||||
items="formatblock;|;insertunorderedlist;insertorderedlist;|;bold;italic;|;createLink;"
|
||||
-->
|
||||
|
||||
<metal:body define-macro="textbody">
|
||||
<tal:body define="body item/body">
|
||||
<div class="content-1"
|
||||
<tal:body define="body item/body;
|
||||
id string:${view/itemNum}.body">
|
||||
<div class="content-1" id="1.body"
|
||||
tal:condition="body"
|
||||
tal:attributes="class string:content-$level;
|
||||
id string:${view/itemNum}.body;
|
||||
ondblclick item/openEditWindow"
|
||||
tal:content="structure body">
|
||||
The body
|
||||
</div>
|
||||
<div class="content-1"
|
||||
tal:define="target item/target"
|
||||
tal:condition="target"
|
||||
tal:attributes="class string:content-$level;
|
||||
ondblclick python: item.openEditWindow('configure.html')"
|
||||
tal:content="structure item/renderTarget">
|
||||
The body
|
||||
<div>
|
||||
<div class="subcolumn"
|
||||
tal:condition="item/xeditable | nothing">
|
||||
<a href="#" title="Edit" style="padding: 5px"
|
||||
tal:attributes="href string:${item/realTargetUrl}/external_edit;
|
||||
title string:Edit ${item/title}"><img
|
||||
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>
|
||||
</tal:body>
|
||||
</metal:body>
|
||||
|
@ -34,8 +51,9 @@
|
|||
|
||||
<metal:body define-macro="conceptbody">
|
||||
<tal:body define="body item/body;">
|
||||
<div class="content-1"
|
||||
<div class="content-1" id="1"
|
||||
tal:attributes="class string:content-$level;
|
||||
id string:${view/itemNum}.body;
|
||||
ondblclick python: item.openEditWindow('configure.html')">
|
||||
<span tal:content="structure body">Node Body</span>
|
||||
</div>
|
||||
|
@ -50,8 +68,9 @@
|
|||
|
||||
<metal:body define-macro="filebody">
|
||||
<tal:body define="body item/body">
|
||||
<div class="content-1"
|
||||
<div class="content-1" id="1"
|
||||
tal:attributes="class string:content-$level;
|
||||
id string:${view/itemNum}.body;
|
||||
ondblclick python: item.openEditWindow('edit_target.html')">
|
||||
<a href="#"
|
||||
tal:attributes="href string:${item/url}/.target/view"
|
||||
|
@ -65,6 +84,7 @@
|
|||
<tal:body define="body item/body">
|
||||
<div class="content-1" style="margin-top: 12px"
|
||||
tal:attributes="class string:content-$level;
|
||||
id string:${view/itemNum}.body;
|
||||
ondblclick python: item.openEditWindow('edit_target.html')">
|
||||
<img src="target"
|
||||
tal:attributes="src string:${item/url}/.target/view" />
|
||||
|
@ -84,11 +104,12 @@
|
|||
|
||||
<metal:body define-macro="listpages">
|
||||
<div class="content-1"
|
||||
tal:content="structure view/body"
|
||||
tal:attributes="ondblclick view/openEditWindow">
|
||||
tal:content="structure item/body"
|
||||
tal:attributes="ondblclick view/openEditWindow;
|
||||
id string:${view/itemNum}.body;">
|
||||
Listing
|
||||
</div><br />
|
||||
<div tal:repeat="item view/pageItems">
|
||||
<div tal:repeat="item item/pageItems">
|
||||
<a href="#"
|
||||
tal:attributes="href item/url"
|
||||
tal:content="item/title">Item</a>
|
||||
|
@ -97,13 +118,18 @@
|
|||
|
||||
|
||||
<metal:resources define-macro="listresources"
|
||||
tal:define="item view/target">
|
||||
tal:define="target item/target">
|
||||
<div class="content-1"
|
||||
tal:content="structure view/body"
|
||||
tal:attributes="ondblclick python: item.openEditWindow('resources.html')">
|
||||
tal:content="structure item/body"
|
||||
tal:attributes="ondblclick python:
|
||||
target and target.openEditWindow('resources.html')
|
||||
or item.openEditWindow();
|
||||
id string:${view/itemNum}.body;">
|
||||
Listing
|
||||
</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">
|
||||
<a href="#"
|
||||
tal:attributes="href string:${view/url}/.target${related/uniqueId}"
|
||||
|
|
|
@ -78,6 +78,8 @@ class Resource(Image, Contained):
|
|||
# TODO (?): check for multiple types (->Error)
|
||||
return concepts and concepts[0] or cm.get('file', None)
|
||||
def setResourceType(self, concept):
|
||||
if concept is None:
|
||||
return
|
||||
current = self.getResourceType()
|
||||
if current != concept:
|
||||
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
|
||||
accessed exactly once per row:
|
||||
|
||||
>>> searchView.itemNum
|
||||
1
|
||||
>>> searchView.rowNum
|
||||
1
|
||||
>>> searchView.rowNum
|
||||
|
|
|
@ -48,16 +48,10 @@ class Search(BaseView):
|
|||
def macro(self):
|
||||
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
|
||||
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)
|
||||
if n: # if given directly we don't use the calculation
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</h3>
|
||||
|
||||
<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">
|
||||
<fieldset class="box">
|
||||
<form action="." method="post" id="1.search.form"
|
||||
|
|
Loading…
Add table
Reference in a new issue