3cf119254b39159f83c4ff62b8057c6b883cbb8f
[fnpeditor.git] / src / editor / plugins / core / lists.js
1 define(function() {
2     
3 'use strict';
4 /* globals gettext, interpolate */
5
6
7 var getBoundriesForAList = function(fragment) {
8     var node;
9
10     if(fragment instanceof fragment.RangeFragment && fragment.hasSiblingBoundries()) {
11         return fragment.boundriesSiblingParents();
12     }
13     if(fragment instanceof fragment.NodeFragment) {
14         node = fragment.node.getNearestElementNode();
15         return {
16             node1: node,
17             node2: node
18         };
19     }
20 };
21
22 var countItems = function(boundries) {
23     var ptr = boundries.node1,
24         c = 1;
25     while(ptr && !ptr.sameNode(boundries.node2)) {
26         c++;
27         ptr = ptr.next();
28     }
29     return c;
30 };
31
32 var toggleListAction = function(type) {
33     
34     var execute = {
35         add: function(params) {
36             var boundries = getBoundriesForAList(params.fragment),
37                 listParams = {klass: type === 'Bullet' ? 'list' : 'list.enum'};
38             if(boundries && boundries.node1) {
39                 listParams.node1 = boundries.node1;
40                 listParams.node2 = boundries.node2;
41                 boundries.node1.document.createList(listParams);
42             } else {
43                 throw new Error('Invalid boundries');
44             }
45         },
46         remove: function(params) {
47             /* globals Node */
48             var current = params.fragment.node;
49
50             var toSearch = current.nodeType === Node.ELEMENT_NODE ? [current] : [];
51             toSearch = toSearch.concat(current.parents());
52             toSearch.some(function(node) {
53                 if(node.is('list')) {
54                     node.object.extractListItems();
55                     return true; // break
56                 }
57             });
58         },
59         changeType: function(params) {
60             params.fragment.node.getParent('list').setClass(type === 'Bullet' ? 'list' : 'list.enum');
61         }
62     };
63
64     var isToggled = function(params) {
65         if(params.fragment && params.fragment.node && params.fragment.node.isInside('list')) {
66             var list = params.fragment.node.getParent('list');
67             return list.getClass() === (type === 'Bullet' ? 'list' : 'list.enum');
68         }
69         return false;
70     };
71
72
73     return {
74         name: 'toggle' + type + 'List',
75         context: ['fragment'],
76         params: {
77             fragment: {type: 'context', name: 'fragment'}
78         },
79         stateDefaults: {
80             label: type === 'Bullet' ? gettext('bull. list') : gettext('num. list')
81         },
82         getState: function(params) {
83             if(!params.fragment || !params.fragment.isValid()) {
84                 return false;
85             }
86
87             if(params.fragment instanceof params.fragment.CaretFragment && params.fragment.node.isInside('list')) {
88                 var list = params.fragment.node.getParent('list');
89                 if((list.getClass() === 'list' && type === 'Enum') || (list.getClass() === 'list.enum' && type === 'Bullet')) {
90                     return {
91                         allowed: true,
92                         description: interpolate(gettext('Change list type to %s'), [type]),
93                         execute: execute.changeType
94                     };
95                 }
96                 return {
97                     allowed: true,
98                     toggled: isToggled(params),
99                     description: gettext('Remove list'),
100                     execute: execute.remove
101                 };
102
103             }
104             var boundries = getBoundriesForAList(params.fragment);
105             if(boundries) {
106                 return {
107                     allowed: true,
108                     description: interpolate(gettext('Make %s fragment(s) into list'), [countItems(getBoundriesForAList(params.fragment))]),
109                     execute: execute.add
110                 };
111             }
112         }
113     };
114 };
115
116
117 return {
118     actions: [toggleListAction('Bullet'), toggleListAction('Enum')]
119 };
120
121 });