WIP: Note editing, markdown to html
[oweals/karmaworld.git] / karmaworld / apps / wysihtml5 / static / wysihtml5 / wysihtml-0.4.17 / src / commands / insertList.js
1 wysihtml5.commands.insertList = (function(wysihtml5) {
2
3   var isNode = function(node, name) {
4     if (node && node.nodeName) {
5       if (typeof name === 'string') {
6         name = [name];
7       }
8       for (var n = name.length; n--;) {
9         if (node.nodeName === name[n]) {
10           return true;
11         }
12       }
13     }
14     return false;
15   };
16
17   var findListEl = function(node, nodeName, composer) {
18     var ret = {
19           el: null,
20           other: false
21         };
22
23     if (node) {
24       var parentLi = wysihtml5.dom.getParentElement(node, { nodeName: "LI" }),
25           otherNodeName = (nodeName === "UL") ? "OL" : "UL";
26
27       if (isNode(node, nodeName)) {
28         ret.el = node;
29       } else if (isNode(node, otherNodeName)) {
30         ret = {
31           el: node,
32           other: true
33         };
34       } else if (parentLi) {
35         if (isNode(parentLi.parentNode, nodeName)) {
36           ret.el = parentLi.parentNode;
37         } else if (isNode(parentLi.parentNode, otherNodeName)) {
38           ret = {
39             el : parentLi.parentNode,
40             other: true
41           };
42         }
43       }
44     }
45
46     // do not count list elements outside of composer
47     if (ret.el && !composer.element.contains(ret.el)) {
48       ret.el = null;
49     }
50
51     return ret;
52   };
53
54   var handleSameTypeList = function(el, nodeName, composer) {
55     var otherNodeName = (nodeName === "UL") ? "OL" : "UL",
56         otherLists, innerLists;
57     // Unwrap list
58     // <ul><li>foo</li><li>bar</li></ul>
59     // becomes:
60     // foo<br>bar<br>
61     composer.selection.executeAndRestore(function() {
62       var otherLists = getListsInSelection(otherNodeName, composer);
63       if (otherLists.length) {
64         for (var l = otherLists.length; l--;) {
65           wysihtml5.dom.renameElement(otherLists[l], nodeName.toLowerCase());
66         }
67       } else {
68         innerLists = getListsInSelection(['OL', 'UL'], composer);
69         for (var i = innerLists.length; i--;) {
70           wysihtml5.dom.resolveList(innerLists[i], composer.config.useLineBreaks);
71         }
72         wysihtml5.dom.resolveList(el, composer.config.useLineBreaks);
73       }
74     });
75   };
76
77   var handleOtherTypeList =  function(el, nodeName, composer) {
78     var otherNodeName = (nodeName === "UL") ? "OL" : "UL";
79     // Turn an ordered list into an unordered list
80     // <ol><li>foo</li><li>bar</li></ol>
81     // becomes:
82     // <ul><li>foo</li><li>bar</li></ul>
83     // Also rename other lists in selection
84     composer.selection.executeAndRestore(function() {
85       var renameLists = [el].concat(getListsInSelection(otherNodeName, composer));
86
87       // All selection inner lists get renamed too
88       for (var l = renameLists.length; l--;) {
89         wysihtml5.dom.renameElement(renameLists[l], nodeName.toLowerCase());
90       }
91     });
92   };
93
94   var getListsInSelection = function(nodeName, composer) {
95       var ranges = composer.selection.getOwnRanges(),
96           renameLists = [];
97
98       for (var r = ranges.length; r--;) {
99         renameLists = renameLists.concat(ranges[r].getNodes([1], function(node) {
100           return isNode(node, nodeName);
101         }));
102       }
103
104       return renameLists;
105   };
106
107   var createListFallback = function(nodeName, composer) {
108     // Fallback for Create list
109     composer.selection.executeAndRestoreRangy(function() {
110       var tempClassName =  "_wysihtml5-temp-" + new Date().getTime(),
111           tempElement = composer.selection.deblockAndSurround({
112             "nodeName": "div",
113             "className": tempClassName
114           }),
115           isEmpty, list;
116
117       // This space causes new lists to never break on enter 
118       var INVISIBLE_SPACE_REG_EXP = /\uFEFF/g;
119       tempElement.innerHTML = tempElement.innerHTML.replace(wysihtml5.INVISIBLE_SPACE_REG_EXP, "");
120       
121       if (tempElement) {
122         isEmpty = wysihtml5.lang.array(["", "<br>", wysihtml5.INVISIBLE_SPACE]).contains(tempElement.innerHTML);
123         list = wysihtml5.dom.convertToList(tempElement, nodeName.toLowerCase(), composer.parent.config.uneditableContainerClassname);
124         if (isEmpty) {
125           composer.selection.selectNode(list.querySelector("li"), true);
126         }
127       }
128     });
129   };
130
131   return {
132     exec: function(composer, command, nodeName) {
133       var doc           = composer.doc,
134           cmd           = (nodeName === "OL") ? "insertOrderedList" : "insertUnorderedList",
135           selectedNode  = composer.selection.getSelectedNode(),
136           list          = findListEl(selectedNode, nodeName, composer);
137
138       if (!list.el) {
139         if (composer.commands.support(cmd)) {
140           doc.execCommand(cmd, false, null);
141         } else {
142           createListFallback(nodeName, composer);
143         }
144       } else if (list.other) {
145         handleOtherTypeList(list.el, nodeName, composer);
146       } else {
147         handleSameTypeList(list.el, nodeName, composer);
148       }
149     },
150
151     state: function(composer, command, nodeName) {
152       var selectedNode = composer.selection.getSelectedNode(),
153           list         = findListEl(selectedNode, nodeName, composer);
154
155       return (list.el && !list.other) ? list.el : false;
156     }
157   };
158
159 })(wysihtml5);