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): | ||||
|  |  | |||
|  | @ -11,31 +11,49 @@ | |||
| </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" | ||||
|           <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> | ||||
| 
 | ||||
| 
 | ||||
| <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
	
	 helmutm
						helmutm