From 553c256574da9aaa598a15c7c774dc8add5f69ec Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 24 Sep 2011 16:14:10 +0100 Subject: [PATCH 1/5] Add support for config hashes in the admin settings page. --- webui/scripts/main.js | 39 +++++++++++++++++-- webui/source/pages/ajax/admin/add-setting.php | 4 ++ .../fragments/admin-setting-value.tpl | 18 +++++++++ .../fragments/new-setting-dialog.tpl | 1 + webui/styles/normal.css | 6 +++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/webui/scripts/main.js b/webui/scripts/main.js index e45dd74..a3296cf 100644 --- a/webui/scripts/main.js +++ b/webui/scripts/main.js @@ -280,11 +280,11 @@ var rc = { var line = $('
'); line.attr('id', 'settings_'+id+'_line'+next.val()); - line.append($('')); + line.append($('')); line.append(' '); var button = $(''); button.click(function() { - rc.settings.remove_field(id, next_value); + rc.settings.remove_stringlist_field(id, next_value); }); line.append(button); @@ -293,12 +293,43 @@ var rc = { // Increment the next counter next.val(parseInt(next_value)+1); - }, remove_stringlist_field: function(id, line) { $("#settings_"+id+"_line"+line).remove(); - }, + }, + + add_hash_field: function(id) { + var container = $('#container_'+id); + var next = $('#settings_'+id+'_next'); + var next_value = next.val(); + + var line = $('
'); + line.attr('id', 'settings_'+id+'_line'+next.val()); + + var hash_key = $(''); + var hash_value = $(''); + hash_key.change(function() { + $('#setting_'+id+'_value'+next_value).attr('name', id+'['+$(this).val()+']'); + }) + + line.append(hash_key).append(' ').append(hash_value).append(' '); + var button = $(''); + button.click(function() { + rc.settings.remove_hash_field(id, next_value); + }); + line.append(button); + + // Add the new item + container.append(line); + + // Increment the next counter + next.val(parseInt(next_value)+1); + }, + + remove_hash_field: function(id, line) { + $("#settings_"+id+"_line"+line).remove(); + }, save: function() { diff --git a/webui/source/pages/ajax/admin/add-setting.php b/webui/source/pages/ajax/admin/add-setting.php index 191c00d..1cc591c 100644 --- a/webui/source/pages/ajax/admin/add-setting.php +++ b/webui/source/pages/ajax/admin/add-setting.php @@ -30,6 +30,10 @@ try { $type = Sihnon_Config::TYPE_STRING_LIST; $value = array(); } break; + case 'hash': { + $type = Sihnon_Config::TYPE_HASH; + $value = array(); + } break; } // Add the new (empty) value. This is because no suitable UI has been presented yet. diff --git a/webui/source/templates/fragments/admin-setting-value.tpl b/webui/source/templates/fragments/admin-setting-value.tpl index 7ffcf9a..16a3dc1 100644 --- a/webui/source/templates/fragments/admin-setting-value.tpl +++ b/webui/source/templates/fragments/admin-setting-value.tpl @@ -22,4 +22,22 @@
{/case} + {case Sihnon_Config::TYPE_HASH} +
+ {foreach from=$value item=hash_value key=hash_key name=settings} +
+ + + +
+ {/foreach} +
+
+ + +
+ + {/case} + {default} + Unsupported setting type! {/switch} \ No newline at end of file diff --git a/webui/source/templates/fragments/new-setting-dialog.tpl b/webui/source/templates/fragments/new-setting-dialog.tpl index 59f67a0..fcea745 100644 --- a/webui/source/templates/fragments/new-setting-dialog.tpl +++ b/webui/source/templates/fragments/new-setting-dialog.tpl @@ -14,6 +14,7 @@ + diff --git a/webui/styles/normal.css b/webui/styles/normal.css index 773ab72..295a321 100644 --- a/webui/styles/normal.css +++ b/webui/styles/normal.css @@ -155,6 +155,12 @@ table#settings td { table#settings input[type=text] { width: 40em; } +table#settings input.hash_key { + width: 10em; +} +table#settings input.hash_value { + width: 25em; +} .settings_addfieldcontainer { text-align: right; } From 7477df269e980ca6bbc2a3b3f05c33f0549c78cb Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 24 Sep 2011 17:57:22 +0100 Subject: [PATCH 2/5] Add 3rdparty jquery/ui plugins --- .../images/jquery.progressbar/progressbar.gif | Bin 0 -> 120 bytes .../jquery.progressbar/progressbg_black.gif | Bin 0 -> 1626 bytes .../jquery.progressbar/progressbg_green.gif | Bin 0 -> 1308 bytes .../jquery.progressbar/progressbg_orange.gif | Bin 0 -> 1308 bytes .../jquery.progressbar/progressbg_red.gif | Bin 0 -> 1308 bytes .../jquery.progressbar/progressbg_yellow.gif | Bin 0 -> 1308 bytes webui/scripts/3rdparty/jquery.asmselect.js | 407 +++++++++ webui/scripts/3rdparty/jquery.jec-1.3.2.js | 851 ++++++++++++++++++ .../3rdparty/jquery.progressbar.min.js | 20 + webui/source/templates/index.tpl | 6 +- webui/styles/3rdparty/jquery.asmselect.css | 63 ++ 11 files changed, 1346 insertions(+), 1 deletion(-) create mode 100644 webui/images/jquery.progressbar/progressbar.gif create mode 100644 webui/images/jquery.progressbar/progressbg_black.gif create mode 100644 webui/images/jquery.progressbar/progressbg_green.gif create mode 100644 webui/images/jquery.progressbar/progressbg_orange.gif create mode 100644 webui/images/jquery.progressbar/progressbg_red.gif create mode 100644 webui/images/jquery.progressbar/progressbg_yellow.gif create mode 100644 webui/scripts/3rdparty/jquery.asmselect.js create mode 100644 webui/scripts/3rdparty/jquery.jec-1.3.2.js create mode 100644 webui/scripts/3rdparty/jquery.progressbar.min.js create mode 100644 webui/styles/3rdparty/jquery.asmselect.css diff --git a/webui/images/jquery.progressbar/progressbar.gif b/webui/images/jquery.progressbar/progressbar.gif new file mode 100644 index 0000000000000000000000000000000000000000..abe588c15c4eda53bcecc0ab00434c925cb1b45f GIT binary patch literal 120 zcmV-;0EhoaNk%w1VS4}!0FeLyVr61;d3%F}ga7~kA^8LW2LJ;AEC2ui0DAxo0006> zT!5*|?GK}zlnMie-n{z{hT=$;rU?ky$+qqbpGZvC_U+C1&iA733kq?-q4CHnBA3kE astJWEqtqebP|XTcn2Prc4vQz30suSWax&ro literal 0 HcmV?d00001 diff --git a/webui/images/jquery.progressbar/progressbg_black.gif b/webui/images/jquery.progressbar/progressbg_black.gif new file mode 100644 index 0000000000000000000000000000000000000000..74fd1f9b3e052e2ca18058526c39f6eaef580cba GIT binary patch literal 1626 zcmZ?wbhEHb{J_A&(9XcX%*^cP=jZS5KWEOIsZ*!+_xJbq_I7u7Po6xvt*x!5rlz8z zqNJpxtgNh|p`od%simc*s;a84uI|&PPaPc{A3uIfN=iydNQjM%jgODd%*;$nOG{5r zPf1CMh=_=aihB3%-TU|Nqobqm-@kwF-n}bVu3Wx+`ND+@=g*&K7zLvtFwh~O19AW; zFR*j`V_@Wv@z}87U^9oXR?LYF3lFz5DtXQE*tqCuw*)hXz=S}h<9!PDO?xyhJz`*D z4O(VWut2qOI!B0{$ASb#W;WiUS0x`FFt*GWkh>7GVDmxWIW~>o{;X7R3Y^O$!xGE2 zW!c5m?n{|?xfGc$uC^@nda-j$I@9_@X`hJG+t%LRUhw$TT<`7c?(VMOl(=zv(^Ez+ z)_`?6KN~d8Ei#|{Pv!T4mx&vAmrRO{u~_?biJiK1T}`Ob;|2cRNy~11T^2Z}B6xM& z*CcuP@U=g>N5ZM( z98XO4{d0SF-`>Bu_McUQ?(C+o7Z$Cay|*u7P0;2Y7oUIeF+2F_aKB{FS6)TOnlC~c zqEl)=t$cd7kwZ;GJb=$cqcL72V8Vg?Igw^z`NDPucLOi6M%>SzPmaB8WhqTXBHCGO?JoqBI#G|eBVX^Ka zj+=FR|BB4-cvr|8TafA5@OXN{y0n9=5-AfJS*3CoJY$n7xX{QhU-N)*PT{#q$JyCM z8ywk-E?KJ2Enj!?*}TG2kr@lcpX^-5T5v8iV{YfGndJrM*oLi{Ib!fRl z3&X1wOQvP5TDho8>eb5StGrgN{l-8QXmriN1DRn$(WUcyk>e=jGJ1cdzed|0k z=eHi}Y+O{ul)Yl9e2Rj`yc)LK&o@*&JGo+hU)6@3*^}Pw)Lbs-arz*~i$&f}yI!rc zZrc53nK#p(kDI*L@A`VrI)BgaYuW4fGu*D$-~WHn>g+9-|DDp@R5;6e#jLAgvvf8d z?aF?;_0p!7uV%0&F4){+iX5-{rS(P3m*4tN-o%)USoX0Uz*qCoZ;!28)r=_D=;|B%iXp0TKlh^ zMTe@p4wNoDlGU@EHO;z8<51l6xjDx()1$x5&pW;Ijne}4FTGCp8`$4%f6(wh*5aXt zL|xOvE@i!n$1U!4KORkBKeyw_MDxBw&U4D&{d~T_+2xXlWMRmq7fbw0etE23elO60 G!5RRh`|ElD literal 0 HcmV?d00001 diff --git a/webui/images/jquery.progressbar/progressbg_green.gif b/webui/images/jquery.progressbar/progressbg_green.gif new file mode 100644 index 0000000000000000000000000000000000000000..f3f3bf681141982dc72429b21b4c8af7dbfd2b70 GIT binary patch literal 1308 zcmZ?wbhEHb{J_A&(9Xb+l$vz#b;JHwRXbng?Rb&B?RnasS0x*s#jbelz3h?O(udAV z9y+ak61L%K)Yq?HH$P8Y{Uo6GmT=cio{6`mr`}bWa!0ZCI#bJahEJb9wclWS_Uzf+ zyLWHhy2UUGMnhmIgn$mnk)XW5&hd|dkweB~!-9j&9Ku>LCpIiR+%BN(HOFIP(jf*W zwhS4E28YIeHYceEFFrCfv2cm4h}qfT*gV}pdWOr%qNS&2=%+7Rb5kh&++^$Qdq+5@ zr2Ege3b%?lwPoeyib#-+FZ^@S*8xJ(IGrLXtbE9F|#f27UKe5 ze|J*~xABYU9Yq^o-95d1ef*l(y>+$)4F@6)^1Qisbmol}Ub}dutlM;c>fAZiotzZ* zYy0Ns=NHVbt9AIH+I(O!zd^woA*M@L*Tg;!Ia}5EX2zD}{nu=zw_Ut&pqYDq)d3S` zHUT*fwcK6ba%Y~ceBSf!N9D&8=L&-4Me zP3E%uP5-?5zPkJV`T6-R96~G>jI5#}84p;*Vir7T;&w}T(9B_^v9Ot6Ok!aRZ&*fR zlZ2K>Vyk%455*RlvKI<$8p~EZ>eAWv;!(H3F^$JPCf76^*(4(j9yO{aX*9Npw!BcD z;NcrZz&%;MSPv^WQ~ z{>*hd6K7|Xy-1r7pts`*Tg9`L&*#;Ad-;5R1Dn>11ubG#YLk*?Sw3g!Jms0P*jb5d y`I5e%sLV#0lvOX6%_)2Ja`}Qbtye3SOv_s3x?NSD+|H4{TcmQQK=FDE)AcBZPoF;Bh+}*9?AhJB zcW>Rg#V`s+LtrR`fDXu!puE7&@sEL#L&jsnf`iQ*!dfvWHY_~cE}-l+$75sCAqFP4 z3>k+8hsJ(3C#eT7J~A}1aEYym+1cROJl#NghReyKrKe};r!QM`Qz-r1Wb5pEM>waX z`_H!uw~9EmW##4N0gJundTm{Gb#(-9$(J7+4>YqgyG{CYqhZ;_g%)Q&xkv}E4VbTg zcT){F>Okb+!c!2O@x`_~7tAX8S&wrq>5&iEggpEB^fJ^sDeq z=Cb=u|GfIXy8Hh5`S~pzLM#@HtfC?r4_L%v7CdO;c1w8B%weRlu$f;>Vqpt!SVm%# zgqBBQt9a56#TJ>e7Yb||%T_$<(%JUnQMbV{jmJGE*EAg2BqIzSHL50QG`5MhyilIt zcNYT3{5OtVk=^HHaIplm6UjSaxxt#o13T(!py3=Ih_x zl)`QNB6>&B##eVwZ(kq3CU$R~Z9&6j7-=kQ<`8D%fhCIsm1c*0ikY~}NLHQ!!7pWncy^ wFDNRrQ6^>8%Vl%QUcFqtpiS%5iY3#sR=KWNw(8ZYHQQdjTFuPH%EDj`0N~Rv?EnA( literal 0 HcmV?d00001 diff --git a/webui/images/jquery.progressbar/progressbg_yellow.gif b/webui/images/jquery.progressbar/progressbg_yellow.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdb0dfc981cbbfbca4e80f4ff5ccfac247b3be91 GIT binary patch literal 1308 zcmZ?wbhEHb{J_A&(9Xb+nws?bX~U~0RWBaqy?B`Y{6X5Q$0g71#Xi36{phCK!yC>I zZ#X@<6ZZ6O)Yq?HpFc=^awp){dEuMqcy3>izI$2a&Lzd`r?arL;I#qs z_3v&<;WmB|y`yO3tGlPSua937ySL7^py5EoL7q4Fj?TQX!fO|=ly#fVPn|obx|5T_ zer@0U{QQF1b+ryZRGSYh<~JxYCWcA!n-^-^|#Oy#Jc5^tOu^4m5MmuR37D z%qAemp_aSrTkg!WmCt+L{iytS;#^_y^UPZ7^A8^!{>N-&c3vKR-Xeg+qwNf{|5JB;x^#Sj>V4P26q?51KiQG!{1Vi%BeO;SI}3 zY?9FONNg2P`k~k&Q}#lEO=H=LM_oGGUOehHIHvKq$K;xZBb#J|!J|giB#p*4(Uup= z6P&z$EN*i(s!-{$)$&Z4>=(A+;FOTC%%@W$(pEm57E|`}>GXuO1rH{vlvzBRoEGPx z)}Ogh1UM^qIruAyYl4)71Tvsex^=j3cZLeOfW@ck$VXy`OH^w~^ literal 0 HcmV?d00001 diff --git a/webui/scripts/3rdparty/jquery.asmselect.js b/webui/scripts/3rdparty/jquery.asmselect.js new file mode 100644 index 0000000..cc1571f --- /dev/null +++ b/webui/scripts/3rdparty/jquery.asmselect.js @@ -0,0 +1,407 @@ +/* + * Alternate Select Multiple (asmSelect) 1.0.4 beta - jQuery Plugin + * http://www.ryancramer.com/projects/asmselect/ + * + * Copyright (c) 2008 by Ryan Cramer - http://www.ryancramer.com + * + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + */ + +(function($) { + + $.fn.asmSelect = function(customOptions) { + + var options = { + + listType: 'ol', // Ordered list 'ol', or unordered list 'ul' + sortable: false, // Should the list be sortable? + highlight: false, // Use the highlight feature? + animate: false, // Animate the the adding/removing of items in the list? + addItemTarget: 'bottom', // Where to place new selected items in list: top or bottom + hideWhenAdded: false, // Hide the option when added to the list? works only in FF + debugMode: false, // Debug mode keeps original select visible + + removeLabel: 'remove', // Text used in the "remove" link + highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item + highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item + + containerClass: 'asmContainer', // Class for container that wraps this widget + selectClass: 'asmSelect', // Class for the newly created ") + .addClass(options.selectClass) + .attr('name', options.selectClass + index) + .attr('id', options.selectClass + index); + + $selectRemoved = $(""); + + $ol = $("<" + options.listType + ">") + .addClass(options.listClass) + .attr('id', options.listClass + index); + + $container = $("
") + .addClass(options.containerClass) + .attr('id', options.containerClass + index); + + buildSelect(); + + $select.change(selectChangeEvent) + .click(selectClickEvent); + + $original.change(originalChangeEvent) + .wrap($container).before($select).before($ol); + + if(options.sortable) makeSortable(); + + if($.browser.msie) $ol.css('display', 'inline-block'); + } + + function makeSortable() { + + // make any items in the selected list sortable + // requires jQuery UI sortables, draggables, droppables + + $ol.sortable({ + items: 'li.' + options.listItemClass, + handle: '.' + options.listItemLabelClass, + axis: 'y', + update: function(e, data) { + + var updatedOptionId; + + $(this).children("li").each(function(n) { + + $option = $('#' + $(this).attr('rel')); + + if($(this).is(".ui-sortable-helper")) { + updatedOptionId = $option.attr('id'); + return; + } + + $original.append($option); + }); + + if(updatedOptionId) triggerOriginalChange(updatedOptionId, 'sort'); + } + + }).addClass(options.listSortableClass); + } + + function selectChangeEvent(e) { + + // an item has been selected on the regular select we created + // check to make sure it's not an IE screwup, and add it to the list + + if($.browser.msie && $.browser.version < 7 && !ieClick) return; + var id = $(this).children("option:selected").slice(0,1).attr('rel'); + addListItem(id); + ieClick = false; + triggerOriginalChange(id, 'add'); // for use by user-defined callbacks + } + + function selectClickEvent() { + + // IE6 lets you scroll around in a select without it being pulled down + // making sure a click preceded the change() event reduces the chance + // if unintended items being added. there may be a better solution? + + ieClick = true; + } + + function originalChangeEvent(e) { + + // select or option change event manually triggered + // on the original + // used only by buildSelect() + + if(disabled == undefined) var disabled = false; + + var $O = $('#' + optionId); + var $option = $("") + .val($O.val()) + .attr('rel', optionId); + + if(disabled) disableSelectOption($option); + + $select.append($option); + } + + function selectFirstItem() { + + // select the firm item from the regular select that we created + + $select.children(":eq(0)").attr("selected", true); + } + + function disableSelectOption($option) { + + // make an option disabled, indicating that it's already been selected + // because safari is the only browser that makes disabled items look 'disabled' + // we apply a class that reproduces the disabled look in other browsers + + $option.addClass(options.optionDisabledClass) + .attr("selected", false) + .attr("disabled", true); + + if(options.hideWhenAdded) $option.hide(); + if($.browser.msie) $select.hide().show(); // this forces IE to update display + } + + function enableSelectOption($option) { + + // given an already disabled select option, enable it + + $option.removeClass(options.optionDisabledClass) + .attr("disabled", false); + + if(options.hideWhenAdded) $option.show(); + if($.browser.msie) $select.hide().show(); // this forces IE to update display + } + + function addListItem(optionId) { + + // add a new item to the html list + + var $O = $('#' + optionId); + + if(!$O) return; // this is the first item, selectLabel + + var $removeLink = $("") + .attr("href", "#") + .addClass(options.removeClass) + .prepend(options.removeLabel) + .click(function() { + dropListItem($(this).parent('li').attr('rel')); + return false; + }); + + var $itemLabel = $("") + .addClass(options.listItemLabelClass) + .html($O.html()); + + var $item = $("
  • ") + .attr('rel', optionId) + .addClass(options.listItemClass) + .append($itemLabel) + .append($removeLink) + .hide(); + + if(!buildingSelect) { + if($O.is(":selected")) return; // already have it + $O.attr('selected', true); + } + + if(options.addItemTarget == 'top' && !buildingSelect) { + $ol.prepend($item); + if(options.sortable) $original.prepend($O); + } else { + $ol.append($item); + if(options.sortable) $original.append($O); + } + + addListItemShow($item); + + disableSelectOption($("[rel=" + optionId + "]", $select)); + + if(!buildingSelect) { + setHighlight($item, options.highlightAddedLabel); + selectFirstItem(); + if(options.sortable) $ol.sortable("refresh"); + } + + } + + function addListItemShow($item) { + + // reveal the currently hidden item with optional animation + // used only by addListItem() + + if(options.animate && !buildingSelect) { + $item.animate({ + opacity: "show", + height: "show" + }, 100, "swing", function() { + $item.animate({ + height: "+=2px" + }, 50, "swing", function() { + $item.animate({ + height: "-=2px" + }, 25, "swing"); + }); + }); + } else { + $item.show(); + } + } + + function dropListItem(optionId, highlightItem) { + + // remove an item from the html list + + if(highlightItem == undefined) var highlightItem = true; + var $O = $('#' + optionId); + + $O.attr('selected', false); + $item = $ol.children("li[rel=" + optionId + "]"); + + dropListItemHide($item); + enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select)); + + if(highlightItem) setHighlight($item, options.highlightRemovedLabel); + + triggerOriginalChange(optionId, 'drop'); + + } + + function dropListItemHide($item) { + + // remove the currently visible item with optional animation + // used only by dropListItem() + + if(options.animate && !buildingSelect) { + + $prevItem = $item.prev("li"); + + $item.animate({ + opacity: "hide", + height: "hide" + }, 100, "linear", function() { + $prevItem.animate({ + height: "-=2px" + }, 50, "swing", function() { + $prevItem.animate({ + height: "+=2px" + }, 100, "swing"); + }); + $item.remove(); + }); + + } else { + $item.remove(); + } + } + + function setHighlight($item, label) { + + // set the contents of the highlight area that appears + // directly after the '); + + addOptions = function (elem, options) { + if ($.isArray(options)) { + $.each(options, function (i, val) { + if ($.isPlainObject(val)) { + $.each(val, function (key, value) { + if ($.isArray(value)) { + var og = $('').attr('label', key); + addOptions(og, value); + og.appendTo(select); + } else if (typeof value === 'number' || typeof value === 'string') { + $('