127 | Theme: 128 | 133 |
134 | 135 | 138 |├── demo └── example.gif ├── LICENSE ├── contextmenu.min.css ├── themes ├── contextmenu_light.min.css ├── contextmenu_dark.min.css ├── contextmenu_light.css └── contextmenu_dark.css ├── contextmenu.css ├── index.html ├── contextmenu.min.js ├── README.md └── contextmenu.js /demo/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m-thalmann/contextmenujs/HEAD/demo/example.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Matthias Thalmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /contextmenu.min.css: -------------------------------------------------------------------------------- 1 | .cm_container{position:fixed;opacity:0;transform:scale(0);transition:transform 0.1s;transform-origin:top left;padding:0}.cm_container.display{opacity:1;transform:scale(1)}.cm_container,.cm_container *{box-sizing:border-box}.cm_container *{position:relative}.cm_container ul{list-style-type:none;padding:0;margin:0;background-color:#ccc;box-shadow:0 0 5px #333}.cm_container li{padding:5px 10px;padding-right:1.7em;cursor:pointer;white-space:nowrap}.cm_container li:hover{background-color:#bbb}.cm_container li .cm_icon_span{width:1.5em;height:1.2em;vertical-align:bottom;display:inline-block;border-right:1px solid #aaa;margin-right:5px;padding-right:5px;text-align:center}.cm_container li .cm_sub_span{width:1em;display:inline-block;text-align:center;position:absolute;top:50%;right:.5em;transform:translateY(-50%)}.cm_container li>ul{position:absolute;top:0;left:100%;opacity:0;transition:opacity 0.2s;visibility:hidden}.cm_container li:hover>ul{opacity:1;visibility:visible}.cm_container li.cm_divider{border-bottom:1px solid #aaa;margin:5px;padding:0;cursor:default}.cm_container li.cm_divider:hover{background-color:inherit}.cm_container.cm_border_right>ul ul{left:unset;right:100%}.cm_container.cm_border_bottom>ul ul{top:unset;bottom:0}.cm_container li[disabled=""]{color:#777;cursor:default}.cm_container li[disabled=""]:hover{background-color:inherit} 2 | -------------------------------------------------------------------------------- /themes/contextmenu_light.min.css: -------------------------------------------------------------------------------- 1 | .cm_container{position:fixed;opacity:0;transform:scale(0);transition:transform 0.1s;transform-origin:top left;padding:0}.cm_container.display{opacity:1;transform:scale(1)}.cm_container,.cm_container *{box-sizing:border-box}.cm_container *{position:relative}.cm_container ul{list-style-type:none;padding:0;margin:0;background-color:#dbdbdb;box-shadow:0 0 5px #626262;border-radius:1px}.cm_container li{padding:5px 10px;padding-right:1.7em;cursor:pointer;white-space:nowrap}.cm_container li:hover{background-color:#b0b0b0}.cm_container li .cm_icon_span{width:1.5em;height:1.2em;vertical-align:bottom;display:inline-block;margin-right:5px;padding-right:5px;text-align:center}.cm_container li .cm_sub_span{width:1em;display:inline-block;text-align:center;position:absolute;top:50%;right:.5em;transform:translateY(-50%)}.cm_container li>ul{position:absolute;top:0;left:100%;opacity:0;transition:opacity 0.2s;visibility:hidden}.cm_container li:hover>ul{opacity:1;visibility:visible}.cm_container li.cm_divider{border-bottom:1px solid #aaa;margin:5px;padding:0;cursor:default}.cm_container li.cm_divider:hover{background-color:inherit}.cm_container.cm_border_right>ul ul{left:unset;right:100%}.cm_container.cm_border_bottom>ul ul{top:unset;bottom:0}.cm_container li[disabled=""]{color:#777;cursor:default}.cm_container li[disabled=""]:hover{background-color:inherit} 2 | -------------------------------------------------------------------------------- /themes/contextmenu_dark.min.css: -------------------------------------------------------------------------------- 1 | .cm_container{position:fixed;opacity:0;transform:scale(0);transition:transform 0.1s;transform-origin:top left;padding:0}.cm_container.display{opacity:1;transform:scale(1)}.cm_container,.cm_container *{box-sizing:border-box}.cm_container *{position:relative}.cm_container ul{list-style-type:none;padding:0;margin:0;background-color:#2d2d2d;box-shadow:0 0 5px #000;border-radius:1px}.cm_container li{padding:5px 10px;padding-right:1.7em;cursor:pointer;white-space:nowrap;color:#ccc}.cm_container li:hover{background-color:#242424}.cm_container li .cm_icon_span{width:1.5em;height:1.2em;vertical-align:bottom;display:inline-block;margin-right:5px;padding-right:5px;text-align:center}.cm_container li .cm_sub_span{width:1em;display:inline-block;text-align:center;position:absolute;top:50%;right:.5em;transform:translateY(-50%)}.cm_container li>ul{position:absolute;top:0;left:100%;opacity:0;transition:opacity 0.2s;visibility:hidden}.cm_container li:hover>ul{opacity:1;visibility:visible}.cm_container li.cm_divider{border-bottom:1px solid #aaa;margin:5px;padding:0;cursor:default}.cm_container li.cm_divider:hover{background-color:inherit}.cm_container.cm_border_right>ul ul{left:unset;right:100%}.cm_container.cm_border_bottom>ul ul{top:unset;bottom:0}.cm_container li[disabled=""]{color:#777;cursor:default}.cm_container li[disabled=""]:hover{background-color:inherit} 2 | -------------------------------------------------------------------------------- /contextmenu.css: -------------------------------------------------------------------------------- 1 | .cm_container{ 2 | position: fixed; 3 | opacity: 0; 4 | transform: scale(0); 5 | transition: transform 0.1s; 6 | transform-origin: top left; 7 | padding: 0; 8 | } 9 | 10 | .cm_container.display{ 11 | opacity: 1; 12 | transform: scale(1); 13 | } 14 | 15 | .cm_container, .cm_container *{ 16 | box-sizing: border-box; 17 | } 18 | 19 | .cm_container *{ 20 | position: relative; 21 | } 22 | 23 | .cm_container ul{ 24 | list-style-type: none; 25 | padding: 0; 26 | margin: 0; 27 | background-color: #ccc; 28 | box-shadow: 0 0 5px #333; 29 | } 30 | 31 | .cm_container li{ 32 | padding: 5px 10px; 33 | padding-right: 1.7em; 34 | cursor: pointer; 35 | white-space: nowrap; 36 | } 37 | 38 | .cm_container li:hover{ 39 | background-color: #bbb; 40 | } 41 | 42 | .cm_container li .cm_icon_span{ 43 | width: 1.5em; 44 | height: 1.2em; 45 | vertical-align: bottom; 46 | display: inline-block; 47 | border-right: 1px solid #aaa; 48 | margin-right: 5px; 49 | padding-right: 5px; 50 | text-align: center; 51 | } 52 | 53 | .cm_container li .cm_sub_span{ 54 | width: 1em; 55 | display: inline-block; 56 | text-align: center; 57 | position: absolute; 58 | top: 50%; 59 | right: 0.5em; 60 | transform: translateY(-50%); 61 | } 62 | 63 | .cm_container li > ul{ 64 | position: absolute; 65 | top: 0; 66 | left: 100%; 67 | opacity: 0; 68 | transition: opacity 0.2s; 69 | visibility: hidden; 70 | } 71 | 72 | .cm_container li:hover > ul{ 73 | opacity: 1; 74 | visibility: visible; 75 | } 76 | 77 | .cm_container li.cm_divider{ 78 | border-bottom: 1px solid #aaa; 79 | margin: 5px; 80 | padding: 0; 81 | cursor: default; 82 | } 83 | 84 | .cm_container li.cm_divider:hover{ 85 | background-color: inherit; 86 | } 87 | 88 | .cm_container.cm_border_right > ul ul{ 89 | left: unset; 90 | right: 100%; 91 | } 92 | 93 | .cm_container.cm_border_bottom > ul ul{ 94 | top: unset; 95 | bottom: 0; 96 | } 97 | 98 | .cm_container li[disabled=""]{ 99 | color: #777; 100 | cursor: default; 101 | } 102 | 103 | .cm_container li[disabled=""]:hover{ 104 | background-color: inherit; 105 | } 106 | -------------------------------------------------------------------------------- /themes/contextmenu_light.css: -------------------------------------------------------------------------------- 1 | .cm_container{ 2 | position: fixed; 3 | opacity: 0; 4 | transform: scale(0); 5 | transition: transform 0.1s; 6 | transform-origin: top left; 7 | padding: 0; 8 | } 9 | 10 | .cm_container.display{ 11 | opacity: 1; 12 | transform: scale(1); 13 | } 14 | 15 | .cm_container, .cm_container *{ 16 | box-sizing: border-box; 17 | } 18 | 19 | .cm_container *{ 20 | position: relative; 21 | } 22 | 23 | .cm_container ul{ 24 | list-style-type: none; 25 | padding: 0; 26 | margin: 0; 27 | background-color: #dbdbdb; 28 | box-shadow: 0 0 5px #626262; 29 | border-radius: 1px; 30 | } 31 | 32 | .cm_container li{ 33 | padding: 5px 10px; 34 | padding-right: 1.7em; 35 | cursor: pointer; 36 | white-space: nowrap; 37 | } 38 | 39 | .cm_container li:hover{ 40 | background-color: #b0b0b0; 41 | } 42 | 43 | .cm_container li .cm_icon_span{ 44 | width: 1.5em; 45 | height: 1.2em; 46 | vertical-align: bottom; 47 | display: inline-block; 48 | margin-right: 5px; 49 | padding-right: 5px; 50 | text-align: center; 51 | } 52 | 53 | .cm_container li .cm_sub_span{ 54 | width: 1em; 55 | display: inline-block; 56 | text-align: center; 57 | position: absolute; 58 | top: 50%; 59 | right: 0.5em; 60 | transform: translateY(-50%); 61 | } 62 | 63 | .cm_container li > ul{ 64 | position: absolute; 65 | top: 0; 66 | left: 100%; 67 | opacity: 0; 68 | transition: opacity 0.2s; 69 | visibility: hidden; 70 | } 71 | 72 | .cm_container li:hover > ul{ 73 | opacity: 1; 74 | visibility: visible; 75 | } 76 | 77 | .cm_container li.cm_divider{ 78 | border-bottom: 1px solid #aaa; 79 | margin: 5px; 80 | padding: 0; 81 | cursor: default; 82 | } 83 | 84 | .cm_container li.cm_divider:hover{ 85 | background-color: inherit; 86 | } 87 | 88 | .cm_container.cm_border_right > ul ul{ 89 | left: unset; 90 | right: 100%; 91 | } 92 | 93 | .cm_container.cm_border_bottom > ul ul{ 94 | top: unset; 95 | bottom: 0; 96 | } 97 | 98 | .cm_container li[disabled=""]{ 99 | color: #777; 100 | cursor: default; 101 | } 102 | 103 | .cm_container li[disabled=""]:hover{ 104 | background-color: inherit; 105 | } 106 | -------------------------------------------------------------------------------- /themes/contextmenu_dark.css: -------------------------------------------------------------------------------- 1 | .cm_container{ 2 | position: fixed; 3 | opacity: 0; 4 | transform: scale(0); 5 | transition: transform 0.1s; 6 | transform-origin: top left; 7 | padding: 0; 8 | } 9 | 10 | .cm_container.display{ 11 | opacity: 1; 12 | transform: scale(1); 13 | } 14 | 15 | .cm_container, .cm_container *{ 16 | box-sizing: border-box; 17 | } 18 | 19 | .cm_container *{ 20 | position: relative; 21 | } 22 | 23 | .cm_container ul{ 24 | list-style-type: none; 25 | padding: 0; 26 | margin: 0; 27 | background-color: #2d2d2d; 28 | box-shadow: 0 0 5px #000000; 29 | border-radius: 1px; 30 | } 31 | 32 | .cm_container li{ 33 | padding: 5px 10px; 34 | padding-right: 1.7em; 35 | cursor: pointer; 36 | white-space: nowrap; 37 | color: #ccc; 38 | } 39 | 40 | .cm_container li:hover{ 41 | background-color: #242424; 42 | } 43 | 44 | .cm_container li .cm_icon_span{ 45 | width: 1.5em; 46 | height: 1.2em; 47 | vertical-align: bottom; 48 | display: inline-block; 49 | margin-right: 5px; 50 | padding-right: 5px; 51 | text-align: center; 52 | } 53 | 54 | .cm_container li .cm_sub_span{ 55 | width: 1em; 56 | display: inline-block; 57 | text-align: center; 58 | position: absolute; 59 | top: 50%; 60 | right: 0.5em; 61 | transform: translateY(-50%); 62 | } 63 | 64 | .cm_container li > ul{ 65 | position: absolute; 66 | top: 0; 67 | left: 100%; 68 | opacity: 0; 69 | transition: opacity 0.2s; 70 | visibility: hidden; 71 | } 72 | 73 | .cm_container li:hover > ul{ 74 | opacity: 1; 75 | visibility: visible; 76 | } 77 | 78 | .cm_container li.cm_divider{ 79 | border-bottom: 1px solid #aaa; 80 | margin: 5px; 81 | padding: 0; 82 | cursor: default; 83 | } 84 | 85 | .cm_container li.cm_divider:hover{ 86 | background-color: inherit; 87 | } 88 | 89 | .cm_container.cm_border_right > ul ul{ 90 | left: unset; 91 | right: 100%; 92 | } 93 | 94 | .cm_container.cm_border_bottom > ul ul{ 95 | top: unset; 96 | bottom: 0; 97 | } 98 | 99 | .cm_container li[disabled=""]{ 100 | color: #777; 101 | cursor: default; 102 | } 103 | 104 | .cm_container li[disabled=""]:hover{ 105 | background-color: inherit; 106 | } 107 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |127 | Theme: 128 | 133 |
134 | 135 | 138 |
', // Icon to display next to the text
110 | "sub": [ // Item has nested items
111 | {
112 | "text": "Item1.1",
113 | "enabled": false // Item is disabled (if it has nested items, they won't show)
114 | }
115 | ]
116 | },
117 | {
118 | "type": ContextMenu.DIVIDER // This item is a divider (shows only gray line, no text etc.)
119 | },
120 | {
121 | "text": "Item2",
122 | "events": { // Adds eventlisteners to the item (you can use any event there is)
123 | "click": function(e){
124 | console.log("clicked");
125 | },
126 | "mouseover": function(e){
127 | console.log("mouse is over menuitem");
128 | }
129 | }
130 | }
131 | ];
132 | ```
133 | **NOTE:** The braces after the = and after `"sub":` are square ones!
134 |
135 | **NOTE:** Every other property, not mentioned here, is skipped!
136 |
137 | ### ContextUtil
138 | A collection of helper methods. Can't be instanciated.
139 | #### Methods
140 | ```javascript
141 | ContextUtil.getProperty(opt, o, def); // Returns the value of 'o' in the array/object opt, if it is set;
142 | // else it returns def (object, string, object)
143 |
144 | ContextUtil.getSizes(obj); // Recursively gets the size of a DOM-List (ul), that has absolute positioned
145 | // children (dom-element)
146 | ```
147 |
148 | ### Options
149 |
150 | | Option | Values | Definition |
151 | |:---------------:|:----------:|:---------------------------------------------------------------:|
152 | | close_on_resize | true/false | Sets if the contextmenu is closed, when the window is resized |
153 | | close_on_click | true/false | Sets if the contextmenu is closed, when the window is clicked |
154 | | default_icon | [string] | Sets the default icon for a menu item (is overridden, when set) |
155 | | default_text | [string] | Sets the default text for a menu item (is overridden, when set) |
156 | | sub_icon | [string] | Sets the arrow icon for sub menus |
157 | | mouse_offset | [integer] | Sets the offset to the mouse, when opened (in pixel) |
158 |
159 | ## Example
160 | ### Code:
161 | ```javascript
162 | var menu = new ContextMenu(
163 | [
164 | {
165 | "text": "Item 1",
166 | "sub": [
167 | {
168 | "text": "Item 11"
169 | },
170 | {
171 | "text": "Item 12"
172 | },
173 | {
174 | "type": ContextMenu.DIVIDER
175 | },
176 | {
177 | "text": "Item 13",
178 | "enabled": false,
179 | "sub": [
180 | {
181 | "text": "Item 131"
182 | }
183 | ]
184 | }
185 | ]
186 | },
187 | {
188 | "text": "Item 2",
189 | "icon": '',
190 | "events": {
191 | "click": function(e){
192 | alert(e);
193 | }
194 | }
195 | }
196 | ]
197 | );
198 | ```
199 |
200 | ### Output:
201 |
202 | 
203 |
--------------------------------------------------------------------------------
/contextmenu.js:
--------------------------------------------------------------------------------
1 | function ContextMenu(menu, options){
2 | var self = this;
3 | var num = ContextMenu.count++;
4 |
5 | this.menu = menu;
6 | this.contextTarget = null;
7 |
8 | if(!(menu instanceof Array)){
9 | throw new Error("Parameter 1 must be of type Array");
10 | }
11 |
12 | if(typeof options !== "undefined"){
13 | if(typeof options !== "object"){
14 | throw new Error("Parameter 2 must be of type object");
15 | }
16 | }else{
17 | options = {};
18 | }
19 |
20 | window.addEventListener("resize", function(){
21 | if(ContextUtil.getProperty(options, "close_on_resize", true)){
22 | self.hide();
23 | }
24 | });
25 |
26 | this.setOptions = function(_options){
27 | if(typeof _options === "object"){
28 | options = _options;
29 | }else{
30 | throw new Error("Parameter 1 must be of type object")
31 | }
32 | }
33 |
34 | this.changeOption = function(option, value){
35 | if(typeof option === "string"){
36 | if(typeof value !== "undefined"){
37 | options[option] = value;
38 | }else{
39 | throw new Error("Parameter 2 must be set");
40 | }
41 | }else{
42 | throw new Error("Parameter 1 must be of type string");
43 | }
44 | }
45 |
46 | this.getOptions = function(){
47 | return options;
48 | }
49 |
50 | this.reload = function(){
51 | if(document.getElementById('cm_' + num) == null){
52 | var cnt = document.createElement("div");
53 | cnt.className = "cm_container";
54 | cnt.id = "cm_" + num;
55 |
56 | document.body.appendChild(cnt);
57 | }
58 |
59 | var container = document.getElementById('cm_' + num);
60 | container.innerHTML = "";
61 |
62 | container.appendChild(renderLevel(menu));
63 | }
64 |
65 | function renderLevel(level){
66 | var ul_outer = document.createElement("ul");
67 |
68 | level.forEach(function(item){
69 | var li = document.createElement("li");
70 | li.menu = self;
71 |
72 | if(typeof item.type === "undefined"){
73 | var icon_span = document.createElement("span");
74 | icon_span.className = 'cm_icon_span';
75 |
76 | if(ContextUtil.getProperty(item, "icon", "") != ""){
77 | icon_span.innerHTML = ContextUtil.getProperty(item, "icon", "");
78 | }else{
79 | icon_span.innerHTML = ContextUtil.getProperty(options, "default_icon", "");
80 | }
81 |
82 | var text_span = document.createElement("span");
83 | text_span.className = 'cm_text';
84 |
85 | if(ContextUtil.getProperty(item, "text", "") != ""){
86 | text_span.innerHTML = ContextUtil.getProperty(item, "text", "");
87 | }else{
88 | text_span.innerHTML = ContextUtil.getProperty(options, "default_text", "item");
89 | }
90 |
91 | var sub_span = document.createElement("span");
92 | sub_span.className = 'cm_sub_span';
93 |
94 | if(typeof item.sub !== "undefined"){
95 | if(ContextUtil.getProperty(options, "sub_icon", "") != ""){
96 | sub_span.innerHTML = ContextUtil.getProperty(options, "sub_icon", "");
97 | }else{
98 | sub_span.innerHTML = '';
99 | }
100 | }
101 |
102 | li.appendChild(icon_span);
103 | li.appendChild(text_span);
104 | li.appendChild(sub_span);
105 |
106 | if(!ContextUtil.getProperty(item, "enabled", true)){
107 | li.setAttribute("disabled", "");
108 | }else{
109 | if(typeof item.events === "object"){
110 | var keys = Object.keys(item.events);
111 |
112 | for(var i = 0; i < keys.length; i++){
113 | li.addEventListener(keys[i], item.events[keys[i]]);
114 | }
115 | }
116 |
117 | if(typeof item.sub !== "undefined"){
118 | li.appendChild(renderLevel(item.sub));
119 | }
120 | }
121 | }else{
122 | if(item.type == ContextMenu.DIVIDER){
123 | li.className = "cm_divider";
124 | }
125 | }
126 |
127 | ul_outer.appendChild(li);
128 | });
129 |
130 | return ul_outer;
131 | }
132 |
133 | this.display = function(e, target){
134 | if(typeof target !== "undefined"){
135 | self.contextTarget = target;
136 | }else{
137 | self.contextTarget = e.target;
138 | }
139 |
140 | var menu = document.getElementById('cm_' + num);
141 |
142 | var clickCoords = {x: e.clientX, y: e.clientY};
143 | var clickCoordsX = clickCoords.x;
144 | var clickCoordsY = clickCoords.y;
145 |
146 | var menuWidth = menu.offsetWidth + 4;
147 | var menuHeight = menu.offsetHeight + 4;
148 |
149 | var windowWidth = window.innerWidth;
150 | var windowHeight = window.innerHeight;
151 |
152 | var mouseOffset = parseInt(ContextUtil.getProperty(options, "mouse_offset", 2));
153 |
154 | if((windowWidth - clickCoordsX) < menuWidth){
155 | menu.style.left = windowWidth - menuWidth + "px";
156 | }else{
157 | menu.style.left = (clickCoordsX + mouseOffset) + "px";
158 | }
159 |
160 | if((windowHeight - clickCoordsY) < menuHeight){
161 | menu.style.top = windowHeight - menuHeight + "px";
162 | }else{
163 | menu.style.top = (clickCoordsY + mouseOffset) + "px";
164 | }
165 |
166 | var sizes = ContextUtil.getSizes(menu);
167 |
168 | if((windowWidth - clickCoordsX) < sizes.width){
169 | menu.classList.add("cm_border_right");
170 | }else{
171 | menu.classList.remove("cm_border_right");
172 | }
173 |
174 | if((windowHeight - clickCoordsY) < sizes.height){
175 | menu.classList.add("cm_border_bottom");
176 | }else{
177 | menu.classList.remove("cm_border_bottom");
178 | }
179 |
180 | menu.classList.add("display");
181 |
182 | if(ContextUtil.getProperty(options, "close_on_click", true)){
183 | window.addEventListener("click", documentClick);
184 | }
185 |
186 | e.preventDefault();
187 | }
188 |
189 | this.hide = function(){
190 | document.getElementById('cm_' + num).classList.remove("display");
191 | window.removeEventListener("click", documentClick);
192 | }
193 |
194 | function documentClick(){
195 | self.hide();
196 | }
197 |
198 | this.reload();
199 | }
200 |
201 | ContextMenu.count = 0;
202 | ContextMenu.DIVIDER = "cm_divider";
203 |
204 | const ContextUtil = {
205 | getProperty: function(options, opt, def){
206 | if(typeof options[opt] !== "undefined"){
207 | return options[opt];
208 | }else{
209 | return def;
210 | }
211 | },
212 |
213 | getSizes: function(obj){
214 | var lis = obj.getElementsByTagName('li');
215 |
216 | var width_def = 0;
217 | var height_def = 0;
218 |
219 | for(var i = 0; i < lis.length; i++){
220 | var li = lis[i];
221 |
222 | if(li.offsetWidth > width_def){
223 | width_def = li.offsetWidth;
224 | }
225 |
226 | if(li.offsetHeight > height_def){
227 | height_def = li.offsetHeight;
228 | }
229 | }
230 |
231 | var width = width_def;
232 | var height = height_def;
233 |
234 | for(var i = 0; i < lis.length; i++){
235 | var li = lis[i];
236 |
237 | var ul = li.getElementsByTagName('ul');
238 | if(typeof ul[0] !== "undefined"){
239 | var ul_size = ContextUtil.getSizes(ul[0]);
240 |
241 | if(width_def + ul_size.width > width){
242 | width = width_def + ul_size.width;
243 | }
244 |
245 | if(height_def + ul_size.height > height){
246 | height = height_def + ul_size.height;
247 | }
248 | }
249 | }
250 |
251 | return {
252 | "width": width,
253 | "height": height
254 | };
255 | }
256 | };
257 |
--------------------------------------------------------------------------------