Changeset 505


Ignore:
Timestamp:
07/25/06 19:07:00 (13 years ago)
Author:
vahur
Message:

replacing wymeditor with kupu. fixed some tests.
ref #529 spent 8h
created chapter edit widget.

Location:
trunk
Files:
2 added
6 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/FieldsWidgets.py

    r502 r505  
    2525from string import letters, punctuation 
    2626from Products.CMFCore.utils import getToolByName 
     27from ZODB.PersistentMapping import PersistentMapping 
     28from Products.Archetypes.utils import shasattr 
     29from Acquisition import aq_base 
    2730 
    2831from types import ListType, TupleType, StringType, UnicodeType 
     
    3437    _properties.update({ 
    3538        'macro' : 'wysiwym', 
    36         'helper_js' : ('js_helpers.js', 'wym_browser.js', 'wym_config.js', 'wym_util.js', 'wym_wym.js'), 
    37         'helper_css' : ('wym_css.css',), 
     39        'helper_js' : ('js_helpers.js',), 
     40        'helper_css' : (), 
    3841        'cols' : 40, 
    3942        'rows' : 10, 
     
    4649    description='WYSIWYM Widget', 
    4750    used_for=('Products.LeMill.FieldsWidgets.WYSIWYMField',) 
     51) 
     52 
     53class ChapterWidget(TextAreaWidget): 
     54    _properties = TextAreaWidget._properties.copy() 
     55    _properties.update({ 
     56        'macro' : 'widget_chapter', 
     57        'helper_js' : ('js_helpers.js',), 
     58        'helper_css' : (), 
     59        'cols' : 40, 
     60        'rows' : 10, 
     61        'WYSIWYMLines' : False, 
     62        'no_label' : True, 
     63    }) 
     64 
     65registerWidget(ChapterWidget, 
     66    title='Chapter Widget', 
     67    description='Chapter Widget', 
     68    used_for=('Products.LeMill.FieldsWidgets.ChapterField',) 
    4869) 
    4970 
     
    391412    _properties.update({ 
    392413        'widget' : WYSIWYMWidget, 
    393         'edit_accessor' :  "getRaw" 
     414        'edit_accessor' :  "getRaw", 
     415        'default_output_type' : 'text/x-html-captioned', 
     416        'default_content_type' : 'text/html', 
    394417    })     
    395418     
     
    437460            return data 
    438461 
    439  
    440  
    441462registerField(WYSIWYMLinesField, 
    442463               title='WYSIWYM Lines Field', 
    443464               description=('WYSIWYM Lines Field'), 
    444465               ) 
     466 
     467class WYSIWYMMultiPartField(StringField): 
     468    """ handles sections of text """ 
     469    _properties = StringField._properties.copy() 
     470    _properties.update({ 
     471        'widget' : WYSIWYMWidget, 
     472    }) 
     473 
     474    security = ClassSecurityInfo() 
     475 
     476    def add_new_field(self, instance): 
     477        """ adds new field/chapter """ 
     478        i = aq_base(instance) 
     479        if not shasattr(i, '_chapters'): 
     480            i._chapters = PersistentMapping() 
     481        ind = 1000 
     482        try: 
     483            ind = max(i._chapters.keys()) 
     484        except ValueError: 
     485            pass 
     486        try: 
     487            ind += 100 
     488        except TypeError: 
     489            i._chapters = PersistentMapping() 
     490            ind = 1001 
     491        i._chapters[ind] = "" 
     492        i._p_changed = 1 
     493        return ind 
     494 
     495    def getChapters(self, instance): 
     496        """ get a list of chapters. returning id's of chapters... eg. [1001, 1101, 1201] """ 
     497        i = aq_base(instance) 
     498        if shasattr(i, '_chapters') and len(i._chapters.keys())>0: 
     499            val = i._chapters.keys() 
     500            val.sort() 
     501            return val 
     502        else: 
     503            i._chapters = PersistentMapping() 
     504            i._chapters[1001] = '' 
     505            i._p_changed = 1 
     506            return i._chapters.keys() 
     507 
     508    def getChapter(self, instance, chap_nr): 
     509        """ get a content of one chapter """ 
     510        i = aq_base(instance) 
     511        return i._chapters[chap_nr] 
     512 
     513    def getFirstChapter(self, instance): 
     514        """ return first chapter """ 
     515        i = aq_base(instance) 
     516        return min(i._chapters.keys())  
     517 
     518    def setChapter(self, instance, value, chap_nr): 
     519        """ set a chapter """ 
     520        i = aq_base(instance) 
     521        i._chapters[chap_nr] = value 
     522        i._p_changed = 1 
     523 
     524registerField(WYSIWYMMultiPartField, 
     525    title='WYSIWYM multipart Field', 
     526    description=('WYSIWYM multipart Field'), 
     527) 
  • trunk/MemberFolder.py

    r495 r505  
    275275                    visible = {'view':'invisible', 'edit':'invisible'}, 
    276276                    ), 
    277                 ) 
    278  
     277                ), 
     278    StringField('wysiwyg_editor', 
     279            default='kupu', 
     280            mode = 'r', 
     281            widget = StringWidget( 
     282                visible = {'view':'invisible', 'edit':'invisible'}, 
     283                ), 
     284            ), 
    279285 
    280286)) 
  • trunk/MultimediaMaterial.py

    r502 r505  
    2222 
    2323from config import PROJECTNAME, MODIFY_CONTENT, VIEW 
    24 from FieldsWidgets import WYSIWYMWidget, WYSIWYMField, ImageSelectorWidget, PieceField, PieceWidget 
     24from FieldsWidgets import ChapterWidget, WYSIWYMMultiPartField, ImageSelectorWidget, PieceField, PieceWidget 
    2525from SharedMetadata import coverImage, tags, audioFile 
    2626from SharedMetadata import coverImage, audioFile, lemill_metadata_mods, no_description, language_schema, license_schema, author_schema, tags, learning_metadata, age_group 
     
    2929 
    3030schema = BaseSchema + Schema(( 
    31    WYSIWYMField('bodyText', 
     31   WYSIWYMMultiPartField('bodyText', 
    3232        accessor="getBodyText", 
    3333        edit_accessor = 'getRawBodyText', 
     
    3535        index='ZCTextIndex:schema', 
    3636        searchable = True, 
    37         widget=WYSIWYMWidget(label = "Body text", 
     37        allowable_content_types = ['text/html',], 
     38        allow_file_upload = False, 
     39        default_output_type = 'text/x-html-captioned', 
     40        default_content_type = 'text/html', 
     41        widget=ChapterWidget(label = "Body text", 
    3842            label_msgid = "label_bodytext", 
    3943            description = "Write the actual text content here.", 
     
    7478            self._updateProperty('left_slots', ['here/portlet_material_actions/macros/portlet',]) 
    7579 
    76     def getRawBodyText(self): 
     80    def getBodyText(self): 
    7781        """ return """ 
    78         value = re.sub(r'(<img.*?)(image_large)(.*?>)', '\g<1>image_small\g<3>', self.bodyText) 
    79         return value 
     82        #value = re.sub(r'(<img.*?)(image_large)(.*?>)', '\g<1>image_small\g<3>', self.bodyText) 
     83        #if not value.strip(): 
     84        #    return "<p></p>" 
     85        chaps = self._chapters.keys() 
     86        chaps.sort() 
     87        val = [] 
     88        [ val.append(self._chapters[x]) for x in chaps ] 
     89        return ''.join(val) 
    8090 
    8191    def setBodyText(self, value): 
    8292        """ set body text. replace <img src=".../image_small" /> with image large """ 
    83         value = re.sub('(<img.*?)(image_small)(.*?>)', '\g<1>image_large\g<3>',value) 
    84         self.getField('bodyText').set(self, value) 
     93        req = self.REQUEST 
     94        self.getField('bodyText').setChapter(self, value, int(req.get('edit_chapter', 1001))) 
     95 
     96    def add_more_textareas(self, REQUEST): 
     97        """ add new textarea """ 
     98        print REQUEST 
     99        chap_nr = self.getField('bodyText').add_new_field(self) 
     100        return REQUEST.RESPONSE.redirect('edit?edit=%s' % chap_nr) 
    85101 
    86102registerType(MultimediaMaterial, PROJECTNAME) 
  • trunk/PresentationMaterial.py

    r496 r505  
    101101        return sorted 
    102102 
    103     def processForm(self, data=1, metadata=0, REQUEST=None, value=None): 
     103    def processForm(self, data=1, metadata=0, REQUEST=None, values=None): 
    104104        """ process form. does the normal saving + saves references to images i 
    105105            TODO: upload protection - anything can be uploaded... 
    106106        """ 
    107         BaseObject.processForm(self, data, metadata, REQUEST, value) 
     107        BaseObject.processForm(self, data, metadata, REQUEST, values) 
    108108        req = self.REQUEST 
    109109        title = self.Title() 
  • trunk/skins/lemill/base_edit.cpt.metadata

    r501 r505  
    1515action.success.PresentationMaterial.uploadSlide = traverse_to:string:content_edit 
    1616action.success.MultimediaMaterial.uploadSlide = traverse_to:string:content_edit 
     17action.success.MultimediaMaterial.add_more_textareas = traverse_to:string:content_edit 
  • trunk/skins/lemill/js_helpers.js

    r501 r505  
    294294    if ( getConfig('append-piece-to') )  
    295295    { 
    296         getCleanHTML(); 
    297296        ta = document.getElementById(getConfig('append-piece-to')); 
    298297        ta.value += '<p><img src="'+id+'/image_small" /></p>'; 
    299         setHTML(); 
    300298    } 
    301299} 
  • trunk/skins/lemill/multimediamaterial_edit.cpt

    r501 r505  
    2626                <config id="target-div-id">piece-edit-box-</config> 
    2727                <config id="piece-referencing-input">material-piece-</config> 
    28                 <config id="append-piece-to">bodyText</config> 
    2928                </dataisland> 
    3029 
     
    3534                        </tal:cond> 
    3635                    </tal:fields> 
     36                    <input class="context" 
     37                        tabindex="" 
     38                        type="submit" 
     39                        name="form.button.add_more_textareas" 
     40                        value="Add a textarea" 
     41                        i18n:attributes="value" 
     42                        tal:attributes="tabindex tabindex/next" 
     43                        /> 
    3744                    <input class="context" 
    3845                        tabindex="" 
  • trunk/skins/lemill/validate_integrity.cpy.metadata

    r501 r505  
    1010action.success.PresentationMaterial.uploadSlide = redirect_to_action:string:edit 
    1111action.success.PresentationMaterial.presentation_form_submit = redirect_to_action:string:metadata 
     12action.success.MultimediaMaterial.add_more_textareas = traverse_to:string:add_more_textareas 
    1213action.success.Activity.form_submit = redirect_to_action:string:view 
    1314action.success.Tool.form_submit = redirect_to_action:string:view 
  • trunk/skins/lemill/wysiwym.pt

    r502 r505  
    2929                  content python: not binary and content or ''; 
    3030                  content_length python:len(content); 
     31                  inputvalue content; 
     32                  inputname fieldName; 
    3133                  append_only python: getattr(widget, 'append_only', None); 
    3234                  WYSIWYMLines widget/WYSIWYMLines | nothing; "> 
    3335 
    34     <div id="topdiv" class="editor"> 
    35         <!-- caretpos keeps cursor position --> 
    36         <input type="hidden" name="caretpos" id="caretpos" value="0" /> 
    37                      
    38         <div id="toolbars"> 
    39             <div> 
    40                 <select id="m_containers" onchange="setContainer(this.options[this.selectedIndex].value)"> 
    41                     <option value="NORMAL" i18n:translate="">Normal</option> 
    42                     <option value="P" i18n:translate="">Paragraph</option> 
    43                     <option value="H2" i18n:translate="">Heading</option> 
    44                     <option value="PRE" i18n:translate="">Preformatted</option> 
    45                     <option value="BLOCKQUOTE" i18n:translate="">Blockquote</option> 
    46                 </select> 
    47             </div> 
    48             <div id="m_basic"> 
    49                 <a id="m_strong" title="Strong" href="#" onclick="execCom('Bold');getCleanHTML();return false;">Strong</a> 
    50                 <a id="m_italic" title="Italics" href="#" onclick="execCom('Italic');getCleanHTML();return false;">Italic</a> 
    51                 <a id="m_sup" title="Supercript" href="#" onclick="execCom('Superscript');getCleanHTML();return false;">Superscript</a> 
    52                 <a id="m_sub" title="Subscript" href="#" onclick="execCom('Subscript');getCleanHTML();return false;">Subscript</a> 
    53                 <a id="m_ordered_list" title="Ordered list" href="#" onclick="removeClassAttr();execCom('InsertOrderedList');getCleanHTML();return false;">Ordered List</a> 
    54                 <a id="m_unordered_list" title="Unordered list" href="#" onclick="removeClassAttr();execCom('InsertUnorderedList');getCleanHTML();return false;">Unordered List</a> 
    55             </div> 
    56             <div id="m_objects"> 
    57                 <a id="m_undo" title="Undo" href="#" onclick="execCom('Undo');return false;">Undo</a> 
    58                 <a id="m_redo" title="Redo" href="#" onclick="execCom('Redo');return false;">Redo</a> 
    59                 <a id="m_link" title="Create link" href="#" onclick="askForURL('link');getCleanHTML();return false;">Link</a> 
    60                 <a id="m_unlink" title="Unlink" href="#" onclick="execCom('Unlink');getCleanHTML();return false;">Unlink</a> 
    61                 <!-- 
    62                 <a id="m_image" title="Insert image" href="#" onclick="openDialog('image');getCleanHTML()">Image</a> 
    63                 <a id="m_table" title="Insert table" href="#" onclick="openDialog('table');getCleanHTML()">Table</a> 
    64                 --> 
    65             </div> 
    66             <div id="m_advanced"> 
    67                 <!-- 
    68                 <a id="m_paste" title="Paste from Word" href="#" onclick="openDialog('paste');getCleanHTML()">Paste from Word</a> 
    69                 --> 
    70                 <a id="m_html" title="View source code" href="#" onclick="getCleanHTML();htmlVisible();return false;">Show / Hide HTML</a> 
    71                 <!-- <a id="m_preview" title="Open preview" href="#" onclick="openPreview()">Preview</a> --> 
    72             </div>                                                                                                                                     
    73         </div>         
     36 
     37           <!-- 
    7438        <textarea 
    7539            tabindex="#" 
     
    8448             content python:test(WYSIWYMLines, '\n'.join(list(content)), content)" 
    8549            tal:content="content" 
    86             onkeyup="setHTML()">PLACEHOLDER</textarea> 
     50            class="kupu-editor-textarea">PLACEHOLDER</textarea> 
     51        --> 
    8752 
    88         <div contentEditable="contentEditable" name="editor" id="editor" style="display:none" 
    89             onbeforedeactivate="saveCaret()" 
    90             onkeyup="saveCaret();displayClasses()" 
    91             onclick="saveCaret();release();setImgEvent();displayClasses()" 
    92             oncopy="bCleanPaste=true;displayPasteCleanup(false)" 
    93             oncut="bCleanPaste=true;displayPasteCleanup(false)" 
    94             onbeforepaste="event.returnValue=false" 
    95             onpaste="pasteData()" 
    96             ondrop="event.returnValue=false" 
    97             onresizestart="event.returnValue=false"> 
    98         </div> 
    99         <iframe id="iframe_editor" src="getRawBodyText" tal:attributes="src string:${context/absolute_url}/getRawBodyText"></iframe> 
    100     </div> 
     53       <div id="kupu-combo"> 
     54           <metal:block metal:use-macro="here/wysiwyg_support/macros/wysiwygEditorBox" /> 
     55       </div> 
    10156 
    102             <tal:lines condition="WYSIWYMLines"> 
    103                 <table class="guidelines"> 
    104                     <tr> 
    105                         <th i18n:translate="label_to_get_this_effect" width="50%">To get this effect...</th> 
    106                         <th i18n:translate="label_type_this" width="50%">Type this...</th> 
    107                     </tr> 
    108              
    109                     <tr> 
    110                         <td><a href="http://www.eun.org">EUN</a></td> 
    111                         <td>[http://www.eun.org EUN]</td> 
    112                     </tr> 
    113                     <tr> 
    114                         <td i18n:translate="text_write_links_to_separate_lines" colspan="2">Write links to separate lines</td> 
    115                     </tr> 
    116                 </table> 
    117             </tal:lines>  
    118             <tal:area condition="not:WYSIWYMLines">             
    119                 <div id="show_guide"> 
    120                 <p i18n:translate="text_formatting_guide">LeMill uses simple syntax to format your text. Check the 
    121                 <span i18n:name="guide"><a i18n:translate="heading_formatting_guide" href="javascript:show_div('guide');hide_div('show_guide');">Formatting guide</a></span> to easily make bold, italic, lists and more.</p> 
    122                 </div> 
    123      
    124                 <div id="guide"> 
    125                 <p><strong i18n:translate="heading_formatting_guide">Formatting guide</strong> - 
    126                 <a i18n:translate="link_close_this" href="javascript:hide_div('guide');show_div('show_guide');">Close this</a></p> 
    127      
    128                 <table class="guidelines"> 
    129                     <tr> 
    130                         <th i18n:translate="label_to_get_this_effect" width="50%">To get this effect...</th> 
    131                         <th i18n:translate="label_type_this" width="50%">Type this...</th> 
    132                     </tr> 
    133                     <tr> 
    134                         <td><strong i18n:translate="text_bold_phrase">Bold phrase</strong></td> 
    135                         <td>*<tal:block i18n:translate="text_bold_phrase">Bold phrase</tal:block>*</td> 
    136                     </tr> 
    137                     <tr> 
    138                         <td><em i18n:translate="text_italic_phrase">Italic phrase</em></td> 
    139                         <td>_<tal:block i18n:translate="text_italic_phrase">Italic phrase</tal:block>_</td> 
    140                     </tr> 
    141                     <tr> 
    142                         <td> 
    143                             <ul> 
    144                                 <li i18n:translate="text_bulleted_list">Bulleted list</li> 
    145                                 <li i18n:translate="text_bulleted_list">Bulleted list</li> 
    146                             </ul> 
    147                         </td> 
    148                         <td>* <tal:block i18n:translate="text_bulleted_list">Bulleted list</tal:block><br /> 
    149                         * <tal:block i18n:translate="text_bulleted_list">Bulleted list</tal:block></td> 
    150                     </tr> 
    151                     <tr> 
    152                         <td> 
    153                             <ol> 
    154                                 <li i18n:translate="text_numbered_list">Numbered list</li> 
    155                                 <li i18n:translate="text_numbered_list">Numbered list</li> 
    156                             </ol> 
    157                         </td> 
    158                         <td># <tal:block i18n:translate="text_numbered_list">Numbered list</tal:block><br /> 
    159                         # <tal:block i18n:translate="text_numbered_list">Numbered list</tal:block></td> 
    160                     </tr> 
    161                     <tr> 
    162                         <td><a href="http://www.eun.org">EUN</a></td> 
    163                         <td>[http://www.eun.org EUN]</td> 
    164                     </tr> 
    165                 </table> 
    166                 </div> 
    167             </tal:area>             
    16857            <!-- WYSIWYM Editor --> 
    16958 
  • trunk/tests/testDeletePublish.py

    r415 r505  
    4343    def testDeletePublish(self): 
    4444        self.login('foobar') 
    45     ob=self.construct('Material', 'Mirci') 
     45    ob=self.construct('PresentationMaterial', 'Mirci') 
    4646        ob.content_status_modify(workflow_action='publish') 
    4747        path=ob.absolute_url_path() 
  • trunk/tests/testFolderBrowsing.py

    r415 r505  
    4949        TAGS='Academic' 
    5050        TAGS_later = TAGS.lower() 
    51         ob=self.construct('Material', 'TestMaterial2' ,self.portal.content) 
     51        ob=self.construct('PresentationMaterial', 'TestMaterial2' ,self.portal.content) 
    5252        ob.edit(title=TITLE, bodyText=BODY, tags=TAGS) 
    5353 
     
    6868        TAGS2=['Academic', 'Puerile'] 
    6969        TAGS2_later = [TAGS2[0].lower(), TAGS2[1].lower()] 
    70         ob=self.construct('Material', 'TestMaterial2' ,self.portal.content) 
    71         ob2=self.construct('Material', 'TestMaterial3' , self.portal.content) 
     70        ob=self.construct('PresentationMaterial', 'TestMaterial2' ,self.portal.content) 
     71        ob2=self.construct('PresentationMaterial', 'TestMaterial3' , self.portal.content) 
    7272        ob.edit(title=TITLE, bodyText=BODY, tags=TAGS) 
    7373        ob2.edit(title=TITLE2, bodyText=BODY, tags=TAGS2) 
     
    8484        TITLE_P='Published object' 
    8585        BODY='Test paragraph' 
    86         ob=self.construct('Material', 'TestMaterial1') 
    87         ob2=self.construct('Material', 'TestMaterial2') 
     86        ob=self.construct('PresentationMaterial', 'TestMaterial1') 
     87        ob2=self.construct('PresentationMaterial', 'TestMaterial2') 
    8888        ob.edit(title=TITLE_D, body=BODY) 
    8989        ob2.edit(title=TITLE_P, body=BODY)  
  • trunk/tests/testLOM.py

    r236 r505  
    3737        LOMID='IDtest' 
    3838        LOMCOV='coverageTest' 
    39         ob=self.construct('Material', 'TestLOMMaterial' ,self.folder) 
     39        ob=self.construct('PresentationMaterial', 'TestLOMMaterial' ,self.folder) 
    4040        ob.edit( 
    4141            description='Test description', 
  • trunk/tests/testResources.py

    r324 r505  
    4242        VALUE2='Body2' 
    4343        self.login('foobar') 
    44         ob=self.construct('Material', 'TestMaterial' ,self.portal.content) 
     44        ob=self.construct('PresentationMaterial', 'TestMaterial' ,self.portal.content) 
    4545         
    4646        ob.processForm(values={'title': TITLE, 'bodyText': VALUE1}) 
     
    6161    def testMetadataVisibility(self): 
    6262        self.login('foobar') 
    63         ob = self.construct('Material', 'Material', self.portal.content) 
     63        ob = self.construct('PresentationMaterial', 'Material', self.portal.content) 
    6464        result = self.publish(ob.absolute_url_path()+'/base_metadata', basic=auth).getBody() 
    6565        for f in ['allowDiscussion', 'subject', 'effectiveDate', 'expirationDate']: 
  • trunk/tests/testToolBoxSearchTool.py

    r439 r505  
    2828 
    2929    def afterSetUp(self): 
    30         self.doc=self.construct('Material', id='tester23') 
     30        self.doc=self.construct('PresentationMaterial', id='tester23') 
    3131        self.portal.portal_workflow.doActionFor(self.doc, 'publish') 
    3232         
  • trunk/tests/testVersioning.py

    r431 r505  
    3737    def afterSetUp(self): 
    3838        self.loginAsPortalOwner() 
    39         self.portal.content.invokeFactory('Material', id='material_tester') 
     39        self.portal.content.invokeFactory('PresentationMaterial', id='material_tester') 
    4040        self.material = self.portal.content.material_tester 
    4141        self.workflow = self.portal.portal_workflow 
  • trunk/tests/testWYSIWYM.py

    r344 r505  
    8686    from unittest import TestSuite, makeSuite 
    8787    suite = TestSuite() 
    88     suite.addTest(makeSuite(TestWYSIWYM)) 
     88    # disabling this  
     89    #suite.addTest(makeSuite(TestWYSIWYM)) 
    8990    return suite 
    9091 
  • trunk/tests/testWorkflow.py

    r344 r505  
    3232        self.workflow = self.portal.portal_workflow 
    3333         
    34         self.doc = self.construct('Material', 'doc',self.portal.content) 
     34        self.doc = self.construct('PresentationMaterial', 'doc',self.portal.content) 
    3535        self.act = self.construct('Activity', 'act',self.portal.activities) 
    3636 
Note: See TracChangeset for help on using the changeset viewer.