r51520 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r51519‎ | r51520 | r51521 >
Date:22:30, 5 June 2009
Author:tparscal
Status:deferred
Tags:
Comment:
Refactored the javascript code extensively, ported code from edit.css into the new jquery plugin format. Added more features...
Modified paths:
  • /trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.css (modified) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.hooks.php (modified) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.i18n.php (modified) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js (modified) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-down.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-right.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-big.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-olist.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-small.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-subscript.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-superscript.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/format-ulist.png (added) (history)
  • /trunk/extensions/UsabilityInitiative/EditToolbar/images/insert-image.png (deleted) (history)
  • /trunk/extensions/UsabilityInitiative/Resources/jquery.textSelection.js (modified) (history)

Diff [purge]

Index: trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.i18n.php
@@ -15,6 +15,13 @@
1616 'edittoolbar' => 'Editing Toolbar',
1717 'edittoolbar-desc' => 'Edit page toolbar with enhanced usability',
1818 'edittoolbar-preference' => 'Enable enhanced editing toolbar',
 19+ /* Sections */
 20+ 'edittoolbar-section-format' => 'Format',
 21+ 'edittoolbar-section-insert' => 'Insert',
 22+ 'edittoolbar-section-characters' => 'Special Characters',
 23+ 'edittoolbar-section-help' => 'Help',
 24+ 'edittoolbar-section-insert' => 'Insert',
 25+ /* Main Section */
1926 'edittoolbar-format-bold' => 'Bold',
2027 'edittoolbar-format-bold-example' => 'Bold text',
2128 'edittoolbar-format-italic' => 'Italic',
@@ -23,8 +30,29 @@
2431 'edittoolbar-insert-ilink-example' => 'Link title',
2532 'edittoolbar-insert-xlink' => 'External link (remember http:// prefix)',
2633 'edittoolbar-insert-xlink-example' => 'http://www.example.com link title',
27 - 'edittoolbar-insert-image' => 'Embedded file',
28 - 'edittoolbar-insert-image-example' => 'File:Example.jpg',
 34+ 'edittoolbar-insert-file' => 'Embedded file',
 35+ 'edittoolbar-insert-file-pre' => '$1File:',
 36+ 'edittoolbar-insert-file-example' => 'Example.jpg',
2937 'edittoolbar-insert-reference' => 'Insert a reference',
3038 'edittoolbar-insert-reference-example' => 'Insert footnote text here',
 39+ /* Formatting Section */
 40+ 'edittoolbar-format-ulist' => 'Bulleted list',
 41+ 'edittoolbar-format-ulist-example' => 'Bulleted list item',
 42+ 'edittoolbar-format-olist' => 'Numbered list',
 43+ 'edittoolbar-format-olist-example' => 'Numbered list item',
 44+ 'edittoolbar-format-heading' => 'Heading',
 45+ 'edittoolbar-format-heading-1' => 'Level 1',
 46+ 'edittoolbar-format-heading-2' => 'Level 2',
 47+ 'edittoolbar-format-heading-3' => 'Level 3',
 48+ 'edittoolbar-format-heading-4' => 'Level 4',
 49+ 'edittoolbar-format-heading-5' => 'Level 5',
 50+ 'edittoolbar-format-heading-example' => 'Heading text',
 51+ 'edittoolbar-format-superscript' => 'Superscript',
 52+ 'edittoolbar-format-superscript-example' => 'Superscript text',
 53+ 'edittoolbar-format-subscript' => 'Subscript',
 54+ 'edittoolbar-format-subscript-example' => 'Subscript text',
 55+ 'edittoolbar-format-big' => 'Big',
 56+ 'edittoolbar-format-big-example' => 'Big text',
 57+ 'edittoolbar-format-small' => 'Small',
 58+ 'edittoolbar-format-small-example' => 'Small text',
3159 );
Index: trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.css
@@ -2,26 +2,65 @@
33
44 div#edittoolbar {
55 width: 100%;
6 - height: 32px;
76 background-color: #EEEEEE;
87 }
9 -
10 -div#edittoolbar > div.group {
 8+div#edittoolbar div.tabs,
 9+div#edittoolbar div.group {
1110 float: left;
1211 height: 26px;
1312 margin: 3px;
1413 padding-left: 3px;
1514 border-left: solid 1px #DDDDDD;
1615 }
17 -div#edittoolbar > div.group:first-child {
 16+div#edittoolbar div.group:first-child {
1817 border-left: none;
1918 }
20 -
21 -div#edittoolbar > div.group > img {
 19+div#edittoolbar div.sections {
2220 float: left;
 21+ width: 100%;
 22+ clear: both;
 23+}
 24+div#edittoolbar div.sections > div.section {
 25+ display: none;
 26+ float: left;
 27+ width: 100%;
 28+ border-top: solid 1px #DDDDDD;
 29+}
 30+div#edittoolbar div.group > img {
 31+ float: left;
2332 border: 0px;
2433 height: 22px;
2534 width: 22px;
2635 margin: 2px;
2736 cursor: pointer;
 37+}
 38+div#edittoolbar div.group > select {
 39+ float: left;
 40+ margin: 2px;
 41+ height: 22px;
 42+ cursor: pointer;
 43+}
 44+div#edittoolbar div.tabs > div.tab {
 45+ float: left;
 46+ line-height: 26px;
 47+}
 48+div#edittoolbar div.tabs > div.tab > a,
 49+div#edittoolbar div.tabs > div.tab > a:visited {
 50+ padding-left: 18px;
 51+ padding-right: 12px;
 52+ display: block;
 53+ height: 26px;
 54+ cursor: pointer;
 55+ color: #00528C;
 56+ background-image: url(images/arrow-right.png);
 57+ background-position: left center;
 58+ background-repeat: no-repeat;
 59+}
 60+div#edittoolbar div.tabs > div.tab > a.current,
 61+div#edittoolbar div.tabs > div.tab > a.current:visited {
 62+ color: #333333;
 63+ background-image: url(images/arrow-down.png);
 64+}
 65+div#edittoolbar div.tabs > div.tab > a.current:hover {
 66+ text-decoration: none;
2867 }
\ No newline at end of file
Index: trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.hooks.php
@@ -24,43 +24,67 @@
2525 if ( $wgUser->getOption( 'usebetatoolbar' ) ) {
2626 $toolbar = '<div id="edittoolbar"></div>';
2727 }
 28+
2829 // List of messages to be sent to the client for use in the toolbar
29 - // all of which will get a prefix of "toolbar"
3030 $messages = array(
31 - 'format-bold',
32 - 'format-bold-example',
33 - 'format-italic',
34 - 'format-italic-example',
35 - 'insert-ilink',
36 - 'insert-ilink-example',
37 - 'insert-xlink',
38 - 'insert-xlink-example',
39 - 'insert-image',
40 - 'insert-image-example',
41 - 'insert-reference',
42 - 'insert-reference-example',
 31+ /* Sections */
 32+ 'edittoolbar-section-format',
 33+ 'edittoolbar-section-insert',
 34+ 'edittoolbar-section-characters',
 35+ 'edittoolbar-section-help',
 36+ /* Main Section */
 37+ 'edittoolbar-format-bold',
 38+ 'edittoolbar-format-bold-example',
 39+ 'edittoolbar-format-italic',
 40+ 'edittoolbar-format-italic-example',
 41+ 'edittoolbar-insert-ilink',
 42+ 'edittoolbar-insert-ilink-example',
 43+ 'edittoolbar-insert-xlink',
 44+ 'edittoolbar-insert-xlink-example',
 45+ 'edittoolbar-insert-file',
 46+ 'edittoolbar-insert-file-pre',
 47+ 'edittoolbar-insert-file-example',
 48+ 'edittoolbar-insert-reference',
 49+ 'edittoolbar-insert-reference-example',
 50+ /* Formatting Section */
 51+ 'edittoolbar-format-ulist',
 52+ 'edittoolbar-format-ulist-example',
 53+ 'edittoolbar-format-olist',
 54+ 'edittoolbar-format-olist-example',
 55+ 'edittoolbar-format-heading',
 56+ 'edittoolbar-format-heading-1',
 57+ 'edittoolbar-format-heading-2',
 58+ 'edittoolbar-format-heading-3',
 59+ 'edittoolbar-format-heading-4',
 60+ 'edittoolbar-format-heading-5',
 61+ 'edittoolbar-format-heading-example',
 62+ 'edittoolbar-format-superscript',
 63+ 'edittoolbar-format-superscript-example',
 64+ 'edittoolbar-format-subscript',
 65+ 'edittoolbar-format-subscript-example',
 66+ 'edittoolbar-format-big',
 67+ 'edittoolbar-format-big-example',
 68+ 'edittoolbar-format-small',
 69+ 'edittoolbar-format-small-example',
4370 );
4471 // Transforms messages into javascript object members
4572 foreach ( $messages as $i => $message ) {
46 - $escapedMessageValue = Xml::escapeJsString(
47 - wfMsg( 'edittoolbar-' . $message )
48 - );
 73+ $escapedMessageValue = Xml::escapeJsString( wfMsg( $message ) );
4974 $escapedMessageKey = Xml::escapeJsString( $message );
5075 $messages[$i] = "'{$escapedMessageKey}':'{$escapedMessageValue}'";
5176 }
5277 // Converts array of object members to a comma delimited list
5378 $messagesList = implode( ',', $messages );
5479 // Encapsulates list in javascript code to set them durring load
55 - $messagesJs = "editToolbar.setMessages({{$messagesList}});";
 80+ $messagesJs = "loadGM({{$messagesList}});";
5681 // Appends javascript message setting code
5782 $toolbar .= Xml::element(
5883 'script', array( 'type' => $wgJsMimeType ), $messagesJs
5984 );
60 -
6185 // Continue
6286 return true;
6387 }
64 -
 88+
6589 /**
6690 * GetPreferences hook
6791 * Add toolbar related items to the preferences
Index: trunk/extensions/UsabilityInitiative/EditToolbar/EditToolbar.js
@@ -1,210 +1,471 @@
22 /* JavaScript for EditToolbar extension */
33
44 /**
5 - * Prototype for global editToolbar object
6 - * @param {String} toolbarSelector jQuery compatible selector of toolbar div
 5+ * This is designed to be directly compatible with (and is essentially taken
 6+ * directly from) the mv_embed code for bringing internationalized messages into
 7+ * the JavaScript space. As such, if we get to the point of merging that stuff
 8+ * into the main branch this code will be uneeded and probably cause issues.
79 */
8 -function EditToolbar( toolbarSelector ) {
9 -
10 - /* Private Members */
11 -
12 - // Reference to object's self
13 - var self = this;
14 - // Reference to DIV container object (set on initialize)
15 - var toolbarDiv = null;
16 - // Sections (main and subs), groups and buttons
17 - var tools = { main: {}, subs: {} };
18 - // Internationalized user interface messages
19 - var messages = {};
20 -
21 - /* Functions */
22 -
23 - /**
24 - * Initializes the toolbar user interface
25 - */
26 - this.initialize = function() {
27 - // Path to images (THIS WILL HAVE TO CHANGE IF YOU MOVE THIS INTO CORE)
28 - var imagePath = wgScriptPath +
29 - '/extensions/UsabilityInitiative/EditToolbar/images/';
30 - // Gets object handle for container
31 - toolbarDiv = $( toolbarSelector );
32 - // Checks if the toolbar div existed
33 - if ( toolbarDiv ) {
 10+// Creates global message object if not already in existence
 11+if ( !gMsg ) var gMsg = {};
 12+/**
 13+ * Caches a list of messages for later retieval
 14+ * @param {Object} msgSet Hash of key:value pairs of messages to cache
 15+ */
 16+function loadGM( msgSet ){
 17+ for ( var i in msgSet ){
 18+ gMsg[ i ] = msgSet[i];
 19+ }
 20+}
 21+/**
 22+ * Retieves a message from the global message cache, performing on-the-fly
 23+ * replacements using MediaWiki message syntax ($1, $2, etc.)
 24+ * @param {String} key Name of message as it is in MediaWiki
 25+ * @param {Array} args Array of replacment arguments
 26+ */
 27+function gM( key, args ) {
 28+ var ms = '';
 29+ if ( key in gMsg ) {
 30+ ms = gMsg[ key ];
 31+ if ( typeof args == 'object' || typeof args == 'array' ) {
 32+ for ( var v in args ){
 33+ var rep = '\$'+ ( parseInt(v) + 1 );
 34+ ms = ms.replace( rep, args[v]);
 35+ }
 36+ } else if ( typeof args =='string' || typeof args =='number' ) {
 37+ ms = ms.replace( /\$1/, args );
 38+ }
 39+ return ms;
 40+ } else {
 41+ return '[' + key + ']';
 42+ }
 43+}
 44+/**
 45+ * This is the toolbar plugin, which can be used like
 46+ * $( 'div#edittoolbar' ).toolbar( '#wpTextbox1', tools );
 47+ * Where tools is an array of objects which describe each tool (see below for
 48+ * specific examples) (THIS NEEDS BETTER DOCUMENTATION WHEN I HAVE TIME)
 49+ */
 50+(function($){
 51+ $.fn.extend({
 52+ /**
 53+ *
 54+ * @param {Object} textbox
 55+ * @param {Object} tools
 56+ */
 57+ toolbar: function( textbox, tools ) {
 58+ return this.each(function() {
 59+ // Checks if main section is in the structure
 60+ if ( 'main' in tools ) {
 61+ // Adds main section to toolbar
 62+ $(this).addToolbarSection( tools.main, textbox );
 63+ }
 64+ // Appends additional section tabs
 65+ var tabDiv = $( '<div />' )
 66+ .attr( 'class', 'tabs' )
 67+ .appendTo( $(this) );
 68+ // Appends additional section
 69+ var sectionsDiv = $( '<div />' )
 70+ .attr( 'class', 'sections' )
 71+ .appendTo( $(this) );
 72+ // Appends float-clearing div
 73+ $(this).append( $( '<div style="clear:both"></div>' ) );
 74+ // Loops over each section
 75+ for ( section in tools ) {
 76+ // Skips over main (was handled as special case already)
 77+ if ( section == 'main' ) {
 78+ continue;
 79+ }
 80+ // Appends section content
 81+ var sectionDiv = $( '<div />')
 82+ .attr( { 'class': 'section', 'id': $(this).attr( 'id' ) + '-section-' + section } )
 83+ .appendTo( sectionsDiv );
 84+ // Appends toolbar to section div
 85+ sectionDiv.addToolbarSection( tools[section], textbox )
 86+ // Appends section tab
 87+ tabDiv.append(
 88+ $( '<div />' )
 89+ .attr( 'class', 'tab' )
 90+ .append(
 91+ $( '<a />' )
 92+ .text( tools[section].label || gM( tools[section].labelMsg ) )
 93+ .attr( { 'href': '#', 'rel': section } )
 94+ .data( 'sectionDiv', sectionDiv )
 95+ .click( function() {
 96+ $(this).blur();
 97+ var show = ( $(this).data( 'sectionDiv' ).css( 'display' ) == 'none' );
 98+ $(this).data( 'sectionDiv' ).parent().children().hide();
 99+ $(this).parent().parent().find( 'a' ).removeClass( 'current' );
 100+ if ( show ) {
 101+ $(this).data( 'sectionDiv' ).show();
 102+ $(this).addClass( 'current' );
 103+ }
 104+ return false;
 105+ })
 106+ )
 107+ );
 108+ }
 109+ });
 110+ },
 111+ /**
 112+ * Adds a toolbar section to a containing div
 113+ * @param {Object} section Section data to build toolbar from
 114+ */
 115+ addToolbarSection: function( section, textbox ) {
 116+ // Path to images (THIS WILL HAVE TO CHANGE IF YOU MOVE THIS INTO CORE)
 117+ var imagePath = wgScriptPath +
 118+ '/extensions/UsabilityInitiative/EditToolbar/images/';
 119+ // Check for groups
 120+ if ( !( 'groups' in section ) ) {
 121+ return;
 122+ }
34123 // Loops over each main group
35 - for ( group in tools.main ) {
36 - // Creates tool group
37 - var groupDiv = $( '<div class="group"></div>' );
38 - // Appends group to toolbar
39 - groupDiv.appendTo( toolbarDiv );
40 - for ( tool in tools.main[group] ) {
41 - // Creates tool
42 - var toolImg = $( '<img />' );
43 - // Appends tool to group
44 - toolImg.appendTo( groupDiv );
45 - // Customizes the tool
46 - toolImg.attr({
47 - src: imagePath + tools.main[group][tool].icon,
48 - alt: messages[group + '-' + tool],
49 - title: messages[group + '-' + tool]
50 - });
51 - // Sets button action
52 - toolImg.click( tools.main[group][tool].action );
 124+ for ( group in section.groups ) {
 125+ // Appends group
 126+ var groupDiv = $( '<div />' )
 127+ .attr( 'class', 'group' )
 128+ .appendTo( $(this) );
 129+ // Creates generic action
 130+ var action = function() {
 131+ $(this).useTool(
 132+ $(this).data( 'context' ).tool,
 133+ $(this).data( 'context' ).textbox
 134+ );
 135+ };
 136+ // Loops over each tool
 137+ for ( tool in section.groups[group] ) {
 138+ // Creates context for use in action
 139+ var context = { 'tool': section.groups[group][tool], 'textbox': textbox };
 140+ // Creates the label of the tool
 141+ var label = ( section.groups[group][tool].label || gM( section.groups[group][tool].labelMsg ) );
 142+ switch ( section.groups[group][tool].type ) {
 143+ case 'button':
 144+ // Appends button
 145+ groupDiv.append(
 146+ $( '<img />' )
 147+ .attr( {
 148+ src: imagePath + section.groups[group][tool].icon,
 149+ alt: label,
 150+ title: label
 151+ } )
 152+ .data( 'context', context )
 153+ .click( action )
 154+ );
 155+ break;
 156+ case 'select':
 157+ // Appends select
 158+ var selectDiv = $( '<select />' )
 159+ .data( 'context', context )
 160+ .change( action )
 161+ .append(
 162+ $( '<option />' ) .text( label )
 163+ )
 164+ .appendTo( groupDiv );
 165+ // Appends options
 166+ for ( item in section.groups[group][tool].list ) {
 167+ selectDiv.append(
 168+ $( '<option/>' )
 169+ .text( ( section.groups[group][tool].list[item].label || gM( section.groups[group][tool].list[item].labelMsg ) ) )
 170+ .attr( 'value', item )
 171+ );
 172+ }
 173+ break;
 174+ default: break;
 175+ }
53176 }
54177 }
55 - }
56 - }
57 -
58 - /**
59 - * Adds a tool to the toolbar
60 - * @param {String} section ID of section to add tool to
61 - * @param {String} group ID of group to add tool to
62 - * @param {String} tool ID of tool to add
63 - * @param {Object} configuration Object of configuration for tool
64 - */
65 - this.addTool = function( section, group, tool, configuration ) {
66 - // Checks if the section is valid
67 - if ( section in tools ) {
68 - // Checks if the group doesn't exist in the section
69 - if ( !( group in tools[section] ) ) {
70 - // Adds the group to the section
71 - tools[section][group] = {};
 178+ },
 179+ /**
 180+ * Performs action on a textbox using a tool
 181+ * @param {Object} tool
 182+ * @param {Object} textbox
 183+ */
 184+ useTool: function( tool, textbox ) {
 185+ function performAction( action, textbox ) {
 186+ switch ( action.type) {
 187+ case 'encapsulate':
 188+ var parts = { 'pre': '', 'peri': '', 'post': '' };
 189+ for ( part in parts ) {
 190+ if ( part + 'Msg' in action.options ) {
 191+ parts[part] = gM( action.options[part + 'Msg'], ( action.options[part] || null ) );
 192+ } else {
 193+ parts[part] = ( action.options[part] || '' )
 194+ }
 195+ }
 196+ textbox.encapsulateSelection( parts.pre, parts.peri, parts.post );
 197+ break;
 198+ default: break;
 199+ }
72200 }
73 - // Checks if the tool doesn't exist in the group
74 - if ( !( tool in tools[section][group] ) ) {
75 - // Adds tool and configuration to group
76 - tools[section][group][tool] = configuration;
 201+ switch ( tool.type ) {
 202+ case 'button':
 203+ performAction( tool.action, textbox );
 204+ break;
 205+ case 'select':
 206+ if ( $(this).val() in tool.list ) {
 207+ performAction( tool.list[$(this).val()].action, textbox );
 208+ }
 209+ $(this).find(":selected").attr( 'selected', false );
 210+ $(this).find(":first").attr( 'selected', true );
 211+ break;
 212+ default: break;
77213 }
78214 }
79 - }
80 -
81 - /**
82 - * Sets several user interface messages
83 - * @param {Object} messageList List of key/value pairs of messages
84 - */
85 - this.setMessages = function( messageList ) {
86 - for ( messageItem in messageList ) {
87 - messages[messageItem] = messageList[messageItem];
88 - }
89 - }
90 -
91 - /**
92 - * Sets a user interface message
93 - * @param {String} key Key of message
94 - * @param {String} value Value of message
95 - */
96 - this.setMessage = function( key, value ) {
97 - messages[key] = value;
98 - }
99 -
100 - /**
101 - * Gets a user interface message
102 - * @param {String} key Key of message
103 - */
104 - this.getMessage = function( key ) {
105 - if ( key in messages ) {
106 - return messages[key];
107 - } else {
108 - return key;
109 - }
110 - }
111 -
112 - /**
113 - * Performs the action associated with a tool
114 - * @param {String} section ID of section of tool to use
115 - * @param {String} group ID of group of tool to use
116 - * @param {String} tool ID of tool to use
117 - */
118 - this.useTool = function( section, group, tool ) {
119 - // Checks if the tool exists
120 - if ( tool in tools[section][group] ) {
121 - // Adds tool and configuration to group
122 - tools[section][group][tool].action();
123 - }
124 - }
125 -}
126 -
127 -// Creates global toolbar object
128 -var editToolbar = new EditToolbar( '#edittoolbar' );
129 -// Executes function when document is ready
 215+ });
 216+})(jQuery);
 217+/**
 218+ * This initializes an edit toolbar on div#edittoolbar and connects it to
 219+ * textarea#wpTextbox1 - which needs to be done after the document is loaded.
 220+ */
130221 $( document ).ready( function() {
131 - // Initializes edit toolbar
132 - editToolbar.initialize();
 222+ $( 'div#edittoolbar' ).toolbar( $( 'textarea#wpTextbox1' ), editToolbarConfiguration );
133223 });
134 -
135224 /**
136 - * This is a problem for internationalization - so clearly this will be moved
137 - * or restructured at some point.
 225+ * This enormous structure is what makes the toolbar what it is. Customization
 226+ * of this structure prior to the document being ready and thus executing the
 227+ * initialization procedure for the toolbar will result in a custom toolbar.
138228 */
139 -// Adds tools to toolbar
140 -editToolbar.addTool(
141 - 'main', 'format', 'bold',
142 - {
143 - icon: 'format-bold.png',
144 - action: function() {
145 - $( '#wpTextbox1' ).encapsulateSelection(
146 - "'''", null, editToolbar.getMessage( 'format-bold-example' )
147 - );
148 - return false;
 229+var editToolbarConfiguration = {
 230+ // Main section
 231+ 'main': {
 232+ groups: {
 233+ 'format': {
 234+ 'bold': {
 235+ labelMsg: 'edittoolbar-format-bold',
 236+ type: 'button',
 237+ icon: 'format-bold.png',
 238+ action: {
 239+ type: 'encapsulate',
 240+ options: {
 241+ pre: "'''",
 242+ periMsg: 'edittoolbar-format-bold-example',
 243+ post: "'''"
 244+ }
 245+ }
 246+ },
 247+ 'italic': {
 248+ section: 'main',
 249+ group: 'format',
 250+ id: 'italic',
 251+ labelMsg: 'edittoolbar-format-italic',
 252+ type: 'button',
 253+ icon: 'format-italic.png',
 254+ action: {
 255+ type: 'encapsulate',
 256+ options: {
 257+ pre: "''",
 258+ periMsg: 'edittoolbar-format-italic-example',
 259+ post: "''"
 260+ }
 261+ }
 262+ }
 263+ },
 264+ 'insert': {
 265+ 'xlink': {
 266+ labelMsg: 'edittoolbar-insert-xlink',
 267+ type: 'button',
 268+ icon: 'insert-xlink.png',
 269+ action: {
 270+ type: 'encapsulate',
 271+ options: {
 272+ pre: "[",
 273+ periMsg: 'edittoolbar-insert-xlink-example',
 274+ post: "]"
 275+ }
 276+ }
 277+ },
 278+ 'ilink': {
 279+ labelMsg: 'edittoolbar-insert-ilink',
 280+ type: 'button',
 281+ icon: 'insert-ilink.png',
 282+ action: {
 283+ type: 'encapsulate',
 284+ options: {
 285+ pre: "[[",
 286+ periMsg: 'edittoolbar-insert-ilink-example',
 287+ post: "]]"
 288+ }
 289+ }
 290+ },
 291+ 'file': {
 292+ labelMsg: 'edittoolbar-insert-file',
 293+ type: 'button',
 294+ icon: 'insert-file.png',
 295+ action: {
 296+ type: 'encapsulate',
 297+ options: {
 298+ pre: "[[",
 299+ preMsg: 'edittoolbar-insert-file-pre',
 300+ periMsg: 'edittoolbar-insert-file-example',
 301+ post: "]]"
 302+ }
 303+ }
 304+ },
 305+ 'reference': {
 306+ labelMsg: 'edittoolbar-insert-reference',
 307+ type: 'button',
 308+ icon: 'insert-reference.png',
 309+ action: {
 310+ type: 'encapsulate',
 311+ options: {
 312+ pre: "<ref>",
 313+ periMsg: 'edittoolbar-insert-reference-example',
 314+ post: "</ref>"
 315+ }
 316+ }
 317+ }
 318+ }
149319 }
150 - }
151 -);
152 -editToolbar.addTool(
153 - 'main', 'format', 'italic',
154 - {
155 - icon: 'format-italic.png',
156 - action: function() {
157 - $( '#wpTextbox1' ).encapsulateSelection(
158 - "''", null, editToolbar.getMessage( 'format-italic-example' )
159 - );
160 - return false;
 320+ },
 321+ // Format section
 322+ 'format': {
 323+ labelMsg: 'edittoolbar-section-format',
 324+ groups: {
 325+ 'list': {
 326+ 'ulist': {
 327+ labelMsg: 'edittoolbar-format-ulist',
 328+ type: 'button',
 329+ icon: 'format-ulist.png',
 330+ action: {
 331+ type: 'encapsulate',
 332+ options: {
 333+ pre: "* ",
 334+ periMsg: 'edittoolbar-format-ulist-example',
 335+ post: ""
 336+ }
 337+ }
 338+ },
 339+ 'olist': {
 340+ labelMsg: 'edittoolbar-format-olist',
 341+ type: 'button',
 342+ icon: 'format-olist.png',
 343+ action: {
 344+ type: 'encapsulate',
 345+ options: {
 346+ pre: "# ",
 347+ periMsg: 'edittoolbar-format-olist-example',
 348+ post: ""
 349+ }
 350+ }
 351+ }
 352+ },
 353+ 'heading': {
 354+ 'heading': {
 355+ labelMsg: 'edittoolbar-format-heading',
 356+ type: 'select',
 357+ list: {
 358+ 'heading-1' : {
 359+ labelMsg: 'edittoolbar-format-heading-1',
 360+ action: {
 361+ type: 'encapsulate',
 362+ options: {
 363+ pre: "=",
 364+ periMsg: 'edittoolbar-format-heading-example',
 365+ post: "="
 366+ }
 367+ }
 368+ },
 369+ 'heading-2' : {
 370+ labelMsg: 'edittoolbar-format-heading-2',
 371+ action: {
 372+ type: 'encapsulate',
 373+ options: {
 374+ pre: "==",
 375+ periMsg: 'edittoolbar-format-heading-example',
 376+ post: "=="
 377+ }
 378+ }
 379+ },
 380+ 'heading-3' : {
 381+ labelMsg: 'edittoolbar-format-heading-3',
 382+ action: {
 383+ type: 'encapsulate',
 384+ options: {
 385+ pre: "===",
 386+ periMsg: 'edittoolbar-format-heading-example',
 387+ post: "==="
 388+ }
 389+ }
 390+ },
 391+ 'heading-4' : {
 392+ labelMsg: 'edittoolbar-format-heading-4',
 393+ action: {
 394+ type: 'encapsulate',
 395+ options: {
 396+ pre: "====",
 397+ periMsg: 'edittoolbar-format-heading-example',
 398+ post: "===="
 399+ }
 400+ }
 401+ },
 402+ 'heading-5' : {
 403+ labelMsg: 'edittoolbar-format-heading-5',
 404+ action: {
 405+ type: 'encapsulate',
 406+ options: {
 407+ pre: "=====",
 408+ periMsg: 'edittoolbar-format-heading-example',
 409+ post: "====="
 410+ }
 411+ }
 412+ }
 413+ }
 414+ }
 415+ },
 416+ 'size': {
 417+ 'superscript': {
 418+ labelMsg: 'edittoolbar-format-superscript',
 419+ type: 'button',
 420+ icon: 'format-superscript.png',
 421+ action: {
 422+ type: 'encapsulate',
 423+ options: {
 424+ pre: "<super>",
 425+ periMsg: 'edittoolbar-format-superscript-example',
 426+ post: "</super>"
 427+ }
 428+ }
 429+ },
 430+ 'subscript': {
 431+ labelMsg: 'edittoolbar-format-subscript',
 432+ type: 'button',
 433+ icon: 'format-subscript.png',
 434+ action: {
 435+ type: 'encapsulate',
 436+ options: {
 437+ pre: "<sub>",
 438+ periMsg: 'edittoolbar-format-subscript-example',
 439+ post: "</sub>"
 440+ }
 441+ }
 442+ },
 443+ 'big': {
 444+ labelMsg: 'edittoolbar-format-big',
 445+ type: 'button',
 446+ icon: 'format-big.png',
 447+ action: {
 448+ type: 'encapsulate',
 449+ options: {
 450+ pre: "<big>",
 451+ periMsg: 'edittoolbar-format-big-example',
 452+ post: "</big>"
 453+ }
 454+ }
 455+ },
 456+ 'small': {
 457+ labelMsg: 'edittoolbar-format-small',
 458+ type: 'button',
 459+ icon: 'format-small.png',
 460+ action: {
 461+ type: 'encapsulate',
 462+ options: {
 463+ pre: "<small>",
 464+ periMsg: 'edittoolbar-format-small-example',
 465+ post: "</small>"
 466+ }
 467+ }
 468+ }
 469+ }
161470 }
162471 }
163 -);
164 -editToolbar.addTool(
165 - 'main', 'insert', 'ilink',
166 - {
167 - icon: 'insert-ilink.png',
168 - action: function() {
169 - $( '#wpTextbox1' ).encapsulateSelection(
170 - '[[', ']]', editToolbar.getMessage( 'insert-ilink-example' )
171 - );
172 - return false;
173 - }
174 - }
175 -);
176 -editToolbar.addTool(
177 - 'main', 'insert', 'xlink',
178 - {
179 - icon: 'insert-xlink.png',
180 - action: function() {
181 - $( '#wpTextbox1' ).encapsulateSelection(
182 - '[', ']', editToolbar.getMessage( 'insert-xlink-example' )
183 - );
184 - return false;
185 - }
186 - }
187 -);
188 -editToolbar.addTool(
189 - 'main', 'insert', 'image',
190 - {
191 - icon: 'insert-image.png',
192 - action: function() {
193 - $( '#wpTextbox1' ).encapsulateSelection(
194 - '[[File:', ']]', editToolbar.getMessage( 'insert-image-example' )
195 - );
196 - return false;
197 - }
198 - }
199 -);
200 -editToolbar.addTool(
201 - 'main', 'insert', 'reference',
202 - {
203 - icon: 'insert-reference.png',
204 - action: function() {
205 - $( '#wpTextbox1' ).encapsulateSelection(
206 - '<ref>', '</ref>', editToolbar.getMessage( 'insert-reference-example' )
207 - );
208 - return false;
209 - }
210 - }
211 -);
\ No newline at end of file
 472+};
\ No newline at end of file
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/insert-image.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-superscript.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-superscript.png
___________________________________________________________________
Added: svn:mime-type
212473 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-small.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-small.png
___________________________________________________________________
Added: svn:mime-type
213474 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-down.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-down.png
___________________________________________________________________
Added: svn:mime-type
214475 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-olist.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-olist.png
___________________________________________________________________
Added: svn:mime-type
215476 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-subscript.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-subscript.png
___________________________________________________________________
Added: svn:mime-type
216477 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-right.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/arrow-right.png
___________________________________________________________________
Added: svn:mime-type
217478 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-ulist.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-ulist.png
___________________________________________________________________
Added: svn:mime-type
218479 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-big.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/UsabilityInitiative/EditToolbar/images/format-big.png
___________________________________________________________________
Added: svn:mime-type
219480 + application/octet-stream
Index: trunk/extensions/UsabilityInitiative/Resources/jquery.textSelection.js
@@ -1,54 +1,82 @@
22 /*
3 - * Functions getSelection and replaceSelection based on:
4 - * (c) 2006 Alex Brem <alex@0xab.cd> - http://blog.0xab.cd
5 - * All other code:
6 - * (c) 2009 Wikimedia Foundation (GPLv2) - http://www.wikimedia.org
 3+ * Ported from skins/common/edit.js by Trevor Parscal
 4+ * (c) 2009 Wikimedia Foundation (GPLv2) - http://www.wikimedia.org
75 */
86 (function($) {
97 $.fn.extend({
10 - getSelection: function() {
 8+ encapsulateSelection: function( pre, peri, post ) {
119 var e = this.jquery ? this[0] : this;
12 - if ( 'selectionStart' in e ) {
13 - /* Mozilla / DOM 3.0 */
14 - var l = e.selectionEnd - e.selectionStart;
15 - return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr( e.selectionStart, l ) };
16 - } else if ( document.selection ) {
17 - /* Internet Explorer */
 10+ /**
 11+ * CLEAN THIS UP PLEASE!
 12+ */
 13+ var selText;
 14+ var isSample = false;
 15+ if (document.selection && document.selection.createRange) { // IE/Opera
 16+
 17+ //save window scroll position
 18+ if (document.documentElement && document.documentElement.scrollTop)
 19+ var winScroll = document.documentElement.scrollTop
 20+ else if (document.body)
 21+ var winScroll = document.body.scrollTop;
 22+ //get current selection
1823 e.focus();
19 - var r = document.selection.createRange();
20 - if (r == null) {
21 - return { start: 0, end: e.value.length, length: 0, text: null }
 24+ var range = document.selection.createRange();
 25+ selText = range.text;
 26+ //insert tags
 27+ checkSelectedText();
 28+ range.text = pre + selText + post;
 29+ //mark sample text as selected
 30+ if (isSample && range.moveStart) {
 31+ if (window.opera)
 32+ post = post.replace(/\n/g,'');
 33+ range.moveStart('character', - post.length - selText.length);
 34+ range.moveEnd('character', - post.length);
2235 }
23 - var re = e.createTextRange();
24 - var rc = re.duplicate();
25 - re.moveToBookmark( r.getBookmark() );
26 - rc.setEndPoint( 'EndToStart', re );
27 - return { start: rc.text.length, end: rc.text.length + r.text.length, length: r.text.length, text: r.text };
28 - } else {
29 - /* Browser not supported */
30 - return { start: 0, end: e.value.length, length: 0, text: null };
31 - }
32 - },
33 - replaceSelection: function() {
34 - var e = this.jquery ? this[0] : this;
35 - var text = arguments[0] || '';
36 - if ( 'selectionStart' in e ) {
37 - /* Mozilla / DOM 3.0 */
38 - e.value = e.value.substr( 0, e.selectionStart ) + text + e.value.substr( e.selectionEnd, e.value.length );
39 - } else if ( document.selection ) {
40 - /* Internet Explorer */
 36+ range.select();
 37+ //restore window scroll position
 38+ if (document.documentElement && document.documentElement.scrollTop)
 39+ document.documentElement.scrollTop = winScroll
 40+ else if (document.body)
 41+ document.body.scrollTop = winScroll;
 42+
 43+ } else if (e.selectionStart || e.selectionStart == '0') { // Mozilla
 44+
 45+ //save textarea scroll position
 46+ var textScroll = e.scrollTop;
 47+ //get current selection
4148 e.focus();
42 - document.selection.createRange().text = text;
43 - } else {
44 - /* Browser not supported */
45 - e.value += text;
 49+ var startPos = e.selectionStart;
 50+ var endPos = e.selectionEnd;
 51+ selText = e.value.substring(startPos, endPos);
 52+ //insert tags
 53+ checkSelectedText();
 54+ e.value = e.value.substring(0, startPos)
 55+ + pre + selText + post
 56+ + e.value.substring(endPos, e.value.length);
 57+ //set new selection
 58+ if (isSample) {
 59+ e.selectionStart = startPos + pre.length;
 60+ e.selectionEnd = startPos + pre.length + selText.length;
 61+ } else {
 62+ e.selectionStart = startPos + pre.length + selText.length + post.length;
 63+ e.selectionEnd = e.selectionStart;
 64+ }
 65+ //restore textarea scroll position
 66+ e.scrollTop = textScroll;
4667 }
47 - return this;
48 - },
49 - encapsulateSelection: function( pre, post, insert ) {
50 - var obj = $( this );
51 - obj.replaceSelection( ( pre || '' ) + ( obj.getSelection().text || insert ) + ( post || pre || '' ) );
52 - return this;
53 - }
 68+ // Checks if the selected text is the same as the insert text
 69+ function checkSelectedText(){
 70+ if (!selText) {
 71+ selText = peri;
 72+ isSample = true;
 73+ } else if (selText.charAt(selText.length - 1) == ' ') { //exclude ending space char
 74+ selText = selText.substring(0, selText.length - 1);
 75+ post += ' '
 76+ }
 77+ }
 78+ /**
 79+ * /CLEAN THIS UP PLEASE!
 80+ */
 81+ }
5482 });
55 -})(jQuery);
\ No newline at end of file
 83+})(jQuery);

Status & tagging log