From aef3cf3acfeb5c78c7da2c999e2babc1371ef212 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 13:48:26 +0200 Subject: [PATCH 1/9] converting publishers to a drop-down menu to save real estate --- core/src/main/java/hudson/model/Project.java | 2 +- .../main/resources/lib/form/hetero-list.jelly | 12 ++++++-- .../hudson/project/config-publishers.jelly | 13 +++++++-- .../main/webapp/scripts/hudson-behavior.js | 28 ++++++++++++++++++- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/hudson/model/Project.java b/core/src/main/java/hudson/model/Project.java index fd228a3521..fb63c2c837 100644 --- a/core/src/main/java/hudson/model/Project.java +++ b/core/src/main/java/hudson/model/Project.java @@ -195,7 +195,7 @@ public abstract class Project

,B extends Build> buildWrappers.rebuild(req,json, BuildWrappers.getFor(this)); builders.rebuildHetero(req,json, Builder.all(), "builder"); - publishers.rebuild(req, json, BuildStepDescriptor.filter(Publisher.all(), this.getClass())); + publishers.rebuildHetero(req, json, Publisher.all(), "publisher"); } @Override diff --git a/core/src/main/resources/lib/form/hetero-list.jelly b/core/src/main/resources/lib/form/hetero-list.jelly index 3325dc18d5..05f0a7ec8b 100644 --- a/core/src/main/resources/lib/form/hetero-list.jelly +++ b/core/src/main/resources/lib/form/hetero-list.jelly @@ -52,6 +52,12 @@ THE SOFTWARE. For each item, add a caption from descriptor.getDisplayName(). This also activates drag&drop (where the header is a grip), and help text support. + + If true, only allow up to one instance per descriptor. + + + Menu alignment against the button. Defaults to tl-bl + @@ -90,12 +96,12 @@ THE SOFTWARE. -

+
-
+
@@ -121,7 +127,7 @@ THE SOFTWARE.
- +
diff --git a/core/src/main/resources/lib/hudson/project/config-publishers.jelly b/core/src/main/resources/lib/hudson/project/config-publishers.jelly index ddbf60fc64..71905f083a 100644 --- a/core/src/main/resources/lib/hudson/project/config-publishers.jelly +++ b/core/src/main/resources/lib/hudson/project/config-publishers.jelly @@ -27,7 +27,14 @@ THE SOFTWARE. --> - + + + + + \ No newline at end of file diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 98b945a4a9..3cf67c89be 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -510,6 +510,7 @@ var jenkinsRules = { // other behavior rules change them (like YUI buttons.) "DIV.hetero-list-container" : function(e) { + e=$(e); if(isInsideRemovable(e)) return; // components for the add button @@ -537,19 +538,27 @@ var jenkinsRules = { var withDragDrop = initContainerDD(e); - var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu }); + var menuAlign = (btn.getAttribute("menualign")||"tl-bl").split("-"); + + var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu, menualignment: menuAlign }); menuButton.getMenu().clickEvent.subscribe(function(type,args,value) { var t = templates[parseInt(args[1].value)]; // where this args[1] comes is a real mystery var nc = document.createElement("div"); nc.className = "repeated-chunk"; nc.setAttribute("name",t.name); + nc.setAttribute("descriptorId",t.descriptorId); nc.innerHTML = t.html; + $(nc).setOpacity(0); renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() { insertionPoint.parentNode.insertBefore(nc, insertionPoint); if(withDragDrop) prepareDD(nc); + new YAHOO.util.ColorAnim(nc, { + opacity: { to:1 } + }, 0.2, YAHOO.util.Easing.easeIn).animate(); + Behaviour.applySubtree(nc,true); },true); }); @@ -563,6 +572,23 @@ var jenkinsRules = { applyTooltip(items[i].element,t); } }); + + if (e.hasClassName("one-each")) { + // does this container already has a ocnfigured instance of the specified descriptor ID? + function has(id) { + return Prototype.Selector.find(e.childElements(),"DIV.repeated-chunk[descriptorId=\""+id+"\"]")!=null; + } + + menuButton.getMenu().showEvent.subscribe(function() { + var items = menuButton.getMenu().getItems(); + for(i=0; i Date: Thu, 19 Apr 2012 13:59:16 +0200 Subject: [PATCH 2/9] make sure the newly added portion is always visible --- war/src/main/webapp/scripts/hudson-behavior.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 3cf67c89be..d488729f08 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -538,11 +538,13 @@ var jenkinsRules = { var withDragDrop = initContainerDD(e); - var menuAlign = (btn.getAttribute("menualign")||"tl-bl").split("-"); + var menuAlign = (btn.getAttribute("menualign")||"tl-bl"); - var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu, menualignment: menuAlign }); + var menuButton = new YAHOO.widget.Button(btn, { type: "menu", menu: menu, menualignment: menuAlign.split("-") }); menuButton.getMenu().clickEvent.subscribe(function(type,args,value) { - var t = templates[parseInt(args[1].value)]; // where this args[1] comes is a real mystery + var item = args[1]; + if (item.cfg.getProperty("disabled")) return; + var t = templates[parseInt(item.value)]; // where this args[1] comes is a real mystery var nc = document.createElement("div"); nc.className = "repeated-chunk"; @@ -551,6 +553,8 @@ var jenkinsRules = { nc.innerHTML = t.html; $(nc).setOpacity(0); + var scroll = document.body.scrollTop; + renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() { insertionPoint.parentNode.insertBefore(nc, insertionPoint); if(withDragDrop) prepareDD(nc); @@ -560,6 +564,8 @@ var jenkinsRules = { }, 0.2, YAHOO.util.Easing.easeIn).animate(); Behaviour.applySubtree(nc,true); + if (menuAlign=="bl-tl") // for a button that gets displayed at the bottom, scroll down so that newly added section is fully visible + document.body.scrollTop = scroll+nc.clientHeight; },true); }); From 085ae79e5bbfded1ee478fdc9bb3f7a4d853b67c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 14:00:57 +0200 Subject: [PATCH 3/9] this needs to trigger the relayout --- war/src/main/webapp/scripts/hudson-behavior.js | 1 + 1 file changed, 1 insertion(+) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index d488729f08..f570302ef0 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -566,6 +566,7 @@ var jenkinsRules = { Behaviour.applySubtree(nc,true); if (menuAlign=="bl-tl") // for a button that gets displayed at the bottom, scroll down so that newly added section is fully visible document.body.scrollTop = scroll+nc.clientHeight; + layoutUpdateCallback.call(); },true); }); From 11f8ac0875cb0a19482b118ff31c273de8be32f5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 14:06:40 +0200 Subject: [PATCH 4/9] adding animation --- war/src/main/webapp/scripts/hudson-behavior.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index f570302ef0..3d9054da7b 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -559,7 +559,7 @@ var jenkinsRules = { insertionPoint.parentNode.insertBefore(nc, insertionPoint); if(withDragDrop) prepareDD(nc); - new YAHOO.util.ColorAnim(nc, { + new YAHOO.util.Anim(nc, { opacity: { to:1 } }, 0.2, YAHOO.util.Easing.easeIn).animate(); @@ -1879,10 +1879,17 @@ var repeatableSupport = { // called when 'delete' button is clicked onDelete : function(n) { n = findAncestorClass(n,"repeated-chunk"); - var p = n.parentNode; - p.removeChild(n); - if (p.tag) - p.tag.update(); + var a = new YAHOO.util.Anim(n, { + opacity: { to:0 }, + height: {to:0 } + }, 0.2, YAHOO.util.Easing.easeIn); + a.onComplete.subscribe(function() { + var p = n.parentNode; + p.removeChild(n); + if (p.tag) + p.tag.update(); + }); + a.animate(); }, // called when 'add' button is clicked From 570d974568bbd6534360599975aca227bdd92106 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 14:12:47 +0200 Subject: [PATCH 5/9] hopefully giving it a name made it easier to understand what it means --- war/src/main/webapp/scripts/hudson-behavior.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 3d9054da7b..38c203dc76 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -544,7 +544,7 @@ var jenkinsRules = { menuButton.getMenu().clickEvent.subscribe(function(type,args,value) { var item = args[1]; if (item.cfg.getProperty("disabled")) return; - var t = templates[parseInt(item.value)]; // where this args[1] comes is a real mystery + var t = templates[parseInt(item.value)]; var nc = document.createElement("div"); nc.className = "repeated-chunk"; From 07477567d249bbbbe99b9d0db1e712fcb3e106c9 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 14:17:19 +0200 Subject: [PATCH 6/9] this is shorter --- war/src/main/webapp/scripts/hudson-behavior.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 38c203dc76..c1cae43178 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -556,7 +556,7 @@ var jenkinsRules = { var scroll = document.body.scrollTop; renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() { - insertionPoint.parentNode.insertBefore(nc, insertionPoint); + insertionPoint.insert({after:nc}); if(withDragDrop) prepareDD(nc); new YAHOO.util.Anim(nc, { From 28bcaea860966dcf16f10d4719a951fc6b4b35fd Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 19 Apr 2012 14:18:34 +0200 Subject: [PATCH 7/9] unused arguments --- war/src/main/webapp/scripts/hudson-behavior.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index c1cae43178..6fb4431f16 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -570,7 +570,7 @@ var jenkinsRules = { },true); }); - menuButton.getMenu().renderEvent.subscribe(function(type,args,value) { + menuButton.getMenu().renderEvent.subscribe(function() { // hook up tooltip for menu items var items = menuButton.getMenu().getItems(); for(i=0; i Date: Thu, 19 Apr 2012 15:36:14 +0200 Subject: [PATCH 8/9] by default, try to preserve the order --- .../main/resources/lib/form/hetero-list.jelly | 6 ++- .../hudson/project/config-publishers.jelly | 1 + .../main/webapp/scripts/hudson-behavior.js | 53 +++++++++++++++++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/core/src/main/resources/lib/form/hetero-list.jelly b/core/src/main/resources/lib/form/hetero-list.jelly index 05f0a7ec8b..198ff6e733 100644 --- a/core/src/main/resources/lib/form/hetero-list.jelly +++ b/core/src/main/resources/lib/form/hetero-list.jelly @@ -58,6 +58,10 @@ THE SOFTWARE. Menu alignment against the button. Defaults to tl-bl + + If true, insert new addition by default to their 'desired' location, which + is the order induced by the descriptors. + @@ -96,7 +100,7 @@ THE SOFTWARE. -
+
diff --git a/core/src/main/resources/lib/hudson/project/config-publishers.jelly b/core/src/main/resources/lib/hudson/project/config-publishers.jelly index 71905f083a..ad29a3c429 100644 --- a/core/src/main/resources/lib/hudson/project/config-publishers.jelly +++ b/core/src/main/resources/lib/hudson/project/config-publishers.jelly @@ -34,6 +34,7 @@ THE SOFTWARE. items="${it.publishersList}" oneEach="true" menuAlign="bl-tl" + honorOrder="true" addCaption="${%Add post-build action}"/> diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 6fb4431f16..2c8dc4b0b6 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -556,7 +556,53 @@ var jenkinsRules = { var scroll = document.body.scrollTop; renderOnDemand(findElementsBySelector(nc,"TR.config-page")[0],function() { - insertionPoint.insert({after:nc}); + function findInsertionPoint() { + // given the element to be inserted 'prospect', + // and the array of existing items 'current', + // and preferred ordering function, return the position in the array + // the prospect should be inserted. + // (for example 0 if it should be the first item) + function findBestPosition(prospect,current,order) { + function desirability(pos) { + var count=0; + for (var i=0; i Date: Thu, 19 Apr 2012 17:50:37 +0200 Subject: [PATCH 9/9] added scorll-into-view capability --- .../main/webapp/scripts/hudson-behavior.js | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 2c8dc4b0b6..3a8a08c699 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -610,8 +610,7 @@ var jenkinsRules = { }, 0.2, YAHOO.util.Easing.easeIn).animate(); Behaviour.applySubtree(nc,true); - if (menuAlign=="bl-tl") // for a button that gets displayed at the bottom, scroll down so that newly added section is fully visible - document.body.scrollTop = scroll+nc.clientHeight; + ensureVisible(nc); layoutUpdateCallback.call(); },true); }); @@ -2063,7 +2062,49 @@ function getStyle(e,a){ if(e.currentStyle) return e.currentStyle[a]; return null; -}; +} + +/** + * Makes sure the given element is within the viewport. + * + * @param {HTMLElement} e + * The element to bring into the viewport. + */ +function ensureVisible(e) { + var viewport = YAHOO.util.Dom.getClientRegion(); + var pos = YAHOO.util.Dom.getRegion(e); + + var Y = viewport.top; + var H = viewport.height; + + function handleStickers(name,f) { + var e = $(name); + if (e) f(e); + document.getElementsBySelector("."+name).each(f); + } + + // if there are any stickers around, subtract them from the viewport + handleStickers("top-sticker",function (t) { + t = t.clientHeight; + Y+=t; H-=t; + }); + + handleStickers("bottom-sticker",function (b) { + b = b.clientHeight; + H-=b; + }); + + var y = pos.top; + var h = pos.height; + + var d = (y+h)-(Y+H); + if (d>0) { + document.body.scrollTop += d; + } else { + var d = Y-y; + if (d>0) document.body.scrollTop -= d; + } +} // set up logic behind the search box function createSearchBox(searchURL) {