From 1f068e6601529952acded862c027e2bcb86f1f3c Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 30 Aug 2021 08:17:40 +0800 Subject: [PATCH 001/304] * support to use session for each browser tab. --- lib/base/front/front.class.php | 1 + www/js/zui/min.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index a45a9563e9..c45f30725d 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -1166,6 +1166,7 @@ EOT; $jsConfig->runMode = $runMode; $jsConfig->timeout = isset($config->timeout) ? $config->timeout : ''; $jsConfig->pingInterval = isset($config->pingInterval) ? $config->pingInterval : ''; + $jsConfig->tabSession = $config->tabSession; $jsLang = new stdclass(); $jsLang->submitting = isset($lang->loading) ? $lang->loading : ''; diff --git a/www/js/zui/min.js b/www/js/zui/min.js index b8b48a1ab9..727e4bb019 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao - v1.9.2 - 2021-08-23 + * ZUI: ZUI for Zentao - v1.9.2 - 2021-08-29 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2021 cnezsoft.com; Licensed MIT @@ -42,7 +42,7 @@ Copyright (c) 2011 Harvest http://getharvest.com MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ function(){var t,e,i,n,o,a={}.hasOwnProperty,s=function(t,e){function i(){this.constructor=t}for(var n in e)a.call(e,n)&&(t[n]=e[n]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},r={zh_cn:{no_results_text:"没有找到"},zh_tw:{no_results_text:"沒有找到"},en:{no_results_text:"No results match"}},l={};n=function(){function e(){this.options_index=0,this.parsed=[]}return e.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},e.prototype.add_group=function(e){var i,n,o,a,s,r;for(i=this.parsed.length,this.parsed.push({array_index:i,group:!0,label:this.escapeExpression(e.label),children:0,disabled:e.disabled,title:e.title,search_keys:t.trim(e.getAttribute("data-keys")||"").replace(/,/g," ")}),s=e.childNodes,r=[],o=0,a=s.length;o\"\'\`]/.test(t)?(e={"<":"<",">":">",'"':""","'":"'","`":"`"},i=/&(?!\w+;)|[\<\>\"\'\`]/g,t.replace(i,function(t){return e[t]||"&"})):t},e}(),n.select_to_array=function(t){var e,i,o,a,s;for(i=new n,s=t.childNodes,o=0,a=s.length;o0?(e=document.createElement("li"),e.className="group-result",e.title=t.title,e.innerHTML=t.search_text,this.outerHTML(e)):""},e.prototype.results_update_field=function(){this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing&&(this.winnow_results(),this.autoResizeDrop())},e.prototype.reset_single_select_options=function(){var t,e,i,n,o;for(n=this.results_data,o=[],e=0,i=n.length;e"+i.search_text.substr(l+r.length),i.search_text=h.substr(0,l)+""+h.substr(l)):i.search_keys_match&&i.search_keys.length&&(l=i.search_keys.search(c),h=i.search_keys.substr(0,l+r.length)+""+i.search_keys.substr(l+r.length),i.search_text+='  '+h.substr(0,l)+""+h.substr(l)+""),null!=s&&(s.group_match=!0)):null!=i.group_array_index&&this.results_data[i.group_array_index].search_match&&(i.search_match=!0)));return this.result_clear_highlight(),a<1&&r.length?(this.update_results_content(""),this.no_results(r)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight(t))},e.prototype.search_string_match=function(t,e){var i,n,o,a;if(e.test(t))return!0;if(this.enable_split_word_search&&(t.indexOf(" ")>=0||0===t.indexOf("["))&&(n=t.replace(/\[|\]/g,"").split(" "),n.length))for(o=0,a=n.length;o0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(t.preventDefault(),this.results_showing)return this.result_select(t);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},e.prototype.clipboard_event_checker=function(t){var e=this;return setTimeout(function(){return e.results_search()},50)},e.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field&&this.form_field.classList&&this.form_field.classList.contains("form-control")?"100%":""+this.form_field.offsetWidth+"px"},e.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},e.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},e.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},e.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},e.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:(e=document.createElement("div"),e.appendChild(t),e.innerHTML)},e.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!/iP(od|hone)/i.test(window.navigator.userAgent)&&(!/Android/i.test(window.navigator.userAgent)||!/Mobile/i.test(window.navigator.userAgent))},e.default_multiple_text="",e.default_single_text="",e.default_no_result_text="No results match",e}(),t=jQuery,t.fn.extend({chosen:function(n){return e.browser_is_supported()?this.each(function(e){var o=t(this),a=o.data("chosen");"destroy"===n&&a?a.destroy():a||o.data("chosen",new i(this,t.extend({},o.data(),n)))}):this}}),i=function(e){function i(){return o=i.__super__.constructor.apply(this,arguments)}return s(i,e),i.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},i.prototype.set_up_html=function(){var e,i;e=["chosen-container"],e.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl");var n=this.form_field.getAttribute("data-css-class");return n&&e.push(n),i={"class":e.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(i.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("
",i),this.is_multiple?this.container.html('
    '):(this.container.html(''+this.default_text+'
      '),this.compact_search?this.container.addClass("chosen-compact").find(".chosen-search").appendTo(this.container.find(".chosen-single")):this.container.find(".chosen-search").prependTo(this.container.find(".chosen-drop")),this.options.highlight_selected!==!1&&this.container.addClass("chosen-highlight-selected")),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-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.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.options.drop_width&&this.dropdown.css("width",this.options.drop_width).addClass("chosen-drop-size-limited"),this.max_drop_width&&this.dropdown.addClass("chosen-auto-max-width"),this.options.no_wrap&&this.dropdown.addClass("chosen-no-wrap"),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},i.prototype.register_observers=function(){var t=this;return this.container.bind("mousedown.chosen",function(e){t.container_mousedown(e)}),this.container.bind("mouseup.chosen",function(e){t.container_mouseup(e)}),this.container.bind("mouseenter.chosen",function(e){t.mouse_enter(e)}),this.container.bind("mouseleave.chosen",function(e){t.mouse_leave(e)}),this.search_results.bind("mouseup.chosen",function(e){t.search_results_mouseup(e)}),this.search_results.bind("mouseover.chosen",function(e){t.search_results_mouseover(e)}),this.search_results.bind("mouseout.chosen",function(e){t.search_results_mouseout(e)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(e){t.search_results_mousewheel(e)}),this.search_results.bind("touchstart.chosen",function(e){t.search_results_touchstart(e)}),this.search_results.bind("touchmove.chosen",function(e){t.search_results_touchmove(e)}),this.search_results.bind("touchend.chosen",function(e){t.search_results_touchend(e)}),this.form_field_jq.bind("chosen:updated.chosen",function(e){t.results_update_field(e)}),this.form_field_jq.bind("chosen:activate.chosen",function(e){t.activate_field(e)}),this.form_field_jq.bind("chosen:open.chosen",function(e){t.container_mousedown(e)}),this.form_field_jq.bind("chosen:close.chosen",function(e){t.input_blur(e)}),this.search_field.bind("blur.chosen",function(e){t.input_blur(e)}),this.search_field.bind("keyup.chosen",function(e){t.keyup_checker(e)}),this.search_field.bind("keydown.chosen",function(e){t.keydown_checker(e)}),this.search_field.bind("focus.chosen",function(e){t.input_focus(e)}),this.search_field.bind("cut.chosen",function(e){t.clipboard_event_checker(e)}),this.search_field.bind("paste.chosen",function(e){t.clipboard_event_checker(e)}),this.is_multiple?this.search_choices.bind("click.chosen",function(e){t.choices_click(e)}):this.container.bind("click.chosen",function(t){t.preventDefault()})},i.prototype.destroy=function(){return t(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},i.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},i.prototype.container_mousedown=function(e){if(!this.is_disabled&&(e&&"mousedown"===e.type&&!this.results_showing&&e.preventDefault(),null==e||!t(e.target).hasClass("search-choice-close")))return this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field()},i.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},i.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e=40*e),this.search_results.scrollTop(e+this.search_results.scrollTop())},i.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},i.prototype.close_field=function(){return t(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},i.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},i.prototype.test_active_click=function(e){var i;return i=t(e.target).closest(".chosen-container"),i.length&&this.container[0]===i[0]?this.active_field=!0:this.close_field()},i.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=n.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch"),this.container.removeClass("chosen-with-search")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"),this.container.addClass("chosen-with-search"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},i.prototype.result_do_highlight=function(t,e){if(t.length){var i,n,o,a,s,r,l=-1;this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),o=parseInt(this.search_results.css("maxHeight"),10),r=this.result_highlight.outerHeight(),s=this.search_results.scrollTop(),a=o+s,n=this.result_highlight.position().top+this.search_results.scrollTop(),i=n+r,this.middle_highlight&&(e||"always"===this.middle_highlight)?l=Math.min(n-r,Math.max(0,n-(o-r)/2)):i>=a?l=i-o>0?i-o:0:n-1?this.search_results.scrollTop(l):this.result_highlight.scrollIntoView&&this.result_highlight.scrollIntoView()}},i.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},i.prototype.results_show=function(){var e=this;if(e.is_multiple&&e.max_selected_options<=e.choices_count())return e.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1;e.results_showing=!0,e.search_field.focus(),e.search_field.val(e.search_field.val()),e.container.addClass("chosen-with-drop"),e.winnow_results(1);var i=e.drop_direction;if("function"==typeof i&&(i=i.call(this)),"auto"===i)if(e.drop_directionFixed)i=e.drop_directionFixed;else{var n=e.container.find(".chosen-drop"),o=n.outerHeight();e.drop_item_height&&o.active-result").length*e.drop_item_height));var a=e.container.offset();a.top+o+30>t(window).height()+t(window).scrollTop()&&(i="up"),e.drop_directionFixed=i}return e.container.toggleClass("chosen-up","up"===i),e.autoResizeDrop(),e.form_field_jq.trigger("chosen:showing_dropdown",{chosen:e})},i.prototype.autoResizeDrop=function(){var e=this,i=e.max_drop_width;if(i){var n=e.container.find(".chosen-drop");n.removeClass("in");var o=0,a=n.find(".chosen-results"),s=a.children("li"),r=parseFloat(a.css("padding-left").replace("px","")),l=parseFloat(a.css("padding-right").replace("px","")),h=(isNaN(r)?0:r)+(isNaN(l)?0:l);s.each(function(){o=Math.max(o,t(this).outerWidth())}),n.css("width",Math.min(o+h+20,i)),e.fixDropWidthTimer=setTimeout(function(){e.fixDropWidthTimer=null,n.addClass("in"),e.winnow_results_set_highlight(1)},50)}},i.prototype.update_results_content=function(t){return this.search_results.html(t)},i.prototype.results_hide=function(){var t=this;return t.fixDropWidthTimer&&(clearTimeout(t.fixDropWidthTimer),t.fixDropWidthTimer=null),t.results_showing&&(t.result_clear_highlight(),t.container.removeClass("chosen-with-drop"),t.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:t}),t.drop_directionFixed=0),t.results_showing=!1},i.prototype.set_tab_index=function(t){var e;if(this.form_field.tabIndex)return e=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=e},i.prototype.set_label_behavior=function(){var e=this;if(this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=t("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0)return this.form_field_label.bind("click.chosen",function(t){return e.is_multiple?e.container_mousedown(t):e.activate_field()})},i.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},i.prototype.search_results_mouseup=function(e){var i;if(i=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first(),i.length)return this.result_highlight=i,this.result_select(e),this.search_field.focus()},i.prototype.search_results_mouseover=function(e){var i;if(i=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(i)},i.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result"))return this.result_clear_highlight()},i.prototype.choice_build=function(e){var i,n,o=this;return i=t("
    • ",{"class":"search-choice"}).html(""+e.html+""),e.disabled?i.addClass("search-choice-disabled"):(n=t("",{"class":"search-choice-close","data-option-array-index":e.array_index}),n.bind("click.chosen",function(t){return o.choice_destroy_link_click(t)}),i.append(n)),this.search_container.before(i)},i.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},i.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},i.prototype.results_reset=function(){var t=this.form_field_jq.val();this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup();var e=this.form_field_jq.val(),i={selected:e};if(t===e||e.length||(i.deselected=t),this.form_field_jq.trigger("change",i),this.sync_sort_field(),this.active_field)return this.results_hide()},i.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},i.prototype.result_select=function(t){var e,i;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),i=this.results_data[e[0].getAttribute("data-option-array-index")],i.selected=!0,this.form_field.options[i.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(i):this.single_set_selected_text(i.text),(t.metaKey||t.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&(this.form_field_jq.trigger("change",{selected:this.form_field.options[i.options_index].value}),this.sync_sort_field()),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())},i.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.compact_search&&this.search_field.attr("placeholder",t),this.selected_item.find("span").attr("title",t).text(t)},i.prototype.sync_sort_field=function(){var e=this;if(e.is_multiple&&e.sort_field){var i=t(e.sort_field);if(!i.length)return;var n=[];e.search_choices.find("li.search-choice").each(function(){var i=t(this),o=i.children(".search-choice-close").first().data("optionArrayIndex"),a=e.results_data[o];a&&a.selected&&n.push(a.value)}),i.val(n.join(e.sort_value_splitter)).trigger("change")}},i.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[e.options_index].value}),this.sync_sort_field(),this.search_field_scale(),!0)},i.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")},i.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":t("
      ").text(t.trim(this.search_field.val())).html()},i.prototype.winnow_results_set_highlight=function(t){var e,i;if(i=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),e=i.length?i.first():this.search_results.find(".active-result").first(),null!=e)return this.result_do_highlight(e,t)},i.prototype.no_results=function(e){var i;return i=t('
    • '+this.results_none_found+' ""
    • '),i.find("span").first().html(e),this.search_results.append(i),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},i.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},i.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},i.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result"),t.length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},i.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last(),t.length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},i.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},i.prototype.keydown_checker=function(t){var e,i;switch(e=null!=(i=t.which)?i:t.keyCode,this.search_field_scale(),8!==e&&this.pending_backstroke&&this.clear_backstroke(),e){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(t),this.mouse_on_container=!1;break;case 13:t.preventDefault();break;case 38:t.preventDefault(),this.keyup_arrow();break;case 40:t.preventDefault(),this.keydown_arrow()}},i.prototype.search_field_scale=function(){var e,i,n,o,a,s,r,l,h;if(this.is_multiple){for(n=0,r=0,a="position:absolute; left: -1000px; top: -1000px; display:none;",s=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],l=0,h=s.length;l",{style:a}),e.text(this.search_field.val()),t("body").append(e),r=e.width()+25,e.remove(),i=this.container.outerWidth(),r>i-10&&(r=i-10),this.search_field.css({width:r+"px"})}},i}(e),i.DEFAULTS=l,i.LANGUAGES=r,t.fn.chosen.Constructor=i}.call(this),function(t){"use strict";var e="zui.selectable",i=function(i,n){this.name=e,this.$=t(i),this.id=t.zui.uuid(),this.selectOrder=1,this.selections={},this.getOptions(n),this._init()},n=function(t,e,i){return t>=i.left&&t<=i.left+i.width&&e>=i.top&&e<=i.top+i.height},o=function(t,e){var i=Math.max(t.left,e.left),o=Math.max(t.top,e.top),a=Math.min(t.left+t.width,e.left+e.width),s=Math.min(t.top+t.height,e.top+e.height);return n(i,o,t)&&n(a,s,t)&&n(i,o,e)&&n(a,s,e)};i.DEFAULTS={selector:"li,tr,div",trigger:"",selectClass:"active",rangeStyle:{border:"1px solid "+(t.zui.colorset?t.zui.colorset.primary:"#3280fc"),backgroundColor:t.zui.colorset?new t.zui.Color(t.zui.colorset.primary).fade(20).toCssStr():"rgba(50, 128, 252, 0.2)"},clickBehavior:"toggle",ignoreVal:3,listenClick:!0},i.prototype.getOptions=function(e){this.options=t.extend({},i.DEFAULTS,this.$.data(),e)},i.prototype.select=function(t){this.toggle(t,!0)},i.prototype.unselect=function(t){this.toggle(t,!1)},i.prototype.toggle=function(e,i,n){var o,a,s=this.options.selector,r=this;if(void 0===e)return void this.$.find(s).each(function(){r.toggle(this,i)});if("object"==typeof e?(o=t(e).closest(s),a=o.data("id")):(a=e,o=r.$.find('.slectable-item[data-id="'+a+'"]')),o&&o.length){if(a||(a=t.zui.uuid(),o.attr("data-id",a)),void 0!==i&&null!==i||(i=!r.selections[a]),!!i!=!!r.selections[a]){var l;"function"==typeof n&&(l=n(i)),l!==!0&&(r.selections[a]=!!i&&r.selectOrder++,r.callEvent(i?"select":"unselect",{id:a,selections:r.selections,target:o, -selected:r.getSelectedArray()},r))}r.options.selectClass&&o.toggleClass(r.options.selectClass,i)}},i.prototype.getSelectedArray=function(){var e=[];return t.each(this.selections,function(t,i){i&&e.push(t)}),e},i.prototype.syncSelectionsFromClass=function(){var e=this,i=e.$children=e.$.find(e.options.selector);e.selections={},i.each(function(){var i=t(this);e.selections[i.data("id")]=i.hasClass(e.options.selectClass)})},i.prototype._init=function(){var e,i,n,a,s,r,l,h=this.options,c=this,d=h.ignoreVal,u=!0,f="."+this.name+"."+this.id,p="function"==typeof h.checkFunc?h.checkFunc:null,g="function"==typeof h.rangeFunc?h.rangeFunc:null,m=!1,v=null,y="mousedown"+f,b=function(){a&&c.$children.each(function(){var e=t(this),i=e.offset();i.width=e.outerWidth(),i.height=e.outerHeight();var n=g?g.call(this,a,i):o(a,i);if(p){var s=p.call(c,{intersect:n,target:e,range:a,targetRange:i});s===!0?c.select(e):s===!1&&c.unselect(e)}else n?c.select(e):c.multiKey||c.unselect(e)})},w=function(o){m&&(s=o.pageX,r=o.pageY,a={width:Math.abs(s-e),height:Math.abs(r-i),left:s>e?e:s,top:r>i?i:r},u&&a.width
      ').css(t.extend({zIndex:1060,position:"absolute",top:e,left:i,pointerEvents:"none"},c.options.rangeStyle)).appendTo(t("body")))),n.css(a),clearTimeout(l),l=setTimeout(b,10),u=!1))},x=function(e){t(document).off(f),clearTimeout(v),m&&(m=!1,n&&n.remove(),u||a&&(clearTimeout(l),b(),a=null),c.callEvent("finish",{selections:c.selections,selected:c.getSelectedArray()}),e.preventDefault())},C=function(o){if(m)return x(o);var a=t.zui.getMouseButtonCode(h.mouseButton);if(!(a>-1&&o.button!==a||c.altKey||3===o.which||c.callEvent("start",o)===!1)){var s=c.$children=c.$.find(h.selector);s.addClass("slectable-item");var r=c.multiKey?"multi":h.clickBehavior;if("single"===r&&c.unselect(),h.listenClick&&("multi"===r?c.toggle(o.target):"single"===r?c.select(o.target):"toggle"===r&&c.toggle(o.target,null,function(t){c.unselect()})),c.callEvent("startDrag",o)===!1)return void c.callEvent("finish",{selections:c.selections,selected:c.getSelectedArray()});e=o.pageX,i=o.pageY,n=null,u=!0,m=!0,t(document).on("mousemove"+f,w).on("mouseup"+f,x),v=setTimeout(function(){t(document).on(y,x)},10),o.preventDefault()}},_=h.container&&"default"!==h.container?t(h.container):this.$;h.trigger?_.on(y,h.trigger,C):_.on(y,C),t(document).on("keydown",function(t){var e=t.keyCode;17===e||91==e?c.multiKey=e:18===e&&(c.altKey=!0)}).on("keyup",function(t){c.multiKey=!1,c.altKey=!1})},i.prototype.callEvent=function(e,i){var n=t.Event(e+"."+this.name);this.$.trigger(n,i);var o=n.result,a=this.options[e];return"function"==typeof a&&(o=a.apply(this,Array.isArray(i)?i:[i])),o},t.fn.selectable=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},t.fn.selectable.Constructor=i,t(function(){t('[data-ride="selectable"]').selectable()})}(jQuery),+function(t,e,i){"use strict";if(!t.fn.droppable)return void console.error("Sortable requires droppable.js");var n="zui.sortable",o={selector:"li,div",dragCssClass:"invisible",sortingClass:"sortable-sorting"},a="order",s=function(e,i){var n=this;n.$=t(e),n.options=t.extend({},o,n.$.data(),i),n.init()};s.DEFAULTS=o,s.NAME=n,s.prototype.init=function(){var e,i=this,n=i.$,o=i.options,s=o.selector,r=o.containerSelector,l=o.sortingClass,h=o.dragCssClass,c=o.targetSelector,d=o.reverse,u=function(e){e=e||i.getItems(1);var n=e.length;n&&e.each(function(e){var i=d?n-e:e;t(this).attr("data-"+a,i).data(a,i)})};u(),n.droppable({handle:o.trigger,target:c?c:r?s+","+r:s,selector:s,container:n,always:o.always,flex:!0,lazy:o.lazy,canMoveHere:o.canMoveHere,dropToClass:o.dropToClass,before:o.before,nested:!!r,mouseButton:o.mouseButton,stopPropagation:o.stopPropagation,start:function(t){h&&t.element.addClass(h),e=!1,i.trigger("start",t)},drag:function(t){if(n.addClass(l),t.isIn){var o=t.element,h=t.target,c=r&&h.is(r);if(c){if(!h.children(s).filter(".dragging").length){h.append(o);var f=i.getItems(1);u(f),i.trigger(a,{list:f,element:o})}return}var p=o.data(a),g=h.data(a);if(p===g)return u(f);p>g?h[d?"after":"before"](o):h[d?"before":"after"](o),e=!0;var f=i.getItems(1);u(f),i.trigger(a,{list:f,element:o})}},finish:function(t){h&&t.element&&t.element.removeClass(h),n.removeClass(l),i.trigger("finish",{list:i.getItems(),element:t.element,changed:e})}})},s.prototype.destroy=function(){this.$.droppable("destroy"),this.$.data(n,null)},s.prototype.reset=function(){this.destroy(),this.init()},s.prototype.getItems=function(e){var i=this.$.find(this.options.selector).not(".drag-shadow");return e?i:i.map(function(){var e=t(this);return{item:e,order:e.data("order")}})},s.prototype.trigger=function(e,i){return t.zui.callEvent(this.options[e],i,this)},t.fn.sortable=function(e){return this.each(function(){var i=t(this),o=i.data(n),a="object"==typeof e&&e;o?"object"==typeof e&&o.reset():i.data(n,o=new s(this,a)),"string"==typeof e&&o[e]()})},t.fn.sortable.Constructor=s}(jQuery,window,document),function(t,e){"use strict";var i="zui.contextmenu",n={animation:"fade",menuTemplate:'',toggleTrigger:!1,duration:200,limitInsideWindow:!0},o=!1,a={},s="zui-contextmenu-"+t.zui.uuid(),r=0,l=0,h=function(){return t(document).off("mousemove."+i).on("mousemove."+i,function(t){r=t.clientX,l=t.clientY}),a},c=function(e,i){if("string"==typeof e&&(e="seperator"===e||"divider"===e||"-"===e||"|"===e?{type:"seperator"}:{label:e,id:i}),"seperator"===e.type||"divider"===e.type)return t('
    • ');var n=t("
      ").attr({href:e.url||"###","class":e.className,style:e.style}).data("item",e);return e.html?e.html===!0?n.html(e.label||e.text):n=t(e.html):n.text(e.label||e.text),e.onClick&&n.on("click",e.onClick),t("
    • ").toggleClass("disabled",e.disabled===!0).append(n)},d=function(e){var i=t("#"+s);return i.length&&i.hasClass("contextmenu-show")&&(!e||(i.data("options")||{}).id===e)},u=null,f=function(e,i){"function"==typeof e&&(i=e,e=null),u&&(clearTimeout(u),u=null);var n=t("#"+s);if(n.length){var o=n.removeClass("contextmenu-show").data("options");if(!e||o.id===e){var r=function(){n.find(".contextmenu-menu").removeClass("open"),o.onHidden&&o.onHidden(),i&&i()};o.onHide&&o.onHide();var l=o.animation;n.find(".contextmenu-menu").removeClass("in"),l?u=setTimeout(r,o.duration):r()}}return a},p=function(h,d,p){t.isPlainObject(h)&&(p=d,d=h,h=d.items),o=!0,d=t.extend({},n,d);var g=t("#"+s);g.length||(g=t('
      ').appendTo("body"));var m=g.find(".contextmenu-menu").off("click."+i).on("click."+i,"a,.contextmenu-item",function(e){var i=t(this),n=d.onClickItem&&d.onClickItem(i.data("item"),i,e);n!==!1&&f()}).empty();m.attr("class","contextmenu-menu"+(d.className?" "+d.className:"")),g.attr("class","contextmenu contextmenu-show");var v=d.menuCreator;if(v)m.append(v(h,d));else{m.append(d.menuTemplate);var y=m.children().first(),b=d.itemCreator||c,w=typeof h;"string"===w?h=h.split(","):"function"===w&&(h=h(d)),t.each(h,function(t,e){y.append(b(e,t,d))})}var x=d.animation,C=d.duration;x===!0&&(d.animation=x="fade"),u&&(clearTimeout(u),u=null);var _=function(){m.addClass("in"),d.onShown&&d.onShown(),p&&p()};d.onShow&&d.onShow(),g.data("options",{animation:x,onHide:d.onHide,onHidden:d.onHidden,id:d.id,duration:C});var k=d.x,T=d.y;k===e&&(k=(d.event||d).clientX),k===e&&(k=r),T===e&&(T=(d.event||d).clientY),T===e&&(T=l);var y=m.children().first(),S=y.outerWidth(),D=y.outerHeight();if(d.position){var M=d.position({x:k,y:T,width:S,height:D},d,m);M&&(k=M.x,T=M.y)}if(d.limitInsideWindow){var P=t(window);k=Math.max(0,Math.min(k,P.width()-S)),T=Math.max(0,Math.min(T,P.height()-D))}return g.css({left:k,top:T}).show(),m.addClass("open"),x?(m.addClass(x),u=setTimeout(function(){_(),o=!1},10)):(_(),o=!1),a};t.extend(a,{NAME:i,DEFAULTS:n,show:p,hide:f,listenMouse:h,isShow:d}),t.zui({ContextMenu:a});var g=function(e,n){var o=this;o.name=i,o.$=t(e),o.id=t.zui.uuid(),n=o.options=t.extend({trigger:"contextmenu"},a.DEFAULTS,this.$.data(),n);var s=function(t){if("mousedown"!==t.type||2===t.button){if(n.toggleTrigger&&o.isShow())o.hide();else{var e={x:t.clientX,y:t.clientY,event:t};o.show(e)}return t.preventDefault(),t.returnValue=!1,!1}},r=n.trigger,l=r+"."+i;n.selector?o.$.on(l,n.selector,s):o.$.on(l,s),n.show&&o.show("object"==typeof n.show?n.show:null)};g.prototype.destory=function(){that.$.off("."+i)},g.prototype.hide=function(t){a.hide(this.id,t)},g.prototype.show=function(e,i){e=t.extend({id:this.id,$toggle:this.$},this.options,e),a.show(e,i)},g.prototype.isShow=function(){return d(this.id)},t.fn.contextmenu=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new g(this,a)),"string"==typeof e&&o[e]()})},t.fn.contextmenu.Constructor=g,t.fn.contextDropdown=function(e){t(this).contextmenu(t.extend({trigger:"click",animation:"fade",toggleTrigger:!0,menuCreator:function(e,i){var n=i.$toggle,o=n.attr("data-target");o||(o=n.attr("href"),o=o&&/#/.test(o)&&o.replace(/.*(?=#[^\s]*$)/,""));var a=o?t(o):n.next(".dropdown-menu"),s=i.transferEvent;if(s!==!1){var r="data-contextmenu-index";a.find("a,.contextmenu-item").each(function(e){t(this).attr(r,e)});var l=a.clone();return l.on("string"==typeof s?s:"click","a,.contextmenu-item",function(e){var i=a.find("["+r+'="'+t(this).attr(r)+'"]'),n=i[0];if(n)return n[e.type]?n[e.type]():i.trigger(e.type),e.preventDefault(),e.stopPropagation(),!1}),l}return a.clone()},position:function(t,e,i){var n=e.placement,o=e.$toggle;if(!n){var a=i.find(".dropdown-menu"),s=a.hasClass("pull-right"),r=o.parent().hasClass("dropup");n=s?r?"top-right":"bottom-right":r?"top-left":"bottom-left",s&&a.removeClass("pull-right")}var l=o[0].getBoundingClientRect();switch(n){case"top-left":return{x:l.left,y:Math.floor(l.top-t.height)};case"top-right":return{x:Math.floor(l.right-t.width),y:Math.floor(l.top-t.height)};case"bottom-left":return{x:l.left,y:l.bottom};case"bottom-right":return{x:Math.floor(l.right-t.width),y:l.bottom}}return t}},e))},t(document).on("click",function(e){var n=t(e.target),a=n.closest('[data-toggle="context-dropdown"]');if(a.length){var s=a.data(i);s||a.contextDropdown({show:!0})}else o||n.closest(".contextmenu").length||f()})}(jQuery,void 0),/*! +selected:r.getSelectedArray()},r))}r.options.selectClass&&o.toggleClass(r.options.selectClass,i)}},i.prototype.getSelectedArray=function(){var e=[];return t.each(this.selections,function(t,i){i&&e.push(t)}),e},i.prototype.syncSelectionsFromClass=function(){var e=this,i=e.$children=e.$.find(e.options.selector);e.selections={},i.each(function(){var i=t(this);e.selections[i.data("id")]=i.hasClass(e.options.selectClass)})},i.prototype._init=function(){var e,i,n,a,s,r,l,h=this.options,c=this,d=h.ignoreVal,u=!0,f="."+this.name+"."+this.id,p="function"==typeof h.checkFunc?h.checkFunc:null,g="function"==typeof h.rangeFunc?h.rangeFunc:null,m=!1,v=null,y="mousedown"+f,b=function(){a&&c.$children.each(function(){var e=t(this),i=e.offset();i.width=e.outerWidth(),i.height=e.outerHeight();var n=g?g.call(this,a,i):o(a,i);if(p){var s=p.call(c,{intersect:n,target:e,range:a,targetRange:i});s===!0?c.select(e):s===!1&&c.unselect(e)}else n?c.select(e):c.multiKey||c.unselect(e)})},w=function(o){m&&(s=o.pageX,r=o.pageY,a={width:Math.abs(s-e),height:Math.abs(r-i),left:s>e?e:s,top:r>i?i:r},u&&a.width').css(t.extend({zIndex:1060,position:"absolute",top:e,left:i,pointerEvents:"none"},c.options.rangeStyle)).appendTo(t("body")))),n.css(a),clearTimeout(l),l=setTimeout(b,10),u=!1))},x=function(e){t(document).off(f),clearTimeout(v),m&&(m=!1,n&&n.remove(),u||a&&(clearTimeout(l),b(),a=null),c.callEvent("finish",{selections:c.selections,selected:c.getSelectedArray()}),e.preventDefault())},C=function(o){if(m)return x(o);var a=t.zui.getMouseButtonCode(h.mouseButton);if(!(a>-1&&o.button!==a||c.altKey||3===o.which||c.callEvent("start",o)===!1)){var s=c.$children=c.$.find(h.selector);s.addClass("slectable-item");var r=c.multiKey?"multi":h.clickBehavior;if("single"===r&&c.unselect(),h.listenClick&&("multi"===r?c.toggle(o.target):"single"===r?c.select(o.target):"toggle"===r&&c.toggle(o.target,null,function(t){c.unselect()})),c.callEvent("startDrag",o)===!1)return void c.callEvent("finish",{selections:c.selections,selected:c.getSelectedArray()});e=o.pageX,i=o.pageY,n=null,u=!0,m=!0,t(document).on("mousemove"+f,w).on("mouseup"+f,x),v=setTimeout(function(){t(document).on(y,x)},10),o.preventDefault()}},_=h.container&&"default"!==h.container?t(h.container):this.$;h.trigger?_.on(y,h.trigger,C):_.on(y,C),t(document).on("keydown",function(t){var e=t.keyCode;17===e||91==e?c.multiKey=e:18===e&&(c.altKey=!0)}).on("keyup",function(t){c.multiKey=!1,c.altKey=!1})},i.prototype.callEvent=function(e,i){var n=t.Event(e+"."+this.name);this.$.trigger(n,i);var o=n.result,a=this.options[e];return"function"==typeof a&&(o=a.apply(this,Array.isArray(i)?i:[i])),o},t.fn.selectable=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},t.fn.selectable.Constructor=i,t(function(){t('[data-ride="selectable"]').selectable()})}(jQuery),+function(t,e,i){"use strict";if(!t.fn.droppable)return void console.error("Sortable requires droppable.js");var n="zui.sortable",o={selector:"li,div",dragCssClass:"invisible",sortingClass:"sortable-sorting"},a="order",s=function(e,i){var n=this;n.$=t(e),n.options=t.extend({},o,n.$.data(),i),n.init()};s.DEFAULTS=o,s.NAME=n,s.prototype.init=function(){var e,i=this,n=i.$,o=i.options,s=o.selector,r=o.containerSelector,l=o.sortingClass,h=o.dragCssClass,c=o.targetSelector,d=o.reverse,u=function(e){e=e||i.getItems(1);var n=e.length;n&&e.each(function(e){var i=d?n-e:e;t(this).attr("data-"+a,i).data(a,i)})};u(),n.droppable({handle:o.trigger,target:c?c:r?s+","+r:s,selector:s,container:n,always:o.always,flex:!0,lazy:o.lazy,canMoveHere:o.canMoveHere,dropToClass:o.dropToClass,before:o.before,nested:!!r,mouseButton:o.mouseButton,stopPropagation:o.stopPropagation,start:function(t){h&&t.element.addClass(h),e=!1,i.trigger("start",t)},drag:function(t){if(n.addClass(l),t.isIn){var o=t.element,h=t.target,c=r&&h.is(r);if(c){if(!h.children(s).filter(".dragging").length){h.append(o);var f=i.getItems(1);u(f),i.trigger(a,{list:f,element:o})}return}var p=o.data(a),g=h.data(a);if(p===g)return u(f);p>g?h[d?"after":"before"](o):h[d?"before":"after"](o),e=!0;var f=i.getItems(1);u(f),i.trigger(a,{list:f,element:o})}},finish:function(t){h&&t.element&&t.element.removeClass(h),n.removeClass(l),i.trigger("finish",{list:i.getItems(),element:t.element,changed:e})}})},s.prototype.destroy=function(){this.$.droppable("destroy"),this.$.data(n,null)},s.prototype.reset=function(){this.destroy(),this.init()},s.prototype.getItems=function(e){var i=this.$.find(this.options.selector).not(".drag-shadow");return e?i:i.map(function(){var e=t(this);return{item:e,order:e.data("order")}})},s.prototype.trigger=function(e,i){return t.zui.callEvent(this.options[e],i,this)},t.fn.sortable=function(e){return this.each(function(){var i=t(this),o=i.data(n),a="object"==typeof e&&e;o?"object"==typeof e&&o.reset():i.data(n,o=new s(this,a)),"string"==typeof e&&o[e]()})},t.fn.sortable.Constructor=s}(jQuery,window,document),function(t,e){"use strict";var i="zui.contextmenu",n={animation:"fade",menuTemplate:'',toggleTrigger:!1,duration:200,limitInsideWindow:!0},o=!1,a={},s="zui-contextmenu-"+t.zui.uuid(),r=0,l=0,h=function(){return t(document).off("mousemove."+i).on("mousemove."+i,function(t){r=t.clientX,l=t.clientY}),a},c=function(e,i){if("string"==typeof e&&(e="seperator"===e||"divider"===e||"-"===e||"|"===e?{type:"seperator"}:{label:e,id:i}),"seperator"===e.type||"divider"===e.type)return t('
    • ');var n=t("
      ").attr({href:e.url||"###","class":e.className,style:e.style}).data("item",e);return e.html?e.html===!0?n.html(e.label||e.text):n=t(e.html):n.text(e.label||e.text),e.onClick&&n.on("click",e.onClick),t("
    • ").toggleClass("disabled",e.disabled===!0).append(n)},d=function(e){var i=t("#"+s);return i.length&&i.hasClass("contextmenu-show")&&(!e||(i.data("options")||{}).id===e)},u=null,f=function(e,i){"function"==typeof e&&(i=e,e=null),u&&(clearTimeout(u),u=null);var n=t("#"+s);if(n.length){var o=n.removeClass("contextmenu-show").data("options");if(!e||o.id===e){var r=function(){n.find(".contextmenu-menu").removeClass("open"),o.onHidden&&o.onHidden(),i&&i()};o.onHide&&o.onHide();var l=o.animation;n.find(".contextmenu-menu").removeClass("in"),l?u=setTimeout(r,o.duration):r()}}return a},p=function(h,d,p){t.isPlainObject(h)&&(p=d,d=h,h=d.items),o=!0,d=t.extend({},n,d);var g=t("#"+s);g.length||(g=t('
      ').appendTo("body"));var m=g.find(".contextmenu-menu").off("click."+i).on("click."+i,"a,.contextmenu-item",function(e){var i=t(this),n=d.onClickItem&&d.onClickItem(i.data("item"),i,e,d);n!==!1&&f()}).empty();m.attr("class","contextmenu-menu"+(d.className?" "+d.className:"")),g.attr("class","contextmenu contextmenu-show");var v=d.menuCreator;if(v)m.append(v(h,d));else{m.append(d.menuTemplate);var y=m.children().first(),b=d.itemCreator||c,w=typeof h;if("string"===w?h=h.split(","):"function"===w&&(h=h(d)),!h)return!1;t.each(h,function(t,e){y.append(b(e,t,d))})}var x=d.animation,C=d.duration;x===!0&&(d.animation=x="fade"),u&&(clearTimeout(u),u=null);var _=function(){m.addClass("in"),d.onShown&&d.onShown(),p&&p()};d.onShow&&d.onShow(),g.data("options",{animation:x,onHide:d.onHide,onHidden:d.onHidden,id:d.id,duration:C});var k=d.x,T=d.y;k===e&&(k=(d.event||d).clientX),k===e&&(k=r),T===e&&(T=(d.event||d).clientY),T===e&&(T=l);var y=m.children().first(),S=y.outerWidth(),D=y.outerHeight();if(d.position){var M=d.position({x:k,y:T,width:S,height:D},d,m);M&&(k=M.x,T=M.y)}if(d.limitInsideWindow){var P=t(window);k=Math.max(0,Math.min(k,P.width()-S)),T=Math.max(0,Math.min(T,P.height()-D))}return g.css({left:k,top:T}).show(),m.addClass("open"),x?(m.addClass(x),u=setTimeout(function(){_(),o=!1},10)):(_(),o=!1),a};t.extend(a,{NAME:i,DEFAULTS:n,show:p,hide:f,listenMouse:h,isShow:d}),t.zui({ContextMenu:a});var g=function(e,n){var o=this;o.name=i,o.$=t(e),o.id=t.zui.uuid(),n=o.options=t.extend({trigger:"contextmenu"},a.DEFAULTS,this.$.data(),n);var s=function(t){if("mousedown"!==t.type||2===t.button){if(n.toggleTrigger&&o.isShow())o.hide();else{var e={x:t.clientX,y:t.clientY,event:t};if(o.show(e)===!1)return}return t.preventDefault(),t.returnValue=!1,!1}},r=n.trigger,l=r+"."+i;n.selector?o.$.on(l,n.selector,s):o.$.on(l,s),n.show&&o.show("object"==typeof n.show?n.show:null)};g.prototype.destory=function(){that.$.off("."+i)},g.prototype.hide=function(t){return a.hide(this.id,t)},g.prototype.show=function(e,i){return e=t.extend({id:this.id,$toggle:this.$},this.options,e),a.show(e,i)},g.prototype.isShow=function(){return d(this.id)},t.fn.contextmenu=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new g(this,a)),"string"==typeof e&&o[e]()})},t.fn.contextmenu.Constructor=g,t.fn.contextDropdown=function(e){t(this).contextmenu(t.extend({trigger:"click",animation:"fade",toggleTrigger:!0,menuCreator:function(e,i){var n=i.$toggle,o=n.attr("data-target");o||(o=n.attr("href"),o=o&&/#/.test(o)&&o.replace(/.*(?=#[^\s]*$)/,""));var a=o?t(o):n.next(".dropdown-menu"),s=i.transferEvent;if(s!==!1){var r="data-contextmenu-index";a.find("a,.contextmenu-item").each(function(e){t(this).attr(r,e)});var l=a.clone();return l.on("string"==typeof s?s:"click","a,.contextmenu-item",function(e){var i=a.find("["+r+'="'+t(this).attr(r)+'"]'),n=i[0];if(n)return n[e.type]?n[e.type]():i.trigger(e.type),e.preventDefault(),e.stopPropagation(),!1}),l}return a.clone()},position:function(t,e,i){var n=e.placement,o=e.$toggle;if(!n){var a=i.find(".dropdown-menu"),s=a.hasClass("pull-right"),r=o.parent().hasClass("dropup");n=s?r?"top-right":"bottom-right":r?"top-left":"bottom-left",s&&a.removeClass("pull-right")}var l=o[0].getBoundingClientRect();switch(n){case"top-left":return{x:l.left,y:Math.floor(l.top-t.height)};case"top-right":return{x:Math.floor(l.right-t.width),y:Math.floor(l.top-t.height)};case"bottom-left":return{x:l.left,y:l.bottom};case"bottom-right":return{x:Math.floor(l.right-t.width),y:l.bottom}}return t}},e))},t(document).on("click",function(e){var n=t(e.target),a=n.closest('[data-toggle="context-dropdown"]');if(a.length){var s=a.data(i);s||a.contextDropdown({show:!0})}else o||n.closest(".contextmenu").length||f()})}(jQuery,void 0),/*! * jQuery Form Plugin * version: 4.2.2 * Requires jQuery v1.7.2 or later @@ -75,5 +75,5 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,h=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t){"use strict";function e(e,i){if(e===!1)return e;if(!e)return i;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var n;return Array.isArray(e)&&(n={},t.each(e,function(e,i){t.isPlainObject(i)?n[i.action]=i:n[i]=!0}),e=n),t.isPlainObject(e)&&(n={},t.each(e,function(e,i){i?n[e]=t.extend({type:e},s[e],t.isPlainObject(i)?i:null):n[e]=!1}),e=n),i?t.extend(!0,{},i,e):e}function i(e,i,n){return i=i||e.type,t(n||e.template).addClass("tree-action").attr(t.extend({"data-type":i,title:e.title||""},e.attr)).data("action",e)}var n="zui.tree",o=0,a=function(e,i){this.name=n,this.$=t(e),this.getOptions(i),this._init()},s={sort:{template:'
      '},add:{template:''},edit:{template:''},"delete":{template:''}};a.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},a.prototype.add=function(e,i,n,o,a){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
        "),r.append(s),this._initList(s,r))):s=r,s){var h=this;Array.isArray(i)||(i=[i]),t.each(i,function(e,i){var n=t("
      • ").data(i).appendTo(s);void 0!==i.id&&n.attr("data-id",i.id);var o=l.itemWrapper?t(l.itemWrapper===!0?'
      • ').append(i(h.add,"add",h.add.templateInList)).appendTo(n)}h.sort&&n.sortable(t.extend({dragCssClass:"tree-drag-holder",trigger:".sort-handler",selector:"li:not(.tree-action-item)",finish:function(t){r.callEvent("action",{action:h.sort,$list:n,target:t.target,item:s})}},h.sort.options,t.isPlainObject(this.options.sortable)?this.options.sortable:null))}o&&(o.hasClass("open")||s&&s.open)&&o.addClass("open in")},a.prototype._initItem=function(n,o,a,s){if(void 0===o){var r=n.prev("li");o=r.length?r.data("idx")+1:1}if(a=a||n.closest("ul"),n.attr("data-idx",o).removeClass("tree-single-item"),!n.data("id")){var l=o;a.hasClass("tree")||(l=a.parent("li").data("id")+"-"+l),n.attr("data-id",l)}n.hasClass("active")&&a.parent("li").addClass("has-active-item"),s=s||n.data();var h=e(s.actions,this.actions);if(h){var c=n.find(".tree-actions");c.length||(c=t('
        ').appendTo(this.options.itemWrapper?n.find(".tree-item-wrapper"):n),t.each(h,function(t,e){e&&c.append(i(e,t))}))}var d=n.children("ul");d.length&&this._initList(d,n,o,s)},a.prototype._init=function(){var i=this.options,a=this;this.actions=e(i.actions),this.$.addClass("tree"),i.animate&&this.$.addClass("tree-animate"),this._initList(this.$);var s=i.initialState,r=t.zui&&t.zui.store&&t.zui.store.enable;r&&(this.selector=n+"::"+(i.name||"")+"#"+(this.$.attr("id")||o++),this.store=t.zui.store[i.name?"get":"pageGet"](this.selector,{})),"preserve"===s&&(r?this.isPreserve=!0:this.options.initialState=s="normal"),this.reload(i.data),r&&(this.isPreserve=!0),"expand"===s?this.expand():"collapse"===s?this.collapse():"active"===s&&this.expandSelect(".active"),this.$.on("click",'.list-toggle,a[href="#"],.tree-toggle',function(e){var i=t(this),n=i.parent("li");a.callEvent("hit",{target:n,item:n.data()}),a.toggle(n),i.is("a")&&e.preventDefault()}).on("click",".tree-action",function(){var e=t(this),i=e.data();if(i.action&&(i=i.action),"sort"!==i.type){var n=e.closest("li:not(.tree-action-item)");a.callEvent("action",{action:i,target:this,$item:n,item:n.data()})}})},a.prototype.preserve=function(e,i,n){if(this.isPreserve)if(e)i=i||e.data("id"),n=void 0===n&&e.hasClass("open"),n?this.store[i]=n:delete this.store[i],this.store.time=(new Date).getTime(),t.zui.store[this.options.name?"set":"pageSet"](this.selector,this.store);else{var o=this;this.store={},this.$.find("li").each(function(){o.preserve(t(this))})}},a.prototype.expandSelect=function(t){this.show(t,!0)},a.prototype.expand=function(t,e,i){t?(t.addClass("open"),!e&&this.options.animate?setTimeout(function(){t.addClass("in")},10):t.addClass("in")):t=this.$.find("li.has-list").addClass("open in"),i||this.preserve(t),this.callEvent("expand",t,this)},a.prototype.show=function(e,i,n){var o=this;e instanceof t||(e=o.$.find("li").filter(e)),e.each(function(){var e=t(this);if(o.expand(e,i,n),e)for(var a=e.parent("ul");a&&a.length&&!a.hasClass("tree");){var s=a.parent("li");s.length?(o.expand(s,i,n),a=s.parent("ul")):a=!1}})},a.prototype.collapse=function(t,e,i){t?!e&&this.options.animate?(t.removeClass("in"),setTimeout(function(){t.removeClass("open")},300)):t.removeClass("open in"):t=this.$.find("li.has-list").removeClass("open in"),i||this.preserve(t),this.callEvent("collapse",t,this)},a.prototype.toggle=function(t){var e=t&&t.hasClass("open")||t===!1||void 0===t&&this.$.find("li.has-list.open").length;this[e?"collapse":"expand"](t)},a.prototype.getOptions=function(e){this.options=t.extend({},a.DEFAULTS,this.$.data(),e),null===this.options.animate&&this.$.hasClass("tree-animate")&&(this.options.animate=!0)},a.prototype.toData=function(e,i){"function"==typeof e&&(i=e,e=null),e=e||this.$;var n=this;return e.children("li:not(.tree-action-item)").map(function(){var e=t(this),o=e.data();delete o["zui.droppable"];var a=e.children("ul");return a.length&&(o.children=n.toData(a)),"function"==typeof i?i(o,e):o}).get()},a.prototype.callEvent=function(e,i){var n;return"function"==typeof this.options[e]&&(n=this.options[e](i,this)),this.$.trigger(t.Event(e+"."+this.name,i)),n},t.fn.tree=function(e,i){return this.each(function(){var o=t(this),s=o.data(n),r="object"==typeof e&&e;s||o.data(n,s=new a(this,r)),"string"==typeof e&&s[e](i)})},t.fn.tree.Constructor=a,t(function(){t('[data-ride="tree"]').tree()})}(jQuery),function(t){"use strict";var e="zui.colorPicker",i='
        ',n={zh_cn:{errorTip:"不是有效的颜色值"},zh_tw:{errorTip:"不是有效的顏色值"},en:{errorTip:"Not a valid color value"}},o=function(i,n){this.name=e,this.$=t(i),this.getOptions(n),this.init()};o.prototype.init=function(){var e=this,n=e.options,o=e.$,a=o.parent(),s=!1;a.hasClass("colorpicker")?e.$picker=a:(e.$picker=t(n.template||i),s=!0),e.$picker.addClass(n.wrapper).find(".cp-title").toggle(void 0!==n.title).text(n.title),e.$menu=e.$picker.find(".dropdown-menu").toggleClass("pull-right",n.pullMenuRight),e.$btn=e.$picker.find(".btn.dropdown-toggle"),e.$btn.find(".ic").addClass("icon-"+n.icon),n.btnTip&&e.$picker.attr("data-toggle","tooltip").tooltip({title:n.btnTip,placement:n.tooltip,container:"body"}),o.attr("data-provide",null),s&&o.after(e.$picker),e.colors={},t.each(n.colors,function(i,n){if(t.zui.Color.isColor(n)){var o=new t.zui.Color(n);e.colors[o.toCssStr()]=o}}),e.updateColors(),e.$picker.on("click",".cp-tile",function(){e.setValue(t(this).data("color"))});var r=function(){var i=o.val(),a=t.zui.Color.isColor(i);o.parent().toggleClass("has-error",!(a||n.optional&&""===i)),a?e.setValue(i,!0):n.optional&&""===i?o.tooltip("hide"):o.is(":focus")||o.tooltip("show",n.errorTip)};o.is("input:not([type=hidden])")?(n.tooltip&&o.attr("data-toggle","tooltip").tooltip({trigger:"manual",placement:n.tooltip,tipClass:"tooltip-danger",container:"body"}),o.on("keyup paste input change",r)):o.appendTo(e.$picker),r()},o.prototype.addColor=function(e){e instanceof t.zui.Color||(e=new t.zui.Color(e));var i=e.toCssStr(),n=this.options;this.colors[i]||(this.colors[i]=e);var o=t('
        ',{titile:e}).data("color",e).css({color:e.contrast().toCssStr(),background:i,"border-color":e.luma()>.43?"#ccc":"transparent"}).attr("data-color",i);this.$menu.append(t("
      • ").css({width:n.tileSize,height:n.tileSize}).append(o)),n.optional&&this.$menu.find(".cp-tile.empty").parent().detach().appendTo(this.$menu)},o.prototype.updateColors=function(e){var i=this.$menu,n=this.options,e=e||this.colors,o=this,a=0;if(i.children("li:not(.heading)").remove(),t.each(e,function(t,e){o.addColor(e),a++}),n.optional){var s=t('
      • ').css({width:n.tileSize,height:n.tileSize});this.$menu.append(s),a++}i.css("width",Math.min(a,n.lineCount)*n.tileSize+6)},o.prototype.setValue=function(e,i){var n=this,o=n.options,a=n.$btn,s="";n.$menu.find(".cp-tile.active").removeClass("active");var r=o.updateBtn;if("auto"===r){var l=a.find(".color-bar");r=!l.length||function(t){l.css("background",t||"")}}if(e){var h=new t.zui.Color(e);s=h.toCssStr().toLowerCase(),r&&("function"==typeof r?r(s,a,n):a.css({background:s,color:h.contrast().toCssStr(),borderColor:h.luma()>.43?"#ccc":s})),n.colors[s]||n.addColor(h),i||n.$.val().toLowerCase()===s||n.$.val(s).trigger("change"),n.$menu.find('.cp-tile[data-color="'+s+'"]').addClass("active"),n.$.tooltip("hide"),n.$.trigger("colorchange",h)}else r&&("function"==typeof r?r(null,a,n):a.attr("style",null)),i||""===n.$.val()||n.$.val(s).trigger("change"),o.optional&&n.$.tooltip("hide"),n.$menu.find(".cp-tile.empty").addClass("active"),n.$.trigger("colorchange",null);o.updateBorder&&t(o.updateBorder).css("border-color",s),o.updateBackground&&t(o.updateBackground).css("background-color",s),o.updateColor&&t(o.updateColor).css("color",s),o.updateText&&t(o.updateText).text(s)},o.prototype.getOptions=function(i){var a=t.extend({},o.DEFAULTS,this.$.data(),i);"string"==typeof a.colors&&(a.colors=a.colors.split(","));var s=a.lang||t.zui.clientLang(),r=this.lang=t.zui.getLangData?t.zui.getLangData(e,s,n):n[s]||n.en;a.errorTip||(a.errorTip=r.errorTip),t.fn.tooltip||(a.btnTip=!1),this.options=a},o.DEFAULTS={colors:["#00BCD4","#388E3C","#3280fc","#3F51B5","#9C27B0","#795548","#F57C00","#F44336","#E91E63"],pullMenuRight:!0,wrapper:"btn-wrapper",tileSize:30,lineCount:5,optional:!0,tooltip:"top",icon:"caret-down",updateBtn:"auto"},o.LANG=n,t.fn.colorPicker=function(e){return this.each(function(){var i=t(this),n=i.data(name),a="object"==typeof e&&e;n||i.data(name,n=new o(this,a)),"string"==typeof e&&n[e]()})},t.fn.colorPicker.Constructor=o,t(function(){t('[data-provide="colorpicker"]').colorPicker()})}(jQuery),function(t,e){function i(t){return t===e&&(t=o+=1),a[t%a.length]}function n(e,i){var n=t(e);i=t.extend({percent:0,size:20,backColor:"#eee",color:"#00da88",borderColor:"#ccc",borderSize:1,rotate:-90,doughnut:8},n.data(),i);var o=i.percent,a=i.size;"string"==typeof o&&(o=Number.parseFloat(o,10)),"string"==typeof a&&(a=Number.parseFloat(a,10)),a=Math.floor(a);var s=a/2,r=3.14*s,l="http://www.w3.org/2000/svg",h=document.createElementNS(l,"svg"),c=document.createElementNS(l,"circle"),d=document.createElementNS(l,"circle"),u=document.createElementNS(l,"circle");d.setAttribute("r",s),d.setAttribute("cx",s),d.setAttribute("cy",s),d.setAttribute("fill",i.backColor),d.setAttribute("stroke",i.borderColor),d.setAttribute("stroke-width",i.borderSize),u.setAttribute("r",i.doughnut),u.setAttribute("cx",s),u.setAttribute("cy",s),u.setAttribute("fill",i.backColor),c.setAttribute("r",s/2),c.setAttribute("cx",s),c.setAttribute("cy",s),c.setAttribute("fill","transparent"),c.setAttribute("stroke-dasharray",(o*r/100).toFixed(1)+" "+r),c.setAttribute("stroke-width",s),c.setAttribute("stroke",i.color),c.setAttribute("transform","rotate(-90) translate(-"+a+")"),h.setAttribute("viewBox","0 0 "+a+" "+a),h.setAttribute("width",a),h.setAttribute("height",a),h.setAttribute("transform","rotate(180)"),h.appendChild(d),h.appendChild(c),h.appendChild(u),n[0].appendChild(h);var f={width:a,height:a};"inline"===n.css("display")&&(f.display="inline-block",f.verticalAlign="middle"),n.css(f)}var o=0,a=["#00a9fc","#ff5d5d","#fdc137","#00da88","#7ec5ff","#8666b8","#bd7b46","#ff9100","#ff3d00","#f57f17","#00e5ff","#00b0ff","#2979ff","#3d5afe","#651fff","#d500f9","#f50057","#ff1744"];jQuery.fn.tableChart=function(){t(this).each(function(){var e=t(this),n=e.data(),o=n.chart||"pie",a=t(n.target);if(a.length){var s=null;if("pie"===o){n=t.extend({scaleShowLabels:!0,scaleLabel:"<%=label%>: <%=value%>"},n);var r=[],l=e.find("tbody > tr").each(function(e){var n=t(this),o=i();n.attr("data-id",e).find(".chart-color-dot").css("background",o),r.push({label:n.find(".chart-label").text(),value:parseFloat(n.data("value")||n.find(".chart-value").text()),color:o,id:e})});r.length>1?n.scaleLabelPlacement="outside":1===r.length&&(n.scaleLabelPlacement="inside",r.push({label:"",value:r[0].value/2e3,color:"#fff",showLabel:!1})),s=a.pieChart(r,n),a.on("mousemove",function(t){var e=s.getSegmentsAtEvent(t);l.removeClass("active"),e.length&&l.filter('[data-id="'+e[0].id+'"]').addClass("active")})}else if("bar"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(i.data("value")||parseFloat(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.barChart(r,n)}else if("line"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(parseInt(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.lineChart(r,n)}null!==s&&e.data("zui.chart",s)}})},t(".table-chart").tableChart();var s=function(i,n){var o=t(i);if(!o.data("pieChart")){var a=o.is("canvas")?o:o.find("canvas"),s=t.extend({value:0,color:t.getThemeColor("primary")||"#006af1",backColor:t.getThemeColor("pale")||"#E9F2FB",doughnut:!0,doughnutSize:85,width:20,height:20,showTip:!1,name:"",tipTemplate:"<%=value%>%",animation:"auto",realValue:parseFloat(o.find(".progress-value").text())},n,o.data()),r=a.length;r||(a=t("").appendTo(o)),a.attr("width")!==e?s.width=a.width():a.attr("width",s.width),a.attr("height")!==e?s.height=a.height():a.attr("height",s.height),r||8!=t.zui.browser.ie||G_vmlCanvasManager.initElement(a[0]),"auto"===s.animation&&(s.animation=s.width>30),o.addClass("progress-pie-"+s.width).css({width:s.width,height:s.height}),s.value=Math.max(0,Math.min(100,s.value));var l=[{value:s.value,label:s.name,color:s.color,circleBeginEnd:!0},{value:100-s.value,label:"",color:s.backColor}],h=a[s.doughnut?"doughnutChart":"pieChart"](l,t.extend({segmentShowStroke:!1,animation:s.animation,showTooltips:s.showTip,tooltipTemplate:s.tipTemplate,percentageInnerCutout:s.doughnutSize,reverseDrawOrder:!0,animationEasing:"easeInOutQuart",onAnimationProgress:s.realValue?function(t){o.find(".progress-value").text(Math.floor(s.realValue*t))}:e,onAnimationComplete:s.realValue?function(t){o.find(".progress-value").text(s.realValue)}:e},s.chartOptions));o.data("pieChart",h)}};jQuery.fn.progressPie=function(e){t(this).each(function(){var i=t(this);if(!i.closest(".hidden").length){var n=i.closest(".tab-pane");n.length&&!n.hasClass("active")?t('[data-toggle="tab"][data-target="#'+n.attr("id")+'"]').one("shown.zui.tab",function(){s(i,e)}):s(this,e)}})},t.fn.pieIcon=function(e){t(this).each(function(){n(this,e)})},t(function(){t(".table-chart").tableChart();var e=t(".progress-pie:visible");e.length<100&&t(".progress-pie:visible").progressPie(),setTimeout(function(){t(".progress-pie:visible").progressPie()},e.length>100?1e3:50),t(".pie-icon:visible").pieIcon()})}(jQuery,void 0),function(t){jQuery.fn.sparkline=function(e){t(this).each(function(){var i=t(this),n=t.extend({values:i.attr("values"),width:i.width()-4,height:i.height()-4},i.data(),e),o=n.height,a=[],s=n.width,r=n.values.split(","),l=0;for(var h in r){var c=parseFloat(r[h]);NaN!=c&&(a.push(c),l=Math.max(c,l))}var d=(Math.min(l,30),Math.min(s,Math.max(10,a.length*s/30))),u=i.children("canvas");u.length||(i.append(''),u=i.children("canvas")),u.attr("width",d).attr("height",o);var f={labels:a,datasets:[{fillColor:t.getThemeColor("pale")||"rgba(0,0,255,0.05)",strokeColor:t.getThemeColor("primary")||"#0054EC",pointColor:t.getThemeColor("secondary")||"rgba(255,136,0,1)",pointStrokeColor:"#fff",data:a}]},p={animation:!0,scaleOverride:!0,scaleStepWidth:Math.ceil(l/10),scaleSteps:10,scaleStartValue:0,showScale:!1,showTooltips:!1,pointDot:!1,scaleShowGridLines:!1,datasetStrokeWidth:1},g=t(u).lineChart(f,p);i.data("sparklineChart",g)})},t(function(){t(".sparkline").sparkline()})}(jQuery),function(t){t.fn.fixedDate=function(){return t(this).each(function(){var e=t(this).attr("autocomplete","off");"0000-00-00"==e.val()&&e.focus(function(){"0000-00-00"==e.val()&&e.val("").datetimepicker("update")}).blur(function(){""==e.val()&&e.val("0000-00-00")})})},window.datepickerOptions={language:t("html").attr("lang"),weekStart:1,todayBtn:1,autoclose:1,todayHighlight:1,startView:2,forceParse:0,showMeridian:1,format:"yyyy-mm-dd hh:ii",startDate:"1970-1-1"},t.extend(t.fn.datetimepicker.defaults,window.datepickerOptions),t(function(){var e={minView:2,format:"yyyy-mm-dd"},i={startView:1,minView:0,maxView:1,format:"hh:ii"},n={minView:3,startView:3,format:"yyyy-mm"};t(".datepicker-wrapper").click(function(){t(this).find(".form-date, .form-datetime, .form-time, .form-month").datetimepicker("show").focus()}),t.fn.datepicker=function(i){return this.datetimepicker(t.extend({},e,i))},t.fn.timepicker=function(e){return this.datetimepicker(t.extend({},i,e))},t.fn.monthpicker=function(e){return this.datetimepicker(t.extend({},n,e))},t.fn.datepickerAll=function(){return this.find(".form-datetime").fixedDate().datetimepicker(),this.find(".form-date").fixedDate().datepicker(),this.find(".form-time").fixedDate().timepicker(),this.find(".form-month").fixedDate().monthpicker(),this},t("body").datepickerAll()})}(jQuery),function(t){var e=function(e,i){i=t.extend({idStart:0,idEnd:9,chosen:!0,datetimepicker:!0,colorPicker:!0,hotkeys:!0},i,e.data());var n=e.find(".template");!n.length&&i.template&&(n=t(i.template));var o=0,a=0,s=function(t){t.is("select.chosen")?t.next(".chosen-container").find("input").focus():t.focus()},r=function(t){var i=e.find("[data-ctrl-index]:focus,.chosen-container-active").first();if(i.length){if(i.is(".chosen-container-active")){if(i.hasClass("chosen-with-drop")&&("down"===t||"up"===t))return;i=i.prev("select.chosen")}var n=i.data("ctrlIndex"),r=i.closest("tr").data("row");"down"===t?r0?r-=1:r=a-1:"left"===t?n>0?n-=1:n=o-1:"right"===t&&(n").html(s);return r.attr("data-row",e).addClass(n.attr("class")).removeClass("template"),i.rowCreator&&i.rowCreator(r,e,i),o?o.after(r):h.append(r),c(r),r};t.extend(l,{createRow:u,template:d});for(var f=i.idStart;f<=i.idEnd;++f)u(f)}else c(e);e.on("click",".btn-copy",function(){var e=t(this),i=t(e.data("copyFrom")).val(),n=t(e.data("copyTo")).val(i).addClass("highlight");setTimeout(function(){n.removeClass("highlight")},2e3)}),i.hotkeys&&t(document).on("keydown",function(t){var e={"Ctrl+#37":"left","Ctrl+#39":"right","#38":"up","#40":"down","Ctrl+#38":"up","Ctrl+#40":"down"},i=[];t.ctrlKey&&i.push("Ctrl"),i.push("#"+t.keyCode);var n=e[i.join("+")];n&&(r(n),t.ctrlKey&&(t.stopPropagation(),t.preventDefault()))}),e.data("zui.batchActionForm",l),setTimeout(t.fixTableResponsive,0)};t.fn.batchActionForm=function(i){return this.each(function(){e(t(this),i)})}}(jQuery),function(t,e){"use strict";var i="zui.table",n={zh_cn:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},zh_tw:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},en:{selectedItems:"Seleted {0} items",attrTotal:"{0} total {1}"},de:{selectedItems:"{0} ausgewählt",attrTotal:"{0} insgesamt {1}"},fr:{selectedItems:"{0} sélectionnés",attrTotal:"{0} total {1}"}},o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),a=t.zui.browser.isIE(),s=a?200:100,r=function(e,o){var a=this;a.name=i;var s=a.$=t(e);o=a.options=t.extend({},r.DEFAULTS,this.$.data(),o),a.langName=o.lang||t.zui.clientLang(),a.lang=t.zui.getLangData(i,a.langName,n),a.id=s.attr("id"),a.id||(a.id=o.id||"table-"+t.zui.uuid(),a.noID=!0,s.attr("id",a.id),o.hot&&console.warn("ZUI: table hot replace id not defined, the element id attribute should be set.")),s.attr("data-ride")||s.attr("data-ride","table");var l=a.getTable();if(l.length){l.find("thead>tr>th").each(function(){var e=t(this);if(!e.attr("title")){var i=t.trim(e.find("a:first").text()||e.text()||"");i.length&&e.attr("title",i)}}),o.nested&&a.initNestedList(),o.checkable&&(s.on("click",".check-all",function(){a.checkAll(!t(this).hasClass("checked"))}),o.checkOnClickRow&&s.on("click","tbody>tr",function(e){t(e.target).closest('.btn,a,.not-check,.form-control,input[type="text"],.chosen-container').length||a.checkRow(t(this))}),s.on("click",'tbody input[type="checkbox"],tbody label[for]',function(e){e.stopPropagation();var i=t(this);i.is("label")&&(i=i.closest(".checkbox-primary").find('input[type="checkbox"]')),a.checkRow(i.closest("tr"),i.is(":checked"))}),o.selectable&&s.selectable(t.extend({},{selector:a.isDataTable?".fixed-left tbody>tr":"tbody>tr",selectClass:"",trigger:".c-id",clickBehavior:"multi",listenClick:!1,start:function(){this.syncSelectionsFromClass()},select:function(e){a.checkRow(e.target,!0),t.cookie("ajax_dragSelected")||(t.cookie("ajax_dragSelected","on",{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("dragSelected"))},unselect:function(t){a.checkRow(t.target,!1)},rangeStyle:{border:"1px solid #006af1",backgroundColor:"rgba(50,128,252,0.2)",borderRadius:"2px"}},t.isPlainObject(o.selectable)?o.selectable:null)));var h=a.$form=s.is("form")?s:s.find("form");h.length&&(o.ajaxForm?h.ajaxForm(t.isPlainObject(o.ajaxForm)?o.ajaxForm:null):h.on("click","[data-form-action]",function(){h.attr("action",t(this).data("formAction")).submit()})),(o.fixFooter||o.fixHeader)&&(a.pageFooterHeight=t("#footer").outerHeight(),a.updateFixUI(!0),t(window).on("scroll resize",function(){a.updateFixUI()}).on("sidebar.toggle",function(){setTimeout(function(){a.updateFixUI()},200)})),o.group&&(s.on("click",".group-toggle",function(){a.toggleRowGroup(t(this).closest("tr").data("id"))}),t(document).on("click",".group-collapse-all",function(){a.toggleGroups(!1)}).on("click",".group-expand-all",function(){a.toggleGroups(!0)})),a.defaultStatistic=s.find(".table-statistic").html(),a.updateStatistic(),a.initModals(),a.checkItems={},a.updateCheckUI()}};r.prototype.initNestedList=function(){var e=this,i=e.options,n=e.getTable().addClass("table-nested"),o=n.find("tbody"),a=o.children("tr[data-id]"),s={},r=[],l=i.preserveNested,h=i.enableEmptyNestedRow;n.toggleClass("disable-empty-nest-row",!h),a.each(function(e){var i=t(this),n=i.data();n.realOrder=e,n.$row=i,n.nestPath?(n.nestPathList=n.nestPath.split(","),n.nestPathList[0]||n.nestPathList.shift(),n.nestPathList[n.nestPathList.length-1]||n.nestPathList.pop(),n.nestPathLevel=n.nestPathList.length,i.attr("data-level",n.nestPathLevel)):(n.nestPath=","+n.id+",",n.nestPathList=[n.id],n.nestPathLevel=1),s[n.id]=n,delete n.children,r.push(n)});var c=[];t.each(r,function(t,n){return n.nestParent&&(n.parent=s[n.nestParent],n.parent)?(n.parent.children?n.parent.children.push(n):n.parent.children=[n],void(i.expandNestChild||e._initedNestedList||(n.$row.addClass("table-nest-hide"),n.parent.$row.addClass("table-nest-child-hide")))):(n.$row.removeClass("table-nest-hide"),void c.push(n))}),e.nestRowsMap=s,e.$nestBody=o;var d=function(e){for(var n=0;n').prependTo(s)),r.toggleClass("table-nest-toggle",!!a.children||h&&a.nested).css("marginLeft",(a.nestPathLevel-1)*i.nestLevelIndent),delete a.$row}};if(d(c),e.nestConfigStoreName="/"+window.config.currentModule+"/"+window.config.currentMethod+"/table."+e.id+".nestConfig",e.nestConfig=l?t.zui.store.get(e.nestConfigStoreName,{}):{},l)for(var u=0;u");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),h=l.find("#"+o).closest('[data-ride="table"],#'+a);if(h.length){var c=h.find(".table-statistic");c.length&&(i.defaultStatistic=c.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=h.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(f){console.error(f)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var p=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(p.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n; -o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
        ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width()}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange()},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
        ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
        ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
        '+(n.errorText||window.lang&&window.lang.timeout)+"
        "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
        ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash);if(a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
        {page}/{totalPage}
        ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
        ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n); -}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
        ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
        ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange()},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
        ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
        ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
        '+(n.errorText||window.lang&&window.lang.timeout)+"
        "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
        ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&(l?"$new"===l&&(l=t.tabSession.getNewTid()):l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
        {page}/{totalPage}
        ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
        ").addClass(n.attr("class")),l=e.clone(),r=l.find("th"); +e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
        ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),function(t,e){function i(){return s}function n(){return r}function o(e){var i=t.parseLink(e),n=i.tid||"";return n===r?e:(i.tid=r,t.createLink(i))}function a(){var a=t.parseLink();s=a.tid!==e?a.tid:"",r=t.zui.uuid(),r=r.substr(r.length-8),t.tabSession={getTid:i,getNewTid:n};var l=window.location.origin;t("a").each(function(){var e=t(this),i=e.attr("href");if(0===i.indexOf(l)){var n=t.parseLink(i),o=n.tid||"";s&&s!==o&&(n.tid=s,i=t.createLink(n),e.attr("href",i))}}),t(document).contextmenu({selector:"a",items:function(e){var i=t(e.event.target).closest("a");if(i.length){var n=i.attr("href");return[{label:"打开",url:n},{label:"在新标签页中打开",onClick:function(){console.log("convertUrlWithNewTid(href)",o(n)),window.open(o(n),"_blank")}}]}}})}if(config.tabSession){var s,r;a()}}(jQuery,void 0),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file From aa5a8bdd33fe857a1ebf53cd8630a4a73a36fdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Mon, 30 Aug 2021 10:56:52 +0800 Subject: [PATCH 002/304] * adjust for add tid for session. --- config/filter.php | 1 + framework/base/helper.class.php | 21 +++- framework/base/router.class.php | 122 ++++++++++++++++++++++++ lib/base/front/front.class.php | 2 + module/common/view/header.lite.html.php | 1 - module/user/control.php | 8 +- 6 files changed, 147 insertions(+), 8 deletions(-) diff --git a/config/filter.php b/config/filter.php index 46681c79d7..919313f523 100644 --- a/config/filter.php +++ b/config/filter.php @@ -20,6 +20,7 @@ $filter->default->paramName = 'reg::paramName'; $filter->default->paramValue = 'reg::paramValue'; $filter->default->get['onlybody'] = 'equal::yes'; +$filter->default->get['tid'] = 'reg::word'; $filter->default->get['HTTP_X_REQUESTED_WITH'] = 'equal::XMLHttpRequest'; $filter->default->cookie['lang'] = 'reg::lang'; diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php index 1f39f5ec90..33141d1ab7 100644 --- a/framework/base/helper.class.php +++ b/framework/base/helper.class.php @@ -160,9 +160,12 @@ class baseHelper public static function processOnlyBodyParam($link, $onlyBody = false) { global $config; - if(!$onlyBody and !self::inOnlyBodyMode()) return $link; - $onlybodyString = strpos($link, '?') === false ? "?onlybody=yes" : "&onlybody=yes"; - return $link . $onlybodyString; + + $sign = strpos($link, '?') === false ? "?" : "&"; + $appendString = ''; + if($onlyBody or self::inOnlyBodyMode()) $appendString = $sign . "onlybody=yes"; + if(self::isWithTID()) $appendString .= empty($appendString) ? "{$sign}tid={$_GET['tid']}" : "&tid={$_GET['tid']}"; + return $link . $appendString; } /** @@ -177,6 +180,18 @@ class baseHelper return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes'); } + /** + * Is with tid. + * + * @static + * @access public + * @return bool + */ + public static function isWithTID() + { + return (!empty($config->tabSession) and isset($_GET['tid'])); + } + /** * 使用helper::import()来引入文件,不要直接使用include或者require. * Using helper::import() to import a file, instead of include or require. diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 9049bb980b..5b5ff3c496 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -855,6 +855,16 @@ class baseRouter { if(defined('SESSION_STARTED')) return; + $ztSessionHandler = new ztSessionHandler(zget($_GET, 'tid', '')); + session_set_save_handler( + array($ztSessionHandler, "open"), + array($ztSessionHandler, "close"), + array($ztSessionHandler, "read"), + array($ztSessionHandler, "write"), + array($ztSessionHandler, "destroy"), + array($ztSessionHandler, "gc") + ); + /* If request header has token, use it as session for authentication. */ if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); @@ -2616,3 +2626,115 @@ class super if($this->scope == 'global') a($GLOBALS); } } + +/** + * ZenTao session handler. + * + * @package framework + */ +class ztSessionHandler +{ + public $sessSavePath; + public $tagID; + + /** + * Construct. + * + * @param string $tagID + * @access public + * @return void + */ + public function __construct($tagID = '') + { + $this->tagID = $tagID; + } + + /** + * Open + * + * @param string $savePath + * @param string $sessionName + * @access public + * @return bool + */ + public function open($savePath, $sessionName) + { + $this->sessSavePath = $savePath; + return true; + } + + /** + * Close + * + * @access public + * @return bool + */ + public function close() + { + return true; + } + + /** + * Read + * + * @param string $id + * @access public + * @return bool + */ + public function read($id) + { + $sessFile = "$this->sessSavePath/sess_$id" . $this->tagID; + if(!file_exists($sessFile)) + { + ($this->tagID and file_exists("$this->sessSavePath/sess_$id")) ? copy("$this->sessSavePath/sess_$id", $sessFile) : touch($sessFile); + } + return (string) file_get_contents($sessFile); + } + + /** + * Write + * + * @param string $id + * @param string $sessData + * @access public + * @return bool + */ + public function write($id, $sessData) + { + $sessFile = "$this->sessSavePath/sess_$id" . $this->tagID; + if(file_put_contents($sessFile, $sessData)) return true; + return false; + } + + /** + * Destroy + * + * @param string $id + * @access public + * @return bool + */ + public function destroy($id) + { + $sessFile = "$this->sessSavePath/sess_$id" . $this->tagID; + @unlink($sessFile); + touch($sessFile); + return true; + } + + /** + * GC + * + * @param int $maxlifeTime + * @access public + * @return bool + */ + public function gc($maxlifeTime) + { + $time = time(); + foreach(glob("$this->sessSavePath/sess_*") as $fileName) + { + if(filemtime($fileName) + $maxlifeTime < $time) @unlink($fileName); + } + return true; + } +} diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index c45f30725d..a25afa7015 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -1166,7 +1166,9 @@ EOT; $jsConfig->runMode = $runMode; $jsConfig->timeout = isset($config->timeout) ? $config->timeout : ''; $jsConfig->pingInterval = isset($config->pingInterval) ? $config->pingInterval : ''; + $jsConfig->onlybody = zget($_GET, 'onlybody', 'no'); $jsConfig->tabSession = $config->tabSession; + if($config->tabSession and helper::inTabIDMode()) $jsConfig->tid = zget($_GET, 'tid', ''); $jsLang = new stdclass(); $jsLang->submitting = isset($lang->loading) ? $lang->loading : ''; diff --git a/module/common/view/header.lite.html.php b/module/common/view/header.lite.html.php index 120292dc77..6020e669c3 100755 --- a/module/common/view/header.lite.html.php +++ b/module/common/view/header.lite.html.php @@ -19,7 +19,6 @@ $onlybody = zget($_GET, 'onlybody', 'no'); zentaoPMS); js::exportConfigVars(); - echo ''; if($config->debug) { $timestamp = time(); diff --git a/module/user/control.php b/module/user/control.php index e16397c027..848d057ac1 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -777,7 +777,7 @@ class user extends control $canModifyDIR = false; $floderPath = $this->app->tmpRoot; } - elseif(!is_dir($this->app->dataRoot) or substr(base_convert(@fileperms($this->app->dataRoot),10,8),-4) != '0777') + elseif(!is_dir($this->app->dataRoot) or substr(base_convert(@fileperms($this->app->dataRoot), 10, 8), -4) != '0777') { $canModifyDIR = false; $floderPath = $this->app->dataRoot; @@ -827,7 +827,7 @@ class user extends control } else { - $response['locate'] = $this->config->webRoot; + $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); return $this->send($response); } } @@ -902,7 +902,7 @@ class user extends control } else { - $response['locate'] = $this->config->webRoot; + $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); return $this->send($response); } } @@ -914,7 +914,7 @@ class user extends control die(helper::removeUTF8Bom(json_encode(array('status' => 'success') + $data))); } - $response['locate'] = $this->config->webRoot; + $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); $response['result'] = 'success'; return $this->send($response); } From 036b0520e0f6054d57de22bc724f2ea30a6715d8 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 30 Aug 2021 11:02:17 +0800 Subject: [PATCH 003/304] * fix createLink not use tid from browser url. --- www/js/zui/min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 727e4bb019..7882c6adf0 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -76,4 +76,4 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= */ function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,h=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t){"use strict";function e(e,i){if(e===!1)return e;if(!e)return i;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var n;return Array.isArray(e)&&(n={},t.each(e,function(e,i){t.isPlainObject(i)?n[i.action]=i:n[i]=!0}),e=n),t.isPlainObject(e)&&(n={},t.each(e,function(e,i){i?n[e]=t.extend({type:e},s[e],t.isPlainObject(i)?i:null):n[e]=!1}),e=n),i?t.extend(!0,{},i,e):e}function i(e,i,n){return i=i||e.type,t(n||e.template).addClass("tree-action").attr(t.extend({"data-type":i,title:e.title||""},e.attr)).data("action",e)}var n="zui.tree",o=0,a=function(e,i){this.name=n,this.$=t(e),this.getOptions(i),this._init()},s={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};a.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},a.prototype.add=function(e,i,n,o,a){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
          "),r.append(s),this._initList(s,r))):s=r,s){var h=this;Array.isArray(i)||(i=[i]),t.each(i,function(e,i){var n=t("
        • ").data(i).appendTo(s);void 0!==i.id&&n.attr("data-id",i.id);var o=l.itemWrapper?t(l.itemWrapper===!0?'
        • ').append(i(h.add,"add",h.add.templateInList)).appendTo(n)}h.sort&&n.sortable(t.extend({dragCssClass:"tree-drag-holder",trigger:".sort-handler",selector:"li:not(.tree-action-item)",finish:function(t){r.callEvent("action",{action:h.sort,$list:n,target:t.target,item:s})}},h.sort.options,t.isPlainObject(this.options.sortable)?this.options.sortable:null))}o&&(o.hasClass("open")||s&&s.open)&&o.addClass("open in")},a.prototype._initItem=function(n,o,a,s){if(void 0===o){var r=n.prev("li");o=r.length?r.data("idx")+1:1}if(a=a||n.closest("ul"),n.attr("data-idx",o).removeClass("tree-single-item"),!n.data("id")){var l=o;a.hasClass("tree")||(l=a.parent("li").data("id")+"-"+l),n.attr("data-id",l)}n.hasClass("active")&&a.parent("li").addClass("has-active-item"),s=s||n.data();var h=e(s.actions,this.actions);if(h){var c=n.find(".tree-actions");c.length||(c=t('
          ').appendTo(this.options.itemWrapper?n.find(".tree-item-wrapper"):n),t.each(h,function(t,e){e&&c.append(i(e,t))}))}var d=n.children("ul");d.length&&this._initList(d,n,o,s)},a.prototype._init=function(){var i=this.options,a=this;this.actions=e(i.actions),this.$.addClass("tree"),i.animate&&this.$.addClass("tree-animate"),this._initList(this.$);var s=i.initialState,r=t.zui&&t.zui.store&&t.zui.store.enable;r&&(this.selector=n+"::"+(i.name||"")+"#"+(this.$.attr("id")||o++),this.store=t.zui.store[i.name?"get":"pageGet"](this.selector,{})),"preserve"===s&&(r?this.isPreserve=!0:this.options.initialState=s="normal"),this.reload(i.data),r&&(this.isPreserve=!0),"expand"===s?this.expand():"collapse"===s?this.collapse():"active"===s&&this.expandSelect(".active"),this.$.on("click",'.list-toggle,a[href="#"],.tree-toggle',function(e){var i=t(this),n=i.parent("li");a.callEvent("hit",{target:n,item:n.data()}),a.toggle(n),i.is("a")&&e.preventDefault()}).on("click",".tree-action",function(){var e=t(this),i=e.data();if(i.action&&(i=i.action),"sort"!==i.type){var n=e.closest("li:not(.tree-action-item)");a.callEvent("action",{action:i,target:this,$item:n,item:n.data()})}})},a.prototype.preserve=function(e,i,n){if(this.isPreserve)if(e)i=i||e.data("id"),n=void 0===n&&e.hasClass("open"),n?this.store[i]=n:delete this.store[i],this.store.time=(new Date).getTime(),t.zui.store[this.options.name?"set":"pageSet"](this.selector,this.store);else{var o=this;this.store={},this.$.find("li").each(function(){o.preserve(t(this))})}},a.prototype.expandSelect=function(t){this.show(t,!0)},a.prototype.expand=function(t,e,i){t?(t.addClass("open"),!e&&this.options.animate?setTimeout(function(){t.addClass("in")},10):t.addClass("in")):t=this.$.find("li.has-list").addClass("open in"),i||this.preserve(t),this.callEvent("expand",t,this)},a.prototype.show=function(e,i,n){var o=this;e instanceof t||(e=o.$.find("li").filter(e)),e.each(function(){var e=t(this);if(o.expand(e,i,n),e)for(var a=e.parent("ul");a&&a.length&&!a.hasClass("tree");){var s=a.parent("li");s.length?(o.expand(s,i,n),a=s.parent("ul")):a=!1}})},a.prototype.collapse=function(t,e,i){t?!e&&this.options.animate?(t.removeClass("in"),setTimeout(function(){t.removeClass("open")},300)):t.removeClass("open in"):t=this.$.find("li.has-list").removeClass("open in"),i||this.preserve(t),this.callEvent("collapse",t,this)},a.prototype.toggle=function(t){var e=t&&t.hasClass("open")||t===!1||void 0===t&&this.$.find("li.has-list.open").length;this[e?"collapse":"expand"](t)},a.prototype.getOptions=function(e){this.options=t.extend({},a.DEFAULTS,this.$.data(),e),null===this.options.animate&&this.$.hasClass("tree-animate")&&(this.options.animate=!0)},a.prototype.toData=function(e,i){"function"==typeof e&&(i=e,e=null),e=e||this.$;var n=this;return e.children("li:not(.tree-action-item)").map(function(){var e=t(this),o=e.data();delete o["zui.droppable"];var a=e.children("ul");return a.length&&(o.children=n.toData(a)),"function"==typeof i?i(o,e):o}).get()},a.prototype.callEvent=function(e,i){var n;return"function"==typeof this.options[e]&&(n=this.options[e](i,this)),this.$.trigger(t.Event(e+"."+this.name,i)),n},t.fn.tree=function(e,i){return this.each(function(){var o=t(this),s=o.data(n),r="object"==typeof e&&e;s||o.data(n,s=new a(this,r)),"string"==typeof e&&s[e](i)})},t.fn.tree.Constructor=a,t(function(){t('[data-ride="tree"]').tree()})}(jQuery),function(t){"use strict";var e="zui.colorPicker",i='
          ',n={zh_cn:{errorTip:"不是有效的颜色值"},zh_tw:{errorTip:"不是有效的顏色值"},en:{errorTip:"Not a valid color value"}},o=function(i,n){this.name=e,this.$=t(i),this.getOptions(n),this.init()};o.prototype.init=function(){var e=this,n=e.options,o=e.$,a=o.parent(),s=!1;a.hasClass("colorpicker")?e.$picker=a:(e.$picker=t(n.template||i),s=!0),e.$picker.addClass(n.wrapper).find(".cp-title").toggle(void 0!==n.title).text(n.title),e.$menu=e.$picker.find(".dropdown-menu").toggleClass("pull-right",n.pullMenuRight),e.$btn=e.$picker.find(".btn.dropdown-toggle"),e.$btn.find(".ic").addClass("icon-"+n.icon),n.btnTip&&e.$picker.attr("data-toggle","tooltip").tooltip({title:n.btnTip,placement:n.tooltip,container:"body"}),o.attr("data-provide",null),s&&o.after(e.$picker),e.colors={},t.each(n.colors,function(i,n){if(t.zui.Color.isColor(n)){var o=new t.zui.Color(n);e.colors[o.toCssStr()]=o}}),e.updateColors(),e.$picker.on("click",".cp-tile",function(){e.setValue(t(this).data("color"))});var r=function(){var i=o.val(),a=t.zui.Color.isColor(i);o.parent().toggleClass("has-error",!(a||n.optional&&""===i)),a?e.setValue(i,!0):n.optional&&""===i?o.tooltip("hide"):o.is(":focus")||o.tooltip("show",n.errorTip)};o.is("input:not([type=hidden])")?(n.tooltip&&o.attr("data-toggle","tooltip").tooltip({trigger:"manual",placement:n.tooltip,tipClass:"tooltip-danger",container:"body"}),o.on("keyup paste input change",r)):o.appendTo(e.$picker),r()},o.prototype.addColor=function(e){e instanceof t.zui.Color||(e=new t.zui.Color(e));var i=e.toCssStr(),n=this.options;this.colors[i]||(this.colors[i]=e);var o=t('
          ',{titile:e}).data("color",e).css({color:e.contrast().toCssStr(),background:i,"border-color":e.luma()>.43?"#ccc":"transparent"}).attr("data-color",i);this.$menu.append(t("
        • ").css({width:n.tileSize,height:n.tileSize}).append(o)),n.optional&&this.$menu.find(".cp-tile.empty").parent().detach().appendTo(this.$menu)},o.prototype.updateColors=function(e){var i=this.$menu,n=this.options,e=e||this.colors,o=this,a=0;if(i.children("li:not(.heading)").remove(),t.each(e,function(t,e){o.addColor(e),a++}),n.optional){var s=t('
        • ').css({width:n.tileSize,height:n.tileSize});this.$menu.append(s),a++}i.css("width",Math.min(a,n.lineCount)*n.tileSize+6)},o.prototype.setValue=function(e,i){var n=this,o=n.options,a=n.$btn,s="";n.$menu.find(".cp-tile.active").removeClass("active");var r=o.updateBtn;if("auto"===r){var l=a.find(".color-bar");r=!l.length||function(t){l.css("background",t||"")}}if(e){var h=new t.zui.Color(e);s=h.toCssStr().toLowerCase(),r&&("function"==typeof r?r(s,a,n):a.css({background:s,color:h.contrast().toCssStr(),borderColor:h.luma()>.43?"#ccc":s})),n.colors[s]||n.addColor(h),i||n.$.val().toLowerCase()===s||n.$.val(s).trigger("change"),n.$menu.find('.cp-tile[data-color="'+s+'"]').addClass("active"),n.$.tooltip("hide"),n.$.trigger("colorchange",h)}else r&&("function"==typeof r?r(null,a,n):a.attr("style",null)),i||""===n.$.val()||n.$.val(s).trigger("change"),o.optional&&n.$.tooltip("hide"),n.$menu.find(".cp-tile.empty").addClass("active"),n.$.trigger("colorchange",null);o.updateBorder&&t(o.updateBorder).css("border-color",s),o.updateBackground&&t(o.updateBackground).css("background-color",s),o.updateColor&&t(o.updateColor).css("color",s),o.updateText&&t(o.updateText).text(s)},o.prototype.getOptions=function(i){var a=t.extend({},o.DEFAULTS,this.$.data(),i);"string"==typeof a.colors&&(a.colors=a.colors.split(","));var s=a.lang||t.zui.clientLang(),r=this.lang=t.zui.getLangData?t.zui.getLangData(e,s,n):n[s]||n.en;a.errorTip||(a.errorTip=r.errorTip),t.fn.tooltip||(a.btnTip=!1),this.options=a},o.DEFAULTS={colors:["#00BCD4","#388E3C","#3280fc","#3F51B5","#9C27B0","#795548","#F57C00","#F44336","#E91E63"],pullMenuRight:!0,wrapper:"btn-wrapper",tileSize:30,lineCount:5,optional:!0,tooltip:"top",icon:"caret-down",updateBtn:"auto"},o.LANG=n,t.fn.colorPicker=function(e){return this.each(function(){var i=t(this),n=i.data(name),a="object"==typeof e&&e;n||i.data(name,n=new o(this,a)),"string"==typeof e&&n[e]()})},t.fn.colorPicker.Constructor=o,t(function(){t('[data-provide="colorpicker"]').colorPicker()})}(jQuery),function(t,e){function i(t){return t===e&&(t=o+=1),a[t%a.length]}function n(e,i){var n=t(e);i=t.extend({percent:0,size:20,backColor:"#eee",color:"#00da88",borderColor:"#ccc",borderSize:1,rotate:-90,doughnut:8},n.data(),i);var o=i.percent,a=i.size;"string"==typeof o&&(o=Number.parseFloat(o,10)),"string"==typeof a&&(a=Number.parseFloat(a,10)),a=Math.floor(a);var s=a/2,r=3.14*s,l="http://www.w3.org/2000/svg",h=document.createElementNS(l,"svg"),c=document.createElementNS(l,"circle"),d=document.createElementNS(l,"circle"),u=document.createElementNS(l,"circle");d.setAttribute("r",s),d.setAttribute("cx",s),d.setAttribute("cy",s),d.setAttribute("fill",i.backColor),d.setAttribute("stroke",i.borderColor),d.setAttribute("stroke-width",i.borderSize),u.setAttribute("r",i.doughnut),u.setAttribute("cx",s),u.setAttribute("cy",s),u.setAttribute("fill",i.backColor),c.setAttribute("r",s/2),c.setAttribute("cx",s),c.setAttribute("cy",s),c.setAttribute("fill","transparent"),c.setAttribute("stroke-dasharray",(o*r/100).toFixed(1)+" "+r),c.setAttribute("stroke-width",s),c.setAttribute("stroke",i.color),c.setAttribute("transform","rotate(-90) translate(-"+a+")"),h.setAttribute("viewBox","0 0 "+a+" "+a),h.setAttribute("width",a),h.setAttribute("height",a),h.setAttribute("transform","rotate(180)"),h.appendChild(d),h.appendChild(c),h.appendChild(u),n[0].appendChild(h);var f={width:a,height:a};"inline"===n.css("display")&&(f.display="inline-block",f.verticalAlign="middle"),n.css(f)}var o=0,a=["#00a9fc","#ff5d5d","#fdc137","#00da88","#7ec5ff","#8666b8","#bd7b46","#ff9100","#ff3d00","#f57f17","#00e5ff","#00b0ff","#2979ff","#3d5afe","#651fff","#d500f9","#f50057","#ff1744"];jQuery.fn.tableChart=function(){t(this).each(function(){var e=t(this),n=e.data(),o=n.chart||"pie",a=t(n.target);if(a.length){var s=null;if("pie"===o){n=t.extend({scaleShowLabels:!0,scaleLabel:"<%=label%>: <%=value%>"},n);var r=[],l=e.find("tbody > tr").each(function(e){var n=t(this),o=i();n.attr("data-id",e).find(".chart-color-dot").css("background",o),r.push({label:n.find(".chart-label").text(),value:parseFloat(n.data("value")||n.find(".chart-value").text()),color:o,id:e})});r.length>1?n.scaleLabelPlacement="outside":1===r.length&&(n.scaleLabelPlacement="inside",r.push({label:"",value:r[0].value/2e3,color:"#fff",showLabel:!1})),s=a.pieChart(r,n),a.on("mousemove",function(t){var e=s.getSegmentsAtEvent(t);l.removeClass("active"),e.length&&l.filter('[data-id="'+e[0].id+'"]').addClass("active")})}else if("bar"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(i.data("value")||parseFloat(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.barChart(r,n)}else if("line"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(parseInt(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.lineChart(r,n)}null!==s&&e.data("zui.chart",s)}})},t(".table-chart").tableChart();var s=function(i,n){var o=t(i);if(!o.data("pieChart")){var a=o.is("canvas")?o:o.find("canvas"),s=t.extend({value:0,color:t.getThemeColor("primary")||"#006af1",backColor:t.getThemeColor("pale")||"#E9F2FB",doughnut:!0,doughnutSize:85,width:20,height:20,showTip:!1,name:"",tipTemplate:"<%=value%>%",animation:"auto",realValue:parseFloat(o.find(".progress-value").text())},n,o.data()),r=a.length;r||(a=t("").appendTo(o)),a.attr("width")!==e?s.width=a.width():a.attr("width",s.width),a.attr("height")!==e?s.height=a.height():a.attr("height",s.height),r||8!=t.zui.browser.ie||G_vmlCanvasManager.initElement(a[0]),"auto"===s.animation&&(s.animation=s.width>30),o.addClass("progress-pie-"+s.width).css({width:s.width,height:s.height}),s.value=Math.max(0,Math.min(100,s.value));var l=[{value:s.value,label:s.name,color:s.color,circleBeginEnd:!0},{value:100-s.value,label:"",color:s.backColor}],h=a[s.doughnut?"doughnutChart":"pieChart"](l,t.extend({segmentShowStroke:!1,animation:s.animation,showTooltips:s.showTip,tooltipTemplate:s.tipTemplate,percentageInnerCutout:s.doughnutSize,reverseDrawOrder:!0,animationEasing:"easeInOutQuart",onAnimationProgress:s.realValue?function(t){o.find(".progress-value").text(Math.floor(s.realValue*t))}:e,onAnimationComplete:s.realValue?function(t){o.find(".progress-value").text(s.realValue)}:e},s.chartOptions));o.data("pieChart",h)}};jQuery.fn.progressPie=function(e){t(this).each(function(){var i=t(this);if(!i.closest(".hidden").length){var n=i.closest(".tab-pane");n.length&&!n.hasClass("active")?t('[data-toggle="tab"][data-target="#'+n.attr("id")+'"]').one("shown.zui.tab",function(){s(i,e)}):s(this,e)}})},t.fn.pieIcon=function(e){t(this).each(function(){n(this,e)})},t(function(){t(".table-chart").tableChart();var e=t(".progress-pie:visible");e.length<100&&t(".progress-pie:visible").progressPie(),setTimeout(function(){t(".progress-pie:visible").progressPie()},e.length>100?1e3:50),t(".pie-icon:visible").pieIcon()})}(jQuery,void 0),function(t){jQuery.fn.sparkline=function(e){t(this).each(function(){var i=t(this),n=t.extend({values:i.attr("values"),width:i.width()-4,height:i.height()-4},i.data(),e),o=n.height,a=[],s=n.width,r=n.values.split(","),l=0;for(var h in r){var c=parseFloat(r[h]);NaN!=c&&(a.push(c),l=Math.max(c,l))}var d=(Math.min(l,30),Math.min(s,Math.max(10,a.length*s/30))),u=i.children("canvas");u.length||(i.append(''),u=i.children("canvas")),u.attr("width",d).attr("height",o);var f={labels:a,datasets:[{fillColor:t.getThemeColor("pale")||"rgba(0,0,255,0.05)",strokeColor:t.getThemeColor("primary")||"#0054EC",pointColor:t.getThemeColor("secondary")||"rgba(255,136,0,1)",pointStrokeColor:"#fff",data:a}]},p={animation:!0,scaleOverride:!0,scaleStepWidth:Math.ceil(l/10),scaleSteps:10,scaleStartValue:0,showScale:!1,showTooltips:!1,pointDot:!1,scaleShowGridLines:!1,datasetStrokeWidth:1},g=t(u).lineChart(f,p);i.data("sparklineChart",g)})},t(function(){t(".sparkline").sparkline()})}(jQuery),function(t){t.fn.fixedDate=function(){return t(this).each(function(){var e=t(this).attr("autocomplete","off");"0000-00-00"==e.val()&&e.focus(function(){"0000-00-00"==e.val()&&e.val("").datetimepicker("update")}).blur(function(){""==e.val()&&e.val("0000-00-00")})})},window.datepickerOptions={language:t("html").attr("lang"),weekStart:1,todayBtn:1,autoclose:1,todayHighlight:1,startView:2,forceParse:0,showMeridian:1,format:"yyyy-mm-dd hh:ii",startDate:"1970-1-1"},t.extend(t.fn.datetimepicker.defaults,window.datepickerOptions),t(function(){var e={minView:2,format:"yyyy-mm-dd"},i={startView:1,minView:0,maxView:1,format:"hh:ii"},n={minView:3,startView:3,format:"yyyy-mm"};t(".datepicker-wrapper").click(function(){t(this).find(".form-date, .form-datetime, .form-time, .form-month").datetimepicker("show").focus()}),t.fn.datepicker=function(i){return this.datetimepicker(t.extend({},e,i))},t.fn.timepicker=function(e){return this.datetimepicker(t.extend({},i,e))},t.fn.monthpicker=function(e){return this.datetimepicker(t.extend({},n,e))},t.fn.datepickerAll=function(){return this.find(".form-datetime").fixedDate().datetimepicker(),this.find(".form-date").fixedDate().datepicker(),this.find(".form-time").fixedDate().timepicker(),this.find(".form-month").fixedDate().monthpicker(),this},t("body").datepickerAll()})}(jQuery),function(t){var e=function(e,i){i=t.extend({idStart:0,idEnd:9,chosen:!0,datetimepicker:!0,colorPicker:!0,hotkeys:!0},i,e.data());var n=e.find(".template");!n.length&&i.template&&(n=t(i.template));var o=0,a=0,s=function(t){t.is("select.chosen")?t.next(".chosen-container").find("input").focus():t.focus()},r=function(t){var i=e.find("[data-ctrl-index]:focus,.chosen-container-active").first();if(i.length){if(i.is(".chosen-container-active")){if(i.hasClass("chosen-with-drop")&&("down"===t||"up"===t))return;i=i.prev("select.chosen")}var n=i.data("ctrlIndex"),r=i.closest("tr").data("row");"down"===t?r0?r-=1:r=a-1:"left"===t?n>0?n-=1:n=o-1:"right"===t&&(n").html(s);return r.attr("data-row",e).addClass(n.attr("class")).removeClass("template"),i.rowCreator&&i.rowCreator(r,e,i),o?o.after(r):h.append(r),c(r),r};t.extend(l,{createRow:u,template:d});for(var f=i.idStart;f<=i.idEnd;++f)u(f)}else c(e);e.on("click",".btn-copy",function(){var e=t(this),i=t(e.data("copyFrom")).val(),n=t(e.data("copyTo")).val(i).addClass("highlight");setTimeout(function(){n.removeClass("highlight")},2e3)}),i.hotkeys&&t(document).on("keydown",function(t){var e={"Ctrl+#37":"left","Ctrl+#39":"right","#38":"up","#40":"down","Ctrl+#38":"up","Ctrl+#40":"down"},i=[];t.ctrlKey&&i.push("Ctrl"),i.push("#"+t.keyCode);var n=e[i.join("+")];n&&(r(n),t.ctrlKey&&(t.stopPropagation(),t.preventDefault()))}),e.data("zui.batchActionForm",l),setTimeout(t.fixTableResponsive,0)};t.fn.batchActionForm=function(i){return this.each(function(){e(t(this),i)})}}(jQuery),function(t,e){"use strict";var i="zui.table",n={zh_cn:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},zh_tw:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},en:{selectedItems:"Seleted {0} items",attrTotal:"{0} total {1}"},de:{selectedItems:"{0} ausgewählt",attrTotal:"{0} insgesamt {1}"},fr:{selectedItems:"{0} sélectionnés",attrTotal:"{0} total {1}"}},o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),a=t.zui.browser.isIE(),s=a?200:100,r=function(e,o){var a=this;a.name=i;var s=a.$=t(e);o=a.options=t.extend({},r.DEFAULTS,this.$.data(),o),a.langName=o.lang||t.zui.clientLang(),a.lang=t.zui.getLangData(i,a.langName,n),a.id=s.attr("id"),a.id||(a.id=o.id||"table-"+t.zui.uuid(),a.noID=!0,s.attr("id",a.id),o.hot&&console.warn("ZUI: table hot replace id not defined, the element id attribute should be set.")),s.attr("data-ride")||s.attr("data-ride","table");var l=a.getTable();if(l.length){l.find("thead>tr>th").each(function(){var e=t(this);if(!e.attr("title")){var i=t.trim(e.find("a:first").text()||e.text()||"");i.length&&e.attr("title",i)}}),o.nested&&a.initNestedList(),o.checkable&&(s.on("click",".check-all",function(){a.checkAll(!t(this).hasClass("checked"))}),o.checkOnClickRow&&s.on("click","tbody>tr",function(e){t(e.target).closest('.btn,a,.not-check,.form-control,input[type="text"],.chosen-container').length||a.checkRow(t(this))}),s.on("click",'tbody input[type="checkbox"],tbody label[for]',function(e){e.stopPropagation();var i=t(this);i.is("label")&&(i=i.closest(".checkbox-primary").find('input[type="checkbox"]')),a.checkRow(i.closest("tr"),i.is(":checked"))}),o.selectable&&s.selectable(t.extend({},{selector:a.isDataTable?".fixed-left tbody>tr":"tbody>tr",selectClass:"",trigger:".c-id",clickBehavior:"multi",listenClick:!1,start:function(){this.syncSelectionsFromClass()},select:function(e){a.checkRow(e.target,!0),t.cookie("ajax_dragSelected")||(t.cookie("ajax_dragSelected","on",{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("dragSelected"))},unselect:function(t){a.checkRow(t.target,!1)},rangeStyle:{border:"1px solid #006af1",backgroundColor:"rgba(50,128,252,0.2)",borderRadius:"2px"}},t.isPlainObject(o.selectable)?o.selectable:null)));var h=a.$form=s.is("form")?s:s.find("form");h.length&&(o.ajaxForm?h.ajaxForm(t.isPlainObject(o.ajaxForm)?o.ajaxForm:null):h.on("click","[data-form-action]",function(){h.attr("action",t(this).data("formAction")).submit()})),(o.fixFooter||o.fixHeader)&&(a.pageFooterHeight=t("#footer").outerHeight(),a.updateFixUI(!0),t(window).on("scroll resize",function(){a.updateFixUI()}).on("sidebar.toggle",function(){setTimeout(function(){a.updateFixUI()},200)})),o.group&&(s.on("click",".group-toggle",function(){a.toggleRowGroup(t(this).closest("tr").data("id"))}),t(document).on("click",".group-collapse-all",function(){a.toggleGroups(!1)}).on("click",".group-expand-all",function(){a.toggleGroups(!0)})),a.defaultStatistic=s.find(".table-statistic").html(),a.updateStatistic(),a.initModals(),a.checkItems={},a.updateCheckUI()}};r.prototype.initNestedList=function(){var e=this,i=e.options,n=e.getTable().addClass("table-nested"),o=n.find("tbody"),a=o.children("tr[data-id]"),s={},r=[],l=i.preserveNested,h=i.enableEmptyNestedRow;n.toggleClass("disable-empty-nest-row",!h),a.each(function(e){var i=t(this),n=i.data();n.realOrder=e,n.$row=i,n.nestPath?(n.nestPathList=n.nestPath.split(","),n.nestPathList[0]||n.nestPathList.shift(),n.nestPathList[n.nestPathList.length-1]||n.nestPathList.pop(),n.nestPathLevel=n.nestPathList.length,i.attr("data-level",n.nestPathLevel)):(n.nestPath=","+n.id+",",n.nestPathList=[n.id],n.nestPathLevel=1),s[n.id]=n,delete n.children,r.push(n)});var c=[];t.each(r,function(t,n){return n.nestParent&&(n.parent=s[n.nestParent],n.parent)?(n.parent.children?n.parent.children.push(n):n.parent.children=[n],void(i.expandNestChild||e._initedNestedList||(n.$row.addClass("table-nest-hide"),n.parent.$row.addClass("table-nest-child-hide")))):(n.$row.removeClass("table-nest-hide"),void c.push(n))}),e.nestRowsMap=s,e.$nestBody=o;var d=function(e){for(var n=0;n').prependTo(s)),r.toggleClass("table-nest-toggle",!!a.children||h&&a.nested).css("marginLeft",(a.nestPathLevel-1)*i.nestLevelIndent),delete a.$row}};if(d(c),e.nestConfigStoreName="/"+window.config.currentModule+"/"+window.config.currentMethod+"/table."+e.id+".nestConfig",e.nestConfig=l?t.zui.store.get(e.nestConfigStoreName,{}):{},l)for(var u=0;u");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),h=l.find("#"+o).closest('[data-ride="table"],#'+a);if(h.length){var c=h.find(".table-statistic");c.length&&(i.defaultStatistic=c.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=h.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(f){console.error(f)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var p=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(p.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n; o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
          ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange()},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
          ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
          ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
          '+(n.errorText||window.lang&&window.lang.timeout)+"
          "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
          ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&(l?"$new"===l&&(l=t.tabSession.getNewTid()):l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
          {page}/{totalPage}
          ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
          ").addClass(n.attr("class")),l=e.clone(),r=l.find("th"); -e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),function(t,e){function i(){return s}function n(){return r}function o(e){var i=t.parseLink(e),n=i.tid||"";return n===r?e:(i.tid=r,t.createLink(i))}function a(){var a=t.parseLink();s=a.tid!==e?a.tid:"",r=t.zui.uuid(),r=r.substr(r.length-8),t.tabSession={getTid:i,getNewTid:n};var l=window.location.origin;t("a").each(function(){var e=t(this),i=e.attr("href");if(0===i.indexOf(l)){var n=t.parseLink(i),o=n.tid||"";s&&s!==o&&(n.tid=s,i=t.createLink(n),e.attr("href",i))}}),t(document).contextmenu({selector:"a",items:function(e){var i=t(e.event.target).closest("a");if(i.length){var n=i.attr("href");return[{label:"打开",url:n},{label:"在新标签页中打开",onClick:function(){console.log("convertUrlWithNewTid(href)",o(n)),window.open(o(n),"_blank")}}]}}})}if(config.tabSession){var s,r;a()}}(jQuery,void 0),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),function(t,e){function i(){return s}function n(){return r}function o(e){var i=t.parseLink(e),n=i.tid||"";return n===r?e:(i.tid=r,t.createLink(i))}function a(){var a=t.parseLink(window.location.href);s=a.tid!==e?a.tid:"",r=t.zui.uuid(),r=r.substr(r.length-8),t.tabSession={getTid:i,getNewTid:n};var l=window.location.origin;t("a").each(function(){var e=t(this),i=e.attr("href");if(0===i.indexOf(l)){var n=t.parseLink(i),o=n.tid||"";s&&s!==o&&(n.tid=s,i=t.createLink(n),e.attr("href",i))}}),t(document).contextmenu({selector:"a",items:function(e){var i=t(e.event.target).closest("a");if(i.length){var n=i.attr("href");return[{label:"打开",url:n},{label:"在新标签页中打开",onClick:function(){console.log("convertUrlWithNewTid(href)",o(n)),window.open(o(n),"_blank")}}]}}})}if(config.tabSession){var s,r;a()}}(jQuery,void 0),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file From 37252fbc473cdce9156579cea81e4acc42a05a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Mon, 30 Aug 2021 13:19:56 +0800 Subject: [PATCH 004/304] * adjust for tid. --- framework/base/helper.class.php | 1 + lib/base/front/front.class.php | 2 +- module/bug/js/common.js | 4 ++-- module/execution/js/kanban.js | 4 ++-- module/my/js/common.js | 5 +++-- module/task/control.php | 5 +++-- module/task/js/batchcreate.js | 2 +- module/task/js/create.js | 6 +++--- module/testcase/js/create.js | 4 ++-- module/user/control.php | 6 +++--- 10 files changed, 21 insertions(+), 18 deletions(-) diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php index 33141d1ab7..9ef6a04521 100644 --- a/framework/base/helper.class.php +++ b/framework/base/helper.class.php @@ -189,6 +189,7 @@ class baseHelper */ public static function isWithTID() { + global $config; return (!empty($config->tabSession) and isset($_GET['tid'])); } diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index a25afa7015..b0f6f89bc1 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -1168,7 +1168,7 @@ EOT; $jsConfig->pingInterval = isset($config->pingInterval) ? $config->pingInterval : ''; $jsConfig->onlybody = zget($_GET, 'onlybody', 'no'); $jsConfig->tabSession = $config->tabSession; - if($config->tabSession and helper::inTabIDMode()) $jsConfig->tid = zget($_GET, 'tid', ''); + if($config->tabSession and helper::isWithTID()) $jsConfig->tid = zget($_GET, 'tid', ''); $jsLang = new stdclass(); $jsLang->submitting = isset($lang->loading) ? $lang->loading : ''; diff --git a/module/bug/js/common.js b/module/bug/js/common.js index 232bdc991e..38c75809ff 100644 --- a/module/bug/js/common.js +++ b/module/bug/js/common.js @@ -577,7 +577,7 @@ function notice() var branch = $('#branch').val(); if(typeof(branch) == 'undefined') branch = 0; var link = createLink('release', 'create', 'productID=' + $('#product').val() + '&branch=' + branch); - if(config.onlybody != 'yes') link += config.requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes'; + if(config.onlybody != 'yes') link += link.indexOf('?') >= 0 ? '&onlybody=yes' : '?onlybody=yes'; html += '' + createBuild + ' '; html += '' + refresh + ''; } @@ -587,7 +587,7 @@ function notice() productID = $('#product').val(); projectID = $('#project').val(); link = createLink('build', 'create','executionID=' + executionID + '&productID=' + productID + '&projectID=' + projectID); - link += config.requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes'; + link += link.indexOf('?') >= 0 ? '&onlybody=yes' : '?onlybody=yes'; html += '' + createBuild + ' '; html += '' + refresh + ''; } diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index 001ec4c5df..bd143f3280 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -34,7 +34,7 @@ $(function() adjustBoardsHeight(); var boardID = ''; - var onlybody = config.requestType == 'GET' ? "&onlybody=yes" : "?onlybody=yes"; + var onlybody = "onlybody=yes"; $.cookie('selfClose', 0, {expires:config.cookieLife, path:config.webRoot}); var $kanban = $('#kanban'); @@ -124,7 +124,7 @@ $(function() { kanbanModalTrigger.show( { - url: link + onlybody, + url: link + (link.indexOf('?') >= 0 ? '&' : '?') + onlybody, shown: function(){$('.modal-iframe').addClass('with-titlebar').data('cancel-reload', true)}, width: 900, hidden: refresh diff --git a/module/my/js/common.js b/module/my/js/common.js index 60242230cc..4fe6837834 100644 --- a/module/my/js/common.js +++ b/module/my/js/common.js @@ -6,6 +6,7 @@ $(function() if(typeof rawMethod === 'string' && rawMethod == 'work') $('#subNavbar li[data-id=' + mode + '] a').append('' + total + ''); } var scp = $('[data-id="changePassword"] a'); - var sign = config.requestType == 'GET' ? '&' : '?'; - scp.attr('href', scp.attr('href') + sign + 'onlybody=yes').modalTrigger({width:500, type:'iframe'}); + var link = scp.attr('href'); + var sign = link.indexOf('?') >= 0 ? '&' : '?'; + scp.attr('href', link + sign + 'onlybody=yes').modalTrigger({width:500, type:'iframe'}); }); diff --git a/module/task/control.php b/module/task/control.php index 15fc428e99..1f2dcd71b9 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -834,8 +834,9 @@ class task extends control die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); } - $this->session->set('estimateList', $this->app->getURI(true), 'execution'); - if(isonlybody() && $this->config->requestType != 'GET') $this->session->set('estimateList', $this->app->getURI(true) . '?onlybody=yes', 'execution'); + $uri = $this->app->getURI(true); + $this->session->set('estimateList', $uri, 'execution'); + if(isonlybody()) $this->session->set('estimateList', $uri . (substr($uri, '?') === false ? '?' : '&') . 'onlybody=yes', 'execution'); $this->view->task = $this->task->getById($taskID); $this->view->estimates = $this->task->getTaskEstimate($taskID); diff --git a/module/task/js/batchcreate.js b/module/task/js/batchcreate.js index e7ee7788cc..3d2ad85b65 100755 --- a/module/task/js/batchcreate.js +++ b/module/task/js/batchcreate.js @@ -101,7 +101,7 @@ function setStoryRelated(num) }); storyLink = createLink('story', 'view', "storyID=" + storyID); - var concat = config.requestType != 'GET' ? '?' : '&'; + var concat = storyLink.indexOf('?') >= 0 ? '&' : '?'; storyLink = storyLink + concat + 'onlybody=yes'; $('#preview' + num).removeAttr('disabled'); $('#preview' + num).attr('href', storyLink); diff --git a/module/task/js/create.js b/module/task/js/create.js index a0e2460ed1..7bf82e1e92 100644 --- a/module/task/js/create.js +++ b/module/task/js/create.js @@ -62,7 +62,7 @@ function loadExecutionStories(executionID) $('#story').next('.picker').remove(); $('#story').replaceWith(data); $('#story').addClass('filled').chosen(); - + /* If there is no story option, select will be hidden and text will be displayed; otherwise, the opposite is true */ if($('#story option').length > 1) { @@ -70,7 +70,7 @@ function loadExecutionStories(executionID) $('#storyBox').addClass('hidden'); } else - { + { $('#storyBox').removeClass('hidden'); $('#story').parent().addClass('hidden'); } @@ -199,7 +199,7 @@ function setPreview() else { storyLink = createLink('story', 'view', "storyID=" + $('#story').val()); - var concat = config.requestType != 'GET' ? '?' : '&'; + var concat = storyLink.indexOf('?') < 0 ? '?' : '&'; if(storyLink.indexOf("onlybody=yes") < 0) storyLink = storyLink + concat + 'onlybody=yes'; diff --git a/module/testcase/js/create.js b/module/testcase/js/create.js index be6f5d6183..38cc157e5c 100644 --- a/module/testcase/js/create.js +++ b/module/testcase/js/create.js @@ -7,8 +7,8 @@ function setPreview() } else { - storyLink = createLink('story', 'view', "storyID=" + $('#story').val()); - var concat = config.requestType != 'GET' ? '?' : '&'; + storyLink = createLink('story', 'view', "storyID=" + $('#story').val()); + var concat = storyLink.indexOf('?') < 0 ? '?' : '&'; storyLink = storyLink + concat + 'onlybody=yes'; $('#preview').removeClass('hidden'); $('#preview').attr('href', storyLink); diff --git a/module/user/control.php b/module/user/control.php index 848d057ac1..0782d019c2 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -827,7 +827,7 @@ class user extends control } else { - $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); + $response['locate'] = $this->config->webRoot . (helper::isWithTID() ? "?tid={$this->get->tid}" : ''); return $this->send($response); } } @@ -902,7 +902,7 @@ class user extends control } else { - $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); + $response['locate'] = $this->config->webRoot . (helper::isWithTID() ? "?tid={$this->get->tid}" : ''); return $this->send($response); } } @@ -914,7 +914,7 @@ class user extends control die(helper::removeUTF8Bom(json_encode(array('status' => 'success') + $data))); } - $response['locate'] = $this->config->webRoot . (helper::inTabIDMode() ? "?tid={$this->get->tid}" : ''); + $response['locate'] = $this->config->webRoot . (helper::isWithTID() ? "?tid={$this->get->tid}" : ''); $response['result'] = 'success'; return $this->send($response); } From bc2111446be653569209748ab004f75b4f013eb8 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 30 Aug 2021 13:29:42 +0800 Subject: [PATCH 005/304] * fix search link incorrect when use tabSession. --- module/index/js/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/index/js/index.js b/module/index/js/index.js index 1dac24549d..0eb412dbec 100644 --- a/module/index/js/index.js +++ b/module/index/js/index.js @@ -667,7 +667,8 @@ $.extend( var reg = /[^0-9]/; if(reg.test(objectValue) || objectType == 'all') { - var searchLink = createLink('search', 'index') + (config.requestType == 'PATH_INFO' ? '?' : '&') + 'words=' + objectValue; + var searchLink = createLink('search', 'index'); + searchLink += (searchLink.indexOf('?') ? '&' : '?') + 'words=' + objectValue; $.apps.open(searchLink); } else From 2017d40e3ca5ff7d7aa2fae068b6e2afde47d946 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 30 Aug 2021 13:29:42 +0800 Subject: [PATCH 006/304] * fix search link incorrect when use tabSession. --- module/index/js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/index/js/index.js b/module/index/js/index.js index 0eb412dbec..5ab4925532 100644 --- a/module/index/js/index.js +++ b/module/index/js/index.js @@ -668,7 +668,7 @@ $.extend( if(reg.test(objectValue) || objectType == 'all') { var searchLink = createLink('search', 'index'); - searchLink += (searchLink.indexOf('?') ? '&' : '?') + 'words=' + objectValue; + searchLink += (searchLink.indexOf('?') >= 0 ? '&' : '?') + 'words=' + objectValue; $.apps.open(searchLink); } else From 7b12c9ca2bb998355923e365e553fbc4cea8ec28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Mon, 30 Aug 2021 14:19:41 +0800 Subject: [PATCH 007/304] * adjust for concat sign for build url. --- module/api/model.php | 4 ++-- module/doc/view/content.html.php | 15 +++++++++----- module/doc/view/showfiles.html.php | 26 ++++++++++++------------- module/doc/view/view.html.php | 15 +++++++++----- module/file/view/download.html.php | 5 +++-- module/file/view/printfiles.html.php | 18 ++++++++++------- module/mail/control.php | 6 +++++- module/my/js/common.js | 4 ---- module/repo/model.php | 8 +++++--- module/testcase/view/createbug.html.php | 6 +----- module/testtask/js/runcase.js | 6 ++++-- module/testtask/view/runcase.html.php | 6 +----- module/user/model.php | 7 +++++-- module/webhook/view/choosedept.html.php | 9 +++++---- 14 files changed, 75 insertions(+), 60 deletions(-) diff --git a/module/api/model.php b/module/api/model.php index 4f5431735e..0518c9730d 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -69,7 +69,7 @@ class apiModel extends model $param = ltrim($param, ','); } $url = rtrim($host, '/') . inlink('getModel', "moduleName=$moduleName&methodName=$methodName¶ms=$param", 'json'); - $url .= $this->config->requestType == "PATH_INFO" ? '?' : '&'; + $url .= substr($url, '?') === false ? '?' : '&'; $url .= $this->config->sessionVar . '=' . session_id(); } else @@ -80,7 +80,7 @@ class apiModel extends model $param = ltrim($param, '&'); } $url = rtrim($host, '/') . helper::createLink($moduleName, $methodName, $param, 'json'); - $url .= $this->config->requestType == "PATH_INFO" ? '?' : '&'; + $url .= substr($url, '?') === false ? '?' : '&'; $url .= $this->config->sessionVar . '=' . session_id(); } diff --git a/module/doc/view/content.html.php b/module/doc/view/content.html.php index 749c11feb4..368767cb7d 100644 --- a/module/doc/view/content.html.php +++ b/module/doc/view/content.html.php @@ -1,8 +1,5 @@ doc->confirmDelete);?> -requestType == 'PATH_INFO' ? '?' : '&'; -$sessionString .= session_name() . '=' . session_id(); -?> +
          @@ -110,7 +107,15 @@ $sessionString .= session_name() . '=' . session_id(); id}");?>" alt="title?>" title="title;?>"> - createLink('file', 'download', 'fileID=' . $file->id) . $sessionString, "", '', "class='btn-icon' style='margin-right: 10px;' title=\"{$lang->doc->download}\"");?> + createLink('file', 'download', 'fileID=' . $file->id); + $downloadLink .= substr($downloadLink, '?') === false ? '?' : '&'; + $downloadLink .= $sessionString; + echo html::a($downloadLink, "", '', "class='btn-icon' style='margin-right: 10px;' title=\"{$lang->doc->download}\""); + } + ?> ", '', "class='btn-icon' title=\"{$lang->doc->deleteFile}\" onclick='deleteFile($file->id)'");?>
          diff --git a/module/doc/view/showfiles.html.php b/module/doc/view/showfiles.html.php index 0e09537080..c805ae8439 100644 --- a/module/doc/view/showfiles.html.php +++ b/module/doc/view/showfiles.html.php @@ -80,10 +80,10 @@ $imageWidth = $imageSize ? $imageSize[0] : 0; } - $sessionString = $config->requestType == 'PATH_INFO' ? '?' : '&'; - $sessionString .= session_name() . '=' . session_id(); - $fileID = $file->id; - $url = helper::createLink('file', 'download', 'fileID=' . $fileID) . $sessionString ; + $fileID = $file->id; + $url = helper::createLink('file', 'download', 'fileID=' . $fileID); + $url .= substr($url, '?') === false ? '?' : '&'; + $url .= session_name() . '=' . session_id(); ?>
          @@ -125,18 +125,18 @@ app->openApp);?> diff --git a/module/file/view/printfiles.html.php b/module/file/view/printfiles.html.php index 0b0f8d3208..d1a3d2e929 100644 --- a/module/file/view/printfiles.html.php +++ b/module/file/view/printfiles.html.php @@ -1,8 +1,5 @@ -requestType == 'PATH_INFO' and !isonlybody()) ? '?' : '&'; -$sessionString .= session_name() . '=' . session_id(); -?> +
          file->common;?>
          @@ -25,11 +22,14 @@ $sessionString .= session_name() . '=' . session_id(); { if(!fileID) return; var fileTypes = 'txt,jpg,jpeg,gif,png,bmp'; - var sessionString = ''; var windowWidth = $(window).width(); - var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left') + sessionString; var width = (windowWidth > imageWidth) ? ((imageWidth < windowWidth * 0.5) ? windowWidth * 0.5 : imageWidth) : windowWidth; var checkExtension = fileTitle.lastIndexOf('.' + extension) == (fileTitle.length - extension.length - 1); + + var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left'); + url += url.indexOf('?') >= 0 ? '&' : '?'; + url += ''; + if(fileTypes.indexOf(extension) >= 0 && checkExtension && config.onlybody != 'yes') { $('
          ').modalTrigger({url: url, type: 'iframe', width: width}).trigger('click'); @@ -78,7 +78,11 @@ $sessionString .= session_name() . '=' . session_id(); $file->size = round($file->size / (1024 * 1024 * 1024), 2); $fileSize = $file->size . 'G'; } - echo "
        • " . html::a($this->createLink('file', 'download', "fileID=$file->id") . $sessionString, $fileTitle . " ({$fileSize})", '_blank', "onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\""); + + $downloadLink = $this->createLink('file', 'download', "fileID=$file->id"); + $downloadLink .= substr($downloadLink, '?') === false ? '?' : '&'; + $downloadLink .= $sessionString; + echo "
        • " . html::a($downloadLink, $fileTitle . " ({$fileSize})", '_blank', "onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\""); $objectType = zget($this->config->file->objectType, $file->objectType); if(common::hasPriv($objectType, 'edit', $object)) diff --git a/module/mail/control.php b/module/mail/control.php index 30f7d41a92..2b9c82ba01 100755 --- a/module/mail/control.php +++ b/module/mail/control.php @@ -436,7 +436,11 @@ class mail extends control { if(empty($_POST)) die(js::reload('parent')); $idList = join('|', $this->post->mailIDList); - die(js::confirm($this->lang->mail->confirmDelete, inlink('batchDelete', "confirm=yes") . ($this->config->requestType == 'GET' ? '&' : '?') . "idList=$idList")); + + $confirmLink = inlink('batchDelete', "confirm=yes"); + $confirmLink .= substr($confirmLink, '?') === false ? '?' : '&'; + $confirmLink .= "idList=$idList"; + die(js::confirm($this->lang->mail->confirmDelete, $confirmLink)); } $idList = array(); if(isset($_GET['idList'])) $idList = explode('|', $_GET['idList']); diff --git a/module/my/js/common.js b/module/my/js/common.js index 4fe6837834..970d9283db 100644 --- a/module/my/js/common.js +++ b/module/my/js/common.js @@ -5,8 +5,4 @@ $(function() $('#subNavbar li[data-id=' + mode + ']').addClass('active'); if(typeof rawMethod === 'string' && rawMethod == 'work') $('#subNavbar li[data-id=' + mode + '] a').append('' + total + ''); } - var scp = $('[data-id="changePassword"] a'); - var link = scp.attr('href'); - var sign = link.indexOf('?') >= 0 ? '&' : '?'; - scp.attr('href', link + sign + 'onlybody=yes').modalTrigger({width:500, type:'iframe'}); }); diff --git a/module/repo/model.php b/module/repo/model.php index bb1dbaf823..4f91a0d4bc 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -920,11 +920,13 @@ class repoModel extends model */ public function setBackSession($type = 'list', $withOtherModule = false) { - $backKey = 'repo' . ucfirst(strtolower($type)); session_start(); $uri = $this->app->getURI(true); - if(!empty($_GET) and $this->config->requestType == 'PATH_INFO') $uri .= "?" . http_build_query($_GET); - $_SESSION[$backKey] = $uri; + if(!empty($_GET) and $this->config->requestType == 'PATH_INFO') $uri .= (substr($uri, '?') === false ? '?' : '&') . http_build_query($_GET); + + $backKey = 'repo' . ucfirst(strtolower($type)); + $this->session->set($backKey, $uri); + if($type == 'list') unset($_SESSION['repoView']); if($withOtherModule) { diff --git a/module/testcase/view/createbug.html.php b/module/testcase/view/createbug.html.php index 2cbbcf46f3..7157e068df 100644 --- a/module/testcase/view/createbug.html.php +++ b/module/testcase/view/createbug.html.php @@ -74,10 +74,6 @@ $(function() $('#tr-detail_1').removeClass("hide"); }); }); -requestType == 'PATH_INFO' ? '?' : '&'; -$sessionString .= session_name() . '=' . session_id(); -?> -var sessionString = ''; +var sessionString = ''; diff --git a/module/testtask/js/runcase.js b/module/testtask/js/runcase.js index ca33d440ee..2c80091d49 100644 --- a/module/testtask/js/runcase.js +++ b/module/testtask/js/runcase.js @@ -29,7 +29,9 @@ function deleteFile(fileID) function downloadFile(fileID, extension, imageWidth) { if(!fileID) return; - var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left') + sessionString; + var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left'); + url += url.indexOf('?') >= 0 ? '&' : '?'; + url += sessionString; window.open(url, '_blank'); return false; } @@ -53,7 +55,7 @@ $(document).ready(function() { // First unbind ajaxForm for form. $("#dataform").unbind('submit'); - + // Bind ajaxForm for form again. $('#dataform').ajaxForm( { diff --git a/module/testtask/view/runcase.html.php b/module/testtask/view/runcase.html.php index faa2195717..1dc448fe13 100644 --- a/module/testtask/view/runcase.html.php +++ b/module/testtask/view/runcase.html.php @@ -130,10 +130,6 @@ $(function() $('#casesResults table caption .result-tip').html($('#resultTip').html()); }); }); -requestType == 'PATH_INFO' ? '?' : '&'; -$sessionString .= session_name() . '=' . session_id(); -?> -var sessionString = ''; +var sessionString = ''; diff --git a/module/user/model.php b/module/user/model.php index 087d0a2347..6cadebbd09 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -110,8 +110,11 @@ class userModel extends model { if(is_array($usersToAppended)) $usersToAppended = join(',', $usersToAppended); $moreLinkParams = "params={$params}&usersToAppended={$usersToAppended}"; - $connectString = $this->config->requestType == 'GET' ? '&' : '?'; - $this->config->user->moreLink = helper::createLink('user', 'ajaxGetMore') . $connectString . "params=" . base64_encode($moreLinkParams); + + $moreLink = helper::createLink('user', 'ajaxGetMore'); + $moreLink .= substr($moreLink, '?') === false ? '?' : '&'; + $moreLink .= "params=" . base64_encode($moreLinkParams); + $this->config->user->moreLink = $moreLink; } if($usersToAppended) $users += $this->dao->select($fields)->from(TABLE_USER)->where('account')->in($usersToAppended)->fetchAll($keyField); diff --git a/module/webhook/view/choosedept.html.php b/module/webhook/view/choosedept.html.php index ff5bff4f80..6b8ae293b3 100644 --- a/module/webhook/view/choosedept.html.php +++ b/module/webhook/view/choosedept.html.php @@ -28,9 +28,9 @@ This is a p

          * @before $.metadata.setType("elem", "script") * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" * @desc Reads metadata from a nested script element - * + * * @param String type The encoding type * @param String name The name of the attribute to be used to get metadata (optional) * @cat Plugins/Metadata @@ -54,69 +52,69 @@ * @see metadata() */ -(function($) { + (function($) { -$.extend({ - metadata : { - defaults : { - type: 'class', - name: 'metadata', - cre: /({.*})/, - single: 'metadata' - }, - setType: function( type, name ){ - this.defaults.type = type; - this.defaults.name = name; - }, - get: function( elem, opts ){ - var settings = $.extend({},this.defaults,opts); - // check for empty string in single property - if ( !settings.single.length ) settings.single = 'metadata'; - - var data = $.data(elem, settings.single); - // returned cached data if it already exists - if ( data ) return data; - - data = "{}"; - - if ( settings.type == "class" ) { - var m = settings.cre.exec( elem.className ); - if ( m ) - data = m[1]; - } else if ( settings.type == "elem" ) { - if( !elem.getElementsByTagName ) - return undefined; - var e = elem.getElementsByTagName(settings.name); - if ( e.length ) - data = $.trim(e[0].innerHTML); - } else if ( elem.getAttribute != undefined ) { - var attr = elem.getAttribute( settings.name ); - if ( attr ) - data = attr; + $.extend({ + metadata : { + defaults : { + type: 'class', + name: 'metadata', + cre: /({.*})/, + single: 'metadata' + }, + setType: function( type, name ){ + this.defaults.type = type; + this.defaults.name = name; + }, + get: function( elem, opts ){ + var settings = $.extend({},this.defaults,opts); + // check for empty string in single property + if ( !settings.single.length ) settings.single = 'metadata'; + + var data = $.data(elem, settings.single); + // returned cached data if it already exists + if ( data ) return data; + + data = "{}"; + + if ( settings.type == "class" ) { + var m = settings.cre.exec( elem.className ); + if ( m ) + data = m[1]; + } else if ( settings.type == "elem" ) { + if( !elem.getElementsByTagName ) + return undefined; + var e = elem.getElementsByTagName(settings.name); + if ( e.length ) + data = $.trim(e[0].innerHTML); + } else if ( elem.getAttribute != undefined ) { + var attr = elem.getAttribute( settings.name ); + if ( attr ) + data = attr; + } + + if ( data.indexOf( '{' ) <0 ) + data = "{" + data + "}"; + + data = eval("(" + data + ")"); + + $.data( elem, settings.single, data ); + return data; } - - if ( data.indexOf( '{' ) <0 ) - data = "{" + data + "}"; - - data = eval("(" + data + ")"); - - $.data( elem, settings.single, data ); - return data; } - } -}); + }); -/** - * Returns the metadata object for the first member of the jQuery object. - * - * @name metadata - * @descr Returns element's metadata object - * @param Object opts An object contianing settings to override the defaults - * @type jQuery - * @cat Plugins/Metadata - */ -$.fn.metadata = function( opts ){ - return $.metadata.get( this[0], opts ); -}; + /** + * Returns the metadata object for the first member of the jQuery object. + * + * @name metadata + * @descr Returns element's metadata object + * @param Object opts An object contianing settings to override the defaults + * @type jQuery + * @cat Plugins/Metadata + */ + $.fn.metadata = function( opts ){ + return $.metadata.get( this[0], opts ); + }; -})(jQuery); \ No newline at end of file +})(jQuery); diff --git a/www/js/jquery/tablesorter/min.js b/www/js/jquery/tablesorter/min.js index 7ec552e613..137511fd52 100644 --- a/www/js/jquery/tablesorter/min.js +++ b/www/js/jquery/tablesorter/min.js @@ -1,7 +1,6 @@ /*! -* TableSorter 2.17.5 min - Client-side table sorting with ease! +* TableSorter 2.31.3 min - Client-side table sorting with ease! * Copyright (c) 2007 Christian Bach */ -!function(g){g.extend({tablesorter:new function(){function d(){var b=arguments[0],a=1':"";m.$headers.each(function(d){c=g(this);a=f.getColumnData(b, m.headers,d,!0);m.headerContent[d]=g(this).html();r=m.headerTemplate.replace(/\{content\}/g,g(this).html()).replace(/\{icon\}/g,e);m.onRenderTemplate&&(h=m.onRenderTemplate.apply(c,[d,r]))&&"string"===typeof h&&(r=h);g(this).html('
          '+r+"
          ");m.onRenderHeader&&m.onRenderHeader.apply(c,[d]);this.column=parseInt(g(this).attr("data-column"),10);this.order=C(f.getData(c,a,"sortInitialOrder")||m.sortInitialOrder)?[1,0,2]:[0,1,2];this.count=-1;this.lockedOrder=!1;k=f.getData(c, a,"lockedOrder")||!1;"undefined"!==typeof k&&!1!==k&&(this.order=this.lockedOrder=C(k)?[1,1,1]:[0,0,0]);c.addClass(f.css.header+" "+m.cssHeader);m.headerList[d]=this;c.parent().addClass(f.css.headerRow+" "+m.cssHeaderRow).attr("role","row");m.tabIndex&&c.attr("tabindex",0)}).attr({scope:"col",role:"columnheader"});B(b);m.debug&&(v("Built headers:",l),d(m.$headers))}function E(b,a,c){var h=b.config;h.$table.find(h.selectorRemove).remove();t(b);x(b);H(h.$table,a,c)}function B(b){var a,c,h=b.config; h.$headers.each(function(e,r){c=g(r);a="false"===f.getData(r,f.getColumnData(b,h.headers,e,!0),"sorter");r.sortDisabled=a;c[a?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+a);b.id&&(a?c.removeAttr("aria-controls"):c.attr("aria-controls",b.id))})}function G(b){var a,c,h=b.config,e=h.sortList,r=e.length,d=f.css.sortNone+" "+h.cssNone,l=[f.css.sortAsc+" "+h.cssAsc,f.css.sortDesc+" "+h.cssDesc],m=["ascending","descending"],y=g(b).find("tfoot tr").children().add(h.$extraHeaders).removeClass(l.join(" ")); h.$headers.removeClass(l.join(" ")).addClass(d).attr("aria-sort","none");for(a=0;a"),c=g(b).width();g(b.tBodies[0]).find("tr:first").children("td:visible").each(function(){a.append(g("").css("width",parseInt(g(this).width()/c*1E3,10)/10+"%"))});g(b).prepend(a)}}function M(b,a){var c,h,e, f,d,l=b.config,m=a||l.sortList;l.sortList=[];g.each(m,function(b,a){f=parseInt(a[0],10);if(e=l.$headers.filter('[data-column="'+f+'"]:last')[0]){h=(h=(""+a[1]).match(/^(1|d|s|o|n)/))?h[0]:"";switch(h){case "1":case "d":h=1;break;case "s":h=d||0;break;case "o":c=e.order[(d||0)%(l.sortReset?3:2)];h=0===c?1:1===c?0:2;break;case "n":e.count+=1;h=e.order[e.count%(l.sortReset?3:2)];break;default:h=0}d=0===b?h:d;c=[f,parseInt(h,10)||0];l.sortList.push(c);h=g.inArray(c[1],e.order);e.count=0<=h?h:c[1]%(l.sortReset? 3:2)}})}function N(b,a){return b&&b[a]?b[a].type||"":""}function O(b,a,c){var h,e,d,k=b.config,l=!c[k.sortMultiSortKey],m=k.$table;m.trigger("sortStart",b);a.count=c[k.sortResetKey]?2:(a.count+1)%(k.sortReset?3:2);k.sortRestart&&(e=a,k.$headers.each(function(){this===e||!l&&g(this).is("."+f.css.sortDesc+",."+f.css.sortAsc)||(this.count=-1)}));e=a.column;if(l){k.sortList=[];if(null!==k.sortForce)for(h=k.sortForce,c=0;ch&&(k.sortList.push([e, h]),1h&&(k.sortList.push([e,h]),1 thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]};f.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",info:"tablesorter-infoOnly",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc", sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"};f.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"};f.log=d;f.benchmark=v;f.construct=function(b){return this.each(function(){var a=g.extend(!0,{},f.defaults,b);a.originalSettings=b;!this.hasInitialized&&f.buildTable&&"TABLE"!==this.tagName? f.buildTable(this,a):f.setup(this,a)})};f.setup=function(b,a){if(!b||!b.tHead||0===b.tBodies.length||!0===b.hasInitialized)return a.debug?d("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"):"";var c="",h=g(b),e=g.metadata;b.hasInitialized=!1;b.isProcessing=!0;b.config=a;g.data(b,"tablesorter",a);a.debug&&g.data(b,"startoveralltimer",new Date);a.supportsDataObject=function(a){a[0]=parseInt(a[0],10);return 1'),c=g.fn.detach?a.detach():a.remove();c=g(b).find("span.tablesorter-savemyplace");a.insertAfter(c);c.remove();b.isProcessing=!1};f.clearTableBody=function(b){g(b)[0].config.$tbodies.children().detach()};f.bindEvents=function(b,a,c){b=g(b)[0];var d, e=b.config;!0!==c&&(e.$extraHeaders=e.$extraHeaders?e.$extraHeaders.add(a):a);a.find(e.selectorSort).add(a.filter(e.selectorSort)).unbind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" ")).bind(["mousedown","mouseup","sort","keyup",""].join(e.namespace+" "),function(c,f){var l;l=c.type;if(!(1!==(c.which||c.button)&&!/sort|keyup/.test(l)||"keyup"===l&&13!==c.which||"mouseup"===l&&!0!==f&&250<(new Date).getTime()-d)){if("mousedown"===l)return d=(new Date).getTime(),/(input|select|button|textarea)/i.test(c.target.tagName)? "":!e.cancelSelection;e.delayInit&&p(e.cache)&&x(b);l=g.fn.closest?g(this).closest("th, td")[0]:/TH|TD/.test(this.tagName)?this:g(this).parents("th, td")[0];l=e.$headers[a.index(l)];l.sortDisabled||O(b,l,c)}});e.cancelSelection&&a.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})};f.restoreHeaders=function(b){var a=g(b)[0].config;a.$table.find(a.selectorHeaders).each(function(b){g(this).find("."+f.css.headerIn).length&&g(this).html(a.headerContent[b])})}; f.destroy=function(b,a,c){b=g(b)[0];if(b.hasInitialized){f.refreshWidgets(b,!0,!0);var d=g(b),e=b.config,r=d.find("thead:first"),k=r.find("tr."+f.css.headerRow).removeClass(f.css.headerRow+" "+e.cssHeaderRow),l=d.find("tfoot:first > tr").children("th, td");!1===a&&0<=g.inArray("uitheme",e.widgets)&&(d.trigger("applyWidgetId",["uitheme"]),d.trigger("applyWidgetId",["zebra"]));r.find("tr").not(k).remove();d.removeData("tablesorter").unbind("sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(e.namespace+ " "));e.$headers.add(l).removeClass([f.css.header,e.cssHeader,e.cssAsc,e.cssDesc,f.css.sortAsc,f.css.sortDesc,f.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true");k.find(e.selectorSort).unbind(["mousedown","mouseup","keypress",""].join(e.namespace+" "));f.restoreHeaders(b);d.toggleClass(f.css.table+" "+e.tableClass+" tablesorter-"+e.theme,!1===a);b.hasInitialized=!1;delete b.config.cache;"function"===typeof c&&c(b)}};f.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i};f.sortNatural=function(b,a){if(b===a)return 0;var c,d,e,g,k,l;d=f.regex;if(d.hex.test(a)){c=parseInt(b.match(d.hex),16);e=parseInt(a.match(d.hex),16);if(ce)return 1}c=b.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");d=a.replace(d.chunk,"\\0$1\\0").replace(d.chunks,"").split("\\0");l=Math.max(c.length,d.length);for(k=0;kg)return 1}return 0};f.sortNaturalAsc=function(b,a,c,d,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:-c||-1:""===a&&0!==c?"boolean"===typeof c?c?1:-1:c||1:f.sortNatural(b,a)};f.sortNaturalDesc=function(b,a,c,d,e){if(b===a)return 0;c=e.string[e.empties[c]||e.emptyTo];return""===b&&0!==c?"boolean"===typeof c?c?-1:1:c||1:""===a&&0!==c?"boolean"===typeof c?c? 1:-1:-c||-1:f.sortNatural(a,b)};f.sortText=function(b,a){return b>a?1:bg.inArray(k[h].id,p))&&(e.debug&&d('Refeshing widgets: Removing "'+k[h].id+'"'),k[h].hasOwnProperty("remove")&&e.widgetInit[k[h].id]&&(k[h].remove(b, e,e.widgetOptions),e.widgetInit[k[h].id]=!1));!0!==c&&f.applyWidget(b,a)};f.getData=function(b,a,c){var d="";b=g(b);var e,f;if(!b.length)return"";e=g.metadata?b.metadata():!1;f=" "+(b.attr("class")||"");"undefined"!==typeof b.data(c)||"undefined"!==typeof b.data(c.toLowerCase())?d+=b.data(c)||b.data(c.toLowerCase()):e&&"undefined"!==typeof e[c]?d+=e[c]:a&&"undefined"!==typeof a[c]?d+=a[c]:" "!==f&&f.match(" "+c+"-")&&(d=f.match(new RegExp("\\s"+c+"-([\\w-]+)"))[1]||"");return g.trim(d)};f.formatFloat= function(b,a){if("string"!==typeof b||""===b)return b;var c;b=(a&&a.config?!1!==a.config.usNumberFormat:"undefined"!==typeof a?a:1)?b.replace(/,/g,""):b.replace(/[\s|\.]/g,"").replace(/,/g,".");/^\s*\([.\d]+\)/.test(b)&&(b=b.replace(/^\s*\(([.\d]+)\)/,"-$1"));c=parseFloat(b);return isNaN(c)?g.trim(b):c};f.isDigit=function(b){return isNaN(b)?/^[\-+(]?\d+[)]?$/.test(b.toString().replace(/[,.'"\s]/g,"")):!0}}});var n=g.tablesorter;g.fn.extend({tablesorter:n.construct});n.addParser({id:"no-parser",is:function(){return!1}, format:function(){return""},type:"text"});n.addParser({id:"text",is:function(){return!0},format:function(d,v){var p=v.config;d&&(d=g.trim(p.ignoreCase?d.toLocaleLowerCase():d),d=p.sortLocaleCompare?n.replaceAccents(d):d);return d},type:"text"});n.addParser({id:"digit",is:function(d){return n.isDigit(d)},format:function(d,v){var p=n.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),v);return d&&"number"===typeof p?p:d?g.trim(d&&v.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});n.addParser({id:"currency", is:function(d){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((d||"").replace(/[+\-,. ]/g,""))},format:function(d,v){var p=n.formatFloat((d||"").replace(/[^\w,. \-()]/g,""),v);return d&&"number"===typeof p?p:d?g.trim(d&&v.config.ignoreCase?d.toLocaleLowerCase():d):d},type:"numeric"});n.addParser({id:"ipAddress",is:function(d){return/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/.test(d)},format:function(d,g){var p,w=d?d.split("."):"",t="",x=w.length; for(p=0;pd.length},format:function(d,g){return d?n.formatFloat(d.replace(/%/g,""),g):d},type:"numeric"});n.addParser({id:"usLongDate",is:function(d){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(d)||/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(d)},format:function(d,g){return d?n.formatFloat((new Date(d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,g):d},type:"numeric"});n.addParser({id:"shortDate",is:function(d){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((d|| "").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(d,g,p,w){if(d){p=g.config;var t=p.$headers.filter("[data-column="+w+"]:last");w=t.length&&t[0].dateFormat||n.getData(t,n.getColumnData(g,p.headers,w),"dateFormat")||p.dateFormat;d=d.replace(/\s+/g," ").replace(/[\-.,]/g,"/");"mmddyyyy"===w?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===w?d=d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===w&&(d=d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3"))}return d?n.formatFloat((new Date(d)).getTime()||d,g):d},type:"numeric"});n.addParser({id:"time",is:function(d){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(d)},format:function(d,g){return d?n.formatFloat((new Date("2000/01/01 "+d.replace(/(\S)([AP]M)$/i,"$1 $2"))).getTime()||d,g):d},type:"numeric"});n.addParser({id:"metadata",is:function(){return!1},format:function(d,n,p){d=n.config;d=d.parserMetadataName?d.parserMetadataName:"sortValue";return g(p).metadata()[d]}, type:"numeric"});n.addWidget({id:"zebra",priority:90,format:function(d,v,p){var w,t,x,z,C,D,E=new RegExp(v.cssChildRow,"i"),B=v.$tbodies;v.debug&&(C=new Date);for(d=0;d0?d.sortList=k:c.hasInitialized&&k&&k.length>0&&i.trigger("sorton",[k]))},remove:function(a){b.storage&&b.storage(a,"tablesorter-savesort","")}})}(jQuery); +!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&"object"==typeof module.exports?module.exports=e(require("jquery")):e(jQuery)}(function(e){"use strict";e.extend({tablesorter:new function(){function t(){var e=arguments[0],t=arguments.length>1?Array.prototype.slice.call(arguments):e;"undefined"!=typeof console&&"undefined"!=typeof console.log?console[/error/i.test(e)?"error":/warn/i.test(e)?"warn":"log"](t):alert(t)}function r(e,r){t(e+" ("+((new Date).getTime()-r.getTime())+"ms)")}function s(e){for(var t in e)return!1;return!0}function a(r,s,a,n){for(var o,i,d=r.config,c=v.parsers.length,l=!1,u="",p=!0;""===u&&p;)a++,s[a]?(l=s[a].cells[n],u=v.getElementText(d,l,n),i=e(l),r.config.debug&&t("Checking if value was empty on row "+a+", column: "+n+': "'+u+'"')):p=!1;for(;--c>=0;)if(o=v.parsers[c],o&&"text"!==o.id&&o.is&&o.is(u,r,l,i))return o;return v.getParserById("text")}function n(e){var s,n,o,i,d,c,l,u,p,g,f=e.config,m=f.$tbodies=f.$table.children("tbody:not(."+f.cssInfoBlock+")"),h=0,b="",y=m.length;if(0===y)return f.debug?t("Warning: *Empty table!* Not building a parser cache"):"";for(f.debug&&(g=new Date,t("Detecting parsers for each column")),n={extractors:[],parsers:[]};y>h;){if(s=m[h].rows,s.length)for(o=f.columns,i=0;o>i;i++)d=f.$headers.filter('[data-column="'+i+'"]:last'),c=v.getColumnData(e,f.headers,i),p=v.getParserById(v.getData(d,c,"extractor")),u=v.getParserById(v.getData(d,c,"sorter")),l="false"===v.getData(d,c,"parser"),f.empties[i]=(v.getData(d,c,"empty")||f.emptyTo||(f.emptyToBottom?"bottom":"top")).toLowerCase(),f.strings[i]=(v.getData(d,c,"string")||f.stringTo||"max").toLowerCase(),l&&(u=v.getParserById("no-parser")),p||(p=!1),u||(u=a(e,s,-1,i)),f.debug&&(b+="column:"+i+"; extractor:"+p.id+"; parser:"+u.id+"; string:"+f.strings[i]+"; empty: "+f.empties[i]+"\n"),n.parsers[i]=u,n.extractors[i]=p;h+=n.parsers.length?y:1}f.debug&&(t(b?b:"No parsers detected"),r("Completed detecting parsers",g)),f.parsers=n.parsers,f.extractors=n.extractors}function o(s){var a,n,o,i,d,c,l,u,p,g,f,m,h,b=s.config,y=b.$tbodies,w=b.extractors,x=b.parsers;if(b.cache={},b.totalRows=0,!x)return b.debug?t("Warning: *Empty table!* Not building a cache"):"";for(b.debug&&(g=new Date),b.showProcessing&&v.isProcessing(s,!0),l=0;ld;++d)if(m={child:[],raw:[]},u=e(y[l].rows[d]),p=[],u.hasClass(b.cssChildRow)&&0!==d)n=a.normalized.length-1,a.normalized[n][b.columns].$row=a.normalized[n][b.columns].$row.add(u),u.prev().hasClass(b.cssChildRow)||u.prev().addClass(v.css.cssHasChild),m.child[n]=e.trim(u[0].textContent||u.text()||"");else{for(m.$row=u,m.order=d,c=0;cd;d++)f.push(a[d][u.columns].$row),u.appender&&(!u.pager||u.pager.removeRows&&p.pager_removeRows||u.pager.ajax)||i.append(a[d][u.columns].$row);v.processTbody(e,i,!1)}u.appender&&u.appender(e,f),u.debug&&r("Rebuilt table",l),t||u.appender||v.applyWidget(e),e.isUpdating&&u.$table.trigger("updateComplete",e)}function d(e){return/^d/i.test(e)||1===e}function c(s){var a,n,o,i,c,l,p,g=s.config;g.headerList=[],g.headerContent=[],g.debug&&(p=new Date),g.columns=v.computeColumnIndex(g.$table.children("thead, tfoot").children("tr")),i=g.cssIcon?'':"",g.$headers=e(e.map(e(s).find(g.selectorHeaders),function(t,r){return n=e(t),n.parent().hasClass(g.cssIgnoreRow)?void 0:(a=v.getColumnData(s,g.headers,r,!0),g.headerContent[r]=n.html(),""===g.headerTemplate||n.find("."+v.css.headerIn).length||(c=g.headerTemplate.replace(/\{content\}/g,n.html()).replace(/\{icon\}/g,n.find("."+v.css.icon).length?"":i),g.onRenderTemplate&&(o=g.onRenderTemplate.apply(n,[r,c]),o&&"string"==typeof o&&(c=o)),n.html('
          '+c+"
          ")),g.onRenderHeader&&g.onRenderHeader.apply(n,[r,g,g.$table]),t.column=parseInt(n.attr("data-column"),10),t.order=d(v.getData(n,a,"sortInitialOrder")||g.sortInitialOrder)?[1,0,2]:[0,1,2],t.count=-1,t.lockedOrder=!1,l=v.getData(n,a,"lockedOrder")||!1,"undefined"!=typeof l&&l!==!1&&(t.order=t.lockedOrder=d(l)?[1,1,1]:[0,0,0]),n.addClass(v.css.header+" "+g.cssHeader),g.headerList[r]=t,n.parent().addClass(v.css.headerRow+" "+g.cssHeaderRow).attr("role","row"),g.tabIndex&&n.attr("tabindex",0),t)})),e(s).find(g.selectorHeaders).attr({scope:"col",role:"columnheader"}),u(s),g.debug&&(r("Built headers:",p),t(g.$headers))}function l(e,t,r){var s=e.config;s.$table.find(s.selectorRemove).remove(),n(e),o(e),y(s,t,r)}function u(t){var r,s,a,n=t.config;n.$headers.each(function(o,i){s=e(i),a=v.getColumnData(t,n.headers,o,!0),r="false"===v.getData(i,a,"sorter")||"false"===v.getData(i,a,"parser"),i.sortDisabled=r,s[r?"addClass":"removeClass"]("sorter-false").attr("aria-disabled",""+r),t.id&&(r?s.removeAttr("aria-controls"):s.attr("aria-controls",t.id))})}function p(t){var r,s,a,n=t.config,o=n.sortList,i=o.length,d=v.css.sortNone+" "+n.cssNone,c=[v.css.sortAsc+" "+n.cssAsc,v.css.sortDesc+" "+n.cssDesc],l=[n.cssIconAsc,n.cssIconDesc,n.cssIconNone],u=["ascending","descending"],p=e(t).find("tfoot tr").children().add(n.$extraHeaders).removeClass(c.join(" "));for(n.$headers.removeClass(c.join(" ")).addClass(d).attr("aria-sort","none").find("."+n.cssIcon).removeClass(l.join(" ")).addClass(l[2]),s=0;i>s;s++)if(2!==o[s][1]&&(r=n.$headers.not(".sorter-false").filter('[data-column="'+o[s][0]+'"]'+(1===i?":last":"")),r.length)){for(a=0;a=0?a:s[1]%(d.sortReset?3:2)}})}function f(e,t){return e&&e[t]?e[t].type||"":""}function m(t,r,s){if(t.isUpdating)return setTimeout(function(){m(t,r,s)},50);var a,n,o,d,c,l=t.config,u=!s[l.sortMultiSortKey],g=l.$table;if(g.trigger("sortStart",t),r.count=s[l.sortResetKey]?2:(r.count+1)%(l.sortReset?3:2),l.sortRestart&&(n=r,l.$headers.each(function(){this===n||!u&&e(this).is("."+v.css.sortDesc+",."+v.css.sortAsc)||(this.count=-1)})),n=parseInt(e(r).attr("data-column"),10),u){if(l.sortList=[],null!==l.sortForce)for(a=l.sortForce,o=0;od&&(l.sortList.push([n,d]),r.colSpan>1))for(o=1;o1)for(o=0;o=0&&l.sortList.splice(c,1);if(v.isValueInArray(n,l.sortList)>=0)for(o=0;od&&(l.sortList.push([n,d]),r.colSpan>1))for(o=1;oa;a++)d=h.cache[a].colMax,c=h.cache[a].normalized,c.sort(function(r,s){for(t=0;w>t;t++){if(o=y[t][0],l=y[t][1],m=0===l,h.sortStable&&r[o]===s[o]&&1===w)return r[h.columns].order-s[h.columns].order;if(n=/n/i.test(f(h.parsers,o)),n&&h.strings[o]?(n="boolean"==typeof h.string[h.strings[o]]?(m?1:-1)*(h.string[h.strings[o]]?-1:1):h.strings[o]?h.string[h.strings[o]]||0:0,u=h.numberSorter?h.numberSorter(r[o],s[o],m,d[o],e):v["sortNumeric"+(m?"Asc":"Desc")](r[o],s[o],n,d[o],o,e)):(p=m?r:s,g=m?s:r,u="function"==typeof b?b(p[o],g[o],m,o,e):"object"==typeof b&&b.hasOwnProperty(o)?b[o](p[o],g[o],m,o,e):v["sortNatural"+(m?"Asc":"Desc")](r[o],s[o],o,e,h)),u)return u}return r[h.columns].order-s[h.columns].order});h.debug&&r("Sorting on "+y.toString()+" and dir "+l+" time",i)}}function b(t,r){t.table.isUpdating&&t.$table.trigger("updateComplete",t.table),e.isFunction(r)&&r(t.table)}function y(t,r,s){var a=e.isArray(r)?r:t.sortList,n="undefined"==typeof r?t.resort:r;n===!1||t.serverSideSorting||t.table.isProcessing?(b(t,s),v.applyWidget(t.table,!1)):a.length?t.$table.trigger("sorton",[a,function(){b(t,s)},!0]):t.$table.trigger("sortReset",[function(){b(t,s),v.applyWidget(t.table,!1)}])}function w(t){var r=t.config,a=r.$table,d="sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave ".split(" ").join(r.namespace+" ");a.unbind(d.replace(/\s+/g," ")).bind("sortReset"+r.namespace,function(s,a){s.stopPropagation(),r.sortList=[],p(t),h(t),i(t),e.isFunction(a)&&a(t)}).bind("updateAll"+r.namespace,function(e,s,a){e.stopPropagation(),t.isUpdating=!0,v.refreshWidgets(t,!0,!0),c(t),v.bindEvents(t,r.$headers,!0),w(t),l(t,s,a)}).bind("update"+r.namespace+" updateRows"+r.namespace,function(e,r,s){e.stopPropagation(),t.isUpdating=!0,u(t),l(t,r,s)}).bind("updateCell"+r.namespace,function(s,n,o,i){s.stopPropagation(),t.isUpdating=!0,a.find(r.selectorRemove).remove();var d,c,l,u,p=r.$tbodies,g=e(n),f=p.index(e.fn.closest?g.closest("tbody"):g.parents("tbody").filter(":first")),m=e.fn.closest?g.closest("tr"):g.parents("tr").filter(":first");n=g[0],p.length&&f>=0&&(l=p.eq(f).find("tr").index(m),u=g.index(),r.cache[f].normalized[l][r.columns].$row=m,c="undefined"==typeof r.extractors[u].id?v.getElementText(r,n,u):r.extractors[u].format(v.getElementText(r,n,u),t,n,u),d="no-parser"===r.parsers[u].id?"":r.parsers[u].format(c,t,n,u),r.cache[f].normalized[l][u]=r.ignoreCase&&"string"==typeof d?d.toLowerCase():d,"numeric"===(r.parsers[u].type||"").toLowerCase()&&(r.cache[f].colMax[u]=Math.max(Math.abs(d)||0,r.cache[f].colMax[u]||0)),d="undefined"!==o?o:r.resort,d!==!1?y(r,d,i):(e.isFunction(i)&&i(t),r.$table.trigger("updateComplete",r.table)))}).bind("addRows"+r.namespace,function(a,o,i,d){if(a.stopPropagation(),t.isUpdating=!0,s(r.cache))u(t),l(t,i,d);else{o=e(o).attr("role","row");var c,p,g,f,m,h,b,w=o.filter("tr").length,x=r.$tbodies.index(o.parents("tbody").filter(":first"));for(r.parsers&&r.parsers.length||n(t),c=0;w>c;c++){for(g=o[c].cells.length,b=[],h={child:[],$row:o.eq(c),order:r.cache[x].normalized.length},p=0;g>p;p++)f="undefined"==typeof r.extractors[p].id?v.getElementText(r,o[c].cells[p],p):r.extractors[p].format(v.getElementText(r,o[c].cells[p],p),t,o[c].cells[p],p),m="no-parser"===r.parsers[p].id?"":r.parsers[p].format(f,t,o[c].cells[p],p),b[p]=r.ignoreCase&&"string"==typeof m?m.toLowerCase():m,"numeric"===(r.parsers[p].type||"").toLowerCase()&&(r.cache[x].colMax[p]=Math.max(Math.abs(b[p])||0,r.cache[x].colMax[p]||0));b.push(h),r.cache[x].normalized.push(b)}y(r,i,d)}}).bind("updateComplete"+r.namespace,function(){t.isUpdating=!1}).bind("sorton"+r.namespace,function(r,n,d,c){var l=t.config;r.stopPropagation(),a.trigger("sortStart",this),g(t,n),p(t),l.delayInit&&s(l.cache)&&o(t),a.trigger("sortBegin",this),h(t),i(t,c),a.trigger("sortEnd",this),v.applyWidget(t),e.isFunction(d)&&d(t)}).bind("appendCache"+r.namespace,function(r,s,a){r.stopPropagation(),i(t,a),e.isFunction(s)&&s(t)}).bind("updateCache"+r.namespace,function(s,a){r.parsers&&r.parsers.length||n(t),o(t),e.isFunction(a)&&a(t)}).bind("applyWidgetId"+r.namespace,function(e,s){e.stopPropagation(),v.getWidgetById(s).format(t,r,r.widgetOptions)}).bind("applyWidgets"+r.namespace,function(e,r){e.stopPropagation(),v.applyWidget(t,r)}).bind("refreshWidgets"+r.namespace,function(e,r,s){e.stopPropagation(),v.refreshWidgets(t,r,s)}).bind("destroy"+r.namespace,function(e,r,s){e.stopPropagation(),v.destroy(t,r,s)}).bind("resetToLoadState"+r.namespace,function(){v.removeWidget(t,!0,!1),r=e.extend(!0,v.defaults,r.originalSettings),t.hasInitialized=!1,v.setup(t,r)})}var v=this;v.version="{{version}}",v.parsers=[],v.widgets=[],v.defaults={theme:"default",widthFixed:!1,showProcessing:!1,headerTemplate:"{content}",onRenderTemplate:null,onRenderHeader:null,cancelSelection:!0,tabIndex:!0,dateFormat:"mmddyyyy",sortMultiSortKey:"shiftKey",sortResetKey:"ctrlKey",usNumberFormat:!0,delayInit:!1,serverSideSorting:!1,resort:!0,headers:{},ignoreCase:!0,sortForce:null,sortList:[],sortAppend:null,sortStable:!1,sortInitialOrder:"asc",sortLocaleCompare:!1,sortReset:!1,sortRestart:!1,emptyTo:"bottom",stringTo:"max",textExtraction:"basic",textAttribute:"data-text",textSorter:null,numberSorter:null,widgets:[],widgetOptions:{zebra:["even","odd"]},initWidgets:!0,widgetClass:"widget-{name}",initialized:null,tableClass:"",cssAsc:"",cssDesc:"",cssNone:"",cssHeader:"",cssHeaderRow:"",cssProcessing:"",cssChildRow:"tablesorter-childRow",cssIcon:"tablesorter-icon",cssIconNone:"",cssIconAsc:"",cssIconDesc:"",cssInfoBlock:"tablesorter-infoOnly",cssNoSort:"tablesorter-noSort",cssIgnoreRow:"tablesorter-ignoreRow",selectorHeaders:"> thead th, > thead td",selectorSort:"th, td",selectorRemove:".remove-me",debug:!1,headerList:[],empties:{},strings:{},parsers:[]},v.css={table:"tablesorter",cssHasChild:"tablesorter-hasChildRow",childRow:"tablesorter-childRow",colgroup:"tablesorter-colgroup",header:"tablesorter-header",headerRow:"tablesorter-headerRow",headerIn:"tablesorter-header-inner",icon:"tablesorter-icon",processing:"tablesorter-processing",sortAsc:"tablesorter-headerAsc",sortDesc:"tablesorter-headerDesc",sortNone:"tablesorter-headerUnSorted"},v.language={sortAsc:"Ascending sort applied, ",sortDesc:"Descending sort applied, ",sortNone:"No sort applied, ",nextAsc:"activate to apply an ascending sort",nextDesc:"activate to apply a descending sort",nextNone:"activate to remove the sort"},v.log=t,v.benchmark=r,v.getElementText=function(t,r,s){if(!r)return"";var a,n=t.textExtraction||"",o=r.jquery?r:e(r);return e.trim("string"==typeof n?("basic"===n?o.attr(t.textAttribute)||r.textContent:r.textContent)||o.text()||"":"function"==typeof n?n(o[0],t.table,s):"function"==typeof(a=v.getColumnData(t.table,n,s))?a(o[0],t.table,s):o[0].textContent||o.text()||"")},v.construct=function(t){return this.each(function(){var r=this,s=e.extend(!0,{},v.defaults,t);s.originalSettings=t,!r.hasInitialized&&v.buildTable&&"TABLE"!==this.tagName?v.buildTable(r,s):v.setup(r,s)})},v.setup=function(r,s){if(!r||!r.tHead||0===r.tBodies.length||r.hasInitialized===!0)return s.debug?t("ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized"):"";var a="",i=e(r),d=e.metadata;r.hasInitialized=!1,r.isProcessing=!0,r.config=s,e.data(r,"tablesorter",s),s.debug&&e.data(r,"startoveralltimer",new Date),s.supportsDataObject=function(e){return e[0]=parseInt(e[0],10),e[0]>1||1===e[0]&&parseInt(e[1],10)>=4}(e.fn.jquery.split(".")),s.string={max:1,min:-1,emptymin:1,emptymax:-1,zero:0,none:0,"null":0,top:!0,bottom:!1},s.emptyTo=s.emptyTo.toLowerCase(),s.stringTo=s.stringTo.toLowerCase(),/tablesorter\-/.test(i.attr("class"))||(a=""!==s.theme?" tablesorter-"+s.theme:""),s.table=r,s.$table=i.addClass(v.css.table+" "+s.tableClass+a).attr("role","grid"),s.$headers=i.find(s.selectorHeaders),s.namespace=s.namespace?"."+s.namespace.replace(/\W/g,""):".tablesorter"+Math.random().toString(16).slice(2),s.$table.children().children("tr").attr("role","row"),s.$tbodies=i.children("tbody:not(."+s.cssInfoBlock+")").attr({"aria-live":"polite","aria-relevant":"all"}),s.$table.children("caption").length&&(a=s.$table.children("caption")[0],a.id||(a.id=s.namespace.slice(1)+"caption"),s.$table.attr("aria-labelledby",a.id)),s.widgetInit={},s.textExtraction=s.$table.attr("data-text-extraction")||s.textExtraction||"basic",c(r),v.fixColumnWidth(r),n(r),s.totalRows=0,s.delayInit||o(r),v.bindEvents(r,s.$headers,!0),w(r),s.supportsDataObject&&"undefined"!=typeof i.data().sortlist?s.sortList=i.data().sortlist:d&&i.metadata()&&i.metadata().sortlist&&(s.sortList=i.metadata().sortlist),v.applyWidget(r,!0),s.sortList.length>0?i.trigger("sorton",[s.sortList,{},!s.initWidgets,!0]):(p(r),s.initWidgets&&v.applyWidget(r,!1)),s.showProcessing&&i.unbind("sortBegin"+s.namespace+" sortEnd"+s.namespace).bind("sortBegin"+s.namespace+" sortEnd"+s.namespace,function(e){clearTimeout(s.processTimer),v.isProcessing(r),"sortBegin"===e.type&&(s.processTimer=setTimeout(function(){v.isProcessing(r,!0)},500))}),r.hasInitialized=!0,r.isProcessing=!1,s.debug&&v.benchmark("Overall initialization time",e.data(r,"startoveralltimer")),i.trigger("tablesorter-initialized",r),"function"==typeof s.initialized&&s.initialized(r)},v.fixColumnWidth=function(t){t=e(t)[0];var r,s,a=t.config,n=a.$table.children("colgroup");n.length&&n.hasClass(v.css.colgroup)&&n.remove(),a.widthFixed&&0===a.$table.children("colgroup").length&&(n=e(''),r=a.$table.width(),a.$tbodies.find("tr:first").children(":visible").each(function(){s=parseInt(e(this).width()/r*1e3,10)/10+"%",n.append(e("").css("width",s))}),a.$table.prepend(n))},v.getColumnData=function(t,r,s,a,n){if("undefined"!=typeof r&&null!==r){t=e(t)[0];var o,i,d=t.config,c=n||d.$headers;if(r[s])return a?r[s]:r[c.index(c.filter('[data-column="'+s+'"]:last'))];for(i in r)if("string"==typeof i&&(o=c.filter('[data-column="'+s+'"]:last').filter(i).add(c.filter('[data-column="'+s+'"]:last').find(i)),o.length))return r[i]}},v.computeColumnIndex=function(t){var r,s,a,n,o,i,d,c,l,u,p,g,f,m=[],h={},b=0;for(r=0;ra;a++)for("undefined"==typeof m[a]&&(m[a]=[]),f=m[a],n=g;g+p>n;n++)f[n]="x"}return b+1},v.isProcessing=function(t,r,s){t=e(t);var a=t[0].config,n=s||t.find("."+v.css.header);r?("undefined"!=typeof s&&a.sortList.length>0&&(n=n.filter(function(){return this.sortDisabled?!1:v.isValueInArray(parseFloat(e(this).attr("data-column")),a.sortList)>=0})),t.add(n).addClass(v.css.processing+" "+a.cssProcessing)):t.add(n).removeClass(v.css.processing+" "+a.cssProcessing)},v.processTbody=function(t,r,s){t=e(t)[0];var a;return s?(t.isProcessing=!0,r.before(''),a=e.fn.detach?r.detach():r.remove()):(a=e(t).find("span.tablesorter-savemyplace"),r.insertAfter(a),a.remove(),void(t.isProcessing=!1))},v.clearTableBody=function(t){e(t)[0].config.$tbodies.children().detach()},v.bindEvents=function(t,r,a){t=e(t)[0];var n,i=t.config;a!==!0&&(i.$extraHeaders=i.$extraHeaders?i.$extraHeaders.add(r):r),r.find(i.selectorSort).add(r.filter(i.selectorSort)).unbind("mousedown mouseup sort keyup ".split(" ").join(i.namespace+" ").replace(/\s+/g," ")).bind("mousedown mouseup sort keyup ".split(" ").join(i.namespace+" "),function(a,d){var c,l=e(a.target),u=a.type;if(!(1!==(a.which||a.button)&&!/sort|keyup/.test(u)||"keyup"===u&&13!==a.which||"mouseup"===u&&d!==!0&&(new Date).getTime()-n>250)){if("mousedown"===u)return void(n=(new Date).getTime());if(c=e.fn.closest?l.closest("td,th"):l.parents("td,th").filter(":first"),/(input|select|button|textarea)/i.test(a.target.tagName)||l.hasClass(i.cssNoSort)||l.parents("."+i.cssNoSort).length>0||l.parents("button").length>0)return!i.cancelSelection;i.delayInit&&s(i.cache)&&o(t),c=e.fn.closest?e(this).closest("th, td")[0]:/TH|TD/.test(this.tagName)?this:e(this).parents("th, td")[0],c=i.$headers[r.index(c)],c.sortDisabled||m(t,c,a)}}),i.cancelSelection&&r.attr("unselectable","on").bind("selectstart",!1).css({"user-select":"none",MozUserSelect:"none"})},v.restoreHeaders=function(t){var r,s=e(t)[0].config;s.$table.find(s.selectorHeaders).each(function(t){r=e(this),r.find("."+v.css.headerIn).length&&r.html(s.headerContent[t])})},v.destroy=function(t,r,s){if(t=e(t)[0],t.hasInitialized){v.removeWidget(t,!0,!1);var a,n=e(t),o=t.config,i=n.find("thead:first"),d=i.find("tr."+v.css.headerRow).removeClass(v.css.headerRow+" "+o.cssHeaderRow),c=n.find("tfoot:first > tr").children("th, td");r===!1&&e.inArray("uitheme",o.widgets)>=0&&(n.trigger("applyWidgetId",["uitheme"]),n.trigger("applyWidgetId",["zebra"])),i.find("tr").not(d).remove(),a="sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache "+"applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState ".split(" ").join(o.namespace+" "),n.removeData("tablesorter").unbind(a.replace(/\s+/g," ")),o.$headers.add(c).removeClass([v.css.header,o.cssHeader,o.cssAsc,o.cssDesc,v.css.sortAsc,v.css.sortDesc,v.css.sortNone].join(" ")).removeAttr("data-column").removeAttr("aria-label").attr("aria-disabled","true"),d.find(o.selectorSort).unbind("mousedown mouseup keypress ".split(" ").join(o.namespace+" ").replace(/\s+/g," ")),v.restoreHeaders(t),n.toggleClass(v.css.table+" "+o.tableClass+" tablesorter-"+o.theme,r===!1),t.hasInitialized=!1,delete t.config.cache,"function"==typeof s&&s(t)}},v.regex={chunk:/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,chunks:/(^\\0|\\0$)/,hex:/^0x[0-9a-f]+$/i},v.sortNatural=function(e,t){if(e===t)return 0;var r,s,a,n,o,i,d,c,l=v.regex;if(l.hex.test(t)){if(s=parseInt(e.match(l.hex),16),n=parseInt(t.match(l.hex),16),n>s)return-1;if(s>n)return 1}for(r=e.replace(l.chunk,"\\0$1\\0").replace(l.chunks,"").split("\\0"),a=t.replace(l.chunk,"\\0$1\\0").replace(l.chunks,"").split("\\0"),c=Math.max(r.length,a.length),d=0;c>d;d++){if(o=isNaN(r[d])?r[d]||0:parseFloat(r[d])||0,i=isNaN(a[d])?a[d]||0:parseFloat(a[d])||0,isNaN(o)!==isNaN(i))return isNaN(o)?1:-1;if(typeof o!=typeof i&&(o+="",i+=""),i>o)return-1;if(o>i)return 1}return 0},v.sortNaturalAsc=function(e,t,r,s,a){if(e===t)return 0;var n=a.string[a.empties[r]||a.emptyTo];return""===e&&0!==n?"boolean"==typeof n?n?-1:1:-n||-1:""===t&&0!==n?"boolean"==typeof n?n?1:-1:n||1:v.sortNatural(e,t)},v.sortNaturalDesc=function(e,t,r,s,a){if(e===t)return 0;var n=a.string[a.empties[r]||a.emptyTo];return""===e&&0!==n?"boolean"==typeof n?n?-1:1:n||1:""===t&&0!==n?"boolean"==typeof n?n?1:-1:-n||-1:v.sortNatural(t,e)},v.sortText=function(e,t){return e>t?1:t>e?-1:0},v.getTextValue=function(e,t,r){if(r){var s,a=e?e.length:0,n=r+t;for(s=0;a>s;s++)n+=e.charCodeAt(s);return t*n}return 0},v.sortNumericAsc=function(e,t,r,s,a,n){if(e===t)return 0;var o=n.config,i=o.string[o.empties[a]||o.emptyTo];return""===e&&0!==i?"boolean"==typeof i?i?-1:1:-i||-1:""===t&&0!==i?"boolean"==typeof i?i?1:-1:i||1:(isNaN(e)&&(e=v.getTextValue(e,r,s)),isNaN(t)&&(t=v.getTextValue(t,r,s)),e-t)},v.sortNumericDesc=function(e,t,r,s,a,n){if(e===t)return 0;var o=n.config,i=o.string[o.empties[a]||o.emptyTo];return""===e&&0!==i?"boolean"==typeof i?i?-1:1:i||1:""===t&&0!==i?"boolean"==typeof i?i?1:-1:-i||-1:(isNaN(e)&&(e=v.getTextValue(e,r,s)),isNaN(t)&&(t=v.getTextValue(t,r,s)),t-e)},v.sortNumeric=function(e,t){return e-t},v.characterEquivalents={a:"áàâãäąå",A:"ÁÀÂÃÄĄÅ",c:"çćč",C:"ÇĆČ",e:"éèêëěę",E:"ÉÈÊËĚĘ",i:"íìİîïı",I:"ÍÌİÎÏ",o:"óòôõö",O:"ÓÒÔÕÖ",ss:"ß",SS:"ẞ",u:"úùûüů",U:"ÚÙÛÜŮ"},v.replaceAccents=function(e){var t,r="[",s=v.characterEquivalents;if(!v.characterRegex){v.characterRegexArray={};for(t in s)"string"==typeof t&&(r+=s[t],v.characterRegexArray[t]=new RegExp("["+s[t]+"]","g"));v.characterRegex=new RegExp(r+"]")}if(v.characterRegex.test(e))for(t in s)"string"==typeof t&&(e=e.replace(v.characterRegexArray[t],t));return e},v.isValueInArray=function(e,t){var r,s=t.length;for(r=0;s>r;r++)if(t[r][0]===e)return r;return-1},v.addParser=function(e){var t,r=v.parsers.length,s=!0;for(t=0;r>t;t++)v.parsers[t].id.toLowerCase()===e.id.toLowerCase()&&(s=!1);s&&v.parsers.push(e)},v.getParserById=function(e){if("false"==e)return!1;var t,r=v.parsers.length;for(t=0;r>t;t++)if(v.parsers[t].id.toLowerCase()===e.toString().toLowerCase())return v.parsers[t];return!1},v.addWidget=function(e){v.widgets.push(e)},v.hasWidget=function(t,r){return t=e(t),t.length&&t[0].config&&t[0].config.widgetInit[r]||!1},v.getWidgetById=function(e){var t,r,s=v.widgets.length;for(t=0;s>t;t++)if(r=v.widgets[t],r&&r.hasOwnProperty("id")&&r.id.toLowerCase()===e.toLowerCase())return r},v.applyWidget=function(t,s,a){t=e(t)[0];var n,o,i,d,c=t.config,l=c.widgetOptions,u=" "+c.table.className+" ",p=[];s!==!1&&t.hasInitialized&&(t.isApplyingWidgets||t.isUpdating)||(c.debug&&(n=new Date),d=new RegExp("\\s"+c.widgetClass.replace(/\{name\}/i,"([\\w-]+)")+"\\s","g"),u.match(d)&&(i=u.match(d),i&&e.each(i,function(e,t){c.widgets.push(t.replace(d,"$1"))})),c.widgets.length&&(t.isApplyingWidgets=!0,c.widgets=e.grep(c.widgets,function(t,r){return e.inArray(t,c.widgets)===r}),e.each(c.widgets||[],function(e,t){d=v.getWidgetById(t),d&&d.id&&(d.priority||(d.priority=10),p[e]=d)}),p.sort(function(e,t){return e.priorityn;n++)o=v.getWidgetById(s[n]),i=e.inArray(s[n],d.widgets),o&&"remove"in o&&(d.debug&&i>=0&&t('Removing "'+s[n]+'" widget'),o.remove(r,d,d.widgetOptions,a),d.widgetInit[s[n]]=!1),i>=0&&a!==!0&&d.widgets.splice(i,1)},v.refreshWidgets=function(t,r,s){t=e(t)[0];var a=t.config,n=a.widgets,o=[],i=function(t){e(t).trigger("refreshComplete")};e.each(v.widgets,function(t,s){s&&s.id&&(r||e.inArray(s.id,n)<0)&&o.push(s.id)}),v.removeWidget(t,o.join(","),!0),s!==!0?(v.applyWidget(t,r||!1,i),r&&v.applyWidget(t,!1,i)):i(t)},v.getData=function(t,r,s){var a,n,o="",i=e(t);return i.length?(a=e.metadata?i.metadata():!1,n=" "+(i.attr("class")||""),"undefined"!=typeof i.data(s)||"undefined"!=typeof i.data(s.toLowerCase())?o+=i.data(s)||i.data(s.toLowerCase()):a&&"undefined"!=typeof a[s]?o+=a[s]:r&&"undefined"!=typeof r[s]?o+=r[s]:" "!==n&&n.match(" "+s+"-")&&(o=n.match(new RegExp("\\s"+s+"-([\\w-]+)"))[1]||""),e.trim(o)):""},v.formatFloat=function(t,r){if("string"!=typeof t||""===t)return t;var s,a=r&&r.config?r.config.usNumberFormat!==!1:"undefined"!=typeof r?r:!0;return t=a?t.replace(/,/g,""):t.replace(/[\s|\.]/g,"").replace(/,/g,"."),/^\s*\([.\d]+\)/.test(t)&&(t=t.replace(/^\s*\(([.\d]+)\)/,"-$1")),s=parseFloat(t),isNaN(s)?e.trim(t):s},v.isDigit=function(e){return isNaN(e)?/^[\-+(]?\d+[)]?$/.test(e.toString().replace(/[,.'"\s]/g,"")):!0}}});var t=e.tablesorter;return e.fn.extend({tablesorter:t.construct}),t.addParser({id:"no-parser",is:function(){return!1},format:function(){return""},type:"text"}),t.addParser({id:"text",is:function(){return!0},format:function(r,s){var a=s.config;return r&&(r=e.trim(a.ignoreCase?r.toLocaleLowerCase():r),r=a.sortLocaleCompare?t.replaceAccents(r):r),r},type:"text"}),t.addParser({id:"digit",is:function(e){return t.isDigit(e)},format:function(r,s){var a=t.formatFloat((r||"").replace(/[^\w,. \-()]/g,""),s);return r&&"number"==typeof a?a:r?e.trim(r&&s.config.ignoreCase?r.toLocaleLowerCase():r):r},type:"numeric"}),t.addParser({id:"currency",is:function(e){return/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/.test((e||"").replace(/[+\-,. ]/g,""))},format:function(r,s){var a=t.formatFloat((r||"").replace(/[^\w,. \-()]/g,""),s);return r&&"number"==typeof a?a:r?e.trim(r&&s.config.ignoreCase?r.toLocaleLowerCase():r):r},type:"numeric"}),t.addParser({id:"url",is:function(e){return/^(https?|ftp|file):\/\//.test(e)},format:function(t){return t?e.trim(t.replace(/(https?|ftp|file):\/\//,"")):t},parsed:!0,type:"text"}),t.addParser({id:"isoDate",is:function(e){return/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/.test(e)},format:function(e){var t=e?new Date(e.replace(/-/g,"/")):e;return t instanceof Date&&isFinite(t)?t.getTime():e},type:"numeric"}),t.addParser({id:"percent",is:function(e){return/(\d\s*?%|%\s*?\d)/.test(e)&&e.length<15},format:function(e,r){return e?t.formatFloat(e.replace(/%/g,""),r):e},type:"numeric"}),t.addParser({id:"image",is:function(e,t,r,s){return s.find("img").length>0},format:function(t,r,s){return e(s).find("img").attr(r.config.imgAttr||"alt")||t},parsed:!0,type:"text"}),t.addParser({id:"usLongDate",is:function(e){return/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i.test(e)||/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i.test(e)},format:function(e){var t=e?new Date(e.replace(/(\S)([AP]M)$/i,"$1 $2")):e;return t instanceof Date&&isFinite(t)?t.getTime():e},type:"numeric"}),t.addParser({id:"shortDate",is:function(e){return/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/.test((e||"").replace(/\s+/g," ").replace(/[\-.,]/g,"/"))},format:function(e,r,s,a){if(e){var n,o,i=r.config,d=i.$headers.filter('[data-column="'+a+'"]:last'),c=d.length&&d[0].dateFormat||t.getData(d,t.getColumnData(r,i.headers,a),"dateFormat")||i.dateFormat;return o=e.replace(/\s+/g," ").replace(/[\-.,]/g,"/"),"mmddyyyy"===c?o=o.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$1/$2"):"ddmmyyyy"===c?o=o.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/,"$3/$2/$1"):"yyyymmdd"===c&&(o=o.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/,"$1/$2/$3")),n=new Date(o),n instanceof Date&&isFinite(n)?n.getTime():e}return e},type:"numeric"}),t.addParser({id:"time",is:function(e){return/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i.test(e)},format:function(e){var t=e?new Date("2000/01/01 "+e.replace(/(\S)([AP]M)$/i,"$1 $2")):e;return t instanceof Date&&isFinite(t)?t.getTime():e},type:"numeric"}),t.addParser({id:"metadata",is:function(){return!1 +},format:function(t,r,s){var a=r.config,n=a.parserMetadataName?a.parserMetadataName:"sortValue";return e(s).metadata()[n]},type:"numeric"}),t.addWidget({id:"zebra",priority:90,format:function(t,r,s){var a,n,o,i,d,c,l,u=new RegExp(r.cssChildRow,"i"),p=r.$tbodies;for(r.debug&&(c=new Date),l=0;l Date: Fri, 3 Sep 2021 10:18:59 +0800 Subject: [PATCH 013/304] * use tablesorter-noSort to ignore sort on click checkbox. --- module/execution/view/linkstory.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/linkstory.html.php b/module/execution/view/linkstory.html.php index 18f5ccfd2e..67c336039f 100644 --- a/module/execution/view/linkstory.html.php +++ b/module/execution/view/linkstory.html.php @@ -33,7 +33,7 @@ -
          +
          From d6ef27f843b837fc5aedd414d681f90c30809515 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 10:26:46 +0800 Subject: [PATCH 014/304] * show tid information on footer for debug. --- module/common/view/footer.html.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/module/common/view/footer.html.php b/module/common/view/footer.html.php index 181a345024..6761afdfc1 100755 --- a/module/common/view/footer.html.php +++ b/module/common/view/footer.html.php @@ -65,8 +65,14 @@ $extHookRule = $extPath . 'footer.*.hook.php'; $extHookFiles = glob($extHookRule); if($extHookFiles) foreach($extHookFiles as $extHookFile) include $extHookFile; ?> -debug): ?> - +debug > 2 and $config->tabSession): ?> +
          +tsid= + +tid= + +sid= +
          From 770bcbbae15dc42fb28f006c6782d93b6e1e8bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Fri, 3 Sep 2021 10:58:41 +0800 Subject: [PATCH 015/304] * adjust for session_set_save_handler condition. --- framework/base/router.class.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index ab502399e8..91323a6ddd 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -855,15 +855,18 @@ class baseRouter { if(defined('SESSION_STARTED')) return; - $ztSessionHandler = new ztSessionHandler(zget($_GET, 'tid', '')); - session_set_save_handler( - array($ztSessionHandler, "open"), - array($ztSessionHandler, "close"), - array($ztSessionHandler, "read"), - array($ztSessionHandler, "write"), - array($ztSessionHandler, "destroy"), - array($ztSessionHandler, "gc") - ); + if(ini_get('session.save_handler') == 'files') + { + $ztSessionHandler = new ztSessionHandler(zget($_GET, 'tid', '')); + session_set_save_handler( + array($ztSessionHandler, "open"), + array($ztSessionHandler, "close"), + array($ztSessionHandler, "read"), + array($ztSessionHandler, "write"), + array($ztSessionHandler, "destroy"), + array($ztSessionHandler, "gc") + ); + } /* If request header has token, use it as session for authentication. */ if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); From 37533710c15a2e6b76f1e1e23f2ff8f5530f5de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Fri, 3 Sep 2021 11:02:22 +0800 Subject: [PATCH 016/304] * set session save_handler. --- framework/base/router.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 91323a6ddd..c3e171fae5 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2651,6 +2651,7 @@ class ztSessionHandler public function __construct($tagID = '') { $this->tagID = $tagID; + ini_set('session.save_handler', 'files'); } /** @@ -2680,6 +2681,7 @@ class ztSessionHandler */ public function open($savePath, $sessionName) { + ini_set('session.save_path', $savePath); $this->sessSavePath = $savePath; return true; } From 7065da1c32d208c789c5a1ef18d64e56a8815fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Fri, 3 Sep 2021 11:04:01 +0800 Subject: [PATCH 017/304] * fix error. --- framework/base/router.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index c3e171fae5..31eb60dd8f 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2681,7 +2681,6 @@ class ztSessionHandler */ public function open($savePath, $sessionName) { - ini_set('session.save_path', $savePath); $this->sessSavePath = $savePath; return true; } From 9634713c392e0ad6ec88439ce42d4250fc4038da Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 11:45:56 +0800 Subject: [PATCH 018/304] * improve independent tab session. --- module/common/view/footer.html.php | 4 +- module/index/js/index.js | 9 ++- www/js/my.full.js | 103 ++++++++++++++--------------- www/js/zui/min.js | 6 +- 4 files changed, 62 insertions(+), 60 deletions(-) diff --git a/module/common/view/footer.html.php b/module/common/view/footer.html.php index 6761afdfc1..3f147a64f4 100755 --- a/module/common/view/footer.html.php +++ b/module/common/view/footer.html.php @@ -66,10 +66,10 @@ $extHookFiles = glob($extHookRule); if($extHookFiles) foreach($extHookFiles as $extHookFile) include $extHookFile; ?> debug > 2 and $config->tabSession): ?> -
          +
          tsid= -tid= +servertid= sid=
          diff --git a/module/index/js/index.js b/module/index/js/index.js index 5ab4925532..1979485b27 100644 --- a/module/index/js/index.js +++ b/module/index/js/index.js @@ -27,6 +27,12 @@ { if(item === 'divider') return $menuMainNav.append('
        • '); + /* Append tid param to app url */ + if($.tabSession && item.url) + { + item.url = $.tabSession.convertUrlWithTid(item.url); + } + var $link= $('
          ') .attr('data-app', item.code) .attr('data-toggle', 'tooltip') @@ -404,8 +410,9 @@ if(!app) return; if(url === true) url = app.url; - var iframe = app.$iframe[0]; + else if($.tabSession) url = $.tabSession.convertUrlWithTid(url); + var iframe = app.$iframe[0]; try { if(url) iframe.contentWindow.location.assign(url); diff --git a/www/js/my.full.js b/www/js/my.full.js index 5749bc7ddb..81ec49bcbe 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -4,10 +4,7 @@ if(!config.tabSession) return; /** Store current tab id */ - var _tid; - - /** Store tab id for new window */ - var _newTid; + var _tid = ''; /** * Get current tab id @@ -15,41 +12,54 @@ */ function getTid(){return _tid;} - /** - * Get tab id for new window - * @returns {string} Tab id - */ - function getNewTid(){return _newTid;} - /** * Convert url with tab id - * @param {string} url + * @param {string} url + * @param {string} [tid] + * @param {boolean} [force] * @returns {string} Tab id */ - function convertUrlWithNewTid(url) + function convertUrlWithTid(url, tid, force) { - var link = $.parseLink(url); - var linkTid = link.tid || ''; + var link = $.parseLink(url); + if(!link.moduleName) return url; - if(linkTid === _newTid) return url; + tid = tid || _tid; + if(!force && link.tid === tid) return url; - link.tid = _newTid; + link.tid = tid; return $.createLink(link); } /** Init */ function init() { - var link = $.parseLink(window.location.href); + /* Check tid when open index page */ + if(config.currentModule === 'index' && config.currentMethod === 'index') + { + _tid = sessionStorage.getItem('TID'); + if(!_tid) + { + var link = $.parseLink(window.location.href); + _tid = link.tid - _tid = link.tid !== undefined ? link.tid : ''; - _newTid = $.zui.uuid(); - _newTid = _newTid.substr(_newTid.length - 8); + if(!_tid) + { + _tid = $.zui.uuid(); + _tid = _tid.substr(_tid.length - 8); + } + } + sessionStorage.setItem('TID', _tid); + } + else if(window.parent !== window) + { + _tid = window.parent.$.tabSession.getTid(); + } $.tabSession = { - getTid: getTid, - getNewTid: getNewTid, + getTid: getTid, + convertUrlWithTid: convertUrlWithTid, }; @@ -58,42 +68,27 @@ $('a').each(function() { var $a = $(this); - var href = $a.attr('href'); - if(href.indexOf(origin) !== 0) return; - var link = $.parseLink(href); - var linkTid = link.tid || ''; - if(_tid && _tid !== linkTid) - { - link.tid = _tid; - href = $.createLink(link); - $a.attr('href', href); - } + var url = $a.attr('href'); + var urlWithTid = convertUrlWithTid(url); + if(urlWithTid !== url) $a.attr('href', urlWithTid); + }); + $('[data-url]').each(function() + { + var $e = $(this); + var url = $e.attr('data-url'); + var urlWithTid = convertUrlWithTid(url); + if(urlWithTid !== url) $e.attr('data-url', urlWithTid); }); - /* Init custom context menu for links */ - $(document).contextmenu( + if(config.debug > 2) { - selector: 'a', - items: function(options) + console.log(document.title || location.href, 'tid', _tid); + + $(function() { - var $a = $(options.event.target).closest('a'); - if(!$a.length) return; - var href = $a.attr('href'); - return [ - { - label: '打开', - url: href, - }, { - label: '在新标签页中打开', - onClick: function() - { - console.log('convertUrlWithNewTid(href)', convertUrlWithNewTid(href)); - window.open(convertUrlWithNewTid(href), '_blank'); - } - } - ]; - } - }); + $('#tid').prepend('localtid=' + _tid + ''); + }); + } } init(); diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 433ee0d9d8..2b50790a7c 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao - v1.9.2 - 2021-08-31 + * ZUI: ZUI for Zentao - v1.9.2 - 2021-09-03 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2021 cnezsoft.com; Licensed MIT @@ -75,5 +75,5 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,h=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t){"use strict";function e(e,i){if(e===!1)return e;if(!e)return i;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var n;return Array.isArray(e)&&(n={},t.each(e,function(e,i){t.isPlainObject(i)?n[i.action]=i:n[i]=!0}),e=n),t.isPlainObject(e)&&(n={},t.each(e,function(e,i){i?n[e]=t.extend({type:e},s[e],t.isPlainObject(i)?i:null):n[e]=!1}),e=n),i?t.extend(!0,{},i,e):e}function i(e,i,n){return i=i||e.type,t(n||e.template).addClass("tree-action").attr(t.extend({"data-type":i,title:e.title||""},e.attr)).data("action",e)}var n="zui.tree",o=0,a=function(e,i){this.name=n,this.$=t(e),this.getOptions(i),this._init()},s={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};a.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},a.prototype.add=function(e,i,n,o,a){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
          ");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),h=l.find("#"+o).closest('[data-ride="table"],#'+a);if(h.length){var c=h.find(".table-statistic");c.length&&(i.defaultStatistic=c.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=h.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(f){console.error(f)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var p=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(p.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n; -o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime
          ').append(t('
          ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');if(!c.length)return void l--;r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||g.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
          ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
          ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
          '+(n.errorText||window.lang&&window.lang.timeout)+"
          "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
          ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&(l?"$new"===l&&(l=t.tabSession.getNewTid()):l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
          {page}/{totalPage}
          ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width()); -})}}else{var o=t("
          ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime
          ').append(t('
          ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');if(!c.length)return void l--;r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||g.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
          ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
          ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
          '+(n.errorText||window.lang&&window.lang.timeout)+"
          "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
          ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
          {page}/{totalPage}
          ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
          ").addClass(n.attr("class")),l=e.clone(),r=l.find("th"); +e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file From 258fd07e538b2f4e3185891fdda0d75ae336cc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Fri, 3 Sep 2021 13:10:17 +0800 Subject: [PATCH 019/304] * remove tid param for requestType is GET. --- framework/base/router.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 31eb60dd8f..da79e733fa 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -1857,6 +1857,7 @@ class baseRouter /* Remove these three params. */ unset($passedParams['onlybody']); + unset($passedParams['tid']); unset($passedParams['HTTP_X_REQUESTED_WITH']); /* Check params from URL. */ From e36992782ee0e8c73c954d0a6d3cc9d3db38d2ca Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 13:27:32 +0800 Subject: [PATCH 020/304] * fix js error when output open var. --- module/index/view/index.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/index/view/index.html.php b/module/index/view/index.html.php index a7d36a5555..65852fc168 100644 --- a/module/index/view/index.html.php +++ b/module/index/view/index.html.php @@ -17,7 +17,7 @@ if(!empty($config->sso->redirect)) js::set('ssoRedirect', $config->sso->redirect js::set('navGroup', $lang->navGroup); js::set('appsLang', $lang->index->app); js::set('appsMenuItems', commonModel::getMainNavList($app->rawModule)); -js::set('defaultOpen', $open); +js::set('defaultOpen', (isset($open) and !empty($open)) ? $open : ''); js::set('manualText', $lang->manual); js::set('manualUrl', ((!empty($config->isINT)) ? $config->manualUrl['int'] : $config->manualUrl['home']) . '&theme=' . $_COOKIE['theme']); ?> From f8d862e0bb4bbb92d6f9c1d969c33566c26ddd4d Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 13:27:46 +0800 Subject: [PATCH 021/304] * refactor tab session. --- www/js/my.full.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index 81ec49bcbe..b9cc3d3b9a 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -1,5 +1,5 @@ /* Tab session */ -(function($, undefined) +(function($) { if(!config.tabSession) return; @@ -34,8 +34,12 @@ /** Init */ function init() { - /* Check tid when open index page */ - if(config.currentModule === 'index' && config.currentMethod === 'index') + /* Check tid */ + if(window.parent !== window) + { + if(window.parent.$.tabSession) _tid = window.parent.$.tabSession.getTid(); + } + else { _tid = sessionStorage.getItem('TID'); if(!_tid) @@ -51,10 +55,6 @@ } sessionStorage.setItem('TID', _tid); } - else if(window.parent !== window) - { - _tid = window.parent.$.tabSession.getTid(); - } $.tabSession = { @@ -64,18 +64,18 @@ /* Handle all links in page */ - var origin = window.location.origin; $('a').each(function() { - var $a = $(this); - var url = $a.attr('href'); + var $a = $(this); + var url = $a.attr('href'); var urlWithTid = convertUrlWithTid(url); + if(urlWithTid !== url) $a.attr('href', urlWithTid); }); $('[data-url]').each(function() { - var $e = $(this); - var url = $e.attr('data-url'); + var $e = $(this); + var url = $e.attr('data-url'); var urlWithTid = convertUrlWithTid(url); if(urlWithTid !== url) $e.attr('data-url', urlWithTid); }); @@ -92,7 +92,7 @@ } init(); -}(jQuery, undefined)); +}(jQuery)); /** * Set the ping url. From 88c9ccfc8e560155b6ae0f99795ef1f7c2007226 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 13:53:11 +0800 Subject: [PATCH 022/304] * remove tid at login page. --- www/js/my.full.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index b9cc3d3b9a..1b699d7e48 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -39,7 +39,7 @@ { if(window.parent.$.tabSession) _tid = window.parent.$.tabSession.getTid(); } - else + else if(config.currentModule === 'index' && config.currentMethod === 'index') { _tid = sessionStorage.getItem('TID'); if(!_tid) @@ -55,6 +55,11 @@ } sessionStorage.setItem('TID', _tid); } + else if(config.currentModule === 'user' && config.currentMethod === 'login') + { + /* Remove tid at login page */ + sessionStorage.removeItem('TID'); + } $.tabSession = { From a5dc5d5dce2e563b73a28aaa6fb52822b6bd7a1f Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 3 Sep 2021 17:38:58 +0800 Subject: [PATCH 023/304] * set tid in login page. --- www/js/my.full.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index 1b699d7e48..8f7a503fbd 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -39,7 +39,7 @@ { if(window.parent.$.tabSession) _tid = window.parent.$.tabSession.getTid(); } - else if(config.currentModule === 'index' && config.currentMethod === 'index') + else if((config.currentModule === 'index' && config.currentMethod === 'index') || (config.currentModule === 'user' && config.currentMethod === 'login')) { _tid = sessionStorage.getItem('TID'); if(!_tid) @@ -55,11 +55,6 @@ } sessionStorage.setItem('TID', _tid); } - else if(config.currentModule === 'user' && config.currentMethod === 'login') - { - /* Remove tid at login page */ - sessionStorage.removeItem('TID'); - } $.tabSession = { From db73472ba74b04b35d3e7d22d08cf5ac256f4a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Sat, 4 Sep 2021 12:56:17 +0800 Subject: [PATCH 024/304] * add tabSession config and add get sessionid method. --- config/config.php | 1 + framework/base/router.class.php | 54 +++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/config/config.php b/config/config.php index 8cc12bba49..5dccd9932e 100644 --- a/config/config.php +++ b/config/config.php @@ -22,6 +22,7 @@ $config->cookieLife = time() + 2592000; // Cookie的生存时间。The co $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. $config->webRoot = ''; // URL根目录。 The root path of the url. $config->customSession = false; // 是否开启自定义session的存储路径。Whether custom the session save path. +$config->tabSession = true; // 是否开启浏览器新标签独立session. /* 框架路由相关设置。Routing settings. */ $config->requestType = 'PATH_INFO'; // 请求类型:PATH_INFO|PATHINFO2|GET。 The request type: PATH_INFO|PATH_INFO2|GET. diff --git a/framework/base/router.class.php b/framework/base/router.class.php index da79e733fa..9dca2e5075 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -855,17 +855,29 @@ class baseRouter { if(defined('SESSION_STARTED')) return; - if(ini_get('session.save_handler') == 'files') + if(ini_get('session.save_handler') == 'files' and isset($_GET['tid'])) { - $ztSessionHandler = new ztSessionHandler(zget($_GET, 'tid', '')); - session_set_save_handler( - array($ztSessionHandler, "open"), - array($ztSessionHandler, "close"), - array($ztSessionHandler, "read"), - array($ztSessionHandler, "write"), - array($ztSessionHandler, "destroy"), - array($ztSessionHandler, "gc") - ); + $savePath = ini_get('session.save_path'); + $writable = is_writable($savePath); + if(!$writable) + { + $savePath = $this->getTmpRoot() . 'session'; + if(!file_exists($savePath) and !mkdir($savePath, 0777, true)) $writable = true; + if($writable) session_save_path($this->getTmpRoot() . 'session'); + } + + if($writable) + { + $ztSessionHandler = new ztSessionHandler($_GET['tid']); + session_set_save_handler( + array($ztSessionHandler, "open"), + array($ztSessionHandler, "close"), + array($ztSessionHandler, "read"), + array($ztSessionHandler, "write"), + array($ztSessionHandler, "destroy"), + array($ztSessionHandler, "gc") + ); + } } /* If request header has token, use it as session for authentication. */ @@ -877,7 +889,7 @@ class baseRouter if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session'); session_start(); - $this->sessionID = session_id(); + $this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id(); if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]); @@ -2641,6 +2653,7 @@ class ztSessionHandler public $sessSavePath; public $tagID; public $sessionFile; + public $sessionID; /** * Construct. @@ -2655,6 +2668,17 @@ class ztSessionHandler ini_set('session.save_handler', 'files'); } + /** + * Get sessionID + * + * @access public + * @return string + */ + public function getSessionID() + { + return $this->sessionID; + } + /** * Get session file. * @@ -2666,9 +2690,13 @@ class ztSessionHandler { if(!empty($this->sessionFile)) return $this->sessionFile; - $fileName = "sess_$id"; - if($this->tagID) $fileName = "sess_" . md5($id . $this->tagID); + $sessionID = $id; + if($this->tagID) $sessionID = md5($id . $this->tagID); + + $fileName = "sess_$sessionID"; + $this->sessionFile = $this->sessSavePath . '/' . $fileName; + $this->sessionID = $sessionID; return $this->sessionFile; } From 96eea18e3a4e3026bcde10f4b276d51aa564a3bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Thu, 9 Sep 2021 16:36:01 +0800 Subject: [PATCH 025/304] * adjust for tid. --- framework/router.class.php | 10 ++++++---- module/user/control.php | 1 + www/js/my.full.js | 4 +++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/framework/router.class.php b/framework/router.class.php index 07f5135d4c..3ecd8d357b 100755 --- a/framework/router.class.php +++ b/framework/router.class.php @@ -597,13 +597,15 @@ class router extends baseRouter */ public function getURI($full = false) { - $URI = !empty($this->rawURI) ? $this->rawURI : $this->URI; + $URI = !empty($this->rawURI) ? $this->rawURI : $this->URI; + $tidParam = ($this->config->requestType == 'PATH_INFO' and helper::isWithTID()) ? "?tid={$_GET['tid']}" : ''; + if($full and $this->config->requestType == 'PATH_INFO') { - if($URI) return $this->config->webRoot . $URI . '.' . $this->viewType; - return $this->config->webRoot; + if($URI) return $this->config->webRoot . $URI . '.' . $this->viewType . $tidParam; + return $this->config->webRoot . $tidParam; } - return $URI; + return $URI . $tidParam; } /** diff --git a/module/user/control.php b/module/user/control.php index c2330563f2..9306da2247 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -487,6 +487,7 @@ class user extends control { $this->referer = $this->server->http_referer ? $this->server->http_referer: ''; if(!empty($referer)) $this->referer = helper::safe64Decode($referer); + if($this->post->referer) $this->referer = $this->post->referer; /* Build zentao link regular. */ $webRoot = $this->config->webRoot; diff --git a/www/js/my.full.js b/www/js/my.full.js index 8f7a503fbd..189f9c2a0c 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -54,6 +54,9 @@ } } sessionStorage.setItem('TID', _tid); + + var link = $.parseLink(window.location.href); + if(!link.tid) window.location.href = convertUrlWithTid(window.location.href, _tid); } $.tabSession = @@ -62,7 +65,6 @@ convertUrlWithTid: convertUrlWithTid, }; - /* Handle all links in page */ $('a').each(function() { From ae191bc5048f6990ff65968c1e138bcb02d5fdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Fri, 10 Sep 2021 08:53:15 +0800 Subject: [PATCH 026/304] * adjust for locate with tid link when not tid. --- www/js/my.full.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index 189f9c2a0c..c7aa0fe5bf 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -56,7 +56,10 @@ sessionStorage.setItem('TID', _tid); var link = $.parseLink(window.location.href); - if(!link.tid) window.location.href = convertUrlWithTid(window.location.href, _tid); + if(link.moduleName == config.currentModule && link.methodName == config.currentMethod && !link.tid) + { + window.location.href = convertUrlWithTid(window.location.href, _tid); + } } $.tabSession = From bcf627baa792e974f68a8e6a75b95051e1a85513 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 17 Sep 2021 13:08:01 +0800 Subject: [PATCH 027/304] * refactor. --- www/js/my.full.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index c7aa0fe5bf..2467e31671 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -42,9 +42,9 @@ else if((config.currentModule === 'index' && config.currentMethod === 'index') || (config.currentModule === 'user' && config.currentMethod === 'login')) { _tid = sessionStorage.getItem('TID'); + var link = $.parseLink(window.location.href); if(!_tid) { - var link = $.parseLink(window.location.href); _tid = link.tid if(!_tid) @@ -55,7 +55,6 @@ } sessionStorage.setItem('TID', _tid); - var link = $.parseLink(window.location.href); if(link.moduleName == config.currentModule && link.methodName == config.currentMethod && !link.tid) { window.location.href = convertUrlWithTid(window.location.href, _tid); From 059867d376cdf536e743e48461e09f9f44ab0662 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Fri, 17 Sep 2021 13:32:20 +0800 Subject: [PATCH 028/304] * fix tid not set when redirect from other pages. --- www/js/my.full.js | 13 +++++++++---- www/js/zui/min.js | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/www/js/my.full.js b/www/js/my.full.js index 2467e31671..f4847310af 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -39,13 +39,18 @@ { if(window.parent.$.tabSession) _tid = window.parent.$.tabSession.getTid(); } - else if((config.currentModule === 'index' && config.currentMethod === 'index') || (config.currentModule === 'user' && config.currentMethod === 'login')) + else { - _tid = sessionStorage.getItem('TID'); + var isIndexOrLoginPage = (config.currentModule === 'index' && config.currentMethod === 'index') || (config.currentModule === 'user' && config.currentMethod === 'login'); var link = $.parseLink(window.location.href); + + _tid = sessionStorage.getItem('TID'); if(!_tid) { - _tid = link.tid + if(link.tid && isIndexOrLoginPage) + { + _tid = link.tid + } if(!_tid) { @@ -55,7 +60,7 @@ } sessionStorage.setItem('TID', _tid); - if(link.moduleName == config.currentModule && link.methodName == config.currentMethod && !link.tid) + if(isIndexOrLoginPage && !link.tid) { window.location.href = convertUrlWithTid(window.location.href, _tid); } diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 2b50790a7c..047fc3003f 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao - v1.9.2 - 2021-09-03 + * ZUI: ZUI for Zentao - v1.9.2 - 2021-09-17 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2021 cnezsoft.com; Licensed MIT @@ -75,5 +75,5 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,h=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t){"use strict";function e(e,i){if(e===!1)return e;if(!e)return i;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var n;return Array.isArray(e)&&(n={},t.each(e,function(e,i){t.isPlainObject(i)?n[i.action]=i:n[i]=!0}),e=n),t.isPlainObject(e)&&(n={},t.each(e,function(e,i){i?n[e]=t.extend({type:e},s[e],t.isPlainObject(i)?i:null):n[e]=!1}),e=n),i?t.extend(!0,{},i,e):e}function i(e,i,n){return i=i||e.type,t(n||e.template).addClass("tree-action").attr(t.extend({"data-type":i,title:e.title||""},e.attr)).data("action",e)}var n="zui.tree",o=0,a=function(e,i){this.name=n,this.$=t(e),this.getOptions(i),this._init()},s={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};a.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},a.prototype.add=function(e,i,n,o,a){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
          ");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),h=l.find("#"+o).closest('[data-ride="table"],#'+a);if(h.length){var c=h.find(".table-statistic");c.length&&(i.defaultStatistic=c.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=h.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(f){console.error(f)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var p=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(p.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n; -o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
          ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');if(!c.length)return void l--;r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||g.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
          ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{onFinish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
          ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
          '+(n.errorText||window.lang&&window.lang.timeout)+"
          "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
          ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
          {page}/{totalPage}
          ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
          ").addClass(n.attr("class")),l=e.clone(),r=l.find("th"); -e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){const r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash,l="";return location.href=t.createLink("index","index",l)+"#app="+encodeURIComponent(r)}if(e!==window&&e.$.apps){o&&e.location.reload();var h=window.name;if(0===h.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=h.substr(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
          ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');if(!c.length)return void l--;r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||g.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
          ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{finish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
          ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
          '+(n.errorText||window.lang&&window.lang.timeout)+"
          "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
          ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
          {page}/{totalPage}
          ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th"); +e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
          ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
          ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){var r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search;return void(location.href=t.createLink("index","index","")+"#app="+encodeURIComponent(r))}if(e!==window&&e.$.apps){o&&e.location.reload();var l=window.name;if(0===l.indexOf("app-")){t.apps=window.apps=e.$.apps;var h=l.substr(4);t.appCode=h,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(h,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file From 14aa0e1b96077ae470500cc2cea8db0640b09113 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Wed, 22 Sep 2021 10:53:25 +0800 Subject: [PATCH 029/304] * fix $.parseLink not work with custom config.webRoot. --- www/js/zui/min.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 047fc3003f..fa1890c4fc 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao - v1.9.2 - 2021-09-17 + * ZUI: ZUI for Zentao - v1.9.2 - 2021-09-22 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2021 cnezsoft.com; Licensed MIT @@ -76,4 +76,4 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= */ function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,h=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t){"use strict";function e(e,i){if(e===!1)return e;if(!e)return i;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var n;return Array.isArray(e)&&(n={},t.each(e,function(e,i){t.isPlainObject(i)?n[i.action]=i:n[i]=!0}),e=n),t.isPlainObject(e)&&(n={},t.each(e,function(e,i){i?n[e]=t.extend({type:e},s[e],t.isPlainObject(i)?i:null):n[e]=!1}),e=n),i?t.extend(!0,{},i,e):e}function i(e,i,n){return i=i||e.type,t(n||e.template).addClass("tree-action").attr(t.extend({"data-type":i,title:e.title||""},e.attr)).data("action",e)}var n="zui.tree",o=0,a=function(e,i){this.name=n,this.$=t(e),this.getOptions(i),this._init()},s={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};a.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},a.prototype.add=function(e,i,n,o,a){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
            "),r.append(s),this._initList(s,r))):s=r,s){var h=this;Array.isArray(i)||(i=[i]),t.each(i,function(e,i){var n=t("
          • ").data(i).appendTo(s);void 0!==i.id&&n.attr("data-id",i.id);var o=l.itemWrapper?t(l.itemWrapper===!0?'
          • ').append(i(h.add,"add",h.add.templateInList)).appendTo(n)}h.sort&&n.sortable(t.extend({dragCssClass:"tree-drag-holder",trigger:".sort-handler",selector:"li:not(.tree-action-item)",finish:function(t){r.callEvent("action",{action:h.sort,$list:n,target:t.target,item:s})}},h.sort.options,t.isPlainObject(this.options.sortable)?this.options.sortable:null))}o&&(o.hasClass("open")||s&&s.open)&&o.addClass("open in")},a.prototype._initItem=function(n,o,a,s){if(void 0===o){var r=n.prev("li");o=r.length?r.data("idx")+1:1}if(a=a||n.closest("ul"),n.attr("data-idx",o).removeClass("tree-single-item"),!n.data("id")){var l=o;a.hasClass("tree")||(l=a.parent("li").data("id")+"-"+l),n.attr("data-id",l)}n.hasClass("active")&&a.parent("li").addClass("has-active-item"),s=s||n.data();var h=e(s.actions,this.actions);if(h){var c=n.find(".tree-actions");c.length||(c=t('
            ').appendTo(this.options.itemWrapper?n.find(".tree-item-wrapper"):n),t.each(h,function(t,e){e&&c.append(i(e,t))}))}var d=n.children("ul");d.length&&this._initList(d,n,o,s)},a.prototype._init=function(){var i=this.options,a=this;this.actions=e(i.actions),this.$.addClass("tree"),i.animate&&this.$.addClass("tree-animate"),this._initList(this.$);var s=i.initialState,r=t.zui&&t.zui.store&&t.zui.store.enable;r&&(this.selector=n+"::"+(i.name||"")+"#"+(this.$.attr("id")||o++),this.store=t.zui.store[i.name?"get":"pageGet"](this.selector,{})),"preserve"===s&&(r?this.isPreserve=!0:this.options.initialState=s="normal"),this.reload(i.data),r&&(this.isPreserve=!0),"expand"===s?this.expand():"collapse"===s?this.collapse():"active"===s&&this.expandSelect(".active"),this.$.on("click",'.list-toggle,a[href="#"],.tree-toggle',function(e){var i=t(this),n=i.parent("li");a.callEvent("hit",{target:n,item:n.data()}),a.toggle(n),i.is("a")&&e.preventDefault()}).on("click",".tree-action",function(){var e=t(this),i=e.data();if(i.action&&(i=i.action),"sort"!==i.type){var n=e.closest("li:not(.tree-action-item)");a.callEvent("action",{action:i,target:this,$item:n,item:n.data()})}})},a.prototype.preserve=function(e,i,n){if(this.isPreserve)if(e)i=i||e.data("id"),n=void 0===n&&e.hasClass("open"),n?this.store[i]=n:delete this.store[i],this.store.time=(new Date).getTime(),t.zui.store[this.options.name?"set":"pageSet"](this.selector,this.store);else{var o=this;this.store={},this.$.find("li").each(function(){o.preserve(t(this))})}},a.prototype.expandSelect=function(t){this.show(t,!0)},a.prototype.expand=function(t,e,i){t?(t.addClass("open"),!e&&this.options.animate?setTimeout(function(){t.addClass("in")},10):t.addClass("in")):t=this.$.find("li.has-list").addClass("open in"),i||this.preserve(t),this.callEvent("expand",t,this)},a.prototype.show=function(e,i,n){var o=this;e instanceof t||(e=o.$.find("li").filter(e)),e.each(function(){var e=t(this);if(o.expand(e,i,n),e)for(var a=e.parent("ul");a&&a.length&&!a.hasClass("tree");){var s=a.parent("li");s.length?(o.expand(s,i,n),a=s.parent("ul")):a=!1}})},a.prototype.collapse=function(t,e,i){t?!e&&this.options.animate?(t.removeClass("in"),setTimeout(function(){t.removeClass("open")},300)):t.removeClass("open in"):t=this.$.find("li.has-list").removeClass("open in"),i||this.preserve(t),this.callEvent("collapse",t,this)},a.prototype.toggle=function(t){var e=t&&t.hasClass("open")||t===!1||void 0===t&&this.$.find("li.has-list.open").length;this[e?"collapse":"expand"](t)},a.prototype.getOptions=function(e){this.options=t.extend({},a.DEFAULTS,this.$.data(),e),null===this.options.animate&&this.$.hasClass("tree-animate")&&(this.options.animate=!0)},a.prototype.toData=function(e,i){"function"==typeof e&&(i=e,e=null),e=e||this.$;var n=this;return e.children("li:not(.tree-action-item)").map(function(){var e=t(this),o=e.data();delete o["zui.droppable"];var a=e.children("ul");return a.length&&(o.children=n.toData(a)),"function"==typeof i?i(o,e):o}).get()},a.prototype.callEvent=function(e,i){var n;return"function"==typeof this.options[e]&&(n=this.options[e](i,this)),this.$.trigger(t.Event(e+"."+this.name,i)),n},t.fn.tree=function(e,i){return this.each(function(){var o=t(this),s=o.data(n),r="object"==typeof e&&e;s||o.data(n,s=new a(this,r)),"string"==typeof e&&s[e](i)})},t.fn.tree.Constructor=a,t(function(){t('[data-ride="tree"]').tree()})}(jQuery),function(t){"use strict";var e="zui.colorPicker",i='
            ',n={zh_cn:{errorTip:"不是有效的颜色值"},zh_tw:{errorTip:"不是有效的顏色值"},en:{errorTip:"Not a valid color value"}},o=function(i,n){this.name=e,this.$=t(i),this.getOptions(n),this.init()};o.prototype.init=function(){var e=this,n=e.options,o=e.$,a=o.parent(),s=!1;a.hasClass("colorpicker")?e.$picker=a:(e.$picker=t(n.template||i),s=!0),e.$picker.addClass(n.wrapper).find(".cp-title").toggle(void 0!==n.title).text(n.title),e.$menu=e.$picker.find(".dropdown-menu").toggleClass("pull-right",n.pullMenuRight),e.$btn=e.$picker.find(".btn.dropdown-toggle"),e.$btn.find(".ic").addClass("icon-"+n.icon),n.btnTip&&e.$picker.attr("data-toggle","tooltip").tooltip({title:n.btnTip,placement:n.tooltip,container:"body"}),o.attr("data-provide",null),s&&o.after(e.$picker),e.colors={},t.each(n.colors,function(i,n){if(t.zui.Color.isColor(n)){var o=new t.zui.Color(n);e.colors[o.toCssStr()]=o}}),e.updateColors(),e.$picker.on("click",".cp-tile",function(){e.setValue(t(this).data("color"))});var r=function(){var i=o.val(),a=t.zui.Color.isColor(i);o.parent().toggleClass("has-error",!(a||n.optional&&""===i)),a?e.setValue(i,!0):n.optional&&""===i?o.tooltip("hide"):o.is(":focus")||o.tooltip("show",n.errorTip)};o.is("input:not([type=hidden])")?(n.tooltip&&o.attr("data-toggle","tooltip").tooltip({trigger:"manual",placement:n.tooltip,tipClass:"tooltip-danger",container:"body"}),o.on("keyup paste input change",r)):o.appendTo(e.$picker),r()},o.prototype.addColor=function(e){e instanceof t.zui.Color||(e=new t.zui.Color(e));var i=e.toCssStr(),n=this.options;this.colors[i]||(this.colors[i]=e);var o=t('
            ',{titile:e}).data("color",e).css({color:e.contrast().toCssStr(),background:i,"border-color":e.luma()>.43?"#ccc":"transparent"}).attr("data-color",i);this.$menu.append(t("
          • ").css({width:n.tileSize,height:n.tileSize}).append(o)),n.optional&&this.$menu.find(".cp-tile.empty").parent().detach().appendTo(this.$menu)},o.prototype.updateColors=function(e){var i=this.$menu,n=this.options,e=e||this.colors,o=this,a=0;if(i.children("li:not(.heading)").remove(),t.each(e,function(t,e){o.addColor(e),a++}),n.optional){var s=t('
          • ').css({width:n.tileSize,height:n.tileSize});this.$menu.append(s),a++}i.css("width",Math.min(a,n.lineCount)*n.tileSize+6)},o.prototype.setValue=function(e,i){var n=this,o=n.options,a=n.$btn,s="";n.$menu.find(".cp-tile.active").removeClass("active");var r=o.updateBtn;if("auto"===r){var l=a.find(".color-bar");r=!l.length||function(t){l.css("background",t||"")}}if(e){var h=new t.zui.Color(e);s=h.toCssStr().toLowerCase(),r&&("function"==typeof r?r(s,a,n):a.css({background:s,color:h.contrast().toCssStr(),borderColor:h.luma()>.43?"#ccc":s})),n.colors[s]||n.addColor(h),i||n.$.val().toLowerCase()===s||n.$.val(s).trigger("change"),n.$menu.find('.cp-tile[data-color="'+s+'"]').addClass("active"),n.$.tooltip("hide"),n.$.trigger("colorchange",h)}else r&&("function"==typeof r?r(null,a,n):a.attr("style",null)),i||""===n.$.val()||n.$.val(s).trigger("change"),o.optional&&n.$.tooltip("hide"),n.$menu.find(".cp-tile.empty").addClass("active"),n.$.trigger("colorchange",null);o.updateBorder&&t(o.updateBorder).css("border-color",s),o.updateBackground&&t(o.updateBackground).css("background-color",s),o.updateColor&&t(o.updateColor).css("color",s),o.updateText&&t(o.updateText).text(s)},o.prototype.getOptions=function(i){var a=t.extend({},o.DEFAULTS,this.$.data(),i);"string"==typeof a.colors&&(a.colors=a.colors.split(","));var s=a.lang||t.zui.clientLang(),r=this.lang=t.zui.getLangData?t.zui.getLangData(e,s,n):n[s]||n.en;a.errorTip||(a.errorTip=r.errorTip),t.fn.tooltip||(a.btnTip=!1),this.options=a},o.DEFAULTS={colors:["#00BCD4","#388E3C","#3280fc","#3F51B5","#9C27B0","#795548","#F57C00","#F44336","#E91E63"],pullMenuRight:!0,wrapper:"btn-wrapper",tileSize:30,lineCount:5,optional:!0,tooltip:"top",icon:"caret-down",updateBtn:"auto"},o.LANG=n,t.fn.colorPicker=function(e){return this.each(function(){var i=t(this),n=i.data(name),a="object"==typeof e&&e;n||i.data(name,n=new o(this,a)),"string"==typeof e&&n[e]()})},t.fn.colorPicker.Constructor=o,t(function(){t('[data-provide="colorpicker"]').colorPicker()})}(jQuery),function(t,e){function i(t){return t===e&&(t=o+=1),a[t%a.length]}function n(e,i){var n=t(e);i=t.extend({percent:0,size:20,backColor:"#eee",color:"#00da88",borderColor:"#ccc",borderSize:1,rotate:-90,doughnut:8},n.data(),i);var o=i.percent,a=i.size;"string"==typeof o&&(o=Number.parseFloat(o,10)),"string"==typeof a&&(a=Number.parseFloat(a,10)),a=Math.floor(a);var s=a/2,r=3.14*s,l="http://www.w3.org/2000/svg",h=document.createElementNS(l,"svg"),c=document.createElementNS(l,"circle"),d=document.createElementNS(l,"circle"),u=document.createElementNS(l,"circle");d.setAttribute("r",s),d.setAttribute("cx",s),d.setAttribute("cy",s),d.setAttribute("fill",i.backColor),d.setAttribute("stroke",i.borderColor),d.setAttribute("stroke-width",i.borderSize),u.setAttribute("r",i.doughnut),u.setAttribute("cx",s),u.setAttribute("cy",s),u.setAttribute("fill",i.backColor),c.setAttribute("r",s/2),c.setAttribute("cx",s),c.setAttribute("cy",s),c.setAttribute("fill","transparent"),c.setAttribute("stroke-dasharray",(o*r/100).toFixed(1)+" "+r),c.setAttribute("stroke-width",s),c.setAttribute("stroke",i.color),c.setAttribute("transform","rotate(-90) translate(-"+a+")"),h.setAttribute("viewBox","0 0 "+a+" "+a),h.setAttribute("width",a),h.setAttribute("height",a),h.setAttribute("transform","rotate(180)"),h.appendChild(d),h.appendChild(c),h.appendChild(u),n[0].appendChild(h);var f={width:a,height:a};"inline"===n.css("display")&&(f.display="inline-block",f.verticalAlign="middle"),n.css(f)}var o=0,a=["#00a9fc","#ff5d5d","#fdc137","#00da88","#7ec5ff","#8666b8","#bd7b46","#ff9100","#ff3d00","#f57f17","#00e5ff","#00b0ff","#2979ff","#3d5afe","#651fff","#d500f9","#f50057","#ff1744"];jQuery.fn.tableChart=function(){t(this).each(function(){var e=t(this),n=e.data(),o=n.chart||"pie",a=t(n.target);if(a.length){var s=null;if("pie"===o){n=t.extend({scaleShowLabels:!0,scaleLabel:"<%=label%>: <%=value%>"},n);var r=[],l=e.find("tbody > tr").each(function(e){var n=t(this),o=i();n.attr("data-id",e).find(".chart-color-dot").css("background",o),r.push({label:n.find(".chart-label").text(),value:parseFloat(n.data("value")||n.find(".chart-value").text()),color:o,id:e})});r.length>1?n.scaleLabelPlacement="outside":1===r.length&&(n.scaleLabelPlacement="inside",r.push({label:"",value:r[0].value/2e3,color:"#fff",showLabel:!1})),s=a.pieChart(r,n),a.on("mousemove",function(t){var e=s.getSegmentsAtEvent(t);l.removeClass("active"),e.length&&l.filter('[data-id="'+e[0].id+'"]').addClass("active")})}else if("bar"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(i.data("value")||parseFloat(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.barChart(r,n)}else if("line"===o){var h=i(),c=[],d={label:e.find("thead .chart-label").text(),color:h,data:[]},l=e.find("tbody > tr").each(function(e){var i=t(this);c.push(i.find(".chart-label").text()),d.data.push(parseInt(i.find(".chart-value").text())),i.find(".chart-color-dot").css("background",h)}),r={labels:c,datasets:[d]};c.length&&(n.barValueSpacing=5),s=a.lineChart(r,n)}null!==s&&e.data("zui.chart",s)}})},t(".table-chart").tableChart();var s=function(i,n){var o=t(i);if(!o.data("pieChart")){var a=o.is("canvas")?o:o.find("canvas"),s=t.extend({value:0,color:t.getThemeColor("primary")||"#006af1",backColor:t.getThemeColor("pale")||"#E9F2FB",doughnut:!0,doughnutSize:85,width:20,height:20,showTip:!1,name:"",tipTemplate:"<%=value%>%",animation:"auto",realValue:parseFloat(o.find(".progress-value").text())},n,o.data()),r=a.length;r||(a=t("").appendTo(o)),a.attr("width")!==e?s.width=a.width():a.attr("width",s.width),a.attr("height")!==e?s.height=a.height():a.attr("height",s.height),r||8!=t.zui.browser.ie||G_vmlCanvasManager.initElement(a[0]),"auto"===s.animation&&(s.animation=s.width>30),o.addClass("progress-pie-"+s.width).css({width:s.width,height:s.height}),s.value=Math.max(0,Math.min(100,s.value));var l=[{value:s.value,label:s.name,color:s.color,circleBeginEnd:!0},{value:100-s.value,label:"",color:s.backColor}],h=a[s.doughnut?"doughnutChart":"pieChart"](l,t.extend({segmentShowStroke:!1,animation:s.animation,showTooltips:s.showTip,tooltipTemplate:s.tipTemplate,percentageInnerCutout:s.doughnutSize,reverseDrawOrder:!0,animationEasing:"easeInOutQuart",onAnimationProgress:s.realValue?function(t){o.find(".progress-value").text(Math.floor(s.realValue*t))}:e,onAnimationComplete:s.realValue?function(t){o.find(".progress-value").text(s.realValue)}:e},s.chartOptions));o.data("pieChart",h)}};jQuery.fn.progressPie=function(e){t(this).each(function(){var i=t(this);if(!i.closest(".hidden").length){var n=i.closest(".tab-pane");n.length&&!n.hasClass("active")?t('[data-toggle="tab"][data-target="#'+n.attr("id")+'"]').one("shown.zui.tab",function(){s(i,e)}):s(this,e)}})},t.fn.pieIcon=function(e){t(this).each(function(){n(this,e)})},t(function(){t(".table-chart").tableChart();var e=t(".progress-pie:visible");e.length<100&&t(".progress-pie:visible").progressPie(),setTimeout(function(){t(".progress-pie:visible").progressPie()},e.length>100?1e3:50),t(".pie-icon:visible").pieIcon()})}(jQuery,void 0),function(t){jQuery.fn.sparkline=function(e){t(this).each(function(){var i=t(this),n=t.extend({values:i.attr("values"),width:i.width()-4,height:i.height()-4},i.data(),e),o=n.height,a=[],s=n.width,r=n.values.split(","),l=0;for(var h in r){var c=parseFloat(r[h]);NaN!=c&&(a.push(c),l=Math.max(c,l))}var d=(Math.min(l,30),Math.min(s,Math.max(10,a.length*s/30))),u=i.children("canvas");u.length||(i.append(''),u=i.children("canvas")),u.attr("width",d).attr("height",o);var f={labels:a,datasets:[{fillColor:t.getThemeColor("pale")||"rgba(0,0,255,0.05)",strokeColor:t.getThemeColor("primary")||"#0054EC",pointColor:t.getThemeColor("secondary")||"rgba(255,136,0,1)",pointStrokeColor:"#fff",data:a}]},p={animation:!0,scaleOverride:!0,scaleStepWidth:Math.ceil(l/10),scaleSteps:10,scaleStartValue:0,showScale:!1,showTooltips:!1,pointDot:!1,scaleShowGridLines:!1,datasetStrokeWidth:1},g=t(u).lineChart(f,p);i.data("sparklineChart",g)})},t(function(){t(".sparkline").sparkline()})}(jQuery),function(t){t.fn.fixedDate=function(){return t(this).each(function(){var e=t(this).attr("autocomplete","off");"0000-00-00"==e.val()&&e.focus(function(){"0000-00-00"==e.val()&&e.val("").datetimepicker("update")}).blur(function(){""==e.val()&&e.val("0000-00-00")})})},window.datepickerOptions={language:t("html").attr("lang"),weekStart:1,todayBtn:1,autoclose:1,todayHighlight:1,startView:2,forceParse:0,showMeridian:1,format:"yyyy-mm-dd hh:ii",startDate:"1970-1-1"},t.extend(t.fn.datetimepicker.defaults,window.datepickerOptions),t(function(){var e={minView:2,format:"yyyy-mm-dd"},i={startView:1,minView:0,maxView:1,format:"hh:ii"},n={minView:3,startView:3,format:"yyyy-mm"};t(".datepicker-wrapper").click(function(){t(this).find(".form-date, .form-datetime, .form-time, .form-month").datetimepicker("show").focus()}),t.fn.datepicker=function(i){return this.datetimepicker(t.extend({},e,i))},t.fn.timepicker=function(e){return this.datetimepicker(t.extend({},i,e))},t.fn.monthpicker=function(e){return this.datetimepicker(t.extend({},n,e))},t.fn.datepickerAll=function(){return this.find(".form-datetime").fixedDate().datetimepicker(),this.find(".form-date").fixedDate().datepicker(),this.find(".form-time").fixedDate().timepicker(),this.find(".form-month").fixedDate().monthpicker(),this},t("body").datepickerAll()})}(jQuery),function(t){var e=function(e,i){i=t.extend({idStart:0,idEnd:9,chosen:!0,datetimepicker:!0,colorPicker:!0,hotkeys:!0},i,e.data());var n=e.find(".template");!n.length&&i.template&&(n=t(i.template));var o=0,a=0,s=function(t){t.is("select.chosen")?t.next(".chosen-container").find("input").focus():t.focus()},r=function(t){var i=e.find("[data-ctrl-index]:focus,.chosen-container-active").first();if(i.length){if(i.is(".chosen-container-active")){if(i.hasClass("chosen-with-drop")&&("down"===t||"up"===t))return;i=i.prev("select.chosen")}var n=i.data("ctrlIndex"),r=i.closest("tr").data("row");"down"===t?r0?r-=1:r=a-1:"left"===t?n>0?n-=1:n=o-1:"right"===t&&(n").html(s);return r.attr("data-row",e).addClass(n.attr("class")).removeClass("template"),i.rowCreator&&i.rowCreator(r,e,i),o?o.after(r):h.append(r),c(r),r};t.extend(l,{createRow:u,template:d});for(var f=i.idStart;f<=i.idEnd;++f)u(f)}else c(e);e.on("click",".btn-copy",function(){var e=t(this),i=t(e.data("copyFrom")).val(),n=t(e.data("copyTo")).val(i).addClass("highlight");setTimeout(function(){n.removeClass("highlight")},2e3)}),i.hotkeys&&t(document).on("keydown",function(t){var e={"Ctrl+#37":"left","Ctrl+#39":"right","#38":"up","#40":"down","Ctrl+#38":"up","Ctrl+#40":"down"},i=[];t.ctrlKey&&i.push("Ctrl"),i.push("#"+t.keyCode);var n=e[i.join("+")];n&&(r(n),t.ctrlKey&&(t.stopPropagation(),t.preventDefault()))}),e.data("zui.batchActionForm",l),setTimeout(t.fixTableResponsive,0)};t.fn.batchActionForm=function(i){return this.each(function(){e(t(this),i)})}}(jQuery),function(t,e){"use strict";var i="zui.table",n={zh_cn:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},zh_tw:{selectedItems:"已选择 {0} 项",attrTotal:"{0}总计 {1}"},en:{selectedItems:"Seleted {0} items",attrTotal:"{0} total {1}"},de:{selectedItems:"{0} ausgewählt",attrTotal:"{0} insgesamt {1}"},fr:{selectedItems:"{0} sélectionnés",attrTotal:"{0} total {1}"}},o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),a=t.zui.browser.isIE(),s=a?200:100,r=function(e,o){var a=this;a.name=i;var s=a.$=t(e);o=a.options=t.extend({},r.DEFAULTS,this.$.data(),o),a.langName=o.lang||t.zui.clientLang(),a.lang=t.zui.getLangData(i,a.langName,n),a.id=s.attr("id"),a.id||(a.id=o.id||"table-"+t.zui.uuid(),a.noID=!0,s.attr("id",a.id),o.hot&&console.warn("ZUI: table hot replace id not defined, the element id attribute should be set.")),s.attr("data-ride")||s.attr("data-ride","table");var l=a.getTable();if(l.length){l.find("thead>tr>th").each(function(){var e=t(this);if(!e.attr("title")){var i=t.trim(e.find("a:first").text()||e.text()||"");i.length&&e.attr("title",i)}}),o.nested&&a.initNestedList(),o.checkable&&(s.on("click",".check-all",function(){a.checkAll(!t(this).hasClass("checked"))}),o.checkOnClickRow&&s.on("click","tbody>tr",function(e){t(e.target).closest('.btn,a,.not-check,.form-control,input[type="text"],.chosen-container').length||a.checkRow(t(this))}),s.on("click",'tbody input[type="checkbox"],tbody label[for]',function(e){e.stopPropagation();var i=t(this);i.is("label")&&(i=i.closest(".checkbox-primary").find('input[type="checkbox"]')),a.checkRow(i.closest("tr"),i.is(":checked"))}),o.selectable&&s.selectable(t.extend({},{selector:a.isDataTable?".fixed-left tbody>tr":"tbody>tr",selectClass:"",trigger:".c-id",clickBehavior:"multi",listenClick:!1,start:function(){this.syncSelectionsFromClass()},select:function(e){a.checkRow(e.target,!0),t.cookie("ajax_dragSelected")||(t.cookie("ajax_dragSelected","on",{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("dragSelected"))},unselect:function(t){a.checkRow(t.target,!1)},rangeStyle:{border:"1px solid #006af1",backgroundColor:"rgba(50,128,252,0.2)",borderRadius:"2px"}},t.isPlainObject(o.selectable)?o.selectable:null)));var h=a.$form=s.is("form")?s:s.find("form");h.length&&(o.ajaxForm?h.ajaxForm(t.isPlainObject(o.ajaxForm)?o.ajaxForm:null):h.on("click","[data-form-action]",function(){h.attr("action",t(this).data("formAction")).submit()})),(o.fixFooter||o.fixHeader)&&(a.pageFooterHeight=t("#footer").outerHeight(),a.updateFixUI(!0),t(window).on("scroll resize",function(){a.updateFixUI()}).on("sidebar.toggle",function(){setTimeout(function(){a.updateFixUI()},200)})),o.group&&(s.on("click",".group-toggle",function(){a.toggleRowGroup(t(this).closest("tr").data("id"))}),t(document).on("click",".group-collapse-all",function(){a.toggleGroups(!1)}).on("click",".group-expand-all",function(){a.toggleGroups(!0)})),a.defaultStatistic=s.find(".table-statistic").html(),a.updateStatistic(),a.initModals(),a.checkItems={},a.updateCheckUI()}};r.prototype.initNestedList=function(){var e=this,i=e.options,n=e.getTable().addClass("table-nested"),o=n.find("tbody"),a=o.children("tr[data-id]"),s={},r=[],l=i.preserveNested,h=i.enableEmptyNestedRow;n.toggleClass("disable-empty-nest-row",!h),a.each(function(e){var i=t(this),n=i.data();n.realOrder=e,n.$row=i,n.nestPath?(n.nestPathList=n.nestPath.split(","),n.nestPathList[0]||n.nestPathList.shift(),n.nestPathList[n.nestPathList.length-1]||n.nestPathList.pop(),n.nestPathLevel=n.nestPathList.length,i.attr("data-level",n.nestPathLevel)):(n.nestPath=","+n.id+",",n.nestPathList=[n.id],n.nestPathLevel=1),s[n.id]=n,delete n.children,r.push(n)});var c=[];t.each(r,function(t,n){return n.nestParent&&(n.parent=s[n.nestParent],n.parent)?(n.parent.children?n.parent.children.push(n):n.parent.children=[n],void(i.expandNestChild||e._initedNestedList||(n.$row.addClass("table-nest-hide"),n.parent.$row.addClass("table-nest-child-hide")))):(n.$row.removeClass("table-nest-hide"),void c.push(n))}),e.nestRowsMap=s,e.$nestBody=o;var d=function(e){for(var n=0;n').prependTo(s)),r.toggleClass("table-nest-toggle",!!a.children||h&&a.nested).css("marginLeft",(a.nestPathLevel-1)*i.nestLevelIndent),delete a.$row}};if(d(c),e.nestConfigStoreName="/"+window.config.currentModule+"/"+window.config.currentMethod+"/table."+e.id+".nestConfig",e.nestConfig=l?t.zui.store.get(e.nestConfigStoreName,{}):{},l)for(var u=0;u");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),h=l.find("#"+o).closest('[data-ride="table"],#'+a);if(h.length){var c=h.find(".table-statistic");c.length&&(i.defaultStatistic=c.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=h.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(f){console.error(f)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var p=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(p.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n; o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime').append(t('
            ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),c){var d=h[0].getBoundingClientRect();l.css({left:d.left,width:h.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||h.data("fixHeaderScroll")||(h.data("fixHeaderScroll",1),i.width()>h.width()&&h.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),h=l.hasClass("body-modal");if(r){var c=n.parent(),d=c.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?c[0].getBoundingClientRect().left:e.left,width:d?c.width():e.width}),h&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),h&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(t,i,n){var o=this;o.isDataTable&&!t.is(".datatable-row-left")&&(t=o.getTable().find('.datatable-row-left[data-index="'+t.data("index")+'"]'));var a=t.find('input[type="checkbox"]');a.length&&!a.is(":disabled")&&(i===e&&(i=!a.is(":checked")),o.isDataTable?o.getTable().find('.datatable-row[data-index="'+t.data("index")+'"]').toggleClass("checked",i):t.toggleClass("checked",i),this.checkItems[t.data("id")]=i,a.prop("checked",i).trigger("change"),n||o.updateCheckUI())},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var h=t(this),c=h.find('input[type="checkbox"]');if(!c.length)return void l--;r=c.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+h.data("index")+'"]'):h;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){"string"==typeof i&&(n=i,i=null),n=n||"show",t.zui.messager?t.zui.messager[n](e,i):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var h=r.beforeSubmit,c=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if(l.removeClass("form-watched").enableForm(!1),(h&&h(n,a,s))!==!1){var r={},c=a.find('[type="file"]');r.fileapi=c.length&&c[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,f="multipart/form-data",p=a.attr("enctype")==f||a.attr("encoding")==f,g=r.fileapi&&r.formdata,m=u&&!g||p&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")}},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var h=r.responser?t(r.responser):l.find(".form-responser");h.length||(h=t("#responser"));var c=i.message,f=function(){var n=i.callback;if(n){var o=n.indexOf("("),a=(o>0?n.substr(0,o):n).split("."),s=e,r=a[0];a.length>1&&(r=a[1],"top"===a[0]?s=e.top:"parent"===a[0]&&(s=e.parent));var h=s[r];if("function"==typeof h){var c=[];return o>0&&")"==n[n.length-1]&&(c=t.parseJSON("["+n.substring(o+1,n.length-1)+"]")),c.push(i),h.apply(l,c)}}};if("success"===i.result){var p=r.locate||i.locate;if(l.enableForm(!0,!!p),c){var g=l.find('[type="submit"]').first(),m=!1;g.length&&(g.popover({container:"body",trigger:"manual",content:c,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||g.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){g.popover("destroy")},r.popoverTime||2e3),m=!0),h.length&&(h.html(''+c+"").show().delay(3e3).fadeOut(100),m=!0),m||a(c,"success")}if(u)return u(i,!0,l);if((r.closeModal||i.closeModal)&&setTimeout(t.zui.closeModal,r.closeModalTime||2e3),f()===!1)return;if(p)if("loadInModal"==p){var v=t(".modal");setTimeout(function(){v.load(v.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===p||"top"===p?e[p]&&setTimeout(function(){e[p].location.reload()},1200):"reload"===p?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.tabs?t.tabs.open(p):e.location.href=p},1200);var y=r.ajaxReload||i.ajaxReload;if(y){var b=t(y);b.length&&b.load(e.location.href+" "+y,function(){b.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof c)h.length?h.html(''+c+"").show().delay(3e3).fadeOut(100):a(c,"danger");else if("object"==typeof c){var w=!1,x=[];t.each(c,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void x.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
            ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var h=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",h);var c=t("#"+e+"_chosen");if(c.length&&c.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){h()===!0&&t(this).removeClass("has-error")}),!w){if(o.hasClass("chosen"))o.trigger("chosen:activate");else if(o.is("textarea")&&o.data("keditor")){var d=o.data("keditor");d.focus(),d.edit.doc.body.focus()}else o.focus();w=!0}}),x.length&&a(x.join(";"),"danger")}if(u)return u(i,!1,l);if(f()===!1)return}}},error:function(t,i,n){if((c&&c(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{finish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
            ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
            '+(n.errorText||window.lang&&window.lang.timeout)+"
            "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=t.trim(e).split(" ");a.each(function(){var e=t(this),n=e.text()+" "+(e.data("key")||e.data("filter"));e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active"))},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
            ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=""===o.value||"0"===o.value,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s&&!o.label?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(h.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),h=s.find('[name="end"],.control-time-end'),c=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);h.find('option[value="'+i+'"]').length&&h.val(i),r.onChange&&r.onChange(h,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");h.find('option[value="'+u+'"]').length&&h.val(u),r.onChange&&r.onChange(h,u)}}else l.on("change",c),a(l,r.begin),a(h,r.end),s.data("timeSpanControlInit",!0);r.end||c()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.parent.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&t.zui.Picker.enableChosen(),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
            {page}/{totalPage}
            ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,h=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(h,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var c=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;h="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(h,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,c=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:40}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()});var d=function(){var e,i,n=t(this),o=t.extend({limitSize:40,suffix:"…"},n.data()),a=n.text();if(a.length>o.limitSize){e=a,i=a.substr(0,o.limitSize)+o.suffix,n.text(i).addClass("limit-text-on");var s=o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle");s.text(s.data("textExpand")),s.on("click",function(){var t=n.toggleClass("limit-text-on").hasClass("limit-text-on");n.text(t?i:e),s.text(s.data(t?"textExpand":"textCollapse"))})}else(o.toggleBtn?t(o.toggleBtn):n.next(".text-limit-toggle")).hide()};t.fn.textLimit=function(){return this.each(d)},t(function(){t(".text-limit").textLimit()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th"); -e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
            ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
            ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){var r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search;return void(location.href=t.createLink("index","index","")+"#app="+encodeURIComponent(r))}if(e!==window&&e.$.apps){o&&e.location.reload();var l=window.name;if(0===l.indexOf("app-")){t.apps=window.apps=e.$.apps;var h=l.substr(4);t.appCode=h,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(h,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};if((0===e.indexOf("http:")||0===e.indexOf("https:"))&&e.indexOf(window.location.origin)<0)return{};var i=e.split("#"),n=i[0].split("?"),o=n[1],a=o?t.getSearchParam("",o):{},s=n[0],r={isOnlyBody:"yes"===a.onlybody,vars:[],hash:i[1]||"",params:a,tid:a.tid||""};if("GET"===config.requestType){r.moduleName=a[config.moduleVar]||"index",r.methodName=a[config.methodVar]||"index",r.viewType=a[config.viewVar]||config.defaultView;for(var l in a)l!==config.moduleVar&&l!==config.methodVar&&l!==config.viewVar&&"onlybody"!==l&&"tid"!==l&&r.vars.push([l,a[l]])}else{var h=s.lastIndexOf("/");h===s.length-1&&(s=s.substr(0,h),h=s.lastIndexOf("/")),h>=0&&(s=s.substr(h+1));var c=s.lastIndexOf(".");c>=0?(r.viewType=s.substr(c+1),s=s.substr(0,c)):r.viewType=config.defaultView;var d=s.split(config.requestFix);if(r.moduleName=d[0]||"index",r.methodName=d[1]||"index",d.length>2)for(var u=2;u.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
            ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var u,f,p,g,m,v=function(){u||(u=t("#subNavbar"),f=t("#pageNav"),p=t("#pageActions"),g=u.children(".nav"),m=g.outerWidth());var e=u.outerWidth(),i=f.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void g.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,m),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),k()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var T=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(T)},t(function(){t("textarea.autosize").each(T),t(document).on("input paste change","textarea.autosize",T)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var S="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=S,t("html").toggleClass("is-firefox",S).toggleClass("not-firefox",!S),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
            ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){var r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var t=270,i=e.getBoundingClientRect();i.top<0&&(t=Math.min(270,i.height)+i.top),e.style.maxHeight=Math.min(270,t)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){var e=window.parent,i=config.currentModule,n=config.currentMethod,o="index"===i&&"index"===n,a="#_single"===location.hash||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search;return void(location.href=t.createLink("index","index","")+"#app="+encodeURIComponent(r))}if(e!==window&&e.$.apps){o&&e.location.reload();var l=window.name;if(0===l.indexOf("app-")){t.apps=window.apps=e.$.apps;var h=l.substr(4);t.appCode=h,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;n&&n.dispatchEvent(new Event(t.type,{bubbles:!0}))}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(h,s,document.title)}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};var i=0===e.indexOf("http:")||0===e.indexOf("https:");if(i){var n=window.location.origin;if(e.indexOf(n)<0)return{};e=e.substr((n+config.webRoot).length)}var o=e.split("#"),a=o[0].split("?"),s=a[1],r=s?t.getSearchParam("",s):{},l=a[0],h={isOnlyBody:"yes"===r.onlybody,vars:[],hash:o[1]||"",params:r,tid:r.tid||""};if("GET"===config.requestType){h.moduleName=r[config.moduleVar]||"index",h.methodName=r[config.methodVar]||"index",h.viewType=r[config.viewVar]||config.defaultView;for(var c in r)c!==config.moduleVar&&c!==config.methodVar&&c!==config.viewVar&&"onlybody"!==c&&"tid"!==c&&h.vars.push([c,r[c]])}else{var d=l.lastIndexOf("/");d===l.length-1&&(l=l.substr(0,d),d=l.lastIndexOf("/")),d>=0&&(l=l.substr(d+1));var u=l.lastIndexOf(".");u>=0?(h.viewType=l.substr(u+1),l=l.substr(0,u)):h.viewType=config.defaultView;var f=l.split(config.requestFix);if(h.moduleName=f[0]||"index",h.methodName=f[1]||"index",f.length>2)for(var p=2;p.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file From 063698a407eeaa8f10344f456ebcb5d24b0afe65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A1=E6=A0=8B?= Date: Thu, 4 Nov 2021 21:12:23 +0800 Subject: [PATCH 030/304] * adjust for zt session handler. --- framework/base/router.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 9dca2e5075..57939efd5f 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2654,6 +2654,8 @@ class ztSessionHandler public $tagID; public $sessionFile; public $sessionID; + public $rawID; + public $rawFile; /** * Construct. @@ -2697,6 +2699,8 @@ class ztSessionHandler $this->sessionFile = $this->sessSavePath . '/' . $fileName; $this->sessionID = $sessionID; + $this->rawID = $id; + $this->rawFile = $this->sessSavePath . '/' . "sess_$id"; return $this->sessionFile; } @@ -2737,7 +2741,11 @@ class ztSessionHandler $sessFile = $this->getSessionFile($id); if(!file_exists($sessFile)) { - ($this->tagID and file_exists("$this->sessSavePath/sess_$id")) ? copy("$this->sessSavePath/sess_$id", $sessFile) : touch($sessFile); + ($this->tagID and file_exists($this->rawFile)) ? copy($this->rawFile, $sessFile) : touch($sessFile); + } + elseif(!file_exists($this->rawFile)) + { + if(strpos(file_get_contents($sessFile), 'user|') !== false) copy($sessFile, $this->rawFile); } return (string) file_get_contents($sessFile); } From dc5ba2d895f3a1b1999e21975d0c5fe74234f08a Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 6 May 2022 16:04:07 +0800 Subject: [PATCH 031/304] * Module/api testcase. --- test/class/api.class.php | 208 ++++++++++++++++++++++ test/model/api/create.php | 51 ++++++ test/model/api/createdemodata.php | 17 ++ test/model/api/createstruct.php | 17 ++ test/model/api/deleterelease.php | 17 ++ test/model/api/getapilistbyrelease.php | 17 ++ test/model/api/getlibbyid.php | 17 ++ test/model/api/getlistbymoduleid.php | 17 ++ test/model/api/getmethod.php | 17 ++ test/model/api/getrelease.php | 17 ++ test/model/api/getreleasebyquery.php | 17 ++ test/model/api/getreleaselistbyapi.php | 17 ++ test/model/api/getstructbyid.php | 17 ++ test/model/api/getstructbyquery.php | 17 ++ test/model/api/getstructlistbylibid.php | 17 ++ test/model/api/getstructlistbyrelease.php | 17 ++ test/model/api/getstructtreebylib.php | 17 ++ test/model/api/gettypelist.php | 17 ++ test/model/api/publishlib.php | 17 ++ test/model/api/request.php | 17 ++ test/model/api/sql.php | 17 ++ test/model/api/update.php | 17 ++ test/model/api/updatestruct.php | 17 ++ test/ztest | 3 + 24 files changed, 619 insertions(+) create mode 100644 test/class/api.class.php create mode 100644 test/model/api/create.php create mode 100644 test/model/api/createdemodata.php create mode 100644 test/model/api/createstruct.php create mode 100644 test/model/api/deleterelease.php create mode 100644 test/model/api/getapilistbyrelease.php create mode 100644 test/model/api/getlibbyid.php create mode 100644 test/model/api/getlistbymoduleid.php create mode 100644 test/model/api/getmethod.php create mode 100644 test/model/api/getrelease.php create mode 100644 test/model/api/getreleasebyquery.php create mode 100644 test/model/api/getreleaselistbyapi.php create mode 100644 test/model/api/getstructbyid.php create mode 100644 test/model/api/getstructbyquery.php create mode 100644 test/model/api/getstructlistbylibid.php create mode 100644 test/model/api/getstructlistbyrelease.php create mode 100644 test/model/api/getstructtreebylib.php create mode 100644 test/model/api/gettypelist.php create mode 100644 test/model/api/publishlib.php create mode 100644 test/model/api/request.php create mode 100644 test/model/api/sql.php create mode 100644 test/model/api/update.php create mode 100644 test/model/api/updatestruct.php diff --git a/test/class/api.class.php b/test/class/api.class.php new file mode 100644 index 0000000000..45b580e70c --- /dev/null +++ b/test/class/api.class.php @@ -0,0 +1,208 @@ +objectModel = $tester->loadModel('api'); + } + + public function publishLibTest($data) + { + $objects = $this->objectModel->publishLib($data); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function deleteReleaseTest($id) + { + $objects = $this->objectModel->deleteRelease($id); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function createTest($params) + { + $_POST = $params; + $objects = $this->objectModel->create($_POST['lib']); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function createStructTest($data) + { + $objects = $this->objectModel->createStruct($data); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function updateStructTest($id) + { + $objects = $this->objectModel->updateStruct($id); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function updateTest($apiID) + { + $objects = $this->objectModel->update($apiID); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getStructListByLibIDTest($id) + { + $objects = $this->objectModel->getStructListByLibID($id); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getStructByIDTest($id) + { + $objects = $this->objectModel->getStructByID($id); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getReleaseTest($libID = 0, $type = '', $param = 0) + { + $objects = $this->objectModel->getRelease($libID = 0, $type = '', $param = 0); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getReleaseListByApiTest($libID) + { + $objects = $this->objectModel->getReleaseListByApi($libID); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getLibByIdTest($id, $version = 0, $release = 0) + { + $objects = $this->objectModel->getLibById($id, $version = 0, $release = 0); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getApiListByReleaseTest($release, $where = '1 = 1 ') + { + $objects = $this->objectModel->getApiListByRelease($release, $where = '1 = 1 '); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getListByModuleIdTest($libID = 0, $moduleID = 0, $release = 0) + { + $objects = $this->objectModel->getListByModuleId($libID = 0, $moduleID = 0, $release = 0); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getStructByQueryTest($libID, $pager = '', $orderBy = '') + { + $objects = $this->objectModel->getStructByQuery($libID, $pager = '', $orderBy = ''); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getStructListByReleaseTest($release, $where = '1 = 1 ', $orderBy = 'id') + { + $objects = $this->objectModel->getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id'); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getReleaseByQueryTest($libID, $pager = '', $orderBy = '') + { + $objects = $this->objectModel->getReleaseByQuery($libID, $pager = '', $orderBy = ''); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getStructTreeByLibTest($libID = 0, $structID = 0) + { + $objects = $this->objectModel->getStructTreeByLib($libID = 0, $structID = 0); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getMethodTest($filePath, $ext = '') + { + $objects = $this->objectModel->getMethod($filePath, $ext = ''); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function requestTest($moduleName, $methodName, $action) + { + $objects = $this->objectModel->request($moduleName, $methodName, $action); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function sqlTest($sql, $keyField = '') + { + $objects = $this->objectModel->sql($sql, $keyField = ''); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function getTypeListTest($libID) + { + $objects = $this->objectModel->getTypeList($libID); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + public function createDemoDataTest($name, $baseUrl, $version = '16.0') + { + $objects = $this->objectModel->createDemoData($name, $baseUrl, $version = '16.0'); + + if(dao::isError()) return dao::getError(); + + return $objects; + } +} diff --git a/test/model/api/create.php b/test/model/api/create.php new file mode 100644 index 0000000000..ed7c402cd9 --- /dev/null +++ b/test/model/api/create.php @@ -0,0 +1,51 @@ +#!/usr/bin/env php +create(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +$data = array( + 'lib' => 910, + 'module' => 0, + 'title' => '测试api', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); + +$normalApi = $data; + +$emptyLibApi = $data; +$emptyLibApi['lib'] = 0; + +$emptyTitleApi = $data; +$emptyTitleApi['title'] = ''; + +$emptyPathApi = $data; +$emptyPathApi['path'] = ''; + +r($api->createTest($normalApi)) && p('lib') && e('910'); //测试创建api +r($api->createTest($emptyLibApi)) && p('lib:0') && e('『API Library』should not be blank.'); //测试没有lib创建api +r($api->createTest($emptyTitleApi)) && p('title:0') && e('『Name』should not be blank.'); //测试没有title创建api +r($api->createTest($emptyPathApi)) && p('path:0') && e('『Request Path』should not be blank.'); //测试没有path创建api + +//system("./ztest init"); diff --git a/test/model/api/createdemodata.php b/test/model/api/createdemodata.php new file mode 100644 index 0000000000..a4d293d1ab --- /dev/null +++ b/test/model/api/createdemodata.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +createDemoData(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->createDemoDataTest()) && p() && e(); diff --git a/test/model/api/createstruct.php b/test/model/api/createstruct.php new file mode 100644 index 0000000000..fd2da8c312 --- /dev/null +++ b/test/model/api/createstruct.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +createStruct(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->createStructTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/deleterelease.php b/test/model/api/deleterelease.php new file mode 100644 index 0000000000..3837854d3c --- /dev/null +++ b/test/model/api/deleterelease.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +deleteRelease(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->deleteReleaseTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getapilistbyrelease.php b/test/model/api/getapilistbyrelease.php new file mode 100644 index 0000000000..1424b0ff8e --- /dev/null +++ b/test/model/api/getapilistbyrelease.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getApiListByRelease(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getApiListByReleaseTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getlibbyid.php b/test/model/api/getlibbyid.php new file mode 100644 index 0000000000..0fc0e6cf84 --- /dev/null +++ b/test/model/api/getlibbyid.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getLibById(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getLibByIdTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getlistbymoduleid.php b/test/model/api/getlistbymoduleid.php new file mode 100644 index 0000000000..67d75b9a32 --- /dev/null +++ b/test/model/api/getlistbymoduleid.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getListByModuleId(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getListByModuleIdTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getmethod.php b/test/model/api/getmethod.php new file mode 100644 index 0000000000..4cef7995f0 --- /dev/null +++ b/test/model/api/getmethod.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getMethod(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getMethodTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getrelease.php b/test/model/api/getrelease.php new file mode 100644 index 0000000000..1f76d4174c --- /dev/null +++ b/test/model/api/getrelease.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getRelease(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getReleaseTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getreleasebyquery.php b/test/model/api/getreleasebyquery.php new file mode 100644 index 0000000000..ee8d4a2fa0 --- /dev/null +++ b/test/model/api/getreleasebyquery.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getReleaseByQuery(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getReleaseByQueryTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getreleaselistbyapi.php b/test/model/api/getreleaselistbyapi.php new file mode 100644 index 0000000000..cc4fc2c567 --- /dev/null +++ b/test/model/api/getreleaselistbyapi.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getReleaseListByApi(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getReleaseListByApiTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructbyid.php b/test/model/api/getstructbyid.php new file mode 100644 index 0000000000..75b2d5fe98 --- /dev/null +++ b/test/model/api/getstructbyid.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getStructByID(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getStructByIDTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructbyquery.php b/test/model/api/getstructbyquery.php new file mode 100644 index 0000000000..58b2be86b3 --- /dev/null +++ b/test/model/api/getstructbyquery.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getStructByQuery(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getStructByQueryTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructlistbylibid.php b/test/model/api/getstructlistbylibid.php new file mode 100644 index 0000000000..673e596d01 --- /dev/null +++ b/test/model/api/getstructlistbylibid.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getStructListByLibID(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getStructListByLibIDTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructlistbyrelease.php b/test/model/api/getstructlistbyrelease.php new file mode 100644 index 0000000000..387e9040ca --- /dev/null +++ b/test/model/api/getstructlistbyrelease.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getStructListByRelease(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getStructListByReleaseTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructtreebylib.php b/test/model/api/getstructtreebylib.php new file mode 100644 index 0000000000..52a2724d67 --- /dev/null +++ b/test/model/api/getstructtreebylib.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getStructTreeByLib(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getStructTreeByLibTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/gettypelist.php b/test/model/api/gettypelist.php new file mode 100644 index 0000000000..1b332719a2 --- /dev/null +++ b/test/model/api/gettypelist.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +getTypeList(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->getTypeListTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/publishlib.php b/test/model/api/publishlib.php new file mode 100644 index 0000000000..c62b0fc6ab --- /dev/null +++ b/test/model/api/publishlib.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +publishLib(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->publishLibTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/request.php b/test/model/api/request.php new file mode 100644 index 0000000000..7fedf37daa --- /dev/null +++ b/test/model/api/request.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +request(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->requestTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/sql.php b/test/model/api/sql.php new file mode 100644 index 0000000000..d353aed638 --- /dev/null +++ b/test/model/api/sql.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +sql(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->sqlTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/update.php b/test/model/api/update.php new file mode 100644 index 0000000000..2d4fd59404 --- /dev/null +++ b/test/model/api/update.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +update(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->updateTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/updatestruct.php b/test/model/api/updatestruct.php new file mode 100644 index 0000000000..5cc5ce3a4e --- /dev/null +++ b/test/model/api/updatestruct.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +updateStruct(); +cid=1 +pid=1 + +*/ + +$api = new apiTest(); + +r($api->updateStructTest()) && p() && e(); \ No newline at end of file diff --git a/test/ztest b/test/ztest index 358a930ca6..9b5e754837 100755 --- a/test/ztest +++ b/test/ztest @@ -16,6 +16,9 @@ switch($argv[1]) case 'api': ztfRun('api'); break; + case 'mapi': + ztfRun('model/api'); + break; case 'control': ztfRun('control'); break; From deaa482c0af82b6a1fcc6eef780f08e2894db115 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 6 May 2022 17:25:09 +0800 Subject: [PATCH 032/304] * CreateStructTest. --- test/model/api/createstruct.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/model/api/createstruct.php b/test/model/api/createstruct.php index fd2da8c312..6c84017dec 100644 --- a/test/model/api/createstruct.php +++ b/test/model/api/createstruct.php @@ -12,6 +12,26 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->createStructTest()) && p() && e(); \ No newline at end of file +$emptyNameStruct = new stdclass(); +$emptyNameStruct->name = ''; +$emptyNameStruct->type = 'formData'; +$emptyNameStruct->attribute = '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]'; +$emptyNameStruct->desc = ''; +$emptyNameStruct->addedBy = $tester->app->user->account; +$emptyNameStruct->addedDate = helper::now(); + +$normalStruct = new stdclass(); +$normalStruct->name = 'struct'; +$normalStruct->type = 'formData'; +$normalStruct->attribute = '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]'; +$normalStruct->desc = ''; +$normalStruct->addedBy = $tester->app->user->account; +$normalStruct->addedDate = helper::now(); + +r($api->createStructTest($normalStruct)) && p('name') && e('struct'); //创建数据结构 +r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『Name』should not be blank.'); //创建没有结构名的数据结构 + +//system("./ztest init"); From 35cd9dd2882b4f838de0bf157955e8c777a0b3c8 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 7 May 2022 10:38:10 +0800 Subject: [PATCH 033/304] * Publishlib and updatestruct testcase. --- test/class/api.class.php | 27 ++++++++++++++++++++++----- test/model/api/publishlib.php | 20 +++++++++++++++++++- test/model/api/updatestruct.php | 27 ++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/test/class/api.class.php b/test/class/api.class.php index 45b580e70c..8e10c4e99b 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -9,10 +9,12 @@ class apiTest public function publishLibTest($data) { - $objects = $this->objectModel->publishLib($data); + $objectID = $this->objectModel->publishLib($data); if(dao::isError()) return dao::getError(); + $objects = $this->objectModel->getRelease($data->lib); + $this->objectModel->deleteRelease($objectID); return $objects; } @@ -27,29 +29,44 @@ class apiTest public function createTest($params) { + global $tester; + $_POST = $params; - $objects = $this->objectModel->create($_POST['lib']); + $objects = $this->objectModel->create($params['lib']); if(dao::isError()) return dao::getError(); + $tester->dao->delete()->from(TABLE_API)->where('id')->eq($objects->id)->exec(); + return $objects; } - public function createStructTest($data) + public function createStructTest($data, $confirm = true) { - $objects = $this->objectModel->createStruct($data); + global $tester; + + $objectID = $this->objectModel->createStruct($data); if(dao::isError()) return dao::getError(); + $objects = $this->objectModel->getStructByID($objectID); + + if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($objects->id)->exec(); + return $objects; } - public function updateStructTest($id) + public function updateStructTest($id, $params, $confirm = true) { + global $tester; + + $_POST = $params; $objects = $this->objectModel->updateStruct($id); if(dao::isError()) return dao::getError(); + if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($id)->exec(); + return $objects; } diff --git a/test/model/api/publishlib.php b/test/model/api/publishlib.php index c62b0fc6ab..373e0a3ebc 100644 --- a/test/model/api/publishlib.php +++ b/test/model/api/publishlib.php @@ -12,6 +12,24 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->publishLibTest()) && p() && e(); \ No newline at end of file +$emptyBuildRelease = new stdclass(); +$emptyBuildRelease->version = ''; +$emptyBuildRelease->desc = ''; +$emptyBuildRelease->lib = 910; +$emptyBuildRelease->addedBy = $tester->app->user->account; +$emptyBuildRelease->addedDate = helper::now(); + +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +r($api->publishLibTest($emptyBuildRelease)) && p('version:0') && e('『Version』should not be blank.'); //没有版本名的发布 +r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布 + +//system("./ztest init"); diff --git a/test/model/api/updatestruct.php b/test/model/api/updatestruct.php index 5cc5ce3a4e..6d0baba8e1 100644 --- a/test/model/api/updatestruct.php +++ b/test/model/api/updatestruct.php @@ -12,6 +12,31 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->updateStructTest()) && p() && e(); \ No newline at end of file +$normalStruct = new stdclass(); +$normalStruct->name = 'struct'; +$normalStruct->type = 'formData'; +$normalStruct->attribute = '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]'; +$normalStruct->desc = ''; +$normalStruct->addedBy = $tester->app->user->account; +$normalStruct->addedDate = helper::now(); + +$data = array( + 'name' => 'editStruct', + 'type' => 'formData', + 'attribute' => '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]', + 'desc' => '', +); + +$normalEditStruct = $data; + +$emptyNameEditStruct = $data; +$emptyNameEditStruct['name'] = ''; + +$struct = $api->createStructTest($normalStruct, false); +r($api->updateStructTest($struct->id, $normalEditStruct, false)) && p('0:new') && e('editStruct'); //正常的修改 +r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『Name』should not be blank.'); //没有名称的修改 + +//system("./ztest init"); From 4fcdc3c72872f9c0a0bdd6989b923479d58df92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Sat, 7 May 2022 14:32:04 +0800 Subject: [PATCH 034/304] * Add testcase. --- test/class/api.class.php | 37 +++++++++++++++++++------ test/model/api/create.php | 2 +- test/model/api/deleterelease.php | 14 +++++++++- test/model/api/getapilistbyrelease.php | 33 +++++++++++++++++++++- test/model/api/getlibbyid.php | 25 ++++++++++++++++- test/model/api/getmethod.php | 2 +- test/model/api/getrelease.php | 13 ++++++++- test/model/api/getstructbyid.php | 14 +++++++++- test/model/api/getstructlistbylibid.php | 14 +++++++++- test/model/api/update.php | 24 +++++++++++++++- 10 files changed, 160 insertions(+), 18 deletions(-) diff --git a/test/class/api.class.php b/test/class/api.class.php index 8e10c4e99b..3e91dc1793 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -7,27 +7,31 @@ class apiTest $this->objectModel = $tester->loadModel('api'); } - public function publishLibTest($data) + public function publishLibTest($data, $confirm = true) { $objectID = $this->objectModel->publishLib($data); if(dao::isError()) return dao::getError(); $objects = $this->objectModel->getRelease($data->lib); - $this->objectModel->deleteRelease($objectID); + + if($confirm) $this->objectModel->deleteRelease($objectID); + return $objects; } - public function deleteReleaseTest($id) + public function deleteReleaseTest($id, $libID = 0) { - $objects = $this->objectModel->deleteRelease($id); + $this->objectModel->deleteRelease($id); + + $objects = $this->objectModel->getRelease($libID); if(dao::isError()) return dao::getError(); return $objects; } - public function createTest($params) + public function createTest($params, $confirm = true) { global $tester; @@ -36,7 +40,7 @@ class apiTest if(dao::isError()) return dao::getError(); - $tester->dao->delete()->from(TABLE_API)->where('id')->eq($objects->id)->exec(); + if($confirm) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($objects->id)->exec(); return $objects; } @@ -79,30 +83,40 @@ class apiTest return $objects; } - public function getStructListByLibIDTest($id) + public function getStructListByLibIDTest($id, $confirm = true) { + global $tester; + $objects = $this->objectModel->getStructListByLibID($id); if(dao::isError()) return dao::getError(); + if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($objects['0']->id)->exec(); + return $objects; } - public function getStructByIDTest($id) + public function getStructByIDTest($id, $confirm = true) { + global $tester; + $objects = $this->objectModel->getStructByID($id); if(dao::isError()) return dao::getError(); + if($confirm) $tester->dao->delete()->from(TABLE_APISTRUCT)->where('id')->eq($objects->id)->exec(); + return $objects; } - public function getReleaseTest($libID = 0, $type = '', $param = 0) + public function getReleaseTest($libID = 0, $type = '', $param = 0, $confirm = true) { $objects = $this->objectModel->getRelease($libID = 0, $type = '', $param = 0); if(dao::isError()) return dao::getError(); + if($confirm) $this->objectModel->deleteRelease($objects->id); + return $objects; } @@ -126,10 +140,15 @@ class apiTest public function getApiListByReleaseTest($release, $where = '1 = 1 ') { + global $tester; + $objects = $this->objectModel->getApiListByRelease($release, $where = '1 = 1 '); if(dao::isError()) return dao::getError(); + foreach($release->snap['apis'] as $api) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($api['id'])->exec(); + $this->objectModel->deleteRelease($release->id); + return $objects; } diff --git a/test/model/api/create.php b/test/model/api/create.php index ed7c402cd9..2ce82c6ecf 100644 --- a/test/model/api/create.php +++ b/test/model/api/create.php @@ -17,7 +17,7 @@ $api = new apiTest(); $data = array( 'lib' => 910, 'module' => 0, - 'title' => '测试api', + 'title' => 'testapi', 'protocol' => 'HTTP', 'method' => 'GET', 'path' => '/api/test/id', diff --git a/test/model/api/deleterelease.php b/test/model/api/deleterelease.php index 3837854d3c..e26c018b02 100644 --- a/test/model/api/deleterelease.php +++ b/test/model/api/deleterelease.php @@ -12,6 +12,18 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->deleteReleaseTest()) && p() && e(); \ No newline at end of file +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +$release = $api->publishLibTest($normalRelease, false); + +r($api->deleteReleaseTest($release->id, $release->lib)) && p('') && e('0'); //删除一个创建的发布 + +//system("./ztest init"); diff --git a/test/model/api/getapilistbyrelease.php b/test/model/api/getapilistbyrelease.php index 1424b0ff8e..6cf332b766 100644 --- a/test/model/api/getapilistbyrelease.php +++ b/test/model/api/getapilistbyrelease.php @@ -12,6 +12,37 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getApiListByReleaseTest()) && p() && e(); \ No newline at end of file +$data = array( + 'lib' => 910, + 'module' => 0, + 'title' => 'testapi', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); +$normalApi = $data; + +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +$apiInfo = $api->createTest($normalApi, false); +$release = $api->publishLibTest($normalRelease, false); + +r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api +//system("./ztest init"); diff --git a/test/model/api/getlibbyid.php b/test/model/api/getlibbyid.php index 0fc0e6cf84..c8977e99f4 100644 --- a/test/model/api/getlibbyid.php +++ b/test/model/api/getlibbyid.php @@ -14,4 +14,27 @@ pid=1 $api = new apiTest(); -r($api->getLibByIdTest()) && p() && e(); \ No newline at end of file +$data = array( + 'lib' => 910, + 'module' => 0, + 'title' => '测试api', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); + +$normalApi = $data; + +$apiInfo = $api->createTest($normalApi, false); +r($api->getLibByIdTest($apiInfo->id)) && p('lib') && e('910'); //获取刚创建的api + +//system("./ztest init"); diff --git a/test/model/api/getmethod.php b/test/model/api/getmethod.php index 4cef7995f0..541abc2054 100644 --- a/test/model/api/getmethod.php +++ b/test/model/api/getmethod.php @@ -14,4 +14,4 @@ pid=1 $api = new apiTest(); -r($api->getMethodTest()) && p() && e(); \ No newline at end of file +r($api->getMethodTest()) && p() && e(); diff --git a/test/model/api/getrelease.php b/test/model/api/getrelease.php index 1f76d4174c..706f8509ea 100644 --- a/test/model/api/getrelease.php +++ b/test/model/api/getrelease.php @@ -12,6 +12,17 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getReleaseTest()) && p() && e(); \ No newline at end of file +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +$release = $api->publishLibTest($normalRelease, false); +r($api->getReleaseTest($release->lib)) && p('version') && e('Version1'); //获取刚创建的发布 + +//system("./ztest init"); diff --git a/test/model/api/getstructbyid.php b/test/model/api/getstructbyid.php index 75b2d5fe98..850e53f665 100644 --- a/test/model/api/getstructbyid.php +++ b/test/model/api/getstructbyid.php @@ -12,6 +12,18 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getStructByIDTest()) && p() && e(); \ No newline at end of file +$normalStruct = new stdclass(); +$normalStruct->name = 'struct'; +$normalStruct->type = 'formData'; +$normalStruct->attribute = '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]'; +$normalStruct->desc = ''; +$normalStruct->addedBy = $tester->app->user->account; +$normalStruct->addedDate = helper::now(); + +$struct = $api->createStructTest($normalStruct, false); +r($api->getStructByIDTest($struct->id)) && p('name') && e('struct'); //获取刚创建的数据结构 + +//system("./ztest init"); diff --git a/test/model/api/getstructlistbylibid.php b/test/model/api/getstructlistbylibid.php index 673e596d01..33cbd31084 100644 --- a/test/model/api/getstructlistbylibid.php +++ b/test/model/api/getstructlistbylibid.php @@ -12,6 +12,18 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getStructListByLibIDTest()) && p() && e(); \ No newline at end of file +$normalStruct = new stdclass(); +$normalStruct->name = 'struct'; +$normalStruct->lib = 910; +$normalStruct->type = 'formData'; +$normalStruct->attribute = '[{"field":"field1","paramsType":"string","required":true,"desc":"desc","structType":"formData","sub":1,"key":"l2u5qy3jc1se6ghigll","children":[]}]'; +$normalStruct->desc = ''; +$normalStruct->addedBy = $tester->app->user->account; +$normalStruct->addedDate = helper::now(); + +$struct = $api->createStructTest($normalStruct, false); + +r($api->getStructListByLibIDTest($normalStruct->lib)) && p('0:lib') && e('910'); //用libID获取刚插入的数据结构 diff --git a/test/model/api/update.php b/test/model/api/update.php index 2d4fd59404..ac31bbfffe 100644 --- a/test/model/api/update.php +++ b/test/model/api/update.php @@ -14,4 +14,26 @@ pid=1 $api = new apiTest(); -r($api->updateTest()) && p() && e(); \ No newline at end of file +$data = array( + 'lib' => 910, + 'module' => 0, + 'title' => 'testapi', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); + +$normalApi = $data; + +$apiInfo = $api->createTest($normalApi); + +r($api->updateTest()) && p() && e(); From 1aec2a21cdf180505a6d6035373260b69c90baa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Sat, 7 May 2022 15:39:22 +0800 Subject: [PATCH 035/304] * Add testcase. --- test/model/api/createdemodata.php | 17 ----------------- test/model/api/request.php | 17 ----------------- test/model/api/update.php | 26 ++++++++++++++++++++++++-- 3 files changed, 24 insertions(+), 36 deletions(-) delete mode 100644 test/model/api/createdemodata.php delete mode 100644 test/model/api/request.php diff --git a/test/model/api/createdemodata.php b/test/model/api/createdemodata.php deleted file mode 100644 index a4d293d1ab..0000000000 --- a/test/model/api/createdemodata.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -createDemoData(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->createDemoDataTest()) && p() && e(); diff --git a/test/model/api/request.php b/test/model/api/request.php deleted file mode 100644 index 7fedf37daa..0000000000 --- a/test/model/api/request.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -request(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->requestTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/update.php b/test/model/api/update.php index ac31bbfffe..b243754af7 100644 --- a/test/model/api/update.php +++ b/test/model/api/update.php @@ -32,8 +32,30 @@ $data = array( 'responseExample' => '' ); +$editData = array( + 'lib' => 910, + 'module' => 0, + 'title' => 'edittestapi', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); + + $normalApi = $data; +$editApi = $editData; -$apiInfo = $api->createTest($normalApi); +$apiInfo = $api->createTest($normalApi, false); -r($api->updateTest()) && p() && e(); +r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api + +//system("./ztest init"); From 603ee02060096031ed8771a4afb93cc611fd5c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Sat, 7 May 2022 17:20:29 +0800 Subject: [PATCH 036/304] * Add testcase. --- test/class/api.class.php | 11 ++++++-- test/model/api/getreleaselistbyapi.php | 13 ++++++++- test/model/api/getstructlistbyrelease.php | 34 ++++++++++++++++++++++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/test/class/api.class.php b/test/class/api.class.php index 3e91dc1793..bbfac27e10 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -74,12 +74,17 @@ class apiTest return $objects; } - public function updateTest($apiID) + public function updateTest($apiID, $params, $confirm = true) { + global $tester; + $_POST = $params; + $objects = $this->objectModel->update($apiID); if(dao::isError()) return dao::getError(); + if($confirm) $tester->dao->delete()->from(TABLE_API)->where('id')->eq($apiID)->exec(); + return $objects; } @@ -120,12 +125,14 @@ class apiTest return $objects; } - public function getReleaseListByApiTest($libID) + public function getReleaseListByApiTest($libID, $id = 0, $confirm = true) { $objects = $this->objectModel->getReleaseListByApi($libID); if(dao::isError()) return dao::getError(); + if($confirm) $this->objectModel->deleteRelease($objects[$id]->id); + return $objects; } diff --git a/test/model/api/getreleaselistbyapi.php b/test/model/api/getreleaselistbyapi.php index cc4fc2c567..f9d0fa231b 100644 --- a/test/model/api/getreleaselistbyapi.php +++ b/test/model/api/getreleaselistbyapi.php @@ -12,6 +12,17 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getReleaseListByApiTest()) && p() && e(); \ No newline at end of file +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +$release = $api->publishLibTest($normalRelease, false); +r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("{$release->id}:lib") && e('910'); //获取刚插入的发布信息 + +//system("./ztest init"); diff --git a/test/model/api/getstructlistbyrelease.php b/test/model/api/getstructlistbyrelease.php index 387e9040ca..a8aeb8e44e 100644 --- a/test/model/api/getstructlistbyrelease.php +++ b/test/model/api/getstructlistbyrelease.php @@ -12,6 +12,38 @@ pid=1 */ +global $tester; $api = new apiTest(); -r($api->getStructListByReleaseTest()) && p() && e(); \ No newline at end of file +$data = array( + 'lib' => 910, + 'module' => 0, + 'title' => 'testapi', + 'protocol' => 'HTTP', + 'method' => 'GET', + 'path' => '/api/test/id', + 'requestType' => 'application/json', + 'status' => 'done', + 'owner' => 'admin', + 'type' => 'formData', + 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', + 'desc' => '', + 'paramsExample' => '', + 'response' => '[]', + 'responseExample' => '' +); +$normalApi = $data; + +$normalRelease = new stdclass(); +$normalRelease->version = 'Version1'; +$normalRelease->desc = ''; +$normalRelease->lib = 910; +$normalRelease->addedBy = $tester->app->user->account; +$normalRelease->addedDate = helper::now(); + +$apiInfo = $api->createTest($normalApi, false); +$release = $api->publishLibTest($normalRelease, false); + +r($api->getStructListByReleaseTest()) && p() && e(); +r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api +//system("./ztest init"); From e74e7c90a1807be577eb49cc2afcc566b70e6c43 Mon Sep 17 00:00:00 2001 From: liyuchun <563917701@qq.com> Date: Mon, 9 May 2022 07:43:07 +0000 Subject: [PATCH 037/304] * Add unitcase. --- module/api/model.php | 9 ++++++--- test/class/api.class.php | 13 +++++++++++-- test/model/api/getlistbymoduleid.php | 5 ++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/module/api/model.php b/module/api/model.php index 4296aa73d6..34fc7a1758 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -375,9 +375,12 @@ class apiModel extends model public function getApiListByRelease($release, $where = '1 = 1 ') { $strJoin = array(); - foreach($release->snap['apis'] as $api) + if(isset($release->snap['apis'])) { - $strJoin[] = "(spec.doc = {$api['id']} and spec.version = {$api['version']} )"; + foreach($release->snap['apis'] as $api) + { + $strJoin[] = "(spec.doc = {$api['id']} and spec.version = {$api['version']} )"; + } } if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; @@ -404,7 +407,7 @@ class apiModel extends model $rel = $this->getRelease(0, 'byId', $release); $where = "1=1 and lib = $libID "; - if($moduleID > 0) + if($moduleID > 0 and isset($rel->snap['modules'])) { $sub = array(); foreach($rel->snap['modules'] as $module) diff --git a/test/class/api.class.php b/test/class/api.class.php index 3e91dc1793..77100bc680 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -152,13 +152,22 @@ class apiTest return $objects; } + /** + * Get list by module ID. + * + * @param int $libID + * @param int $moduleID + * @param int $release + * @access public + * @return void + */ public function getListByModuleIdTest($libID = 0, $moduleID = 0, $release = 0) { - $objects = $this->objectModel->getListByModuleId($libID = 0, $moduleID = 0, $release = 0); + $objects = $this->objectModel->getListByModuleId($libID, $moduleID, $release); if(dao::isError()) return dao::getError(); - return $objects; + return current($objects); } public function getStructByQueryTest($libID, $pager = '', $orderBy = '') diff --git a/test/model/api/getlistbymoduleid.php b/test/model/api/getlistbymoduleid.php index 67d75b9a32..d463eaa29a 100644 --- a/test/model/api/getlistbymoduleid.php +++ b/test/model/api/getlistbymoduleid.php @@ -14,4 +14,7 @@ pid=1 $api = new apiTest(); -r($api->getListByModuleIdTest()) && p() && e(); \ No newline at end of file +r($api->getListByModuleIdTest(1, 1, 1)) && p('title') && e('获取token'); //通过正常的libID、moduleID、releaseID查询api信息 +r($api->getListByModuleIdTest(1, 1, 0)) && p('title') && e('获取我的个人信息'); //通过正常的libID、moduleID,不传releaseID,查询api信息 +r($api->getListByModuleIdTest(1, 0, 0)) && p('title') && e('获取token'); //通过正常的libID,不传moduleID、releaseID查询api信息 +r($api->getListByModuleIdTest(0, 0, 0)) && p('title') && e('0'); //通过不存在的libID,moduleID,releaseID查询api信息 From b21e8bf480701dfed6537fdb33b779de61d951a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Tue, 10 May 2022 15:21:06 +0800 Subject: [PATCH 038/304] * Modify. --- module/api/model.php | 7 +++++-- test/class/api.class.php | 10 +--------- test/model/api/create.php | 2 -- test/model/api/createstruct.php | 2 -- test/model/api/deleterelease.php | 2 -- test/model/api/getapilistbyrelease.php | 1 - test/model/api/getlibbyid.php | 2 -- test/model/api/getrelease.php | 2 -- test/model/api/getreleaselistbyapi.php | 2 -- test/model/api/getstructbyid.php | 2 -- test/model/api/getstructlistbyrelease.php | 5 ++--- test/model/api/publishlib.php | 2 -- test/model/api/update.php | 2 -- test/model/api/updatestruct.php | 2 -- 14 files changed, 8 insertions(+), 35 deletions(-) diff --git a/module/api/model.php b/module/api/model.php index 34fc7a1758..cedaa2bb5b 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -500,9 +500,12 @@ class apiModel extends model public function getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id') { $strJoin = array(); - foreach($release->snap['structs'] as $struct) + if(isset($release->snap['structs'])) { - $strJoin[] = "(object.id = {$struct['id']} and spec.version = {$struct['version']} )"; + foreach($release->snap['structs'] as $struct) + { + $strJoin[] = "(object.id = {$struct['id']} and spec.version = {$struct['version']} )"; + } } if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; diff --git a/test/class/api.class.php b/test/class/api.class.php index 36452dee5c..669ec0d62f 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -128,6 +128,7 @@ class apiTest public function getReleaseListByApiTest($libID, $id = 0, $confirm = true) { $objects = $this->objectModel->getReleaseListByApi($libID); + a($objects); if(dao::isError()) return dao::getError(); @@ -248,13 +249,4 @@ class apiTest return $objects; } - - public function createDemoDataTest($name, $baseUrl, $version = '16.0') - { - $objects = $this->objectModel->createDemoData($name, $baseUrl, $version = '16.0'); - - if(dao::isError()) return dao::getError(); - - return $objects; - } } diff --git a/test/model/api/create.php b/test/model/api/create.php index 2ce82c6ecf..0c5abf7402 100644 --- a/test/model/api/create.php +++ b/test/model/api/create.php @@ -47,5 +47,3 @@ r($api->createTest($normalApi)) && p('lib') && e('910'); r($api->createTest($emptyLibApi)) && p('lib:0') && e('『API Library』should not be blank.'); //测试没有lib创建api r($api->createTest($emptyTitleApi)) && p('title:0') && e('『Name』should not be blank.'); //测试没有title创建api r($api->createTest($emptyPathApi)) && p('path:0') && e('『Request Path』should not be blank.'); //测试没有path创建api - -//system("./ztest init"); diff --git a/test/model/api/createstruct.php b/test/model/api/createstruct.php index 6c84017dec..b87296eb06 100644 --- a/test/model/api/createstruct.php +++ b/test/model/api/createstruct.php @@ -33,5 +33,3 @@ $normalStruct->addedDate = helper::now(); r($api->createStructTest($normalStruct)) && p('name') && e('struct'); //创建数据结构 r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『Name』should not be blank.'); //创建没有结构名的数据结构 - -//system("./ztest init"); diff --git a/test/model/api/deleterelease.php b/test/model/api/deleterelease.php index e26c018b02..3a55f87ba1 100644 --- a/test/model/api/deleterelease.php +++ b/test/model/api/deleterelease.php @@ -25,5 +25,3 @@ $normalRelease->addedDate = helper::now(); $release = $api->publishLibTest($normalRelease, false); r($api->deleteReleaseTest($release->id, $release->lib)) && p('') && e('0'); //删除一个创建的发布 - -//system("./ztest init"); diff --git a/test/model/api/getapilistbyrelease.php b/test/model/api/getapilistbyrelease.php index 6cf332b766..55f80d724c 100644 --- a/test/model/api/getapilistbyrelease.php +++ b/test/model/api/getapilistbyrelease.php @@ -45,4 +45,3 @@ $apiInfo = $api->createTest($normalApi, false); $release = $api->publishLibTest($normalRelease, false); r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api -//system("./ztest init"); diff --git a/test/model/api/getlibbyid.php b/test/model/api/getlibbyid.php index c8977e99f4..c884024d4a 100644 --- a/test/model/api/getlibbyid.php +++ b/test/model/api/getlibbyid.php @@ -36,5 +36,3 @@ $normalApi = $data; $apiInfo = $api->createTest($normalApi, false); r($api->getLibByIdTest($apiInfo->id)) && p('lib') && e('910'); //获取刚创建的api - -//system("./ztest init"); diff --git a/test/model/api/getrelease.php b/test/model/api/getrelease.php index 706f8509ea..a8728da6a8 100644 --- a/test/model/api/getrelease.php +++ b/test/model/api/getrelease.php @@ -24,5 +24,3 @@ $normalRelease->addedDate = helper::now(); $release = $api->publishLibTest($normalRelease, false); r($api->getReleaseTest($release->lib)) && p('version') && e('Version1'); //获取刚创建的发布 - -//system("./ztest init"); diff --git a/test/model/api/getreleaselistbyapi.php b/test/model/api/getreleaselistbyapi.php index f9d0fa231b..d9a542a37c 100644 --- a/test/model/api/getreleaselistbyapi.php +++ b/test/model/api/getreleaselistbyapi.php @@ -24,5 +24,3 @@ $normalRelease->addedDate = helper::now(); $release = $api->publishLibTest($normalRelease, false); r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("{$release->id}:lib") && e('910'); //获取刚插入的发布信息 - -//system("./ztest init"); diff --git a/test/model/api/getstructbyid.php b/test/model/api/getstructbyid.php index 850e53f665..503b36e58e 100644 --- a/test/model/api/getstructbyid.php +++ b/test/model/api/getstructbyid.php @@ -25,5 +25,3 @@ $normalStruct->addedDate = helper::now(); $struct = $api->createStructTest($normalStruct, false); r($api->getStructByIDTest($struct->id)) && p('name') && e('struct'); //获取刚创建的数据结构 - -//system("./ztest init"); diff --git a/test/model/api/getstructlistbyrelease.php b/test/model/api/getstructlistbyrelease.php index a8aeb8e44e..8099c03982 100644 --- a/test/model/api/getstructlistbyrelease.php +++ b/test/model/api/getstructlistbyrelease.php @@ -44,6 +44,5 @@ $normalRelease->addedDate = helper::now(); $apiInfo = $api->createTest($normalApi, false); $release = $api->publishLibTest($normalRelease, false); -r($api->getStructListByReleaseTest()) && p() && e(); -r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api -//system("./ztest init"); +r($api->getStructListByReleaseTest($release->lib)) && p('') && e(''); +//r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api diff --git a/test/model/api/publishlib.php b/test/model/api/publishlib.php index 373e0a3ebc..e6b0060132 100644 --- a/test/model/api/publishlib.php +++ b/test/model/api/publishlib.php @@ -31,5 +31,3 @@ $normalRelease->addedDate = helper::now(); r($api->publishLibTest($emptyBuildRelease)) && p('version:0') && e('『Version』should not be blank.'); //没有版本名的发布 r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布 - -//system("./ztest init"); diff --git a/test/model/api/update.php b/test/model/api/update.php index b243754af7..052c0cf149 100644 --- a/test/model/api/update.php +++ b/test/model/api/update.php @@ -57,5 +57,3 @@ $editApi = $editData; $apiInfo = $api->createTest($normalApi, false); r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api - -//system("./ztest init"); diff --git a/test/model/api/updatestruct.php b/test/model/api/updatestruct.php index 6d0baba8e1..74e0af5fdd 100644 --- a/test/model/api/updatestruct.php +++ b/test/model/api/updatestruct.php @@ -38,5 +38,3 @@ $emptyNameEditStruct['name'] = ''; $struct = $api->createStructTest($normalStruct, false); r($api->updateStructTest($struct->id, $normalEditStruct, false)) && p('0:new') && e('editStruct'); //正常的修改 r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『Name』should not be blank.'); //没有名称的修改 - -//system("./ztest init"); From 845c84a1eb2da52d68b1ccae2235abc4b60abea8 Mon Sep 17 00:00:00 2001 From: sunjun Date: Fri, 13 May 2022 02:53:47 +0000 Subject: [PATCH 039/304] *sprint_sunjun_631 --- module/execution/control.php | 15 ++++- .../execution/view/ajaxgetdropmenu.html.php | 63 ++++++++++++++----- module/project/model.php | 11 ++++ 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 0f3f306bda..407d833f02 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -3138,7 +3138,7 @@ class execution extends control foreach($executions as $execution) { - if(isset($orderedExecutions[$execution->parent])) unset($orderedExecutions[$execution->parent]); + if(isset($orderedExecutions[$execution->parent]) and $project->model != 'waterfall') unset($orderedExecutions[$execution->parent]); $execution->teams = zget($teams, $execution->id, array()); $orderedExecutions[$execution->id] = $execution; } @@ -3160,11 +3160,20 @@ class execution extends control $projectExecutions = array(); $parentIdList = array(); + $childrenIdList = array(); foreach($orderedExecutions as $execution) { - $projectExecutions[$execution->project][] = $execution; if($execution->type != 'stage') continue; - if($execution->grade == 2 and $execution->project != $execution->parent) $parentIdList[$execution->parent] = $execution->parent; + if($execution->grade == 2 and $execution->project != $execution->parent) + { + $parentIdList[$execution->parent] = $execution->parent; + $childrenIdList[$execution->parent][] = $execution->id; + } + } + foreach($orderedExecutions as $id => $execution) + { + $execution->children = isset($childrenIdList[$execution->id]) ? $childrenIdList[$execution->id] : array(); + $projectExecutions[$execution->project][] = $execution; } $parents = array(); diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index f5c2d77aa6..d504cfd1a3 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -71,7 +71,6 @@ foreach($executions as $projectID => $projectExecutions) if($executionCounts[$projectID]['others']) $normalExecutionsHtml .= '
            • '; if($executionCounts[$projectID]['closed']) $closedExecutionsHtml .= '
              • '; } - foreach($projectExecutions as $index => $execution) { $kanbanLink = $this->createLink('execution', 'kanban', "executionID=%s"); @@ -80,27 +79,63 @@ foreach($executions as $projectID => $projectExecutions) if($execution->type == 'kanban' and $link != $kanbanLink) $link = $kanbanLink; $selected = $execution->id == $executionID ? 'selected' : ''; - if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) + if(!empty($execution->children)) { - $myExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; + foreach($execution->children as $id) + { + $selected = $id == $executionID ? 'selected' : ''; + if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) + { + $myExecutionsHtml .= '
              • ' . html::a(sprintf($link, $id), $executionNames[$id], '', "class='$selected clickable' title='{$executionNames[$id]}' data-key='" . zget($executionsPinYin, $executionNames[$id], '') . "' data-app='{$this->app->tab}'") . '
              • '; - if($selected == 'selected') $tabActive = 'myExecution'; + if($selected == 'selected') $tabActive = 'myExecution'; - $myExecutions ++; + $myExecutions ++; + } + else if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM != $this->app->user->account and !isset($execution->teams[$this->app->user->account])) + { + $normalExecutionsHtml .= '
              • ' . html::a(sprintf($link, $id), $executionNames[$id], '', "class='$selected clickable' title='{$executionNames[$id]}' data-key='" . zget($executionsPinYin, $executionNames[$id], '') . "' data-app='{$this->app->tab}'") . '
              • '; + + if($selected == 'selected') $tabActive = 'other'; + + $others ++; + } + else if($execution->status == 'done' or $execution->status == 'closed') + { + $closedExecutionsHtml .= '
              • ' . html::a(sprintf($link, $id), $executionNames[$id], '', "class='$selected clickable' title='{$executionNames[$id]}' data-key='" . zget($executionsPinYin, $executionNames[$id], '') . "' data-app='{$this->app->tab}'") . '
              • '; + + if($selected == 'selected') $tabActive = 'closed'; + } + } } - else if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM != $this->app->user->account and !isset($execution->teams[$this->app->user->account])) + elseif($execution->grade == 2 and $execution->parent != $execution->project) { - $normalExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; - - if($selected == 'selected') $tabActive = 'other'; - - $others ++; + continue; } - else if($execution->status == 'done' or $execution->status == 'closed') + else { - $closedExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='$execution->name' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; + if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) + { + $myExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$executionNames[$execution->id]}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; - if($selected == 'selected') $tabActive = 'closed'; + if($selected == 'selected') $tabActive = 'myExecution'; + + $myExecutions ++; + } + else if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM != $this->app->user->account and !isset($execution->teams[$this->app->user->account])) + { + $normalExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$executionNames[$execution->id]}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; + + if($selected == 'selected') $tabActive = 'other'; + + $others ++; + } + else if($execution->status == 'done' or $execution->status == 'closed') + { + $closedExecutionsHtml .= '
              • ' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$executionNames[$execution->id]}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
              • '; + + if($selected == 'selected') $tabActive = 'closed'; + } } /* If the execution is the last one in the project, print the closed label. */ diff --git a/module/project/model.php b/module/project/model.php index b65d3d13af..b46a01e92b 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2285,6 +2285,17 @@ class projectModel extends model } /* In the case of the waterfall model, calculate the sub-stage. */ + if($projectID == 0) + { + foreach($executions as $key => $execution) + { + if($execution->type == 'stage') + { + $execution->children = isset($children[$execution->id]) ? $children[$execution->id] : array(); + unset($children[$execution->id]); + } + } + } $project = $this->getByID($projectID); if($project and $project->model == 'waterfall') { From 730561654f6948260e881491cba8101bb6ec6dfd Mon Sep 17 00:00:00 2001 From: sunjun Date: Fri, 13 May 2022 05:41:39 +0000 Subject: [PATCH 040/304] sprint_sunjun_631 --- module/execution/view/ajaxgetdropmenu.html.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index d504cfd1a3..9b3d5afaf2 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -71,6 +71,7 @@ foreach($executions as $projectID => $projectExecutions) if($executionCounts[$projectID]['others']) $normalExecutionsHtml .= '
                • '; if($executionCounts[$projectID]['closed']) $closedExecutionsHtml .= '
                  • '; } + foreach($projectExecutions as $index => $execution) { $kanbanLink = $this->createLink('execution', 'kanban', "executionID=%s"); @@ -108,11 +109,7 @@ foreach($executions as $projectID => $projectExecutions) } } } - elseif($execution->grade == 2 and $execution->parent != $execution->project) - { - continue; - } - else + elseif($execution->grade ==1) { if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { From e9aab00257bdf322dba2fdb58d45ca2e21697a3e Mon Sep 17 00:00:00 2001 From: sunjun Date: Sat, 14 May 2022 19:39:22 +0800 Subject: [PATCH 041/304] sprint_sunjun_631 --- module/execution/control.php | 10 ---------- module/execution/view/all.html.php | 23 +++++++++++------------ 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 407d833f02..17ac64b75a 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -3342,20 +3342,10 @@ class execution extends control $executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager); - $parentIdList = array(); - foreach($executionStats as $execution) - { - if($execution->type != 'stage') continue; - if($execution->grade == 2 and $execution->project != $execution->parent) $parentIdList[$execution->parent] = $execution->parent; - } - $parents = array(); - if($parentIdList) $parents = $this->execution->getByIdList($parentIdList); - $this->view->executionStats = $executionStats; $this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID); $this->view->productID = $productID; $this->view->projectID = $projectID; - $this->view->parents = $parents; $this->view->projects = array('') + $this->project->getPairsByProgram(); $this->view->pager = $pager; $this->view->orderBy = $orderBy; diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 299daac777..6d7691160d 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -38,6 +38,7 @@ config->systemMode == 'new'):?>
                    + execution->selectProject}'");?>
                    @@ -127,18 +128,12 @@ id);?> - name; - $onlyChildStage = ($execution->grade == 2 and $execution->project != $execution->parent); - if($onlyChildStage and isset($parents[$execution->parent])) $executionName = $parents[$execution->parent]->name . '/' . $executionName; - ?> - flex' title=''> + flex' title='name?>'> systemMode == 'new'):?> '>execution->typeList[$execution->type]?> projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $executionName, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $executionName, '', "class='text-ellipsis'"); - if($onlyChildStage) echo "{$lang->programplan->childrenAB} "; + $executionLink = $execution->projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $execution->name, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'"); echo !empty($execution->children) ? $execution->name : $executionLink; if(isset($execution->delay)) echo "{$lang->execution->delayed} "; ?> @@ -146,7 +141,7 @@ - + code;?> systemMode == 'new' and $this->app->tab == 'execution'):?> @@ -228,6 +223,10 @@ if(isset($child->delay)) echo "{$lang->execution->delayed} "; ?> + + code;?> + projectName;?> + PM);?> processStatus('execution', $child);?> @@ -236,7 +235,7 @@ hours->progress); ?> - + percent . '%';?> stage->typeList, $child->attribute, '');?> begin) ? '' : $child->begin;?> @@ -269,11 +268,11 @@ ?> + begin;?>'>begin) ? '' : $child->begin;?> + end;?>'>end) ? '' : $child->end;?> lang->execution->workHour;?>'>hours->totalEstimate . ' ' . $this->lang->execution->workHourUnit;?> lang->execution->workHour;?>'>hours->totalConsumed . ' ' . $this->lang->execution->workHourUnit;?> lang->execution->workHour;?>'>hours->totalLeft . ' ' . $this->lang->execution->workHourUnit;?> - - burns);?>'> " . $this->loadModel('flow')->getFieldValue($extendField, $child) . "";?> From 9ad4d27dc46e43a145c6d15690c2e5eab803cc5c Mon Sep 17 00:00:00 2001 From: sunjun Date: Sat, 14 May 2022 20:32:54 +0800 Subject: [PATCH 042/304] sprint_sunjun_631 --- module/execution/view/all.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 6d7691160d..8bd968fbfd 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -141,7 +141,7 @@ - + code;?> systemMode == 'new' and $this->app->tab == 'execution'):?> From 486355165843d23d51a051e9e5e9c05dca07e0f5 Mon Sep 17 00:00:00 2001 From: sunjun Date: Sat, 14 May 2022 21:06:48 +0800 Subject: [PATCH 043/304] sprint_sunjun_631 --- module/execution/view/all.html.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 8bd968fbfd..03c34d9e3a 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -225,7 +225,9 @@ code;?> - projectName;?> + systemMode == 'new'):?> + projectName;?> + PM);?> processStatus('execution', $child);?> From f5fe24b54f619f937c253c6c7c672b13b9ee58ae Mon Sep 17 00:00:00 2001 From: sunjun Date: Sun, 15 May 2022 12:47:45 +0800 Subject: [PATCH 044/304] sprint_sunjun_631 --- module/execution/view/ajaxgetdropmenu.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index 9b3d5afaf2..b334bc227b 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -109,7 +109,7 @@ foreach($executions as $projectID => $projectExecutions) } } } - elseif($execution->grade ==1) + elseif($execution->grade == 1 or $config->systemMode == 'classic') { if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { From a4f026d786e72e458a6c3208e0c0fad0d44b2e33 Mon Sep 17 00:00:00 2001 From: sunjun Date: Mon, 16 May 2022 09:08:47 +0800 Subject: [PATCH 045/304] sprint_sunjun_631 --- module/execution/control.php | 10 ++++++++++ module/execution/view/all.html.php | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 17ac64b75a..407d833f02 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -3342,10 +3342,20 @@ class execution extends control $executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager); + $parentIdList = array(); + foreach($executionStats as $execution) + { + if($execution->type != 'stage') continue; + if($execution->grade == 2 and $execution->project != $execution->parent) $parentIdList[$execution->parent] = $execution->parent; + } + $parents = array(); + if($parentIdList) $parents = $this->execution->getByIdList($parentIdList); + $this->view->executionStats = $executionStats; $this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID); $this->view->productID = $productID; $this->view->projectID = $projectID; + $this->view->parents = $parents; $this->view->projects = array('') + $this->project->getPairsByProgram(); $this->view->pager = $pager; $this->view->orderBy = $orderBy; diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 03c34d9e3a..15d04376ac 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -128,13 +128,19 @@ id);?> - flex' title='name?>'> + name; + $onlyChildStage = ($execution->grade == 2 and $execution->project != $execution->parent); + if($onlyChildStage and isset($parents[$execution->parent])) $executionName = $parents[$execution->parent]->name . '/' . $executionName; + ?> + flex' title=''> systemMode == 'new'):?> '>execution->typeList[$execution->type]?> projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $execution->name, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'"); + $executionLink = $execution->projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $executionName, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $executionName, '', "class='text-ellipsis'"); echo !empty($execution->children) ? $execution->name : $executionLink; + if($onlyChildStage) echo "{$lang->programplan->childrenAB} "; if(isset($execution->delay)) echo "{$lang->execution->delayed} "; ?> children)):?> From 249190e049acde155929334911d8cdd035829d59 Mon Sep 17 00:00:00 2001 From: sunjun Date: Mon, 16 May 2022 09:11:50 +0800 Subject: [PATCH 046/304] sprint_sunjun_631 --- module/execution/view/all.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 15d04376ac..02761a9d33 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -139,8 +139,8 @@ projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $executionName, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $executionName, '', "class='text-ellipsis'"); - echo !empty($execution->children) ? $execution->name : $executionLink; if($onlyChildStage) echo "{$lang->programplan->childrenAB} "; + echo !empty($execution->children) ? $execution->name : $executionLink; if(isset($execution->delay)) echo "{$lang->execution->delayed} "; ?> children)):?> From d26e9a0c942d2091ff606fb860756810474af860 Mon Sep 17 00:00:00 2001 From: sunjun Date: Mon, 16 May 2022 09:13:55 +0800 Subject: [PATCH 047/304] sprint_sunjun_631 --- module/execution/view/all.html.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 02761a9d33..c747140a80 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -38,7 +38,6 @@ config->systemMode == 'new'):?>
                    - execution->selectProject}'");?>
                    From 08dcf36583acd33334706253670831fa95d545fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Mon, 16 May 2022 09:14:37 +0800 Subject: [PATCH 048/304] * Modify testcase. --- test/model/api/getmethod.php | 17 ----------------- test/model/api/getreleasebyquery.php | 17 ----------------- test/model/api/getstructbyquery.php | 17 ----------------- test/model/api/getstructtreebylib.php | 17 ----------------- test/model/api/gettypelist.php | 17 ----------------- test/model/api/sql.php | 17 ----------------- 6 files changed, 102 deletions(-) delete mode 100644 test/model/api/getmethod.php delete mode 100644 test/model/api/getreleasebyquery.php delete mode 100644 test/model/api/getstructbyquery.php delete mode 100644 test/model/api/getstructtreebylib.php delete mode 100644 test/model/api/gettypelist.php delete mode 100644 test/model/api/sql.php diff --git a/test/model/api/getmethod.php b/test/model/api/getmethod.php deleted file mode 100644 index 541abc2054..0000000000 --- a/test/model/api/getmethod.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -getMethod(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->getMethodTest()) && p() && e(); diff --git a/test/model/api/getreleasebyquery.php b/test/model/api/getreleasebyquery.php deleted file mode 100644 index ee8d4a2fa0..0000000000 --- a/test/model/api/getreleasebyquery.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -getReleaseByQuery(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->getReleaseByQueryTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructbyquery.php b/test/model/api/getstructbyquery.php deleted file mode 100644 index 58b2be86b3..0000000000 --- a/test/model/api/getstructbyquery.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -getStructByQuery(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->getStructByQueryTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/getstructtreebylib.php b/test/model/api/getstructtreebylib.php deleted file mode 100644 index 52a2724d67..0000000000 --- a/test/model/api/getstructtreebylib.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -getStructTreeByLib(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->getStructTreeByLibTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/gettypelist.php b/test/model/api/gettypelist.php deleted file mode 100644 index 1b332719a2..0000000000 --- a/test/model/api/gettypelist.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -getTypeList(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->getTypeListTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/api/sql.php b/test/model/api/sql.php deleted file mode 100644 index d353aed638..0000000000 --- a/test/model/api/sql.php +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env php -sql(); -cid=1 -pid=1 - -*/ - -$api = new apiTest(); - -r($api->sqlTest()) && p() && e(); \ No newline at end of file From 750877376b1013ab36a832a7845d9780edf18e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Mon, 16 May 2022 09:14:58 +0800 Subject: [PATCH 049/304] * Modify testcase. --- test/class/api.class.php | 53 ---------------------------------------- 1 file changed, 53 deletions(-) diff --git a/test/class/api.class.php b/test/class/api.class.php index 669ec0d62f..b92a9256ae 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -178,15 +178,6 @@ class apiTest return current($objects); } - public function getStructByQueryTest($libID, $pager = '', $orderBy = '') - { - $objects = $this->objectModel->getStructByQuery($libID, $pager = '', $orderBy = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - public function getStructListByReleaseTest($release, $where = '1 = 1 ', $orderBy = 'id') { $objects = $this->objectModel->getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id'); @@ -196,15 +187,6 @@ class apiTest return $objects; } - public function getReleaseByQueryTest($libID, $pager = '', $orderBy = '') - { - $objects = $this->objectModel->getReleaseByQuery($libID, $pager = '', $orderBy = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - public function getStructTreeByLibTest($libID = 0, $structID = 0) { $objects = $this->objectModel->getStructTreeByLib($libID = 0, $structID = 0); @@ -214,39 +196,4 @@ class apiTest return $objects; } - public function getMethodTest($filePath, $ext = '') - { - $objects = $this->objectModel->getMethod($filePath, $ext = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - public function requestTest($moduleName, $methodName, $action) - { - $objects = $this->objectModel->request($moduleName, $methodName, $action); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - public function sqlTest($sql, $keyField = '') - { - $objects = $this->objectModel->sql($sql, $keyField = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - public function getTypeListTest($libID) - { - $objects = $this->objectModel->getTypeList($libID); - - if(dao::isError()) return dao::getError(); - - return $objects; - } } From ef4c0d984902b7e54ce76e5cef610987cb5787c6 Mon Sep 17 00:00:00 2001 From: zenggang Date: Mon, 16 May 2022 02:46:27 +0000 Subject: [PATCH 050/304] * Fix bug#22471 --- module/search/view/buildform.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php index 494fb16547..d2e6cbe7da 100644 --- a/module/search/view/buildform.html.php +++ b/module/search/view/buildform.html.php @@ -416,7 +416,7 @@ $(function() { var $e = $(e.target); var ePos = $e.offset(); - $period.css({'left': ePos.left + 211, 'top': ePos.top + 29, 'min-height': $('.datetimepicker').outerHeight()}).show().data('target', $e.attr('id')).data('fieldNO', fieldNO).find('li.active').removeClass('active'); + $period.css({'left': ePos.left - 120, 'top': ePos.top + 29, 'min-height': $('.datetimepicker').outerHeight()}).show().data('target', $e.attr('id')).data('fieldNO', fieldNO).find('li.active').removeClass('active'); if($e.attr('placeholder')) { $period.find("li > a[href='" + $e.attr('placeholder').replace('$', '#') + "']").closest('li').addClass('active'); From 073ee90d40dd429e1b1ee6af32e0daaf4588bac7 Mon Sep 17 00:00:00 2001 From: sunjun Date: Mon, 16 May 2022 11:10:20 +0800 Subject: [PATCH 051/304] sprint_sunjun_631 --- module/execution/view/ajaxgetdropmenu.html.php | 3 ++- module/product/view/ajaxgetdropmenu.html.php | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index b334bc227b..45c6013935 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -26,6 +26,7 @@ #closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;} #gray-line {width: 230px;height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;} #dropMenu.has-search-text .hide-in-search {display: flex;} +#swapper li>.selected {color: #0c64eb!important; background: #e9f2fb!important;} $projectExecutions) } } } - elseif($execution->grade == 1 or $config->systemMode == 'classic') + else if($execution->grade == 1 or $config->systemMode == 'classic') { if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { diff --git a/module/product/view/ajaxgetdropmenu.html.php b/module/product/view/ajaxgetdropmenu.html.php index d7e1be4a9d..dab16dd063 100644 --- a/module/product/view/ajaxgetdropmenu.html.php +++ b/module/product/view/ajaxgetdropmenu.html.php @@ -28,6 +28,7 @@ #subHeader .tree ul {display: block;} #closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;} #gray-line {width: 230px; height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;} +#swapper li >.selected {color: #0c64eb!important;background: #e9f2fb!important;} Date: Mon, 16 May 2022 13:43:08 +0800 Subject: [PATCH 052/304] * Fix bug #22490. --- module/caselib/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/caselib/model.php b/module/caselib/model.php index bbdd5e2ee2..ba94410657 100644 --- a/module/caselib/model.php +++ b/module/caselib/model.php @@ -258,7 +258,7 @@ class caselibModel extends model $cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery) ->beginIF($queryLibID != 'all')->andWhere('lib')->eq((int)$libID)->fi() - ->beginIF($this->config->systemMode == 'new' and $this->lang->navGroup->caselib != 'qa')->andWhere('project')->eq($this->session->project)->fi() + ->beginIF($this->config->systemMode == 'new' and $this->app->tab != 'qa')->andWhere('project')->eq($this->session->project)->fi() ->andWhere('product')->eq(0) ->andWhere('deleted')->eq(0) ->orderBy($sort)->page($pager)->fetchAll(); @@ -282,7 +282,7 @@ class caselibModel extends model $this->config->testcase->search['params']['lib']['values'] = array('' => '', $libID => $libraries[$libID], 'all' => $this->lang->caselib->all); $this->config->testcase->search['params']['lib']['operator'] = '='; $this->config->testcase->search['params']['lib']['control'] = 'select'; - $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($libID, $viewType = 'caselib'); + $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($libID, 'caselib'); if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']); unset($this->config->testcase->search['fields']['product']); unset($this->config->testcase->search['params']['product']); From a0bd326f3b7dfcc8988344cd9fa0e5d3b8f8e38e Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Mon, 16 May 2022 06:43:34 +0000 Subject: [PATCH 053/304] * Fix bug. --- db/update16.5.sql | 2 +- module/bug/model.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/update16.5.sql b/db/update16.5.sql index 0de2bd993f..f5fb998d89 100644 --- a/db/update16.5.sql +++ b/db/update16.5.sql @@ -341,7 +341,7 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c ('testcase', 'fromCaseVersion', 'char', '30', '用例来源版本', 'input', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'precondition', 'text', '', '前置条件', 'textarea', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), -('testsuite', 'type', 'text', '', '类型', 'redio', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); +('testsuite', 'type', 'text', '', '类型', 'radio', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projectModel' ORDER BY id DESC LIMIT 1) WHERE `module`='project' AND `field`='model'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY id DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type'; diff --git a/module/bug/model.php b/module/bug/model.php index 9ff6b81d69..0c2536da59 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -3276,7 +3276,7 @@ class bugModel extends model $menu .= $this->buildMenu('bug', 'confirmBug', $params, $bug, $type, 'ok', '', "iframe", true); if($type == 'view') $menu .= $this->buildMenu('bug', 'assignTo', $params, $bug, $type, '', '', "iframe", true); - $menu .= $this->buildMenu('bug', 'resolve', $params, $bug, $type, 'checked', '', "iframe", true); + $menu .= $this->buildMenu('bug', 'resolve', $params, $bug, $type, 'checked', '', "iframe showinonlybody", true); $menu .= $this->buildMenu('bug', 'close', $params, $bug, $type, '', '', "text-danger iframe showinonlybody", true); if($type == 'view') $menu .= $this->buildMenu('bug', 'activate', $params, $bug, $type, '', '', "text-success iframe showinonlybody", true); if($type == 'view' && $this->app->tab != 'product') From ad9305f120eed5586cef3ec8727b4700c27e5440 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Mon, 16 May 2022 06:53:14 +0000 Subject: [PATCH 054/304] * Fix bug. --- db/update16.5.sql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/db/update16.5.sql b/db/update16.5.sql index f5fb998d89..b801aad61a 100644 --- a/db/update16.5.sql +++ b/db/update16.5.sql @@ -340,8 +340,7 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c ('testcase', 'fromCaseID', 'char', '30', '用例来源ID', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'fromCaseVersion', 'char', '30', '用例来源版本', 'input', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'precondition', 'text', '', '前置条件', 'textarea', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), -('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), -('testsuite', 'type', 'text', '', '类型', 'radio', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); +('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projectModel' ORDER BY id DESC LIMIT 1) WHERE `module`='project' AND `field`='model'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY id DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type'; @@ -352,7 +351,7 @@ UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='project' AND `field`='parent'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projects' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='execution' AND `field`='parent'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason'; -UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY id DESC LIMIT 1), `control`='redio' WHERE `module`='testsuite' AND `field`='type'; +UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY id DESC LIMIT 1), `control`='radio' WHERE `module`='testsuite' AND `field`='type'; UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='browse'; UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='create'; From d0a5b69f6e5a0d092f8b68b9e1ff9856b305f6b2 Mon Sep 17 00:00:00 2001 From: tanghucheng Date: Mon, 16 May 2022 06:57:50 +0000 Subject: [PATCH 055/304] * Fix bug for sql. --- db/update16.5.sql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/db/update16.5.sql b/db/update16.5.sql index 0de2bd993f..b801aad61a 100644 --- a/db/update16.5.sql +++ b/db/update16.5.sql @@ -340,8 +340,7 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c ('testcase', 'fromCaseID', 'char', '30', '用例来源ID', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'fromCaseVersion', 'char', '30', '用例来源版本', 'input', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), ('testcase', 'precondition', 'text', '', '前置条件', 'textarea', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), -('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'), -('testsuite', 'type', 'text', '', '类型', 'redio', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); +('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'); UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projectModel' ORDER BY id DESC LIMIT 1) WHERE `module`='project' AND `field`='model'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY id DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type'; @@ -352,7 +351,7 @@ UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='project' AND `field`='parent'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projects' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='execution' AND `field`='parent'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason'; -UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY id DESC LIMIT 1), `control`='redio' WHERE `module`='testsuite' AND `field`='type'; +UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY id DESC LIMIT 1), `control`='radio' WHERE `module`='testsuite' AND `field`='type'; UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='browse'; UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='create'; From e085535743def839783aa705a800814df99400d2 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 16 May 2022 14:59:06 +0800 Subject: [PATCH 056/304] * Fix bug#22375. --- module/task/control.php | 8 ++++---- module/task/view/batchcreate.html.php | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/module/task/control.php b/module/task/control.php index d9d0637b80..22dd0806b0 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -333,7 +333,7 @@ class task extends control if(!empty($_POST)) { $mails = $this->task->batchCreate($executionID, $extra); - if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + if(dao::isError()) return print(js::error(dao::getError())); $taskIDList = array(); foreach($mails as $mail) $taskIDList[] = $mail->taskID; @@ -349,14 +349,14 @@ class task extends control $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all'); $kanbanData = json_encode($kanbanData); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)")); + return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, 0)")); } else { - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); + return print(js::reload('parent.parent')); } } - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $taskLink)); + return print(js::locate($taskLink, 'parent')); } $story = $this->story->getByID($storyID); diff --git a/module/task/view/batchcreate.html.php b/module/task/view/batchcreate.html.php index fa922a4fd2..43756f432f 100755 --- a/module/task/view/batchcreate.html.php +++ b/module/task/view/batchcreate.html.php @@ -57,7 +57,7 @@ } $colspan = count($visibleFields) + 3; ?> -
                    +
                    @@ -81,7 +81,7 @@ task->getFlowExtendFields(); - foreach($extendFields as $extendField) + foreach($extendFields as $extendField) { $required = strpos(",$extendField->rules,", ',1,') !== false ? 'required' : ''; echo ""; @@ -166,9 +166,9 @@ - loadModel('flow'); - foreach($extendFields as $extendField) + foreach($extendFields as $extendField) { $object = new stdclass(); $object->{$extendField->field} = $extendField->default; @@ -240,9 +240,9 @@ - loadModel('flow'); - foreach($extendFields as $extendField) + foreach($extendFields as $extendField) { $object = new stdclass(); $object->{$extendField->field} = $extendField->default; From 39c0ad9c17e7268dde9210fdce58870e93368407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Mon, 16 May 2022 16:08:30 +0800 Subject: [PATCH 057/304] *Finish task #54207. --- module/task/model.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index f070271d1d..398eb17cb9 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1069,7 +1069,8 @@ class taskModel extends model $this->dao->insert(TABLE_TASKSPEC)->data($taskSpec)->autoCheck()->exec(); } - if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); + if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); + elseif($oldTask->story != false) $this->loadModel('story')->setStage($oldTask->story); if($task->status == 'done') $this->loadModel('score')->create('task', 'finish', $taskID); if($task->status == 'closed') $this->loadModel('score')->create('task', 'close', $taskID); if($task->status != $oldTask->status) $this->loadModel('kanban')->updateLane($task->execution, 'task', $taskID); From 4c968d5872d39d1ff8c21ccff46149a0fdb3081f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Mon, 16 May 2022 16:21:34 +0800 Subject: [PATCH 058/304] *Optimize the code. --- module/task/model.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/task/model.php b/module/task/model.php index 398eb17cb9..e2dcb02ef3 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1069,8 +1069,11 @@ class taskModel extends model $this->dao->insert(TABLE_TASKSPEC)->data($taskSpec)->autoCheck()->exec(); } - if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); - elseif($oldTask->story != false) $this->loadModel('story')->setStage($oldTask->story); + if($this->post->story != $oldTask->story) + { + $this->loadModel('story')->setStage($this->post->story); + $this->loadModel('story')->setStage($oldTask->story); + } if($task->status == 'done') $this->loadModel('score')->create('task', 'finish', $taskID); if($task->status == 'closed') $this->loadModel('score')->create('task', 'close', $taskID); if($task->status != $oldTask->status) $this->loadModel('kanban')->updateLane($task->execution, 'task', $taskID); From ecea8c61471844d169ab4c345819dc7660a30f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Mon, 16 May 2022 08:24:40 +0000 Subject: [PATCH 059/304] Update model.php --- module/task/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index e2dcb02ef3..b1d739e7af 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1072,7 +1072,7 @@ class taskModel extends model if($this->post->story != $oldTask->story) { $this->loadModel('story')->setStage($this->post->story); - $this->loadModel('story')->setStage($oldTask->story); + $this->story->setStage($oldTask->story); } if($task->status == 'done') $this->loadModel('score')->create('task', 'finish', $taskID); if($task->status == 'closed') $this->loadModel('score')->create('task', 'close', $taskID); From 94af8b93af5df2383e5c123b284acbf55efc1208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Mon, 16 May 2022 16:26:19 +0800 Subject: [PATCH 060/304] *Optimize the code. --- module/task/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index b1d739e7af..83a9d9a7b6 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1075,7 +1075,7 @@ class taskModel extends model $this->story->setStage($oldTask->story); } if($task->status == 'done') $this->loadModel('score')->create('task', 'finish', $taskID); - if($task->status == 'closed') $this->loadModel('score')->create('task', 'close', $taskID); + if($task->status == 'closed') $this->score->create('task', 'close', $taskID); if($task->status != $oldTask->status) $this->loadModel('kanban')->updateLane($task->execution, 'task', $taskID); $this->loadModel('action'); $changed = $task->parent != $oldTask->parent; From 3ae610d77dd53fc1b178f2a6076c58b968424795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Mon, 16 May 2022 08:27:21 +0000 Subject: [PATCH 061/304] Update model.php --- module/task/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index 83a9d9a7b6..b1d739e7af 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1075,7 +1075,7 @@ class taskModel extends model $this->story->setStage($oldTask->story); } if($task->status == 'done') $this->loadModel('score')->create('task', 'finish', $taskID); - if($task->status == 'closed') $this->score->create('task', 'close', $taskID); + if($task->status == 'closed') $this->loadModel('score')->create('task', 'close', $taskID); if($task->status != $oldTask->status) $this->loadModel('kanban')->updateLane($task->execution, 'task', $taskID); $this->loadModel('action'); $changed = $task->parent != $oldTask->parent; From 5ee54fb81ab2b84b16818be3d5f87afb9e1e4f21 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 16 May 2022 16:30:24 +0800 Subject: [PATCH 062/304] * Fix bug#22496. --- module/group/lang/resource.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 9e7c18a9bd..e4531417e3 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -470,9 +470,7 @@ $lang->resource->branch->edit = 'editAction'; $lang->resource->branch->close = 'closeAction'; $lang->resource->branch->activate = 'activateAction'; $lang->resource->branch->sort = 'sort'; -$lang->resource->branch->delete = 'delete'; $lang->resource->branch->batchEdit = 'batchEdit'; -$lang->resource->branch->setDefault = 'setDefaultAction'; $lang->resource->branch->mergeBranch = 'mergeBranchAction'; $lang->branch->methodOrder[0] = 'manage'; @@ -480,10 +478,8 @@ $lang->branch->methodOrder[5] = 'create'; $lang->branch->methodOrder[10] = 'edit'; $lang->branch->methodOrder[15] = 'close'; $lang->branch->methodOrder[20] = 'activate'; -$lang->branch->methodOrder[25] = 'sort'; -$lang->branch->methodOrder[30] = 'delete'; -$lang->branch->methodOrder[35] = 'batchEdit'; -$lang->branch->methodOrder[40] = 'setDefault'; +$lang->branch->methodOrder[35] = 'sort'; +$lang->branch->methodOrder[30] = 'batchEdit'; $lang->branch->methodOrder[45] = 'mergeBranch'; /* Story. */ From c01b9f54cf183dac6a4d66c7327a7e701049d209 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 16 May 2022 16:40:25 +0800 Subject: [PATCH 063/304] * Fix bug#22496. --- module/group/lang/resource.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index e4531417e3..953c7b9aed 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -478,9 +478,9 @@ $lang->branch->methodOrder[5] = 'create'; $lang->branch->methodOrder[10] = 'edit'; $lang->branch->methodOrder[15] = 'close'; $lang->branch->methodOrder[20] = 'activate'; -$lang->branch->methodOrder[35] = 'sort'; +$lang->branch->methodOrder[25] = 'sort'; $lang->branch->methodOrder[30] = 'batchEdit'; -$lang->branch->methodOrder[45] = 'mergeBranch'; +$lang->branch->methodOrder[35] = 'mergeBranch'; /* Story. */ $lang->resource->story = new stdclass(); From 19565d5455728549da027ef41cac7f9031615a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E8=BE=B0=E8=BD=A9?= Date: Mon, 16 May 2022 17:02:26 +0800 Subject: [PATCH 064/304] * Add comment. --- test/class/api.class.php | 124 +++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 11 deletions(-) diff --git a/test/class/api.class.php b/test/class/api.class.php index b92a9256ae..4d16170329 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -7,6 +7,14 @@ class apiTest $this->objectModel = $tester->loadModel('api'); } + /** + * Test publish a lib. + * + * @param object $data + * @param bool $confirm + * @access public + * @return object + */ public function publishLibTest($data, $confirm = true) { $objectID = $this->objectModel->publishLib($data); @@ -20,6 +28,14 @@ class apiTest return $objects; } + /** + * Test delete a release. + * + * @param int $id + * @param int $libID + * @access public + * @return object + */ public function deleteReleaseTest($id, $libID = 0) { $this->objectModel->deleteRelease($id); @@ -31,6 +47,14 @@ class apiTest return $objects; } + /** + * Test create a api. + * + * @param array $params + * @param bool $confirm + * @access public + * @return object + */ public function createTest($params, $confirm = true) { global $tester; @@ -45,6 +69,14 @@ class apiTest return $objects; } + /** + * Test create a data struct. + * + * @param object $data + * @param bool $confirm + * @access public + * @return object + */ public function createStructTest($data, $confirm = true) { global $tester; @@ -60,6 +92,15 @@ class apiTest return $objects; } + /** + * Test update a data struct. + * + * @param int $id + * @param array $params + * @param bool $confirm + * @access public + * @return object + */ public function updateStructTest($id, $params, $confirm = true) { global $tester; @@ -74,6 +115,15 @@ class apiTest return $objects; } + /** + * Test update a api. + * + * @param int $apiID + * @param array $params + * @param bool $confirm + * @access public + * @return object + */ public function updateTest($apiID, $params, $confirm = true) { global $tester; @@ -88,6 +138,14 @@ class apiTest return $objects; } + /** + * Test get data struct list by libID. + * + * @param int $id + * @param bool $confirm + * @access public + * @return object + */ public function getStructListByLibIDTest($id, $confirm = true) { global $tester; @@ -101,6 +159,14 @@ class apiTest return $objects; } + /** + * Test get a data struct by ID. + * + * @param int $id + * @param bool $confirm + * @access public + * @return object + */ public function getStructByIDTest($id, $confirm = true) { global $tester; @@ -114,6 +180,16 @@ class apiTest return $objects; } + /** + * Test get release by libID. + * + * @param int $libID + * @param string $type + * @param int $params + * @param bool $confirm + * @access public + * @return object + */ public function getReleaseTest($libID = 0, $type = '', $param = 0, $confirm = true) { $objects = $this->objectModel->getRelease($libID = 0, $type = '', $param = 0); @@ -125,6 +201,15 @@ class apiTest return $objects; } + /** + * Test get release list by api. + * + * @param int $libID + * @param int $id + * @param bool $confirm + * @access public + * @return object + */ public function getReleaseListByApiTest($libID, $id = 0, $confirm = true) { $objects = $this->objectModel->getReleaseListByApi($libID); @@ -137,6 +222,15 @@ class apiTest return $objects; } + /** + * Test get lib by ID. + * + * @param int $id + * @param int $version + * @param int $release + * @access public + * @return object + */ public function getLibByIdTest($id, $version = 0, $release = 0) { $objects = $this->objectModel->getLibById($id, $version = 0, $release = 0); @@ -146,6 +240,15 @@ class apiTest return $objects; } + /** + * Test get lib by ID. + * + * @param int $id + * @param int $version + * @param int $release + * @access public + * @return object + */ public function getApiListByReleaseTest($release, $where = '1 = 1 ') { global $tester; @@ -161,7 +264,7 @@ class apiTest } /** - * Get list by module ID. + * Test get list by module ID. * * @param int $libID * @param int $moduleID @@ -178,6 +281,15 @@ class apiTest return current($objects); } + /** + * Test get struct list by release. + * + * @param object $release + * @param string $where + * @param string $orderBy + * @access public + * @return object + */ public function getStructListByReleaseTest($release, $where = '1 = 1 ', $orderBy = 'id') { $objects = $this->objectModel->getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id'); @@ -186,14 +298,4 @@ class apiTest return $objects; } - - public function getStructTreeByLibTest($libID = 0, $structID = 0) - { - $objects = $this->objectModel->getStructTreeByLib($libID = 0, $structID = 0); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - } From 48c052efadb32f562d2cb609d4ad87cd73842b43 Mon Sep 17 00:00:00 2001 From: zhouxudong Date: Mon, 16 May 2022 09:23:29 +0000 Subject: [PATCH 065/304] * Fix bug #22531. --- lib/base/front/front.class.php | 5 +---- module/bug/model.php | 2 +- module/bug/view/view.html.php | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index a2ebdd9851..1e51691d89 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -509,10 +509,7 @@ class baseHTML setcookie('goback', json_encode($gobackList), $config->cookieLife, $config->webRoot, '', $config->cookieSecure, false); } - $dataApp = array_search($gobackLink, $gobackList) ? array_search($gobackLink, $gobackList) : ''; - $dataApp = empty($dataApp) ? '' : "data-app='$dataApp'"; - - return "{$label}"; + return "{$label}"; } /** diff --git a/module/bug/model.php b/module/bug/model.php index 9ff6b81d69..0062ffdc16 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -3281,7 +3281,7 @@ class bugModel extends model if($type == 'view') $menu .= $this->buildMenu('bug', 'activate', $params, $bug, $type, '', '', "text-success iframe showinonlybody", true); if($type == 'view' && $this->app->tab != 'product') { - $menu .= $this->buildMenu('bug', 'toStory', $toStoryParams, $bug, $type, $this->lang->icons['story'], '', '', '', "data-app='product'", $this->lang->bug->toStory); + $menu .= $this->buildMenu('bug', 'toStory', $toStoryParams, $bug, $type, $this->lang->icons['story'], '', '', '', "data-app='qa'", $this->lang->bug->toStory); $menu .= $this->buildMenu('bug', 'createCase', $convertParams, $bug, $type, 'sitemap'); } if($type == 'view') diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index b7f0629533..1d52f7da9c 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -217,7 +217,7 @@ From 7e9466abbde21c829aad9ea4433547655fdfccfb Mon Sep 17 00:00:00 2001 From: sunjun Date: Mon, 16 May 2022 21:08:04 +0800 Subject: [PATCH 066/304] sprint_sunjun_631 --- module/execution/view/all.html.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index c747140a80..75db4158ef 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -275,8 +275,8 @@ ?> - - + + From 397930ac4eb43e58b9665452de0fa0dccb44de90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 08:56:07 +0800 Subject: [PATCH 067/304] * Code for task #54189. --- module/common/model.php | 2 +- module/upgrade/model.php | 77 ---------------------------------------- 2 files changed, 1 insertion(+), 78 deletions(-) diff --git a/module/common/model.php b/module/common/model.php index 616bc1d5b4..a923835821 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -2216,7 +2216,7 @@ EOD; { if($this->app->getModuleName() == 'upgrade' and $this->session->upgrading) return false; - $statusFile = $this->app->getAppRoot() . 'www' . DIRECTORY_SEPARATOR . 'ok.txt'; + $statusFile = $this->app->getAppRoot() . 'www' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'ok.txt'; return (!is_file($statusFile) or (time() - filemtime($statusFile)) > 3600) ? $statusFile : false; } diff --git a/module/upgrade/model.php b/module/upgrade/model.php index e1017434f4..8af145b95c 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -455,9 +455,6 @@ class upgradeModel extends model case '16_0_beta1': $this->loadModel('api')->createDemoData($this->lang->api->zentaoAPI, 'http://' . $_SERVER['HTTP_HOST'] . $this->app->config->webRoot . 'api.php/v1', '16.0'); break; - case '16_1': - $this->moveKanbanData(); - break; case '16_2': $this->updateSpaceTeam(); $this->updateDocField(); @@ -5575,80 +5572,6 @@ class upgradeModel extends model return true; } - /** - * Move kanban card data to kanbancell table. - * - * @access public - * @return void - */ - public function moveKanbanData() - { - /* Move common kanban data. */ - $cards = $this->dao->select('id,kanban,`column`,lane')->from(TABLE_KANBANCARD)->fetchAll('id'); - - $cellGroup = array(); - foreach($cards as $cardID => $card) - { - if(!$card->lane or !$card->column) continue; - - $key = $card->kanban . '-' . $card->lane . '-' . $card->column; - $cards = isset($cellGroup[$key]) ? $cellGroup[$key] . "$cardID," : ",$cardID,"; - $cellGroup[$key] = $cards; - } - - foreach($cellGroup as $key => $cards) - { - $key = explode('-', $key); - if(!is_array($key)) continue; - - $cell = new stdclass(); - $cell->kanban = $key[0]; - $cell->lane = $key[1]; - $cell->column = $key[2]; - $cell->type = 'common'; - $cell->cards = $cards; - - $this->dao->insert(TABLE_KANBANCELL)->data($cell)->exec(); - } - - /* Drop group kanban data. */ - $groupLanePairs = $this->dao->select('id')->from(TABLE_KANBANLANE)->where('`groupby`')->ne('')->fetchPairs(); - if(!empty($groupLanePairs)) - { - $this->dao->delete()->from(TABLE_KANBANLANE)->where('id')->in($groupLanePairs)->exec(); - $this->dao->delete()->from(TABLE_KANBANCOLUMN)->where('lane')->in($groupLanePairs)->exec(); - } - - /* Move execution kanban data. */ - $executionKanban = $this->dao->select('t1.id as `lane`, t1.execution, t1.type, t2.id as `column`, t2.cards')->from(TABLE_KANBANLANE)->alias('t1') - ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.id = t2.lane') - ->where('t1.execution')->gt(0) - ->fetchGroup('lane'); - - foreach($executionKanban as $laneID => $laneGroup) - { - foreach($laneGroup as $colData) - { - if(!$laneID or !$colData->column) continue; - - $cell = new stdclass(); - $cell->kanban = $colData->execution; - $cell->lane = $laneID; - $cell->column = $colData->column; - $cell->type = $colData->type; - $cell->cards = $colData->cards; - - $this->dao->insert(TABLE_KANBANCELL)->data($cell)->exec(); - } - } - - /* Drop unused field. */ - $this->dao->exec("ALTER TABLE " . TABLE_KANBANCARD . " DROP COLUMN `lane`;"); - $this->dao->exec("ALTER TABLE " . TABLE_KANBANCARD . " DROP COLUMN `column`;"); - $this->dao->exec("ALTER TABLE " . TABLE_KANBANCOLUMN . " DROP COLUMN `lane`;"); - $this->dao->exec("ALTER TABLE " . TABLE_KANBANCOLUMN . " DROP COLUMN `cards`;"); - } - /** * Update kanban space team. * From 4bd3e1ba3e3c640663d2e7e3df175eda57dcc533 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 09:21:23 +0800 Subject: [PATCH 068/304] * Finish task #54353. --- module/productplan/control.php | 2 +- module/productplan/lang/en.php | 1 + module/productplan/lang/zh-cn.php | 1 + module/productplan/model.php | 7 ++++--- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/module/productplan/control.php b/module/productplan/control.php index aaa4f4238b..7b89d95e8d 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -282,7 +282,7 @@ class productplan extends control * @access public * @return void */ - public function browse($productID = 0, $branch = '', $browseType = 'doing', $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 ) + public function browse($productID = 0, $branch = '', $browseType = 'undone', $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 ) { $branchID = $branch === '' ? 'all' : $branch; if(!$branch) $branch = 0; diff --git a/module/productplan/lang/en.php b/module/productplan/lang/en.php index deffacf4d9..74b1c53c8b 100644 --- a/module/productplan/lang/en.php +++ b/module/productplan/lang/en.php @@ -136,6 +136,7 @@ $lang->productplan->beginLetterParentTip = "The start date of the child plan[%s] $lang->productplan->endGreaterParentTip = "The completion date of the child plan[%s]: %s, cannot be greater than the completion date of the parent plan: %s."; $lang->productplan->featureBar['browse']['all'] = 'All'; +$lang->productplan->featureBar['browse']['undone'] = 'Undone'; $lang->productplan->featureBar['browse']['wait'] = 'Waiting'; $lang->productplan->featureBar['browse']['doing'] = 'Doing'; $lang->productplan->featureBar['browse']['done'] = 'Done'; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index f9ba7d14cf..dae76ae9a8 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -136,6 +136,7 @@ $lang->productplan->beginLetterParentTip = "子计划[%s]的开始日期:%s, $lang->productplan->endGreaterParentTip = "子计划[%s]的完成日期:%s,不能大于父计划的完成日期: %s"; $lang->productplan->featureBar['browse']['all'] = '所有'; +$lang->productplan->featureBar['browse']['undone'] = '未完成'; $lang->productplan->featureBar['browse']['wait'] = '未开始'; $lang->productplan->featureBar['browse']['doing'] = '进行中'; $lang->productplan->featureBar['browse']['done'] = '已完成'; diff --git a/module/productplan/model.php b/module/productplan/model.php index ea4fac5627..bab02fd315 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -71,20 +71,21 @@ class productplanModel extends model * * @param int $product * @param int $branch - * @param string $browseType + * @param string $browseType all|undone|wait|doing|done|closed * @param object $pager * @param string $orderBy * @param string $param skipparent * @access public * @return object */ - public function getList($product = 0, $branch = 0, $browseType = 'doing', $pager = null, $orderBy = 'begin_desc', $param = '') + public function getList($product = 0, $branch = 0, $browseType = 'undone', $pager = null, $orderBy = 'begin_desc', $param = '') { $date = date('Y-m-d'); $plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) ->andWhere('deleted')->eq(0) ->beginIF(!empty($branch) and $branch != 'all')->andWhere('branch')->eq($branch)->fi() - ->beginIF($browseType != 'all')->andWhere('status')->eq($browseType)->fi() + ->beginIF(strpos(',all,undone,', $browseType) === false)->andWhere('status')->eq($browseType)->fi() + ->beginIF($browseType == 'undone')->andWhere('status')->in('wait,doing')->fi() ->beginIF(strpos($param, 'skipparent') !== false)->andWhere('parent')->ne(-1)->fi() ->orderBy($orderBy) ->page($pager) From 475c0d6acc1c2ff2bca5e6bf7251b8dc87b84bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 09:32:25 +0800 Subject: [PATCH 069/304] *Fix bug #22338. --- module/kanban/css/view.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 3ddb7da61b..8878575984 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -135,3 +135,5 @@ @-moz-document url-prefix(){ .region .kanban-lane-items{scrollbar-width:thin; padding:5px 0px 5px 5px !important;} .region .kanban-card .info .user{right: -6px !important;}} #archivedCards .table-empty-tip {border-style: hidden;} #archivedColumns .table-empty-tip {border-style: hidden;} + +.dragging>.kanban-card{background-color:#fff !important;opacity:.2} From c4e649ef25150ddcb442e1fcb67e751ca0f70957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 09:35:32 +0800 Subject: [PATCH 070/304] * Finish task #54186. --- module/user/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/user/control.php b/module/user/control.php index 2a0cbb46bc..2c7a00be88 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -833,6 +833,7 @@ class user extends control $response['result'] = 'success'; if(strpos($this->referer, $loginLink) === false and strpos($this->referer, $denyLink) === false and + strpos($this->referer, 'ajax') === false and strpos($this->referer, 'block') === false and $this->referer ) { From e848ea7d3f25d5a574da18dd5342b84edff8af5e Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 09:39:07 +0800 Subject: [PATCH 071/304] * Fix the project logic to which the lookup execution belongs. --- module/bug/model.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/bug/model.php b/module/bug/model.php index 14ed23097e..e4beb47890 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -79,7 +79,7 @@ class bugModel extends model ->remove('files,labels,uid,oldTaskID,contactListMenu,region,lane') ->get(); - if($bug->execution != 0) $bug->project = $this->dao->select('parent')->from(TABLE_EXECUTION)->where('id')->eq($bug->execution)->fetch('parent'); + if($bug->execution != 0) $bug->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($bug->execution)->fetch('project'); /* Check repeat bug. */ $result = $this->loadModel('common')->removeDuplicate('bug', $bug, "product={$bug->product}"); @@ -211,7 +211,7 @@ class bugModel extends model if(isset($data->lanes[$i])) $bug->laneID = $data->lanes[$i]; - if($bug->execution != 0) $bug->project = $this->dao->select('parent')->from(TABLE_EXECUTION)->where('id')->eq($bug->execution)->fetch('parent'); + if($bug->execution != 0) $bug->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($bug->execution)->fetch('project'); /* Assign the bug to the person in charge of the module. */ if(!empty($moduleOwners[$bug->module])) @@ -349,7 +349,7 @@ class bugModel extends model $bug->task = 0; $bug->pri = 3; $bug->severity = 3; - $bug->project = $this->dao->select('parent')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('parent'); + $bug->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('project'); $this->dao->insert(TABLE_BUG)->data($bug, $skip = 'gitlab,gitlabProject')->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); if(!dao::isError()) return $this->dao->lastInsertID(); From faf8ee28b9544ffb8515f264da6c813791ec8851 Mon Sep 17 00:00:00 2001 From: wangyuting2 <851424971@qq.com> Date: Tue, 17 May 2022 09:58:28 +0800 Subject: [PATCH 072/304] * Fix bug #22520 --- lib/dao/dao.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php index 82d2c0f4fc..585a299654 100644 --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -187,7 +187,7 @@ class dao extends baseDAO */ public function checkflow() { - global $app, $config; + global $app, $config, $lang; if(!isset($config->bizVersion)) return $this; @@ -204,6 +204,9 @@ class dao extends baseDAO $rawrules = $this->dbh->query("select * from " . TABLE_WORKFLOWRULE)->fetchall(); foreach($rawrules as $rule) $rules[$rule->id] = $rule; + $table = strtolower(str_replace(array($config->db->prefix, '`'), '', $this->table)); + if(!isset($lang->$table)) $lang->$table = new stdclass(); + foreach($flowfields as $key => $field) { if(!$field) @@ -212,6 +215,8 @@ class dao extends baseDAO continue; } + $lang->$table->{$field->field} = $field->name; + $ruleids = explode(',', trim($field->rules, ',') . ',' . trim($field->layoutrules, ',')); $ruleids = array_unique($ruleids); From d65a6ee4eb8364b48baf9d719c7edf56c62a08a0 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 09:58:49 +0800 Subject: [PATCH 073/304] * Modify testcase of productplan model. --- test/class/productplan.class.php | 2 +- test/model/productplan/getlist.php | 36 +++++++++++++++++++++--------- test/ztest | 4 ++-- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/test/class/productplan.class.php b/test/class/productplan.class.php index 4b98b90534..b98236ac72 100644 --- a/test/class/productplan.class.php +++ b/test/class/productplan.class.php @@ -65,7 +65,7 @@ class productPlan * @access public * @return array */ - public function getList($product, $branch, $browseType, $pager, $orderBy, $param) + public function getList($product = 0, $branch = 0, $browseType = 'undone', $pager = null, $orderBy = 'begin_desc', $param = '') { $productplans = $this->productplan->getList($product, $branch, $browseType, $pager, $orderBy, $param); if(dao::isError()) return dao::getError(); diff --git a/test/model/productplan/getlist.php b/test/model/productplan/getlist.php index 76bbbd31d9..389c040872 100755 --- a/test/model/productplan/getlist.php +++ b/test/model/productplan/getlist.php @@ -9,19 +9,35 @@ title=cid=1 cid=1 pid=1 -获取product=1的所有数据 >> 3 +获取空数据 >> 0 +获取product=1的所有的计划 >> 1;1;wait +获取product=1的所有的非父计划 >> 2;1;wait +获取product=1的所有未完成的计划 >> 3;1;wait +获取product=1的所有未开始的计划 >> 3;1;wait +获取product=1的所有进行中的计划 >> 101;1;doing +获取product=2的所有已完成的计划 >> 103;2;done +获取product=1的所有已关闭的计划 >> 102;1;closed */ $productplan = new Productplan('admin'); -$List = array(); -$List[0] = 1; -$List[1] = 0; -$List[2] = 'all'; -$List[3] = null; -$List[4] = 'begin_desc'; -$List[5] = 'kipparent'; +$dataList = array(); +$dataList[0] = $productplan->getList(); +$dataList[1] = $productplan->getList(1, 0, 'all', null, 'begin_desc'); +$dataList[2] = $productplan->getList(1, 0, 'all', null, 'begin_desc', 'kipparent'); +$dataList[3] = $productplan->getList(1, 0, 'undone', null, 'begin_desc'); +$dataList[4] = $productplan->getList(1, 0, 'wait', null, 'begin_desc'); +$dataList[5] = $productplan->getList(1, 0, 'doing', null, 'begin_desc'); +$dataList[6] = $productplan->getList(2, 0, 'done', null, 'begin_desc'); +$dataList[7] = $productplan->getList(1, 0, 'closed', null, 'begin_desc'); -r($productplan->getList(1, 0, 'all', null, 'begin_desc', 'kipparent')) && p('3:id') && e('3'); //获取product=1的所有数据 -?> \ No newline at end of file +r($dataList[0]) && p() && e('0'); // 获取空数据 +r($dataList[1]) && p('1:id;1:product;1:status') && e('1;1;wait'); // 获取product=1的所有的计划 +r($dataList[2]) && p('2:id;2:product;2:status') && e('2;1;wait'); // 获取product=1的所有的非父计划 +r($dataList[3]) && p('3:id;3:product;3:status') && e('3;1;wait'); // 获取product=1的所有未完成的计划 +r($dataList[4]) && p('3:id;3:product;3:status') && e('3;1;wait'); // 获取product=1的所有未开始的计划 +r($dataList[5]) && p('101:id;101:product;101:status') && e('101;1;doing'); // 获取product=1的所有进行中的计划 +r($dataList[6]) && p('103:id;103:product;103:status') && e('103;2;done'); // 获取product=2的所有已完成的计划 +r($dataList[7]) && p('102:id;102:product;102:status') && e('102;1;closed'); // 获取product=1的所有已关闭的计划 +?> diff --git a/test/ztest b/test/ztest index 10d9f2559b..ef7d8cb240 100755 --- a/test/ztest +++ b/test/ztest @@ -112,8 +112,8 @@ switch($argv[1]) case 'projectstory': ztfRun('model/projectstory'); break; - case 'productsonplan': - ztfRun('model/productsonplan'); + case 'productplan': + ztfRun('model/productplan'); break; case 'program': ztfRun('model/program'); From 566b87823f8a0592e39677022f96ca2f0dbc0096 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 17 May 2022 10:07:26 +0800 Subject: [PATCH 074/304] * Finish task #54346,#54345. --- module/build/view/linkstory.html.php | 2 +- module/release/view/linkstory.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/build/view/linkstory.html.php b/module/build/view/linkstory.html.php index d874361a28..56e906e431 100644 --- a/module/build/view/linkstory.html.php +++ b/module/build/view/linkstory.html.php @@ -42,7 +42,7 @@ ` or `` - foreach ($Block['element']['elements'] as $Index0 => &$Element0) { - // `` - foreach ($Element0['elements'] as $Index1 => &$Element1) { - // ` + + + + + +app->getModuleRoot() . 'common/view/mail.footer.html.php';?> diff --git a/module/mail/model.php b/module/mail/model.php index 370e9b2373..652894eecb 100644 --- a/module/mail/model.php +++ b/module/mail/model.php @@ -691,7 +691,7 @@ class mailModel extends model $action = $this->action->getById($actionID); $history = $this->action->getHistory($actionID); $objectType = $action->objectType; - $object = $this->loadModel($objectType)->getByID($objectID); + $object = $objectType == 'kanbancard' ? $this->loadModel('kanban')->getCardByID($objectID) : $this->loadModel($objectType)->getByID($objectID); $nameFields = $this->config->action->objectNameFields[$objectType]; $title = zget($object, $nameFields, ''); $subject = $this->getSubject($objectType, $object, $title, $action->action); @@ -726,6 +726,8 @@ class mailModel extends model if($objectType == 'review') $this->app->loadLang('baseline'); /* Get mail content. */ + if($objectType == 'kanbancard') $objectType = 'kanban'; + $modulePath = $this->app->getModulePath($appName = '', $objectType); $oldcwd = getcwd(); $viewFile = $modulePath . 'view/sendmail.html.php'; diff --git a/module/message/config.php b/module/message/config.php index d39fb726e9..c637cac386 100644 --- a/module/message/config.php +++ b/module/message/config.php @@ -10,22 +10,25 @@ $config->message->objectTypes['case'] = array('opened', 'edited', 'commen $config->message->objectTypes['testtask'] = array('opened', 'edited', 'started', 'blocked', 'closed', 'activated'); $config->message->objectTypes['todo'] = array('opened', 'edited'); $config->message->objectTypes['doc'] = array('created', 'edited'); +$config->message->objectTypes['kanbancard'] = array('created', 'edited', 'finished', 'activated', 'archived', 'restore', 'deleted', 'moved'); $config->message->available = array(); -$config->message->available['mail']['story'] = $config->message->objectTypes['story']; -$config->message->available['mail']['task'] = $config->message->objectTypes['task']; -$config->message->available['mail']['bug'] = $config->message->objectTypes['bug']; -$config->message->available['mail']['testtask'] = array('opened', 'edited', 'closed'); -$config->message->available['mail']['doc'] = $config->message->objectTypes['doc']; +$config->message->available['mail']['story'] = $config->message->objectTypes['story']; +$config->message->available['mail']['task'] = $config->message->objectTypes['task']; +$config->message->available['mail']['bug'] = $config->message->objectTypes['bug']; +$config->message->available['mail']['testtask'] = array('opened', 'edited', 'closed'); +$config->message->available['mail']['doc'] = $config->message->objectTypes['doc']; +$config->message->available['mail']['kanbancard'] = $config->message->objectTypes['kanbancard']; $config->message->available['webhook'] = $config->message->objectTypes; -$config->message->available['message']['bug'] = $config->message->objectTypes['bug']; -$config->message->available['message']['story'] = $config->message->objectTypes['story']; -$config->message->available['message']['task'] = $config->message->objectTypes['task']; -$config->message->available['message']['testtask'] = $config->message->objectTypes['testtask']; -$config->message->available['message']['todo'] = $config->message->objectTypes['todo']; -$config->message->available['message']['doc'] = $config->message->objectTypes['doc']; +$config->message->available['message']['bug'] = $config->message->objectTypes['bug']; +$config->message->available['message']['story'] = $config->message->objectTypes['story']; +$config->message->available['message']['task'] = $config->message->objectTypes['task']; +$config->message->available['message']['testtask'] = $config->message->objectTypes['testtask']; +$config->message->available['message']['todo'] = $config->message->objectTypes['todo']; +$config->message->available['message']['doc'] = $config->message->objectTypes['doc']; +$config->message->available['message']['kanbancard'] = $config->message->objectTypes['kanbancard']; $config->message->typeLink = array(); $config->message->typeLink['mail'] = 'mail|index'; diff --git a/module/message/css/setting.css b/module/message/css/setting.css index 0a26a1d7fe..86c0394948 100644 --- a/module/message/css/setting.css +++ b/module/message/css/setting.css @@ -2,5 +2,3 @@ .checkbox-primary {margin: 0px; width: 120px; float: left;} .checkbox-primary label {white-space: nowrap; overflow: hidden; text-overflow: ellipsis;} div.chosen-container + select + div.chosen-container > .chosen-choices {border-top: 0px;} - -.table-bordered thead .checkbox-primary {width: 200px;} diff --git a/module/message/lang/en.php b/module/message/lang/en.php index c584d5a185..1f2284ea19 100644 --- a/module/message/lang/en.php +++ b/module/message/lang/en.php @@ -44,3 +44,6 @@ $lang->message->label->blocked = 'block'; $lang->message->label->bugconfirmed = 'confirm'; $lang->message->label->compilepass = 'compile pass'; $lang->message->label->compilefail = 'compile fail'; +$lang->message->label->archived = 'archive'; +$lang->message->label->restore = 'restore'; +$lang->message->label->moved = 'move'; diff --git a/module/message/lang/zh-cn.php b/module/message/lang/zh-cn.php index 1e1610ab6b..34c7e2b051 100644 --- a/module/message/lang/zh-cn.php +++ b/module/message/lang/zh-cn.php @@ -44,3 +44,6 @@ $lang->message->label->blocked = '阻塞'; $lang->message->label->bugconfirmed = '确认'; $lang->message->label->compilepass = '构建通过'; $lang->message->label->compilefail = '构建失败'; +$lang->message->label->archived = '归档'; +$lang->message->label->restore = '还原'; +$lang->message->label->moved = '移动'; diff --git a/module/message/model.php b/module/message/model.php index 83a55e3ebb..98f547130c 100644 --- a/module/message/model.php +++ b/module/message/model.php @@ -64,6 +64,7 @@ class messageModel extends model */ public function send($objectType, $objectID, $actionType, $actionID, $actor = '') { + $objectType = strtolower($objectType); $messageSetting = $this->config->message->setting; if(is_string($messageSetting)) $messageSetting = json_decode($messageSetting, true); diff --git a/xuanxuan/extension/xuan/message/ext/config/xuanxuan.php b/xuanxuan/extension/xuan/message/ext/config/xuanxuan.php index 2573bf051f..fa8db98fe0 100644 --- a/xuanxuan/extension/xuan/message/ext/config/xuanxuan.php +++ b/xuanxuan/extension/xuan/message/ext/config/xuanxuan.php @@ -1,9 +1,11 @@ message->objectTypes['mr'] = array('compilepass', 'compilefail'); -$config->message->available['xuanxuan']['story'] = $config->message->objectTypes['story']; -$config->message->available['xuanxuan']['task'] = $config->message->objectTypes['task']; -$config->message->available['xuanxuan']['bug'] = $config->message->objectTypes['bug']; -$config->message->available['xuanxuan']['todo'] = $config->message->objectTypes['todo']; -$config->message->available['xuanxuan']['mr'] = $config->message->objectTypes['mr']; +$config->message->available['xuanxuan']['story'] = $config->message->objectTypes['story']; +$config->message->available['xuanxuan']['task'] = $config->message->objectTypes['task']; +$config->message->available['xuanxuan']['bug'] = $config->message->objectTypes['bug']; +$config->message->available['xuanxuan']['todo'] = $config->message->objectTypes['todo']; +$config->message->available['xuanxuan']['mr'] = $config->message->objectTypes['mr']; +$config->message->available['xuanxuan']['kanbancard'] = $config->message->objectTypes['kanbancard']; + $config->message->setting['xuanxuan']['setting'] = $config->message->available['xuanxuan']; From d204f15d47e2beb0b7eac2ee0b09427666515803 Mon Sep 17 00:00:00 2001 From: wangyuting2 <851424971@qq.com> Date: Tue, 17 May 2022 14:56:44 +0800 Subject: [PATCH 085/304] * Fix workflow default lang bug. --- lib/dao/dao.class.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php index 585a299654..6443a4d5f2 100644 --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -113,6 +113,7 @@ class dao extends baseDAO $app->loadLang('workflowfield'); $app->loadConfig('flow'); $app->loadConfig('workflowfield'); + foreach($fields as $field) { if(isset($data->{$field->field})) @@ -187,7 +188,7 @@ class dao extends baseDAO */ public function checkflow() { - global $app, $config, $lang; + global $app, $config; if(!isset($config->bizVersion)) return $this; @@ -204,9 +205,6 @@ class dao extends baseDAO $rawrules = $this->dbh->query("select * from " . TABLE_WORKFLOWRULE)->fetchall(); foreach($rawrules as $rule) $rules[$rule->id] = $rule; - $table = strtolower(str_replace(array($config->db->prefix, '`'), '', $this->table)); - if(!isset($lang->$table)) $lang->$table = new stdclass(); - foreach($flowfields as $key => $field) { if(!$field) @@ -215,8 +213,6 @@ class dao extends baseDAO continue; } - $lang->$table->{$field->field} = $field->name; - $ruleids = explode(',', trim($field->rules, ',') . ',' . trim($field->layoutrules, ',')); $ruleids = array_unique($ruleids); From be47bb739c21e53a765bc5435e915267e697b257 Mon Sep 17 00:00:00 2001 From: mayue Date: Tue, 17 May 2022 07:06:36 +0000 Subject: [PATCH 086/304] * Finish task #54191. --- module/productplan/control.php | 28 ++++++++-- module/productplan/js/create.js | 14 +++-- module/productplan/js/edit.js | 15 +++++- module/productplan/model.php | 68 ++++++++++++++++++++----- module/productplan/view/create.html.php | 12 +++-- module/productplan/view/edit.html.php | 7 +++ 6 files changed, 119 insertions(+), 25 deletions(-) diff --git a/module/productplan/control.php b/module/productplan/control.php index 7b89d95e8d..c2a745e912 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -91,6 +91,10 @@ class productplan extends control if($parent) $this->view->parentPlan = $this->productplan->getById($parent); $branchPairs = $product->type == 'normal' ? array() : $this->loadModel('branch')->getPairs($productID, 'active'); + /* Get parent plan pairs. */ + $parentPlanPairs = $this->productplan->getTopPlanPairs($productID, $branchID); + $this->view->parentPlanPairs = $parentPlanPairs; + /*Get default branch.*/ $branchList = $this->loadModel('branch')->getList($productID); foreach($branchList as $branch) @@ -140,10 +144,12 @@ class productplan extends control $oldBranch = array($planID => $plan->branch); $this->commonAction($plan->product, $plan->branch); - $this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->productplan->edit; - $this->view->position[] = $this->lang->productplan->edit; - $this->view->oldBranch = $oldBranch; - $this->view->plan = $plan; + $this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->productplan->edit; + $this->view->position[] = $this->lang->productplan->edit; + $this->view->productID = $plan->product; + $this->view->oldBranch = $oldBranch; + $this->view->plan = $plan; + $this->view->parentPlanPairs = $this->productplan->getTopPlanPairs($plan->product, $plan->branch, $planID); $this->display(); } @@ -942,4 +948,18 @@ class productplan extends control $lastPlan = $this->productplan->getLast($productID, $branch, $parent); echo json_encode($lastPlan); } + + /** + * AJAX: Get top plan. + * + * @param int $productID + * @param int $branch + * @access public + * @return object + */ + public function ajaxGetTopPlan($productID, $branch = 0) + { + $parentPlanPairs = $this->productplan->getTopPlanPairs($productID, $branch); + return print(html::select('parent', array('0' => '') + $parentPlanPairs, '', 'class="form-control"')); + } } diff --git a/module/productplan/js/create.js b/module/productplan/js/create.js index 09617fe5d4..e9ecce37c7 100644 --- a/module/productplan/js/create.js +++ b/module/productplan/js/create.js @@ -66,12 +66,20 @@ $('#future').on('change', function() $('#branch').change(function() { var branchID = $(this).val(); - var link = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchID); + var getLastLink = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchID); + var getTopPlanLink = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branchID); - $.post(link, function(data) + $.post(getLastLink, function(data) { data = JSON.parse(data); var planTitle = data ? '(' + lastLang + ': ' + data.title + ')' : ''; $('#title').parent().next('td').html(planTitle); }) -}) + + $.post(getTopPlanLink, function(data) + { + $('#parent').replaceWith(data); + $('#parent_chosen').remove(); + $('#parent').chosen(); + }) +}); diff --git a/module/productplan/js/edit.js b/module/productplan/js/edit.js index cf0449041d..4c387ab424 100644 --- a/module/productplan/js/edit.js +++ b/module/productplan/js/edit.js @@ -25,11 +25,23 @@ function getConflictStories(planID, branch) { $.get(createLink('productplan', 'ajaxGetConflictStory', 'planID=' + planID + '&newBranch=' + branch), function(conflictStories) { - if(conflictStories != '' && !confirm(conflictStories)) + var result = confirm(conflictStories) ? true : false; + if(conflictStories != '' && !result) { $('#branch').val(oldBranch[planID]); $('#branch').trigger("chosen:updated"); } + + if(result) + { + var link = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branch); + $.post(link, function(data) + { + $('#parent').replaceWith(data); + $('#parent_chosen').remove(); + $('#parent').chosen(); + }) + } }); } @@ -73,4 +85,3 @@ $('#future').on('change', function() } }); -$('#future').change(); diff --git a/module/productplan/model.php b/module/productplan/model.php index cea66f66ff..1f7da91ec3 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -177,6 +177,29 @@ class productplanModel extends model return $plans; } + /** + * Get top plan pairs. + * + * @param int $productID + * @param int $branch + * @param int $exclude + * @access public + * @return array + */ + public function getTopPlanPairs($productID, $branch = '', $exclude = '') + { + $planPairs = $this->dao->select("id,title")->from(TABLE_PRODUCTPLAN) + ->where('product')->eq($productID) + ->beginIF($branch !== '')->andWhere('branch')->eq($branch)->fi() + ->andWhere('parent')->le(0) + ->andWhere('deleted')->eq(0) + ->fetchPairs(); + + if($exclude) unset($planPairs[$exclude]); + + return $planPairs; + } + /** * Get plan pairs. * @@ -404,19 +427,17 @@ class productplanModel extends model if($plan->parent > 0) { - if($plan->parentBegin != $this->config->productplan->future) + $parentPlan = $this->getByID($plan->parent); + if($parentPlan->begin != $this->config->productplan->future) { - if($plan->begin < $plan->parentBegin) dao::$errors['begin'] = sprintf($this->lang->productplan->beginLetterParent, $plan->parentBegin); + if($plan->begin < $parentPlan->begin) dao::$errors['begin'] = sprintf($this->lang->productplan->beginLetterParent, $parentPlan->begin); } - if($plan->parentEnd != $this->config->productplan->future) + if($parentPlan->end != $this->config->productplan->future) { - if($plan->end !== $this->config->productplan->future and $plan->end > $plan->parentEnd) dao::$errors['end'] = sprintf($this->lang->productplan->endGreaterParent, $plan->parentEnd); + if($plan->end !== $this->config->productplan->future and $plan->end > $parentPlan->end) dao::$errors['end'] = sprintf($this->lang->productplan->endGreaterParent, $parentPlan->end); } } - unset($plan->parentBegin); - unset($plan->parentEnd); - if(!$this->post->future and strpos($this->config->productplan->create->requiredFields, 'begin') !== false and empty($_POST['begin'])) { dao::$errors['begin'] = sprintf($this->lang->error->notempty, $this->lang->productplan->begin); @@ -442,7 +463,6 @@ class productplanModel extends model $this->loadModel('score')->create('productplan', 'create', $planID); if(!empty($plan->parent)) { - $parentPlan = $this->getByID($plan->parent); if($parentPlan->parent == '0') { $this->dao->update(TABLE_PRODUCTPLAN)->set('parent')->eq('-1')->where('id')->eq($plan->parent)->andWhere('parent')->eq('0')->exec(); @@ -473,7 +493,7 @@ class productplanModel extends model */ public function update($planID) { - $oldPlan = $this->dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch(); + $oldPlan = $this->getByID($planID); $plan = fixer::input('post')->stripTags($this->config->productplan->editor->edit['id'], $this->config->allowedTags) ->setIF($this->post->future or empty($_POST['begin']), 'begin', $this->config->productplan->future) ->setIF($this->post->future or empty($_POST['end']), 'end', $this->config->productplan->future) @@ -481,9 +501,11 @@ class productplanModel extends model ->remove('delta,uid,future') ->get(); - if($oldPlan->parent > 0) + $parentPlan = $this->getByID($plan->parent); + + + if($plan->parent > 0) { - $parentPlan = $this->getByID($oldPlan->parent); if($parentPlan->begin !== $this->config->productplan->future) { if($plan->begin < $parentPlan->begin) dao::$errors['begin'] = sprintf($this->lang->productplan->beginLetterParent, $parentPlan->begin); @@ -493,9 +515,9 @@ class productplanModel extends model if($plan->end !== $this->config->productplan->future and $plan->end > $parentPlan->end) dao::$errors['end'] = sprintf($this->lang->productplan->endGreaterParent, $parentPlan->end); } } - elseif($oldPlan->parent == -1 and $plan->begin != $this->config->productplan->future) + elseif($parentPlan and $plan->begin != $this->config->productplan->future) { - $childPlans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('parent')->eq($planID)->andWhere('deleted')->eq(0)->fetchAll('id'); + $childPlans = $this->getChildren($parentPlan->id); $minBegin = $plan->begin; $maxEnd = $plan->end; foreach($childPlans as $childID => $childPlan) @@ -520,11 +542,31 @@ class productplanModel extends model ->exec(); if(dao::isError()) return false; + if($plan->parent > 0) $this->updateParentStatus($plan->parent); if($oldPlan->parent > 0) $this->updateParentStatus($oldPlan->parent); if(!dao::isError()) { $this->file->updateObjectID($this->post->uid, $planID, 'plan'); + if(!empty($plan->parent)) + { + if($parentPlan->parent == '0') + { + $this->dao->update(TABLE_PRODUCTPLAN)->set('parent')->eq('-1')->where('id')->eq($plan->parent)->andWhere('parent')->eq('0')->exec(); + + /* Transfer stories and bugs linked with the parent plan to the child plan. */ + $this->dao->update(TABLE_PLANSTORY)->set('plan')->eq($planID)->where('plan')->eq($plan->parent)->exec(); + $this->dao->update(TABLE_BUG)->set('plan')->eq($planID)->where('plan')->eq($plan->parent)->exec(); + $stories = $this->dao->select('*')->from(TABLE_STORY)->where("CONCAT(',', plan, ',')")->like("%,{$plan->parent},%")->fetchAll('id'); + foreach($stories as $storyID => $story) + { + $storyPlan = str_replace(",{$plan->parent},", ",$planID,", ",$story->plan,"); + $storyPlan = trim($storyPlan, ','); + + $this->dao->update(TABLE_STORY)->set('plan')->eq($storyPlan)->where('id')->eq($storyID)->exec(); + } + } + } return common::createChanges($oldPlan, $plan); } } diff --git a/module/productplan/view/create.html.php b/module/productplan/view/create.html.php index 9bc121ac68..3d37c51178 100644 --- a/module/productplan/view/create.html.php +++ b/module/productplan/view/create.html.php @@ -28,8 +28,6 @@ @@ -49,6 +47,12 @@ + + + + + @@ -74,8 +78,10 @@ id);?> - branch);?> + + branch);?> + diff --git a/module/productplan/view/edit.html.php b/module/productplan/view/edit.html.php index fc054df441..ca7f0a626c 100644 --- a/module/productplan/view/edit.html.php +++ b/module/productplan/view/edit.html.php @@ -15,6 +15,7 @@ execution->weekend);?> +
                    @@ -38,6 +39,12 @@
                    + parent >= 0):?> + parent == '-1' ? "class='hidden'" : ''?>> + + + parent == -1 ? "disabled='disabled'" : '' ;?> From 39959d08e9f96b4dab256f2fc0d0e7dbc44d3031 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 17 May 2022 15:08:06 +0800 Subject: [PATCH 087/304] * Fix bug#54483. --- module/tree/control.php | 2 +- module/tree/js/browse.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/module/tree/control.php b/module/tree/control.php index f9e3d76c0f..6ba17a19fe 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -392,7 +392,7 @@ class tree extends control if(dao::isError()) return print(js::error(dao::getError())); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $moduleIDList)); - if(($viewType == 'doc' || $viewType == 'api') and isonlybody()) die(js::reload('parent.parent')); + if(($viewType == 'doc' || $viewType == 'api') and isonlybody()) die(js::reload('parent')); if(isonlybody()) die(js::closeModal('parent.parent', '', "function(){parent.parent.$('a.refresh').click()}")); die(js::reload('parent')); diff --git a/module/tree/js/browse.js b/module/tree/js/browse.js index 4b2a9692a0..8e2576af23 100644 --- a/module/tree/js/browse.js +++ b/module/tree/js/browse.js @@ -76,4 +76,6 @@ $(document).ready(function() { toggleCopy(false); $('[data-id="edit"] a').modalTrigger({type: 'iframe', width: 500}); + + parent.$('#triggerModal .modal-content .modal-header .close').on('click', function(){parent.location.reload();}); }); From 1c9bfe9bd6e8dcbfa82aea06c5fcca405384678f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 15:10:28 +0800 Subject: [PATCH 088/304] * Fix jira and markdown bug. --- lib/michelf/Michelf/Markdown.php | 50 ++++++++++----------- lib/michelf/Michelf/MarkdownExtra.php | 64 +++++++++++++-------------- module/convert/model.php | 2 +- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/lib/michelf/Michelf/Markdown.php b/lib/michelf/Michelf/Markdown.php index e7a5976d97..cb184d0948 100644 --- a/lib/michelf/Michelf/Markdown.php +++ b/lib/michelf/Michelf/Markdown.php @@ -52,31 +52,31 @@ class Markdown implements MarkdownInterface { /** * Change to ">" for HTML output. */ - public string $empty_element_suffix = " />"; + public $empty_element_suffix = " />"; /** * The width of indentation of the output markup */ - public int $tab_width = 4; + public $tab_width = 4; /** * Change to `true` to disallow markup or entities. */ - public bool $no_markup = false; - public bool $no_entities = false; + public $no_markup = false; + public $no_entities = false; /** * Change to `true` to enable line breaks on \n without two trailling spaces * @var boolean */ - public bool $hard_wrap = false; + public $hard_wrap = false; /** * Predefined URLs and titles for reference links and images. */ - public array $predef_urls = array(); - public array $predef_titles = array(); + public $predef_urls = array(); + public $predef_titles = array(); /** * Optional filter function for URLs @@ -117,7 +117,7 @@ class Markdown implements MarkdownInterface { *
                  • List item three
                  • * */ - public bool $enhanced_ordered_list = false; + public $enhanced_ordered_list = false; /** * Parser implementation @@ -126,17 +126,17 @@ class Markdown implements MarkdownInterface { * Regex to match balanced [brackets]. * Needed to insert a maximum bracked depth while converting to PHP. */ - protected int $nested_brackets_depth = 6; + protected $nested_brackets_depth = 6; protected $nested_brackets_re; - protected int $nested_url_parenthesis_depth = 4; + protected $nested_url_parenthesis_depth = 4; protected $nested_url_parenthesis_re; /** * Table of hash values for escaped characters: */ - protected string $escape_chars = '\`*_{}[]()>#+-.!'; - protected string $escape_chars_re; + protected $escape_chars = '\`*_{}[]()>#+-.!'; + protected $escape_chars_re; /** * Constructor function. Initialize appropriate member variables. @@ -166,19 +166,19 @@ class Markdown implements MarkdownInterface { /** * Internal hashes used during transformation. */ - protected array $urls = array(); + protected $urls = array(); protected $titles = array(); - protected array $html_hashes = array(); + protected $html_hashes = array(); /** * Status flag to avoid invalid nesting. */ - protected bool $in_anchor = false; + protected $in_anchor = false; /** * Status flag to avoid invalid nesting. */ - protected bool $in_emphasis_processing = false; + protected $in_emphasis_processing = false; /** * Called before the transformation process starts to setup parser states. @@ -251,7 +251,7 @@ class Markdown implements MarkdownInterface { /** * Define the document gamut */ - protected array $document_gamut = array( + protected $document_gamut = array( // Strip link definitions, store in hashes. "stripLinkDefinitions" => 20, "runBasicBlockGamut" => 30, @@ -512,7 +512,7 @@ class Markdown implements MarkdownInterface { * Define the block gamut - these are all the transformations that form * block-level tags like paragraphs, headers, and list items. */ - protected array $block_gamut = array( + protected $block_gamut = array( "doHeaders" => 10, "doHorizontalRules" => 20, "doLists" => 40, @@ -583,7 +583,7 @@ class Markdown implements MarkdownInterface { * These are all the transformations that occur *within* block-level * tags like paragraphs, headers, and list items. */ - protected array $span_gamut = array( + protected $span_gamut = array( // Process character escapes, code spans, and inline HTML // in one shot. "parseSpan" => -30, @@ -1090,7 +1090,7 @@ class Markdown implements MarkdownInterface { /** * Nesting tracker for list levels */ - protected int $list_level = 0; + protected $list_level = 0; /** * Process the contents of a single ordered or unordered list, splitting it @@ -1231,7 +1231,7 @@ class Markdown implements MarkdownInterface { * Define the emphasis operators with their regex matches * @var array */ - protected array $em_relist = array( + protected $em_relist = array( '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(?utf8_strlen = fn($text) => preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m); + //$this->utf8_strlen = fn($text) => preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m); } /** diff --git a/lib/michelf/Michelf/MarkdownExtra.php b/lib/michelf/Michelf/MarkdownExtra.php index 060a4aecc0..ac4601517b 100644 --- a/lib/michelf/Michelf/MarkdownExtra.php +++ b/lib/michelf/Michelf/MarkdownExtra.php @@ -20,18 +20,18 @@ class MarkdownExtra extends \Michelf\Markdown { /** * Prefix for footnote ids. */ - public string $fn_id_prefix = ""; + public $fn_id_prefix = ""; /** * Optional title attribute for footnote links. */ - public string $fn_link_title = ""; + public $fn_link_title = ""; /** * Optional class attribute for footnote links and backlinks. */ - public string $fn_link_class = "footnote-ref"; - public string $fn_backlink_class = "footnote-backref"; + public $fn_link_class = "footnote-ref"; + public $fn_backlink_class = "footnote-backref"; /** * Content to be displayed within footnote backlinks. The default is '↩'; @@ -40,7 +40,7 @@ class MarkdownExtra extends \Michelf\Markdown { * Optionally use '^^' and '%%' to refer to the footnote number and * reference number respectively. {@see parseFootnotePlaceholders()} */ - public string $fn_backlink_html = '↩︎'; + public $fn_backlink_html = '↩︎'; /** * Optional title and aria-label attributes for footnote backlinks for @@ -48,42 +48,42 @@ class MarkdownExtra extends \Michelf\Markdown { * Use '^^' and '%%' to refer to the footnote number and reference number * respectively. {@see parseFootnotePlaceholders()} */ - public string $fn_backlink_title = ""; - public string $fn_backlink_label = ""; + public $fn_backlink_title = ""; + public $fn_backlink_label = ""; /** * Class name for table cell alignment (%% replaced left/center/right) * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center' * If empty, the align attribute is used instead of a class name. */ - public string $table_align_class_tmpl = ''; + public $table_align_class_tmpl = ''; /** * Optional class prefix for fenced code block. */ - public string $code_class_prefix = ""; + public $code_class_prefix = ""; /** * Class attribute for code blocks goes on the `code` tag; * setting this to true will put attributes on the `pre` tag instead. */ - public bool $code_attr_on_pre = false; + public $code_attr_on_pre = false; /** * Predefined abbreviations. */ - public array $predef_abbr = array(); + public $predef_abbr = array(); /** * Only convert atx-style headers if there's a space between the header and # */ - public bool $hashtag_protection = false; + public $hashtag_protection = false; /** * Determines whether footnotes should be appended to the end of the document. * If true, footnote html can be retrieved from $this->footnotes_assembled. */ - public bool $omit_footnotes = false; + public $omit_footnotes = false; /** @@ -96,7 +96,7 @@ class MarkdownExtra extends \Michelf\Markdown { * reachable to accessibility tools the same way they would be with the * default HTML output. */ - public ?string $footnotes_assembled = null; + public $footnotes_assembled = null; /** * Parser implementation @@ -137,22 +137,22 @@ class MarkdownExtra extends \Michelf\Markdown { /** * Extra variables used during extra transformations. */ - protected array $footnotes = array(); - protected array $footnotes_ordered = array(); - protected array $footnotes_ref_count = array(); - protected array $footnotes_numbers = array(); - protected array $abbr_desciptions = array(); - protected string $abbr_word_re = ''; + protected $footnotes = array(); + protected $footnotes_ordered = array(); + protected $footnotes_ref_count = array(); + protected $footnotes_numbers = array(); + protected $abbr_desciptions = array(); + protected $abbr_word_re = ''; /** * Give the current footnote number. */ - protected int $footnote_counter = 1; + protected $footnote_counter = 1; /** * Ref attribute for links */ - protected array $ref_attr = array(); + protected $ref_attr = array(); /** * Setting up Extra-specific variables. @@ -201,12 +201,12 @@ class MarkdownExtra extends \Michelf\Markdown { /** * Expression to use to catch attributes (includes the braces) */ - protected string $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}'; + protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}'; /** * Expression to use when parsing in a context when no capture is desired */ - protected string $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}'; + protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}'; /** * Parse attributes caught by the $this->id_class_attr_catch_re expression @@ -323,28 +323,28 @@ class MarkdownExtra extends \Michelf\Markdown { /** * Tags that are always treated as block tags */ - protected string $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure|details|summary'; + protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure|details|summary'; /** * Tags treated as block tags only if the opening tag is alone on its line */ - protected string $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; + protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; /** * Tags where markdown="1" default to span mode: */ - protected string $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; /** * Tags which must not have their contents modified, no matter where * they appear */ - protected string $clean_tags_re = 'script|style|math|svg'; + protected $clean_tags_re = 'script|style|math|svg'; /** * Tags that do not need to be closed. */ - protected string $auto_close_tags_re = 'hr|img|param|source|track'; + protected $auto_close_tags_re = 'hr|img|param|source|track'; /** * Hashify HTML Blocks and "clean tags". @@ -1524,17 +1524,17 @@ class MarkdownExtra extends \Michelf\Markdown { * work in the middle of a word. * @var array */ - protected array $em_relist = array( + protected $em_relist = array( '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(?openedBy = $this->getJiraAccount($data->CREATOR, $method); $bug->openedDate = substr($data->CREATED, 0, 19); $bug->openedBuild = 'trunk'; - $bug->assignedTo = $this->getJiraAccount($data->ASSIGNEE, $method); + $bug->assignedTo = $bug->status == 'closed' ? 'closed' : $this->getJiraAccount($data->ASSIGNEE, $method); if($data->RESOLUTION) { From 738ec653cbcc215aa5c9bb7c2b2169ebd558868a Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 15:17:06 +0800 Subject: [PATCH 089/304] * Finish task #54391. --- module/kanban/control.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/module/kanban/control.php b/module/kanban/control.php index 32d3943bcd..58bfc14150 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -1391,16 +1391,9 @@ class kanban extends control } else { - if($card->fromType == '') - { - $this->kanban->delete(TABLE_KANBANCARD, $cardID); - $this->loadModel('action')->create('kanbancard', $cardID, 'Deleted', '', $cardID); - } + if($card->fromType == '') $this->kanban->delete(TABLE_KANBANCARD, $cardID); - if($card->fromType != '') - { - $this->dao->delete()->from(TABLE_KANBANCARD)->where('id')->eq($cardID)->exec(); - } + if($card->fromType != '') $this->dao->delete()->from(TABLE_KANBANCARD)->where('id')->eq($cardID)->exec(); if(isonlybody()) return print(js::reload('parent.parent')); return print(js::reload('parent')); From 72f135d90bf1829f69f9653ea57dd8ec51d559cf Mon Sep 17 00:00:00 2001 From: mayue Date: Tue, 17 May 2022 07:35:26 +0000 Subject: [PATCH 090/304] * Optimize code. --- module/productplan/js/edit.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/productplan/js/edit.js b/module/productplan/js/edit.js index 4c387ab424..44147dfdc7 100644 --- a/module/productplan/js/edit.js +++ b/module/productplan/js/edit.js @@ -37,9 +37,9 @@ function getConflictStories(planID, branch) var link = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branch); $.post(link, function(data) { - $('#parent').replaceWith(data); - $('#parent_chosen').remove(); - $('#parent').chosen(); + $('#parent').replaceWith(data); + $('#parent_chosen').remove(); + $('#parent').chosen(); }) } }); From cca3f564379572e2412195cf7d2f1ee1827cbd9c Mon Sep 17 00:00:00 2001 From: zhouxudong Date: Tue, 17 May 2022 07:38:22 +0000 Subject: [PATCH 091/304] * Finish task #54480. --- module/my/control.php | 1 + module/my/css/team.css | 2 ++ module/my/view/team.html.php | 5 ++++- module/user/control.php | 17 +++++++++-------- module/user/view/create.html.php | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/module/my/control.php b/module/my/control.php index 8d71b1f6c1..2e3efc3220 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -938,6 +938,7 @@ EOF; $this->view->title = $this->lang->my->team; $this->view->position[] = $this->lang->my->team; $this->view->users = $users; + $this->view->deptID = $deptID; $this->view->orderBy = $orderBy; $this->view->pager = $pager; diff --git a/module/my/css/team.css b/module/my/css/team.css index cc48190d78..9c05ff4789 100644 --- a/module/my/css/team.css +++ b/module/my/css/team.css @@ -1,2 +1,4 @@ .c-gender {width: 80px;} .c-phone, .c-skype, .c-visits {width: 100px;} +#mainMenu {margin: -10px 0 8px; float:right} +#mainContent {float:left} diff --git a/module/my/view/team.html.php b/module/my/view/team.html.php index bf8842e118..df72944d97 100644 --- a/module/my/view/team.html.php +++ b/module/my/view/team.html.php @@ -14,7 +14,10 @@ include '../../common/view/header.html.php'; ?>
                    -
                    + +
                    '>task->pri;?> {$extendField->name} > >task->priList, $pri, 'class=form-control');?> > >task->priList, $pri, 'class=form-control');?>bug->deadline;?> deadline) echo $bug->deadline; + if($bug->deadline) echo $bug->deadline; if(isset($bug->delay)) printf($lang->bug->delayWarning, $bug->delay); ?> begin;?>'>begin) ? '' : $child->begin;?>end;?>'>end) ? '' : $child->end;?>begin;?>'>begin) ? '' : $child->begin;?>end;?>'>end) ? '' : $child->end;?> lang->execution->workHour;?>'>hours->totalEstimate . ' ' . $this->lang->execution->workHourUnit;?> lang->execution->workHour;?>'>hours->totalConsumed . ' ' . $this->lang->execution->workHourUnit;?> lang->execution->workHour;?>'>hours->totalLeft . ' ' . $this->lang->execution->workHourUnit;?>
                    - id => sprintf('%03d', $story->id)), ($story->stage == 'developed' or $story->status == 'closed') ? $story->id : '');?> + id => sprintf('%03d', $story->id)), (in_array($story->stage, array('developed', 'closed', 'tested'))) ? $story->id : '');?> story->priList, $story->pri, $story->pri)?> diff --git a/module/release/view/linkstory.html.php b/module/release/view/linkstory.html.php index 0b10f22482..a2979b2f87 100644 --- a/module/release/view/linkstory.html.php +++ b/module/release/view/linkstory.html.php @@ -42,7 +42,7 @@
                    - stage == 'developed' or $story->status == 'closed') echo 'checked';?> /> + stage, array('developed', 'closed', 'tested'))) echo 'checked';?> />
                    id);?> From 2ee1ea4b7a8558516316ecb169731e757bc3226e Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 10:36:41 +0800 Subject: [PATCH 075/304] * Modifying judgment logic. --- module/productplan/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/productplan/model.php b/module/productplan/model.php index bab02fd315..cea66f66ff 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -84,7 +84,7 @@ class productplanModel extends model $plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) ->andWhere('deleted')->eq(0) ->beginIF(!empty($branch) and $branch != 'all')->andWhere('branch')->eq($branch)->fi() - ->beginIF(strpos(',all,undone,', $browseType) === false)->andWhere('status')->eq($browseType)->fi() + ->beginIF(strpos(',all,undone,', ",$browseType,") === false)->andWhere('status')->eq($browseType)->fi() ->beginIF($browseType == 'undone')->andWhere('status')->in('wait,doing')->fi() ->beginIF(strpos($param, 'skipparent') !== false)->andWhere('parent')->ne(-1)->fi() ->orderBy($orderBy) From 4bc08301f8d89e0e252e01b0da858af29174f317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 10:40:11 +0800 Subject: [PATCH 076/304] *Fix bug #22375 --- module/task/js/edit.js | 2 +- module/task/model.php | 1 + module/task/view/edit.html.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/module/task/js/edit.js b/module/task/js/edit.js index 92971548ad..c8c8586921 100644 --- a/module/task/js/edit.js +++ b/module/task/js/edit.js @@ -162,7 +162,7 @@ $('#confirmButton').click(function() var memberCount = ''; var assignedTo = ''; var totalEstimate = 0; - var totalConsumed = 0; + var totalConsumed = oldConsumed; var totalLeft = 0; $('select[name^=team]').each(function() { diff --git a/module/task/model.php b/module/task/model.php index b1d739e7af..f04071e1dc 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -818,6 +818,7 @@ class taskModel extends model $currentTask->consumed += (float)$member->consumed; $currentTask->left += (float)$member->left; } + $currentTask->consumed += (float)$oldTask->consumed; if(!empty($task)) { diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php index 86c852d0c3..8846d49488 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -17,6 +17,7 @@ story);?> assignedTo);?> execution);?> +consumed);?> task->confirmChangeExecution);?> team) < 6 ? 6 - count($task->team) : 1);?> From 9fad4e929bb98a16b1d3f02c62e8900a1bab5db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 11:06:49 +0800 Subject: [PATCH 077/304] *Fix bug #22559. --- module/kanban/css/view.css | 1 + 1 file changed, 1 insertion(+) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 8878575984..1ca818996b 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -127,6 +127,7 @@ .kanban-card .releaseTitle .icon, .kanban-card .title .icon, .kanban-card .productplanTitle .icon, .kanban-card .title .icon, .kanban-card .buildTitle .icon{padding-right: 5px;} .kanban-card .label-finish {margin-right: 7px; margin-top: -1px; padding: 3px 5px; float: left; background-color:#2a5f29;} .kanban-card .releaseTitle, .kanban-card .productplanTitle {width: 100%; float: left;} +.kanban-card .productplanDesc {width: 235px;} .progress-box {width:100%; display: flex; flex-direction: row; margin-top: 10px;} .progress {flex: auto; margin: 5px auto 5px;} From 46e4eae295dd6de002ca1c8d2fe45ee223e9de18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 11:15:33 +0800 Subject: [PATCH 078/304] * Finish task #54205. --- lib/michelf/.github/workflows/ci.yml | 25 + lib/michelf/.scrutinizer.yml | 36 + lib/michelf/.travis.yml | 19 + lib/michelf/Michelf/Markdown.inc.php | 10 + lib/michelf/Michelf/Markdown.php | 1889 ++++++++++++++++ lib/michelf/Michelf/MarkdownExtra.inc.php | 11 + lib/michelf/Michelf/MarkdownExtra.php | 1870 ++++++++++++++++ lib/michelf/Michelf/MarkdownInterface.inc.php | 9 + lib/michelf/Michelf/MarkdownInterface.php | 38 + lib/michelf/michelf.class.php | 27 + lib/parsedownextraplugin/LICENSE.txt | 20 - lib/parsedownextraplugin/parsedown.php | 1992 ----------------- lib/parsedownextraplugin/parsedownextra.php | 686 ------ .../parsedownextraplugin.class.php | 590 ----- module/common/model.php | 8 +- 15 files changed, 3937 insertions(+), 3293 deletions(-) create mode 100644 lib/michelf/.github/workflows/ci.yml create mode 100644 lib/michelf/.scrutinizer.yml create mode 100644 lib/michelf/.travis.yml create mode 100644 lib/michelf/Michelf/Markdown.inc.php create mode 100644 lib/michelf/Michelf/Markdown.php create mode 100644 lib/michelf/Michelf/MarkdownExtra.inc.php create mode 100644 lib/michelf/Michelf/MarkdownExtra.php create mode 100644 lib/michelf/Michelf/MarkdownInterface.inc.php create mode 100644 lib/michelf/Michelf/MarkdownInterface.php create mode 100644 lib/michelf/michelf.class.php delete mode 100644 lib/parsedownextraplugin/LICENSE.txt delete mode 100644 lib/parsedownextraplugin/parsedown.php delete mode 100644 lib/parsedownextraplugin/parsedownextra.php delete mode 100644 lib/parsedownextraplugin/parsedownextraplugin.class.php diff --git a/lib/michelf/.github/workflows/ci.yml b/lib/michelf/.github/workflows/ci.yml new file mode 100644 index 0000000000..6e49b8397b --- /dev/null +++ b/lib/michelf/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI +on: + pull_request: null + push: + branches: + - lib +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + php: ['7.4', '8.0'] + + name: Linting - PHP ${{ matrix.php }} + steps: + - uses: actions/checkout@v2 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + extensions: intl + - run: composer install --no-progress +# - run: composer codestyle + - run: composer phpstan + - run: composer tests diff --git a/lib/michelf/.scrutinizer.yml b/lib/michelf/.scrutinizer.yml new file mode 100644 index 0000000000..7542096df5 --- /dev/null +++ b/lib/michelf/.scrutinizer.yml @@ -0,0 +1,36 @@ +build: + environment: + php: + version: '7.4' + nodes: + analysis: + project_setup: + override: + - 'true' + tests: + override: + - + command: 'vendor/bin/phpunit --coverage-clover=clover.xml' + coverage: + file: 'clover.xml' + format: 'clover' + - + command: phpcs-run + use_website_config: true + environment: + node: + version: 6.0.0 + tests: true +filter: + excluded_paths: + - 'test/*' +checks: + php: true +coding_style: + php: + indentation: + general: + use_tabs: true + spaces: + around_operators: + concatenation: true diff --git a/lib/michelf/.travis.yml b/lib/michelf/.travis.yml new file mode 100644 index 0000000000..5a2a16a4ec --- /dev/null +++ b/lib/michelf/.travis.yml @@ -0,0 +1,19 @@ +language: php + +matrix: + include: + - php: hhvm-3.18 + dist: trusty + - php: 7.4 + dist: bionic + - php: 8.0 + dist: bionic + +install: + - composer install --prefer-dist + +script: + - vendor/bin/phpunit --log-junit=phpunit.log + +notifications: + email: false diff --git a/lib/michelf/Michelf/Markdown.inc.php b/lib/michelf/Michelf/Markdown.inc.php new file mode 100644 index 0000000000..e2bd3808e8 --- /dev/null +++ b/lib/michelf/Michelf/Markdown.inc.php @@ -0,0 +1,10 @@ + + * @copyright 2004-2019 Michel Fortin + * @copyright (Original Markdown) 2004-2006 John Gruber + */ + +namespace Michelf; + +/** + * Markdown Parser Class + */ +class Markdown implements MarkdownInterface { + /** + * Define the package version + * @var string + */ + const MARKDOWNLIB_VERSION = "2.0"; + + /** + * Simple function interface - Initialize the parser and return the result + * of its transform method. This will work fine for derived classes too. + * + * @api + * + * @param string $text + * @return string + */ + public static function defaultTransform($text) { + // Take parser class on which this function was called. + $parser_class = static::class; + + // Try to take parser from the static parser list + static $parser_list; + $parser =& $parser_list[$parser_class]; + + // Create the parser it not already set + if (!$parser) { + $parser = new $parser_class; + } + + // Transform text using parser. + return $parser->transform($text); + } + + /** + * Configuration variables + */ + /** + * Change to ">" for HTML output. + */ + public string $empty_element_suffix = " />"; + + /** + * The width of indentation of the output markup + */ + public int $tab_width = 4; + + /** + * Change to `true` to disallow markup or entities. + */ + public bool $no_markup = false; + public bool $no_entities = false; + + + /** + * Change to `true` to enable line breaks on \n without two trailling spaces + * @var boolean + */ + public bool $hard_wrap = false; + + /** + * Predefined URLs and titles for reference links and images. + */ + public array $predef_urls = array(); + public array $predef_titles = array(); + + /** + * Optional filter function for URLs + * @var callable|null + */ + public $url_filter_func = null; + + /** + * Optional header id="" generation callback function. + * @var callable|null + */ + public $header_id_func = null; + + /** + * Optional function for converting code block content to HTML + * @var callable|null + */ + public $code_block_content_func = null; + + /** + * Optional function for converting code span content to HTML. + * @var callable|null + */ + public $code_span_content_func = null; + + /** + * Class attribute to toggle "enhanced ordered list" behaviour + * setting this to true will allow ordered lists to start from the index + * number that is defined first. + * + * For example: + * 2. List item two + * 3. List item three + * + * Becomes: + *
                      + *
                    1. List item two
                    2. + *
                    3. List item three
                    4. + *
                    + */ + public bool $enhanced_ordered_list = false; + + /** + * Parser implementation + */ + /** + * Regex to match balanced [brackets]. + * Needed to insert a maximum bracked depth while converting to PHP. + */ + protected int $nested_brackets_depth = 6; + protected $nested_brackets_re; + + protected int $nested_url_parenthesis_depth = 4; + protected $nested_url_parenthesis_re; + + /** + * Table of hash values for escaped characters: + */ + protected string $escape_chars = '\`*_{}[]()>#+-.!'; + protected string $escape_chars_re; + + /** + * Constructor function. Initialize appropriate member variables. + * @return void + */ + public function __construct() { + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + // Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + /** + * Internal hashes used during transformation. + */ + protected array $urls = array(); + protected $titles = array(); + protected array $html_hashes = array(); + + /** + * Status flag to avoid invalid nesting. + */ + protected bool $in_anchor = false; + + /** + * Status flag to avoid invalid nesting. + */ + protected bool $in_emphasis_processing = false; + + /** + * Called before the transformation process starts to setup parser states. + * @return void + */ + protected function setup() { + // Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + $this->in_anchor = false; + $this->in_emphasis_processing = false; + } + + /** + * Called after the transformation process to clear any variable which may + * be taking up memory unnecessarly. + * @return void + */ + protected function teardown() { + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + /** + * Main function. Performs some preprocessing on the input text and pass + * it through the document gamut. + * + * @api + * + * @param string $text + * @return string + */ + public function transform($text) { + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + /** + * Define the document gamut + */ + protected array $document_gamut = array( + // Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + "runBasicBlockGamut" => 30, + ); + + /** + * Strips link definitions from text, stores the URLs and titles in + * hash references + * @param string $text + * @return string + */ + protected function stripLinkDefinitions($text) { + + $less_than_tab = $this->tab_width - 1; + + // Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array($this, '_stripLinkDefinitions_callback'), + $text + ); + return $text; + } + + /** + * The callback to strip link definitions + * @param array $matches + * @return string + */ + protected function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; // String that will replace the block + } + + /** + * Hashify HTML blocks + * @param string $text + * @return string + */ + protected function hashHTMLBlocks($text) { + if ($this->no_markup) { + return $text; + } + + $less_than_tab = $this->tab_width - 1; + + /** + * Hashify HTML blocks: + * + * We only want to do this for block-level HTML tags, such as headers, + * lists, and tables. That's because we still want to wrap

                    s around + * "paragraphs" that are wrapped in non-block-level tags, such as + * anchors, phrase emphasis, and spans. The list of tags we're looking + * for is hard-coded: + * + * * List "a" is made of tags which can be both inline or block-level. + * These will be treated block-level when the start tag is alone on + * its line, otherwise they're not matched here and will be taken as + * inline later. + * * List "b" is made of tags which are always block-level; + */ + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|style|form|fieldset|iframe|math|svg|'. + 'article|section|nav|aside|hgroup|header|footer|'. + 'figure|details|summary'; + + // Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). // end of opening tag + '.*?'. // last level nested tag content + str_repeat(' + # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + /** + * First, look for nested blocks, e.g.: + *

                    + *
                    + * tags for inner block must be indented. + *
                    + *
                    + * + * The outermost tags must start at the left margin for this to match, + * and the inner nested divs must be indented. + * We need to do this before the next, more liberal match, because the + * next match will start at the first `
                    ` and stop at the + * first `
                    `. + */ + $text = preg_replace_callback('{(?> + (?> + (?<=\n) # Starting on its own line + | # or + \A\n? # the at beginning of the doc + ) + ( # save in $1 + + # Match from `\n` to `\n`, handling nested tags + # in between. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_b_re.')# start tag = $2 + '.$attr.'> # attributes followed by > and \n + '.$content.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special version for tags of group a. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_a_re.')# start tag = $3 + '.$attr.'>[ ]*\n # attributes followed by > + '.$content2.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special case just for
                    . It was easier to make a special + # case than to make the other regex more complicated. + + [ ]{0,'.$less_than_tab.'} + <(hr) # start tag = $2 + '.$attr.' # attributes + /?> # the matching end tag + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # Special case for standalone HTML comments: + + [ ]{0,'.$less_than_tab.'} + (?s: + + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # PHP and ASP-style processor instructions ( + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + ) + )}Sxmi', + array($this, '_hashHTMLBlocks_callback'), + $text + ); + + return $text; + } + + /** + * The callback for hashing HTML blocks + * @param string $matches + * @return string + */ + protected function _hashHTMLBlocks_callback($matches) { + $text = $matches[1]; + $key = $this->hashBlock($text); + return "\n\n$key\n\n"; + } + + /** + * Called whenever a tag must be hashed when a function insert an atomic + * element in the text stream. Passing $text to through this function gives + * a unique text-token which will be reverted back when calling unhash. + * + * The $boundary argument specify what character should be used to surround + * the token. By convension, "B" is used for block elements that needs not + * to be wrapped into paragraph tags at the end, ":" is used for elements + * that are word separators and "X" is used in the general case. + * + * @param string $text + * @param string $boundary + * @return string + */ + protected function hashPart($text, $boundary = 'X') { + // Swap back any tag hash found in $text so we do not have to `unhash` + // multiple times at the end. + $text = $this->unhash($text); + + // Then hash the block. + static $i = 0; + $key = "$boundary\x1A" . ++$i . $boundary; + $this->html_hashes[$key] = $text; + return $key; // String that will replace the tag. + } + + /** + * Shortcut function for hashPart with block-level boundaries. + * @param string $text + * @return string + */ + protected function hashBlock($text) { + return $this->hashPart($text, 'B'); + } + + /** + * Define the block gamut - these are all the transformations that form + * block-level tags like paragraphs, headers, and list items. + */ + protected array $block_gamut = array( + "doHeaders" => 10, + "doHorizontalRules" => 20, + "doLists" => 40, + "doCodeBlocks" => 50, + "doBlockQuotes" => 60, + ); + + /** + * Run block gamut tranformations. + * + * We need to escape raw HTML in Markdown source before doing anything + * else. This need to be done for each block, and not only at the + * begining in the Markdown function since hashed blocks can be part of + * list items and could have been indented. Indented blocks would have + * been seen as a code block in a previous pass of hashHTMLBlocks. + * + * @param string $text + * @return string + */ + protected function runBlockGamut($text) { + $text = $this->hashHTMLBlocks($text); + return $this->runBasicBlockGamut($text); + } + + /** + * Run block gamut tranformations, without hashing HTML blocks. This is + * useful when HTML blocks are known to be already hashed, like in the first + * whole-document pass. + * + * @param string $text + * @return string + */ + protected function runBasicBlockGamut($text) { + + foreach ($this->block_gamut as $method => $priority) { + $text = $this->$method($text); + } + + // Finally form paragraph and restore hashed blocks. + $text = $this->formParagraphs($text); + + return $text; + } + + /** + * Convert horizontal rules + * @param string $text + * @return string + */ + protected function doHorizontalRules($text) { + return preg_replace( + '{ + ^[ ]{0,3} # Leading space + ([-*_]) # $1: First marker + (?> # Repeated marker group + [ ]{0,2} # Zero, one, or two spaces. + \1 # Marker character + ){2,} # Group repeated at least twice + [ ]* # Tailing spaces + $ # End of line. + }mx', + "\n".$this->hashBlock("empty_element_suffix")."\n", + $text + ); + } + + /** + * These are all the transformations that occur *within* block-level + * tags like paragraphs, headers, and list items. + */ + protected array $span_gamut = array( + // Process character escapes, code spans, and inline HTML + // in one shot. + "parseSpan" => -30, + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + "doImages" => 10, + "doAnchors" => 20, + // Make links out of things like `` + // Must come after doAnchors, because you can use < and > + // delimiters in inline links like [this](). + "doAutoLinks" => 30, + "encodeAmpsAndAngles" => 40, + "doItalicsAndBold" => 50, + "doHardBreaks" => 60, + ); + + /** + * Run span gamut transformations + * @param string $text + * @return string + */ + protected function runSpanGamut($text) { + foreach ($this->span_gamut as $method => $priority) { + $text = $this->$method($text); + } + + return $text; + } + + /** + * Do hard breaks + * @param string $text + * @return string + */ + protected function doHardBreaks($text) { + if ($this->hard_wrap) { + return preg_replace_callback('/ *\n/', + array($this, '_doHardBreaks_callback'), $text); + } else { + return preg_replace_callback('/ {2,}\n/', + array($this, '_doHardBreaks_callback'), $text); + } + } + + /** + * Trigger part hashing for the hard break (callback method) + * @param array $matches + * @return string + */ + protected function _doHardBreaks_callback($matches) { + return $this->hashPart("empty_element_suffix\n"); + } + + /** + * Turn Markdown link shortcuts into XHTML tags. + * @param string $text + * @return string + */ + protected function doAnchors($text) { + if ($this->in_anchor) { + return $text; + } + $this->in_anchor = true; + + // First, handle reference-style links: [link text] [id] + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array($this, '_doAnchors_reference_callback'), $text); + + // Next, inline-style links: [link text](url "optional title") + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + ) + }xs', + array($this, '_doAnchors_inline_callback'), $text); + + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link text][1] + // or [link text](/foo) + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array($this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + + /** + * Callback method to parse referenced anchors + * @param array $matches + * @return string + */ + protected function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + // for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + // lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeURLAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } else { + $result = $whole_match; + } + return $result; + } + + /** + * Callback method to parse inline anchors + * @param array $matches + * @return string + */ + protected function _doAnchors_inline_callback($matches) { + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] === '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + // If the URL was of the form it got caught by the HTML + // tag parser and hashed. Need to reverse the process before using + // the URL. + $unhashed = $this->unhash($url); + if ($unhashed !== $url) + $url = preg_replace('/^<(.*)>$/', '\1', $unhashed); + + $url = $this->encodeURLAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + /** + * Turn Markdown image shortcuts into tags. + * @param string $text + * @return string + */ + protected function doImages($text) { + // First, handle reference-style labeled images: ![alt text][id] + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array($this, '_doImages_reference_callback'), $text); + + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + ) + }xs', + array($this, '_doImages_inline_callback'), $text); + + return $text; + } + + /** + * Callback to parse references image tags + * @param array $matches + * @return string + */ + protected function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); // for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeURLAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } else { + // If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + + /** + * Callback to parse inline image tags + * @param array $matches + * @return string + */ + protected function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeURLAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; // $title already quoted + } + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + /** + * Parse Markdown heading elements to HTML + * @param string $text + * @return string + */ + protected function doHeaders($text) { + /** + * Setext-style headers: + * Header 1 + * ======== + * + * Header 2 + * -------- + */ + $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', + array($this, '_doHeaders_callback_setext'), $text); + + /** + * atx-style headers: + * # Header 1 + * ## Header 2 + * ## Header 2 with closing hashes ## + * ... + * ###### Header 6 + */ + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + \n+ + }xm', + array($this, '_doHeaders_callback_atx'), $text); + + return $text; + } + + /** + * Setext header parsing callback + * @param array $matches + * @return string + */ + protected function _doHeaders_callback_setext($matches) { + // Terrible hack to check we haven't found an empty list item. + if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) { + return $matches[0]; + } + + $level = $matches[2][0] == '=' ? 1 : 2; + + // ID attribute generation + $idAtt = $this->_generateIdFromHeaderValue($matches[1]); + + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + /** + * ATX header parsing callback + * @param array $matches + * @return string + */ + protected function _doHeaders_callback_atx($matches) { + // ID attribute generation + $idAtt = $this->_generateIdFromHeaderValue($matches[2]); + + $level = strlen($matches[1]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + /** + * If a header_id_func property is set, we can use it to automatically + * generate an id attribute. + * + * This method returns a string in the form id="foo", or an empty string + * otherwise. + * @param string $headerValue + * @return string + */ + protected function _generateIdFromHeaderValue($headerValue) { + if (!is_callable($this->header_id_func)) { + return ""; + } + + $idValue = call_user_func($this->header_id_func, $headerValue); + if (!$idValue) { + return ""; + } + + return ' id="' . $this->encodeAttribute($idValue) . '"'; + } + + /** + * Form HTML ordered (numbered) and unordered (bulleted) lists. + * @param string $text + * @return string + */ + protected function doLists($text) { + $less_than_tab = $this->tab_width - 1; + + // Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + + $markers_relist = array( + $marker_ul_re => $marker_ol_re, + $marker_ol_re => $marker_ul_re, + ); + + foreach ($markers_relist as $marker_re => $other_marker_re) { + // Re-usable pattern to match any entirel ul or ol list: + $whole_list_re = ' + ( # $1 = whole list + ( # $2 + ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces + ('.$marker_re.') # $4 = first list item marker + [ ]+ + ) + (?s:.+?) + ( # $5 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another list item marker + [ ]* + '.$marker_re.'[ ]+ + ) + | + (?= # Lookahead for another kind of list + \n + \3 # Must have the same indentation + '.$other_marker_re.'[ ]+ + ) + ) + ) + '; // mx + + // We use a different prefix before nested lists than top-level lists. + //See extended comment in _ProcessListItems(). + + if ($this->list_level) { + $text = preg_replace_callback('{ + ^ + '.$whole_list_re.' + }mx', + array($this, '_doLists_callback'), $text); + } else { + $text = preg_replace_callback('{ + (?:(?<=\n)\n|\A\n?) # Must eat the newline + '.$whole_list_re.' + }mx', + array($this, '_doLists_callback'), $text); + } + } + + return $text; + } + + /** + * List parsing callback + * @param array $matches + * @return string + */ + protected function _doLists_callback($matches) { + // Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + $marker_ol_start_re = '[0-9]+'; + + $list = $matches[1]; + $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; + + $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); + + $list .= "\n"; + $result = $this->processListItems($list, $marker_any_re); + + $ol_start = 1; + if ($this->enhanced_ordered_list) { + // Get the start number for ordered list. + if ($list_type == 'ol') { + $ol_start_array = array(); + $ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array); + if ($ol_start_check){ + $ol_start = $ol_start_array[0]; + } + } + } + + if ($ol_start > 1 && $list_type == 'ol'){ + $result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . ""); + } else { + $result = $this->hashBlock("<$list_type>\n" . $result . ""); + } + return "\n". $result ."\n\n"; + } + + /** + * Nesting tracker for list levels + */ + protected int $list_level = 0; + + /** + * Process the contents of a single ordered or unordered list, splitting it + * into individual list items. + * @param string $list_str + * @param string $marker_any_re + * @return string + */ + protected function processListItems($list_str, $marker_any_re) { + /** + * The $this->list_level global keeps track of when we're inside a list. + * Each time we enter a list, we increment it; when we leave a list, + * we decrement. If it's zero, we're not in a list anymore. + * + * We do this because when we're not inside a list, we want to treat + * something like this: + * + * I recommend upgrading to version + * 8. Oops, now this line is treated + * as a sub-list. + * + * As a single paragraph, despite the fact that the second line starts + * with a digit-period-space sequence. + * + * Whereas when we're inside a list (or sub-list), that line will be + * treated as the start of a sub-list. What a kludge, huh? This is + * an aspect of Markdown's syntax that's hard to parse perfectly + * without resorting to mind-reading. Perhaps the solution is to + * change the syntax rules such that sub-lists must start with a + * starting cardinal number; e.g. "1." or "a.". + */ + $this->list_level++; + + // Trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + $list_str = preg_replace_callback('{ + (\n)? # leading line = $1 + (^[ ]*) # leading whitespace = $2 + ('.$marker_any_re.' # list marker and space = $3 + (?:[ ]+|(?=\n)) # space only required if item is not empty + ) + ((?s:.*?)) # list item text = $4 + (?:(\n+(?=\n))|\n) # tailing blank line = $5 + (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) + }xm', + array($this, '_processListItems_callback'), $list_str); + + $this->list_level--; + return $list_str; + } + + /** + * List item parsing callback + * @param array $matches + * @return string + */ + protected function _processListItems_callback($matches) { + $item = $matches[4]; + $leading_line =& $matches[1]; + $leading_space =& $matches[2]; + $marker_space = $matches[3]; + $tailing_blank_line =& $matches[5]; + + if ($leading_line || $tailing_blank_line || + preg_match('/\n{2,}/', $item)) + { + // Replace marker with the appropriate whitespace indentation + $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; + $item = $this->runBlockGamut($this->outdent($item)."\n"); + } else { + // Recursion for sub-lists: + $item = $this->doLists($this->outdent($item)); + $item = $this->formParagraphs($item, false); + } + + return "
                  • " . $item . "
                  • \n"; + } + + /** + * Process Markdown `
                    ` blocks.
                    +	 * @param  string $text
                    +	 * @return string
                    +	 */
                    +	protected function doCodeBlocks($text) {
                    +		$text = preg_replace_callback('{
                    +				(?:\n\n|\A\n?)
                    +				(	            # $1 = the code block -- one or more lines, starting with a space/tab
                    +				  (?>
                    +					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
                    +					.*\n+
                    +				  )+
                    +				)
                    +				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
                    +			}xm',
                    +			array($this, '_doCodeBlocks_callback'), $text);
                    +
                    +		return $text;
                    +	}
                    +
                    +	/**
                    +	 * Code block parsing callback
                    +	 * @param  array $matches
                    +	 * @return string
                    +	 */
                    +	protected function _doCodeBlocks_callback($matches) {
                    +		$codeblock = $matches[1];
                    +
                    +		$codeblock = $this->outdent($codeblock);
                    +		if (is_callable($this->code_block_content_func)) {
                    +			$codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
                    +		} else {
                    +			$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
                    +		}
                    +
                    +		# trim leading newlines and trailing newlines
                    +		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
                    +
                    +		$codeblock = "
                    $codeblock\n
                    "; + return "\n\n" . $this->hashBlock($codeblock) . "\n\n"; + } + + /** + * Create a code span markup for $code. Called from handleSpanToken. + * @param string $code + * @return string + */ + protected function makeCodeSpan($code) { + if (is_callable($this->code_span_content_func)) { + $code = call_user_func($this->code_span_content_func, $code); + } else { + $code = htmlspecialchars(trim($code), ENT_NOQUOTES); + } + return $this->hashPart("$code"); + } + + /** + * Define the emphasis operators with their regex matches + * @var array + */ + protected array $em_relist = array( + '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(?em_relist as $em => $em_re) { + foreach ($this->strong_relist as $strong => $strong_re) { + // Construct list of allowed token expressions. + $token_relist = array(); + if (isset($this->em_strong_relist["$em$strong"])) { + $token_relist[] = $this->em_strong_relist["$em$strong"]; + } + $token_relist[] = $em_re; + $token_relist[] = $strong_re; + + // Construct master expression from list. + $token_re = '{(' . implode('|', $token_relist) . ')}'; + $this->em_strong_prepared_relist["$em$strong"] = $token_re; + } + } + } + + /** + * Convert Markdown italics (emphasis) and bold (strong) to HTML + * @param string $text + * @return string + */ + protected function doItalicsAndBold($text) { + if ($this->in_emphasis_processing) { + return $text; // avoid reentrency + } + $this->in_emphasis_processing = true; + + $token_stack = array(''); + $text_stack = array(''); + $em = ''; + $strong = ''; + $tree_char_em = false; + + while (1) { + // Get prepared regular expression for seraching emphasis tokens + // in current context. + $token_re = $this->em_strong_prepared_relist["$em$strong"]; + + // Each loop iteration search for the next emphasis token. + // Each token is then passed to handleSpanToken. + $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + $text_stack[0] .= $parts[0]; + $token =& $parts[1]; + $text =& $parts[2]; + + if (empty($token)) { + // Reached end of text span: empty stack without emitting. + // any more emphasis. + while ($token_stack[0]) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + break; + } + + $token_len = strlen($token); + if ($tree_char_em) { + // Reached closing marker while inside a three-char emphasis. + if ($token_len == 3) { + // Three-char closing marker, close em and strong. + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + $strong = ''; + } else { + // Other closing marker: close one em or strong and + // change current token state to match the other + $token_stack[0] = str_repeat($token[0], 3-$token_len); + $tag = $token_len == 2 ? "strong" : "em"; + $span = $text_stack[0]; + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] = $this->hashPart($span); + $$tag = ''; // $$tag stands for $em or $strong + } + $tree_char_em = false; + } else if ($token_len == 3) { + if ($em) { + // Reached closing marker for both em and strong. + // Closing strong marker: + for ($i = 0; $i < 2; ++$i) { + $shifted_token = array_shift($token_stack); + $tag = strlen($shifted_token) == 2 ? "strong" : "em"; + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] .= $this->hashPart($span); + $$tag = ''; // $$tag stands for $em or $strong + } + } else { + // Reached opening three-char emphasis marker. Push on token + // stack; will be handled by the special condition above. + $em = $token[0]; + $strong = "$em$em"; + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $tree_char_em = true; + } + } else if ($token_len == 2) { + if ($strong) { + // Unwind any dangling emphasis marker: + if (strlen($token_stack[0]) == 1) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + $em = ''; + } + // Closing strong marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $strong = ''; + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $strong = $token; + } + } else { + // Here $token_len == 1 + if ($em) { + if (strlen($token_stack[0]) == 1) { + // Closing emphasis marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + } else { + $text_stack[0] .= $token; + } + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $em = $token; + } + } + } + $this->in_emphasis_processing = false; + return $text_stack[0]; + } + + /** + * Parse Markdown blockquotes to HTML + * @param string $text + * @return string + */ + protected function doBlockQuotes($text) { + $text = preg_replace_callback('/ + ( # Wrap whole match in $1 + (?> + ^[ ]*>[ ]? # ">" at the start of a line + .+\n # rest of the first line + (.+\n)* # subsequent consecutive lines + \n* # blanks + )+ + ) + /xm', + array($this, '_doBlockQuotes_callback'), $text); + + return $text; + } + + /** + * Blockquote parsing callback + * @param array $matches + * @return string + */ + protected function _doBlockQuotes_callback($matches) { + $bq = $matches[1]; + // trim one level of quoting - trim whitespace-only lines + $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); + $bq = $this->runBlockGamut($bq); // recurse + + $bq = preg_replace('/^/m', " ", $bq); + // These leading spaces cause problem with
                     content,
                    +		// so we need to fix that:
                    +		$bq = preg_replace_callback('{(\s*
                    .+?
                    )}sx', + array($this, '_doBlockQuotes_callback2'), $bq); + + return "\n" . $this->hashBlock("
                    \n$bq\n
                    ") . "\n\n"; + } + + /** + * Blockquote parsing callback + * @param array $matches + * @return string + */ + protected function _doBlockQuotes_callback2($matches) { + $pre = $matches[1]; + $pre = preg_replace('/^ /m', '', $pre); + return $pre; + } + + /** + * Parse paragraphs + * + * @param string $text String to process in paragraphs + * @param boolean $wrap_in_p Whether paragraphs should be wrapped in

                    tags + * @return string + */ + protected function formParagraphs($text, $wrap_in_p = true) { + // Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + // Wrap

                    tags and unhashify HTML blocks + foreach ($grafs as $key => $value) { + if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { + // Is a paragraph. + $value = $this->runSpanGamut($value); + if ($wrap_in_p) { + $value = preg_replace('/^([ ]*)/', "

                    ", $value); + $value .= "

                    "; + } + $grafs[$key] = $this->unhash($value); + } else { + // Is a block. + // Modify elements of @grafs in-place... + $graf = $value; + $block = $this->html_hashes[$graf]; + $graf = $block; +// if (preg_match('{ +// \A +// ( # $1 =
                    tag +//
                    ]* +// \b +// markdown\s*=\s* ([\'"]) # $2 = attr quote char +// 1 +// \2 +// [^>]* +// > +// ) +// ( # $3 = contents +// .* +// ) +// (
                    ) # $4 = closing tag +// \z +// }xs', $block, $matches)) +// { +// list(, $div_open, , $div_content, $div_close) = $matches; +// +// // We can't call Markdown(), because that resets the hash; +// // that initialization code should be pulled into its own sub, though. +// $div_content = $this->hashHTMLBlocks($div_content); +// +// // Run document gamut methods on the content. +// foreach ($this->document_gamut as $method => $priority) { +// $div_content = $this->$method($div_content); +// } +// +// $div_open = preg_replace( +// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); +// +// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; +// } + $grafs[$key] = $graf; + } + } + + return implode("\n\n", $grafs); + } + + /** + * Encode text for a double-quoted HTML attribute. This function + * is *not* suitable for attributes enclosed in single quotes. + * @param string $text + * @return string + */ + protected function encodeAttribute($text) { + $text = $this->encodeAmpsAndAngles($text); + $text = str_replace('"', '"', $text); + return $text; + } + + /** + * Encode text for a double-quoted HTML attribute containing a URL, + * applying the URL filter if set. Also generates the textual + * representation for the URL (removing mailto: or tel:) storing it in $text. + * This function is *not* suitable for attributes enclosed in single quotes. + * + * @param string $url + * @param string $text Passed by reference + * @return string URL + */ + protected function encodeURLAttribute($url, &$text = null) { + if (is_callable($this->url_filter_func)) { + $url = call_user_func($this->url_filter_func, $url); + } + + if (preg_match('{^mailto:}i', $url)) { + $url = $this->encodeEntityObfuscatedAttribute($url, $text, 7); + } else if (preg_match('{^tel:}i', $url)) { + $url = $this->encodeAttribute($url); + $text = substr($url, 4); + } else { + $url = $this->encodeAttribute($url); + $text = $url; + } + + return $url; + } + + /** + * Smart processing for ampersands and angle brackets that need to + * be encoded. Valid character entities are left alone unless the + * no-entities mode is set. + * @param string $text + * @return string + */ + protected function encodeAmpsAndAngles($text) { + if ($this->no_entities) { + $text = str_replace('&', '&', $text); + } else { + // Ampersand-encoding based entirely on Nat Irons's Amputator + // MT plugin: + $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', + '&', $text); + } + // Encode remaining <'s + $text = str_replace('<', '<', $text); + + return $text; + } + + /** + * Parse Markdown automatic links to anchor HTML tags + * @param string $text + * @return string + */ + protected function doAutoLinks($text) { + $text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i', + array($this, '_doAutoLinks_url_callback'), $text); + + // Email addresses: + $text = preg_replace_callback('{ + < + (?:mailto:)? + ( + (?: + [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ + | + ".*?" + ) + \@ + (?: + [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ + | + \[[\d.a-fA-F:]+\] # IPv4 & IPv6 + ) + ) + > + }xi', + array($this, '_doAutoLinks_email_callback'), $text); + + return $text; + } + + /** + * Parse URL callback + * @param array $matches + * @return string + */ + protected function _doAutoLinks_url_callback($matches) { + $url = $this->encodeURLAttribute($matches[1], $text); + $link = "$text"; + return $this->hashPart($link); + } + + /** + * Parse email address callback + * @param array $matches + * @return string + */ + protected function _doAutoLinks_email_callback($matches) { + $addr = $matches[1]; + $url = $this->encodeURLAttribute("mailto:$addr", $text); + $link = "$text"; + return $this->hashPart($link); + } + + /** + * Input: some text to obfuscate, e.g. "mailto:foo@example.com" + * + * Output: the same text but with most characters encoded as either a + * decimal or hex entity, in the hopes of foiling most address + * harvesting spam bots. E.g.: + * + * mailto:foo + * @example.co + * m + * + * Note: the additional output $tail is assigned the same value as the + * ouput, minus the number of characters specified by $head_length. + * + * Based by a filter by Matthew Wickline, posted to BBEdit-Talk. + * With some optimizations by Milian Wolff. Forced encoding of HTML + * attribute special characters by Allan Odgaard. + * + * @param string $text + * @param string $tail Passed by reference + * @param integer $head_length + * @return string + */ + protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) { + if ($text == "") { + return $tail = ""; + } + + $chars = preg_split('/(? $char) { + $ord = ord($char); + // Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; // Pseudo-random function. + // roughly 10% raw, 45% hex, 45% dec + // '@' *must* be encoded. I insist. + // '"' and '>' have to be encoded inside the attribute + if ($r > 90 && strpos('@"&>', $char) === false) { + /* do nothing */ + } else if ($r < 45) { + $chars[$key] = '&#x'.dechex($ord).';'; + } else { + $chars[$key] = '&#'.$ord.';'; + } + } + } + + $text = implode('', $chars); + $tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text; + + return $text; + } + + /** + * Take the string $str and parse it into tokens, hashing embeded HTML, + * escaped characters and handling code spans. + * @param string $str + * @return string + */ + protected function parseSpan($str) { + $output = ''; + + $span_re = '{ + ( + \\\\'.$this->escape_chars_re.' + | + (?no_markup ? '' : ' + | + # comment + | + <\?.*?\?> | <%.*?%> # processing instruction + | + <[!$]?[-a-zA-Z0-9:_]+ # regular tags + (?> + \s + (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* + )? + > + | + <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag + | + # closing tag + ').' + ) + }xs'; + + while (1) { + // Each loop iteration seach for either the next tag, the next + // openning code span marker, or the next escaped character. + // Each token is then passed to handleSpanToken. + $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); + + // Create token from text preceding tag. + if ($parts[0] != "") { + $output .= $parts[0]; + } + + // Check if we reach the end. + if (isset($parts[1])) { + $output .= $this->handleSpanToken($parts[1], $parts[2]); + $str = $parts[2]; + } else { + break; + } + } + + return $output; + } + + /** + * Handle $token provided by parseSpan by determining its nature and + * returning the corresponding value that should replace it. + * @param string $token + * @param string $str Passed by reference + * @return string + */ + protected function handleSpanToken($token, &$str) { + switch ($token[0]) { + case "\\": + return $this->hashPart("&#". ord($token[1]). ";"); + case "`": + // Search for end marker in remaining text. + if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', + $str, $matches)) + { + $str = $matches[2]; + $codespan = $this->makeCodeSpan($matches[1]); + return $this->hashPart($codespan); + } + return $token; // Return as text since no ending marker found. + default: + return $this->hashPart($token); + } + } + + /** + * Remove one level of line-leading tabs or spaces + * @param string $text + * @return string + */ + protected function outdent($text) { + return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text); + } + + + /** + * String length function for detab. `_initDetab` will create a function to + * handle UTF-8 if the default function does not exist. + * can be a string or function + */ + protected $utf8_strlen = 'mb_strlen'; + + /** + * Replace tabs with the appropriate amount of spaces. + * + * For each line we separate the line in blocks delemited by tab characters. + * Then we reconstruct every line by adding the appropriate number of space + * between each blocks. + * + * @param string $text + * @return string + */ + protected function detab($text) { + $text = preg_replace_callback('/^.*\t.*$/m', + array($this, '_detab_callback'), $text); + + return $text; + } + + /** + * Replace tabs callback + * @param string $matches + * @return string + */ + protected function _detab_callback($matches) { + $line = $matches[0]; + $strlen = $this->utf8_strlen; // strlen function for UTF-8. + + // Split in blocks. + $blocks = explode("\t", $line); + // Add each blocks to the line. + $line = $blocks[0]; + unset($blocks[0]); // Do not add first block twice. + foreach ($blocks as $block) { + // Calculate amount of space, insert spaces, insert block. + $amount = $this->tab_width - + $strlen($line, 'UTF-8') % $this->tab_width; + $line .= str_repeat(" ", $amount) . $block; + } + return $line; + } + + /** + * Check for the availability of the function in the `utf8_strlen` property + * (initially `mb_strlen`). If the function is not available, create a + * function that will loosely count the number of UTF-8 characters with a + * regular expression. + * @return void + */ + protected function _initDetab() { + + if (function_exists($this->utf8_strlen)) { + return; + } + + $this->utf8_strlen = fn($text) => preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m); + } + + /** + * Swap back in all the tags hashed by _HashHTMLBlocks. + * @param string $text + * @return string + */ + protected function unhash($text) { + return preg_replace_callback('/(.)\x1A[0-9]+\1/', + array($this, '_unhash_callback'), $text); + } + + /** + * Unhashing callback + * @param array $matches + * @return string + */ + protected function _unhash_callback($matches) { + return $this->html_hashes[$matches[0]]; + } +} diff --git a/lib/michelf/Michelf/MarkdownExtra.inc.php b/lib/michelf/Michelf/MarkdownExtra.inc.php new file mode 100644 index 0000000000..d09bd7a480 --- /dev/null +++ b/lib/michelf/Michelf/MarkdownExtra.inc.php @@ -0,0 +1,11 @@ + + * @copyright 2004-2019 Michel Fortin + * @copyright (Original Markdown) 2004-2006 John Gruber + */ + +namespace Michelf; + +/** + * Markdown Extra Parser Class + */ +class MarkdownExtra extends \Michelf\Markdown { + /** + * Configuration variables + */ + /** + * Prefix for footnote ids. + */ + public string $fn_id_prefix = ""; + + /** + * Optional title attribute for footnote links. + */ + public string $fn_link_title = ""; + + /** + * Optional class attribute for footnote links and backlinks. + */ + public string $fn_link_class = "footnote-ref"; + public string $fn_backlink_class = "footnote-backref"; + + /** + * Content to be displayed within footnote backlinks. The default is '↩'; + * the U+FE0E on the end is a Unicode variant selector used to prevent iOS + * from displaying the arrow character as an emoji. + * Optionally use '^^' and '%%' to refer to the footnote number and + * reference number respectively. {@see parseFootnotePlaceholders()} + */ + public string $fn_backlink_html = '↩︎'; + + /** + * Optional title and aria-label attributes for footnote backlinks for + * added accessibility (to ensure backlink uniqueness). + * Use '^^' and '%%' to refer to the footnote number and reference number + * respectively. {@see parseFootnotePlaceholders()} + */ + public string $fn_backlink_title = ""; + public string $fn_backlink_label = ""; + + /** + * Class name for table cell alignment (%% replaced left/center/right) + * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center' + * If empty, the align attribute is used instead of a class name. + */ + public string $table_align_class_tmpl = ''; + + /** + * Optional class prefix for fenced code block. + */ + public string $code_class_prefix = ""; + + /** + * Class attribute for code blocks goes on the `code` tag; + * setting this to true will put attributes on the `pre` tag instead. + */ + public bool $code_attr_on_pre = false; + + /** + * Predefined abbreviations. + */ + public array $predef_abbr = array(); + + /** + * Only convert atx-style headers if there's a space between the header and # + */ + public bool $hashtag_protection = false; + + /** + * Determines whether footnotes should be appended to the end of the document. + * If true, footnote html can be retrieved from $this->footnotes_assembled. + */ + public bool $omit_footnotes = false; + + + /** + * After parsing, the HTML for the list of footnotes appears here. + * This is available only if $omit_footnotes == true. + * + * Note: when placing the content of `footnotes_assembled` on the page, + * consider adding the attribute `role="doc-endnotes"` to the `div` or + * `section` that will enclose the list of footnotes so they are + * reachable to accessibility tools the same way they would be with the + * default HTML output. + */ + public ?string $footnotes_assembled = null; + + /** + * Parser implementation + */ + + /** + * Constructor function. Initialize the parser object. + * @return void + */ + public function __construct() { + // Add extra escapable characters before parent constructor + // initialize the table. + $this->escape_chars .= ':|'; + + // Insert extra document, block, and span transformations. + // Parent constructor will do the sorting. + $this->document_gamut += array( + "doFencedCodeBlocks" => 5, + "stripFootnotes" => 15, + "stripAbbreviations" => 25, + "appendFootnotes" => 50, + ); + $this->block_gamut += array( + "doFencedCodeBlocks" => 5, + "doTables" => 15, + "doDefLists" => 45, + ); + $this->span_gamut += array( + "doFootnotes" => 5, + "doAbbreviations" => 70, + ); + + $this->enhanced_ordered_list = true; + parent::__construct(); + } + + + /** + * Extra variables used during extra transformations. + */ + protected array $footnotes = array(); + protected array $footnotes_ordered = array(); + protected array $footnotes_ref_count = array(); + protected array $footnotes_numbers = array(); + protected array $abbr_desciptions = array(); + protected string $abbr_word_re = ''; + + /** + * Give the current footnote number. + */ + protected int $footnote_counter = 1; + + /** + * Ref attribute for links + */ + protected array $ref_attr = array(); + + /** + * Setting up Extra-specific variables. + */ + protected function setup() { + parent::setup(); + + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + $this->footnote_counter = 1; + $this->footnotes_assembled = null; + + foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + } + } + + /** + * Clearing Extra-specific variables. + */ + protected function teardown() { + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + + if ( ! $this->omit_footnotes ) + $this->footnotes_assembled = null; + + parent::teardown(); + } + + + /** + * Extra attribute parser + */ + /** + * Expression to use to catch attributes (includes the braces) + */ + protected string $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}'; + + /** + * Expression to use when parsing in a context when no capture is desired + */ + protected string $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}'; + + /** + * Parse attributes caught by the $this->id_class_attr_catch_re expression + * and return the HTML-formatted list of attributes. + * + * Currently supported attributes are .class and #id. + * + * In addition, this method also supports supplying a default Id value, + * which will be used to populate the id attribute in case it was not + * overridden. + * @param string $tag_name + * @param string $attr + * @param mixed $defaultIdValue + * @param array $classes + * @return string + */ + protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) { + if (empty($attr) && !$defaultIdValue && empty($classes)) { + return ""; + } + + // Split on components + preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches); + $elements = $matches[0]; + + // Handle classes and IDs (only first ID taken into account) + $attributes = array(); + $id = false; + foreach ($elements as $element) { + if ($element[0] === '.') { + $classes[] = substr($element, 1); + } else if ($element[0] === '#') { + if ($id === false) $id = substr($element, 1); + } else if (strpos($element, '=') > 0) { + $parts = explode('=', $element, 2); + $attributes[] = $parts[0] . '="' . $parts[1] . '"'; + } + } + + if ($id === false || $id === '') { + $id = $defaultIdValue; + } + + // Compose attributes as string + $attr_str = ""; + if (!empty($id)) { + $attr_str .= ' id="'.$this->encodeAttribute($id) .'"'; + } + if (!empty($classes)) { + $attr_str .= ' class="'. implode(" ", $classes) . '"'; + } + if (!$this->no_markup && !empty($attributes)) { + $attr_str .= ' '.implode(" ", $attributes); + } + return $attr_str; + } + + /** + * Strips link definitions from text, stores the URLs and titles in + * hash references. + * @param string $text + * @return string + */ + protected function stripLinkDefinitions($text) { + $less_than_tab = $this->tab_width - 1; + + // Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr + (?:\n+|\Z) + }xm', + array($this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + + /** + * Strip link definition callback + * @param array $matches + * @return string + */ + protected function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]); + return ''; // String that will replace the block + } + + + /** + * HTML block parser + */ + /** + * Tags that are always treated as block tags + */ + protected string $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure|details|summary'; + + /** + * Tags treated as block tags only if the opening tag is alone on its line + */ + protected string $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; + + /** + * Tags where markdown="1" default to span mode: + */ + protected string $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + + /** + * Tags which must not have their contents modified, no matter where + * they appear + */ + protected string $clean_tags_re = 'script|style|math|svg'; + + /** + * Tags that do not need to be closed. + */ + protected string $auto_close_tags_re = 'hr|img|param|source|track'; + + /** + * Hashify HTML Blocks and "clean tags". + * + * We only want to do this for block-level HTML tags, such as headers, + * lists, and tables. That's because we still want to wrap

                    s around + * "paragraphs" that are wrapped in non-block-level tags, such as anchors, + * phrase emphasis, and spans. The list of tags we're looking for is + * hard-coded. + * + * This works by calling _HashHTMLBlocks_InMarkdown, which then calls + * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" + * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back + * _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. + * These two functions are calling each other. It's recursive! + * @param string $text + * @return string + */ + protected function hashHTMLBlocks($text) { + if ($this->no_markup) { + return $text; + } + + // Call the HTML-in-Markdown hasher. + list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); + + return $text; + } + + /** + * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. + * + * * $indent is the number of space to be ignored when checking for code + * blocks. This is important because if we don't take the indent into + * account, something like this (which looks right) won't work as expected: + * + *

                    + *
                    + * Hello World. <-- Is this a Markdown code block or text? + *
                    <-- Is this a Markdown code block or a real tag? + *
                    + * + * If you don't like this, just don't indent the tag on which + * you apply the markdown="1" attribute. + * + * * If $enclosing_tag_re is not empty, stops at the first unmatched closing + * tag with that name. Nested tags supported. + * + * * If $span is true, text inside must treated as span. So any double + * newline will be replaced by a single newline so that it does not create + * paragraphs. + * + * Returns an array of that form: ( processed text , remaining text ) + * + * @param string $text + * @param integer $indent + * @param string $enclosing_tag_re + * @param boolean $span + * @return array + */ + protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0, + $enclosing_tag_re = '', $span = false) + { + + if ($text === '') return array('', ''); + + // Regex to check for the presense of newlines around a block tag. + $newline_before_re = '/(?:^\n?|\n\n)*$/'; + $newline_after_re = + '{ + ^ # Start of text following the tag. + (?>[ ]*)? # Optional comment. + [ ]*\n # Must be followed by newline. + }xs'; + + // Regex to match any tag. + $block_tag_re = + '{ + ( # $2: Capture whole tag. + # Tag name. + ' . $this->block_tags_re . ' | + ' . $this->context_block_tags_re . ' | + ' . $this->clean_tags_re . ' | + (?!\s)'.$enclosing_tag_re . ' + ) + (?: + (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. + (?> + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ' . ( !$span ? ' # If not in span. + | + # Indented code block + (?: ^[ ]*\n | ^ | \n[ ]*\n ) + [ ]{' . ($indent + 4) . '}[^\n]* \n + (?> + (?: [ ]{' . ($indent + 4) . '}[^\n]* | [ ]* ) \n + )* + | + # Fenced code block marker + (?<= ^ | \n ) + [ ]{0,' . ($indent + 3) . '}(?:~{3,}|`{3,}) + [ ]* + (?: \.?[-_:a-zA-Z0-9]+ )? # standalone class name + [ ]* + (?: ' . $this->id_class_attr_nocatch_re . ' )? # extra attributes + [ ]* + (?= \n ) + ' : '' ) . ' # End (if not is span). + | + # Code span marker + # Note, this regex needs to go after backtick fenced + # code blocks but it should also be kept outside of the + # "if not in span" condition adding backticks to the parser + `+ + ) + }xs'; + + + $depth = 0; // Current depth inside the tag tree. + $parsed = ""; // Parsed text that will be returned. + + // Loop through every tag until we find the closing tag of the parent + // or loop until reaching the end of text if no parent tag specified. + do { + // Split the text using the first $tag_match pattern found. + // Text before pattern will be first in the array, text after + // pattern will be at the end, and between will be any catches made + // by the pattern. + $parts = preg_split($block_tag_re, $text, 2, + PREG_SPLIT_DELIM_CAPTURE); + + // If in Markdown span mode, add a empty-string span-level hash + // after each newline to prevent triggering any block element. + if ($span) { + $void = $this->hashPart("", ':'); + $newline = "\n$void"; + $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; + } + + $parsed .= $parts[0]; // Text before current tag. + + // If end of $text has been reached. Stop loop. + if (count($parts) < 3) { + $text = ""; + break; + } + + $tag = $parts[1]; // Tag to handle. + $text = $parts[2]; // Remaining text after current tag. + + // Check for: Fenced code block marker. + // Note: need to recheck the whole tag to disambiguate backtick + // fences from code spans + if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) { + // Fenced code block marker: find matching end marker. + $fence_indent = strlen($capture[1]); // use captured indent in re + $fence_re = $capture[2]; // use captured fence in re + if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text, + $matches)) + { + // End marker found: pass text unchanged until marker. + $parsed .= $tag . $matches[0]; + $text = substr($text, strlen($matches[0])); + } + else { + // No end marker: just skip it. + $parsed .= $tag; + } + } + // Check for: Indented code block. + else if ($tag[0] === "\n" || $tag[0] === " ") { + // Indented code block: pass it unchanged, will be handled + // later. + $parsed .= $tag; + } + // Check for: Code span marker + // Note: need to check this after backtick fenced code blocks + else if ($tag[0] === "`") { + // Find corresponding end marker. + $tag_re = preg_quote($tag); + if (preg_match('{^(?>.+?|\n(?!\n))*?(?block_tags_re . ')\b}', $tag) || + ( preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) && + preg_match($newline_before_re, $parsed) && + preg_match($newline_after_re, $text) ) + ) + { + // Need to parse tag and following text using the HTML parser. + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); + + // Make sure it stays outside of any paragraph by adding newlines. + $parsed .= "\n\n$block_text\n\n"; + } + // Check for: Clean tag (like script, math) + // HTML Comments, processing instructions. + else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) || + $tag[1] === '!' || $tag[1] === '?') + { + // Need to parse tag and following text using the HTML parser. + // (don't check for markdown attribute) + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); + + $parsed .= $block_text; + } + // Check for: Tag with same name as enclosing tag. + else if ($enclosing_tag_re !== '' && + // Same name as enclosing tag. + preg_match('{^= 0); + + return array($parsed, $text); + } + + /** + * Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. + * + * * Calls $hash_method to convert any blocks. + * * Stops when the first opening tag closes. + * * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. + * (it is not inside clean tags) + * + * Returns an array of that form: ( processed text , remaining text ) + * @param string $text + * @param string $hash_method + * @param bool $md_attr Handle `markdown="1"` attribute + * @return array + */ + protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { + if ($text === '') return array('', ''); + + // Regex to match `markdown` attribute inside of a tag. + $markdown_attr_re = ' + { + \s* # Eat whitespace before the `markdown` attribute + markdown + \s*=\s* + (?> + (["\']) # $1: quote delimiter + (.*?) # $2: attribute value + \1 # matching delimiter + | + ([^\s>]*) # $3: unquoted attribute value + ) + () # $4: make $3 always defined (avoid warnings) + }xs'; + + // Regex to match any tag. + $tag_re = '{ + ( # $2: Capture whole tag. + + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ) + }xs'; + + $original_text = $text; // Save original text in case of faliure. + + $depth = 0; // Current depth inside the tag tree. + $block_text = ""; // Temporary text holder for current text. + $parsed = ""; // Parsed text that will be returned. + $base_tag_name_re = ''; + + // Get the name of the starting tag. + // (This pattern makes $base_tag_name_re safe without quoting.) + if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) + $base_tag_name_re = $matches[1]; + + // Loop through every tag until we find the corresponding closing tag. + do { + // Split the text using the first $tag_match pattern found. + // Text before pattern will be first in the array, text after + // pattern will be at the end, and between will be any catches made + // by the pattern. + $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (count($parts) < 3) { + // End of $text reached with unbalenced tag(s). + // In that case, we return original text unchanged and pass the + // first character as filtered to prevent an infinite loop in the + // parent function. + return array($original_text[0], substr($original_text, 1)); + } + + $block_text .= $parts[0]; // Text before current tag. + $tag = $parts[1]; // Tag to handle. + $text = $parts[2]; // Remaining text after current tag. + + // Check for: Auto-close tag (like
                    ) + // Comments and Processing Instructions. + if (preg_match('{^auto_close_tags_re . ')\b}', $tag) || + $tag[1] === '!' || $tag[1] === '?') + { + // Just add the tag to the block as if it was text. + $block_text .= $tag; + } + else { + // Increase/decrease nested tag count. Only do so if + // the tag's name match base tag's. + if (preg_match('{^contain_span_tags_re . ')\b}', $tag)); + + // Calculate indent before tag. + if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { + $strlen = $this->utf8_strlen; + $indent = $strlen($matches[1], 'UTF-8'); + } else { + $indent = 0; + } + + // End preceding block with this tag. + $block_text .= $tag; + $parsed .= $this->$hash_method($block_text); + + // Get enclosing tag name for the ParseMarkdown function. + // (This pattern makes $tag_name_re safe without quoting.) + preg_match('/^<([\w:$]*)\b/', $tag, $matches); + $tag_name_re = $matches[1]; + + // Parse the content using the HTML-in-Markdown parser. + list ($block_text, $text) + = $this->_hashHTMLBlocks_inMarkdown($text, $indent, + $tag_name_re, $span_mode); + + // Outdent markdown text. + if ($indent > 0) { + $block_text = preg_replace("/^[ ]{1,$indent}/m", "", + $block_text); + } + + // Append tag content to parsed text. + if (!$span_mode) { + $parsed .= "\n\n$block_text\n\n"; + } else { + $parsed .= (string) $block_text; + } + + // Start over with a new block. + $block_text = ""; + } + else $block_text .= $tag; + } + + } while ($depth > 0); + + // Hash last block text that wasn't processed inside the loop. + $parsed .= $this->$hash_method($block_text); + + return array($parsed, $text); + } + + /** + * Called whenever a tag must be hashed when a function inserts a "clean" tag + * in $text, it passes through this function and is automaticaly escaped, + * blocking invalid nested overlap. + * @param string $text + * @return string + */ + protected function hashClean($text) { + return $this->hashPart($text, 'C'); + } + + /** + * Turn Markdown link shortcuts into XHTML tags. + * @param string $text + * @return string + */ + protected function doAnchors($text) { + if ($this->in_anchor) { + return $text; + } + $this->in_anchor = true; + + // First, handle reference-style links: [link text] [id] + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + (' . $this->nested_brackets_re . ') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array($this, '_doAnchors_reference_callback'), $text); + + // Next, inline-style links: [link text](url "optional title") + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + (' . $this->nested_brackets_re . ') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + (' . $this->nested_url_parenthesis_re . ') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes + ) + }xs', + array($this, '_doAnchors_inline_callback'), $text); + + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link text][1] + // or [link text](/foo) + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array($this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + + /** + * Callback for reference anchors + * @param array $matches + * @return string + */ + protected function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + // for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + // lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeURLAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) + $result .= $this->ref_attr[$link_id]; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + + /** + * Callback for inline anchors + * @param array $matches + * @return string + */ + protected function _doAnchors_inline_callback($matches) { + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] === '' ? $matches[4] : $matches[3]; + $title_quote =& $matches[6]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); + + // if the URL was of the form it got caught by the HTML + // tag parser and hashed. Need to reverse the process before using the URL. + $unhashed = $this->unhash($url); + if ($unhashed !== $url) + $url = preg_replace('/^<(.*)>$/', '\1', $unhashed); + + $url = $this->encodeURLAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $attr; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + /** + * Turn Markdown image shortcuts into tags. + * @param string $text + * @return string + */ + protected function doImages($text) { + // First, handle reference-style labeled images: ![alt text][id] + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + (' . $this->nested_brackets_re . ') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array($this, '_doImages_reference_callback'), $text); + + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + (' . $this->nested_brackets_re . ') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + (' . $this->nested_url_parenthesis_re . ') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + (?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes + ) + }xs', + array($this, '_doImages_inline_callback'), $text); + + return $text; + } + + /** + * Callback for referenced images + * @param array $matches + * @return string + */ + protected function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id === "") { + $link_id = strtolower($alt_text); // for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeURLAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) { + $result .= $this->ref_attr[$link_id]; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + // If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + + /** + * Callback for inline images + * @param array $matches + * @return string + */ + protected function _doImages_inline_callback($matches) { + $alt_text = $matches[2]; + $url = $matches[3] === '' ? $matches[4] : $matches[3]; + $title_quote =& $matches[6]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeURLAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; // $title already quoted + } + $result .= $attr; + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + /** + * Process markdown headers. Redefined to add ID and class attribute support. + * @param string $text + * @return string + */ + protected function doHeaders($text) { + // Setext-style headers: + // Header 1 {#header1} + // ======== + // + // Header 2 {#header2 .class1 .class2} + // -------- + // + $text = preg_replace_callback( + '{ + (^.+?) # $1: Header text + (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes + [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer + }mx', + array($this, '_doHeaders_callback_setext'), $text); + + // atx-style headers: + // # Header 1 {#header1} + // ## Header 2 {#header2} + // ## Header 2 with closing hashes ## {#header3.class1.class2} + // ... + // ###### Header 6 {.class2} + // + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]'.($this->hashtag_protection ? '+' : '*').' + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + (?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes + [ ]* + \n+ + }xm', + array($this, '_doHeaders_callback_atx'), $text); + + return $text; + } + + /** + * Callback for setext headers + * @param array $matches + * @return string + */ + protected function _doHeaders_callback_setext($matches) { + if ($matches[3] === '-' && preg_match('{^- }', $matches[1])) { + return $matches[0]; + } + + $level = $matches[3][0] === '=' ? 1 : 2; + + $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null; + + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId); + $block = "" . $this->runSpanGamut($matches[1]) . ""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + /** + * Callback for atx headers + * @param array $matches + * @return string + */ + protected function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + + $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null; + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId); + $block = "" . $this->runSpanGamut($matches[2]) . ""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + /** + * Form HTML tables. + * @param string $text + * @return string + */ + protected function doTables($text) { + $less_than_tab = $this->tab_width - 1; + // Find tables with leading pipe. + // + // | Header 1 | Header 2 + // | -------- | -------- + // | Cell 1 | Cell 2 + // | Cell 3 | Cell 4 + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,' . $less_than_tab . '} # Allowed whitespace. + [|] # Optional leading pipe (present) + (.+) \n # $1: Header row (at least one pipe) + + [ ]{0,' . $less_than_tab . '} # Allowed whitespace. + [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + [ ]* # Allowed whitespace. + [|] .* \n # Row content. + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array($this, '_doTable_leadingPipe_callback'), $text); + + // Find tables without leading pipe. + // + // Header 1 | Header 2 + // -------- | -------- + // Cell 1 | Cell 2 + // Cell 3 | Cell 4 + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,' . $less_than_tab . '} # Allowed whitespace. + (\S.*[|].*) \n # $1: Header row (at least one pipe) + + [ ]{0,' . $less_than_tab . '} # Allowed whitespace. + ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + .* [|] .* \n # Row content + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array($this, '_DoTable_callback'), $text); + + return $text; + } + + /** + * Callback for removing the leading pipe for each row + * @param array $matches + * @return string + */ + protected function _doTable_leadingPipe_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + $content = preg_replace('/^ *[|]/m', '', $content); + + return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); + } + + /** + * Make the align attribute in a table + * @param string $alignname + * @return string + */ + protected function _doTable_makeAlignAttr($alignname) { + if (empty($this->table_align_class_tmpl)) { + return " align=\"$alignname\""; + } + + $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl); + return " class=\"$classname\""; + } + + /** + * Calback for processing tables + * @param array $matches + * @return string + */ + protected function _doTable_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + $attr = []; + + // Remove any tailing pipes for each line. + $head = preg_replace('/[|] *$/m', '', $head); + $underline = preg_replace('/[|] *$/m', '', $underline); + $content = preg_replace('/[|] *$/m', '', $content); + + // Reading alignement from header underline. + $separators = preg_split('/ *[|] */', $underline); + foreach ($separators as $n => $s) { + if (preg_match('/^ *-+: *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('right'); + else if (preg_match('/^ *:-+: *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('center'); + else if (preg_match('/^ *:-+ *$/', $s)) + $attr[$n] = $this->_doTable_makeAlignAttr('left'); + else + $attr[$n] = ''; + } + + // Parsing span elements, including code spans, character escapes, + // and inline HTML tags, so that pipes inside those gets ignored. + $head = $this->parseSpan($head); + $headers = preg_split('/ *[|] */', $head); + $col_count = count($headers); + $attr = array_pad($attr, $col_count, ''); + + // Write column headers. + $text = "\n"; + $text .= "\n"; + $text .= "\n"; + foreach ($headers as $n => $header) { + $text .= " " . $this->runSpanGamut(trim($header)) . "\n"; + } + $text .= "\n"; + $text .= "\n"; + + // Split content by row. + $rows = explode("\n", trim($content, "\n")); + + $text .= "\n"; + foreach ($rows as $row) { + // Parsing span elements, including code spans, character escapes, + // and inline HTML tags, so that pipes inside those gets ignored. + $row = $this->parseSpan($row); + + // Split row by cell. + $row_cells = preg_split('/ *[|] */', $row, $col_count); + $row_cells = array_pad($row_cells, $col_count, ''); + + $text .= "\n"; + foreach ($row_cells as $n => $cell) { + $text .= " " . $this->runSpanGamut(trim($cell)) . "\n"; + } + $text .= "\n"; + } + $text .= "\n"; + $text .= "
                    "; + + return $this->hashBlock($text) . "\n"; + } + + /** + * Form HTML definition lists. + * @param string $text + * @return string + */ + protected function doDefLists($text) { + $less_than_tab = $this->tab_width - 1; + + // Re-usable pattern to match any entire dl list: + $whole_list_re = '(?> + ( # $1 = whole list + ( # $2 + [ ]{0,' . $less_than_tab . '} + ((?>.*\S.*\n)+) # $3 = defined term + \n? + [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition + ) + (?s:.+?) + ( # $4 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another term + [ ]{0,' . $less_than_tab . '} + (?: \S.*\n )+? # defined term + \n? + [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition + ) + (?! # Negative lookahead for another definition + [ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition + ) + ) + ) + )'; // mx + + $text = preg_replace_callback('{ + (?>\A\n?|(?<=\n\n)) + ' . $whole_list_re . ' + }mx', + array($this, '_doDefLists_callback'), $text); + + return $text; + } + + /** + * Callback for processing definition lists + * @param array $matches + * @return string + */ + protected function _doDefLists_callback($matches) { + // Re-usable patterns to match list item bullets and number markers: + $list = $matches[1]; + + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + $result = trim($this->processDefListItems($list)); + $result = "
                    \n" . $result . "\n
                    "; + return $this->hashBlock($result) . "\n\n"; + } + + /** + * Process the contents of a single definition list, splitting it + * into individual term and definition list items. + * @param string $list_str + * @return string + */ + protected function processDefListItems($list_str) { + + $less_than_tab = $this->tab_width - 1; + + // Trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + // Process definition terms. + $list_str = preg_replace_callback('{ + (?>\A\n?|\n\n+) # leading line + ( # definition terms = $1 + [ ]{0,' . $less_than_tab . '} # leading whitespace + (?!\:[ ]|[ ]) # negative lookahead for a definition + # mark (colon) or more whitespace. + (?> \S.* \n)+? # actual term (not whitespace). + ) + (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed + # with a definition mark. + }xm', + array($this, '_processDefListItems_callback_dt'), $list_str); + + // Process actual definitions. + $list_str = preg_replace_callback('{ + \n(\n+)? # leading line = $1 + ( # marker space = $2 + [ ]{0,' . $less_than_tab . '} # whitespace before colon + \:[ ]+ # definition mark (colon) + ) + ((?s:.+?)) # definition text = $3 + (?= \n+ # stop at next definition mark, + (?: # next term or end of text + [ ]{0,' . $less_than_tab . '} \:[ ] | +
                    | \z + ) + ) + }xm', + array($this, '_processDefListItems_callback_dd'), $list_str); + + return $list_str; + } + + /** + * Callback for
                    elements in definition lists + * @param array $matches + * @return string + */ + protected function _processDefListItems_callback_dt($matches) { + $terms = explode("\n", trim($matches[1])); + $text = ''; + foreach ($terms as $term) { + $term = $this->runSpanGamut(trim($term)); + $text .= "\n
                    " . $term . "
                    "; + } + return $text . "\n"; + } + + /** + * Callback for
                    elements in definition lists + * @param array $matches + * @return string + */ + protected function _processDefListItems_callback_dd($matches) { + $leading_line = $matches[1]; + $marker_space = $matches[2]; + $def = $matches[3]; + + if ($leading_line || preg_match('/\n{2,}/', $def)) { + // Replace marker with the appropriate whitespace indentation + $def = str_repeat(' ', strlen($marker_space)) . $def; + $def = $this->runBlockGamut($this->outdent($def . "\n\n")); + $def = "\n". $def ."\n"; + } + else { + $def = rtrim($def); + $def = $this->runSpanGamut($this->outdent($def)); + } + + return "\n
                    " . $def . "
                    \n"; + } + + /** + * Adding the fenced code block syntax to regular Markdown: + * + * ~~~ + * Code block + * ~~~ + * + * @param string $text + * @return string + */ + protected function doFencedCodeBlocks($text) { + + $text = preg_replace_callback('{ + (?:\n|\A) + # 1: Opening marker + ( + (?:~{3,}|`{3,}) # 3 or more tildes/backticks. + ) + [ ]* + (?: + \.?([-_:a-zA-Z0-9]+) # 2: standalone class name + )? + [ ]* + (?: + ' . $this->id_class_attr_catch_re . ' # 3: Extra attributes + )? + [ ]* \n # Whitespace and newline following marker. + + # 4: Content + ( + (?> + (?!\1 [ ]* \n) # Not a closing marker. + .*\n+ + )+ + ) + + # Closing marker. + \1 [ ]* (?= \n ) + }xm', + array($this, '_doFencedCodeBlocks_callback'), $text); + + return $text; + } + + /** + * Callback to process fenced code blocks + * @param array $matches + * @return string + */ + protected function _doFencedCodeBlocks_callback($matches) { + $classname =& $matches[2]; + $attrs =& $matches[3]; + $codeblock = $matches[4]; + + if ($this->code_block_content_func) { + $codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname); + } else { + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + } + + $codeblock = preg_replace_callback('/^\n+/', + array($this, '_doFencedCodeBlocks_newlines'), $codeblock); + + $classes = array(); + if ($classname !== "") { + if ($classname[0] === '.') { + $classname = substr($classname, 1); + } + $classes[] = $this->code_class_prefix . $classname; + } + $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes); + $pre_attr_str = $this->code_attr_on_pre ? $attr_str : ''; + $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str; + $codeblock = "$codeblock
                    "; + + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + + /** + * Replace new lines in fenced code blocks + * @param array $matches + * @return string + */ + protected function _doFencedCodeBlocks_newlines($matches) { + return str_repeat("empty_element_suffix", + strlen($matches[0])); + } + + /** + * Redefining emphasis markers so that emphasis by underscore does not + * work in the middle of a word. + * @var array + */ + protected array $em_relist = array( + '' => '(?:(? '(? '(? '(?:(? '(? '(? '(?:(? '(? '(? tags + * @return string HTML output + */ + protected function formParagraphs($text, $wrap_in_p = true) { + // Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + // Wrap

                    tags and unhashify HTML blocks + foreach ($grafs as $key => $value) { + $value = trim($this->runSpanGamut($value)); + + // Check if this should be enclosed in a paragraph. + // Clean tag hashes & block tag hashes are left alone. + $is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); + + if ($is_p) { + $value = "

                    $value

                    "; + } + $grafs[$key] = $value; + } + + // Join grafs in one text, then unhash HTML tags. + $text = implode("\n\n", $grafs); + + // Finish by removing any tag hashes still present in $text. + $text = $this->unhash($text); + + return $text; + } + + + /** + * Footnotes - Strips link definitions from text, stores the URLs and + * titles in hash references. + * @param string $text + * @return string + */ + protected function stripFootnotes($text) { + $less_than_tab = $this->tab_width - 1; + + // Link defs are in the form: [^id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,' . $less_than_tab . '}\[\^(.+?)\][ ]?: # note_id = $1 + [ ]* + \n? # maybe *one* newline + ( # text = $2 (no blank lines allowed) + (?: + .+ # actual text + | + \n # newlines but + (?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker. + (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed + # by non-indented content + )* + ) + }xm', + array($this, '_stripFootnotes_callback'), + $text); + return $text; + } + + /** + * Callback for stripping footnotes + * @param array $matches + * @return string + */ + protected function _stripFootnotes_callback($matches) { + $note_id = $this->fn_id_prefix . $matches[1]; + $this->footnotes[$note_id] = $this->outdent($matches[2]); + return ''; // String that will replace the block + } + + /** + * Replace footnote references in $text [^id] with a special text-token + * which will be replaced by the actual footnote marker in appendFootnotes. + * @param string $text + * @return string + */ + protected function doFootnotes($text) { + if (!$this->in_anchor) { + $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); + } + return $text; + } + + /** + * Append footnote list to text + * @param string $text + * @return string + */ + protected function appendFootnotes($text) { + $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array($this, '_appendFootnotes_callback'), $text); + + if ( ! empty( $this->footnotes_ordered ) ) { + $this->_doFootnotes(); + if ( ! $this->omit_footnotes ) { + $text .= "\n\n"; + $text .= "
                    \n"; + $text .= "empty_element_suffix . "\n"; + $text .= $this->footnotes_assembled; + $text .= "
                    "; + } + } + return $text; + } + + + /** + * Generates the HTML for footnotes. Called by appendFootnotes, even if + * footnotes are not being appended. + * @return void + */ + protected function _doFootnotes() { + $attr = array(); + if ($this->fn_backlink_class !== "") { + $class = $this->fn_backlink_class; + $class = $this->encodeAttribute($class); + $attr['class'] = " class=\"$class\""; + } + $attr['role'] = " role=\"doc-backlink\""; + $num = 0; + + $text = "
                      \n\n"; + while (!empty($this->footnotes_ordered)) { + $footnote = reset($this->footnotes_ordered); + $note_id = key($this->footnotes_ordered); + unset($this->footnotes_ordered[$note_id]); + $ref_count = $this->footnotes_ref_count[$note_id]; + unset($this->footnotes_ref_count[$note_id]); + unset($this->footnotes[$note_id]); + + $footnote .= "\n"; // Need to append newline before parsing. + $footnote = $this->runBlockGamut("$footnote\n"); + $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array($this, '_appendFootnotes_callback'), $footnote); + + $num++; + $note_id = $this->encodeAttribute($note_id); + + // Prepare backlink, multiple backlinks if multiple references + // Do not create empty backlinks if the html is blank + $backlink = ""; + if (!empty($this->fn_backlink_html)) { + for ($ref_num = 1; $ref_num <= $ref_count; ++$ref_num) { + if (!empty($this->fn_backlink_title)) { + $attr['title'] = ' title="' . $this->encodeAttribute($this->fn_backlink_title) . '"'; + } + if (!empty($this->fn_backlink_label)) { + $attr['label'] = ' aria-label="' . $this->encodeAttribute($this->fn_backlink_label) . '"'; + } + $parsed_attr = $this->parseFootnotePlaceholders( + implode('', $attr), + $num, + $ref_num + ); + $backlink_text = $this->parseFootnotePlaceholders( + $this->fn_backlink_html, + $num, + $ref_num + ); + $ref_count_mark = $ref_num > 1 ? $ref_num : ''; + $backlink .= " $backlink_text"; + } + $backlink = trim($backlink); + } + + // Add backlink to last paragraph; create new paragraph if needed. + if (!empty($backlink)) { + if (preg_match('{

                      $}', $footnote)) { + $footnote = substr($footnote, 0, -4) . " $backlink

                      "; + } else { + $footnote .= "\n\n

                      $backlink

                      "; + } + } + + $text .= "
                    1. \n"; + $text .= $footnote . "\n"; + $text .= "
                    2. \n\n"; + } + $text .= "
                    \n"; + + $this->footnotes_assembled = $text; + } + + /** + * Callback for appending footnotes + * @param array $matches + * @return string + */ + protected function _appendFootnotes_callback($matches) { + $node_id = $this->fn_id_prefix . $matches[1]; + + // Create footnote marker only if it has a corresponding footnote *and* + // the footnote hasn't been used by another marker. + if (isset($this->footnotes[$node_id])) { + $num =& $this->footnotes_numbers[$node_id]; + if (!isset($num)) { + // Transfer footnote content to the ordered list and give it its + // number + $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; + $this->footnotes_ref_count[$node_id] = 1; + $num = $this->footnote_counter++; + $ref_count_mark = ''; + } else { + $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1; + } + + $attr = ""; + if ($this->fn_link_class !== "") { + $class = $this->fn_link_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_link_title !== "") { + $title = $this->fn_link_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + $attr .= " role=\"doc-noteref\""; + + $attr = str_replace("%%", $num, $attr); + $node_id = $this->encodeAttribute($node_id); + + return + "". + "$num". + ""; + } + + return "[^" . $matches[1] . "]"; + } + + /** + * Build footnote label by evaluating any placeholders. + * - ^^ footnote number + * - %% footnote reference number (Nth reference to footnote number) + * @param string $label + * @param int $footnote_number + * @param int $reference_number + * @return string + */ + protected function parseFootnotePlaceholders($label, $footnote_number, $reference_number) { + return str_replace( + array('^^', '%%'), + array($footnote_number, $reference_number), + $label + ); + } + + + /** + * Abbreviations - strips abbreviations from text, stores titles in hash + * references. + * @param string $text + * @return string + */ + protected function stripAbbreviations($text) { + $less_than_tab = $this->tab_width - 1; + + // Link defs are in the form: [id]*: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?: # abbr_id = $1 + (.*) # text = $2 (no blank lines allowed) + }xm', + array($this, '_stripAbbreviations_callback'), + $text); + return $text; + } + + /** + * Callback for stripping abbreviations + * @param array $matches + * @return string + */ + protected function _stripAbbreviations_callback($matches) { + $abbr_word = $matches[1]; + $abbr_desc = $matches[2]; + if ($this->abbr_word_re) { + $this->abbr_word_re .= '|'; + } + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + return ''; // String that will replace the block + } + + /** + * Find defined abbreviations in text and wrap them in elements. + * @param string $text + * @return string + */ + protected function doAbbreviations($text) { + if ($this->abbr_word_re) { + // cannot use the /x modifier because abbr_word_re may + // contain significant spaces: + $text = preg_replace_callback('{' . + '(?abbr_word_re . ')' . + '(?![\w\x1A])' . + '}', + array($this, '_doAbbreviations_callback'), $text); + } + return $text; + } + + /** + * Callback for processing abbreviations + * @param array $matches + * @return string + */ + protected function _doAbbreviations_callback($matches) { + $abbr = $matches[0]; + if (isset($this->abbr_desciptions[$abbr])) { + $desc = $this->abbr_desciptions[$abbr]; + if (empty($desc)) { + return $this->hashPart("$abbr"); + } + $desc = $this->encodeAttribute($desc); + return $this->hashPart("$abbr"); + } + return $matches[0]; + } +} diff --git a/lib/michelf/Michelf/MarkdownInterface.inc.php b/lib/michelf/Michelf/MarkdownInterface.inc.php new file mode 100644 index 0000000000..c4e9ac7f64 --- /dev/null +++ b/lib/michelf/Michelf/MarkdownInterface.inc.php @@ -0,0 +1,9 @@ + + * @copyright 2004-2021 Michel Fortin + * @copyright (Original Markdown) 2004-2006 John Gruber + */ + +namespace Michelf; + +/** + * Markdown Parser Interface + */ +interface MarkdownInterface { + /** + * Initialize the parser and return the result of its transform method. + * This will work fine for derived classes too. + * + * @api + * + * @param string $text + * @return string + */ + public static function defaultTransform($text); + + /** + * Main function. Performs some preprocessing on the input text + * and pass it through the document gamut. + * + * @api + * + * @param string $text + * @return string + */ + public function transform($text); +} diff --git a/lib/michelf/michelf.class.php b/lib/michelf/michelf.class.php new file mode 100644 index 0000000000..6f55684fb5 --- /dev/null +++ b/lib/michelf/michelf.class.php @@ -0,0 +1,27 @@ +fn_id_prefix = "post22-"; + $html = $parser->transform($mdCodes); + + return "
                    $html
                    "; + } +} diff --git a/lib/parsedownextraplugin/LICENSE.txt b/lib/parsedownextraplugin/LICENSE.txt deleted file mode 100644 index 8e7c764d16..0000000000 --- a/lib/parsedownextraplugin/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2018 Emanuil Rusev, erusev.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/parsedownextraplugin/parsedown.php b/lib/parsedownextraplugin/parsedown.php deleted file mode 100644 index 69147dc2ac..0000000000 --- a/lib/parsedownextraplugin/parsedown.php +++ /dev/null @@ -1,1992 +0,0 @@ -textElements($text); - - # convert to markup - $markup = $this->elements($Elements); - - # trim line breaks - $markup = trim($markup, "\n"); - - return $markup; - } - - protected function textElements($text) - { - # make sure no definitions are set - $this->DefinitionData = array(); - - # standardize line breaks - $text = str_replace(array("\r\n", "\r"), "\n", $text); - - # remove surrounding line breaks - $text = trim($text, "\n"); - - # split text into lines - $lines = explode("\n", $text); - - # iterate through lines to identify blocks - return $this->linesElements($lines); - } - - # - # Setters - # - - function setBreaksEnabled($breaksEnabled) - { - $this->breaksEnabled = $breaksEnabled; - - return $this; - } - - protected $breaksEnabled; - - function setMarkupEscaped($markupEscaped) - { - $this->markupEscaped = $markupEscaped; - - return $this; - } - - protected $markupEscaped; - - function setUrlsLinked($urlsLinked) - { - $this->urlsLinked = $urlsLinked; - - return $this; - } - - protected $urlsLinked = true; - - function setSafeMode($safeMode) - { - $this->safeMode = (bool) $safeMode; - - return $this; - } - - protected $safeMode; - - function setStrictMode($strictMode) - { - $this->strictMode = (bool) $strictMode; - - return $this; - } - - protected $strictMode; - - protected $safeLinksWhitelist = array( - 'http://', - 'https://', - 'ftp://', - 'ftps://', - 'mailto:', - 'tel:', - 'data:image/png;base64,', - 'data:image/gif;base64,', - 'data:image/jpeg;base64,', - 'irc:', - 'ircs:', - 'git:', - 'ssh:', - 'news:', - 'steam:', - ); - - # - # Lines - # - - protected $BlockTypes = array( - '#' => array('Header'), - '*' => array('Rule', 'List'), - '+' => array('List'), - '-' => array('SetextHeader', 'Table', 'Rule', 'List'), - '0' => array('List'), - '1' => array('List'), - '2' => array('List'), - '3' => array('List'), - '4' => array('List'), - '5' => array('List'), - '6' => array('List'), - '7' => array('List'), - '8' => array('List'), - '9' => array('List'), - ':' => array('Table'), - '<' => array('Comment', 'Markup'), - '=' => array('SetextHeader'), - '>' => array('Quote'), - '[' => array('Reference'), - '_' => array('Rule'), - '`' => array('FencedCode'), - '|' => array('Table'), - '~' => array('FencedCode'), - ); - - # ~ - - protected $unmarkedBlockTypes = array( - 'Code', - ); - - # - # Blocks - # - - protected function lines(array $lines) - { - return $this->elements($this->linesElements($lines)); - } - - protected function linesElements(array $lines) - { - $Elements = array(); - $CurrentBlock = null; - - foreach ($lines as $line) - { - if (chop($line) === '') - { - if (isset($CurrentBlock)) - { - $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted']) - ? $CurrentBlock['interrupted'] + 1 : 1 - ); - } - - continue; - } - - while (($beforeTab = strstr($line, "\t", true)) !== false) - { - $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4; - - $line = $beforeTab - . str_repeat(' ', $shortage) - . substr($line, strlen($beforeTab) + 1) - ; - } - - $indent = strspn($line, ' '); - - $text = $indent > 0 ? substr($line, $indent) : $line; - - # ~ - - $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); - - # ~ - - if (isset($CurrentBlock['continuable'])) - { - $methodName = 'block' . $CurrentBlock['type'] . 'Continue'; - $Block = $this->$methodName($Line, $CurrentBlock); - - if (isset($Block)) - { - $CurrentBlock = $Block; - - continue; - } - else - { - if ($this->isBlockCompletable($CurrentBlock['type'])) - { - $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; - $CurrentBlock = $this->$methodName($CurrentBlock); - } - } - } - - # ~ - - $marker = $text[0]; - - # ~ - - $blockTypes = $this->unmarkedBlockTypes; - - if (isset($this->BlockTypes[$marker])) - { - foreach ($this->BlockTypes[$marker] as $blockType) - { - $blockTypes []= $blockType; - } - } - - # - # ~ - - foreach ($blockTypes as $blockType) - { - $Block = $this->{"block$blockType"}($Line, $CurrentBlock); - - if (isset($Block)) - { - $Block['type'] = $blockType; - - if ( ! isset($Block['identified'])) - { - if (isset($CurrentBlock)) - { - $Elements[] = $this->extractElement($CurrentBlock); - } - - $Block['identified'] = true; - } - - if ($this->isBlockContinuable($blockType)) - { - $Block['continuable'] = true; - } - - $CurrentBlock = $Block; - - continue 2; - } - } - - # ~ - - if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph') - { - $Block = $this->paragraphContinue($Line, $CurrentBlock); - } - - if (isset($Block)) - { - $CurrentBlock = $Block; - } - else - { - if (isset($CurrentBlock)) - { - $Elements[] = $this->extractElement($CurrentBlock); - } - - $CurrentBlock = $this->paragraph($Line); - - $CurrentBlock['identified'] = true; - } - } - - # ~ - - if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) - { - $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; - $CurrentBlock = $this->$methodName($CurrentBlock); - } - - # ~ - - if (isset($CurrentBlock)) - { - $Elements[] = $this->extractElement($CurrentBlock); - } - - # ~ - - return $Elements; - } - - protected function extractElement(array $Component) - { - if ( ! isset($Component['element'])) - { - if (isset($Component['markup'])) - { - $Component['element'] = array('rawHtml' => $Component['markup']); - } - elseif (isset($Component['hidden'])) - { - $Component['element'] = array(); - } - } - - return $Component['element']; - } - - protected function isBlockContinuable($Type) - { - return method_exists($this, 'block' . $Type . 'Continue'); - } - - protected function isBlockCompletable($Type) - { - return method_exists($this, 'block' . $Type . 'Complete'); - } - - # - # Code - - protected function blockCode($Line, $Block = null) - { - if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted'])) - { - return; - } - - if ($Line['indent'] >= 4) - { - $text = substr($Line['body'], 4); - - $Block = array( - 'element' => array( - 'name' => 'pre', - 'element' => array( - 'name' => 'code', - 'text' => $text, - ), - ), - ); - - return $Block; - } - } - - protected function blockCodeContinue($Line, $Block) - { - if ($Line['indent'] >= 4) - { - if (isset($Block['interrupted'])) - { - $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); - - unset($Block['interrupted']); - } - - $Block['element']['element']['text'] .= "\n"; - - $text = substr($Line['body'], 4); - - $Block['element']['element']['text'] .= $text; - - return $Block; - } - } - - protected function blockCodeComplete($Block) - { - return $Block; - } - - # - # Comment - - protected function blockComment($Line) - { - if ($this->markupEscaped or $this->safeMode) - { - return; - } - - if (strpos($Line['text'], '') !== false) - { - $Block['closed'] = true; - } - - return $Block; - } - } - - protected function blockCommentContinue($Line, array $Block) - { - if (isset($Block['closed'])) - { - return; - } - - $Block['element']['rawHtml'] .= "\n" . $Line['body']; - - if (strpos($Line['text'], '-->') !== false) - { - $Block['closed'] = true; - } - - return $Block; - } - - # - # Fenced Code - - protected function blockFencedCode($Line) - { - $marker = $Line['text'][0]; - - $openerLength = strspn($Line['text'], $marker); - - if ($openerLength < 3) - { - return; - } - - $infostring = trim(substr($Line['text'], $openerLength), "\t "); - - if (strpos($infostring, '`') !== false) - { - return; - } - - $Element = array( - 'name' => 'code', - 'text' => '', - ); - - if ($infostring !== '') - { - /** - * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes - * Every HTML element may have a class attribute specified. - * The attribute, if specified, must have a value that is a set - * of space-separated tokens representing the various classes - * that the element belongs to. - * [...] - * The space characters, for the purposes of this specification, - * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), - * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and - * U+000D CARRIAGE RETURN (CR). - */ - $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r")); - - $Element['attributes'] = array('class' => "language-$language"); - } - - $Block = array( - 'char' => $marker, - 'openerLength' => $openerLength, - 'element' => array( - 'name' => 'pre', - 'element' => $Element, - ), - ); - - return $Block; - } - - protected function blockFencedCodeContinue($Line, $Block) - { - if (isset($Block['complete'])) - { - return; - } - - if (isset($Block['interrupted'])) - { - $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); - - unset($Block['interrupted']); - } - - if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength'] - and chop(substr($Line['text'], $len), ' ') === '' - ) { - $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1); - - $Block['complete'] = true; - - return $Block; - } - - $Block['element']['element']['text'] .= "\n" . $Line['body']; - - return $Block; - } - - protected function blockFencedCodeComplete($Block) - { - return $Block; - } - - # - # Header - - protected function blockHeader($Line) - { - $level = strspn($Line['text'], '#'); - - if ($level > 6) - { - return; - } - - $text = trim($Line['text'], '#'); - - if ($this->strictMode and isset($text[0]) and $text[0] !== ' ') - { - return; - } - - $text = trim($text, ' '); - - $Block = array( - 'element' => array( - 'name' => 'h' . $level, - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $text, - 'destination' => 'elements', - ) - ), - ); - - return $Block; - } - - # - # List - - protected function blockList($Line, array $CurrentBlock = null) - { - list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]'); - - if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches)) - { - $contentIndent = strlen($matches[2]); - - if ($contentIndent >= 5) - { - $contentIndent -= 1; - $matches[1] = substr($matches[1], 0, -$contentIndent); - $matches[3] = str_repeat(' ', $contentIndent) . $matches[3]; - } - elseif ($contentIndent === 0) - { - $matches[1] .= ' '; - } - - $markerWithoutWhitespace = strstr($matches[1], ' ', true); - - $Block = array( - 'indent' => $Line['indent'], - 'pattern' => $pattern, - 'data' => array( - 'type' => $name, - 'marker' => $matches[1], - 'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)), - ), - 'element' => array( - 'name' => $name, - 'elements' => array(), - ), - ); - $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/'); - - if ($name === 'ol') - { - $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0'; - - if ($listStart !== '1') - { - if ( - isset($CurrentBlock) - and $CurrentBlock['type'] === 'Paragraph' - and ! isset($CurrentBlock['interrupted']) - ) { - return; - } - - $Block['element']['attributes'] = array('start' => $listStart); - } - } - - $Block['li'] = array( - 'name' => 'li', - 'handler' => array( - 'function' => 'li', - 'argument' => !empty($matches[3]) ? array($matches[3]) : array(), - 'destination' => 'elements' - ) - ); - - $Block['element']['elements'] []= & $Block['li']; - - return $Block; - } - } - - protected function blockListContinue($Line, array $Block) - { - if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument'])) - { - return null; - } - - $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker'])); - - if ($Line['indent'] < $requiredIndent - and ( - ( - $Block['data']['type'] === 'ol' - and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) - ) or ( - $Block['data']['type'] === 'ul' - and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) - ) - ) - ) { - if (isset($Block['interrupted'])) - { - $Block['li']['handler']['argument'] []= ''; - - $Block['loose'] = true; - - unset($Block['interrupted']); - } - - unset($Block['li']); - - $text = isset($matches[1]) ? $matches[1] : ''; - - $Block['indent'] = $Line['indent']; - - $Block['li'] = array( - 'name' => 'li', - 'handler' => array( - 'function' => 'li', - 'argument' => array($text), - 'destination' => 'elements' - ) - ); - - $Block['element']['elements'] []= & $Block['li']; - - return $Block; - } - elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line)) - { - return null; - } - - if ($Line['text'][0] === '[' and $this->blockReference($Line)) - { - return $Block; - } - - if ($Line['indent'] >= $requiredIndent) - { - if (isset($Block['interrupted'])) - { - $Block['li']['handler']['argument'] []= ''; - - $Block['loose'] = true; - - unset($Block['interrupted']); - } - - $text = substr($Line['body'], $requiredIndent); - - $Block['li']['handler']['argument'] []= $text; - - return $Block; - } - - if ( ! isset($Block['interrupted'])) - { - $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']); - - $Block['li']['handler']['argument'] []= $text; - - return $Block; - } - } - - protected function blockListComplete(array $Block) - { - if (isset($Block['loose'])) - { - foreach ($Block['element']['elements'] as &$li) - { - if (end($li['handler']['argument']) !== '') - { - $li['handler']['argument'] []= ''; - } - } - } - - return $Block; - } - - # - # Quote - - protected function blockQuote($Line) - { - if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) - { - $Block = array( - 'element' => array( - 'name' => 'blockquote', - 'handler' => array( - 'function' => 'linesElements', - 'argument' => (array) $matches[1], - 'destination' => 'elements', - ) - ), - ); - - return $Block; - } - } - - protected function blockQuoteContinue($Line, array $Block) - { - if (isset($Block['interrupted'])) - { - return; - } - - if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) - { - $Block['element']['handler']['argument'] []= $matches[1]; - - return $Block; - } - - if ( ! isset($Block['interrupted'])) - { - $Block['element']['handler']['argument'] []= $Line['text']; - - return $Block; - } - } - - # - # Rule - - protected function blockRule($Line) - { - $marker = $Line['text'][0]; - - if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '') - { - $Block = array( - 'element' => array( - 'name' => 'hr', - ), - ); - - return $Block; - } - } - - # - # Setext - - protected function blockSetextHeader($Line, array $Block = null) - { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) - { - return; - } - - if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '') - { - $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; - - return $Block; - } - } - - # - # Markup - - protected function blockMarkup($Line) - { - if ($this->markupEscaped or $this->safeMode) - { - return; - } - - if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches)) - { - $element = strtolower($matches[1]); - - if (in_array($element, $this->textLevelElements)) - { - return; - } - - $Block = array( - 'name' => $matches[1], - 'element' => array( - 'rawHtml' => $Line['text'], - 'autobreak' => true, - ), - ); - - return $Block; - } - } - - protected function blockMarkupContinue($Line, array $Block) - { - if (isset($Block['closed']) or isset($Block['interrupted'])) - { - return; - } - - $Block['element']['rawHtml'] .= "\n" . $Line['body']; - - return $Block; - } - - # - # Reference - - protected function blockReference($Line) - { - if (strpos($Line['text'], ']') !== false - and preg_match('/^\[(.+?)\]:[ ]*+?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches) - ) { - $id = strtolower($matches[1]); - - $Data = array( - 'url' => $matches[2], - 'title' => isset($matches[3]) ? $matches[3] : null, - ); - - $this->DefinitionData['Reference'][$id] = $Data; - - $Block = array( - 'element' => array(), - ); - - return $Block; - } - } - - # - # Table - - protected function blockTable($Line, array $Block = null) - { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) - { - return; - } - - if ( - strpos($Block['element']['handler']['argument'], '|') === false - and strpos($Line['text'], '|') === false - and strpos($Line['text'], ':') === false - or strpos($Block['element']['handler']['argument'], "\n") !== false - ) { - return; - } - - if (chop($Line['text'], ' -:|') !== '') - { - return; - } - - $alignments = array(); - - $divider = $Line['text']; - - $divider = trim($divider); - $divider = trim($divider, '|'); - - $dividerCells = explode('|', $divider); - - foreach ($dividerCells as $dividerCell) - { - $dividerCell = trim($dividerCell); - - if ($dividerCell === '') - { - return; - } - - $alignment = null; - - if ($dividerCell[0] === ':') - { - $alignment = 'left'; - } - - if (substr($dividerCell, - 1) === ':') - { - $alignment = $alignment === 'left' ? 'center' : 'right'; - } - - $alignments []= $alignment; - } - - # ~ - - $HeaderElements = array(); - - $header = $Block['element']['handler']['argument']; - - $header = trim($header); - $header = trim($header, '|'); - - $headerCells = explode('|', $header); - - if (count($headerCells) !== count($alignments)) - { - return; - } - - foreach ($headerCells as $index => $headerCell) - { - $headerCell = trim($headerCell); - - $HeaderElement = array( - 'name' => 'th', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $headerCell, - 'destination' => 'elements', - ) - ); - - if (isset($alignments[$index])) - { - $alignment = $alignments[$index]; - - $HeaderElement['attributes'] = array( - 'style' => "text-align: $alignment;", - ); - } - - $HeaderElements []= $HeaderElement; - } - - # ~ - - $Block = array( - 'alignments' => $alignments, - 'identified' => true, - 'element' => array( - 'name' => 'table', - 'elements' => array(), - ), - ); - - $Block['element']['elements'] []= array( - 'name' => 'thead', - ); - - $Block['element']['elements'] []= array( - 'name' => 'tbody', - 'elements' => array(), - ); - - $Block['element']['elements'][0]['elements'] []= array( - 'name' => 'tr', - 'elements' => $HeaderElements, - ); - - return $Block; - } - - protected function blockTableContinue($Line, array $Block) - { - if (isset($Block['interrupted'])) - { - return; - } - - if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|')) - { - $Elements = array(); - - $row = $Line['text']; - - $row = trim($row); - $row = trim($row, '|'); - - preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches); - - $cells = array_slice($matches[0], 0, count($Block['alignments'])); - - foreach ($cells as $index => $cell) - { - $cell = trim($cell); - - $Element = array( - 'name' => 'td', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $cell, - 'destination' => 'elements', - ) - ); - - if (isset($Block['alignments'][$index])) - { - $Element['attributes'] = array( - 'style' => 'text-align: ' . $Block['alignments'][$index] . ';', - ); - } - - $Elements []= $Element; - } - - $Element = array( - 'name' => 'tr', - 'elements' => $Elements, - ); - - $Block['element']['elements'][1]['elements'] []= $Element; - - return $Block; - } - } - - # - # ~ - # - - protected function paragraph($Line) - { - return array( - 'type' => 'Paragraph', - 'element' => array( - 'name' => 'p', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $Line['text'], - 'destination' => 'elements', - ), - ), - ); - } - - protected function paragraphContinue($Line, array $Block) - { - if (isset($Block['interrupted'])) - { - return; - } - - $Block['element']['handler']['argument'] .= "\n".$Line['text']; - - return $Block; - } - - # - # Inline Elements - # - - protected $InlineTypes = array( - '!' => array('Image'), - '&' => array('SpecialCharacter'), - '*' => array('Emphasis'), - ':' => array('Url'), - '<' => array('UrlTag', 'EmailTag', 'Markup'), - '[' => array('Link'), - '_' => array('Emphasis'), - '`' => array('Code'), - '~' => array('Strikethrough'), - '\\' => array('EscapeSequence'), - ); - - # ~ - - protected $inlineMarkerList = '!*_&[:<`~\\'; - - # - # ~ - # - - public function line($text, $nonNestables = array()) - { - return $this->elements($this->lineElements($text, $nonNestables)); - } - - protected function lineElements($text, $nonNestables = array()) - { - # standardize line breaks - $text = str_replace(array("\r\n", "\r"), "\n", $text); - - $Elements = array(); - - $nonNestables = (empty($nonNestables) - ? array() - : array_combine($nonNestables, $nonNestables) - ); - - # $excerpt is based on the first occurrence of a marker - - while ($excerpt = strpbrk($text, $this->inlineMarkerList)) - { - $marker = $excerpt[0]; - - $markerPosition = strlen($text) - strlen($excerpt); - - $Excerpt = array('text' => $excerpt, 'context' => $text); - - foreach ($this->InlineTypes[$marker] as $inlineType) - { - # check to see if the current inline type is nestable in the current context - - if (isset($nonNestables[$inlineType])) - { - continue; - } - - $Inline = $this->{"inline$inlineType"}($Excerpt); - - if ( ! isset($Inline)) - { - continue; - } - - # makes sure that the inline belongs to "our" marker - - if (isset($Inline['position']) and $Inline['position'] > $markerPosition) - { - continue; - } - - # sets a default inline position - - if ( ! isset($Inline['position'])) - { - $Inline['position'] = $markerPosition; - } - - # cause the new element to 'inherit' our non nestables - - - $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables']) - ? array_merge($Inline['element']['nonNestables'], $nonNestables) - : $nonNestables - ; - - # the text that comes before the inline - $unmarkedText = substr($text, 0, $Inline['position']); - - # compile the unmarked text - $InlineText = $this->inlineText($unmarkedText); - $Elements[] = $InlineText['element']; - - # compile the inline - $Elements[] = $this->extractElement($Inline); - - # remove the examined text - $text = substr($text, $Inline['position'] + $Inline['extent']); - - continue 2; - } - - # the marker does not belong to an inline - - $unmarkedText = substr($text, 0, $markerPosition + 1); - - $InlineText = $this->inlineText($unmarkedText); - $Elements[] = $InlineText['element']; - - $text = substr($text, $markerPosition + 1); - } - - $InlineText = $this->inlineText($text); - $Elements[] = $InlineText['element']; - - foreach ($Elements as &$Element) - { - if ( ! isset($Element['autobreak'])) - { - $Element['autobreak'] = false; - } - } - - return $Elements; - } - - # - # ~ - # - - protected function inlineText($text) - { - $Inline = array( - 'extent' => strlen($text), - 'element' => array(), - ); - - $Inline['element']['elements'] = self::pregReplaceElements( - $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/', - array( - array('name' => 'br'), - array('text' => "\n"), - ), - $text - ); - - return $Inline; - } - - protected function inlineCode($Excerpt) - { - $marker = $Excerpt['text'][0]; - - if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(? strlen($matches[0]), - 'element' => array( - 'name' => 'code', - 'text' => $text, - ), - ); - } - } - - protected function inlineEmailTag($Excerpt) - { - $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'; - - $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@' - . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*'; - - if (strpos($Excerpt['text'], '>') !== false - and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches) - ){ - $url = $matches[1]; - - if ( ! isset($matches[2])) - { - $url = "mailto:$url"; - } - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'a', - 'text' => $matches[1], - 'attributes' => array( - 'href' => $url, - ), - ), - ); - } - } - - protected function inlineEmphasis($Excerpt) - { - if ( ! isset($Excerpt['text'][1])) - { - return; - } - - $marker = $Excerpt['text'][0]; - - if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) - { - $emphasis = 'strong'; - } - elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) - { - $emphasis = 'em'; - } - else - { - return; - } - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => $emphasis, - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $matches[1], - 'destination' => 'elements', - ) - ), - ); - } - - protected function inlineEscapeSequence($Excerpt) - { - if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) - { - return array( - 'element' => array('rawHtml' => $Excerpt['text'][1]), - 'extent' => 2, - ); - } - } - - protected function inlineImage($Excerpt) - { - if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') - { - return; - } - - $Excerpt['text']= substr($Excerpt['text'], 1); - - $Link = $this->inlineLink($Excerpt); - - if ($Link === null) - { - return; - } - - $Inline = array( - 'extent' => $Link['extent'] + 1, - 'element' => array( - 'name' => 'img', - 'attributes' => array( - 'src' => $Link['element']['attributes']['href'], - 'alt' => $Link['element']['handler']['argument'], - ), - 'autobreak' => true, - ), - ); - - $Inline['element']['attributes'] += $Link['element']['attributes']; - - unset($Inline['element']['attributes']['href']); - - return $Inline; - } - - protected function inlineLink($Excerpt) - { - $Element = array( - 'name' => 'a', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => null, - 'destination' => 'elements', - ), - 'nonNestables' => array('Url', 'Link'), - 'attributes' => array( - 'href' => null, - 'title' => null, - ), - ); - - $extent = 0; - - $remainder = $Excerpt['text']; - - if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) - { - $Element['handler']['argument'] = $matches[1]; - - $extent += strlen($matches[0]); - - $remainder = substr($remainder, $extent); - } - else - { - return; - } - - if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) - { - $Element['attributes']['href'] = $matches[1]; - - if (isset($matches[2])) - { - $Element['attributes']['title'] = substr($matches[2], 1, - 1); - } - - $extent += strlen($matches[0]); - } - else - { - if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) - { - $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument']; - $definition = strtolower($definition); - - $extent += strlen($matches[0]); - } - else - { - $definition = strtolower($Element['handler']['argument']); - } - - if ( ! isset($this->DefinitionData['Reference'][$definition])) - { - return; - } - - $Definition = $this->DefinitionData['Reference'][$definition]; - - $Element['attributes']['href'] = $Definition['url']; - $Element['attributes']['title'] = $Definition['title']; - } - - return array( - 'extent' => $extent, - 'element' => $Element, - ); - } - - protected function inlineMarkup($Excerpt) - { - if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) - { - return; - } - - if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches)) - { - return array( - 'element' => array('rawHtml' => $matches[0]), - 'extent' => strlen($matches[0]), - ); - } - - if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) - { - return array( - 'element' => array('rawHtml' => $matches[0]), - 'extent' => strlen($matches[0]), - ); - } - - if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches)) - { - return array( - 'element' => array('rawHtml' => $matches[0]), - 'extent' => strlen($matches[0]), - ); - } - } - - protected function inlineSpecialCharacter($Excerpt) - { - if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false - and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches) - ) { - return array( - 'element' => array('rawHtml' => '&' . $matches[1] . ';'), - 'extent' => strlen($matches[0]), - ); - } - - return; - } - - protected function inlineStrikethrough($Excerpt) - { - if ( ! isset($Excerpt['text'][1])) - { - return; - } - - if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) - { - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'del', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $matches[1], - 'destination' => 'elements', - ) - ), - ); - } - } - - protected function inlineUrl($Excerpt) - { - if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') - { - return; - } - - if (strpos($Excerpt['context'], 'http') !== false - and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE) - ) { - $url = $matches[0][0]; - - $Inline = array( - 'extent' => strlen($matches[0][0]), - 'position' => $matches[0][1], - 'element' => array( - 'name' => 'a', - 'text' => $url, - 'attributes' => array( - 'href' => $url, - ), - ), - ); - - return $Inline; - } - } - - protected function inlineUrlTag($Excerpt) - { - if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches)) - { - $url = $matches[1]; - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'a', - 'text' => $url, - 'attributes' => array( - 'href' => $url, - ), - ), - ); - } - } - - # ~ - - protected function unmarkedText($text) - { - $Inline = $this->inlineText($text); - return $this->element($Inline['element']); - } - - # - # Handlers - # - - protected function handle(array $Element) - { - if (isset($Element['handler'])) - { - if (!isset($Element['nonNestables'])) - { - $Element['nonNestables'] = array(); - } - - if (is_string($Element['handler'])) - { - $function = $Element['handler']; - $argument = $Element['text']; - unset($Element['text']); - $destination = 'rawHtml'; - } - else - { - $function = $Element['handler']['function']; - $argument = $Element['handler']['argument']; - $destination = $Element['handler']['destination']; - } - - $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']); - - if ($destination === 'handler') - { - $Element = $this->handle($Element); - } - - unset($Element['handler']); - } - - return $Element; - } - - protected function handleElementRecursive(array $Element) - { - return $this->elementApplyRecursive(array($this, 'handle'), $Element); - } - - protected function handleElementsRecursive(array $Elements) - { - return $this->elementsApplyRecursive(array($this, 'handle'), $Elements); - } - - protected function elementApplyRecursive($closure, array $Element) - { - $Element = call_user_func($closure, $Element); - - if (isset($Element['elements'])) - { - $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']); - } - elseif (isset($Element['element'])) - { - $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']); - } - - return $Element; - } - - protected function elementApplyRecursiveDepthFirst($closure, array $Element) - { - if (isset($Element['elements'])) - { - $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']); - } - elseif (isset($Element['element'])) - { - $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']); - } - - $Element = call_user_func($closure, $Element); - - return $Element; - } - - protected function elementsApplyRecursive($closure, array $Elements) - { - foreach ($Elements as &$Element) - { - $Element = $this->elementApplyRecursive($closure, $Element); - } - - return $Elements; - } - - protected function elementsApplyRecursiveDepthFirst($closure, array $Elements) - { - foreach ($Elements as &$Element) - { - $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element); - } - - return $Elements; - } - - protected function element(array $Element) - { - if ($this->safeMode) - { - $Element = $this->sanitiseElement($Element); - } - - # identity map if element has no handler - $Element = $this->handle($Element); - - $hasName = isset($Element['name']); - - $markup = ''; - - if ($hasName) - { - $markup .= '<' . $Element['name']; - - if (isset($Element['attributes'])) - { - foreach ($Element['attributes'] as $name => $value) - { - if ($value === null) - { - continue; - } - - $markup .= " $name=\"".self::escape($value).'"'; - } - } - } - - $permitRawHtml = false; - - if (isset($Element['text'])) - { - $text = $Element['text']; - } - // very strongly consider an alternative if you're writing an - // extension - elseif (isset($Element['rawHtml'])) - { - $text = $Element['rawHtml']; - - $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode']; - $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; - } - - $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']); - - if ($hasContent) - { - $markup .= $hasName ? '>' : ''; - - if (isset($Element['elements'])) - { - $markup .= $this->elements($Element['elements']); - } - elseif (isset($Element['element'])) - { - $markup .= $this->element($Element['element']); - } - else - { - if (!$permitRawHtml) - { - $markup .= self::escape($text, true); - } - else - { - $markup .= $text; - } - } - - $markup .= $hasName ? '' : ''; - } - elseif ($hasName) - { - $markup .= ' />'; - } - - return $markup; - } - - protected function elements(array $Elements) - { - $markup = ''; - - $autoBreak = true; - - foreach ($Elements as $Element) - { - if (empty($Element)) - { - continue; - } - - $autoBreakNext = (isset($Element['autobreak']) - ? $Element['autobreak'] : isset($Element['name']) - ); - // (autobreak === false) covers both sides of an element - $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext; - - $markup .= ($autoBreak ? "\n" : '') . $this->element($Element); - $autoBreak = $autoBreakNext; - } - - $markup .= $autoBreak ? "\n" : ''; - - return $markup; - } - - # ~ - - protected function li($lines) - { - $Elements = $this->linesElements($lines); - - if ( ! in_array('', $lines) - and isset($Elements[0]) and isset($Elements[0]['name']) - and $Elements[0]['name'] === 'p' - ) { - unset($Elements[0]['name']); - } - - return $Elements; - } - - # - # AST Convenience - # - - /** - * Replace occurrences $regexp with $Elements in $text. Return an array of - * elements representing the replacement. - */ - protected static function pregReplaceElements($regexp, $Elements, $text) - { - $newElements = array(); - - while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE)) - { - $offset = $matches[0][1]; - $before = substr($text, 0, $offset); - $after = substr($text, $offset + strlen($matches[0][0])); - - $newElements[] = array('text' => $before); - - foreach ($Elements as $Element) - { - $newElements[] = $Element; - } - - $text = $after; - } - - $newElements[] = array('text' => $text); - - return $newElements; - } - - # - # Deprecated Methods - # - - function parse($text) - { - $markup = $this->text($text); - - return $markup; - } - - protected function sanitiseElement(array $Element) - { - static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/'; - static $safeUrlNameToAtt = array( - 'a' => 'href', - 'img' => 'src', - ); - - if ( ! isset($Element['name'])) - { - unset($Element['attributes']); - return $Element; - } - - if (isset($safeUrlNameToAtt[$Element['name']])) - { - $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]); - } - - if ( ! empty($Element['attributes'])) - { - foreach ($Element['attributes'] as $att => $val) - { - # filter out badly parsed attribute - if ( ! preg_match($goodAttribute, $att)) - { - unset($Element['attributes'][$att]); - } - # dump onevent attribute - elseif (self::striAtStart($att, 'on')) - { - unset($Element['attributes'][$att]); - } - } - } - - return $Element; - } - - protected function filterUnsafeUrlInAttribute(array $Element, $attribute) - { - foreach ($this->safeLinksWhitelist as $scheme) - { - if (self::striAtStart($Element['attributes'][$attribute], $scheme)) - { - return $Element; - } - } - - $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]); - - return $Element; - } - - # - # Static Methods - # - - protected static function escape($text, $allowQuotes = false) - { - return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8'); - } - - protected static function striAtStart($string, $needle) - { - $len = strlen($needle); - - if ($len > strlen($string)) - { - return false; - } - else - { - return strtolower(substr($string, 0, $len)) === strtolower($needle); - } - } - - static function instance($name = 'default') - { - if (isset(self::$instances[$name])) - { - return self::$instances[$name]; - } - - $instance = new static(); - - self::$instances[$name] = $instance; - - return $instance; - } - - private static $instances = array(); - - # - # Fields - # - - protected $DefinitionData; - - # - # Read-Only - - protected $specialCharacters = array( - '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~' - ); - - protected $StrongRegex = array( - '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s', - '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us', - ); - - protected $EmRegex = array( - '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', - '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', - ); - - protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+'; - - protected $voidElements = array( - 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', - ); - - protected $textLevelElements = array( - 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', - 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', - 'i', 'rp', 'del', 'code', 'strike', 'marquee', - 'q', 'rt', 'ins', 'font', 'strong', - 's', 'tt', 'kbd', 'mark', - 'u', 'xm', 'sub', 'nobr', - 'sup', 'ruby', - 'var', 'span', - 'wbr', 'time', - ); -} diff --git a/lib/parsedownextraplugin/parsedownextra.php b/lib/parsedownextraplugin/parsedownextra.php deleted file mode 100644 index 2eeeda6e0b..0000000000 --- a/lib/parsedownextraplugin/parsedownextra.php +++ /dev/null @@ -1,686 +0,0 @@ -BlockTypes[':'] []= 'DefinitionList'; - $this->BlockTypes['*'] []= 'Abbreviation'; - - # identify footnote definitions before reference definitions - array_unshift($this->BlockTypes['['], 'Footnote'); - - # identify footnote markers before before links - array_unshift($this->InlineTypes['['], 'FootnoteMarker'); - } - - # - # ~ - - function text($text) - { - $Elements = $this->textElements($text); - - # convert to markup - $markup = $this->elements($Elements); - - # trim line breaks - $markup = trim($markup, "\n"); - - # merge consecutive dl elements - - $markup = preg_replace('/<\/dl>\s+
                    \s+/', '', $markup); - - # add footnotes - - if (isset($this->DefinitionData['Footnote'])) - { - $Element = $this->buildFootnoteElement(); - - $markup .= "\n" . $this->element($Element); - } - - return $markup; - } - - # - # Blocks - # - - # - # Abbreviation - - protected function blockAbbreviation($Line) - { - if (preg_match('/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/', $Line['text'], $matches)) - { - $this->DefinitionData['Abbreviation'][$matches[1]] = $matches[2]; - - $Block = array( - 'hidden' => true, - ); - - return $Block; - } - } - - # - # Footnote - - protected function blockFootnote($Line) - { - if (preg_match('/^\[\^(.+?)\]:[ ]?(.*)$/', $Line['text'], $matches)) - { - $Block = array( - 'label' => $matches[1], - 'text' => $matches[2], - 'hidden' => true, - ); - - return $Block; - } - } - - protected function blockFootnoteContinue($Line, $Block) - { - if ($Line['text'][0] === '[' and preg_match('/^\[\^(.+?)\]:/', $Line['text'])) - { - return; - } - - if (isset($Block['interrupted'])) - { - if ($Line['indent'] >= 4) - { - $Block['text'] .= "\n\n" . $Line['text']; - - return $Block; - } - } - else - { - $Block['text'] .= "\n" . $Line['text']; - - return $Block; - } - } - - protected function blockFootnoteComplete($Block) - { - $this->DefinitionData['Footnote'][$Block['label']] = array( - 'text' => $Block['text'], - 'count' => null, - 'number' => null, - ); - - return $Block; - } - - # - # Definition List - - protected function blockDefinitionList($Line, $Block) - { - if ( ! isset($Block) or $Block['type'] !== 'Paragraph') - { - return; - } - - $Element = array( - 'name' => 'dl', - 'elements' => array(), - ); - - $terms = explode("\n", $Block['element']['handler']['argument']); - - foreach ($terms as $term) - { - $Element['elements'] []= array( - 'name' => 'dt', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $term, - 'destination' => 'elements' - ), - ); - } - - $Block['element'] = $Element; - - $Block = $this->addDdElement($Line, $Block); - - return $Block; - } - - protected function blockDefinitionListContinue($Line, array $Block) - { - if ($Line['text'][0] === ':') - { - $Block = $this->addDdElement($Line, $Block); - - return $Block; - } - else - { - if (isset($Block['interrupted']) and $Line['indent'] === 0) - { - return; - } - - if (isset($Block['interrupted'])) - { - $Block['dd']['handler']['function'] = 'textElements'; - $Block['dd']['handler']['argument'] .= "\n\n"; - - $Block['dd']['handler']['destination'] = 'elements'; - - unset($Block['interrupted']); - } - - $text = substr($Line['body'], min($Line['indent'], 4)); - - $Block['dd']['handler']['argument'] .= "\n" . $text; - - return $Block; - } - } - - # - # Header - - protected function blockHeader($Line) - { - $Block = parent::blockHeader($Line); - - if ($Block !== null && preg_match('/[ #]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['handler']['argument'], $matches, PREG_OFFSET_CAPTURE)) - { - $attributeString = $matches[1][0]; - - $Block['element']['attributes'] = $this->parseAttributeData($attributeString); - - $Block['element']['handler']['argument'] = substr($Block['element']['handler']['argument'], 0, $matches[0][1]); - } - - return $Block; - } - - # - # Markup - - protected function blockMarkup($Line) - { - if ($this->markupEscaped or $this->safeMode) - { - return; - } - - if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches)) - { - $element = strtolower($matches[1]); - - if (in_array($element, $this->textLevelElements)) - { - return; - } - - $Block = array( - 'name' => $matches[1], - 'depth' => 0, - 'element' => array( - 'rawHtml' => $Line['text'], - 'autobreak' => true, - ), - ); - - $length = strlen($matches[0]); - $remainder = substr($Line['text'], $length); - - if (trim($remainder) === '') - { - if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) - { - $Block['closed'] = true; - $Block['void'] = true; - } - } - else - { - if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) - { - return; - } - if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder)) - { - $Block['closed'] = true; - } - } - - return $Block; - } - } - - protected function blockMarkupContinue($Line, array $Block) - { - if (isset($Block['closed'])) - { - return; - } - - if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open - { - $Block['depth'] ++; - } - - if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close - { - if ($Block['depth'] > 0) - { - $Block['depth'] --; - } - else - { - $Block['closed'] = true; - } - } - - if (isset($Block['interrupted'])) - { - $Block['element']['rawHtml'] .= "\n"; - unset($Block['interrupted']); - } - - $Block['element']['rawHtml'] .= "\n".$Line['body']; - - return $Block; - } - - protected function blockMarkupComplete($Block) - { - if ( ! isset($Block['void'])) - { - $Block['element']['rawHtml'] = $this->processTag($Block['element']['rawHtml']); - } - - return $Block; - } - - # - # Setext - - protected function blockSetextHeader($Line, array $Block = null) - { - $Block = parent::blockSetextHeader($Line, $Block); - - if ($Block !== null && preg_match('/[ ]*{('.$this->regexAttribute.'+)}[ ]*$/', $Block['element']['handler']['argument'], $matches, PREG_OFFSET_CAPTURE)) - { - $attributeString = $matches[1][0]; - - $Block['element']['attributes'] = $this->parseAttributeData($attributeString); - - $Block['element']['handler']['argument'] = substr($Block['element']['handler']['argument'], 0, $matches[0][1]); - } - - return $Block; - } - - # - # Inline Elements - # - - # - # Footnote Marker - - protected function inlineFootnoteMarker($Excerpt) - { - if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches)) - { - $name = $matches[1]; - - if ( ! isset($this->DefinitionData['Footnote'][$name])) - { - return; - } - - $this->DefinitionData['Footnote'][$name]['count'] ++; - - if ( ! isset($this->DefinitionData['Footnote'][$name]['number'])) - { - $this->DefinitionData['Footnote'][$name]['number'] = ++ $this->footnoteCount; # » & - } - - $Element = array( - 'name' => 'sup', - 'attributes' => array('id' => 'fnref'.$this->DefinitionData['Footnote'][$name]['count'].':'.$name), - 'element' => array( - 'name' => 'a', - 'attributes' => array('href' => '#fn:'.$name, 'class' => 'footnote-ref'), - 'text' => $this->DefinitionData['Footnote'][$name]['number'], - ), - ); - - return array( - 'extent' => strlen($matches[0]), - 'element' => $Element, - ); - } - } - - private $footnoteCount = 0; - - # - # Link - - protected function inlineLink($Excerpt) - { - $Link = parent::inlineLink($Excerpt); - - $remainder = $Link !== null ? substr($Excerpt['text'], $Link['extent']) : ''; - - if (preg_match('/^[ ]*{('.$this->regexAttribute.'+)}/', $remainder, $matches)) - { - $Link['element']['attributes'] += $this->parseAttributeData($matches[1]); - - $Link['extent'] += strlen($matches[0]); - } - - return $Link; - } - - # - # ~ - # - - private $currentAbreviation; - private $currentMeaning; - - protected function insertAbreviation(array $Element) - { - if (isset($Element['text'])) - { - $Element['elements'] = self::pregReplaceElements( - '/\b'.preg_quote($this->currentAbreviation, '/').'\b/', - array( - array( - 'name' => 'abbr', - 'attributes' => array( - 'title' => $this->currentMeaning, - ), - 'text' => $this->currentAbreviation, - ) - ), - $Element['text'] - ); - - unset($Element['text']); - } - - return $Element; - } - - protected function inlineText($text) - { - $Inline = parent::inlineText($text); - - if (isset($this->DefinitionData['Abbreviation'])) - { - foreach ($this->DefinitionData['Abbreviation'] as $abbreviation => $meaning) - { - $this->currentAbreviation = $abbreviation; - $this->currentMeaning = $meaning; - - $Inline['element'] = $this->elementApplyRecursiveDepthFirst( - array($this, 'insertAbreviation'), - $Inline['element'] - ); - } - } - - return $Inline; - } - - # - # Util Methods - # - - protected function addDdElement(array $Line, array $Block) - { - $text = substr($Line['text'], 1); - $text = trim($text); - - unset($Block['dd']); - - $Block['dd'] = array( - 'name' => 'dd', - 'handler' => array( - 'function' => 'lineElements', - 'argument' => $text, - 'destination' => 'elements' - ), - ); - - if (isset($Block['interrupted'])) - { - $Block['dd']['handler']['function'] = 'textElements'; - - unset($Block['interrupted']); - } - - $Block['element']['elements'] []= & $Block['dd']; - - return $Block; - } - - protected function buildFootnoteElement() - { - $Element = array( - 'name' => 'div', - 'attributes' => array('class' => 'footnotes'), - 'elements' => array( - array('name' => 'hr'), - array( - 'name' => 'ol', - 'elements' => array(), - ), - ), - ); - - uasort($this->DefinitionData['Footnote'], 'self::sortFootnotes'); - - foreach ($this->DefinitionData['Footnote'] as $definitionId => $DefinitionData) - { - if ( ! isset($DefinitionData['number'])) - { - continue; - } - - $text = $DefinitionData['text']; - - $textElements = parent::textElements($text); - - $numbers = range(1, $DefinitionData['count']); - - $backLinkElements = array(); - - foreach ($numbers as $number) - { - $backLinkElements[] = array('text' => ' '); - $backLinkElements[] = array( - 'name' => 'a', - 'attributes' => array( - 'href' => "#fnref$number:$definitionId", - 'rev' => 'footnote', - 'class' => 'footnote-backref', - ), - 'rawHtml' => '↩', - 'allowRawHtmlInSafeMode' => true, - 'autobreak' => false, - ); - } - - unset($backLinkElements[0]); - - $n = count($textElements) -1; - - if ($textElements[$n]['name'] === 'p') - { - $backLinkElements = array_merge( - array( - array( - 'rawHtml' => ' ', - 'allowRawHtmlInSafeMode' => true, - ), - ), - $backLinkElements - ); - - unset($textElements[$n]['name']); - - $textElements[$n] = array( - 'name' => 'p', - 'elements' => array_merge( - array($textElements[$n]), - $backLinkElements - ), - ); - } - else - { - $textElements[] = array( - 'name' => 'p', - 'elements' => $backLinkElements - ); - } - - $Element['elements'][1]['elements'] []= array( - 'name' => 'li', - 'attributes' => array('id' => 'fn:'.$definitionId), - 'elements' => array_merge( - $textElements - ), - ); - } - - return $Element; - } - - # ~ - - protected function parseAttributeData($attributeString) - { - $Data = array(); - - $attributes = preg_split('/[ ]+/', $attributeString, - 1, PREG_SPLIT_NO_EMPTY); - - foreach ($attributes as $attribute) - { - if ($attribute[0] === '#') - { - $Data['id'] = substr($attribute, 1); - } - else # "." - { - $classes []= substr($attribute, 1); - } - } - - if (isset($classes)) - { - $Data['class'] = implode(' ', $classes); - } - - return $Data; - } - - # ~ - - protected function processTag($elementMarkup) # recursive - { - # http://stackoverflow.com/q/1148928/200145 - libxml_use_internal_errors(true); - - $DOMDocument = new DOMDocument; - - # http://stackoverflow.com/q/11309194/200145 - $elementMarkup = mb_convert_encoding($elementMarkup, 'HTML-ENTITIES', 'UTF-8'); - - # http://stackoverflow.com/q/4879946/200145 - $DOMDocument->loadHTML($elementMarkup); - $DOMDocument->removeChild($DOMDocument->doctype); - $DOMDocument->replaceChild($DOMDocument->firstChild->firstChild->firstChild, $DOMDocument->firstChild); - - $elementText = ''; - - if ($DOMDocument->documentElement->getAttribute('markdown') === '1') - { - foreach ($DOMDocument->documentElement->childNodes as $Node) - { - $elementText .= $DOMDocument->saveHTML($Node); - } - - $DOMDocument->documentElement->removeAttribute('markdown'); - - $elementText = "\n".$this->text($elementText)."\n"; - } - else - { - foreach ($DOMDocument->documentElement->childNodes as $Node) - { - $nodeMarkup = $DOMDocument->saveHTML($Node); - - if ($Node instanceof DOMElement and ! in_array($Node->nodeName, $this->textLevelElements)) - { - $elementText .= $this->processTag($nodeMarkup); - } - else - { - $elementText .= $nodeMarkup; - } - } - } - - # because we don't want for markup to get encoded - $DOMDocument->documentElement->nodeValue = 'placeholder\x1A'; - - $markup = $DOMDocument->saveHTML($DOMDocument->documentElement); - $markup = str_replace('placeholder\x1A', $elementText, $markup); - - return $markup; - } - - # ~ - - protected function sortFootnotes($A, $B) # callback - { - return $A['number'] - $B['number']; - } - - # - # Fields - # - - protected $regexAttribute = '(?:[#.][-\w]+[ ]*)'; -} diff --git a/lib/parsedownextraplugin/parsedownextraplugin.class.php b/lib/parsedownextraplugin/parsedownextraplugin.class.php deleted file mode 100644 index f4787db640..0000000000 --- a/lib/parsedownextraplugin/parsedownextraplugin.class.php +++ /dev/null @@ -1,590 +0,0 @@ -'; - - protected $regexAttribute = '(?:[#.][-\w:\\\]+[ ]*|[-\w:\\\]+(?:=(?:["\'][^\n]*?["\']|[^\s]+)?)?[ ]*)'; - - # Method aliases for every configuration property - public function __call($key, array $arguments = array()) { - $property = lcfirst(substr($key, 3)); - if (strpos($key, 'set') === 0 && property_exists($this, $property)) { - $this->{$property} = $arguments[0]; - return $this; - } - throw new Exception('Method ' . $key . ' does not exists.'); - } - - public function __construct() { - if (version_compare(parent::version, '0.8.0-beta-1') < 0) { - throw new Exception('ParsedownExtraPlugin requires a later version of Parsedown'); - } - $this->BlockTypes['!'][] = 'Image'; - parent::__construct(); - } - - protected function blockAbbreviation($Line) { - // Allow empty abbreviations - if (preg_match('/^\*\[(.+?)\]:[ ]*$/', $Line['text'], $matches)) { - $this->DefinitionData['Abbreviation'][$matches[1]] = null; - return array('hidden' => true); - } - return parent::blockAbbreviation($Line); - } - - protected function blockCodeComplete($Block) { - $this->doSetAttributes($Block['element']['element'], $this->blockCodeAttributes); - $this->doSetContent($Block['element']['element'], $this->blockCodeHtml, true); - // Put code attributes on parent element - if ($this->codeAttributesOnParent) { - if ($this->codeAttributesOnParent === true) { - // $this->codeAttributesOnParent = array_keys($Block['element']['element']['attributes']); - $this->codeAttributesOnParent = array('class', 'id'); - } - foreach ((array) $this->codeAttributesOnParent as $Name) { - if (isset($Block['element']['element']['attributes'][$Name])) { - $Block['element']['attributes'][$Name] = $Block['element']['element']['attributes'][$Name]; - unset($Block['element']['element']['attributes'][$Name]); - } - } - } - $Block['element']['element']['rawHtml'] = $Block['element']['element']['text']; - $Block['element']['element']['allowRawHtmlInSafeMode'] = true; - unset($Block['element']['element']['text']); - return $Block; - } - - protected function blockFencedCode($Line) { - // Re-enable the multiple class name feature - $Line['text'] = strtr(trim($Line['text']), array( - ' ' => "\x1A", - '.' => "\x1A." - )); - // Enable custom attribute syntax on code block - $Attributes = array(); - if (strpos($Line['text'], '{') !== false && substr($Line['text'], -1) === '}') { - $Parts = explode('{', $Line['text'], 2); - $Attributes = $this->parseAttributeData(strtr(substr($Parts[1], 0, -1), "\x1A", ' ')); - $Line['text'] = trim($Parts[0]); - } - if (!$Block = parent::blockFencedCode($Line)) { - return; - } - if ($Attributes) { - $Block['element']['element']['attributes'] = $Attributes; - } else if (isset($Block['element']['element']['attributes']['class'])) { - $Classes = explode("\x1A", strtr($Block['element']['element']['attributes']['class'], ' ', "\x1A")); - // `~~~ php` → `
                    `
                    -            // `~~~ php html` → `
                    `
                    -            // `~~~ .php` → `
                    `
                    -            // `~~~ .php.html` → `
                    `
                    -            // `~~~ .php html` → `
                    `
                    -            // `~~~ {.php #foo}` → `
                    `
                    -            $Results = [];
                    -            foreach ($Classes as $Class) {
                    -                if ($Class === "" || $Class === strtr($this->blockCodeClassFormat, array('%s' => ""))) {
                    -                    continue;
                    -                }
                    -                if ($Class[0] === '.') {
                    -                    $Results[] = substr($Class, 1);
                    -                } else if (preg_match('/^' . strtr(preg_quote($this->blockCodeClassFormat), array('%s' => '\S+')) . '$/', $Class)) {
                    -                    $Results[] = $Class; // Do nothing!
                    -                } else {
                    -                    $Results[] = sprintf($this->blockCodeClassFormat, $Class);
                    -                }
                    -            }
                    -            if ($Results = array_unique($Results)) {
                    -                $Block['element']['element']['attributes']['class'] = implode(' ', $Results);
                    -            } else {
                    -                unset($Block['element']['element']['attributes']['class']);
                    -            }
                    -        }
                    -        return $Block;
                    -    }
                    -
                    -    protected function blockFencedCodeComplete($Block) {
                    -        return $this->blockCodeComplete($Block);
                    -    }
                    -
                    -    protected function blockHeader($Line) {
                    -        if (!$Block = parent::blockHeader($Line)) {
                    -            return;
                    -        }
                    -        $Level = strspn($Line['text'], '#');
                    -        $this->doSetAttributes($Block['element'], $this->headerAttributes, array($Level));
                    -        $this->doSetContent($Block['element'], $this->headerText, false, 'argument', array($Level));
                    -        return $Block;
                    -    }
                    -
                    -    protected function blockImage($Line) {
                    -        if (!$this->figuresEnabled) {
                    -            return;
                    -        }
                    -        // Match exactly an image syntax in a paragraph (with optional custom attributes, and optional hard break marker)
                    -        if (preg_match('/^\!\[[^\n]*?\](\[[^\n]*?\]|\([^\n]*?\))(\s*\{' . $this->regexAttribute . '+?\})?([ ]{2})?$/', $Line['text'])) {
                    -            $Block = array(
                    -                'description' => "",
                    -                'element' => array(
                    -                    'name' => 'figure',
                    -                    'attributes' => array(),
                    -                    'elements' => array(
                    -                        $this->inlineImage($Line)
                    -                    )
                    -                )
                    -            );
                    -            $this->doSetAttributes($Block['element'], $this->figureAttributes);
                    -            return $Block;
                    -        }
                    -        return;
                    -    }
                    -
                    -    protected function blockImageComplete($Block) {
                    -        if (!empty($Block['description'])) {
                    -            $Description = $Block['description'];
                    -            $Block['element']['elements'][] = array(
                    -                'name' => 'figcaption',
                    -                'rawHtml' => $this->{strpos($Description, "\n\n") === false ? 'line' : 'text'}(trim($Description, "\n"))
                    -            );
                    -            // unset($Block['description']);
                    -        }
                    -        if ($this->imageAttributesOnParent) {
                    -            $Inline = $Block['element']['elements'][0];
                    -            if ($this->imageAttributesOnParent === true) {
                    -                $this->imageAttributesOnParent = array_keys($Inline['element']['attributes']);
                    -            }
                    -            foreach ((array) $this->imageAttributesOnParent as $Name) {
                    -                if (isset($Inline['element']['attributes'][$Name])) {
                    -                    // Merge class names
                    -                    if (
                    -                        $Name === 'class' &&
                    -                        isset($Block['element']['attributes'][$Name]) &&
                    -                        isset($Inline['element']['attributes'][$Name])
                    -                    ) {
                    -                        $Classes = array_merge(
                    -                            explode(' ', $Block['element']['attributes'][$Name]),
                    -                            explode(' ', $Inline['element']['attributes'][$Name])
                    -                        );
                    -                        sort($Classes);
                    -                        $Block['element']['attributes']['class'] = implode(' ', array_unique(array_filter($Classes)));
                    -                        unset($Block['element']['elements'][0]['element']['attributes'][$Name]);
                    -                        continue;
                    -                    }
                    -                    $Block['element']['attributes'][$Name] = $Inline['element']['attributes'][$Name];
                    -                    unset($Block['element']['elements'][0]['element']['attributes'][$Name]);
                    -                }
                    -            }
                    -        }
                    -        return $Block;
                    -    }
                    -
                    -    protected function blockImageContinue($Line, array $Block) {
                    -        if (isset($Block['complete'])) {
                    -            return;
                    -        }
                    -        if (isset($Block['interrupted'])) {
                    -            $Block['description'] .= "\n";
                    -            unset($Block['interrupted']);
                    -        }
                    -        if ($Line['indent'] === 0) {
                    -            $Block['complete'] = true;
                    -            return;
                    -        }
                    -        if ($Line['indent'] > 0 && $Line['indent'] < 4) {
                    -            $Block['description'] .= "\n" . $Line['text'];
                    -            return $Block;
                    -        }
                    -        return;
                    -    }
                    -
                    -    protected function blockQuoteComplete($Block) {
                    -        $this->doSetAttributes($Block['element'], $this->blockQuoteAttributes);
                    -        $this->doSetContent($Block['element'], $this->blockQuoteText, false, 'arguments');
                    -        return $Block;
                    -    }
                    -
                    -    protected function blockSetextHeader($Line, array $Block = null) {
                    -        if (!$Block = parent::blockSetextHeader($Line, $Block)) {
                    -            return;
                    -        }
                    -        $Level = $Line['text'][0] === '=' ? 1 : 2;
                    -        $this->doSetAttributes($Block['element'], $this->headerAttributes, array($Level));
                    -        $this->doSetContent($Block['element'], $this->headerText, false, 'argument', array($Level));
                    -        return $Block;
                    -    }
                    -
                    -    protected function blockTableContinue($Line, array $Block) {
                    -        if (!$Block = parent::blockTableContinue($Line, $Block)) {
                    -            return;
                    -        }
                    -        $Aligns = $Block['alignments'];
                    -        // `
                    ` or `` - foreach ($Element1['elements'] as $Index2 => &$Element2) { - $this->doSetAttributes($Element2, $this->tableColumnAttributes, array($Aligns[$Index2], $Index2, $Index1)); - } - } - } - return $Block; - } - - protected function blockTableComplete($Block) { - $this->doSetAttributes($Block['element'], $this->tableAttributes); - return $Block; - } - - protected function buildFootnoteElement() { - $DefinitionData = $this->DefinitionData['Footnote']; - if (!$Footnotes = parent::buildFootnoteElement()) { - return; - } - $DefinitionKey = array_keys($DefinitionData); - $DefinitionData = array_values($DefinitionData); - $this->doSetAttributes($Footnotes, $this->footnoteAttributes); - foreach ($Footnotes['elements'][1]['elements'] as $Index0 => &$Element0) { - $Name = $DefinitionKey[$Index0]; - $Count = $DefinitionData[$Index0]['count']; - $Args = array(is_numeric($Name) ? (float) $Name : $Name, $Count); - $this->doSetAttributes($Element0, $this->footnoteBackReferenceAttributes, $Args); - foreach ($Element0['elements'] as $Index1 => &$Element1) { - if (!isset($Element1['elements'])) { - continue; - } - $Count = 0; - foreach ($Element1['elements'] as $Index2 => &$Element2) { - if (!isset($Element2['name']) || $Element2['name'] !== 'a') { - continue; - } - $Args[1] = ++$Count; - $this->doSetAttributes($Element2, $this->footnoteBackLinkAttributes, $Args); - $this->doSetContent($Element2, $this->footnoteBackLinkHtml, false, 'rawHtml'); - } - } - } - return $Footnotes; - } - - protected function doGetAttributes($Element) { - if (isset($Element['attributes'])) { - return (array) $Element['attributes']; - } - return array(); - } - - protected function doGetContent($Element) { - if (isset($Element['text'])) { - return $Element['text']; - } - if (isset($Element['rawHtml'])) { - return $Element['rawHtml']; - } - if (isset($Element['handler']['argument'])) { - return implode("\n", (array) $Element['handler']['argument']); - } - return null; - } - - private function doSetLink($Excerpt, $Function) { - if (!$Inline = call_user_func('parent::' . $Function, $Excerpt)) { - return; - } - $this->doSetAttributes($Inline['element'], $this->linkAttributes, array($this->isLocal($Inline['element'], 'href'))); - $this->doSetData($this->DefinitionData['Reference'], $this->referenceData); - return $Inline; - } - - protected function doSetAttributes(&$Element, $From, $Args = array()) { - $Attributes = $this->doGetAttributes($Element); - $Content = $this->doGetContent($Element); - if (is_callable($From)) { - $Args = array_merge(array($Content, $Attributes, &$Element), $Args); - $Element['attributes'] = array_replace($Attributes, (array) call_user_func_array($From, $Args)); - } else { - $Element['attributes'] = array_replace($Attributes, (array) $From); - } - } - - protected function doSetContent(&$Element, $From, $Esc = false, $Mode = 'text', $Args = array()) { - $Attributes = $this->doGetAttributes($Element); - $Content = $this->doGetContent($Element); - if ($Esc) { - $Content = parent::escape($Content, true); - } - if (is_callable($From)) { - $Args = array_merge(array($Content, $Attributes, &$Element), $Args); - $Content = call_user_func_array($From, $Args); - } else if (!empty($From)) { - $Content = sprintf($From, $Content); - } - if ($Mode === 'arguments') { - $Element['handler']['argument'] = explode("\n", $Content); - } else if ($Mode === 'argument') { - $Element['handler']['argument'] = $Content; - } else { - $Element[$Mode] = $Content; - } - } - - protected function doSetData(&$To, $From) { - $To = array_replace((array) $To, (array) $From); - } - - protected function element(array $Element) { - if (!$Any = parent::element($Element)) { - return; - } - if (substr($Any, -3) === ' />') { - if (is_callable($this->voidElementSuffix)) { - $Attributes = $this->doGetAttributes($Element); - $Content = $this->doGetContent($Element); - $Suffix = call_user_func_array($this->voidElementSuffix, [$Content, $Attributes, &$Element]); - } else { - $Suffix = $this->voidElementSuffix; - } - $Any = substr_replace($Any, $Suffix, -3); - } - return $Any; - } - - protected function inlineCode($Excerpt) { - if (!$Inline = parent::inlineCode($Excerpt)) { - return; - } - $this->doSetAttributes($Inline['element'], $this->codeAttributes); - $this->doSetContent($Inline['element'], $this->codeHtml, true); - $Inline['element']['rawHtml'] = $Inline['element']['text']; - $Inline['element']['allowRawHtmlInSafeMode'] = true; - unset($Inline['element']['text']); - return $Inline; - } - - protected function inlineFootnoteMarker($Excerpt) { - if (!$Inline = parent::inlineFootnoteMarker($Excerpt)) { - return; - } - $Name = null; - if (preg_match('/^\[\^(.+?)\]/', $Excerpt['text'], $matches)) { - $Name = $matches[1]; - } - $Args = array(is_numeric($Name) ? (float) $Name : $Name, $this->DefinitionData['Footnote'][$Name]['count']); - $this->doSetAttributes($Inline['element'], $this->footnoteReferenceAttributes, $Args); - $this->doSetAttributes($Inline['element']['element'], $this->footnoteLinkAttributes, $Args); - $this->doSetContent($Inline['element']['element'], $this->footnoteLinkHtml, false, 'text', $Args); - $Inline['element']['element']['rawHtml'] = $Inline['element']['element']['text']; - $Inline['element']['element']['allowRawHtmlInSafeMode'] = true; - unset($Inline['element']['element']['text']); - return $Inline; - } - - protected function inlineImage($Excerpt) { - if (!$Inline = parent::inlineImage($Excerpt)) { - return; - } - $this->doSetAttributes($Inline['element'], $this->imageAttributes, array($this->isLocal($Inline['element'], 'src'))); - return $Inline; - } - - protected function inlineLink($Excerpt) { - return $this->doSetLink($Excerpt, __FUNCTION__); - } - - protected function inlineText($Text) { - $this->doSetData($this->DefinitionData['Abbreviation'], $this->abbreviationData); - return parent::inlineText($Text); - } - - protected function inlineUrl($Excerpt) { - return $this->doSetLink($Excerpt, __FUNCTION__); - } - - protected function inlineUrlTag($Excerpt) { - return $this->doSetLink($Excerpt, __FUNCTION__); - } - - protected function isLocal($Element, $Key) { - $Link = isset($Element['attributes'][$Key]) ? (string) $Element['attributes'][$Key] : null; - if ( - // `` - $Link === "" || - // `` - // `` - // `` - // `` - // `` - strpos('./?&#', $Link[0]) !== false && strpos($Link, '//') !== 0 || - // `` - strpos($Link, 'data:') === 0 || - // `` - strpos($Link, 'javascript:') === 0 || - // `` - strpos($Link, 'mailto:') === 0 - ) { - return true; - } - if (isset($_SERVER['HTTP_HOST'])) { - $Host = $_SERVER['HTTP_HOST']; - } else if (isset($_SERVER['SERVER_NAME'])) { - $Host = $_SERVER['SERVER_NAME']; - } else { - $Host = ""; - } - // `` - if (strpos($Link, '//') === 0 && strpos($Link, '//' . $Host) !== 0) { - return false; - } - if ( - // `` - strpos($Link, 'https://' . $Host) === 0 || - // `` - strpos($Link, 'http://' . $Host) === 0 - ) { - return true; - } - // `` - return strpos($Link, '://') === false; - } - - protected function parseAttributeData($attributeString) { - // Allow compact attributes - $attributeString = strtr($attributeString, array( - '#' => ' #', - '.' => ' .' - )); - if (strpos($attributeString, '="') !== false || strpos($attributeString, "='") !== false) { - $attributeString = preg_replace_callback('#([-\w]+=)(["\'])([^\n]*?)\2#', function($matches) { - $value = strtr($matches[3], array( - ' #' => '#', - ' .' => '.', - ' ' => "\x1A" - )); - return $matches[1] . $matches[2] . $value . $matches[2]; - }, $attributeString); - } - $Attributes = array(); - foreach (explode(' ', $attributeString) as $v) { - if (!$v) { - continue; - } - // `{#foo}` - if ($v[0] === '#' && isset($v[1])) { - $Attributes['id'] = substr($v, 1); - // `{.foo}` - } else if ($v[0] === '.' && isset($v[1])) { - $Attributes['class'][] = substr($v, 1); - // ~ - } else if (strpos($v, '=') !== false) { - $vv = explode('=', $v, 2); - // `{foo=}` - if ($vv[1] === "") { - if ($vv[0] === 'class') { - continue; - } - $Attributes[$vv[0]] = ""; - // `{foo="bar baz"}` - // `{foo='bar baz'}` - } else if ($vv[1][0] === '"' && substr($vv[1], -1) === '"' || $vv[1][0] === "'" && substr($vv[1], -1) === "'") { - $values = stripslashes(strtr(substr(substr($vv[1], 1), 0, -1), "\x1A", ' ')); - if ($vv[0] === 'class' && isset($Attributes[$vv[0]])) { - $values = explode(' ', $values); - $Attributes[$vv[0]] = array_merge($Attributes[$vv[0]], $values); - } else { - $Attributes[$vv[0]] = $values; - } - // `{foo=bar}` - } else { - if ($vv[0] === 'class' && isset($Attributes[$vv[0]])) { - $Attributes[$vv[0]] = array_merge($Attributes[$vv[0]], [$vv[1]]); - } else { - $Attributes[$vv[0]] = $vv[1]; - } - } - // `{foo}` - } else { - if ($v === 'class' && isset($Attributes[$v])) { - continue; - } - $Attributes[$v] = $v; - } - } - if (isset($Attributes['class'])) { - $Attributes['class'] = implode(' ', array_unique((array) $Attributes['class'])); - } - return $Attributes; - } - -} diff --git a/module/common/model.php b/module/common/model.php index a923835821..b3ef19aac3 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -3250,13 +3250,11 @@ EOD; if(empty($markdown)) return false; global $app; - $app->loadClass('parsedownextraplugin'); + $app->loadClass('michelf'); - $Parsedown = new parsedownextraplugin; + $Michelf = new michelf; - $Parsedown->voidElementSuffix = '>'; // HTML5 - - return $Parsedown->text($markdown); + return $Michelf->parse($markdown); } } From 59b7e2675cd040ca8ddcac050f984db543974a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 11:18:05 +0800 Subject: [PATCH 079/304] * Remove unused code. --- lib/michelf/.github/workflows/ci.yml | 25 ------------------- lib/michelf/.scrutinizer.yml | 36 ---------------------------- lib/michelf/.travis.yml | 19 --------------- 3 files changed, 80 deletions(-) delete mode 100644 lib/michelf/.github/workflows/ci.yml delete mode 100644 lib/michelf/.scrutinizer.yml delete mode 100644 lib/michelf/.travis.yml diff --git a/lib/michelf/.github/workflows/ci.yml b/lib/michelf/.github/workflows/ci.yml deleted file mode 100644 index 6e49b8397b..0000000000 --- a/lib/michelf/.github/workflows/ci.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: CI -on: - pull_request: null - push: - branches: - - lib -jobs: - tests: - runs-on: ubuntu-latest - strategy: - matrix: - php: ['7.4', '8.0'] - - name: Linting - PHP ${{ matrix.php }} - steps: - - uses: actions/checkout@v2 - - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: none - extensions: intl - - run: composer install --no-progress -# - run: composer codestyle - - run: composer phpstan - - run: composer tests diff --git a/lib/michelf/.scrutinizer.yml b/lib/michelf/.scrutinizer.yml deleted file mode 100644 index 7542096df5..0000000000 --- a/lib/michelf/.scrutinizer.yml +++ /dev/null @@ -1,36 +0,0 @@ -build: - environment: - php: - version: '7.4' - nodes: - analysis: - project_setup: - override: - - 'true' - tests: - override: - - - command: 'vendor/bin/phpunit --coverage-clover=clover.xml' - coverage: - file: 'clover.xml' - format: 'clover' - - - command: phpcs-run - use_website_config: true - environment: - node: - version: 6.0.0 - tests: true -filter: - excluded_paths: - - 'test/*' -checks: - php: true -coding_style: - php: - indentation: - general: - use_tabs: true - spaces: - around_operators: - concatenation: true diff --git a/lib/michelf/.travis.yml b/lib/michelf/.travis.yml deleted file mode 100644 index 5a2a16a4ec..0000000000 --- a/lib/michelf/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: php - -matrix: - include: - - php: hhvm-3.18 - dist: trusty - - php: 7.4 - dist: bionic - - php: 8.0 - dist: bionic - -install: - - composer install --prefer-dist - -script: - - vendor/bin/phpunit --log-junit=phpunit.log - -notifications: - email: false From 628c54a83806a4f30fac0313120efdffdff9b44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 11:26:35 +0800 Subject: [PATCH 080/304] *Optimize the code. --- module/kanban/css/view.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 1ca818996b..b5b899dd88 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -127,7 +127,7 @@ .kanban-card .releaseTitle .icon, .kanban-card .title .icon, .kanban-card .productplanTitle .icon, .kanban-card .title .icon, .kanban-card .buildTitle .icon{padding-right: 5px;} .kanban-card .label-finish {margin-right: 7px; margin-top: -1px; padding: 3px 5px; float: left; background-color:#2a5f29;} .kanban-card .releaseTitle, .kanban-card .productplanTitle {width: 100%; float: left;} -.kanban-card .productplanDesc {width: 235px;} +.kanban-card .productplanDesc {min-width: 200px;} .progress-box {width:100%; display: flex; flex-direction: row; margin-top: 10px;} .progress {flex: auto; margin: 5px auto 5px;} From 7ff5e4142b292dd900ca8d45a170db0964933b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 13:22:07 +0800 Subject: [PATCH 081/304] * Finish task #54194. --- module/story/css/create.css | 1 + 1 file changed, 1 insertion(+) diff --git a/module/story/css/create.css b/module/story/css/create.css index f42cfff37e..2407fdb37a 100644 --- a/module/story/css/create.css +++ b/module/story/css/create.css @@ -6,3 +6,4 @@ #source_chosen {min-width: 50px !important;} #feedback.input-group + #notifyEmailLabel {position: relative; width: 50%; left: 48%} +#product + .picker{min-width: 400px} From fb4e586acfcb491c8acbc53f636228adb2617ca3 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 17 May 2022 14:50:31 +0800 Subject: [PATCH 082/304] * Finish task #54349. --- module/common/lang/menu.php | 2 +- module/custom/control.php | 21 +++++++++++++++++++ module/custom/lang/en.php | 7 +++++++ module/custom/lang/zh-cn.php | 7 +++++++ module/custom/view/header.html.php | 4 ++-- module/kanban/control.php | 3 +++ module/kanban/js/view.js | 10 +++++++++ module/kanban/model.php | 20 ++++++++++-------- module/kanban/view/view.html.php | 1 + module/kanban/view/viewarchivedcard.html.php | 5 +++-- .../kanban/view/viewarchivedcolumn.html.php | 4 ++-- 11 files changed, 68 insertions(+), 16 deletions(-) diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 6899c593d3..0929eaccff 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -476,7 +476,7 @@ $lang->company->menuOrder[30] = 'addUser'; $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); $lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,'); -$lang->admin->menu->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'class' => 'dropdown dropdown-hover', 'exclude' => 'custom-index,custom-set,custom-product,custom-execution,custom-required,custom-flow,custom-score,custom-feedback,custom-timezone,custom-mode'); +$lang->admin->menu->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'class' => 'dropdown dropdown-hover', 'exclude' => 'custom-index,custom-set,custom-product,custom-execution,custom-kanban,custom-required,custom-flow,custom-score,custom-feedback,custom-timezone,custom-mode'); $lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate'); $lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension'); $lang->admin->menu->dev = array('link' => "$lang->redev|dev|api", 'alias' => 'db', 'subModule' => 'dev,editor,entry'); diff --git a/module/custom/control.php b/module/custom/control.php index 62ad339866..d46597c491 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -518,6 +518,27 @@ class custom extends control $this->display(); } + /** + * Set whether the kanban is read-only. + * + * @access public + * @return void + */ + public function kanban() + { + if($_POST) + { + $this->loadModel('setting')->setItem("system.common.CRKanban@{$this->config->vision}", $this->post->kanban); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload')); + } + + $this->view->title = $this->lang->custom->kanban; + $this->view->position[] = $this->lang->custom->common; + $this->view->position[] = $this->view->title; + + $this->display(); + } + /** * Set flow. * diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php index 84ffb3fb62..d2161714d5 100644 --- a/module/custom/lang/en.php +++ b/module/custom/lang/en.php @@ -49,6 +49,7 @@ $lang->custom->switch = "Switch"; $lang->custom->oneUnit = "One {$lang->hourCommon}"; $lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s"; $lang->custom->superReviewers = "Super Reviewer"; +$lang->custom->kanban = "Kanban"; if($config->systemMode == 'new') $lang->custom->execution = 'Execution'; if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon; @@ -79,11 +80,13 @@ $lang->custom->saveTips = 'After clicking save, the current %s will b $lang->custom->numberError = 'The interval must be greater than zero!'; $lang->custom->closedExecution = 'Closed ' . $lang->executionCommon; +$lang->custom->closedKanban = 'Closed ' . $lang->custom->kanban; $lang->custom->closedProduct = 'Closed ' . $lang->productCommon; if($config->systemMode == 'new') $lang->custom->object['project'] = 'Project'; $lang->custom->object['product'] = $lang->productCommon; $lang->custom->object['execution'] = $lang->custom->execution; +$lang->custom->object['kanban'] = $lang->custom->kanban; $lang->custom->object['story'] = 'Story'; $lang->custom->object['task'] = 'Task'; $lang->custom->object['bug'] = 'Bug'; @@ -174,6 +177,7 @@ $lang->custom->notice->conceptResult = 'According to your preference, $lang->custom->notice->conceptPath = 'Go to Admin -> Custom -> Concept to set it.'; $lang->custom->notice->readOnlyOfProduct = 'If Change Forbidden, any change on stories, bugs, cases, efforts, releases and plans of the closed product is also forbidden.'; $lang->custom->notice->readOnlyOfExecution = "If Change Forbidden, any change on tasks, builds, efforts and stories of the closed {$lang->executionCommon} is also forbidden."; +$lang->custom->notice->readOnlyOfKanban = "If Change Forbidden, any change on kanban card and related operations of {$lang->custom->kanban} is also forbidden."; $lang->custom->notice->URSREmpty = 'Custom requirement name can not be empty!'; $lang->custom->notice->confirmDelete = 'Are you sure you want to delete it?'; $lang->custom->notice->confirmReviewCase = 'Set the case in Wait to Normal?'; @@ -232,6 +236,9 @@ $lang->custom->CRProduct[0] = 'Change Forbidden'; $lang->custom->CRExecution[1] = 'Change Allowed'; $lang->custom->CRExecution[0] = 'Change Forbidden'; +$lang->custom->CRKanban[1] = 'Change Allowed'; +$lang->custom->CRKanban[0] = 'Change Forbidden'; + $lang->custom->moduleName['product'] = $lang->productCommon; $lang->custom->moduleName['productplan'] = 'Plan'; $lang->custom->moduleName['execution'] = $lang->custom->execution; diff --git a/module/custom/lang/zh-cn.php b/module/custom/lang/zh-cn.php index 991319a060..747d231c88 100644 --- a/module/custom/lang/zh-cn.php +++ b/module/custom/lang/zh-cn.php @@ -49,6 +49,7 @@ $lang->custom->switch = "切换"; $lang->custom->oneUnit = "一个{$lang->hourCommon}"; $lang->custom->convertRelationTitle = "请先设置{$lang->hourCommon}转换为%s的换算系数"; $lang->custom->superReviewers = "超级评审人"; +$lang->custom->kanban = "看板"; if($config->systemMode == 'new') $lang->custom->execution = '执行'; if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon; @@ -79,11 +80,13 @@ $lang->custom->saveTips = '点击保存后,则以当前%s为默认 $lang->custom->numberError = '区间必须大于零'; $lang->custom->closedExecution = '已关闭' . $lang->custom->execution; +$lang->custom->closedKanban = '已关闭' . $lang->custom->kanban; $lang->custom->closedProduct = '已关闭' . $lang->productCommon; if($config->systemMode == 'new') $lang->custom->object['project'] = '项目'; $lang->custom->object['product'] = $lang->productCommon; $lang->custom->object['execution'] = $lang->custom->execution; +$lang->custom->object['kanban'] = $lang->custom->kanban; $lang->custom->object['story'] = $lang->SRCommon; $lang->custom->object['task'] = '任务'; $lang->custom->object['bug'] = 'Bug'; @@ -174,6 +177,7 @@ $lang->custom->notice->conceptResult = '我们已经根据您的选择为 $lang->custom->notice->conceptPath = '您可以在:后台 -> 自定义 -> 流程页面修改。'; $lang->custom->notice->readOnlyOfProduct = '禁止修改后,已关闭' . $lang->productCommon . '下的' . $lang->SRCommon . '、Bug、用例、日志、发布、计划都禁止修改。'; $lang->custom->notice->readOnlyOfExecution = "禁止修改后,已关闭{$lang->custom->execution}下的任务、版本、日志以及关联需求都禁止修改。"; +$lang->custom->notice->readOnlyOfKanban = "禁止修改后,已关闭{$lang->custom->kanban}下的卡片以及相关设置都禁止修改。"; $lang->custom->notice->URSREmpty = '自定义需求名称不能为空!'; $lang->custom->notice->confirmDelete = '您确定要删除吗?'; $lang->custom->notice->confirmReviewCase = '是否将待评审的用例修改为正常状态?'; @@ -232,6 +236,9 @@ $lang->custom->CRProduct[0] = '禁止修改'; $lang->custom->CRExecution[1] = '允许修改'; $lang->custom->CRExecution[0] = '禁止修改'; +$lang->custom->CRKanban[1] = '允许修改'; +$lang->custom->CRKanban[0] = '禁止修改'; + $lang->custom->moduleName['product'] = $lang->productCommon; $lang->custom->moduleName['productplan'] = '计划'; $lang->custom->moduleName['execution'] = $lang->custom->execution; diff --git a/module/custom/view/header.html.php b/module/custom/view/header.html.php index a74dcd2e93..26b58c1e3f 100644 --- a/module/custom/view/header.html.php +++ b/module/custom/view/header.html.php @@ -5,8 +5,8 @@ foreach($lang->custom->object as $object => $name) { if(strpos('story|todo|block', $object) !== false) echo ""; - if(strpos('execution|product', $object) !== false) common::printLink('custom', $object, "", "{$lang->custom->$object}", '', "class='btn btn-link' id='{$object}Tab'"); - if(strpos('execution|product', $object) === false) common::printLink('custom', 'set', "module=$object&field=" . key($lang->custom->{$object}->fields), "{$name}", '', "class='btn btn-link' id='{$object}Tab'"); + if(strpos('execution|product|kanban', $object) !== false) common::printLink('custom', $object, "", "{$lang->custom->$object}", '', "class='btn btn-link' id='{$object}Tab'"); + if(strpos('execution|product|kanban', $object) === false) common::printLink('custom', 'set', "module=$object&field=" . key($lang->custom->{$object}->fields), "{$name}", '', "class='btn btn-link' id='{$object}Tab'"); if($object == 'user') common::printLink('custom', 'required', "", "{$lang->custom->required}", '', "class='btn btn-link' id='requiredTab'"); } diff --git a/module/kanban/control.php b/module/kanban/control.php index 72fc0b3a02..3436377707 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -741,6 +741,9 @@ class kanban extends control } } + $region = $this->kanban->getRegionByID($regionID); + + $this->view->kanban = $this->kanban->getByID($region->kanban); $this->view->columns = $columnsData; $this->display(); diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 7ac9f595fd..c3d5ff4403 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -40,6 +40,7 @@ function fullScreen() $('.action').hide(); $('.kanban-group-header').hide(); $(".title").attr("disabled", true).css("pointer-events", "none"); + $('.kanban-col.kanban-header-col').css('padding', '0px 0px 0px 0px'); window.sortableDisabled = true; $.cookie('isFullScreen', 1); }; @@ -76,12 +77,15 @@ function fullScreen() */ function exitFullScreen() { + $('.region-actions > div > .action').show(); + if(kanban.status == 'closed') return; $('#kanbanContainer').removeClass('fullscreen') .off('scroll', tryUpdateKanbanAffix); $('.actions').show(); $('.action').show(); $('.kanban-group-header').show(); $(".title").attr("disabled", false).css("pointer-events", "auto"); + $('.kanban-col.kanban-header-col').css('padding', '0px 30px'); window.sortableDisabled = false; $.cookie('isFullScreen', 0); } @@ -1408,6 +1412,12 @@ $(function() initSortable(); resetRegionHeight('open'); + + if(!CRKanban && kanban.status == "closed") + { + fullScreen(); + $('.region-actions > div > .action').show(); + } }); function initSortable() diff --git a/module/kanban/model.php b/module/kanban/model.php index 68e3c05c69..a9e6e2dc40 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -2940,24 +2940,26 @@ class kanbanModel extends model $actions .= "
                    "; $actions .= " {$this->lang->kanban->fullScreen}"; - $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeightBtn or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'delete')); + $CRKanban = ($this->config->CRKanban or $kanban->status != 'closed'); + $printRegionBtn = ($CRKanban and (common::hasPriv('kanban', 'createRegion') or $printSetHeightBtn or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'import') or common::hasPriv('kanban', 'setColumnWidth'))); + $printKanbanBtn = (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); - if($printSettingBtn) + if($printRegionBtn or $printKanbanBtn) { $actions .= "" . ' ' . $this->lang->kanban->setting . ''; $actions .= ""; } diff --git a/module/kanban/view/view.html.php b/module/kanban/view/view.html.php index 9f960fc8e2..455d9aa99b 100644 --- a/module/kanban/view/view.html.php +++ b/module/kanban/view/view.html.php @@ -21,6 +21,7 @@ $laneCount = 0; foreach($regions as $region) $laneCount += $region->laneCount; js::set('vision', $this->config->vision); +js::set('CRKanban', $this->config->CRKanban); js::set('regions', $regions); js::set('kanban', $kanban); js::set('kanbanLang', $lang->kanban); diff --git a/module/kanban/view/viewarchivedcard.html.php b/module/kanban/view/viewarchivedcard.html.php index 1a18aed718..ebe2f900fc 100644 --- a/module/kanban/view/viewarchivedcard.html.php +++ b/module/kanban/view/viewarchivedcard.html.php @@ -172,8 +172,9 @@ $app->loadLang('productplan');
                    performable) echo "id='performable'";?>> config->CRKanban or $kanban->status != 'closed'); + $canRestore = (commonModel::hasPriv('kanban', 'restoreCard') and $CRKanban); + $canDelete = (commonModel::hasPriv('kanban', 'deleteCard') and $CRKanban); if($canRestore) echo html::a(inlink('restoreCard', "cardID={$card->id}"), $lang->kanban->restore, '', "class='btn btn-xs btn-primary' target='hiddenwin'"); diff --git a/module/kanban/view/viewarchivedcolumn.html.php b/module/kanban/view/viewarchivedcolumn.html.php index 5db11bd570..ee70925597 100644 --- a/module/kanban/view/viewarchivedcolumn.html.php +++ b/module/kanban/view/viewarchivedcolumn.html.php @@ -35,7 +35,7 @@
                    name;?>
                    - archived == '1') echo html::a(inlink('restoreColumn', "columnID={$column->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?> + archived == '1' && ($this->config->CRKanban or $kanban->status != 'closed')) echo html::a(inlink('restoreColumn', "columnID={$column->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
                    child) && $column->archived == '0'):?> @@ -43,7 +43,7 @@ child) ? 'hr' : '';?>
                    name;?>
                    - archived == '1') echo html::a(inlink('restoreColumn', "columnID={$childColumn->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?> + archived == '1' && ($this->config->CRKanban or $kanban->status != 'closed')) echo html::a(inlink('restoreColumn', "columnID={$childColumn->id}"), $lang->kanban->restore, '', "class='btn btn-primary' target='hiddenwin'");?>
                    From 71cb47e7ebbdc053fd43ff7a230fd795fa478b5a Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 17 May 2022 14:51:13 +0800 Subject: [PATCH 083/304] * Finish task #54349. --- module/custom/view/kanban.html.php | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 module/custom/view/kanban.html.php diff --git a/module/custom/view/kanban.html.php b/module/custom/view/kanban.html.php new file mode 100644 index 0000000000..2bd85af67b --- /dev/null +++ b/module/custom/view/kanban.html.php @@ -0,0 +1,41 @@ + + * @package custom + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
                    + + + + + + + + + + + +
                    custom->closedKanban;?> + CRKanban) ? $config->CRKanban : 0;?> + custom->CRKanban as $key => $value):?> + + + custom->notice->readOnlyOfKanban;?>
                    + +
                    + +
                    + + From e2e88e49521dec5c4094a9ccb12b42537bb043d7 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 14:53:43 +0800 Subject: [PATCH 084/304] * Finish task #54391. --- module/action/lang/en.php | 2 +- module/action/lang/zh-cn.php | 2 +- module/kanban/control.php | 11 ++++-- module/kanban/lang/en.php | 1 + module/kanban/lang/zh-cn.php | 1 + module/kanban/model.php | 36 +++++++++++++++++++ module/kanban/view/sendmail.html.php | 34 ++++++++++++++++++ module/mail/model.php | 4 ++- module/message/config.php | 25 +++++++------ module/message/css/setting.css | 2 -- module/message/lang/en.php | 3 ++ module/message/lang/zh-cn.php | 3 ++ module/message/model.php | 1 + .../xuan/message/ext/config/xuanxuan.php | 12 ++++--- 14 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 module/kanban/view/sendmail.html.php diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 19cabc24e4..8c61aa03e5 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -162,7 +162,7 @@ $lang->action->desc->hidden = '$date, hidden by $actoraction->desc->commented = '$date, added by $actor.' . "\n"; $lang->action->desc->activated = '$date, activated by $actor .' . "\n"; $lang->action->desc->blocked = '$date, blocked by $actor .' . "\n"; -$lang->action->desc->moved = '$date, moved by $actor , which was "$extra".' . "\n"; +$lang->action->desc->moved = '$date, moved by $actor .' . "\n"; $lang->action->desc->confirmed = '$date, $actor confirmed the story change. The latest build is #$extra.' . "\n"; $lang->action->desc->caseconfirmed = '$date, $actor confirmed the case change. The latest build is #$extra' . "\n"; $lang->action->desc->bugconfirmed = '$date, $actor confirmed Bug.' . "\n"; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index b70a9b69bd..d43c3604f3 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -162,7 +162,7 @@ $lang->action->desc->hidden = '$date, 由 $actor $lang->action->desc->commented = '$date, 由 $actor 添加备注。' . "\n"; $lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; $lang->action->desc->blocked = '$date, 由 $actor 阻塞。' . "\n"; -$lang->action->desc->moved = '$date, 由 $actor 移动,之前为 "$extra"。' . "\n"; +$lang->action->desc->moved = '$date, 由 $actor 移动。' . "\n"; $lang->action->desc->confirmed = '$date, 由 $actor 确认' . $lang->SRCommon . '变动,最新版本为#$extra。' . "\n"; $lang->action->desc->caseconfirmed = '$date, 由 $actor 确认用例变动,最新版本为#$extra。' . "\n"; $lang->action->desc->bugconfirmed = '$date, 由 $actor 确认Bug。' . "\n"; diff --git a/module/kanban/control.php b/module/kanban/control.php index 72fc0b3a02..32d3943bcd 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -975,6 +975,9 @@ class kanban extends control { $this->kanban->moveCard($cardID, $fromColID, $toColID, $fromLaneID, $toLaneID, $kanbanID); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $this->loadModel('action')->create('kanbanCard', $cardID, 'moved'); + $kanbanGroup = $this->kanban->getKanbanData($kanbanID); echo json_encode($kanbanGroup); } @@ -1388,11 +1391,15 @@ class kanban extends control } else { - if($card->fromType == '') $this->kanban->delete(TABLE_KANBANCARD, $cardID); + if($card->fromType == '') + { + $this->kanban->delete(TABLE_KANBANCARD, $cardID); + $this->loadModel('action')->create('kanbancard', $cardID, 'Deleted', '', $cardID); + } + if($card->fromType != '') { $this->dao->delete()->from(TABLE_KANBANCARD)->where('id')->eq($cardID)->exec(); - $this->loadModel('action')->create('kanbancard', $cardID, 'Deleted', '', $cardID); } if(isonlybody()) return print(js::reload('parent.parent')); diff --git a/module/kanban/lang/en.php b/module/kanban/lang/en.php index cce018447c..0da9f49c01 100644 --- a/module/kanban/lang/en.php +++ b/module/kanban/lang/en.php @@ -334,6 +334,7 @@ $lang->kanbancard->delete = 'Delete'; $lang->kanbancard->name = 'Card Name'; $lang->kanbancard->legendBasicInfo = 'Basic Info'; $lang->kanbancard->legendLifeTime = 'Card Life'; +$lang->kanbancard->legendDesc = 'Card Description'; $lang->kanbancard->space = 'Space'; $lang->kanbancard->region = 'Region'; $lang->kanbancard->kanban = 'Kanban'; diff --git a/module/kanban/lang/zh-cn.php b/module/kanban/lang/zh-cn.php index 00a8305975..154fd13465 100644 --- a/module/kanban/lang/zh-cn.php +++ b/module/kanban/lang/zh-cn.php @@ -334,6 +334,7 @@ $lang->kanbancard->delete = '删除'; $lang->kanbancard->name = '卡片名称'; $lang->kanbancard->legendBasicInfo = '基本信息'; $lang->kanbancard->legendLifeTime = '卡片的一生'; +$lang->kanbancard->legendDesc = '卡片描述'; $lang->kanbancard->space = '所属空间'; $lang->kanbancard->region = '所属区域'; $lang->kanbancard->kanban = '所属看板'; diff --git a/module/kanban/model.php b/module/kanban/model.php index 68e3c05c69..c0639e484a 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -3572,6 +3572,42 @@ class kanbanModel extends model return $menus; } + /** + * Get toList and ccList. + * + * @param object $card + * @access public + * @return bool|array + */ + public function getToAndCcList($card) + { + /* Set toList and ccList. */ + $toList = $card->createdBy; + $ccList = trim($card->assignedTo, ','); + if(strpos(",$ccList,", ",$card->createdBy,") === false) + { + $ccList .= ",$card->createdBy"; + } + + if(empty($toList)) + { + if(empty($ccList)) return false; + if(strpos($ccList, ',') === false) + { + $toList = $ccList; + $ccList = ''; + } + else + { + $commaPos = strpos($ccList, ','); + $toList = substr($ccList, 0, $commaPos); + $ccList = substr($ccList, $commaPos + 1); + } + } + + return array($toList, $ccList); + } + /** * Check if user can execute an action. * diff --git a/module/kanban/view/sendmail.html.php b/module/kanban/view/sendmail.html.php new file mode 100644 index 0000000000..939287afb9 --- /dev/null +++ b/module/kanban/view/sendmail.html.php @@ -0,0 +1,34 @@ + + * @package kanban + * @version $Id: sendmail.html.php 867 2022-05-17 13:50:58Z $ + * @link https://www.zentao.net + */ +?> +id . ' ' . $object->name;?> +app->getModuleRoot() . 'common/view/mail.header.html.php';?> +
                    + + + + +
                    + kanban", 'html'), $mailTitle, '', "style='color: #333; text-decoration: underline;'");?> +
                    +
                    +
                    + lang->kanbancard->legendDesc;?> +
                    desc;?>
                    +
                    +
                    productplan->parent;?> title;?> - begin);?> - end);?>
                    productplan->last . ': ' . $lastPlan->title . ')';?>
                    productplan->parent;?> '') + $parentPlanPairs, '', "class='form-control chosen'");?> +
                    productplan->begin;?>
                    productplan->title;?> title, "class='form-control' required");?>
                    productplan->parent;?> '') + $parentPlanPairs, $plan->parent, "class='form-control chosen'");?> +
                    productplan->status;?>
                    diff --git a/module/user/control.php b/module/user/control.php index 2c7a00be88..fbdfe74293 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -538,14 +538,15 @@ class user extends control $title = $this->lang->company->common . $this->lang->colon . $this->lang->user->create; $position[] = $this->lang->user->create; - $this->view->title = $title; - $this->view->position = $position; - $this->view->depts = $this->dept->getOptionMenu(); - $this->view->groupList = $groupList; - $this->view->roleGroup = $roleGroup; - $this->view->deptID = $deptID; - $this->view->rand = $this->user->updateSessionRandom(); - $this->view->companies = $this->loadModel('company')->getOutsideCompanies(); + $this->view->title = $title; + $this->view->gobackLink = $this->createLink('company', 'browse'); + $this->view->position = $position; + $this->view->depts = $this->dept->getOptionMenu(); + $this->view->groupList = $groupList; + $this->view->roleGroup = $roleGroup; + $this->view->deptID = $deptID; + $this->view->rand = $this->user->updateSessionRandom(); + $this->view->companies = $this->loadModel('company')->getOutsideCompanies(); $this->display(); } diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index 35f26e1182..9f0ef23954 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -111,7 +111,7 @@ $showVisionList = count($visionList) > 1;
                    config->vision);?> - + goback, '', 'class="btn btn-wide"')?>
                    From 40f4e808daeefac86274a2be3582393bf7337098 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 17 May 2022 15:43:15 +0800 Subject: [PATCH 092/304] * Finish task #54354. --- module/custom/config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/custom/config.php b/module/custom/config.php index 9b42284642..c95872d315 100644 --- a/module/custom/config.php +++ b/module/custom/config.php @@ -56,8 +56,8 @@ $config->custom->fieldList['build'] = 'scmPath,filePath,desc'; $config->custom->fieldList['bug']['create'] = 'module,project,deadline,type,os,browser,severity,pri,steps,keywords'; $config->custom->fieldList['bug']['edit'] = 'plan,project,assignedTo,deadline,type,os,browser,severity,pri,steps,keywords'; $config->custom->fieldList['bug']['resolve'] = 'resolvedBuild,resolvedDate,assignedTo,comment'; -$config->custom->fieldList['testcase']['create'] = 'stage,story,pri,precondition,keywords'; -$config->custom->fieldList['testcase']['edit'] = 'stage,story,pri,precondition,keywords,status'; +$config->custom->fieldList['testcase']['create'] = 'stage,story,pri,precondition,keywords,module'; +$config->custom->fieldList['testcase']['edit'] = 'stage,story,pri,precondition,keywords,status,module'; $config->custom->fieldList['testsuite'] = 'desc'; $config->custom->fieldList['caselib'] = 'desc'; $config->custom->fieldList['testcase']['createcase'] = 'lib,stage,pri,precondition,keywords'; From 22cc7108e20f2b4ffc6b1afa36100b08dd91851b Mon Sep 17 00:00:00 2001 From: mayue Date: Tue, 17 May 2022 07:45:19 +0000 Subject: [PATCH 093/304] * Optimize code task#54191. --- module/productplan/js/create.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/productplan/js/create.js b/module/productplan/js/create.js index e9ecce37c7..dd3bcd3ebc 100644 --- a/module/productplan/js/create.js +++ b/module/productplan/js/create.js @@ -66,17 +66,17 @@ $('#future').on('change', function() $('#branch').change(function() { var branchID = $(this).val(); - var getLastLink = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchID); - var getTopPlanLink = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branchID); + var lastPlanLink = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchID); + var topPlanLink = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branchID); - $.post(getLastLink, function(data) + $.post(lastPlanLink, function(data) { data = JSON.parse(data); var planTitle = data ? '(' + lastLang + ': ' + data.title + ')' : ''; $('#title').parent().next('td').html(planTitle); }) - $.post(getTopPlanLink, function(data) + $.post(topPlanLink, function(data) { $('#parent').replaceWith(data); $('#parent_chosen').remove(); From 8a06d71cfd01525122c0ed4f590e221a6abacf21 Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 17 May 2022 07:46:52 +0000 Subject: [PATCH 094/304] * Finish task#54192,54196 --- module/execution/model.php | 16 +++++++--------- module/program/js/edit.js | 8 +++++--- module/program/model.php | 1 + module/project/model.php | 24 ++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index 30da5f61e6..8a0a562f5a 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -2008,17 +2008,15 @@ class executionModel extends model */ public function getTasks2Imported($toExecution, $branches) { - $products = $this->loadModel('product')->getProducts($toExecution); - if(empty($products)) return array(); + $execution = $this->getById($toExecution); + $project = $this->loadModel('project')->getById($execution->project); + $brotherProjects = $this->project->getBrotherProjects($project); + $executions = $this->dao->select('id')->from(TABLE_EXECUTION) + ->where('project')->in(array_keys($brotherProjects)) + ->andWhere('status')->ne('closed') + ->fetchPairs('id'); - $execution = $this->getById($toExecution); - $executions = $this->dao->select('t1.product, t1.project')->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project=t2.id') - ->where('t1.product')->in(array_keys($products)) - ->andWhere('t2.project')->eq($execution->project) - ->fetchGroup('project'); $branches = str_replace(',', "','", $branches); - $tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName')->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') diff --git a/module/program/js/edit.js b/module/program/js/edit.js index df353f8db3..285a5ab56a 100644 --- a/module/program/js/edit.js +++ b/module/program/js/edit.js @@ -79,7 +79,9 @@ $(function() $('#changeUnitTip').modal('hide'); }) - /* If end is longtime, set the default date to today */ - var today = $.zui.formatDate(new Date(), 'yyyy-MM-dd'); - if($('#end').val() == longTime) $('#end').val(today).datetimepicker('update').val(longTime); + /* If end is longtime, set the default date to today */ + var today = $.zui.formatDate(new Date(), 'yyyy-MM-dd'); + if($('#end').val() == longTime) $('#end').val(today).datetimepicker('update').val(longTime); + + $('#realBegan').datetimepicker('setEndDate', today); }); diff --git a/module/program/model.php b/module/program/model.php index 8978cae49f..78f73db1f6 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -754,6 +754,7 @@ class programModel extends model ->setIF($this->post->begin == '0000-00-00', 'begin', '') ->setIF($this->post->end == '0000-00-00', 'end', '') ->setIF($this->post->delta == 999, 'end', LONG_TIME) + ->setIF($this->post->realBegan != '' and $oldProgram->status == 'wait', 'status', 'doing') ->setIF($this->post->future, 'budget', 0) ->setIF($this->post->budget != 0, 'budget', round($this->post->budget, 2)) ->setIF(!isset($_POST['budgetUnit']), 'budgetUnit', $oldProgram->budgetUnit) diff --git a/module/project/model.php b/module/project/model.php index 79b9e6acfc..d3d9544f00 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -700,6 +700,30 @@ class projectModel extends model ->fetchPairs(); } + /** + * Get all the projects under the program set to which an project belongs. + * + * @param object $project + * @access public + * @return void + */ + public function getBrotherProjects($project) + { + $projectIds = array_filter(explode(',', $project->path)); + $parentProgram = $this->dao->select('*')->from(TABLE_PROGRAM) + ->where('id')->in($projectIds) + ->andWhere('`type`')->eq('program') + ->orderBy('grade desc') + ->fetch(); + + $projects = $this->dao->select('*')->from(TABLE_PROJECT) + ->where('type')->eq('project') + ->andWhere('deleted')->eq(0) + ->andWhere('path')->like("{$parentProgram->path}%") + ->fetchAll('id'); + return $projects; + } + /** * Get project by id list. * From d0340d56661f604f4d33f84eab95b34bc7cd3155 Mon Sep 17 00:00:00 2001 From: mayue Date: Tue, 17 May 2022 07:47:50 +0000 Subject: [PATCH 095/304] * Optimize code. --- module/productplan/js/create.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/productplan/js/create.js b/module/productplan/js/create.js index dd3bcd3ebc..bbf0718f74 100644 --- a/module/productplan/js/create.js +++ b/module/productplan/js/create.js @@ -65,7 +65,7 @@ $('#future').on('change', function() $('#branch').change(function() { - var branchID = $(this).val(); + var branchID = $(this).val(); var lastPlanLink = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchID); var topPlanLink = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branchID); From c097334f3bb895c987d402e3b327246935e6f212 Mon Sep 17 00:00:00 2001 From: zhouxudong Date: Tue, 17 May 2022 07:58:26 +0000 Subject: [PATCH 096/304] * Finish task #54480. --- module/my/view/team.html.php | 8 ++++---- module/user/control.php | 17 ++++++++--------- module/user/view/create.html.php | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/module/my/view/team.html.php b/module/my/view/team.html.php index df72944d97..b253907ba1 100644 --- a/module/my/view/team.html.php +++ b/module/my/view/team.html.php @@ -13,11 +13,11 @@ +
                    - -
                    +
                    diff --git a/module/user/control.php b/module/user/control.php index fbdfe74293..2c7a00be88 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -538,15 +538,14 @@ class user extends control $title = $this->lang->company->common . $this->lang->colon . $this->lang->user->create; $position[] = $this->lang->user->create; - $this->view->title = $title; - $this->view->gobackLink = $this->createLink('company', 'browse'); - $this->view->position = $position; - $this->view->depts = $this->dept->getOptionMenu(); - $this->view->groupList = $groupList; - $this->view->roleGroup = $roleGroup; - $this->view->deptID = $deptID; - $this->view->rand = $this->user->updateSessionRandom(); - $this->view->companies = $this->loadModel('company')->getOutsideCompanies(); + $this->view->title = $title; + $this->view->position = $position; + $this->view->depts = $this->dept->getOptionMenu(); + $this->view->groupList = $groupList; + $this->view->roleGroup = $roleGroup; + $this->view->deptID = $deptID; + $this->view->rand = $this->user->updateSessionRandom(); + $this->view->companies = $this->loadModel('company')->getOutsideCompanies(); $this->display(); } diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index 9f0ef23954..71cab7c1a0 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -111,7 +111,7 @@ $showVisionList = count($visionList) > 1;
                    config->vision);?> - goback, '', 'class="btn btn-wide"')?> + createLink('company', 'browse'), $lang->goback, '', 'class="btn btn-wide"')?>
                    From bf6ba1ee20e56a5ffe9bcd2a57d8cf38f747b1ec Mon Sep 17 00:00:00 2001 From: zhouxudong Date: Tue, 17 May 2022 08:00:31 +0000 Subject: [PATCH 097/304] * Finish task #54480. --- module/my/css/team.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/my/css/team.css b/module/my/css/team.css index 9c05ff4789..cc48190d78 100644 --- a/module/my/css/team.css +++ b/module/my/css/team.css @@ -1,4 +1,2 @@ .c-gender {width: 80px;} .c-phone, .c-skype, .c-visits {width: 100px;} -#mainMenu {margin: -10px 0 8px; float:right} -#mainContent {float:left} From 268d3c3bcf05d31c824466b76c7a5768d1d3b2de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 17 May 2022 16:04:39 +0800 Subject: [PATCH 098/304] * Finish task #54218. --- module/execution/view/all.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 75db4158ef..102388d861 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -132,7 +132,7 @@ $onlyChildStage = ($execution->grade == 2 and $execution->project != $execution->parent); if($onlyChildStage and isset($parents[$execution->parent])) $executionName = $parents[$execution->parent]->name . '/' . $executionName; ?> - flex' title=''> + flex' title=''> systemMode == 'new'):?> '>execution->typeList[$execution->type]?> From 925aa3f8d8c13ef356db6316f8e21666c12cf284 Mon Sep 17 00:00:00 2001 From: zhouxudong Date: Tue, 17 May 2022 08:12:27 +0000 Subject: [PATCH 099/304] * Finish task #54480. --- module/my/view/team.html.php | 4 +++- module/user/view/create.html.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/module/my/view/team.html.php b/module/my/view/team.html.php index b253907ba1..c99df1ccde 100644 --- a/module/my/view/team.html.php +++ b/module/my/view/team.html.php @@ -14,7 +14,9 @@ include '../../common/view/header.html.php'; ?>
                    diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index 71cab7c1a0..8d248a899d 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -111,7 +111,7 @@ $showVisionList = count($visionList) > 1; config->vision);?> - createLink('company', 'browse'), $lang->goback, '', 'class="btn btn-wide"')?> + createLink('company', 'browse'), $lang->goback, '', "class='btn btn-wide'")?> From 9887a64cfb6a262f8f8975ce1308d031a8c199fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 16:12:53 +0800 Subject: [PATCH 100/304] *Fix bug #22375. --- module/task/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index f04071e1dc..e74b70e6b0 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1022,7 +1022,7 @@ class taskModel extends model $requiredFields = str_replace(',estimate,', ',', $requiredFields); } - if(strpos(',doing,pause,', $task->status) && empty($teams) && empty($task->left)) + if(strpos(',doing,pause,', $task->status) && empty($task->left)) { dao::$errors[] = sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]); return false; From aef54696eca48d2c44ba1cf68201974573f48103 Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 17 May 2022 08:21:49 +0000 Subject: [PATCH 101/304] * Adjust code --- module/project/model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/project/model.php b/module/project/model.php index d3d9544f00..7f381a0c3a 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -709,6 +709,8 @@ class projectModel extends model */ public function getBrotherProjects($project) { + if($project->parent == 0) return array($project->id => $project); + $projectIds = array_filter(explode(',', $project->path)); $parentProgram = $this->dao->select('*')->from(TABLE_PROGRAM) ->where('id')->in($projectIds) From 5bb5dfce548708205ce67c0d3ad98ae8dc5ef348 Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 17 May 2022 08:44:50 +0000 Subject: [PATCH 102/304] * Adjust code --- module/project/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/project/model.php b/module/project/model.php index 7f381a0c3a..af675d3055 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -718,11 +718,11 @@ class projectModel extends model ->orderBy('grade desc') ->fetch(); - $projects = $this->dao->select('*')->from(TABLE_PROJECT) + $projects = $this->dao->select('id')->from(TABLE_PROJECT) ->where('type')->eq('project') ->andWhere('deleted')->eq(0) ->andWhere('path')->like("{$parentProgram->path}%") - ->fetchAll('id'); + ->fetchPairs('id'); return $projects; } From dfa70c678b1e50367f78dd050cda6768ca4210e5 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 17 May 2022 16:51:19 +0800 Subject: [PATCH 103/304] * Finish task #54349. --- module/custom/view/kanban.html.php | 2 +- module/group/lang/resource.php | 1 + module/kanban/js/view.js | 3 ++- module/kanban/model.php | 2 +- module/kanban/view/viewcard.html.php | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/module/custom/view/kanban.html.php b/module/custom/view/kanban.html.php index 2bd85af67b..787c1b1eea 100644 --- a/module/custom/view/kanban.html.php +++ b/module/custom/view/kanban.html.php @@ -16,7 +16,7 @@ custom->closedKanban;?> - CRKanban) ? $config->CRKanban : 0;?> + CRKanban) ? $config->CRKanban : 1;?> custom->CRKanban as $key => $value):?> diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 953c7b9aed..3df0680181 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1270,6 +1270,7 @@ $lang->resource->custom->editStoryConcept = 'editStoryConcept'; $lang->resource->custom->browseStoryConcept = 'browseStoryConcept'; $lang->resource->custom->setDefaultConcept = 'setDefaultConcept'; $lang->resource->custom->deleteStoryConcept = 'deleteStoryConcept'; +$lang->resource->custom->kanban = 'kanban'; $lang->custom->methodOrder[5] = 'index'; $lang->custom->methodOrder[10] = 'set'; diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index c3d5ff4403..3a214e9595 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -78,13 +78,13 @@ function fullScreen() function exitFullScreen() { $('.region-actions > div > .action').show(); + $(".title").attr("disabled", false).css("pointer-events", "auto"); if(kanban.status == 'closed') return; $('#kanbanContainer').removeClass('fullscreen') .off('scroll', tryUpdateKanbanAffix); $('.actions').show(); $('.action').show(); $('.kanban-group-header').show(); - $(".title").attr("disabled", false).css("pointer-events", "auto"); $('.kanban-col.kanban-header-col').css('padding', '0px 30px'); window.sortableDisabled = false; $.cookie('isFullScreen', 0); @@ -1417,6 +1417,7 @@ $(function() { fullScreen(); $('.region-actions > div > .action').show(); + $(".title").attr("disabled", false).css("pointer-events", "auto"); } }); diff --git a/module/kanban/model.php b/module/kanban/model.php index a9e6e2dc40..dfba3b54a5 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -2940,7 +2940,7 @@ class kanbanModel extends model $actions .= "
                    "; $actions .= " {$this->lang->kanban->fullScreen}"; - $CRKanban = ($this->config->CRKanban or $kanban->status != 'closed'); + $CRKanban = !($this->config->CRKanban === '0' and $kanban->status === 'closed'); $printRegionBtn = ($CRKanban and (common::hasPriv('kanban', 'createRegion') or $printSetHeightBtn or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'import') or common::hasPriv('kanban', 'setColumnWidth'))); $printKanbanBtn = (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); diff --git a/module/kanban/view/viewcard.html.php b/module/kanban/view/viewcard.html.php index fe05b9f6fd..2f2c191868 100644 --- a/module/kanban/view/viewcard.html.php +++ b/module/kanban/view/viewcard.html.php @@ -34,7 +34,7 @@
                    - deleted and !$card->archived):?> + deleted and !$card->archived and !($this->config->CRKanban === '0' and $kanban->status === 'closed')):?> id", "{$lang->kanbancard->assign}", '', "class='btn btn-link iframe' title='{$lang->kanbancard->assign}'", true, true); if($kanban->archived) From 56363dbfeb5fffc4a9c1ac7b13d772407edac1d3 Mon Sep 17 00:00:00 2001 From: zenggang Date: Tue, 17 May 2022 08:52:33 +0000 Subject: [PATCH 104/304] * Adjust code --- module/execution/model.php | 2 +- module/project/model.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index 8a0a562f5a..69d78ba413 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -2012,7 +2012,7 @@ class executionModel extends model $project = $this->loadModel('project')->getById($execution->project); $brotherProjects = $this->project->getBrotherProjects($project); $executions = $this->dao->select('id')->from(TABLE_EXECUTION) - ->where('project')->in(array_keys($brotherProjects)) + ->where('project')->in($brotherProjects) ->andWhere('status')->ne('closed') ->fetchPairs('id'); diff --git a/module/project/model.php b/module/project/model.php index af675d3055..0020701820 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -709,7 +709,7 @@ class projectModel extends model */ public function getBrotherProjects($project) { - if($project->parent == 0) return array($project->id => $project); + if($project->parent == 0) return array($project->id => $project->id); $projectIds = array_filter(explode(',', $project->path)); $parentProgram = $this->dao->select('*')->from(TABLE_PROGRAM) From 7ce0103bbadcdc1c730526cde2201cb27af25e0d Mon Sep 17 00:00:00 2001 From: sunjun Date: Tue, 17 May 2022 08:59:11 +0000 Subject: [PATCH 105/304] sprint_sunjun_54321 --- module/my/control.php | 10 +++++++++- module/my/lang/de.php | 2 +- module/my/lang/en.php | 1 + module/my/lang/fr.php | 1 + module/my/lang/zh-cn.php | 1 + module/my/lang/zh-tw.php | 1 + module/my/model.php | 28 ++++++++++++++++++++++++++++ module/my/view/task.html.php | 9 +++++---- 8 files changed, 47 insertions(+), 6 deletions(-) diff --git a/module/my/control.php b/module/my/control.php index 4738673f24..95aacc972f 100644 --- a/module/my/control.php +++ b/module/my/control.php @@ -392,6 +392,7 @@ EOF; */ public function task($type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { + $this->loadModel('task'); /* Save session. */ if($this->app->viewType != 'json') $this->session->set('taskList', $this->app->getURI(true), 'execution'); @@ -404,7 +405,14 @@ EOF; $sort = common::appendOrder($orderBy); /* Get tasks. */ - $tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $type, 0, $pager, $sort); + if($type == 'assignedBy') + { + $tasks = $this->my->getAssignedByMe($this->app->user->account, $type, 0, $pager, $sort, 0, 'task'); + } + else + { + $tasks = $this->task->getUserTasks($this->app->user->account, $type, 0, $pager, $sort); + } $parents = array(); $executionIDList = array(); diff --git a/module/my/lang/de.php b/module/my/lang/de.php index b558580030..ae56776df9 100644 --- a/module/my/lang/de.php +++ b/module/my/lang/de.php @@ -56,7 +56,7 @@ $lang->my->taskMenu->assignedToMe = 'AssignedToMe'; $lang->my->taskMenu->openedByMe = 'CreatedByMe'; $lang->my->taskMenu->finishedByMe = 'FinishedByMe'; $lang->my->taskMenu->closedByMe = 'ClosedByMe'; -$lang->my->taskMenu->canceledByMe = 'CancelledByMe'; +$lang->my->taskMenu->assignedByMe = 'AssignedByMe'; $lang->my->storyMenu = new stdclass(); $lang->my->storyMenu->assignedToMe = 'AssignedToMe'; diff --git a/module/my/lang/en.php b/module/my/lang/en.php index 4705823a20..f97a214255 100644 --- a/module/my/lang/en.php +++ b/module/my/lang/en.php @@ -66,6 +66,7 @@ $lang->my->taskMenu->openedByMe = 'CreatedByMe'; $lang->my->taskMenu->finishedByMe = 'FinishedByMe'; $lang->my->taskMenu->closedByMe = 'ClosedByMe'; $lang->my->taskMenu->canceledByMe = 'CancelledByMe'; +$lang->my->taskMenu->assignedByMe = 'AssignedByMe'; $lang->my->storyMenu = new stdclass(); $lang->my->storyMenu->assignedToMe = 'AssignedToMe'; diff --git a/module/my/lang/fr.php b/module/my/lang/fr.php index b558580030..a1020163b0 100644 --- a/module/my/lang/fr.php +++ b/module/my/lang/fr.php @@ -57,6 +57,7 @@ $lang->my->taskMenu->openedByMe = 'CreatedByMe'; $lang->my->taskMenu->finishedByMe = 'FinishedByMe'; $lang->my->taskMenu->closedByMe = 'ClosedByMe'; $lang->my->taskMenu->canceledByMe = 'CancelledByMe'; +$lang->my->taskMenu->assignedByMe = 'AssignedByMe'; $lang->my->storyMenu = new stdclass(); $lang->my->storyMenu->assignedToMe = 'AssignedToMe'; diff --git a/module/my/lang/zh-cn.php b/module/my/lang/zh-cn.php index 93e5ddba0d..763e49b434 100644 --- a/module/my/lang/zh-cn.php +++ b/module/my/lang/zh-cn.php @@ -66,6 +66,7 @@ $lang->my->taskMenu->openedByMe = '由我创建'; $lang->my->taskMenu->finishedByMe = '由我完成'; $lang->my->taskMenu->closedByMe = '由我关闭'; $lang->my->taskMenu->canceledByMe = '由我取消'; +$lang->my->taskMenu->assignedByMe = '由我指派'; $lang->my->storyMenu = new stdclass(); $lang->my->storyMenu->assignedToMe = '指派给我'; diff --git a/module/my/lang/zh-tw.php b/module/my/lang/zh-tw.php index 9bbe89a5ba..dc42ee55d2 100644 --- a/module/my/lang/zh-tw.php +++ b/module/my/lang/zh-tw.php @@ -65,6 +65,7 @@ $lang->my->taskMenu->openedByMe = '由我創建'; $lang->my->taskMenu->finishedByMe = '由我完成'; $lang->my->taskMenu->closedByMe = '由我關閉'; $lang->my->taskMenu->canceledByMe = '由我取消'; +$lang->my->taskMenu->assignedByMe = '由我指派'; $lang->my->storyMenu = new stdclass(); $lang->my->storyMenu->assignedToMe = '指派給我'; diff --git a/module/my/model.php b/module/my/model.php index 3941377e1e..7f059f8f9d 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -309,4 +309,32 @@ class myModel extends model return $actions; } + public function getAssignedByMe($account, $type = 'assignedBy', $limit = 0, $pager = null, $orderBy = "id_desc", $projectID = 0, $objectType = '') + { + $this->loadModel($objectType); + $objectList = $this->dao->select('t1.*') + ->from($this->config->objectTables[$objectType])->alias('t1') + ->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id = t2.objectID and t2.objectType='{$objectType}'") + ->where('t2.actor')->eq($account) + ->andWhere('t2.action')->eq('assigned') + ->andWhere('t1.deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager, 't1.id') + ->fetchAll('id'); + if($objectType == 'task') + { + $projectList = array(); + foreach($objectList as $task) $projectList[$task->project] = $task->project; + $projectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('id')->in($projectList)->fetchPairs('id'); + foreach($objectList as $task) $task->projectName = zget($projectPairs, $task->project); + + $executionList = array(); + foreach($objectList as $task) $executionList[$task->execution] = $task->execution; + $executionPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('id')->in($executionList)->fetchPairs('id'); + foreach($objectList as $task) $task->executionName = zget($executionPairs, $task->execution); + + if($objectList) return $this->loadModel('task')->processTasks($objectList); + return array(); + } + } } diff --git a/module/my/view/task.html.php b/module/my/view/task.html.php index 68520fe242..54b0acd24d 100644 --- a/module/my/view/task.html.php +++ b/module/my/view/task.html.php @@ -20,10 +20,11 @@ {$pager->recTotal}"; ?> rawMethod == 'contribute'):?> rawMethod, "mode=$mode&type=openedBy"), "{$lang->my->taskMenu->openedByMe}" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'"); - echo html::a(inlink($app->rawMethod, "mode=$mode&type=finishedBy"), "{$lang->my->taskMenu->finishedByMe}" . ($type == 'finishedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'finishedBy' ? ' btn-active-text' : '') . "'"); - echo html::a(inlink($app->rawMethod, "mode=$mode&type=closedBy"), "{$lang->my->taskMenu->closedByMe}" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'"); - echo html::a(inlink($app->rawMethod, "mode=$mode&type=canceledBy"), "{$lang->my->taskMenu->canceledByMe}" . ($type == 'canceledBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'canceledBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=$mode&type=openedBy"), "{$lang->my->taskMenu->openedByMe}" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=$mode&type=finishedBy"), "{$lang->my->taskMenu->finishedByMe}" . ($type == 'finishedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'finishedBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=$mode&type=closedBy"), "{$lang->my->taskMenu->closedByMe}" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=$mode&type=canceledBy"), "{$lang->my->taskMenu->canceledByMe}" . ($type == 'canceledBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'canceledBy' ? ' btn-active-text' : '') . "'"); + echo html::a(inlink($app->rawMethod, "mode=$mode&type=assignedBy"), "{$lang->my->taskMenu->assignedByMe}" . ($type == 'assignedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedBy' ? ' btn-active-text' : '') . "'"); ?>
                    From c0d9625c1dc4a8de46973ed5ed85ce7eb9fbb3e3 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 17 May 2022 17:07:36 +0800 Subject: [PATCH 106/304] * Add testcase of kanban module. --- module/action/lang/en.php | 2 +- module/kanban/model.php | 5 +---- test/class/kanban.class.php | 16 ++++++++++++++++ test/model/kanban/gettoandcclist.php | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100755 test/model/kanban/gettoandcclist.php diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 8c61aa03e5..615656a4b0 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -162,7 +162,7 @@ $lang->action->desc->hidden = '$date, hidden by $actoraction->desc->commented = '$date, added by $actor.' . "\n"; $lang->action->desc->activated = '$date, activated by $actor .' . "\n"; $lang->action->desc->blocked = '$date, blocked by $actor .' . "\n"; -$lang->action->desc->moved = '$date, moved by $actor .' . "\n"; +$lang->action->desc->moved = '$date, moved by $actor .' . "\n"; $lang->action->desc->confirmed = '$date, $actor confirmed the story change. The latest build is #$extra.' . "\n"; $lang->action->desc->caseconfirmed = '$date, $actor confirmed the case change. The latest build is #$extra' . "\n"; $lang->action->desc->bugconfirmed = '$date, $actor confirmed Bug.' . "\n"; diff --git a/module/kanban/model.php b/module/kanban/model.php index c0639e484a..20f3499ac0 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -3584,10 +3584,7 @@ class kanbanModel extends model /* Set toList and ccList. */ $toList = $card->createdBy; $ccList = trim($card->assignedTo, ','); - if(strpos(",$ccList,", ",$card->createdBy,") === false) - { - $ccList .= ",$card->createdBy"; - } + if(strpos(",$ccList,", ",$card->createdBy,") === false) $ccList .= ",$card->createdBy"; if(empty($toList)) { diff --git a/test/class/kanban.class.php b/test/class/kanban.class.php index 6e6e5adc1c..a11899708a 100644 --- a/test/class/kanban.class.php +++ b/test/class/kanban.class.php @@ -1733,6 +1733,22 @@ class kanbanTest return $count; } + /** + * Get toList and ccList. + * + * @param object $card + * @access public + * @return array + */ + public function getToAndCcListTest($card) + { + $objects = $this->objectModel->getToAndCcList($card); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + /** * Test check if user can execute an action. * diff --git a/test/model/kanban/gettoandcclist.php b/test/model/kanban/gettoandcclist.php new file mode 100755 index 0000000000..f987bfa4c1 --- /dev/null +++ b/test/model/kanban/gettoandcclist.php @@ -0,0 +1,19 @@ +#!/usr/bin/env php +getToAndCcList(); +cid=1 +pid=1 + +获取id=1的卡片发信人员 >> admin;admin + +*/ +$kanban = new kanbanTest(); + +$card = $kanban->getCardByIDTest('1'); +r($kanban->getToAndCcListTest($card)) && p('0;1') && e('admin;admin'); // 获取id=1的卡片发信人员 From 3099628ce164386af5af739970d06433cda9dda7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=8D=8E=E4=BC=9F?= Date: Tue, 17 May 2022 17:08:27 +0800 Subject: [PATCH 107/304] *Optimize the code. --- module/task/js/edit.js | 7 +++++-- module/task/model.php | 2 +- module/task/view/edit.html.php | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/module/task/js/edit.js b/module/task/js/edit.js index c8c8586921..bce67de89a 100644 --- a/module/task/js/edit.js +++ b/module/task/js/edit.js @@ -191,9 +191,12 @@ $('#confirmButton').click(function() if(memberCount < 2) { alert(teamMemberError); + return false; } - else + if(totalLeft == 0) { - $('.close').click(); + alert(totalLeftError); + return false; } + $('.close').click(); }); diff --git a/module/task/model.php b/module/task/model.php index e74b70e6b0..f04071e1dc 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1022,7 +1022,7 @@ class taskModel extends model $requiredFields = str_replace(',estimate,', ',', $requiredFields); } - if(strpos(',doing,pause,', $task->status) && empty($task->left)) + if(strpos(',doing,pause,', $task->status) && empty($teams) && empty($task->left)) { dao::$errors[] = sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]); return false; diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php index 8846d49488..964ef08841 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -22,6 +22,7 @@ team) < 6 ? 6 - count($task->team) : 1);?> task->error->teamMember);?> +lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
                    @@ -252,7 +253,7 @@