diff options
author | Aleksander Machniak <alec@alec.pl> | 2012-09-07 11:24:49 (GMT) |
---|---|---|
committer | Aleksander Machniak <alec@alec.pl> | 2012-09-07 11:24:49 (GMT) |
commit | e9ca874fc54fb6bc8429a3a6e7866e6e6e92820b (patch) | |
tree | 606e5fd164ac866f3853009a9e383af247613484 /public_html | |
parent | 052ee511388c7525edd126abfcb5d7232f4bd1bb (diff) | |
download | kolab-wap-e9ca874fc54fb6bc8429a3a6e7866e6e6e92820b.tar.gz |
Added select widget
Added domain selector
Diffstat (limited to 'public_html')
-rw-r--r-- | public_html/js/kolab_admin.js | 218 | ||||
-rw-r--r-- | public_html/skins/default/images/domain_ico.png | bin | 0 -> 751 bytes | |||
-rw-r--r-- | public_html/skins/default/images/user_ico.png | bin | 0 -> 616 bytes | |||
-rw-r--r-- | public_html/skins/default/style.css | 74 | ||||
-rw-r--r-- | public_html/skins/default/templates/main.html | 9 | ||||
-rw-r--r-- | public_html/skins/default/ui.js | 36 |
6 files changed, 318 insertions, 19 deletions
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js index be08f8a..701f818 100644 --- a/public_html/js/kolab_admin.js +++ b/public_html/js/kolab_admin.js @@ -413,6 +413,47 @@ function kolab_admin() } }; + // position and display popup + this.popup_show = function(e, popup) + { + var popup = $(popup), + pos = this.mouse_pos(e), + win = $(window), + w = popup.width(), + h = popup.height(), + left = pos.left - w, + top = pos.top; + + if (top + h > win.height()) + top -= h; + if (left + w > win.width()) + left -= w; + + popup.css({left: left + 'px', top: top + 'px'}).show(); + e.stopPropagation(); + }; + + // Return absolute mouse position of an event + this.mouse_pos = function(e) + { + if (!e) e = window.event; + + var mX = (e.pageX) ? e.pageX : e.clientX, + mY = (e.pageY) ? e.pageY : e.clientY; + + if (document.body && document.all) { + mX += document.body.scrollLeft; + mY += document.body.scrollTop; + } + + if (e._offset) { + mX += e._offset.left; + mY += e._offset.top; + } + + return { left:mX, top:mY }; + }; + /*********************************************************/ /********* keyboard autocomplete methods *********/ @@ -682,7 +723,10 @@ function kolab_admin() // replace some textarea fields with pretty/smart input lists $('textarea[data-type="list"]', form) - .each(function() { kadm.form_element_wrapper(this); }); + .each(function() { kadm.form_list_element_wrapper(this); }); + // create smart select fields + $('input[data-type="select"]', form) + .each(function() { kadm.form_select_element_wrapper(this); }); }; // Form serialization @@ -690,7 +734,7 @@ function kolab_admin() { var form = $(data.id); - // replace some textarea fields with pretty/smart input lists + // smart list fields $('textarea[data-type="list"]', form).not('disabled').each(function() { var i, v, value = [], re = RegExp('^' + RegExp.escape(this.name) + '\[[0-9-]+\]$'); @@ -713,6 +757,11 @@ function kolab_admin() data.json[this.name] = value; }); + // smart selects + $('input[data-type="select"]', form).each(function() { + delete data.json[this.name]; + }); + return data; }; @@ -728,12 +777,12 @@ function kolab_admin() // remove old wrapper $('span[class="listarea"]', elem.parent()).remove(); // insert new list element - this.form_element_wrapper(elem.get(0)); + this.form_list_element_wrapper(elem.get(0)); } }; - // Replaces form element with smart element - this.form_element_wrapper = function(form_element) + // Replaces form element with smart list element + this.form_list_element_wrapper = function(form_element) { var i = 0, j = 0, list = [], elem, e = $(form_element), form = form_element.form, @@ -746,7 +795,7 @@ function kolab_admin() e.hide(); if (autocomplete) - list = this.env.assoc_fields[form_element.name]; + list = this.env.assoc_fields ? this.env.assoc_fields[form_element.name] : []; else if (form_element.value) list = form_element.value.split("\n"); @@ -835,7 +884,7 @@ function kolab_admin() content = '<span class="listelement"><span class="actions">' + (!ac ? '<span title="" class="add"></span>' : ac && idx == -1 ? '<span title="" class="search"></span>' : '') + (!ac || idx >= 0 ? '<span title="" class="reset"></span>' : '') - + '</span><input></span>'; + + '</span><input type="text" autocomplete="off"></span>'; elem = $(content); input = $('input', elem); @@ -928,6 +977,147 @@ function kolab_admin() af[name][key] = val; }; + // Replaces form element with smart select element + this.form_select_element_wrapper = function(form_element) + { + var e = $(form_element), + form = form_element.form, + elem = $('<span class="link"></span>'), + area = $('<span class="listarea autocomplete select popup"></span>'), + content = $('<span class="listcontent"></span>'); + list = this.env.assoc_fields ? this.env.assoc_fields[form_element.name] : []; + + elem.text(e.val()).css({cursor: 'pointer'}) + .click(function(e) { + var popup = $('span.listarea', this.parentNode); + kadm.popup_show(e, popup); + $('input', popup).val('').focus(); + $('span.listcontent > span.listelement', popup).removeClass('selected').show(); + }) + .appendTo(form_element.parentNode); + + if (list.length <= 1) + return; + + if (form_element.type != 'hidden') e.hide(); + area.hide(); + + elem = this.form_list_element(form, { + autocomplete: true, + element: e + }, -1); + + elem.appendTo(area); + content.appendTo(area); + + // popup events + $('input', area) + .click(function(e) { + // stop click on the popup + e.stopPropagation(); + }) + .keypress(function(e) { + // prevent form submission with Enter key + if (e.which == 13) + e.preventDefault(); + }) + .keyup(function(e) { + // filtering + var s = this.value, + options = $('span.listcontent > span.listelement', area); + + // Enter key + if (e.which == 13) { + options.filter('.selected').click() + return; + } + // Escape + else if (e.which == 27) { + area.hide(); + this.value = s = ''; + } + // UP/Down arrows + else if (e.which == 38 || e.which == 40) { + options = options.not(':hidden'); + var selected = options.filter('.selected'); + + if (!selected.length) { + if (e.which == 40) // Down key + options.first().addClass('selected').parent().get(0).scrollTop = 0; + } + else { + var focused = selected[e.which == 40 ? 'next' : 'prev'](); + + while (focused.length && focused.is(':hidden')) + focused = selected[e.which == 40 ? 'next' : 'prev'](); + + if (!focused.length) + focused = options[e.which == 40 ? 'first' : 'last'](); + + if (focused.length) { + selected.removeClass('selected'); + focused.addClass('selected'); + + var parent = focused.parent(), + parent_height = parent.height(), + parent_top = parent.get(0).scrollTop, + top = focused.offset().top - parent.offset().top, + height = focused.height(); + + if (top < 0) + parent.get(0).scrollTop = 0; + else if (top >= parent_height) + parent.get(0).scrollTop = top - parent_height + height + parent_top; + } + } + + return; + } + + if (!s) { + options.show().removeClass('selected'); + return; + } + + options.each(function() { + var o = $(this), v = o.data('value'); + o[v.indexOf(s) != -1 ? 'show' : 'hide']().removeClass('selected'); + }); + + options = options.not(':hidden'); + if (options.length == 1) + options.addClass('selected'); + }); + + // add option rows + $.each(list, function(i, v) { + var elem = kadm.form_select_option_element(form, {value: v, key: v, element: e}); + elem.appendTo(content); + }); + + area.appendTo(form_element.parentNode); + }; + + // Creates option element for smart select + this.form_select_option_element = function(form, data) + { + // build element content + var elem = $('<span class="listelement"></span>') + .data('value', data.key).text(data.value) + .click(function(e) { + var val = $(this).data('value'), + elem = $(data.element), + old_val = elem.val(); + + $('span.link', elem.parent()).text(val); + elem.val(val); + if (val != old_val) + elem.change(); + }); + + return elem; + }; + /*********************************************************/ /********* Forms *********/ @@ -1458,6 +1648,19 @@ RegExp.escape = function(str) return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; +// make a string URL safe (and compatible with PHP's rawurlencode()) +function urlencode(str) +{ + if (window.encodeURIComponent) + return encodeURIComponent(str).replace('*', '%2A'); + + return escape(str) + .replace('+', '%2B') + .replace('*', '%2A') + .replace('/', '%2F') + .replace('@', '%40'); +}; + // Initialize application object (don't change var name!) var kadm = new kolab_admin(); @@ -1465,4 +1668,5 @@ var kadm = new kolab_admin(); $(document).click(function() { // destroy autocompletion kadm.ac_stop(); + $('.popup').hide(); }); diff --git a/public_html/skins/default/images/domain_ico.png b/public_html/skins/default/images/domain_ico.png Binary files differnew file mode 100644 index 0000000..98d4c3b --- /dev/null +++ b/public_html/skins/default/images/domain_ico.png diff --git a/public_html/skins/default/images/user_ico.png b/public_html/skins/default/images/user_ico.png Binary files differnew file mode 100644 index 0000000..89badba --- /dev/null +++ b/public_html/skins/default/images/user_ico.png diff --git a/public_html/skins/default/style.css b/public_html/skins/default/style.css index 64d0ef1..be30a88 100644 --- a/public_html/skins/default/style.css +++ b/public_html/skins/default/style.css @@ -140,6 +140,12 @@ td.label { white-space: nowrap; } +#topmenu > span { + color: #f8fcff; + font-size: 11px; + text-shadow: black 1px 1px; +} + #navigation { margin: 0 15px; text-align: right; @@ -243,14 +249,20 @@ td.label { #topmenu .logout { background: url(images/logout.png) center 10px no-repeat; - padding: 9px 16px; + padding: 10px 16px; margin: 0px 5px 0px 10px; } #topmenu .login { - color: #f8fcff; - font-size: 11px; - text-shadow: black 1px 1px; + padding-left: 20px; + margin-right: 20px; + background: url(images/user_ico.png) 0 1px no-repeat; +} + +#topmenu .domain { + padding-left: 20px; + margin-right: 10px; + background: url(images/domain_ico.png) 0 2px no-repeat; } #navigation ul { @@ -515,6 +527,17 @@ pre.debug { overflow: auto; } +.popup { + display: none; + position: absolute; + border: none; + border-radius: 3px; + box-shadow: 0 2px 6px 0 #333; + -moz-box-shadow: 0 2px 6px 0 #333; + -webkit-box-shadow: 0 2px 6px 0 #333; + -o-box-shadow: 0 2px 6px 0 #333; +} + /********* Form smart inputs *********/ span.listarea { @@ -523,13 +546,16 @@ span.listarea { max-height: 209px; overflow-y: auto; overflow-x: hidden; - margin: 0 0 1px; + margin: 0; padding: 0; background-color: white; border: 1px solid #d0d0d0; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; + text-align: left; + text-shadow: none; + color: black; } span.listelement { @@ -639,6 +665,39 @@ span.listarea.autocomplete span.listelement input.autocomplete { background-color: #f0f0f0; } +span.listarea.select { + width: 200px; +} + +span.listarea.select > span.listelement input { + width: 180px; +} + +span.listcontent { + display: block; + padding: 0; + margin: 0; + overflow: hidden; + max-height: 94px; + overflow-x: hidden; + overflow-y: auto; + border-top: 1px solid #d0d0d0; + background-color: #f5f5f5; + cursor: default; +} + +span.listcontent span.listelement { + padding-left: 3px; +} + +span.listcontent span.listelement:hover { + background-color: #d6efff; +} + +span.listcontent span.listelement.selected { + background-color: #d6efff; +} + /***** autocomplete list *****/ #autocompletepane @@ -840,6 +899,11 @@ fieldset.tabbed vertical-align: top; } +#domain-selector span.link { + color: #1E90FF; + text-decoration: none; +} + /**** User/Group task elements ****/ #userlist table, diff --git a/public_html/skins/default/templates/main.html b/public_html/skins/default/templates/main.html index ed902c6..7dbdf55 100644 --- a/public_html/skins/default/templates/main.html +++ b/public_html/skins/default/templates/main.html @@ -13,6 +13,15 @@ <div id="logo" onclick="document.location='.'"></div> <div id="topmenu"> <span class="login">{$user.fullname}</span> + <span id="domain-selector" class="domain"> + {if count($engine->get_env('domains')) > 1} + <form id="domain-selector-form" method="post" style="display: inline"> + <input data-type="select" name="domain" type="hidden" value="{$user.domain}" /> + </form> + {else} + {$user.domain} + {/if} + </span> <span class="logout link" title="{$engine->translate('Logout')}" onclick="kadm.main_logout()"></span> </div> <div id="navigation">{$main_menu}</div> diff --git a/public_html/skins/default/ui.js b/public_html/skins/default/ui.js index 7c598e6..94891c6 100644 --- a/public_html/skins/default/ui.js +++ b/public_html/skins/default/ui.js @@ -45,7 +45,7 @@ function search_init(task) if (this.value == kadm.t('search')) $(this).val('').removeClass('inactive'); }); -} +}; function search_reset() { @@ -54,7 +54,7 @@ function search_reset() input.val(kadm.t('search')).addClass('inactive'); kadm.command(kadm.env.search_task + '.list', {search: ''}); -} +}; function search_details() { @@ -64,7 +64,7 @@ function search_details() div.slideDown(200); else div.slideUp(200); -} +}; /** * Fieldsets-to-tabs converter @@ -110,7 +110,7 @@ function init_tabs(id, current) // add the tab to container tab.append(a).appendTo(tabs); }); -} +}; function show_tab(id, index) { @@ -122,14 +122,30 @@ function show_tab(id, index) // Select/unselect tab $('#tab'+idx).toggleClass('tablink-selected', idx == index); }); -} +}; + +// Domain selector initializer +function domain_selector() +{ + // domain selector + if (kadm.env.domains && kadm.env.domains.length > 1) { + var form = $('#domain-selector-form'); + + kadm.env.assoc_fields = {domain: kadm.env.domains}; + kadm.form_init('domain-selector-form'); + + $('input[name="domain"]', form).change(function() { + window.location = '?domain=' + urlencode(this.value); + }); + } +}; // Form "onload" handler function form_load(id) { if (id != 'search-form') init_tabs(id); -} +}; // UI resize handler function ui_resize() @@ -139,8 +155,13 @@ function ui_resize() if (h > 100) { $('#taskcontent').height(h - 22); } -} +}; +// UI loader +function ui_load() +{ + domain_selector(); +} /** * UI Initialization @@ -148,3 +169,4 @@ function ui_resize() kadm.add_event_listener('form-load', form_load); kadm.add_event_listener('http-response', ui_resize); //$(window).resize(function() { ui_resize(); }); +$(window).load(function() { ui_load(); }); |