diff --git a/src/formats/bbcode.js b/src/formats/bbcode.js index 277e13121..83f78677f 100644 --- a/src/formats/bbcode.js +++ b/src/formats/bbcode.js @@ -137,26 +137,56 @@ }, bulletlist: { txtExec: function (caller, selected) { + var editor = this; var content = ''; - each(selected.split(/\r?\n/), function () { - content += (content ? '\n' : '') + - '[li]' + this + '[/li]'; - }); + getEditorCommand('bulletlist')._dropDown( + editor, + caller, + function (listType) { + selected.split(/\r?\n/).forEach(function (item) { + content += (content ? '\n' : '') + + '[li]' + item + '[/li]'; + }); - this.insertText('[ul]\n' + content + '\n[/ul]'); + if (listType === 'disc') { + editor.insertText( + '[ul]\n' + content + '\n[/ul]' + ); + } else { + editor.insertText( + '[ul=' + listType + ']\n' + content + '\n[/ul]' + ); + } + } + ); } }, orderedlist: { txtExec: function (caller, selected) { + var editor = this; var content = ''; - each(selected.split(/\r?\n/), function () { - content += (content ? '\n' : '') + - '[li]' + this + '[/li]'; - }); + getEditorCommand('orderedlist')._dropDown( + editor, + caller, + function (tagType) { + selected.split(/\r?\n/).forEach(function (item) { + content += (content ? '\n' : '') + + '[li]' + item + '[/li]'; + }); - this.insertText('[ol]\n' + content + '\n[/ol]'); + if (tagType === '1') { + editor.insertText( + '[ol]\n' + content + '\n[/ol]' + ); + } else { + editor.insertText( + '[ol=' + tagType + ']\n' + content + '\n[/ol]' + ); + } + } + ); } }, table: { @@ -436,14 +466,41 @@ // START_COMMAND: Lists ul: { - tags: { - ul: null + styles: { + 'list-style-type': null }, breakStart: true, isInline: false, skipLastLineBreak: true, - format: '[ul]{0}[/ul]', - html: '' + format: function (element, content) { + var tag = element.nodeName.toLowerCase(); + var listType = element.style['list-style-type']; + var validTypes = ['disc', 'circle', 'square', 'none']; + + // That call is not for this tag, skip it + if (tag !== 'ul') { + return content; + } + + if (listType && listType !== 'disc' && + validTypes.indexOf(listType) > -1) { + return '[ul=' + listType + ']' + content + '[/ul]'; + } else { + return '[ul]' + content + '[/ul]'; + } + }, + html: function (token, attrs, content) { + var listType = 'disc'; + var validTypes = ['disc', 'circle', 'square', 'none']; + var attr = attrs.defaultattr; + + if (attr && validTypes.indexOf(attr) > -1) { + listType = attr; + } + + return ''; + } }, list: { breakStart: true, @@ -452,14 +509,51 @@ html: '' }, ol: { - tags: { - ol: null + styles: { + 'list-style-type': null }, breakStart: true, isInline: false, skipLastLineBreak: true, - format: '[ol]{0}[/ol]', - html: '
    {0}
' + format: function (element, content) { + var tag = element.nodeName.toLowerCase(); + var tagType = attr(element, 'data-tagtype'); + var validTypes = ['1', 'A', 'a', 'I', 'i']; + + // That call is not for this tag, skip it + if (tag !== 'ol') { + return content; + } + + if (tagType && tagType !== '1' && + validTypes.indexOf(tagType) > -1) { + return '[ol=' + tagType + ']' + content + '[/ol]'; + } else { + return '[ol]' + content + '[/ol]'; + } + }, + html: function (token, attrs, content) { + var tagType = '1'; + var styleType = 'decimal'; + var validTypes = ['1', 'A', 'a', 'I', 'i']; + var attr = attrs.defaultattr; + + if (attr && validTypes.indexOf(attr) > -1) { + tagType = attr; + } + + switch (tagType) { + case '1': styleType = 'decimal'; break; + case 'A': styleType = 'upper-alpha'; break; + case 'a': styleType = 'lower-alpha'; break; + case 'I': styleType = 'upper-roman'; break; + case 'i': styleType = 'lower-roman'; break; + default: styleType = 'decimal'; break; + } + + return '
    ' + content + '
'; + } }, li: { tags: { diff --git a/src/formats/xhtml.js b/src/formats/xhtml.js index dcd1d1acc..7e90521a2 100644 --- a/src/formats/xhtml.js +++ b/src/formats/xhtml.js @@ -100,10 +100,54 @@ } }, bulletlist: { - txtExec: [''] + txtExec: function (caller, selected) { + var editor = this; + var content = ''; + + getEditorCommand('bulletlist')._dropDown( + editor, + caller, + function (listType) { + selected.split(/\r?\n/).forEach(function (item) { + content += (content ? '\n' : '') + + '
  • ' + item + '
  • '; + }); + + editor.insertText( + '' + ); + } + ); + } }, orderedlist: { - txtExec: ['
    1. ', '
    '] + txtExec: function (caller, selected) { + var editor = this; + var content = ''; + + getEditorCommand('orderedlist')._dropDown( + editor, + caller, + function (tagType, styleType) { + selected.split(/\r?\n/).forEach(function (item) { + content += (content ? '\n' : '') + + '
  • ' + item + '
  • '; + }); + + if (styleType === 'decimal') { + editor.insertText( + '
      ' + content + '
    ' + ); + } else { + editor.insertText( + '
      ' + content + '
    ' + ); + } + } + ); + } }, table: { txtExec: ['
    ', '
    '] @@ -1156,6 +1200,16 @@ conv: function (node) { node.parentNode.removeChild(node); } + }, + { + tags: { + ol: { + 'data-tagtype': null + } + }, + conv: function (node) { + removeAttr(node, 'data-tagtype'); + } } ]; diff --git a/src/lib/defaultCommands.js b/src/lib/defaultCommands.js index 9f8fe3281..ae1f62e29 100644 --- a/src/lib/defaultCommands.js +++ b/src/lib/defaultCommands.js @@ -284,18 +284,97 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Bullet List bulletlist: { - exec: function () { - fixFirefoxListBug(this); - this.execCommand('insertunorderedlist'); + _dropDown: function (editor, caller, callback) { + var content = dom.createElement('div'); + + dom.on(content, 'click', 'a', function (e) { + callback(dom.data(this, 'type')); + editor.closeDropDown(true); + e.preventDefault(); + }); + + dom.appendChild(content, _tmpl('ulistTypeOpt', + { type: 'disc', text: 'Bullet' }, true)); + dom.appendChild(content, _tmpl('ulistTypeOpt', + { type: 'circle', text: 'Circle' }, true)); + dom.appendChild(content, _tmpl('ulistTypeOpt', + { type: 'square', text: 'Square' }, true)); + dom.appendChild(content, _tmpl('ulistTypeOpt', + { type: 'none', text: 'None' }, true)); + + editor.createDropDown(caller, 'listtype-picker', content); + }, + exec: function (caller) { + var editor = this; + + defaultCmds.bulletlist._dropDown(editor, caller, function (type) { + fixFirefoxListBug(this); + editor.wysiwygEditorInsertHtml( + '' + ); + }); }, tooltip: 'Bullet list' }, // END_COMMAND // START_COMMAND: Ordered List orderedlist: { - exec: function () { - fixFirefoxListBug(this); - this.execCommand('insertorderedlist'); + _dropDown: function (editor, caller, callback) { + var content = dom.createElement('div'); + + dom.on(content, 'click', 'a', function (e) { + callback(dom.data(this, 'tagtype'), + dom.data(this, 'styletype')); + editor.closeDropDown(true); + e.preventDefault(); + }); + + dom.appendChild(content, _tmpl('olistTypeOpt', + { + tagType: '1', + styleType: 'decimal', + text: 'Decimal numbers (1, 2, 3, 4)' + }, true)); + dom.appendChild(content, _tmpl('olistTypeOpt', + { + tagType: 'a', + styleType: 'lower-alpha', + text: 'Alphabetic lowercase (a, b, c, d)' + }, true)); + dom.appendChild(content, _tmpl('olistTypeOpt', + { + tagType: 'A', + styleType: 'upper-alpha', + text: 'Alphabetic uppercase (A, B, C, D)' + }, true)); + dom.appendChild(content, _tmpl('olistTypeOpt', + { + tagType: 'i', + styleType: 'lower-roman', + text: 'Roman lowercase (i, ii, iii, iv)' + }, true)); + dom.appendChild(content, _tmpl('olistTypeOpt', + { + tagType: 'I', + styleType: 'upper-roman', + text: 'Roman uppercase (I, II, III, IV)' + }, true)); + + editor.createDropDown(caller, 'listtype-picker', content); + }, + exec: function (caller) { + var editor = this; + + defaultCmds.orderedlist._dropDown(editor, caller, + function (tagType, styleType) { + fixFirefoxListBug(this); + editor.wysiwygEditorInsertHtml( + '

    ' + ); + } + ); }, tooltip: 'Numbered list' }, diff --git a/src/lib/templates.js b/src/lib/templates.js index 98543f09a..2926aa88e 100644 --- a/src/lib/templates.js +++ b/src/lib/templates.js @@ -39,6 +39,16 @@ var _templates = { sizeOpt: '{size}', + ulistTypeOpt: '' + + '', + + olistTypeOpt: '{text}', + pastetext: '
    ' + '
    ' + diff --git a/src/themes/inc/defaultbase.less b/src/themes/inc/defaultbase.less index 9fe3dddb6..7fcc64a0b 100644 --- a/src/themes/inc/defaultbase.less +++ b/src/themes/inc/defaultbase.less @@ -225,6 +225,7 @@ div.sceditor-dropdown div { div.sceditor-font-picker, div.sceditor-fontsize-picker, + div.sceditor-listtype-picker, div.sceditor-format { padding: 6px 0; } @@ -264,6 +265,7 @@ div.sceditor-dropdown div { } .sceditor-fontsize-option, + .sceditor-listtype-option, .sceditor-font-option, .sceditor-format a { display: block; @@ -273,7 +275,13 @@ div.sceditor-dropdown div { color: #222; } - .sceditor-fontsize-option { + ul.sceditor-listtype { + padding: 0; + margin: 0 20px; + } + + .sceditor-fontsize-option, + .sceditor-listtype-option { padding: 7px 13px; } @@ -281,17 +289,17 @@ div.sceditor-dropdown div { float: left; } - .sceditor-color-option { - display: block; - border: 2px solid #fff; - height: 18px; - width: 18px; - overflow: hidden; - } + .sceditor-color-option { + display: block; + border: 2px solid #fff; + height: 18px; + width: 18px; + overflow: hidden; + } - .sceditor-color-option:hover { - border: 1px solid #aaa; - } + .sceditor-color-option:hover { + border: 1px solid #aaa; + } /** diff --git a/tests/unit/formats/bbcode.js b/tests/unit/formats/bbcode.js index b58aae2d7..e733429c7 100644 --- a/tests/unit/formats/bbcode.js +++ b/tests/unit/formats/bbcode.js @@ -253,7 +253,7 @@ QUnit.test('New line handling', function (assert) { this.htmlToBBCode( '
    text
    ' + '
    ' + IE_BR_STR + '
    ' + - '' + '' ), 'text\n\n[ul]\n[li]text[/li]\n[/ul]\n', 'Div siblings with a list' @@ -264,7 +264,7 @@ QUnit.test('New line handling', function (assert) { '
    text
    ' + '
    ' + IE_BR_STR + '
    ' + '
    ' + IE_BR_STR + '
    ' + - '' + '' ), 'text\n\n\n[ul]\n[li]text[/li]\n[/ul]\n', 'Multiple div siblings with a list' @@ -284,7 +284,7 @@ QUnit.test('New line handling', function (assert) { assert.equal( this.htmlToBBCode( - '' + '' ), '[ul]\n[li]newline\n[/li]\n[/ul]\n', 'List item last child block level' @@ -571,28 +571,79 @@ QUnit.test('colour', function (assert) { QUnit.test('List', function (assert) { assert.equal( - this.htmlToBBCode(''), + this.htmlToBBCode(''), '[ul]\n[li]test[/li]\n[/ul]\n', - 'UL tag' + 'UL tag, disc type' ); assert.equal( - this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), + this.htmlToBBCode(''), + '[ul=circle]\n[li]test[/li]\n[/ul]\n', + 'UL tag, circle type' + ); + + assert.equal( + this.htmlToBBCode(''), + '[ul=square]\n[li]test[/li]\n[/ul]\n', + 'UL tag, square type' + ); + + assert.equal( + this.htmlToBBCode(''), + '[ul=none]\n[li]test[/li]\n[/ul]\n', + 'UL tag, none type' + ); + + assert.equal( + this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), '[ol]\n[li]test[/li]\n[/ol]\n', - 'OL tag' + 'OL tag, type="1"' + ); + + assert.equal( + this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), + '[ol=A]\n[li]test[/li]\n[/ol]\n', + 'OL tag, type="A"' + ); + + assert.equal( + this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), + '[ol=a]\n[li]test[/li]\n[/ol]\n', + 'OL tag, type="a"' + ); + + assert.equal( + this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), + '[ol=I]\n[li]test[/li]\n[/ol]\n', + 'OL tag, type="I"' + ); + + assert.equal( + this.htmlToBBCode('
    1. test' + IE_BR_STR + '
    '), + '[ol=i]\n[li]test[/li]\n[/ol]\n', + 'OL tag, type="i"' ); assert.equal( this.htmlToBBCode( - '