diff --git a/.gitignore b/.gitignore index a84615cf13..68c48822e9 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ nbproject # WebFinger .well-known +/.buildpath diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php index 5ed7882ac9..7d1c282838 100644 --- a/3rdparty/Sabre/VObject/Reader.php +++ b/3rdparty/Sabre/VObject/Reader.php @@ -117,7 +117,7 @@ class Sabre_VObject_Reader { //$result = preg_match('/(?P[A-Z0-9-]+)(?:;(?P^(?([^:^\"]|\"([^\"]*)\")*))?"; $regex = "/^(?P$token)$parameters:(?P.*)$/i"; diff --git a/3rdparty/css/chosen/chosen-sprite.png b/3rdparty/css/chosen/chosen-sprite.png index f20db4439e..9edce05a6a 100644 Binary files a/3rdparty/css/chosen/chosen-sprite.png and b/3rdparty/css/chosen/chosen-sprite.png differ diff --git a/3rdparty/css/chosen/chosen.css b/3rdparty/css/chosen/chosen.css index 247d07bf02..b9c6d88028 100644 --- a/3rdparty/css/chosen/chosen.css +++ b/3rdparty/css/chosen/chosen.css @@ -1,9 +1,4 @@ /* @group Base */ -select.chzn-select { - visibility: hidden; - height: 28px !important; - min-height: 28px !important; -} .chzn-container { font-size: 13px; position: relative; @@ -60,9 +55,21 @@ select.chzn-select { white-space: nowrap; -o-text-overflow: ellipsis; -ms-text-overflow: ellipsis; - -moz-binding: url('/xml/ellipsis.xml#ellipsis'); text-overflow: ellipsis; } +.chzn-container-single .chzn-single abbr { + display: block; + position: absolute; + right: 26px; + top: 8px; + width: 12px; + height: 13px; + font-size: 1px; + background: url(chosen-sprite.png) right top no-repeat; +} +.chzn-container-single .chzn-single abbr:hover { + background-position: right -11px; +} .chzn-container-single .chzn-single div { -webkit-border-radius: 0 4px 4px 0; -moz-border-radius : 0 4px 4px 0; @@ -94,18 +101,19 @@ select.chzn-select { } .chzn-container-single .chzn-search { padding: 3px 4px; + position: relative; margin: 0; white-space: nowrap; } .chzn-container-single .chzn-search input { - background: #fff url('chosen-sprite.png') no-repeat 100% -20px; - background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); - background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); - background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: #fff url('chosen-sprite.png') no-repeat 100% -22px; + background: url('chosen-sprite.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('chosen-sprite.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); margin: 1px 0; padding: 4px 20px 4px 5px; outline: 0; @@ -123,6 +131,11 @@ select.chzn-select { } /* @end */ +.chzn-container-single-nosearch .chzn-search input { + position: absolute; + left: -9000px; +} + /* @group Multi Chosen */ .chzn-container-multi .chzn-choices { background-color: #fff; @@ -197,18 +210,18 @@ select.chzn-select { .chzn-container-multi .chzn-choices .search-choice .search-choice-close { display: block; position: absolute; - right: 5px; - top: 6px; - width: 8px; - height: 9px; + right: 3px; + top: 4px; + width: 12px; + height: 13px; font-size: 1px; background: url(chosen-sprite.png) right top no-repeat; } .chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover { - background-position: right -9px; + background-position: right -11px; } .chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close { - background-position: right -9px; + background-position: right -11px; } /* @end */ @@ -226,6 +239,7 @@ select.chzn-select { padding: 0; } .chzn-container .chzn-results li { + display: none; line-height: 80%; padding: 7px 7px 8px; margin: 0; @@ -233,6 +247,7 @@ select.chzn-select { } .chzn-container .chzn-results .active-result { cursor: pointer; + display: list-item; } .chzn-container .chzn-results .highlighted { background: #3875d7; @@ -247,6 +262,7 @@ select.chzn-select { } .chzn-container .chzn-results .no-results { background: #f4f4f4; + display: list-item; } .chzn-container .chzn-results .group-result { cursor: default; @@ -309,6 +325,18 @@ select.chzn-select { } /* @end */ +/* @group Disabled Support */ +.chzn-disabled { + cursor: default; + opacity:0.5 !important; +} +.chzn-disabled .chzn-single { + cursor: default; +} +.chzn-disabled .chzn-choices .search-choice .search-choice-close { + cursor: default; +} + /* @group Right to Left */ .chzn-rtl { direction:rtl;text-align: right; } .chzn-rtl .chzn-single { padding-left: 0; padding-right: 8px; } @@ -327,14 +355,14 @@ select.chzn-select { .chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 20px; } .chzn-rtl.chzn-container-active .chzn-single-with-drop div { border-right: none; } .chzn-rtl .chzn-search input { - background: url('chosen-sprite.png') no-repeat -38px -20px, #ffffff; - background: url('chosen-sprite.png') no-repeat -38px -20px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); - background: url('chosen-sprite.png') no-repeat -38px -20px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat -38px -20px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat -38px -20px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); - background: url('chosen-sprite.png') no-repeat -38px -20px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); - background: url('chosen-sprite.png') no-repeat -38px -20px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); - background: url('chosen-sprite.png') no-repeat -38px -20px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, #ffffff; + background: url('chosen-sprite.png') no-repeat -38px -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('chosen-sprite.png') no-repeat -38px -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); padding: 4px 5px 4px 20px; } /* @end */ \ No newline at end of file diff --git a/3rdparty/js/chosen/VERSION b/3rdparty/js/chosen/VERSION index f374f6662e..b0bb878545 100644 --- a/3rdparty/js/chosen/VERSION +++ b/3rdparty/js/chosen/VERSION @@ -1 +1 @@ -0.9.1 +0.9.5 diff --git a/3rdparty/js/chosen/chosen.jquery.js b/3rdparty/js/chosen/chosen.jquery.js index 5ea409d90e..e7e661c096 100644 --- a/3rdparty/js/chosen/chosen.jquery.js +++ b/3rdparty/js/chosen/chosen.jquery.js @@ -1,7 +1,7 @@ // Chosen, a Select Box Enhancer for jQuery and Protoype // by Patrick Filler for Harvest, http://getharvest.com // -// Version 0.9 +// Version 0.9.5 // Full source at https://github.com/harvesthq/chosen // Copyright (c) 2011 Harvest http://getharvest.com @@ -16,18 +16,22 @@ root = this; $ = jQuery; $.fn.extend({ - chosen: function(data, options) { + chosen: function(options) { + if ($.browser === "msie" && ($.browser.version === "6.0" || $.browser.version === "7.0")) { + return this; + } return $(this).each(function(input_field) { if (!($(this)).hasClass("chzn-done")) { - return new Chosen(this, data, options); + return new Chosen(this, options); } }); } }); Chosen = (function() { - function Chosen(elmn) { + function Chosen(form_field, options) { + this.form_field = form_field; + this.options = options != null ? options : {}; this.set_default_values(); - this.form_field = elmn; this.form_field_jq = $(this.form_field); this.is_multiple = this.form_field.multiple; this.is_rtl = this.form_field_jq.hasClass("chzn-rtl"); @@ -40,22 +44,28 @@ this.click_test_action = __bind(function(evt) { return this.test_active_click(evt); }, this); + this.activate_action = __bind(function(evt) { + return this.activate_field(evt); + }, this); this.active_field = false; this.mouse_on_container = false; this.results_showing = false; this.result_highlighted = null; this.result_single_selected = null; - return this.choices = 0; + this.allow_single_deselect = (this.options.allow_single_deselect != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false; + this.disable_search_threshold = this.options.disable_search_threshold || 0; + this.choices = 0; + return this.results_none_found = this.options.no_results_text || "No results match"; }; Chosen.prototype.set_up_html = function() { var container_div, dd_top, dd_width, sf_width; this.container_id = this.form_field.id.length ? this.form_field.id.replace(/(:|\.)/g, '_') : this.generate_field_id(); this.container_id += "_chzn"; - this.f_width = this.form_field_jq.width(); + this.f_width = this.form_field_jq.outerWidth(); this.default_text = this.form_field_jq.data('placeholder') ? this.form_field_jq.data('placeholder') : this.default_text_default; container_div = $("
", { id: this.container_id, - "class": "chzn-container " + (this.is_rtl ? ' chzn-rtl' : void 0), + "class": "chzn-container" + (this.is_rtl ? ' chzn-rtl' : ''), style: 'width: ' + this.f_width + 'px;' }); if (this.is_multiple) { @@ -66,6 +76,9 @@ this.form_field_jq.hide().after(container_div); this.container = $('#' + this.container_id); this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single")); + if (!this.is_multiple && this.form_field.options.length <= this.disable_search_threshold) { + this.container.addClass("chzn-container-single-nosearch"); + } this.dropdown = this.container.find('div.chzn-drop').first(); dd_top = this.container.height(); dd_width = this.f_width - get_side_border_padding(this.dropdown); @@ -92,8 +105,11 @@ return this.set_tab_index(); }; Chosen.prototype.register_observers = function() { - this.container.click(__bind(function(evt) { - return this.container_click(evt); + this.container.mousedown(__bind(function(evt) { + return this.container_mousedown(evt); + }, this)); + this.container.mouseup(__bind(function(evt) { + return this.container_mouseup(evt); }, this)); this.container.mouseenter(__bind(function(evt) { return this.mouse_enter(evt); @@ -101,8 +117,8 @@ this.container.mouseleave(__bind(function(evt) { return this.mouse_leave(evt); }, this)); - this.search_results.click(__bind(function(evt) { - return this.search_results_click(evt); + this.search_results.mouseup(__bind(function(evt) { + return this.search_results_mouseup(evt); }, this)); this.search_results.mouseover(__bind(function(evt) { return this.search_results_mouseover(evt); @@ -129,30 +145,52 @@ return this.search_field.focus(__bind(function(evt) { return this.input_focus(evt); }, this)); - } else { - return this.selected_item.focus(__bind(function(evt) { - return this.activate_field(evt); - }, this)); } }; - Chosen.prototype.container_click = function(evt) { - if (evt && evt.type === "click") { - evt.stopPropagation(); - } - if (!this.pending_destroy_click) { - if (!this.active_field) { - if (this.is_multiple) { - this.search_field.val(""); - } - $(document).click(this.click_test_action); - this.results_show(); - } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) { - evt.preventDefault(); - this.results_toggle(); + Chosen.prototype.search_field_disabled = function() { + this.is_disabled = this.form_field_jq.attr('disabled'); + if (this.is_disabled) { + this.container.addClass('chzn-disabled'); + this.search_field.attr('disabled', true); + if (!this.is_multiple) { + this.selected_item.unbind("focus", this.activate_action); } - return this.activate_field(); + return this.close_field(); } else { - return this.pending_destroy_click = false; + this.container.removeClass('chzn-disabled'); + this.search_field.attr('disabled', false); + if (!this.is_multiple) { + return this.selected_item.bind("focus", this.activate_action); + } + } + }; + Chosen.prototype.container_mousedown = function(evt) { + var target_closelink; + if (!this.is_disabled) { + target_closelink = evt != null ? ($(evt.target)).hasClass("search-choice-close") : false; + if (evt && evt.type === "mousedown") { + evt.stopPropagation(); + } + if (!this.pending_destroy_click && !target_closelink) { + if (!this.active_field) { + if (this.is_multiple) { + this.search_field.val(""); + } + $(document).click(this.click_test_action); + this.results_show(); + } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) { + evt.preventDefault(); + this.results_toggle(); + } + return this.activate_field(); + } else { + return this.pending_destroy_click = false; + } + } + }; + Chosen.prototype.container_mouseup = function(evt) { + if (evt.target.nodeName === "ABBR") { + return this.results_reset(evt); } }; Chosen.prototype.mouse_enter = function() { @@ -164,7 +202,7 @@ Chosen.prototype.input_focus = function(evt) { if (!this.active_field) { return setTimeout((__bind(function() { - return this.container_click(); + return this.container_mousedown(); }, this)), 50); } }; @@ -235,9 +273,13 @@ this.choice_build(data); } else if (data.selected && !this.is_multiple) { this.selected_item.find("span").text(data.text); + if (this.allow_single_deselect) { + this.selected_item.find("span").first().after(""); + } } } } + this.search_field_disabled(); this.show_search_field_default(); this.search_field_scale(); this.search_results.html(content); @@ -252,7 +294,7 @@ } }; Chosen.prototype.result_add_option = function(option) { - var classes; + var classes, style; if (!option.disabled) { option.dom_id = this.container_id + "_o_" + option.array_index; classes = option.selected && this.is_multiple ? [] : ["active-result"]; @@ -262,7 +304,11 @@ if (option.group_array_index != null) { classes.push("group-option"); } - return '
  • ' + option.html + '
  • '; + if (option.classes !== "") { + classes.push(option.classes); + } + style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : ""; + return '
  • ' + option.html + '
  • '; } else { return ""; } @@ -353,12 +399,12 @@ return this.search_field.removeClass("default"); } }; - Chosen.prototype.search_results_click = function(evt) { + Chosen.prototype.search_results_mouseup = function(evt) { var target; target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); if (target.length) { this.result_highlight = target; - return this.result_select(); + return this.result_select(evt); } }; Chosen.prototype.search_results_mouseover = function(evt) { @@ -391,8 +437,12 @@ }; Chosen.prototype.choice_destroy_link_click = function(evt) { evt.preventDefault(); - this.pending_destroy_click = true; - return this.choice_destroy($(evt.target)); + if (!this.is_disabled) { + this.pending_destroy_click = true; + return this.choice_destroy($(evt.target)); + } else { + return evt.stopPropagation; + } }; Chosen.prototype.choice_destroy = function(link) { this.choices -= 1; @@ -403,18 +453,29 @@ this.result_deselect(link.attr("rel")); return link.parents('li').first().remove(); }; - Chosen.prototype.result_select = function() { + Chosen.prototype.results_reset = function(evt) { + this.form_field.options[0].selected = true; + this.selected_item.find("span").text(this.default_text); + this.show_search_field_default(); + $(evt.target).remove(); + this.form_field_jq.trigger("change"); + if (this.active_field) { + return this.results_hide(); + } + }; + Chosen.prototype.result_select = function(evt) { var high, high_id, item, position; if (this.result_highlight) { high = this.result_highlight; high_id = high.attr("id"); this.result_clear_highlight(); - high.addClass("result-selected"); if (this.is_multiple) { this.result_deactivate(high); } else { + this.search_results.find(".result-selected").removeClass("result-selected"); this.result_single_selected = high; } + high.addClass("result-selected"); position = high_id.substr(high_id.lastIndexOf("_") + 1); item = this.results_data[position]; item.selected = true; @@ -423,18 +484,23 @@ this.choice_build(item); } else { this.selected_item.find("span").first().text(item.text); + if (this.allow_single_deselect) { + this.selected_item.find("span").first().after(""); + } + } + if (!(evt.metaKey && this.is_multiple)) { + this.results_hide(); } - this.results_hide(); this.search_field.val(""); this.form_field_jq.trigger("change"); return this.search_field_scale(); } }; Chosen.prototype.result_activate = function(el) { - return el.addClass("active-result").show(); + return el.addClass("active-result"); }; Chosen.prototype.result_deactivate = function(el) { - return el.removeClass("active-result").hide(); + return el.removeClass("active-result"); }; Chosen.prototype.result_deselect = function(pos) { var result, result_data; @@ -530,17 +596,18 @@ return _results; }; Chosen.prototype.winnow_results_set_highlight = function() { - var do_high; + var do_high, selected_results; if (!this.result_highlight) { - do_high = this.search_results.find(".active-result").first(); - if (do_high) { + selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; + do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); + if (do_high != null) { return this.result_do_highlight(do_high); } } }; Chosen.prototype.no_results = function(terms) { var no_results_html; - no_results_html = $('
  • No results match ""
  • '); + no_results_html = $('
  • ' + this.results_none_found + ' ""
  • '); no_results_html.find("span").first().html(terms); return this.search_results.append(no_results_html); }; @@ -611,7 +678,7 @@ case 13: evt.preventDefault(); if (this.results_showing) { - return this.result_select(); + return this.result_select(evt); } break; case 27: @@ -623,6 +690,8 @@ case 38: case 40: case 16: + case 91: + case 17: break; default: return this.results_search(); @@ -758,7 +827,9 @@ html: option.innerHTML, selected: option.selected, disabled: group_disabled === true ? group_disabled : option.disabled, - group_array_index: group_position + group_array_index: group_position, + classes: option.className, + style: option.style.cssText }); } else { this.parsed.push({ diff --git a/3rdparty/js/chosen/chosen.jquery.min.js b/3rdparty/js/chosen/chosen.jquery.min.js index 1d6a6983d8..371ee53e7a 100644 --- a/3rdparty/js/chosen/chosen.jquery.min.js +++ b/3rdparty/js/chosen/chosen.jquery.min.js @@ -1,10 +1,10 @@ // Chosen, a Select Box Enhancer for jQuery and Protoype // by Patrick Filler for Harvest, http://getharvest.com // -// Version 0.9 +// Version 0.9.5 // Full source at https://github.com/harvesthq/chosen // Copyright (c) 2011 Harvest http://getharvest.com // MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md // This file is generated by `cake build`, do not edit it by hand. -(function(){var a,b,c,d,e=function(a,b){return function(){return a.apply(b,arguments)}};d=this,a=jQuery,a.fn.extend({chosen:function(c,d){return a(this).each(function(e){if(!a(this).hasClass("chzn-done"))return new b(this,c,d)})}}),b=function(){function b(b){this.set_default_values(),this.form_field=b,this.form_field_jq=a(this.form_field),this.is_multiple=this.form_field.multiple,this.is_rtl=this.form_field_jq.hasClass("chzn-rtl"),this.default_text_default=this.form_field.multiple?"Select Some Options":"Select an Option",this.set_up_html(),this.register_observers(),this.form_field_jq.addClass("chzn-done")}b.prototype.set_default_values=function(){this.click_test_action=e(function(a){return this.test_active_click(a)},this),this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.result_single_selected=null;return this.choices=0},b.prototype.set_up_html=function(){var b,d,e,f;this.container_id=this.form_field.id.length?this.form_field.id.replace(/(:|\.)/g,"_"):this.generate_field_id(),this.container_id+="_chzn",this.f_width=this.form_field_jq.width(),this.default_text=this.form_field_jq.data("placeholder")?this.form_field_jq.data("placeholder"):this.default_text_default,b=a("
    ",{id:this.container_id,"class":"chzn-container "+(this.is_rtl?" chzn-rtl":void 0),style:"width: "+this.f_width+"px;"}),this.is_multiple?b.html('
      '):b.html(''+this.default_text+'
        '),this.form_field_jq.hide().after(b),this.container=a("#"+this.container_id),this.container.addClass("chzn-container-"+(this.is_multiple?"multi":"single")),this.dropdown=this.container.find("div.chzn-drop").first(),d=this.container.height(),e=this.f_width-c(this.dropdown),this.dropdown.css({width:e+"px",top:d+"px"}),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chzn-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chzn-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chzn-search").first(),this.selected_item=this.container.find(".chzn-single").first(),f=e-c(this.search_container)-c(this.search_field),this.search_field.css({width:f+"px"})),this.results_build();return this.set_tab_index()},b.prototype.register_observers=function(){this.container.click(e(function(a){return this.container_click(a)},this)),this.container.mouseenter(e(function(a){return this.mouse_enter(a)},this)),this.container.mouseleave(e(function(a){return this.mouse_leave(a)},this)),this.search_results.click(e(function(a){return this.search_results_click(a)},this)),this.search_results.mouseover(e(function(a){return this.search_results_mouseover(a)},this)),this.search_results.mouseout(e(function(a){return this.search_results_mouseout(a)},this)),this.form_field_jq.bind("liszt:updated",e(function(a){return this.results_update_field(a)},this)),this.search_field.blur(e(function(a){return this.input_blur(a)},this)),this.search_field.keyup(e(function(a){return this.keyup_checker(a)},this)),this.search_field.keydown(e(function(a){return this.keydown_checker(a)},this));if(this.is_multiple){this.search_choices.click(e(function(a){return this.choices_click(a)},this));return this.search_field.focus(e(function(a){return this.input_focus(a)},this))}return this.selected_item.focus(e(function(a){return this.activate_field(a)},this))},b.prototype.container_click=function(b){b&&b.type==="click"&&b.stopPropagation();if(!this.pending_destroy_click){this.active_field?!this.is_multiple&&b&&(a(b.target)===this.selected_item||a(b.target).parents("a.chzn-single").length)&&(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(document).click(this.click_test_action),this.results_show());return this.activate_field()}return this.pending_destroy_click=!1},b.prototype.mouse_enter=function(){return this.mouse_on_container=!0},b.prototype.mouse_leave=function(){return this.mouse_on_container=!1},b.prototype.input_focus=function(a){if(!this.active_field)return setTimeout(e(function(){return this.container_click()},this),50)},b.prototype.input_blur=function(a){if(!this.mouse_on_container){this.active_field=!1;return setTimeout(e(function(){return this.blur_test()},this),100)}},b.prototype.blur_test=function(a){if(!this.active_field&&this.container.hasClass("chzn-container-active"))return this.close_field()},b.prototype.close_field=function(){a(document).unbind("click",this.click_test_action),this.is_multiple||(this.selected_item.attr("tabindex",this.search_field.attr("tabindex")),this.search_field.attr("tabindex",-1)),this.active_field=!1,this.results_hide(),this.container.removeClass("chzn-container-active"),this.winnow_results_clear(),this.clear_backstroke(),this.show_search_field_default();return this.search_field_scale()},b.prototype.activate_field=function(){!this.is_multiple&&!this.active_field&&(this.search_field.attr("tabindex",this.selected_item.attr("tabindex")),this.selected_item.attr("tabindex",-1)),this.container.addClass("chzn-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val());return this.search_field.focus()},b.prototype.test_active_click=function(b){return a(b.target).parents("#"+this.container_id).length?this.active_field=!0:this.close_field()},b.prototype.results_build=function(){var a,b,c,e,f,g;c=new Date,this.parsing=!0,this.results_data=d.SelectParser.select_to_array(this.form_field),this.is_multiple&&this.choices>0?(this.search_choices.find("li.search-choice").remove(),this.choices=0):this.is_multiple||this.selected_item.find("span").text(this.default_text),a="",g=this.results_data;for(e=0,f=g.length;e'+a("
        ").text(b.label).html()+""}return""},b.prototype.result_add_option=function(a){var b;if(!a.disabled){a.dom_id=this.container_id+"_o_"+a.array_index,b=a.selected&&this.is_multiple?[]:["active-result"],a.selected&&b.push("result-selected"),a.group_array_index!=null&&b.push("group-option");return'
      • '+a.html+"
      • "}return""},b.prototype.results_update_field=function(){this.result_clear_highlight(),this.result_single_selected=null;return this.results_build()},b.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight();if(b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(c'+b.html+''),d=a("#"+c).find("a").first();return d.click(e(function(a){return this.choice_destroy_link_click(a)},this))},b.prototype.choice_destroy_link_click=function(b){b.preventDefault(),this.pending_destroy_click=!0;return this.choice_destroy(a(b.target))},b.prototype.choice_destroy=function(a){this.choices-=1,this.show_search_field_default(),this.is_multiple&&this.choices>0&&this.search_field.val().length<1&&this.results_hide(),this.result_deselect(a.attr("rel"));return a.parents("li").first().remove()},b.prototype.result_select=function(){var a,b,c,d;if(this.result_highlight){a=this.result_highlight,b=a.attr("id"),this.result_clear_highlight(),a.addClass("result-selected"),this.is_multiple?this.result_deactivate(a):this.result_single_selected=a,d=b.substr(b.lastIndexOf("_")+1),c=this.results_data[d],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.is_multiple?this.choice_build(c):this.selected_item.find("span").first().text(c.text),this.results_hide(),this.search_field.val(""),this.form_field_jq.trigger("change");return this.search_field_scale()}},b.prototype.result_activate=function(a){return a.addClass("active-result").show()},b.prototype.result_deactivate=function(a){return a.removeClass("active-result").hide()},b.prototype.result_deselect=function(b){var c,d;d=this.results_data[b],d.selected=!1,this.form_field.options[d.options_index].selected=!1,c=a("#"+this.container_id+"_o_"+b),c.removeClass("result-selected").addClass("active-result").show(),this.result_clear_highlight(),this.winnow_results(),this.form_field_jq.trigger("change");return this.search_field_scale()},b.prototype.results_search=function(a){return this.results_showing?this.winnow_results():this.results_show()},b.prototype.winnow_results=function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;j=new Date,this.no_results_clear(),h=0,i=this.search_field.val()===this.default_text?"":a("
        ").text(a.trim(this.search_field.val())).html(),f=new RegExp("^"+i.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),m=new RegExp(i.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),r=this.results_data;for(n=0,p=r.length;n=0||c.html.indexOf("[")===0){e=c.html.replace(/\[|\]/g,"").split(" ");if(e.length)for(o=0,q=e.length;o"+c.html.substr(k+i.length),l=l.substr(0,k)+""+l.substr(k)):l=c.html,a("#"+g).html!==l&&a("#"+g).html(l),this.result_activate(a("#"+g)),c.group_array_index!=null&&a("#"+this.results_data[c.group_array_index].dom_id).show()):(this.result_highlight&&g===this.result_highlight.attr("id")&&this.result_clear_highlight(),this.result_deactivate(a("#"+g)))}}return h<1&&i.length?this.no_results(i):this.winnow_results_set_highlight()},b.prototype.winnow_results_clear=function(){var b,c,d,e,f;this.search_field.val(""),c=this.search_results.find("li"),f=[];for(d=0,e=c.length;dNo results match ""'),c.find("span").first().html(b);return this.search_results.append(c)},b.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},b.prototype.keydown_arrow=function(){var b,c;this.result_highlight?this.results_showing&&(c=this.result_highlight.nextAll("li.active-result").first(),c&&this.result_do_highlight(c)):(b=this.search_results.find("li.active-result").first(),b&&this.result_do_highlight(a(b)));if(!this.results_showing)return this.results_show()},b.prototype.keyup_arrow=function(){var a;if(!this.results_showing&&!this.is_multiple)return this.results_show();if(this.result_highlight){a=this.result_highlight.prevAll("li.active-result");if(a.length)return this.result_do_highlight(a.first());this.choices>0&&this.results_hide();return this.result_clear_highlight()}},b.prototype.keydown_backstroke=function(){if(this.pending_backstroke){this.choice_destroy(this.pending_backstroke.find("a").first());return this.clear_backstroke()}this.pending_backstroke=this.search_container.siblings("li.search-choice").last();return this.pending_backstroke.addClass("search-choice-focus")},b.prototype.clear_backstroke=function(){this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus");return this.pending_backstroke=null},b.prototype.keyup_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale();switch(b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices>0)return this.keydown_backstroke();if(!this.pending_backstroke){this.result_clear_highlight();return this.results_search()}break;case 13:a.preventDefault();if(this.results_showing)return this.result_select();break;case 27:if(this.results_showing)return this.results_hide();break;case 9:case 38:case 40:case 16:break;default:return this.results_search()}},b.prototype.keydown_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale(),b!==8&&this.pending_backstroke&&this.clear_backstroke();switch(b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:this.keydown_arrow()}},b.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"];for(i=0,j=g.length;i",{style:f}),c.text(this.search_field.val()),a("body").append(c),h=c.width()+25,c.remove(),h>this.f_width-10&&(h=this.f_width-10),this.search_field.css({width:h+"px"}),b=this.container.height();return this.dropdown.css({top:b+"px"})}},b.prototype.generate_field_id=function(){var a;a=this.generate_random_id(),this.form_field.id=a;return a},b.prototype.generate_random_id=function(){var b;b="sel"+this.generate_random_char()+this.generate_random_char()+this.generate_random_char();while(a("#"+b).length>0)b+=this.generate_random_char();return b},b.prototype.generate_random_char=function(){var a,b,c;a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ",c=Math.floor(Math.random()*a.length);return b=a.substring(c,c+1)};return b}(),c=function(a){var b;return b=a.outerWidth()-a.width()},d.get_side_border_padding=c}).call(this),function(){var a;a=function(){function a(){this.options_index=0,this.parsed=[]}a.prototype.add_node=function(a){return a.nodeName==="OPTGROUP"?this.add_group(a):this.add_option(a)},a.prototype.add_group=function(a){var b,c,d,e,f,g;b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:a.label,children:0,disabled:a.disabled}),f=a.childNodes,g=[];for(d=0,e=f.length;d",{id:this.container_id,"class":"chzn-container"+(this.is_rtl?" chzn-rtl":""),style:"width: "+this.f_width+"px;"}),this.is_multiple?b.html('
          '):b.html(''+this.default_text+'
            '),this.form_field_jq.hide().after(b),this.container=a("#"+this.container_id),this.container.addClass("chzn-container-"+(this.is_multiple?"multi":"single")),!this.is_multiple&&this.form_field.options.length<=this.disable_search_threshold&&this.container.addClass("chzn-container-single-nosearch"),this.dropdown=this.container.find("div.chzn-drop").first(),d=this.container.height(),e=this.f_width-c(this.dropdown),this.dropdown.css({width:e+"px",top:d+"px"}),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chzn-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chzn-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chzn-search").first(),this.selected_item=this.container.find(".chzn-single").first(),f=e-c(this.search_container)-c(this.search_field),this.search_field.css({width:f+"px"})),this.results_build();return this.set_tab_index()},b.prototype.register_observers=function(){this.container.mousedown(e(function(a){return this.container_mousedown(a)},this)),this.container.mouseup(e(function(a){return this.container_mouseup(a)},this)),this.container.mouseenter(e(function(a){return this.mouse_enter(a)},this)),this.container.mouseleave(e(function(a){return this.mouse_leave(a)},this)),this.search_results.mouseup(e(function(a){return this.search_results_mouseup(a)},this)),this.search_results.mouseover(e(function(a){return this.search_results_mouseover(a)},this)),this.search_results.mouseout(e(function(a){return this.search_results_mouseout(a)},this)),this.form_field_jq.bind("liszt:updated",e(function(a){return this.results_update_field(a)},this)),this.search_field.blur(e(function(a){return this.input_blur(a)},this)),this.search_field.keyup(e(function(a){return this.keyup_checker(a)},this)),this.search_field.keydown(e(function(a){return this.keydown_checker(a)},this));if(this.is_multiple){this.search_choices.click(e(function(a){return this.choices_click(a)},this));return this.search_field.focus(e(function(a){return this.input_focus(a)},this))}},b.prototype.search_field_disabled=function(){this.is_disabled=this.form_field_jq.attr("disabled");if(this.is_disabled){this.container.addClass("chzn-disabled"),this.search_field.attr("disabled",!0),this.is_multiple||this.selected_item.unbind("focus",this.activate_action);return this.close_field()}this.container.removeClass("chzn-disabled"),this.search_field.attr("disabled",!1);if(!this.is_multiple)return this.selected_item.bind("focus",this.activate_action)},b.prototype.container_mousedown=function(b){var c;if(!this.is_disabled){c=b!=null?a(b.target).hasClass("search-choice-close"):!1,b&&b.type==="mousedown"&&b.stopPropagation();if(!this.pending_destroy_click&&!c){this.active_field?!this.is_multiple&&b&&(a(b.target)===this.selected_item||a(b.target).parents("a.chzn-single").length)&&(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(document).click(this.click_test_action),this.results_show());return this.activate_field()}return this.pending_destroy_click=!1}},b.prototype.container_mouseup=function(a){if(a.target.nodeName==="ABBR")return this.results_reset(a)},b.prototype.mouse_enter=function(){return this.mouse_on_container=!0},b.prototype.mouse_leave=function(){return this.mouse_on_container=!1},b.prototype.input_focus=function(a){if(!this.active_field)return setTimeout(e(function(){return this.container_mousedown()},this),50)},b.prototype.input_blur=function(a){if(!this.mouse_on_container){this.active_field=!1;return setTimeout(e(function(){return this.blur_test()},this),100)}},b.prototype.blur_test=function(a){if(!this.active_field&&this.container.hasClass("chzn-container-active"))return this.close_field()},b.prototype.close_field=function(){a(document).unbind("click",this.click_test_action),this.is_multiple||(this.selected_item.attr("tabindex",this.search_field.attr("tabindex")),this.search_field.attr("tabindex",-1)),this.active_field=!1,this.results_hide(),this.container.removeClass("chzn-container-active"),this.winnow_results_clear(),this.clear_backstroke(),this.show_search_field_default();return this.search_field_scale()},b.prototype.activate_field=function(){!this.is_multiple&&!this.active_field&&(this.search_field.attr("tabindex",this.selected_item.attr("tabindex")),this.selected_item.attr("tabindex",-1)),this.container.addClass("chzn-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val());return this.search_field.focus()},b.prototype.test_active_click=function(b){return a(b.target).parents("#"+this.container_id).length?this.active_field=!0:this.close_field()},b.prototype.results_build=function(){var a,b,c,e,f,g;c=new Date,this.parsing=!0,this.results_data=d.SelectParser.select_to_array(this.form_field),this.is_multiple&&this.choices>0?(this.search_choices.find("li.search-choice").remove(),this.choices=0):this.is_multiple||this.selected_item.find("span").text(this.default_text),a="",g=this.results_data;for(e=0,f=g.length;e')));this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.search_results.html(a);return this.parsing=!1},b.prototype.result_add_group=function(b){if(!b.disabled){b.dom_id=this.container_id+"_g_"+b.array_index;return'
          • '+a("
            ").text(b.label).html()+"
          • "}return""},b.prototype.result_add_option=function(a){var b,c;if(!a.disabled){a.dom_id=this.container_id+"_o_"+a.array_index,b=a.selected&&this.is_multiple?[]:["active-result"],a.selected&&b.push("result-selected"),a.group_array_index!=null&&b.push("group-option"),a.classes!==""&&b.push(a.classes),c=a.style.cssText!==""?' style="'+a.style+'"':"";return'
          • "+a.html+"
          • "}return""},b.prototype.results_update_field=function(){this.result_clear_highlight(),this.result_single_selected=null;return this.results_build()},b.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight();if(b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(c'+b.html+''),d=a("#"+c).find("a").first();return d.click(e(function(a){return this.choice_destroy_link_click(a)},this))},b.prototype.choice_destroy_link_click=function(b){b.preventDefault();if(!this.is_disabled){this.pending_destroy_click=!0;return this.choice_destroy(a(b.target))}return b.stopPropagation},b.prototype.choice_destroy=function(a){this.choices-=1,this.show_search_field_default(),this.is_multiple&&this.choices>0&&this.search_field.val().length<1&&this.results_hide(),this.result_deselect(a.attr("rel"));return a.parents("li").first().remove()},b.prototype.results_reset=function(b){this.form_field.options[0].selected=!0,this.selected_item.find("span").text(this.default_text),this.show_search_field_default(),a(b.target).remove(),this.form_field_jq.trigger("change");if(this.active_field)return this.results_hide()},b.prototype.result_select=function(a){var b,c,d,e;if(this.result_highlight){b=this.result_highlight,c=b.attr("id"),this.result_clear_highlight(),this.is_multiple?this.result_deactivate(b):(this.search_results.find(".result-selected").removeClass("result-selected"),this.result_single_selected=b),b.addClass("result-selected"),e=c.substr(c.lastIndexOf("_")+1),d=this.results_data[e],d.selected=!0,this.form_field.options[d.options_index].selected=!0,this.is_multiple?this.choice_build(d):(this.selected_item.find("span").first().text(d.text),this.allow_single_deselect&&this.selected_item.find("span").first().after('')),(!a.metaKey||!this.is_multiple)&&this.results_hide(),this.search_field.val(""),this.form_field_jq.trigger("change");return this.search_field_scale()}},b.prototype.result_activate=function(a){return a.addClass("active-result")},b.prototype.result_deactivate=function(a){return a.removeClass("active-result")},b.prototype.result_deselect=function(b){var c,d;d=this.results_data[b],d.selected=!1,this.form_field.options[d.options_index].selected=!1,c=a("#"+this.container_id+"_o_"+b),c.removeClass("result-selected").addClass("active-result").show(),this.result_clear_highlight(),this.winnow_results(),this.form_field_jq.trigger("change");return this.search_field_scale()},b.prototype.results_search=function(a){return this.results_showing?this.winnow_results():this.results_show()},b.prototype.winnow_results=function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;j=new Date,this.no_results_clear(),h=0,i=this.search_field.val()===this.default_text?"":a("
            ").text(a.trim(this.search_field.val())).html(),f=new RegExp("^"+i.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),m=new RegExp(i.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),r=this.results_data;for(n=0,p=r.length;n=0||c.html.indexOf("[")===0){e=c.html.replace(/\[|\]/g,"").split(" ");if(e.length)for(o=0,q=e.length;o"+c.html.substr(k+i.length),l=l.substr(0,k)+""+l.substr(k)):l=c.html,a("#"+g).html!==l&&a("#"+g).html(l),this.result_activate(a("#"+g)),c.group_array_index!=null&&a("#"+this.results_data[c.group_array_index].dom_id).show()):(this.result_highlight&&g===this.result_highlight.attr("id")&&this.result_clear_highlight(),this.result_deactivate(a("#"+g)))}}return h<1&&i.length?this.no_results(i):this.winnow_results_set_highlight()},b.prototype.winnow_results_clear=function(){var b,c,d,e,f;this.search_field.val(""),c=this.search_results.find("li"),f=[];for(d=0,e=c.length;d'+this.results_none_found+' ""'),c.find("span").first().html(b);return this.search_results.append(c)},b.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},b.prototype.keydown_arrow=function(){var b,c;this.result_highlight?this.results_showing&&(c=this.result_highlight.nextAll("li.active-result").first(),c&&this.result_do_highlight(c)):(b=this.search_results.find("li.active-result").first(),b&&this.result_do_highlight(a(b)));if(!this.results_showing)return this.results_show()},b.prototype.keyup_arrow=function(){var a;if(!this.results_showing&&!this.is_multiple)return this.results_show();if(this.result_highlight){a=this.result_highlight.prevAll("li.active-result");if(a.length)return this.result_do_highlight(a.first());this.choices>0&&this.results_hide();return this.result_clear_highlight()}},b.prototype.keydown_backstroke=function(){if(this.pending_backstroke){this.choice_destroy(this.pending_backstroke.find("a").first());return this.clear_backstroke()}this.pending_backstroke=this.search_container.siblings("li.search-choice").last();return this.pending_backstroke.addClass("search-choice-focus")},b.prototype.clear_backstroke=function(){this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus");return this.pending_backstroke=null},b.prototype.keyup_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale();switch(b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices>0)return this.keydown_backstroke();if(!this.pending_backstroke){this.result_clear_highlight();return this.results_search()}break;case 13:a.preventDefault();if(this.results_showing)return this.result_select(a);break;case 27:if(this.results_showing)return this.results_hide();break;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},b.prototype.keydown_checker=function(a){var b,c;b=(c=a.which)!=null?c:a.keyCode,this.search_field_scale(),b!==8&&this.pending_backstroke&&this.clear_backstroke();switch(b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:this.keydown_arrow()}},b.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"];for(i=0,j=g.length;i",{style:f}),c.text(this.search_field.val()),a("body").append(c),h=c.width()+25,c.remove(),h>this.f_width-10&&(h=this.f_width-10),this.search_field.css({width:h+"px"}),b=this.container.height();return this.dropdown.css({top:b+"px"})}},b.prototype.generate_field_id=function(){var a;a=this.generate_random_id(),this.form_field.id=a;return a},b.prototype.generate_random_id=function(){var b;b="sel"+this.generate_random_char()+this.generate_random_char()+this.generate_random_char();while(a("#"+b).length>0)b+=this.generate_random_char();return b},b.prototype.generate_random_char=function(){var a,b,c;a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ",c=Math.floor(Math.random()*a.length);return b=a.substring(c,c+1)};return b}(),c=function(a){var b;return b=a.outerWidth()-a.width()},d.get_side_border_padding=c}).call(this),function(){var a;a=function(){function a(){this.options_index=0,this.parsed=[]}a.prototype.add_node=function(a){return a.nodeName==="OPTGROUP"?this.add_group(a):this.add_option(a)},a.prototype.add_group=function(a){var b,c,d,e,f,g;b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:a.label,children:0,disabled:a.disabled}),f=a.childNodes,g=[];for(d=0,e=f.length;d + * Location: http://github.com/tplaner/When + * Created: September 2010 + * Description: Determines the next date of recursion given an iCalendar "rrule" like pattern. + * Requirements: PHP 5.3+ - makes extensive use of the Date and Time library (http://us2.php.net/manual/en/book.datetime.php) + */ +class When +{ + protected $frequency; + + protected $start_date; + protected $try_date; + + protected $end_date; + + protected $gobymonth; + protected $bymonth; + + protected $gobyweekno; + protected $byweekno; + + protected $gobyyearday; + protected $byyearday; + + protected $gobymonthday; + protected $bymonthday; + + protected $gobyday; + protected $byday; + + protected $gobysetpos; + protected $bysetpos; + + protected $suggestions; + + protected $count; + protected $counter; + + protected $goenddate; + + protected $interval; + + protected $wkst; + + protected $valid_week_days; + protected $valid_frequency; + + /** + * __construct + */ + public function __construct() + { + $this->frequency = null; + + $this->gobymonth = false; + $this->bymonth = range(1,12); + + $this->gobymonthday = false; + $this->bymonthday = range(1,31); + + $this->gobyday = false; + // setup the valid week days (0 = sunday) + $this->byday = range(0,6); + + $this->gobyyearday = false; + $this->byyearday = range(0,366); + + $this->gobysetpos = false; + $this->bysetpos = range(1,366); + + $this->gobyweekno = false; + // setup the range for valid weeks + $this->byweekno = range(0,54); + + $this->suggestions = array(); + + // this will be set if a count() is specified + $this->count = 0; + // how many *valid* results we returned + $this->counter = 0; + + // max date we'll return + $this->end_date = new DateTime('9999-12-31'); + + // the interval to increase the pattern by + $this->interval = 1; + + // what day does the week start on? (0 = sunday) + $this->wkst = 0; + + $this->valid_week_days = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'); + + $this->valid_frequency = array('SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'); + } + + /** + * @param DateTime|string $start_date of the recursion - also is the first return value. + * @param string $frequency of the recrusion, valid frequencies: secondly, minutely, hourly, daily, weekly, monthly, yearly + */ + public function recur($start_date, $frequency = "daily") + { + try + { + if(is_object($start_date)) + { + $this->start_date = clone $start_date; + } + else + { + // timestamps within the RFC have a 'Z' at the end of them, remove this. + $start_date = trim($start_date, 'Z'); + $this->start_date = new DateTime($start_date); + } + + $this->try_date = clone $this->start_date; + } + catch(Exception $e) + { + throw new InvalidArgumentException('Invalid start date DateTime: ' . $e); + } + + $this->freq($frequency); + + return $this; + } + + public function freq($frequency) + { + if(in_array(strtoupper($frequency), $this->valid_frequency)) + { + $this->frequency = strtoupper($frequency); + } + else + { + throw new InvalidArgumentException('Invalid frequency type.'); + } + + return $this; + } + + // accepts an rrule directly + public function rrule($rrule) + { + // strip off a trailing semi-colon + $rrule = trim($rrule, ";"); + + $parts = explode(";", $rrule); + + foreach($parts as $part) + { + list($rule, $param) = explode("=", $part); + + $rule = strtoupper($rule); + $param = strtoupper($param); + + switch($rule) + { + case "FREQ": + $this->frequency = $param; + break; + case "UNTIL": + $this->until($param); + break; + case "COUNT": + $this->count($param); + break; + case "INTERVAL": + $this->interval($param); + break; + case "BYDAY": + $params = explode(",", $param); + $this->byday($params); + break; + case "BYMONTHDAY": + $params = explode(",", $param); + $this->bymonthday($params); + break; + case "BYYEARDAY": + $params = explode(",", $param); + $this->byyearday($params); + break; + case "BYWEEKNO": + $params = explode(",", $param); + $this->byweekno($params); + break; + case "BYMONTH": + $params = explode(",", $param); + $this->bymonth($params); + break; + case "BYSETPOS": + $params = explode(",", $param); + $this->bysetpos($params); + break; + case "WKST": + $this->wkst($param); + break; + } + } + + return $this; + } + + //max number of items to return based on the pattern + public function count($count) + { + $this->count = (int)$count; + + return $this; + } + + // how often the recurrence rule repeats + public function interval($interval) + { + $this->interval = (int)$interval; + + return $this; + } + + // starting day of the week + public function wkst($day) + { + switch($day) + { + case 'SU': + $this->wkst = 0; + break; + case 'MO': + $this->wkst = 1; + break; + case 'TU': + $this->wkst = 2; + break; + case 'WE': + $this->wkst = 3; + break; + case 'TH': + $this->wkst = 4; + break; + case 'FR': + $this->wkst = 5; + break; + case 'SA': + $this->wkst = 6; + break; + } + + return $this; + } + + // max date + public function until($end_date) + { + try + { + if(is_object($end_date)) + { + $this->end_date = clone $end_date; + } + else + { + // timestamps within the RFC have a 'Z' at the end of them, remove this. + $end_date = trim($end_date, 'Z'); + $this->end_date = new DateTime($end_date); + } + } + catch(Exception $e) + { + throw new InvalidArgumentException('Invalid end date DateTime: ' . $e); + } + + return $this; + } + + public function bymonth($months) + { + if(is_array($months)) + { + $this->gobymonth = true; + $this->bymonth = $months; + } + + return $this; + } + + public function bymonthday($days) + { + if(is_array($days)) + { + $this->gobymonthday = true; + $this->bymonthday = $days; + } + + return $this; + } + + public function byweekno($weeks) + { + $this->gobyweekno = true; + + if(is_array($weeks)) + { + $this->byweekno = $weeks; + } + + return $this; + } + + public function bysetpos($days) + { + $this->gobysetpos = true; + + if(is_array($days)) + { + $this->bysetpos = $days; + } + + return $this; + } + + public function byday($days) + { + $this->gobyday = true; + + if(is_array($days)) + { + $this->byday = array(); + foreach($days as $day) + { + $len = strlen($day); + + $as = '+'; + + // 0 mean no occurence is set + $occ = 0; + + if($len == 3) + { + $occ = substr($day, 0, 1); + } + if($len == 4) + { + $as = substr($day, 0, 1); + $occ = substr($day, 1, 1); + } + + if($as == '-') + { + $occ = '-' . $occ; + } + else + { + $occ = '+' . $occ; + } + + $day = substr($day, -2, 2); + switch($day) + { + case 'SU': + $this->byday[] = $occ . 'SU'; + break; + case 'MO': + $this->byday[] = $occ . 'MO'; + break; + case 'TU': + $this->byday[] = $occ . 'TU'; + break; + case 'WE': + $this->byday[] = $occ . 'WE'; + break; + case 'TH': + $this->byday[] = $occ . 'TH'; + break; + case 'FR': + $this->byday[] = $occ . 'FR'; + break; + case 'SA': + $this->byday[] = $occ . 'SA'; + break; + } + } + } + + return $this; + } + + public function byyearday($days) + { + $this->gobyyearday = true; + + if(is_array($days)) + { + $this->byyearday = $days; + } + + return $this; + } + + // this creates a basic list of dates to "try" + protected function create_suggestions() + { + switch($this->frequency) + { + case "YEARLY": + $interval = 'year'; + break; + case "MONTHLY": + $interval = 'month'; + break; + case "WEEKLY": + $interval = 'week'; + break; + case "DAILY": + $interval = 'day'; + break; + case "HOURLY": + $interval = 'hour'; + break; + case "MINUTELY": + $interval = 'minute'; + break; + case "SECONDLY": + $interval = 'second'; + break; + } + + $month_day = $this->try_date->format('j'); + $month = $this->try_date->format('n'); + $year = $this->try_date->format('Y'); + + $timestamp = $this->try_date->format('H:i:s'); + + if($this->gobysetpos) + { + if($this->try_date == $this->start_date) + { + $this->suggestions[] = clone $this->try_date; + } + else + { + if($this->gobyday) + { + foreach($this->bysetpos as $_pos) + { + $tmp_array = array(); + $_mdays = range(1, date('t',mktime(0,0,0,$month,1,$year))); + foreach($_mdays as $_mday) + { + $date_time = new DateTime($year . '-' . $month . '-' . $_mday . ' ' . $timestamp); + + $occur = ceil($_mday / 7); + + $day_of_week = $date_time->format('l'); + $dow_abr = strtoupper(substr($day_of_week, 0, 2)); + + // set the day of the month + (positive) + $occur = '+' . $occur . $dow_abr; + $occur_zero = '+0' . $dow_abr; + + // set the day of the month - (negative) + $total_days = $date_time->format('t') - $date_time->format('j'); + $occur_neg = '-' . ceil(($total_days + 1)/7) . $dow_abr; + + $day_from_end_of_month = $date_time->format('t') + 1 - $_mday; + + if(in_array($occur, $this->byday) || in_array($occur_zero, $this->byday) || in_array($occur_neg, $this->byday)) + { + $tmp_array[] = clone $date_time; + } + } + + if($_pos > 0) + { + $this->suggestions[] = clone $tmp_array[$_pos - 1]; + } + else + { + $this->suggestions[] = clone $tmp_array[count($tmp_array) + $_pos]; + } + + } + } + } + } + elseif($this->gobyyearday) + { + foreach($this->byyearday as $_day) + { + if($_day >= 0) + { + $_day--; + + $_time = strtotime('+' . $_day . ' days', mktime(0, 0, 0, 1, 1, $year)); + $this->suggestions[] = new Datetime(date('Y-m-d', $_time) . ' ' . $timestamp); + } + else + { + $year_day_neg = 365 + $_day; + $leap_year = $this->try_date->format('L'); + if($leap_year == 1) + { + $year_day_neg = 366 + $_day; + } + + $_time = strtotime('+' . $year_day_neg . ' days', mktime(0, 0, 0, 1, 1, $year)); + $this->suggestions[] = new Datetime(date('Y-m-d', $_time) . ' ' . $timestamp); + } + } + } + // special case because for years you need to loop through the months too + elseif($this->gobyday && $interval == "year") + { + foreach($this->bymonth as $_month) + { + // this creates an array of days of the month + $_mdays = range(1, date('t',mktime(0,0,0,$_month,1,$year))); + foreach($_mdays as $_mday) + { + $date_time = new DateTime($year . '-' . $_month . '-' . $_mday . ' ' . $timestamp); + + // get the week of the month (1, 2, 3, 4, 5, etc) + $week = $date_time->format('W'); + + if($date_time >= $this->start_date && in_array($week, $this->byweekno)) + { + $this->suggestions[] = clone $date_time; + } + } + } + } + elseif($interval == "day") + { + $this->suggestions[] = clone $this->try_date; + } + elseif($interval == "week") + { + $this->suggestions[] = clone $this->try_date; + + if($this->gobyday) + { + $week_day = $this->try_date->format('w'); + + $days_in_month = $this->try_date->format('t'); + + $overflow_count = 1; + $_day = $month_day; + + $run = true; + while($run) + { + $_day++; + if($_day <= $days_in_month) + { + $tmp_date = new DateTime($year . '-' . $month . '-' . $_day . ' ' . $timestamp); + } + else + { + //$tmp_month = $month+1; + $tmp_date = new DateTime($year . '-' . $month . '-' . $overflow_count . ' ' . $timestamp); + $tmp_date->modify('+1 month'); + $overflow_count++; + } + + $week_day = $tmp_date->format('w'); + + if($this->try_date == $this->start_date) + { + if($week_day == $this->wkst) + { + $this->try_date = clone $tmp_date; + $this->try_date->modify('-7 days'); + $run = false; + } + } + + if($week_day != $this->wkst) + { + $this->suggestions[] = clone $tmp_date; + } + else + { + $run = false; + } + } + } + } + elseif($this->gobyday || $interval == "month") + { + $_mdays = range(1, date('t',mktime(0,0,0,$month,1,$year))); + foreach($_mdays as $_mday) + { + $date_time = new DateTime($year . '-' . $month . '-' . $_mday . ' ' . $timestamp); + + // get the week of the month (1, 2, 3, 4, 5, etc) + $week = $date_time->format('W'); + + if($date_time >= $this->start_date && in_array($week, $this->byweekno)) + { + $this->suggestions[] = clone $date_time; + } + } + } + elseif($this->gobymonth) + { + foreach($this->bymonth as $_month) + { + $date_time = new DateTime($year . '-' . $_month . '-' . $month_day . ' ' . $timestamp); + + if($date_time >= $this->start_date) + { + $this->suggestions[] = clone $date_time; + } + } + } + else + { + $this->suggestions[] = clone $this->try_date; + } + + if($interval == "month") + { + $this->try_date->modify('last day of ' . $this->interval . ' ' . $interval); + } + else + { + $this->try_date->modify($this->interval . ' ' . $interval); + } + } + + protected function valid_date($date) + { + $year = $date->format('Y'); + $month = $date->format('n'); + $day = $date->format('j'); + + $year_day = $date->format('z') + 1; + + $year_day_neg = -366 + $year_day; + $leap_year = $date->format('L'); + if($leap_year == 1) + { + $year_day_neg = -367 + $year_day; + } + + // this is the nth occurence of the date + $occur = ceil($day / 7); + + $week = $date->format('W'); + + $day_of_week = $date->format('l'); + $dow_abr = strtoupper(substr($day_of_week, 0, 2)); + + // set the day of the month + (positive) + $occur = '+' . $occur . $dow_abr; + $occur_zero = '+0' . $dow_abr; + + // set the day of the month - (negative) + $total_days = $date->format('t') - $date->format('j'); + $occur_neg = '-' . ceil(($total_days + 1)/7) . $dow_abr; + + $day_from_end_of_month = $date->format('t') + 1 - $day; + + if(in_array($month, $this->bymonth) && + (in_array($occur, $this->byday) || in_array($occur_zero, $this->byday) || in_array($occur_neg, $this->byday)) && + in_array($week, $this->byweekno) && + (in_array($day, $this->bymonthday) || in_array(-$day_from_end_of_month, $this->bymonthday)) && + (in_array($year_day, $this->byyearday) || in_array($year_day_neg, $this->byyearday))) + { + return true; + } + else + { + return false; + } + } + + // return the next valid DateTime object which matches the pattern and follows the rules + public function next() + { + // check the counter is set + if($this->count !== 0) + { + if($this->counter >= $this->count) + { + return false; + } + } + + // create initial set of suggested dates + if(count($this->suggestions) === 0) + { + $this->create_suggestions(); + } + + // loop through the suggested dates + while(count($this->suggestions) > 0) + { + // get the first one on the array + $try_date = array_shift($this->suggestions); + + // make sure the date doesn't exceed the max date + if($try_date > $this->end_date) + { + return false; + } + + // make sure it falls within the allowed days + if($this->valid_date($try_date) === true) + { + $this->counter++; + return $try_date; + } + else + { + // we might be out of suggested days, so load some more + if(count($this->suggestions) === 0) + { + $this->create_suggestions(); + } + } + } + } +} diff --git a/apps/admin_dependencies_chk/settings.php b/apps/admin_dependencies_chk/settings.php index de2f97aa79..34028056db 100644 --- a/apps/admin_dependencies_chk/settings.php +++ b/apps/admin_dependencies_chk/settings.php @@ -51,7 +51,7 @@ $modules[] =array( 'message'=> $l->t('The program mp3info is useful to discover ID3 tags of your music files')); $modules[] =array( - 'status' => OC_Helper::canExecute("ldap_bind") ? 'ok' : 'error', + 'status' => function_exists("ldap_bind") ? 'ok' : 'error', 'part'=> 'php-ldap', 'modules'=> array('user_ldap'), 'message'=> $l->t('The php-ldap module is needed connect to your ldap server')); diff --git a/apps/bookmarks/bookmarksHelper.php b/apps/bookmarks/bookmarksHelper.php index 44d4235b9b..ac512fbc24 100644 --- a/apps/bookmarks/bookmarksHelper.php +++ b/apps/bookmarks/bookmarksHelper.php @@ -56,6 +56,9 @@ function getURLMetadata($url) { } $metadata['url'] = $url; + if (!function_exists('curl_init')){ + return $metadata; + } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @@ -66,4 +69,4 @@ function getURLMetadata($url) { $metadata['title'] = htmlspecialchars_decode(@$match[1]); return $metadata; -} \ No newline at end of file +} diff --git a/apps/calendar/ajax/editevent.php b/apps/calendar/ajax/editevent.php index 3abf4de98b..46feb06849 100644 --- a/apps/calendar/ajax/editevent.php +++ b/apps/calendar/ajax/editevent.php @@ -34,7 +34,14 @@ if($errarr){ OC_JSON::error(); exit; } - $vcalendar = Sabre_VObject_Reader::read($data['calendardata']); + $vcalendar = OC_Calendar_Object::parse($data['calendardata']); + + $last_modified = $vcalendar->VEVENT->__get('LAST-MODIFIED'); + if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){ + OC_JSON::error(array('modified'=>true)); + exit; + } + OC_Calendar_Object::updateVCalendarFromRequest($_POST, $vcalendar); $result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); if ($data['calendarid'] != $cal) { diff --git a/apps/calendar/ajax/editeventform.php b/apps/calendar/ajax/editeventform.php index 34d6c657ce..63c7293407 100644 --- a/apps/calendar/ajax/editeventform.php +++ b/apps/calendar/ajax/editeventform.php @@ -26,7 +26,7 @@ if($calendar['userid'] != OC_User::getUser()){ echo $l10n->t('Wrong calendar'); exit; } -$object = Sabre_VObject_Reader::read($data['calendardata']); +$object = OC_Calendar_Object::parse($data['calendardata']); $vevent = $object->VEVENT; $dtstart = $vevent->DTSTART; $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); @@ -63,9 +63,16 @@ foreach($categories as $category){ } $repeat = isset($vevent->CATEGORY) ? $vevent->CATEGORY->value : ''; $description = isset($vevent->DESCRIPTION) ? $vevent->DESCRIPTION->value : ''; +$last_modified = $vevent->__get('LAST-MODIFIED'); +if ($last_modified){ + $lastmodified = $last_modified->getDateTime()->format('U'); +}else{ + $lastmodified = 0; +} $tmpl = new OC_Template('calendar', 'part.editevent'); $tmpl->assign('id', $id); +$tmpl->assign('lastmodified', $lastmodified); $tmpl->assign('calendar_options', $calendar_options); $tmpl->assign('category_options', $category_options); $tmpl->assign('repeat_options', $repeat_options); diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php index 8f466bee91..1ef6bd3059 100644 --- a/apps/calendar/ajax/events.php +++ b/apps/calendar/ajax/events.php @@ -6,42 +6,79 @@ * See the COPYING-README file. */ -require_once ("../../../lib/base.php"); -if(!OC_USER::isLoggedIn()) { - die(""); +require_once ('../../../lib/base.php'); +require_once('../../../3rdparty/when/When.php'); + +function addoutput($event, $vevent, $return_event){ + $return_event['id'] = (int)$event['id']; + $return_event['title'] = $event['summary']; + $return_event['description'] = isset($vevent->DESCRIPTION)?$vevent->DESCRIPTION->value:''; + $last_modified = $vevent->__get('LAST-MODIFIED'); + if ($last_modified){ + $lastmodified = $last_modified->getDateTime()->format('U'); + }else{ + $lastmodified = 0; + } + $return_event['lastmodified'] = (int)$lastmodified; + return $return_event; } + +OC_JSON::checkLoggedIn(); OC_JSON::checkAppEnabled('calendar'); $start = DateTime::createFromFormat('U', $_GET['start']); $end = DateTime::createFromFormat('U', $_GET['end']); $events = OC_Calendar_Object::allInPeriod($_GET['calendar_id'], $start, $end); -$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); +$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $return = array(); -foreach($events as $event) -{ - $object = Sabre_VObject_Reader::read($event['calendardata']); +foreach($events as $event){ + $object = OC_Calendar_Object::parse($event['calendardata']); $vevent = $object->VEVENT; $dtstart = $vevent->DTSTART; $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); + $return_event = array(); $start_dt = $dtstart->getDateTime(); $start_dt->setTimezone(new DateTimeZone($user_timezone)); $end_dt = $dtend->getDateTime(); $end_dt->setTimezone(new DateTimeZone($user_timezone)); - - $return_event = array(); - $return_event['id'] = $event['id']; - $return_event['title'] = $event['summary']; - $return_event['description'] = isset($vevent->DESCRIPTION)?$vevent->DESCRIPTION->value:''; - $return_event['start'] = $start_dt->format('Y-m-d H:i:s'); - $return_event['end'] = $end_dt->format('Y-m-d H:i:s'); - $return_event['allDay'] = false; - if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE) - { + if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){ $return_event['allDay'] = true; - $end_dt->modify('-1 sec'); - $return_event['end'] = $end_dt->format('Y-m-d H:i:s'); + }else{ + $return_event['allDay'] = false; + } + //Repeating Events + if($event['repeating'] == 1){ + $duration = (double) $end_dt->format('U') - (double) $start_dt->format('U'); + $r = new When(); + $r->recur((string) $start_dt->format('Ymd\THis'))->rrule((string) $vevent->RRULE); + while($result = $r->next()){ + if($result->format('U') > $_GET['end']){ + break; + } + if($return_event['allDay'] == true){ + $return_event['start'] = $result->format('Y-m-d'); + $return_event['end'] = date('Y-m-d', $result->format('U') + $duration--); + }else{ + $return_event['start'] = $result->format('Y-m-d H:i:s'); + $return_event['end'] = date('Y-m-d H:i:s', $result->format('U') + $duration); + } + $return[] = addoutput($event, $vevent, $return_event); + } + }else{ + $return_event = array(); + if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){ + $return_event['allDay'] = true; + $return_event['start'] = $start_dt->format('Y-m-d'); + $end_dt->modify('-1 sec'); + $return_event['end'] = $end_dt->format('Y-m-d'); + }else{ + $return_event['start'] = $start_dt->format('Y-m-d H:i:s'); + $return_event['end'] = $end_dt->format('Y-m-d H:i:s'); + $return_event['allDay'] = false; + } + $return[] = addoutput($event, $vevent, $return_event); } - $return[] = $return_event; } OC_JSON::encodedPrint($return); +?> \ No newline at end of file diff --git a/apps/calendar/ajax/guesstimezone.php b/apps/calendar/ajax/guesstimezone.php new file mode 100755 index 0000000000..a3594498b0 --- /dev/null +++ b/apps/calendar/ajax/guesstimezone.php @@ -0,0 +1,39 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +function make_array_out_of_xml ($xml){ + $returnarray = array(); + $xml = (array)$xml ; + foreach ($xml as $property => $value){ + $value = (array)$value; + if(!isset($value[0])){ + $returnarray[$property] = make_array_out_of_xml($value); + }else{ + $returnarray[$property] = trim($value[0]); + } + } + return $returnarray; +} +require_once ("../../../lib/base.php"); +OC_JSON::checkLoggedIn(); +OC_JSON::checkAppEnabled('calendar'); +$l = new OC_L10N('calendar'); +$lat = $_GET['lat']; +$long = $_GET['long']; +$geolocation = file_get_contents('http://ws.geonames.org/timezone?lat=' . $lat . '&lng=' . $long); +//Information are by Geonames (http://www.geonames.org) and licensed under the Creative Commons Attribution 3.0 License +$geoxml = simplexml_load_string($geolocation); +$geoarray = make_array_out_of_xml($geoxml); +if(isset($geoarray['timezone']['timezoneId']) && $geoarray['timezone']['timezoneId'] != ''){ + OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $geoarray['timezone']['timezoneId']); + $message = array('message'=> $l->t('New Timezone:') . $geoarray['timezone']['timezoneId']); + OC_JSON::success($message); +}else{ + OC_JSON::error(); +} + +?> \ No newline at end of file diff --git a/apps/calendar/ajax/moveevent.php b/apps/calendar/ajax/moveevent.php index 1fef1c5b20..6b315a3921 100644 --- a/apps/calendar/ajax/moveevent.php +++ b/apps/calendar/ajax/moveevent.php @@ -22,9 +22,15 @@ $delta = new DateInterval('P0D'); $delta->d = $_POST['dayDelta']; $delta->i = $_POST['minuteDelta']; -$vcalendar = Sabre_VObject_Reader::read($data['calendardata']); +$vcalendar = OC_Calendar_Object::parse($data['calendardata']); $vevent = $vcalendar->VEVENT; +$last_modified = $vevent->__get('LAST-MODIFIED'); +if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){ + OC_JSON::error(); + exit; +} + $dtstart = $vevent->DTSTART; $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); $start_type = $dtstart->getDateType(); @@ -50,4 +56,4 @@ $dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); $vevent->DTSTAMP = $dtstamp; $result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); -OC_JSON::success(); +OC_JSON::success(array('lastmodified'=>(int)$now->format('U'))); diff --git a/apps/calendar/ajax/neweventform.php b/apps/calendar/ajax/neweventform.php index d02b116347..68423adb34 100644 --- a/apps/calendar/ajax/neweventform.php +++ b/apps/calendar/ajax/neweventform.php @@ -15,39 +15,35 @@ if(!OC_USER::isLoggedIn()) { } OC_JSON::checkAppEnabled('calendar'); +if (!isset($_POST['start'])){ + OC_JSON::error(); + die; +} +$start = $_POST['start']; +$end = $_POST['end']; +$allday = $_POST['allday']; + +if (!$end){ + $duration = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'duration', '60'); + $end = $start + ($duration * 60); +} +$start = new DateTime('@'.$start); +$end = new DateTime('@'.$end); +$timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); +$start->setTimezone(new DateTimeZone($timezone)); +$end->setTimezone(new DateTimeZone($timezone)); + $calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser()); $category_options = OC_Calendar_Object::getCategoryOptions($l10n); $repeat_options = OC_Calendar_Object::getRepeatOptions($l10n); -$startday = substr($_GET['d'], 0, 2); -$startmonth = substr($_GET['d'], 2, 2); -$startyear = substr($_GET['d'], 4, 4); -$allday = $_GET['t'] == 'allday'; -if(!$allday){ - $starthour = substr($_GET['t'], 0, 2); - $startminutes = substr($_GET['t'], 2, 2); -}else{ - $starthour = '00'; - $startminutes = '00'; -} - -$datetimestamp = mktime($starthour, $startminutes, 0, $startmonth, $startday, $startyear); -$duration = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'duration', "60"); -$datetimestamp = $datetimestamp + ($duration * 60); -$endmonth = date("m", $datetimestamp); -$endday = date("d", $datetimestamp); -$endyear = date("Y", $datetimestamp); -$endtime = date("G", $datetimestamp); -$endminutes = date("i", $datetimestamp); - - $tmpl = new OC_Template('calendar', 'part.newevent'); $tmpl->assign('calendar_options', $calendar_options); $tmpl->assign('category_options', $category_options); -$tmpl->assign('startdate', $startday . '-' . $startmonth . '-' . $startyear); -$tmpl->assign('starttime', $starthour . ':' . $startminutes); -$tmpl->assign('enddate', $endday . '-' . $endmonth . '-' . $endyear); -$tmpl->assign('endtime', ($endtime <= 9 ? '0' : '') . $endtime . ':' . $endminutes); +$tmpl->assign('startdate', $start->format('d-m-Y')); +$tmpl->assign('starttime', $start->format('H:i')); +$tmpl->assign('enddate', $end->format('d-m-Y')); +$tmpl->assign('endtime', $end->format('H:i')); $tmpl->assign('allday', $allday); $tmpl->printpage(); ?> diff --git a/apps/calendar/ajax/resizeevent.php b/apps/calendar/ajax/resizeevent.php index 3a2bf87afd..28a185411e 100644 --- a/apps/calendar/ajax/resizeevent.php +++ b/apps/calendar/ajax/resizeevent.php @@ -22,9 +22,15 @@ $delta = new DateInterval('P0D'); $delta->d = $_POST['dayDelta']; $delta->i = $_POST['minuteDelta']; -$vcalendar = Sabre_VObject_Reader::read($data['calendardata']); +$vcalendar = OC_Calendar_Object::parse($data['calendardata']); $vevent = $vcalendar->VEVENT; +$last_modified = $vevent->__get('LAST-MODIFIED'); +if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){ + OC_JSON::error(); + exit; +} + $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent); $end_type = $dtend->getDateType(); $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type); @@ -40,4 +46,4 @@ $dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC); $vevent->DTSTAMP = $dtstamp; $result = OC_Calendar_Object::edit($id, $vcalendar->serialize()); -OC_JSON::success(); +OC_JSON::success(array('lastmodified'=>$now->format('U'))); diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php index 2dc01eab0f..5675e624dd 100644 --- a/apps/calendar/appinfo/app.php +++ b/apps/calendar/appinfo/app.php @@ -21,3 +21,5 @@ OC_App::addNavigationEntry( array( 'name' => $l->t('Calendar'))); OC_App::registerPersonal('calendar', 'settings'); + +require_once('apps/calendar/lib/search.php'); \ No newline at end of file diff --git a/apps/calendar/css/style.css b/apps/calendar/css/style.css index e6d212ef53..0204f2fc12 100644 --- a/apps/calendar/css/style.css +++ b/apps/calendar/css/style.css @@ -24,8 +24,6 @@ #listview #events {width:25em;padding: 4px;} #listview #events .day {width:auto;padding-left:10px;border-bottom: 2px solid #EEEEEE;text-align:left;} -#sysbox{display: none;} - .actions {height: 33px; min-width: 800px;} .controls {min-width: 800px;} .center {text-align: center;} @@ -99,3 +97,31 @@ button.category{margin:0 3px;} { cursor: pointer; } +.tipsy-event .tipsy-inner{ +background-color:#0098E4; +border:2px solid #1d2d44; +max-width:400px; +padding:0; +} +.tipsy-event .tipsy-arrow-s{ +border-top-color:#1d2d44; +} +.tipsy-event .tipsy-arrow-n{ +border-bottom-color:#1d2d44; +} +.tipsy-event .summary, +.tipsy-event .timespan, +.tipsy-event .description{ +padding:0 8px; +} +.tipsy-event .summary{ +background-color:#1d2d44; +font-size:1.2em; +font-weight:bold; +text-align:left; +padding:0 8px 2px; +} +.tipsy-event .description{ +line-height:1.2; +margin-bottom:4px; +} diff --git a/apps/calendar/index.php b/apps/calendar/index.php index 1129bdcf7f..7561f987b2 100644 --- a/apps/calendar/index.php +++ b/apps/calendar/index.php @@ -13,7 +13,7 @@ OC_Util::checkAppEnabled('calendar'); $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1); if( count($calendars) == 0){ OC_Calendar_Calendar::addCalendar(OC_User::getUser(),'Default calendar'); - $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser()); + $calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1); } $eventSources = array(); foreach($calendars as $calendar){ @@ -32,6 +32,9 @@ if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'mont OC_Util::addScript('3rdparty/fullcalendar', 'fullcalendar'); OC_Util::addStyle('3rdparty/fullcalendar', 'fullcalendar'); +if(OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone") == null){ + OC_UTIL::addScript('calendar', 'geo'); +} OC_Util::addScript('calendar', 'calendar'); OC_Util::addStyle('calendar', 'style'); OC_Util::addScript('', 'jquery.multiselect'); diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js index bf9e2628ff..005e359f8e 100644 --- a/apps/calendar/js/calendar.js +++ b/apps/calendar/js/calendar.js @@ -10,6 +10,8 @@ Calendar={ space:' ', UI:{ startEventDialog:function(){ + $('.tipsy').remove(); + $('#calendar_holder').fullCalendar('unselect'); Calendar.UI.lockTime(); $( "#from" ).datepicker({ dateFormat : 'dd-mm-yy' @@ -31,36 +33,16 @@ Calendar={ } }); }, - newEvent:function(date, allDay, jsEvent, view){ - var dayofmonth = date.getDate(); - var month = date.getMonth(); - var year = date.getFullYear(); - var hour = date.getHours(); - var min = date.getMinutes(); - if(dayofmonth <= 9){ - dayofmonth = '0' + dayofmonth; - } - month++; - if(month <= 9){ - month = '0' + month; - } - if(hour <= 9){ - hour = '0' + hour; - } - if(min <= 9){ - min = '0' + min; - } - var date = String(dayofmonth) + String(month) + String(year); - if (allDay){ - var time = 'allday'; - }else{ - var time = String(hour) + String(min); + newEvent:function(start, end, allday){ + start = Math.round(start.getTime()/1000); + if (end){ + end = Math.round(end.getTime()/1000); } if($('#event').dialog('isOpen') == true){ // TODO: save event $('#event').dialog('destroy').remove(); }else{ - $('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'neweventform.php') + '?d=' + date + '&t=' + time, Calendar.UI.startEventDialog); + $('#dialog_holder').load(OC.filePath('calendar', 'ajax', 'neweventform.php'), {start:start, end:end, allday:allday?1:0}, Calendar.UI.startEventDialog); } }, editEvent:function(calEvent, jsEvent, view){ @@ -91,27 +73,27 @@ Calendar={ $.post(url, post, function(data){ if(data.status == "error"){ - var output = "Missing fields:
            "; + var output = missing_field + ":
            "; if(data.title == "true"){ - output = output + "Title
            "; + output = output + missing_field_title + "
            "; } if(data.cal == "true"){ - output = output + "Calendar
            "; + output = output + missing_field_calendar + "
            "; } if(data.from == "true"){ - output = output + "From Date
            "; + output = output + missing_field_fromdate + "
            "; } if(data.fromtime == "true"){ - output = output + "From Time
            "; + output = output + missing_field_fromtime + "
            "; } if(data.to == "true"){ - output = output + "To Date
            "; + output = output + missing_field_todate + "
            "; } if(data.totime == "true"){ - output = output + "To Time
            "; + output = output + missing_field_totime + "
            "; } if(data.endbeforestart == "true"){ - output = "The event ends before it starts!"; + output = output + missing_field_startsbeforeends + "!
            "; } if(data.dberror == "true"){ output = "There was a database fail!"; @@ -125,22 +107,28 @@ Calendar={ },"json"); }, moveEvent:function(event, dayDelta, minuteDelta, allDay, revertFunc){ - $.post(OC.filePath('calendar', 'ajax', 'moveevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0}, + $('.tipsy').remove(); + $.post(OC.filePath('calendar', 'ajax', 'moveevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, allDay: allDay?1:0, lastmodified: event.lastmodified}, function(data) { if (data.status == 'success'){ + event.lastmodified = data.lastmodified; console.log("Event moved successfully"); }else{ revertFunc(); + $('#calendar_holder').fullCalendar('refetchEvents'); } }); }, resizeEvent:function(event, dayDelta, minuteDelta, revertFunc){ - $.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta}, + $('.tipsy').remove(); + $.post(OC.filePath('calendar', 'ajax', 'resizeevent.php'), { id: event.id, dayDelta: dayDelta, minuteDelta: minuteDelta, lastmodified: event.lastmodified}, function(data) { if (data.status == 'success'){ + event.lastmodified = data.lastmodified; console.log("Event resized successfully"); }else{ revertFunc(); + $('#calendar_holder').fullCalendar('refetchEvents'); } }); }, @@ -148,32 +136,20 @@ Calendar={ $("#advanced_options").css("display", "block"); $("#advanced_options_button").css("display", "none"); }, - createEventPopup:function(event, e, view){ - var popup = $(this).data('popup'); - if (!popup){ - popup = $(document.createElement('div')); - $(this).data('popup', popup).append(popup); - popup.addClass('popup') - popup.addClass('event_popup') - .html(Calendar.UI.getEventPopupText(event)); - } - popup.css('left', -(popup.width() - $(this).width())/2) - .show(); - }, - hideEventPopup:function(){ - $(this).data('popup').hide(); - }, getEventPopupText:function(event){ if (event.allDay){ - var timespan = $.fullCalendar.formatDates(event.start, event.end, t('calendar', "MMMM d[ yyyy]{ '—'[ MMMM][ d] yyyy}")); + var timespan = $.fullCalendar.formatDates(event.start, event.end, 'ddd d MMMM[ yyyy]{ -[ddd d] MMMM yyyy}', {monthNamesShort: monthNamesShort, monthNames: monthNames, dayNames: dayNames, dayNamesShort: dayNamesShort}); //t('calendar', "ddd d MMMM[ yyyy]{ -[ddd d] MMMM yyyy}") }else{ - var timespan = $.fullCalendar.formatDates(event.start, event.end, t('calendar', "HH:mm[ MMMM d yyyy]{ '—' HH:mm MMMM d yyyy}")); + var timespan = $.fullCalendar.formatDates(event.start, event.end, 'ddd d MMMM[ yyyy] ' + defaulttime + '{ -[ ddd d MMMM yyyy]' + defaulttime + '}', {monthNamesShort: monthNamesShort, monthNames: monthNames, dayNames: dayNames, dayNamesShort: dayNamesShort}); //t('calendar', "ddd d MMMM[ yyyy] HH:mm{ -[ ddd d MMMM yyyy] HH:mm}") // Tue 18 October 2011 08:00 - 16:00 } - return '' + timespan + '' - + ' ' - + '' + event.title + '' - + '' + event.description + ''; + var html = + '
            ' + event.title + '
            ' + + '
            ' + timespan + '
            '; + if (event.description){ + html += '
            ' + event.description + '
            '; + } + return html; }, lockTime:function(){ if($('#allday_checkbox').is(':checked')) { @@ -201,6 +177,7 @@ Calendar={ //} }, scrollCalendar:function(event){ + $('.tipsy').remove(); var direction; if(event.detail){ if(event.detail < 0){ @@ -216,10 +193,17 @@ Calendar={ direction = 'down'; } } - if(direction == 'down'){ + var scroll = $(document).scrollTop(), + doc_height = $(document).height(), + win_height = $(window).height(); + if(direction == 'down' && win_height == (doc_height - scroll)){ $('#calendar_holder').fullCalendar('next'); - }else{ + $(document).scrollTop(0); + event.preventDefault(); + }else if (direction == 'top' && scroll == 0) { $('#calendar_holder').fullCalendar('prev'); + $(document).scrollTop(win_height); + event.preventDefault(); } }, Calendar:{ @@ -495,20 +479,20 @@ function ListView(element, calendar) { } } $(document).ready(function(){ - //Calendar.UI.initScroll(); + Calendar.UI.initScroll(); $('#calendar_holder').fullCalendar({ header: false, firstDay: 1, editable: true, defaultView: defaultView, timeFormat: { - agenda: 'HH:mm{ - HH:mm}', - '': 'HH:mm' + agenda: agendatime, + '': defaulttime }, titleFormat: { list: 'yyyy/MMM/d dddd' }, - axisFormat: 'HH:mm', + axisFormat: defaulttime, monthNames: monthNames, monthNamesShort: monthNamesShort, dayNames: dayNames, @@ -518,12 +502,25 @@ $(document).ready(function(){ $('#datecontrol_date').html(view.title); $.get(OC.filePath('calendar', 'ajax', 'changeview.php') + "?v="+view.name); }, - dayClick: Calendar.UI.newEvent, + selectable: true, + selectHelper: true, + select: Calendar.UI.newEvent, eventClick: Calendar.UI.editEvent, eventDrop: Calendar.UI.moveEvent, eventResize: Calendar.UI.resizeEvent, - eventMouseover: Calendar.UI.createEventPopup, - eventMouseout: Calendar.UI.hideEventPopup, + eventRender: function(event, element) { + element.tipsy({ + className: 'tipsy-event', + opacity: 0.9, + gravity:$.fn.tipsy.autoBounds(150, 's'), + fade:true, + delayIn: 400, + html:true, + title:function() { + return Calendar.UI.getEventPopupText(event); + } + }); + }, eventSources: eventSources }); $('#oneweekview_radio').click(function(){ diff --git a/apps/calendar/js/geo.js b/apps/calendar/js/geo.js new file mode 100755 index 0000000000..acea17c026 --- /dev/null +++ b/apps/calendar/js/geo.js @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2011 Georg Ehrke + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition(function(position) { + $.getJSON(OC.filePath('calendar', 'ajax', 'guesstimezone.php?lat=' + position.coords.latitude + '&long=' + position.coords.longitude + ''), + function(data){ + if (data.status == 'success'){ + $('#notification').html(data.message); + $('#notification').slideDown(); + window.setTimeout(function(){$('#notification').slideUp();}, 5000); + }else{ + console.log('Can\'t set new timezone.'); + } + }); + }); +} \ No newline at end of file diff --git a/apps/calendar/l10n/xgettextfiles b/apps/calendar/l10n/xgettextfiles index 4cc636436b..27b8e45719 100644 --- a/apps/calendar/l10n/xgettextfiles +++ b/apps/calendar/l10n/xgettextfiles @@ -1,7 +1,11 @@ ../appinfo/app.php +../lib/object.php ../templates/calendar.php -../templates/part.editevent.php -../templates/part.eventinfo.php -../templates/part.newevent.php ../templates/part.choosecalendar.php -../js/calendar.js +../templates/part.choosecalendar.rowfields.php +../templates/part.editcalendar.php +../templates/part.editevent.php +../templates/part.eventform.php +../templates/part.import.php +../templates/part.newevent.php +../templates/settings.php \ No newline at end of file diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php index e44334bc75..b016469042 100644 --- a/apps/calendar/lib/object.php +++ b/apps/calendar/lib/object.php @@ -43,12 +43,14 @@ class OC_Calendar_Object{ public static function allInPeriod($id, $start, $end){ $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ?' .' AND ((startdate >= ? AND startdate <= ? AND repeating = 0)' - .' OR (startdate <= ? AND enddate >= ? AND repeating = 1))' ); + .' OR (enddate >= ? AND enddate <= ? AND repeating = 0)' + .' OR (startdate <= ? AND repeating = 1))' ); $start = self::getUTCforMDB($start); $end = self::getUTCforMDB($end); $result = $stmt->execute(array($id, $start, $end, - $end, $start)); + $start, $end, + $end)); $calendarobjects = array(); while( $row = $result->fetchRow()){ @@ -307,6 +309,7 @@ class OC_Calendar_Object{ */ public static function parse($data){ try { + Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime'; $calendar = Sabre_VObject_Reader::read($data); return $calendar; } catch (Exception $e) { @@ -426,7 +429,7 @@ class OC_Calendar_Object{ $errarr['endbeforestart'] = 'true'; $errnum++; } - if($fromday == $today && $frommonth == $tomonth && $fromyear == $toyear){ + if(!$allday && $fromday == $today && $frommonth == $tomonth && $fromyear == $toyear){ list($tohours, $tominutes) = explode(':', $request['totime']); list($fromhours, $fromminutes) = explode(':', $request['fromtime']); if($tohours < $fromhours){ @@ -481,9 +484,11 @@ class OC_Calendar_Object{ $categories = isset($request["categories"]) ? $request["categories"] : null; $allday = isset($request["allday"]); $from = $request["from"]; - $fromtime = $request["fromtime"]; $to = $request["to"]; - $totime = $request["totime"]; + if (!$allday){ + $fromtime = $request['fromtime']; + $totime = $request['totime']; + } $description = $request["description"]; //$repeat = $request["repeat"]; /*switch($request["repeatfreq"]){ @@ -525,7 +530,7 @@ class OC_Calendar_Object{ $dtstart->setDateTime($start, Sabre_VObject_Element_DateTime::DATE); $dtend->setDateTime($end, Sabre_VObject_Element_DateTime::DATE); }else{ - $timezone = OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone", "Europe/London"); + $timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get()); $timezone = new DateTimeZone($timezone); $start = new DateTime($from.' '.$fromtime, $timezone); $end = new DateTime($to.' '.$totime, $timezone); diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php new file mode 100644 index 0000000000..41faf49a51 --- /dev/null +++ b/apps/calendar/lib/search.php @@ -0,0 +1,26 @@ + 0){ + $searchquery = explode(' ', $query); + }else{ + $searchquery[] = $query; + } + foreach($calendars as $calendar){ + $objects = OC_Calendar_Object::all($calendar['id']); + foreach($objects as $object){ + if(substr_count(strtolower($object['summary']), strtolower($query)) > 0){//$name,$text,$link,$type + $results[]=new OC_Search_Result($object['summary'],'','#','Cal.'); + } + } + } + return $results; + } +} +new OC_Search_Provider_Calendar(); \ No newline at end of file diff --git a/apps/calendar/templates/calendar.php b/apps/calendar/templates/calendar.php old mode 100644 new mode 100755 index 1c948b948c..2003b7efc4 --- a/apps/calendar/templates/calendar.php +++ b/apps/calendar/templates/calendar.php @@ -1,12 +1,24 @@ - +
            @@ -25,12 +37,13 @@ var allDayText = 't('All day') ?>';
            - +
            +
            diff --git a/apps/calendar/templates/part.editevent.php b/apps/calendar/templates/part.editevent.php index ae969f2dc3..b3acfc4a07 100644 --- a/apps/calendar/templates/part.editevent.php +++ b/apps/calendar/templates/part.editevent.php @@ -1,6 +1,7 @@
            ">
            + inc("part.eventform"); ?>
            diff --git a/apps/contacts/ajax/addcard.php b/apps/contacts/ajax/addcard.php index 0cecd3bdc0..dd5b90651f 100644 --- a/apps/contacts/ajax/addcard.php +++ b/apps/contacts/ajax/addcard.php @@ -68,11 +68,16 @@ foreach( $add as $propname){ } $id = OC_Contacts_VCard::add($aid,$vcard->serialize()); +$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR'); +$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL'); + $details = OC_Contacts_VCard::structureContact($vcard); $name = $details['FN'][0]['value']; $tmpl = new OC_Template('contacts','part.details'); $tmpl->assign('details',$details); $tmpl->assign('id',$id); +$tmpl->assign('adr_types',$adr_types); +$tmpl->assign('phone_types',$phone_types); $page = $tmpl->fetchPage(); OC_JSON::success(array('data' => array( 'id' => $id, 'name' => $name, 'page' => $page ))); diff --git a/apps/contacts/ajax/setproperty.php b/apps/contacts/ajax/setproperty.php index 18e0087247..22f228cbf4 100644 --- a/apps/contacts/ajax/setproperty.php +++ b/apps/contacts/ajax/setproperty.php @@ -70,6 +70,9 @@ $vcard->children[$line]->setValue($value); // Add parameters $postparameters = isset($_POST['parameters'])?$_POST['parameters']:array(); +if ($vcard->children[$line]->name == 'TEL' && !array_key_exists('TYPE', $postparameters)){ + $postparameters['TYPE']=''; +} for($i=0;$ichildren[$line]->parameters);$i++){ $name = $vcard->children[$line]->parameters[$i]->name; if(array_key_exists($name,$postparameters)){ @@ -77,7 +80,14 @@ for($i=0;$ichildren[$line]->parameters);$i++){ unset($vcard->children[$line]->parameters[$i]); } else{ - $vcard->children[$line]->parameters[$i]->value = $postparameters[$name]; + unset($vcard->children[$line][$name]); + $values = $postparameters[$name]; + if (!is_array($values)){ + $values = array($values); + } + foreach($values as $value){ + $vcard->children[$line]->add($name, $value); + } } unset($postparameters[$name]); } @@ -94,7 +104,17 @@ $checksum = md5($vcard->children[$line]->serialize()); OC_Contacts_VCard::edit($id,$vcard->serialize()); -$tmpl = new OC_Template('contacts','part.property'); +$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR'); +$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL'); + +if ($vcard->children[$line]->name == 'FN'){ + $tmpl = new OC_Template('contacts','part.property.FN'); +} +else{ + $tmpl = new OC_Template('contacts','part.property'); +} +$tmpl->assign('adr_types',$adr_types); +$tmpl->assign('phone_types',$phone_types); $tmpl->assign('property',OC_Contacts_VCard::structureProperty($vcard->children[$line],$line)); $page = $tmpl->fetchPage(); diff --git a/apps/contacts/ajax/showsetproperty.php b/apps/contacts/ajax/showsetproperty.php index 4ec3dd7d8e..2ec4b89b82 100644 --- a/apps/contacts/ajax/showsetproperty.php +++ b/apps/contacts/ajax/showsetproperty.php @@ -62,12 +62,14 @@ if(is_null($line)){ } $adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR'); +$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL'); $tmpl = new OC_Template('contacts','part.setpropertyform'); $tmpl->assign('id',$id); $tmpl->assign('checksum',$checksum); $tmpl->assign('property',OC_Contacts_VCard::structureProperty($vcard->children[$line])); $tmpl->assign('adr_types',$adr_types); +$tmpl->assign('phone_types',$phone_types); $page = $tmpl->fetchPage(); OC_JSON::success(array('data' => array( 'page' => $page ))); diff --git a/apps/contacts/css/formtastic.css b/apps/contacts/css/formtastic.css index 629c220732..fede92b61c 100644 --- a/apps/contacts/css/formtastic.css +++ b/apps/contacts/css/formtastic.css @@ -94,16 +94,14 @@ This stylesheet forms part of the Formtastic Rails Plugin /* INPUTS --------------------------------------------------------------------------------------------------*/ .formtastic .inputs { - overflow:hidden; /* clear containing floats */ -} - -.formtastic .input { - overflow:hidden; /* clear containing floats */ padding:0.5em 0; /* padding and negative margin juggling is for Firefox */ margin-top:-0.5em; margin-bottom:1em; } +.formtastic .input { +} + /* LEFT ALIGNED LABELS --------------------------------------------------------------------------------------------------*/ diff --git a/apps/contacts/css/styles.css b/apps/contacts/css/styles.css index ad64c777ee..f351589fe1 100644 --- a/apps/contacts/css/styles.css +++ b/apps/contacts/css/styles.css @@ -3,16 +3,22 @@ #contacts_deletecard {position:absolute;top:15px;right:0;} #contacts_details_list { list-style:none; } -#contacts_details_list li { overflow:hidden; } +#contacts_details_list li { overflow:visible; } #contacts_details_list li p.contacts_property_name { width:25%; float:left;text-align:right;padding-right:0.3em;color:#666; } -#contacts_details_list li p.contacts_property_data, #contacts_details_list li ul.contacts_property_data { width:72%; overflow:hidden; } -#contacts_addproperty_button, #contacts_setproperty_button { margin-left:25%; } +#contacts_details_list li p.contacts_property_data, #contacts_details_list li ul.contacts_property_data { width:72%;float:left; } +#contacts_setproperty_button { margin-left:25%; } -.contacts_property_data ul, .contacts_property_data ol { list-style:none; } +.contacts_property_data ul, ol.contacts_property_data { list-style:none; } .contacts_property_data li { overflow: hidden; } .contacts_property_data li label { width:20%; float:left; text-align:right;padding-right:0.3em; } +.contacts_property_data input { float:left; } .contacts_property_data li input { width:70%;overflow:hidden; } +.chzn-container { margin:3px 0 0; } +.chzn-container .chzn-choices { border-radius: 0.5em; } +.chzn-container.chzn-container-active .chzn-choices { border-bottom-left-radius: 0;border-bottom-right-radius: 0; } +.chzn-container .chzn-drop { border-bottom-left-radius: 0.5em;border-bottom-right-radius: 0.5em; } + /* Form setup ----------------------------------------------------------------*/ /* .forme {} */ /* .forme ul, .forme ol { list-style:none; } */ diff --git a/apps/contacts/index.php b/apps/contacts/index.php index 7e93d6183e..29d41d3c4c 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -75,8 +75,14 @@ if( !is_null($id) || count($contacts)){ $details = OC_Contacts_VCard::structureContact($vcard); } +$l10n = new OC_L10N('contacts'); +$adr_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'ADR'); +$phone_types = OC_Contacts_VCard::getTypesOfProperty($l10n, 'TEL'); + // Process the template $tmpl = new OC_Template( 'contacts', 'index', 'user' ); +$tmpl->assign('adr_types',$adr_types); +$tmpl->assign('phone_types',$phone_types); $tmpl->assign('addressbooks', $addressbooks); $tmpl->assign('contacts', $contacts); $tmpl->assign('details', $details ); diff --git a/apps/contacts/js/interface.js b/apps/contacts/js/interface.js index 1cc3a5dfd6..eb81e87268 100644 --- a/apps/contacts/js/interface.js +++ b/apps/contacts/js/interface.js @@ -64,6 +64,7 @@ $(document).ready(function(){ else{ $('#contacts_generic').clone().insertAfter($('#contacts_addpropertyform .contacts_property_name')); } + $('#contacts_addpropertyform .contacts_property_data select').chosen(); }); $('#contacts_addpropertyform input[type="submit"]').live('click',function(){ @@ -82,7 +83,8 @@ $(document).ready(function(){ $.getJSON('ajax/showaddcard.php',{},function(jsondata){ if(jsondata.status == 'success'){ $('#rightcontent').data('id',''); - $('#rightcontent').html(jsondata.data.page); + $('#rightcontent').html(jsondata.data.page) + .find('select').chosen(); } else{ alert(jsondata.data.message); @@ -108,10 +110,11 @@ $(document).ready(function(){ $('.contacts_property [data-use="edit"]').live('click',function(){ var id = $('#rightcontent').data('id'); - var checksum = $(this).parents('li').first().data('checksum'); + var checksum = $(this).parents('.contacts_property').first().data('checksum'); $.getJSON('ajax/showsetproperty.php',{'id': id, 'checksum': checksum },function(jsondata){ if(jsondata.status == 'success'){ - $('.contacts_property[data-checksum="'+checksum+'"]').html(jsondata.data.page); + $('.contacts_property[data-checksum="'+checksum+'"]').html(jsondata.data.page) + .find('select').chosen(); } else{ alert(jsondata.data.message); @@ -148,10 +151,12 @@ $(document).ready(function(){ $('.contacts_property').live('mouseenter',function(){ - $(this).find('span').show(); + $(this).find('span[data-use]').show(); }); $('.contacts_property').live('mouseleave',function(){ - $(this).find('span').hide(); + $(this).find('span[data-use]').hide(); }); + + $('#contacts_addcardform select').chosen(); }); diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php index 56602f25c0..4865fae764 100644 --- a/apps/contacts/lib/vcard.php +++ b/apps/contacts/lib/vcard.php @@ -296,7 +296,13 @@ class OC_Contacts_VCard{ $property = new Sabre_VObject_Property( $name, $value ); $parameternames = array_keys($parameters); foreach($parameternames as $i){ - $property->parameters[] = new Sabre_VObject_Parameter($i,$parameters[$i]); + $values = $parameters[$i]; + if (!is_array($values)){ + $values = array($values); + } + foreach($values as $value){ + $property->add($i, $value); + } } $vcard->add($property); @@ -352,7 +358,17 @@ class OC_Contacts_VCard{ $parameter->name = 'PREF'; $parameter->value = '1'; } - $temp['parameters'][$parameter->name] = $parameter->value; + if ($property->name == 'TEL' && $parameter->name == 'TYPE'){ + if (isset($temp['parameters'][$parameter->name])){ + $temp['parameters'][$parameter->name][] = $parameter->value; + } + else{ + $temp['parameters'][$parameter->name] = array($parameter->value); + } + } + else{ + $temp['parameters'][$parameter->name] = $parameter->value; + } } return $temp; } diff --git a/apps/contacts/templates/part.addcardform.php b/apps/contacts/templates/part.addcardform.php index 037e3629bb..627053547a 100644 --- a/apps/contacts/templates/part.addcardform.php +++ b/apps/contacts/templates/part.addcardform.php @@ -43,7 +43,7 @@
          • -
          • diff --git a/apps/contacts/templates/part.details.php b/apps/contacts/templates/part.details.php index f5bd75809b..afad0b7f64 100644 --- a/apps/contacts/templates/part.details.php +++ b/apps/contacts/templates/part.details.php @@ -1,5 +1,5 @@ -

            + inc('part.property.FN', array('property' => $_['details']['FN'][0])); ?> @@ -29,12 +29,12 @@ +
            +

            -
            -