cms/css/layout

3333                float: left;
3434        }
35        
35
3636        #TreeActions button.disabled {
3737                color: #aaa;
... ...
8686                color: #666;
8787        }
88        
88
8989        input.disabled:hover {
9090                background-image: url(../images/textures/ToolBar.png);
9191        }
92        
92
9393        input.action.loading, input.action.loading:hover {
9494        padding-left: 22px;
... ...
255255        #top #Logo a {
256256                margin: 0;
257                 display: block; 
257                display: block;
258258                font-size: 14px;
259259                text-decoration: none;
260                 height: 26px; 
260                height: 26px;
261261                line-height: 22px;
262                 position: absolute; 
263                 top: 5px; 
262                position: absolute;
263                top: 5px;
264264                right: 8px;
265265                padding-right: 34px;
... ...
270270                padding-bottom: 0;
271271        }
272        
272
273273#bottom {
274274        width: 100%;
... ...
348348        overflow-x: hidden;
349349}
350        
350
351351        #sitetree_holder #TreeTools {
352352                float: left;
... ...
434434                                margin: 0;
435435                        }
436                 #TreeTools #action_publish_selected, 
436                #TreeTools #action_publish_selected,
437437                #TreeTools #action_publish_selected {
438438                        padding: 2px 1px;
... ...
446446        display: none;
447447}
448        
449 div.spacer, 
448
449div.spacer,
450450li.spacer {
451451        float: none;
... ...
566566        width: 190px;
567567        height: 120px;
568         overflow-y: auto;       
568        overflow-y: auto;
569569        margin-right: 0 !important;
570570}
... ...
620620}
621621#Form_EditorToolbarImageForm fieldset label.left,
622 #Form_EditorToolbarFlashForm fieldset label.left, 
622#Form_EditorToolbarFlashForm fieldset label.left,
623623#Form_EditorToolbarLinkForm fieldset label.left {
624624        float:left;
... ...
648648#Form_EditorToolbarLinkForm .buttonRefresh {
649649        display:block;
650         border:1px solid #F0F0EE; 
650        border:1px solid #F0F0EE;
651651        width:20px; height:20px;
652652        float: left;
653653}
654654#Form_EditorToolbarLinkForm a.buttonRefreshHover {
655         border: 1px solid #0A246A; 
655        border: 1px solid #0A246A;
656656        background-color:#B2BBD0;
657657}
... ...
670670        width: 160px;
671671}
672        
672
673673#Form_EditorToolbarImageForm_Width,
674674#Form_EditorToolbarImageForm_Height,
675 #Form_EditorToolbarFlashForm_Width,
676 #Form_EditorToolbarFlashForm_Height {
675#Form_EditorToolbarFlashForm_Width {
677676        outline: 3px solid #E9E9E9;
678677}
... ...
712711                border-color: #FF9300;
713712        }
714        
713
715714        .message.warning {
716715                background-color: #FFD2A6;
... ...
721720                border-color: #FF0000;
722721        }
722
723
724
725
726#Form_EditorToolbarYoutubeForm p {
727        margin-left:5px;
728}
729#right form#Form_EditorToolbarYoutubeForm {
730        background: #eee;
731        border-bottom: 1px solid #ccc;
732        display: none;
733        margin: 1px 0 0 0;
734        padding: 5px;
735        /*
736         * HACK IE (all versions): container needs to be higher stacking order
737         * than any DOM-elemnt under it.
738         * @see http://www.aplus.co.yu/lab/z-pos/
739         */
740        /*overflow: hidden;*/
741        z-index: 1001;
742}
743#contentPanel input#Form_EditorToolbarYoutubeForm_Width {
744        width: 30px;
745}
746
747#contentPanel input#Form_EditorToolbarYoutubeForm_Height {
748        width: 30px;
749}
750
751
752#Form_EditorToolbarYoutubeForm fieldset label.left {
753        float:left;
754        margin-left:0px;
755        color: #666;
756        line-height: 1.2;
757        font-size: 11px;
758        width: 190px;
759}
760
761
762
763#Form_EditorToolbarYoutubeForm fieldset li div.middleColumn {
764        float: none;
765}
766
767
768#Form_EditorToolbarYoutubeForm fieldset div.fieldgroupField {
769        display: inline;
770}
771
772#Form_EditorToolbarVimeoForm p {
773        margin-left:5px;
774}
775#right form#Form_EditorToolbarVimeoForm {
776        background: #eee;
777        border-bottom: 1px solid #ccc;
778        display: none;
779        margin: 1px 0 0 0;
780        padding: 5px;
781        /*
782         * HACK IE (all versions): container needs to be higher stacking order
783         * than any DOM-elemnt under it.
784         * @see http://www.aplus.co.yu/lab/z-pos/
785         */
786        /*overflow: hidden;*/
787        z-index: 1001;
788}
789#contentPanel input#Form_EditorToolbarVimeoForm_Width {
790        width: 30px;
791}
792
793#contentPanel input#Form_EditorToolbarVimeoForm_Height {
794        width: 30px;
795}
796
797
798#Form_EditorToolbarVimeoForm fieldset label.left {
799        float:left;
800        margin-left:0px;
801        color: #666;
802        line-height: 1.2;
803        font-size: 11px;
804        width: 190px;
805}
806
807
808
809#Form_EditorToolbarVimeoForm fieldset li div.middleColumn {
810        float: none;
811}
812
813
814#Form_EditorToolbarVimeoForm fieldset div.fieldgroupField {
815        display: inline;
816}

cms/javascript/tinymce_ssbuttons/langs/de.js

22insertlink: 'Link einfÌgen',
33insertimage: 'Bild einfÌgen',
4 insertflash: 'Flash Objekt einfÌgen'
4insertflash: 'Flash Objekt einfÌgen',
5insertyoutube: 'YouTube einfÌgen',
6insertvimeo: 'Vimeo einfÌgen'
57});

cms/javascript/tinymce_ssbuttons/langs/en.js

22insertlink: 'Insert Link',
33insertimage: 'Insert Image',
4 insertflash: 'Insert Flash Object'
4insertflash: 'Insert Flash Object',
5insertyoutube: 'Insert YouTube',
6insertvimeo: 'Insert Vimeo'
57});

cms/javascript/tinymce_ssbuttons/editor_plugin_src.js

99                 *
1010                 * @returns Name/value array containing information about the plugin.
11                  * @type Array 
11                 * @type Array
1212                 */
1313                getInfo : function() {
... ...
2828                                'sslink' : 'Form_EditorToolbarLinkForm',
2929                                'ssimage' : 'Form_EditorToolbarImageForm',
30                                 'ssflash' : 'Form_EditorToolbarFlashForm'
30                                'ssflash' : 'Form_EditorToolbarFlashForm',
31                                'ssyoutube' : 'Form_EditorToolbarYoutubeForm',
32                                'ssvimeo' : 'Form_EditorToolbarVimeoForm'
3133                        };
3234
33                         ed.addButton('sslink', {title : ed.getLang('tinymce_ssbuttons.insertlink'), cmd : 'sslink', 'class' : 'mce_link'});
34                         ed.addButton('ssimage', {title : ed.getLang('tinymce_ssbuttons.insertimage'), cmd : 'ssimage', 'class' : 'mce_image'});
35                         ed.addButton('ssflash', {title : ed.getLang('tinymce_ssbuttons.insertflash'), cmd : 'ssflash', 'class' : 'mce_flash', 'image': url + '/img/flash.gif'});
35                        ed.addButton('sslink', {title : ed.getLang('tinymce_ssbuttons.insertlink'), cmd : 'sslink', 'class' : 'mce_link'});
36                        ed.addButton('ssimage', {title : ed.getLang('tinymce_ssbuttons.insertimage'), cmd : 'ssimage', 'class' : 'mce_image'});
37                        ed.addButton('ssflash', {title : ed.getLang('tinymce_ssbuttons.insertflash'), cmd : 'ssflash', 'class' : 'mce_flash', 'image': url + '/img/flash.gif'});
38                        ed.addButton('ssyoutube', {title : ed.getLang('tinymce_ssbuttons.insertyoutube'), cmd : 'ssyoutube', 'class' : 'mce_youtube', 'image': url + '/img/youtube.png'});
39                        ed.addButton('ssvimeo', {title : ed.getLang('tinymce_ssbuttons.insertvimeo'), cmd : 'ssvimeo', 'class' : 'mce_vimeo', 'image': url + '/img/vimeo.png'});
3640
3741                        /**
... ...
4145                        function showSidePanel(showCommand, hideCommands) {
4246                                ed.ss_focus_bookmark = ed.selection.getBookmark();
43                                 hideCommands.each(function(command) { 
47                                hideCommands.each(function(command) {
4448                                        ed.controlManager.setActive(command,false);
45                                         Element.hide(forms[command]); 
49                                        Element.hide(forms[command]);
4650                                });
4751
... ...
6468
6569                        ed.addCommand("ssclosesidepanel", function(ed) {
66                                 showSidePanel('', [ 'sslink', 'ssimage', 'ssflash' ]);
70                                showSidePanel('', [ 'sslink', 'ssimage', 'ssflash', 'ssyoutube', 'ssvimeo' ]);
6771                        });
6872
6973                        ed.addCommand("sslink", function(ed) {
70                                 showSidePanel('sslink', [ 'ssimage', 'ssflash' ]);
74                                showSidePanel('sslink', [ 'ssimage', 'ssflash', 'ssyoutube', 'ssvimeo' ]);
7175                        });
7276
7377                        ed.addCommand("ssimage", function(ed) {
74                                 showSidePanel('ssimage', [ 'sslink', 'ssflash' ]);
78                                showSidePanel('ssimage', [ 'sslink', 'ssflash', 'ssyoutube', 'ssvimeo' ]);
7579                        });
7680
7781                        ed.addCommand("ssflash", function(ed) {
78                                 showSidePanel('ssflash', [ 'ssimage', 'sslink' ]);
82                                showSidePanel('ssflash', [ 'ssimage', 'sslink', 'ssyoutube', 'ssvimeo' ]);
83                        });
84
85                        ed.addCommand("ssyoutube", function(ed) {
86                                showSidePanel('ssyoutube', [ 'ssimage', 'sslink', 'ssflash', 'ssvimeo' ]);
87                        });
88
89                        ed.addCommand("ssvimeo", function(ed) {
90                                showSidePanel('ssvimeo', [ 'ssimage', 'sslink', 'ssflash', 'ssyoutube' ]);
7991                        });
8092
... ...
89101                                $('Form_EditorToolbarLinkForm').updateSelection(ed);
90102                        });
91                
103
92104                        // resize image containers when the image is resized.
93105                        if(!tinymce.isOpera && !tinymce.isWebKit) ed.onMouseUp.add(function(ed, o) {

cms/templates/LeftAndMain.ss

1111<body class="stillLoading $CSSClasses">
1212        <div id="Loading" style="background: #FFF url($LoadingImage) 50% 50% no-repeat; position: absolute;z-index: 100000;height: 100%;width: 100%;margin: 0;padding: 0;z-index: 100000;position: absolute;"><% _t('LOADING','Loading...',PR_HIGH) %><noscript><h1><% _t('REQUIREJS','The CMS requires that you have JavaScript enabled.',PR_HIGH) %></h1></noscript></div>
13        
13
1414        <div id="top">
1515                $CMSTopMenu
1616        </div>
17        
17
1818        <div id="left" style="float:left">
1919                $Left
2020        </div>
21        
21
2222        <div id="separator" style="float:left">
2323                &nbsp;
2424        </div>
25        
25
2626        <div class="right" id="right">
2727                $Right
... ...
3333                        $LinkForm
3434                        $FlashForm
35                        $YoutubeForm
36                        $VimeoForm
3537                <% end_control %>
3638        </div>
37        
39
3840        <div id="bottom">
3941                <div class="holder">
4042                        <div id="logInStatus">
4143                                <a href="$ApplicationLink" title="<% _t('SSWEB','Silverstripe Website') %>">$ApplicationName</a>&nbsp;-&nbsp;
42                                 <abbr style="border-style: none" title="<% _t('APPVERSIONTEXT1',"This is the") %> $ApplicationName <% _t('APPVERSIONTEXT2',"version that you are currently running, technically it's the CVS branch") %>">$CMSVersion</abbr> &nbsp; &nbsp; &nbsp; 
44                                <abbr style="border-style: none" title="<% _t('APPVERSIONTEXT1',"This is the") %> $ApplicationName <% _t('APPVERSIONTEXT2',"version that you are currently running, technically it's the CVS branch") %>">$CMSVersion</abbr> &nbsp; &nbsp; &nbsp;
4345                                <% control CurrentMember %>
4446                                        <% _t('LOGGEDINAS','Logged in as') %> <strong><% if FirstName && Surname %>$FirstName $Surname<% else_if FirstName %>$FirstName<% else %>$Email<% end_if %></strong> | <a href="{$BaseHref}admin/myprofile" id="EditMemberProfile"><% _t('EDITPROFILE','Profile') %></a> | <a href="Security/logout" id="LogoutLink"><% _t('LOGOUT','Log out') %></a>

cms/_config.php

33/**
44 * Extended URL rules for the CMS module
5  * 
5 *
66 * @package cms
77 */
... ...
1010        'admin/help//$Action/$ID' => 'CMSHelp',
1111        'admin/bulkload//$Action/$ID/$OtherID' => 'BulkLoaderAdmin',
12         'admin/cms//$Action/$ID/$OtherID' => 'CMSMain', 
12        'admin/cms//$Action/$ID/$OtherID' => 'CMSMain',
1313        'PageComment//$Action/$ID' => 'PageComment_Controller',
1414        'dev/buildcache/$Action' => 'RebuildStaticCacheTask',
... ...
3737HtmlEditorConfig::get('cms')->enablePlugins('media', 'fullscreen');
3838HtmlEditorConfig::get('cms')->enablePlugins(array('ssbuttons' => '../../../cms/javascript/tinymce_ssbuttons/editor_plugin_src.js'));
39                        
39
4040HtmlEditorConfig::get('cms')->insertButtonsBefore('formatselect', 'styleselect');
41 HtmlEditorConfig::get('cms')->insertButtonsBefore('advcode', 'ssimage', 'ssflash', 'sslink', 'unlink', 'anchor', 'separator' );
41HtmlEditorConfig::get('cms')->insertButtonsBefore('advcode', 'ssimage', 'ssflash', 'ssyoutube', 'ssvimeo', 'sslink', 'unlink', 'anchor', 'separator' );
4242HtmlEditorConfig::get('cms')->insertButtonsAfter ('advcode', 'fullscreen', 'separator');
43                        
43
4444HtmlEditorConfig::get('cms')->removeButtons('tablecontrols');
4545HtmlEditorConfig::get('cms')->addButtonsToLine(3, 'tablecontrols');

sapphire/forms/HtmlEditorField.php

88 */
99class HtmlEditorField extends TextareaField {
10        
10
1111        /**
1212         * Includes the JavaScript neccesary for this field to work using the {@link Requirements} system.
... ...
1616                Requirements::customScript(HtmlEditorConfig::get_active()->generateJS(), 'htmlEditorConfig');
1717        }
18        
18
1919        /**
2020         * @see TextareaField::__construct()
... ...
2222        public function __construct($name, $title = null, $rows = 30, $cols = 20, $value = '', $form = null) {
2323                parent::__construct($name, $title, $rows, $cols, $value, $form);
24                
24
2525                $this->addExtraClass('htmleditor');
26                
26
2727                self::include_js();
2828        }
29        
29
3030        /**
3131         * @return string
... ...
3434                // mark up broken links
3535                $value  = new SS_HTMLValue($this->value);
36                
36
3737                if($links = $value->getElementsByTagName('a')) foreach($links as $link) {
3838                        $matches = array();
39                        
39
4040                        if(preg_match('/\[sitetree_link id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) {
4141                                if(!DataObject::get_by_id('SiteTree', $matches[1])) {
... ...
4545                        }
4646                }
47                
47
4848                return $this->createTag (
4949                        'textarea',
... ...
6060                );
6161        }
62        
62
6363        public function saveInto($record) {
6464                if($record->escapeTypeForField($this->name) != 'xml') {
... ...
6767                        );
6868                }
69                
69
7070                $linkedPages = array();
7171                $linkedFiles = array();
72                
72
7373                $htmlValue = new SS_HTMLValue($this->value);
74                
74
7575                // Populate link tracking for internal links & links to asset files.
7676                if($links = $htmlValue->getElementsByTagName('a')) foreach($links as $link) {
7777                        $href = Director::makeRelative($link->getAttribute('href'));
78                        
78
7979                        if($href) {
8080                                if(preg_match('/\[sitetree_link id=([0-9]+)\]/i', $href, $matches)) {
8181                                        $ID = $matches[1];
82                                        
82
8383                                        // clear out any broken link classes
8484                                        if($class = $link->getAttribute('class')) {
8585                                                $link->setAttribute('class', preg_replace('/(^ss-broken|ss-broken$| ss-broken )/', null, $class));
8686                                        }
87                                        
87
8888                                        $linkedPages[] = $ID;
8989                                        if(!DataObject::get_by_id('SiteTree', $ID))  $record->HasBrokenLink = true;
... ...
101101                        }
102102                }
103                
103
104104                // Resample images, add default attributes and add to assets tracking.
105105                if($images = $htmlValue->getElementsByTagName('img')) foreach($images as $img) {
... ...
110110                                        $record->HasBrokenFile = true;
111111                                }
112                                
112
113113                                continue;
114114                        }
115                        
115
116116                        // Resample the images if the width & height have changed.
117117                        $width  = $img->getAttribute('width');
118118                        $height = $img->getAttribute('height');
119                        
119
120120                        if($image){
121121                                if($width && $height && ($width != $image->getWidth() || $height != $image->getHeight())) {
... ...
126126                                }
127127                        }
128                        
128
129129                        // Add default empty title & alt attributes.
130130                        if(!$img->getAttribute('alt')) $img->setAttribute('alt', '');
131131                        if(!$img->getAttribute('title')) $img->setAttribute('title', '');
132                        
132
133133                        //If the src attribute is not set, then we won't add this to the list:
134134                        if($img->getAttribute('src')){
... ...
137137                        }
138138                }
139                
139
140140                // Save file & link tracking data.
141141                if($record->ID && $record->many_many('LinkTracking') && $tracker = $record->LinkTracking()) {
... ...
149149                        }
150150                }
151                
151
152152                if($record->ID && $record->many_many('ImageTracking') && $tracker = $record->ImageTracking()) {
153153                        $filter = sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d', $this->name, $record->ID);
... ...
159159                        }
160160                }
161                
161
162162                $record->{$this->name} = $htmlValue->getContent();
163163        }
... ...
172172                return $field;
173173        }
174        
174
175175}
176176
... ...
198198class HtmlEditorField_Toolbar extends RequestHandler {
199199        protected $controller, $name;
200        
200
201201        function __construct($controller, $name) {
202202                parent::__construct();
203203                Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js");
204204                Requirements::javascript(SAPPHIRE_DIR . "/javascript/tiny_mce_improvements.js");
205                
205
206206                Requirements::javascript(SAPPHIRE_DIR ."/thirdparty/jquery-form/jquery.form.js");
207207                Requirements::javascript(SAPPHIRE_DIR ."/javascript/HtmlEditorField.js");
208                
208
209209                $this->controller = $controller;
210210                $this->name = $name;
... ...
213213        /**
214214         * Searches the SiteTree for display in the dropdown
215          * 
215         *
216216         * @return callback
217          */     
217         */
218218        function siteTreeSearchCallback($sourceObject, $labelField, $search) {
219219                return DataObject::get($sourceObject, "\"MenuTitle\" LIKE '%$search%' OR \"Title\" LIKE '%$search%'");
220220        }
221        
221
222222        /**
223223         * Return a {@link Form} instance allowing a user to
224224         * add links in the TinyMCE content editor.
225          * 
225         *
226226         * @return Form
227227         */
... ...
230230                // mimic the SiteTree::getMenuTitle(), which is bypassed when the search is performed
231231                $siteTree->setSearchFunction(array($this, 'siteTreeSearchCallback'));
232                
232
233233                $form = new Form(
234234                        $this->controller,
235                         "{$this->name}/LinkForm", 
235                        "{$this->name}/LinkForm",
236236                        new FieldSet(
237237                                new LiteralField('Heading', '<h2><img src="cms/images/closeicon.gif" alt="' . _t('HtmlEditorField.CLOSE', 'close').'" title="' . _t('HtmlEditorField.CLOSE', 'close') . '" />' . _t('HtmlEditorField.LINK', 'Link') . '</h2>'),
238238                                new OptionsetField(
239239                                        'LinkType',
240                                         _t('HtmlEditorField.LINKTO', 'Link to'), 
240                                        _t('HtmlEditorField.LINKTO', 'Link to'),
241241                                        array(
242242                                                'internal' => _t('HtmlEditorField.LINKINTERNAL', 'Page on the site'),
... ...
244244                                                'anchor' => _t('HtmlEditorField.LINKANCHOR', 'Anchor on this page'),
245245                                                'email' => _t('HtmlEditorField.LINKEMAIL', 'Email address'),
246                                                 'file' => _t('HtmlEditorField.LINKFILE', 'Download a file'),                   
246                                                'file' => _t('HtmlEditorField.LINKFILE', 'Download a file'),
247247                                        )
248248                                ),
... ...
262262                        )
263263                );
264                
264
265265                $form->loadDataFrom($this);
266                
266
267267                $this->extend('updateLinkForm', $form);
268                
268
269269                return $form;
270270        }
... ...
273273         * Return a {@link Form} instance allowing a user to
274274         * add images to the TinyMCE content editor.
275          * 
275         *
276276         * @return Form
277277         */
... ...
306306                        )
307307                );
308                
308
309309                $actions = new FieldSet(
310310                        new FormAction('insertimage', _t('HtmlEditorField.BUTTONINSERTIMAGE', 'Insert image'))
311311                );
312                
312
313313                $form = new Form(
314314                        $this->controller,
... ...
317317                        $actions
318318                );
319                
319
320320                $form->disableSecurityToken();
321321                $form->loadDataFrom($this);
322                
323                 // Allow other people to extend the fields being added to the imageform 
322
323                // Allow other people to extend the fields being added to the imageform
324324                $this->extend('updateImageForm', $form);
325                
325
326326                return $form;
327327        }
... ...
330330                $form = new Form(
331331                        $this->controller,
332                         "{$this->name}/FlashForm", 
332                        "{$this->name}/FlashForm",
333333                        new FieldSet(
334334                                new LiteralField('Heading', '<h2><img src="cms/images/closeicon.gif" alt="'._t('HtmlEditorField.CLOSE', 'close').'" title="'._t('HtmlEditorField.CLOSE', 'close').'" />'._t('HtmlEditorField.FLASH', 'Flash').'</h2>'),
... ...
349349                $form->loadDataFrom($this);
350350                $form->disableSecurityToken();
351                
351
352352                $this->extend('updateFlashForm', $form);
353                
353
354354                return $form;
355355        }
356
357        function YoutubeForm() {
358                $form = new Form(
359                        $this->controller,
360                        "{$this->name}/YoutubeForm",
361                        new FieldSet(
362                                new LiteralField('Heading', '<h2><img src="cms/images/closeicon.gif" alt="'._t('HtmlEditorField.CLOSE', 'close').'" title="'._t('HtmlEditorField.CLOSE', 'close').'" />'._t('HtmlEditorField.YOUTUBE', 'YouTube').'</h2>'),
363                                new TextField('YouTubeVideoCode', _t('HtmlEditorField.YOUTUBEVIDEOCODE', 'YouTube Video Code')),
364                                new CheckboxField('IncludeRelated', 'Include related videos', false),
365                                new CheckboxField('EnablePrivacyMode', 'Enable privacy-enabled mode', false),
366                                new FieldGroup(_t('HtmlEditorField.IMAGEDIMENSIONS', "Dimensions"),
367                                        new TextField("Width", _t('HtmlEditorField.IMAGEWIDTHPX', "Width"), 640),
368                                        new TextField("Height", "x " . _t('HtmlEditorField.IMAGEHEIGHTPX', "Height"), 385)
369                                )
370                        ),
371                        new FieldSet(
372                                new FormAction("insertyoutube", _t('HtmlEditorField.BUTTONINSERTYOUTUBE', 'Insert YouTube'))
373                        )
374                );
375
376                $form->disableSecurityToken();
377                $form->loadDataFrom($this);
378                $form->disableSecurityToken();
379
380                $this->extend('updateYoutubeForm', $form);
381
382                return $form;
383        }
384
385        function VimeoForm() {
386                $form = new Form(
387                        $this->controller,
388                        "{$this->name}/VimeoForm",
389                        new FieldSet(
390                                new LiteralField('Heading', '<h2><img src="cms/images/closeicon.gif" alt="'._t('HtmlEditorField.CLOSE', 'close').'" title="'._t('HtmlEditorField.CLOSE', 'close').'" />'._t('HtmlEditorField.VIMEO', 'Vimeo').'</h2>'),
391                                new TextField('VimeoVideoCode', _t('HtmlEditorField.VIMEOVIDEOCODE', 'Vimeo Video Code')),
392                                new CheckboxField('IntroPortrait', 'Show intro portrait', false),
393                                new CheckboxField('IntroTitle', 'Show intro title', false),
394                                new CheckboxField('IntroByline', 'Show intro byline', false),
395                                new CheckboxField('Autoplay', 'Autoplay the video', false),
396                                new CheckboxField('Loop', 'Loop the video', false),
397                                new FieldGroup(_t('HtmlEditorField.IMAGEDIMENSIONS', "Dimensions"),
398                                        new TextField("Width", _t('HtmlEditorField.IMAGEWIDTHPX', "Width"), 640),
399                                        new TextField("Height", "x " . _t('HtmlEditorField.IMAGEHEIGHTPX', "Height"), 385)
400                                )
401                        ),
402                        new FieldSet(
403                                new FormAction("insertvimeo", _t('HtmlEditorField.BUTTONINSERTVIMEO', 'Insert Vimeo'))
404                        )
405                );
406
407                $form->disableSecurityToken();
408                $form->loadDataFrom($this);
409                $form->disableSecurityToken();
410
411                $this->extend('updateVimeoForm', $form);
412
413                return $form;
414        }
356415}
357416

sapphire/javascript/tiny_mce_improvements.js

3131                }
3232        },
33        
33
3434        destroy: function() {
3535                this.ToolbarForm = null;
3636                this.onsubmit = null;
37                
37
3838                var i,item;
3939                for(i=0;item=this.elements.LinkType[i];i++) {
... ...
4242                }
4343        },
44        
44
4545        linkTypeChanged: function(setDefaults) {
4646                var linkType = Form.Element.getValue(this.elements.LinkType);
... ...
5757                    }
5858                }
59                
59
6060                if (jQuery('#Form_EditorToolbarLinkForm_AnchorSelector')) {
6161                        if ( linkType=='anchor' ) {
... ...
7070
7171        addAnchorSelector: function() {
72                 (function($) { 
72                (function($) {
7373                        if (!$('#Form_EditorToolbarLinkForm_AnchorSelector').length) {
7474                                // this function collects the anchors in the currently active editor and regenerates the dropdown
... ...
126126                                });
127127                        }
128                 })(jQuery);     
129         },
130        
128                })(jQuery);
129        },
130
131131        toggle: function(ed) {
132132                this.addAnchorSelector();
... ...
134134                this.respondToNodeChange(ed);
135135        },
136        
136
137137        open: function(ed) {
138138                this.ToolbarForm.open();
139                
139
140140                this.originalSelection = null;
141141                var mceInst = tinyMCE.activeEditor;
142142        },
143        
143
144144        updateSelection: function(ed) {
145145                if(ed.selection.getRng()) {
... ...
147147            }
148148    },
149        
149
150150        respondToNodeChange: function(ed) {
151151            if(ed == null) ed = tinyMCE.activeEditor;
152            
152
153153                if(this.style.display == 'block') {
154154                        var i,data = this.getCurrentLink(ed);
155                        
155
156156                        if(data) {
157157                                for(i in data) {
... ...
160160                                        }
161161                                }
162                                
162
163163                        // If we haven't selected an existing link, then just make sure we default to "internal" for the link
164164                        // type.
... ...
169169                }
170170        },
171        
171
172172        handleaction_insert: function() {
173173                var href;
174174                var target = null;
175                
175
176176                switch(Form.Element.getValue(this.elements.LinkType)) {
177177                        case 'internal':
... ...
184184
185185                        case 'anchor':
186                                 href = '#' + this.elements.Anchor.value; 
186                                href = '#' + this.elements.Anchor.value;
187187                                if($('Form_EditorToolbarLinkForm_TargetBlank')) {
188188                                        if($('Form_EditorToolbarLinkForm_TargetBlank').checked) target = '_blank';
189189                                }
190190                                break;
191                        
191
192192                        case 'file':
193193                                href = this.elements.file.value;
194194                                target = '_blank';
195195                                break;
196                        
196
197197                        case 'email':
198                                 href = 'mailto:' + this.elements.email.value; 
198                                href = 'mailto:' + this.elements.email.value;
199199                                break;
200200
... ...
215215                    tinyMCE.activeEditor.selection.setRng(this.originalSelection);
216216                }
217                
217
218218                var attributes = {
219                     href : href, 
220                     target : target, 
219                    href : href,
220                    target : target,
221221                    title : this.elements.Description.value,
222222                    innerHTML : this.elements.LinkText.value ? this.elements.LinkText.value : "Your Link"
... ...
226226                this.ssInsertLink(tinyMCE.activeEditor, attributes, this);
227227        },
228        
228
229229        /**
230230         * Insert a link into the given editor.
... ...
248248                        } catch(er) {}
249249                };
250                
250
251251                function replace() {
252252                        tinymce.each(ed.dom.select('a'), function(e) {
... ...
272272                                ed.dom.remove(e, 1);
273273                }
274                
274
275275                this.respondToNodeChange(ed);
276276        },
277        
277
278278        handleaction_remove: function() {
279279                tinyMCE.activeEditor.execCommand('unlink', false);
280280        },
281        
281
282282        /**
283283         * Return information about the currently selected link, suitable for population of the link
... ...
286286        getCurrentLink: function(ed) {
287287            if(ed == null) ed = tinyMCE.activeEditor;
288            
288
289289                var selectedText = "";
290290            selectedText = ed.selection.getContent({format : 'text'});
... ...
298298
299299                var href = "", target = "", title = "", onclick = "", action = "insert", style_class = "";
300                
300
301301                // We use a separate field for linkDataSource from tinyMCE.linkElement.
302302                // If we have selected beyond the range of an <a> element, then use use that <a> element to get the link data source,
... ...
323323                        }
324324                }
325                
325
326326                // Is anchor not a link
327327                if (linkDataSource != null && tinymce.DOM.getAttrib(linkDataSource, 'href') == "")
... ...
353353                        action = "update";
354354                }
355                
355
356356                // Turn into relative
357357                if(href.match(new RegExp('^' + tinyMCE.settings['document_base_url'] + '(.*)$'))) {
358358                        href = RegExp.$1;
359359                }
360                
360
361361                var linkText = ed.selection.getContent({format : 'html'}).replace(/<\/?a[^>]*>/ig,'');
362                
362
363363                // Get rid of TinyMCE's temporary URLs
364364                if(href.match(/^javascript:\s*mctmp/)) href = '';
365                
365
366366                if(href.match(/^mailto:(.*)$/)) {
367367                        return {
... ...
409409                    }
410410                }
411         }               
412        
411        }
412
413413}
414414
... ...
424424                this.parentForm = null;
425425                this.onclick = null;
426                
426
427427        },
428428        onclick: function() {
... ...
454454        toggle: function(ed) {
455455                this.ToolbarForm.toggle(ed);
456                
456
457457                this.resetFields();
458458        },
... ...
495495                                }
496496                        }
497                        
497
498498                        // Proportionate updating of heights
499499                        if(updatedFieldName == 'Width') {
... ...
501501                                imgElement.removeAttribute('height');
502502                                this.elements.Height.value = imgElement.height;
503                                
503
504504                        } else if(updatedFieldName == 'Height') {
505505                                imgElement.height = this.elements.Height.value;
... ...
538538                }
539539        },
540        
540
541541        selectImage: function(image) {
542542                if(this.selectedImage) {
... ...
547547                this.selectedImage.setAttribute("class", "selectedImage");
548548                this.selectedImage.className = "selectedImage";
549                
549
550550                try {
551551                        var imgTag = image.getElementsByTagName('img')[0];
... ...
555555                }
556556        },
557        
557
558558        handleaction_insertimage: function() {
559559                if(this.selectedImage) {
... ...
561561                }
562562        },
563        
563
564564        handleaction_editimage: function() {
565565                if(this.selectedImage) {
... ...
572572ImageThumbnail.prototype = {
573573        destroy: function() {
574                 this.onclick = null;           
575         },
576        
574                this.onclick = null;
575        },
576
577577        onclick: function(e) {
578578                $('Form_EditorToolbarImageForm').selectImage(this);
579579                return false;
580580        },
581        
581
582582        edit: function() {
583583                var windowWidth = Element.getDimensions(window.top.document.body).width;
... ...
615615                return;
616616        },
617        
617
618618        insert: function() {
619619                var formObj = $('Form_EditorToolbarImageForm');
... ...
624624                var relativeHref = this.href.substr(baseURL.length);
625625                var captionText = formObj.elements.CaptionText.value;
626                
626
627627                if(!tinyMCE.selectedInstance) tinyMCE.selectedInstance = tinyMCE.activeEditor;
628628                if(tinyMCE.selectedInstance.contentWindow.focus) tinyMCE.selectedInstance.contentWindow.focus();
629                
629
630630                this.ssInsertImage(tinyMCE.activeEditor, {
631631                        'src' : relativeHref,
... ...
636636                        'class' : cssClass
637637                }, captionText);
638                
638
639639                return false;
640640        },
641        
641
642642        /**
643643         * Insert an image with the given attributes
... ...
646646                el = ed.selection.getNode();
647647                var html;
648                
648
649649                if(captionText) {
650650                        html = '<div style="width: ' + attributes.width + 'px;" class="captionImage ' + attributes['class'] + '">';
... ...
655655                        html = '<img id="__mce_tmp" />';
656656                }
657                
657
658658                if(el && el.nodeName == 'IMG') {
659659                        ed.dom.setAttribs(el, attributes);
... ...
669669                                skip_undo : 1
670670                        });
671                        
671
672672                        ed.dom.setAttribs('__mce_tmp', attributes);
673673                        ed.dom.setAttrib('__mce_tmp', 'id', '');
... ...
675675                }
676676        }
677        
677
678678}
679679
... ...
713713                                }
714714                        }
715                
715
716716                        // Trick the folder dropdown into registering a change, so the image thumbnails are reloaded
717717                        folderID = $('Form_EditorToolbarImageForm_FolderID').value;
... ...
753753}
754754
755YoutubeForm = Class.extend('ToolbarForm');
756YoutubeForm.prototype = {
757        initialize: function() {
758        },
759        destroy: function() {
760                this.ToolbarForm = null;
761                this.onsubmit = null;
762
763        },
764        update_params: function(event) {
765                if(tinyMCE.imgElement) {
766                }
767        },
768        respondToNodeChange: function() {
769                if(tinyMCE.imgElement) {
770                } else {
771                }
772        },
773        selectYoutube: function(youtube) {
774                if(this.selectedYoutube) {
775                        this.selectedYoutube.setAttribute("class", "");
776                }
777                this.selectedYoutube = youtube;
778                this.selectedYoutube.setAttribute("class", "selectedYoutube");
779        },
780        handleaction_insertyoutube: function() {
781
782                var formObj = $('Form_EditorToolbarYoutubeForm');
783                var youtubeCode = formObj.elements.YouTubeVideoCode.value;
784                var includeRelated = formObj.elements.IncludeRelated.checked;
785                var enablePrivacyMode = formObj.elements.EnablePrivacyMode.checked;
786                var width = formObj.elements.Width.value;
787                var height = formObj.elements.Height.value;
788
789                var youtubeDomain = enablePrivacyMode?'www.youtube-nocookie.com':'www.youtube.com';
790                youtubeURL = 'http://' + youtubeDomain + '/v/' + youtubeCode + '?fs=1&amp;hl=en_US';
791                if (!includeRelated) youtubeURL += '&amp;rel=0';
792
793
794                if(!tinyMCE.selectedInstance) tinyMCE.selectedInstance = tinyMCE.activeEditor;
795                if(tinyMCE.selectedInstance.contentWindow.focus) tinyMCE.selectedInstance.contentWindow.focus();
796
797                var html = '';
798
799                html += '<object width="'+ width +'" height="' + height + '">';
800                html += '<param name="movie" value="' + youtubeURL + '"></param>';
801                html += '<param name="allowFullScreen" value="true"></param>';
802                html += '<param name="allowscriptaccess" value="always"></param>';
803                html += '<embed src="' + youtubeURL + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="'+ width +'" height="' + height + '"></embed>';
804                html += '</object>';
805
806                tinyMCE.selectedInstance.execCommand("mceInsertContent", false, html);
807                tinyMCE.selectedInstance.execCommand('mceRepaint');
808
809
810                return false;
811
812        }
813}
814
815VimeoForm = Class.extend('ToolbarForm');
816VimeoForm.prototype = {
817        initialize: function() {
818        },
819        destroy: function() {
820                this.ToolbarForm = null;
821                this.onsubmit = null;
822
823        },
824        update_params: function(event) {
825                if(tinyMCE.imgElement) {
826                }
827        },
828        respondToNodeChange: function() {
829                if(tinyMCE.imgElement) {
830                } else {
831                }
832        },
833        selectVimeo: function(vimeo) {
834                if(this.selectedVimeo) {
835                        this.selectedVimeo.setAttribute("class", "");
836                }
837                this.selectedVimeo = vimeo;
838                this.selectedVimeo.setAttribute("class", "selectedVimeo");
839        },
840        handleaction_insertvimeo: function() {
841                var formObj = $('Form_EditorToolbarVimeoForm');
842                var vimeoCode = formObj.elements.VimeoVideoCode.value;
843                var introPortrait = formObj.elements.IntroPortrait.checked?'1':'0';
844                var introTitle = formObj.elements.IntroTitle.checked?'1':'0';
845                var introByline = formObj.elements.IntroByline.checked?'1':'0';
846                var autoplay = formObj.elements.Autoplay.checked?'1':'0';
847                var loop = formObj.elements.Loop.checked?'1':'0';
848                var width = formObj.elements.Width.value;
849                var height = formObj.elements.Height.value;
850                var vimeoURL = 'http://vimeo.com/moogaloop.swf?clip_id='+ vimeoCode +'&amp;server=vimeo.com&amp;show_title=' + introTitle + '&amp;show_byline=' + introByline + '&amp;show_portrait=' + introPortrait + '&amp;color=&amp;fullscreen=1&amp;autoplay=' + autoplay + '&amp;loop=' + loop;
851
852                if(!tinyMCE.selectedInstance) tinyMCE.selectedInstance = tinyMCE.activeEditor;
853                if(tinyMCE.selectedInstance.contentWindow.focus) tinyMCE.selectedInstance.contentWindow.focus();
854
855                var html = '';
856
857                html += '<object width="'+ width +'" height="' + height + '">';
858                html += '<param name="movie" value="' + vimeoURL + '"></param>';
859                html += '<param name="allowFullScreen" value="true"></param>';
860                html += '<param name="allowscriptaccess" value="always"></param>';
861                html += '<embed src="' + vimeoURL + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="'+ width +'" height="' + height + '"></embed>';
862                html += '</object>';
863
864                tinyMCE.selectedInstance.execCommand("mceInsertContent", false, html);
865                tinyMCE.selectedInstance.execCommand('mceRepaint');
866
867
868                return false;
869
870        }
871}
872
755873FlashThumbnail = Class.create();
756874FlashThumbnail.prototype = {
757875        destroy: function() {
758                 this.onclick = null;           
759         },
760        
876                this.onclick = null;
877        },
878
761879        onclick: function(e) {
762880                $('Form_EditorToolbarFlashForm').selectFlash(this);
763881                return false;
764882        },
765        
883
766884        insert: function() {
767885                var formObj = $('Form_EditorToolbarFlashForm');
... ...
771889                var width = formObj.elements.Width.value;
772890                var height = formObj.elements.Height.value;
773                
891
774892                if(!tinyMCE.selectedInstance) tinyMCE.selectedInstance = tinyMCE.activeEditor;
775893                if(tinyMCE.selectedInstance.contentWindow.focus) tinyMCE.selectedInstance.contentWindow.focus();
... ...
777895                if (width == "") width = 100;
778896                if (height == "") height = 100;
779                
897
780898                html = '';
781899                html += '<object width="' + width +'" height="' + height +'" type="application/x-shockwave-flash" data="'+ relativeHref +'">';
782900                html += '<param value="'+ relativeHref +'" name="movie">';
783901                html += '</object>';
784                
902
785903                tinyMCE.selectedInstance.execCommand("mceInsertContent", false, html);
786904                tinyMCE.selectedInstance.execCommand('mceRepaint');
787         //      ed.execCommand('mceInsertContent', false, html, {skip_undo : 1}); 
905        //      ed.execCommand('mceInsertContent', false, html, {skip_undo : 1});
788906                return false;
789907        }
... ...
800918FlashThumbnail.applyTo('#Form_EditorToolbarFlashForm div.thumbnailstrip a');
801919SideFormAction.applyTo('#Form_EditorToolbarFlashForm .Actions input');
920
921YoutubeForm.applyTo('#Form_EditorToolbarYoutubeForm');
922SideFormAction.applyTo('#Form_EditorToolbarYoutubeForm .Actions input');
923
924VimeoForm.applyTo('#Form_EditorToolbarVimeoForm');
925SideFormAction.applyTo('#Form_EditorToolbarVimeoForm .Actions input');
802926
803927/**
... ...
834958                        this.aspectRatio = this.height / this.width;
835959                }
836        
960
837961                this.originalWidth = this.width;
838962                this.originalHeight = this.height;
... ...
844968                return f;
845969        },
846        
970
847971        resizeTo: function(width, height) {
848972                var newWidth = parseInt(height);
... ...
850974                if(isNaN(newWidth)) newWidth = this.width;
851975                if(isNaN(newHeight)) newHeight = this.height;
852                
976
853977                // Constrain to width of the window
854978                if((this.offsetLeft + this.offsetWidth + 20) > this.ownerDoc().offsetWidth)
855979                        newWidth += (this.ownerDoc().offsetWidth - this.offsetLeft - this.offsetWidth - 20);
856        
980
857981                if(this.aspectRatio) {
858982                        // Figure out which dimension we have altered more
859                         var heightChange = this.originalHeight / this.height; 
983                        var heightChange = this.originalHeight / this.height;
860984                        if(heightChange < 1) heightChange = 1/heightChange;
861                        
985
862986                        var widthChange = this.originalWidth / this.width;
863987                        if(widthChange < 1) widthChange = 1/widthChange;
864                        
988
865989                        // Scale by the more constant dimension (so if you edit the height, change width to suit)
866990                        if(widthChange > heightChange)
... ...
873997                this.style.height = newHeight + 'px';
874998                this.width = newWidth;
875                 this.height = newHeight;       
876                
999                this.height = newHeight;
1000
8771001                // Auto-size special image holders
8781002                if(this.parentNode.parentNode.className.match(/(^|\b)specialImage($|\b)/)) {
... ...
9161040                // replace indented text with a <blockquote>
9171041                value = value.replace(/<p [^>]*margin-left[^>]*>([^\n|\n\015|\015\n]*)<\/p>/ig,"<blockquote><p>$1</p></blockquote>");
918        
1042
9191043                // replace VML pixel image references with image tags - experimental
9201044                value = value.replace(/<[a-z0-9]+:imagedata[^>]+src="?([^> "]+)"?[^>]*>/ig,"<img src=\"$1\">");
921                
1045
9221046                // Word comments
923                 value = value.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), ""); 
924                        
925                 // kill class=mso??? and on mouse* tags 
926                 value = value.replace(/([ \f\r\t\n\'\"])class=mso[a-z0-9]+[^ >]+/ig, "$1"); 
927                 value = value.replace(/([ \f\r\t\n\'\"]class=")mso[a-z0-9]+[^ ">]+ /ig, "$1"); 
928                 value = value.replace(/([ \f\r\t\n\'\"])class="mso[a-z0-9]+[^">]+"/ig, "$1"); 
1047                value = value.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");
1048
1049                // kill class=mso??? and on mouse* tags
1050                value = value.replace(/([ \f\r\t\n\'\"])class=mso[a-z0-9]+[^ >]+/ig, "$1");
1051                value = value.replace(/([ \f\r\t\n\'\"]class=")mso[a-z0-9]+[^ ">]+ /ig, "$1");
1052                value = value.replace(/([ \f\r\t\n\'\"])class="mso[a-z0-9]+[^">]+"/ig, "$1");
9291053                value = value.replace(/([ \f\r\t\n\'\"])on[a-z]+=[^ >]+/ig, "$1");
930                 value = value.replace(/ >/ig, ">"); 
931        
1054                value = value.replace(/ >/ig, ">");
1055
9321056                // remove everything that's in a closing tag
933                 value = value.replace(/<(\/[A-Za-z0-9]+)[ \f\r\t\n]+[^>]*>/ig,"<$1>");         
1057                value = value.replace(/<(\/[A-Za-z0-9]+)[ \f\r\t\n]+[^>]*>/ig,"<$1>");
9341058        }
9351059
... ...
9541078                        }
9551079                }
956                
1080
9571081        }
9581082        return value;

sapphire/lang/en_US.php

332332$lang['en_US']['HtmlEditorField']['ANCHORVALUE'] = 'Anchor';
333333$lang['en_US']['HtmlEditorField']['BUTTONINSERTFLASH'] = 'Insert Flash';
334$lang['en_US']['HtmlEditorField']['BUTTONINSERTYOUTUBE'] = 'Insert YouTube';
335$lang['en_US']['HtmlEditorField']['BUTTONINSERTVIMEO'] = 'Insert Vimeo';
334336$lang['en_US']['HtmlEditorField']['BUTTONINSERTIMAGE'] = 'Insert image';
335337$lang['en_US']['HtmlEditorField']['BUTTONINSERTLINK'] = 'Insert link';
... ...
345347$lang['en_US']['HtmlEditorField']['FILE'] = 'File';
346348$lang['en_US']['HtmlEditorField']['FLASH'] = 'Flash';
349$lang['en_US']['HtmlEditorField']['YOUTUBE'] = 'YouTube';
350$lang['en_US']['HtmlEditorField']['VIMEO'] = 'Vimeo';
351$lang['en_US']['HtmlEditorField']['YOUTUBEVIDEOCODE'] = 'YouTube Video Code';
352$lang['en_US']['HtmlEditorField']['VIMEOVIDEOCODE'] = 'Vimeo Video Code';
347353$lang['en_US']['HtmlEditorField']['FOLDER'] = 'Folder';
348354$lang['en_US']['HtmlEditorField']['IMAGE'] = 'Image';
... ...
710716$lang['en_US']['Security']['PASSWORDSENTTEXT'] = 'Thank you! A reset link has been sent to  \'%s\', provided an account exists for this email address.';
711717$lang['en_US']['SecurityAdmin']['GROUPNAME'] = 'Group name';
712 $lang['en_US']['SecurityAdmin']['IPADDRESSESHELP'] = '<p>You can restrict this group to a particular 
718$lang['en_US']['SecurityAdmin']['IPADDRESSESHELP'] = '<p>You can restrict this group to a particular
713719                                                IP address range (one range per line). <br />Ranges can be in any of the following forms: <br />
714720                                                203.96.152.12<br />
... ...
813819$lang['en_US']['SiteTree']['METATITLE'] = 'Title';
814820$lang['en_US']['SiteTree']['MODIFIEDONDRAFT'] = 'Modified on draft site';
815 $lang['en_US']['SiteTree']['NOTEUSEASHOMEPAGE'] = 'Use this page as the \'home page\' for the following domains: 
821$lang['en_US']['SiteTree']['NOTEUSEASHOMEPAGE'] = 'Use this page as the \'home page\' for the following domains:
816822                                                        (separate multiple domains with commas)';
817823$lang['en_US']['SiteTree']['PAGELOCATION'] = 'Page location';