From 3c99b0f23a1f3f11fa2549cab4ee3fad45537bad Mon Sep 17 00:00:00 2001 From: Ed Date: Mon, 18 Jun 2012 21:27:35 -0300 Subject: [PATCH] Issue #4: Adds missing requirements for WidgetAreaEditor NEW: Updates WidgetAreaEditor images to fit new design BUG: Removes use of deprecated method Name() on FormField --- code/form/WidgetAreaEditor.php | 3 - code/model/Widget.php | 2 +- css/WidgetAreaEditor.css | 84 +++++++++++++++ images/add-bg-hover.png | Bin 0 -> 621 bytes images/add-bg.png | Bin 0 -> 578 bytes images/delete.gif | Bin 0 -> 356 bytes images/handled-bg.png | Bin 0 -> 1303 bytes javascript/WidgetAreaEditor.js | 191 +++++++++++++++++++++++++++++++++ 8 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 css/WidgetAreaEditor.css create mode 100644 images/add-bg-hover.png create mode 100644 images/add-bg.png create mode 100644 images/delete.gif create mode 100644 images/handled-bg.png create mode 100644 javascript/WidgetAreaEditor.js diff --git a/code/form/WidgetAreaEditor.php b/code/form/WidgetAreaEditor.php index 532c688..814c132 100644 --- a/code/form/WidgetAreaEditor.php +++ b/code/form/WidgetAreaEditor.php @@ -21,10 +21,7 @@ class WidgetAreaEditor extends FormField { function FieldHolder($properties = array()) { Requirements::css('widgets/css/WidgetAreaEditor.css'); - Requirements::javascript(THIRDPARTY_DIR . "/prototype/prototype.js"); - Requirements::javascript(THIRDPARTY_DIR . '/behaviour/behaviour.js'); Requirements::javascript('widgets/javascript/WidgetAreaEditor.js'); - return $this->renderWith("WidgetAreaEditor"); } diff --git a/code/model/Widget.php b/code/model/Widget.php index 8ef5b7a..5da61e4 100644 --- a/code/model/Widget.php +++ b/code/model/Widget.php @@ -91,7 +91,7 @@ class Widget extends DataObject { $output = ''; $fields = $this->getCMSFields(); foreach($fields as $field) { - $name = $field->Name(); + $name = $field->getName(); $field->setValue($this->getField($name)); $renderedField = $field->FieldHolder(); $renderedField = preg_replace("/name=\"([A-Za-z0-9\-_]+)\"/", "name=\"Widget[" . $this->ID . "][\\1]\"", $renderedField); diff --git a/css/WidgetAreaEditor.css b/css/WidgetAreaEditor.css new file mode 100644 index 0000000..c5a45e0 --- /dev/null +++ b/css/WidgetAreaEditor.css @@ -0,0 +1,84 @@ +div.availableWidgetsHolder { + width: 30%; +} + +div.usedWidgetsHolder { + width: 66%; + max-width: 745px; +} + +div.availableWidgetsHolder { + float: left; +} + +div.usedWidgetsHolder { + float: right; +} + +div.usedWidgets .ui-state-highlight { + background: #EEEEEE; + + border: 1px solid #DDDDDD; + + width: 98%; + + margin-bottom: 5px; +} + +.NoWidgets { + padding: 50px; /* Make this nice and big and easily 'droppable' */ +} + +div.usedWidgets div.Widget, +div.availableWidgets div.Widget { + width: 98%; + border: 1px solid #ddd; + border-top: none; + margin-bottom: 10px; + background: #F0F3F4; +} + +div.widgetDescription{ + padding: 10px 0; +} +div.widgetDescription p, +div.widgetFields { + padding: 0 8px; + color: #666; + font-size: 11px; +} + +p.deleteWidget { + margin: 0 0 4px; + height: 22px; + line-height: 2.2; + font-size: 12px; +} +span.widgetDelete { + padding-left: 20px; + margin-right: 8px; + float: right; + background: url(../images/delete.gif) no-repeat left center; + cursor: pointer; +} +div.usedWidgets div.Widget h3, +div.availableWidgets div.Widget h3 { + font-size: 12px; + color: #fff; + line-height: 1.8; + padding: 0 5px; + margin: 0; +} + div.usedWidgets div.Widget h3 { + cursor: move; + background: #000 url(../images/handled-bg.png) right top; + } + div.availableWidgets div.Widget h3 { + cursor: pointer; + color: #444; + padding-right: 25px; + background: #ccc url(../images/add-bg.png) right center; + } + div.availableWidgets div.Widget h3:hover { + background: #ccc url(../images/add-bg-hover.png) right center; + } \ No newline at end of file diff --git a/images/add-bg-hover.png b/images/add-bg-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..161876e56efbc60dae953cffa6e7729755f7fe43 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0y~yV0sB;YjH3E$wt?pd>|!R;u=vBoS#-wo>-L1;Fyx1 zl&avFo0y&&l$w}QS$Hzl2B?eQ)5S5Q;?|oxyR(B6B@R4P%bZg-{EGd&Jw5IR=UXc0mW6|1sKobu1 zUE?i$Klyy>_3QiY?ArU|*V*4|pC6xncG+4+hLu~rMOp>E*QXzUGgIIi^UlfeAlLJzIa1ok6Bgt-m>QhFUfyC7t7FKvi0`dh5z^6?KyPN z`S-cGwkv^RvMPPf<}LBtXKqwEa&n#1!&_Iij~@Qb{(LLQc7dvom;T-~^xRbK|L~F1 z%NrM!>t|orV{q8@_S54#s-BZNYyN#|{dwumn`@tef#eZvXFqfHj5+#e=gqUWv$g$t z{-@8L-0;`{2l|0>MmC19)>ZSl{X1iT>4(A7)z4*}Q$iB}#{Chr literal 0 HcmV?d00001 diff --git a/images/add-bg.png b/images/add-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..b350dd2a0724b80b8ab97354b6ab63d817ca9122 GIT binary patch literal 578 zcmeAS@N?(olHy`uVBq!ia0y~yV0sB;YjH3E$wt?pd>|!R;u=vBoS#-wo>-L1;Fyx1 zl&avFo0y&&l$w}QS$HzlhJk_ciKmNWNX4x;ch34>W{^1WFz+?fW3}67T^ipwAKe_c zXXcOc>JLhsEV5R;0>V$7ZBO!*bd!xnBJwT6M=f*u3IEmj~E#=wvv&cN`N2}o&!(BY5+hig2 zcE7Al?LQ;A^zi4-+RO}IQ=a~`n0;9zeffR=^K~|Fa<|TU4RmjWh^J8hq8Gd3zkj>G zzv7<{&@J6czLzcLeXh7@p*`!Y_1<^a;;(N7nQf!5c3fUu@86G2n{HM7dQ!N0Yh7s^ zP<^V_vhyDC^ZZvW-T3Q;E5~buJo3)`FXJD)(v7; zvi6=!+rBq){q_Hr@i%YY+-l0OKis4%RlQfe7|}5jv~V*9)@eqs?(h94#_foymIN8 z8p9cBrbD6(mt+{0vN6nIV_3t>uvwVn>FTAY)~-F|<1x+BWMg~#yNeh9xQM+!w*R^s z=dRxFE6VJr6*!LdcfMG+?B0?kmzrDeX|O+BzGQ;E&5Fv(RW=4E#2MB*n_ikQ;e|TG zq5Q%=28M|Y4Etml7V>dCpIE<)i(#)M$Gyye{}${$cDDbG8UFwO&wvdm{$ycfV6b4& z0ZD@V#K6|*FsHynhbwtYzo7f7mbR_Y41sf0cnqc*6i*In6=plYu#khZ{hbK=s|5^3 z(t>w==eYH`xx_8u4`bzHsBz0+=4Ng7c49JZXXRDx?lte{5o&RsVy-VH%~LgVHfIr+ pT(Uq*U{DK}F&n?GxKkkGObad{emylODNPw~2_>EGV-}7K)&R_9cl!VU literal 0 HcmV?d00001 diff --git a/images/handled-bg.png b/images/handled-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f8a232b7980a70da79aa1bfbbeae844b45b80eeb GIT binary patch literal 1303 zcmaJ>T}&KR6h15zE7*kep|pLdlcBz7cYb!eEQ~B=+1a(LELj%}Gtuflzl#QjDCKY2Tm9W*mNQ`0)#>SsjF~KynmUh$hp;{B`orR@7i1RRW z?w#-Z&Uel|xvxiCAKOr|wE_S(gm?2X0LN7vKfK<7-!BGZ8vbmtf}K{I)@`K(1A$-C zx)2dogdP+_f;9N-7pMWCl#tsytWoB*fMy`VLorT~sbz>-mSWvIyqvGR~O zn;~^`F+Q}C3$J`+uVv{RO{Y>RD&?j$qlaee>+5X|m&=I}PIFMTgtSvNYl;dyGDSny zEm>0uTT$rJ1}qxx6M0C`h%6TRkH%LjWZsVcy@K&Mp1IJ|1|o>XmP{PgPVZEhpbh{8s++_{$?Bi4&Pb z&*f+4pW4XWB0nA4U-$l0<=elDH!jZJ`TOd?I;dKZhJ^}fie@)Epz0F!$V~^7P0o(R z;lQ!v(Y;$sz<+(=0}AH8{A=<1i7e1+kx$*dUOgWO9d9E6W*KSkLv@wtMH~%#8?P%kv#nbWU zJE~!Q7uMn@58gdo4)5mBNesv&4`XaJyElI99S0oh63d{e>H_|Mieok-z$aOmKVPMHF+~0hs?g|;S&>Q4?bE0nWwW$cgBuS#=p7` zu6##*-XmA1LeTVaa?g3U>p{ru$?muw|E%D7(|mTy?SSdY*}JLGwO1Ftr4ESMJ7;n; n55R%3LLZF&VOX}l{m)Gan3ez7pLpn;WnWd{U@Je~oOtOUd@IB2 literal 0 HcmV?d00001 diff --git a/javascript/WidgetAreaEditor.js b/javascript/WidgetAreaEditor.js new file mode 100644 index 0000000..16f895a --- /dev/null +++ b/javascript/WidgetAreaEditor.js @@ -0,0 +1,191 @@ +(function($) { + $.entwine('ss', function($) { + $('.WidgetAreaEditor').entwine({ + onmatch: function() { + var parentName=$(this).attr('name'); + this.rewriteWidgetAreaAttributes(); + + var availableWidgets=$('#availableWidgets-'+$(this).attr('name')).children().each(function() { + // Don't run on comments, whitespace, etc + if($(this)[0].nodeType==1) { + // Gotta change their ID's because otherwise we get clashes between two tabs + $(this)[0].id=$(this)[0].id+'-'+parentName; + } + }); + + var parentRef=$(this); + + + // Used widgets are sortable + $(this).find('.usedWidgets').sortable({ + opacity: 0.6, + handle: '.handle', + update: function(e, ui) {parentRef.updateWidgets(e, ui)}, + placeholder: 'ui-state-highlight', + forcePlaceholderSize: true + }); + + // Figure out maxid, this is used when creating new widgets + $(this).data('maxid', 0); + + var usedWidgets = $(this).find('.usedWidgets .Widget'); + usedWidgets.each(function() { + var widget = $(this)[0]; + if(widget.id) { + widgetid = widget.id.match(/Widget\[(.+?)\]\[([0-9]+)\]/i); + if(widgetid && parseInt(widgetid[2]) > parseInt(parentRef.data('maxid'))) { + parentRef.data('maxid', parseInt(widgetid[2])); + } + } + }); + + + // Ensure correct sort values are written when page is saved + // TODO Adjust to new event listeners + $('.cms-container').bind('submitform', this.beforeSave); + }, + + rewriteWidgetAreaAttributes: function() { + var name = $(this).attr('name'); + + var monkeyWith = function(widgets, name) { + if (!widgets) { + return; + } + + widgets.each(function() { + widget=$(this)[0]; + if (!widget.rewritten && (widget.id || widget.name)) { + if (widget.id && widget.id.indexOf('Widget[') === 0) { + var newValue = widget.id.replace(/Widget\[/, 'Widget['+name+']['); + //console.log('Renaming '+widget.tagName+' ID '+widget.id+' to '+newValue); + widget.id = newValue; + } + if (widget.name && widget.name.indexOf('Widget[') === 0) { + var newValue = widget.name.replace(/Widget\[/, 'Widget['+name+']['); + //console.log('Renaming '+widget.tagName+' Name '+widget.name+' to '+newValue); + widget.name=newValue; + } + widget.rewritten='yes'; + }else { + //console.log('Skipping '+(widget.id ? widget.id : (widget.name ? widget.name : 'unknown '+widget.tagName))); + } + }); + } + + monkeyWith($('#WidgetAreaEditor-'+name+' .Widget'), name); + monkeyWith($('#WidgetAreaEditor-'+name+' .Widget *'), name); + }, + + beforeSave: function() { + // Ensure correct sort values are written when page is saved + var usedWidgets = $('#usedWidgets-'+$(this).attr('name')); + if(usedWidgets) { + this.sortWidgets(); + + var children=usedWidgets.children(); + + children.each(function() { + if($(this).beforeSave) { + $(this).beforeSave(); + } + }); + } + }, + + addWidget: function(className, holder) { + if($('#WidgetAreaEditor-'+holder).attr('maxwidgets')) { + var maxCount = $('#WidgetAreaEditor-'+holder).attr('maxwidgets'); + var count = $('#usedWidgets-'+holder+' .Widget').length; + if (count+1 > maxCount) { + alert(ss.i18n._t('WidgetAreaEditor.TOOMANY')); + return; + } + } + + var parentRef=$(this); + $.ajax({ + 'url': 'Widget_Controller/EditableSegment/' + className, + 'success' : function(response) {parentRef.insertWidgetEditor(response)} + }); + }, + + updateWidgets: function(e, ui) { + // Gotta get the name of the current dohickey based off the ID + var name = $(this).attr('id').split('-').pop(); + + var i=0; + var usedWidgets = $('#usedWidgets-'+name).children().each(function() { + var widget = $(this)[0]; + if(widget.id) { + $(this).find('input[name='+widget.id.replace(/\]/g,'\\]').replace(/\[/g,'\\[')+'\\[Sort\\]]').val(i); + i++; + } + }); + }, + + insertWidgetEditor: function(response) { + var usedWidgets = $('#usedWidgets-'+$(this).attr('name')).children(); + + // Give the widget a unique id + var newID=parseInt($(this).data('maxid'))+1; + $(this).data('maxid', newID); + + var widgetContent = response.replace(/Widget\[0\]/gi, "Widget[new-" + (newID) + "]"); + $('#usedWidgets-'+$(this).attr('name')).prepend(widgetContent); + + this.rewriteWidgetAreaAttributes(); + }, + + sortWidgets: function() { + // Order the sort by the order the widgets are in the list + $('#usedWidgets-'+$(this).attr('name')).children().each(function() { + var div = $(this)[0]; + + if(div.nodeName != '#comment') { + var fields = div.getElementsByTagName('input'); + for(j = 0; field = fields.item(j); j++) { + if(field.name == div.id + '[Sort]') { + field.value = i; + } + } + } + }); + }, + + deleteWidget: function(widgetToRemove) { + // Remove a widget from the used widgets column + widgetToRemove.remove(); + } + }); + + $('div.availableWidgets .Widget h3').entwine({ + onclick: function(event) { + parts = $(this).parent().attr('id').split('-'); + var widgetArea = parts.pop(); + var className = parts.pop(); + $('#WidgetAreaEditor-'+widgetArea).addWidget(className, widgetArea); + } + }); + + /** + * Disable chosen + */ + $('div.usedWidgets .field.dropdown select, div.usedWidgets .field select[multiple]').entwine({ + onmatch: function() { + $(this).addClass('no-chzn'); + + this._super(); + } + }); + + $('div.usedWidgets div.Widget').entwine({ + onmatch: function() { + // Call deleteWidget when delete button is pushed + $(this).find('span.widgetDelete').click(function() { + $(this).closest('.WidgetAreaEditor').deleteWidget($(this).parent().parent()); + }); + } + }); + }) +})(jQuery); \ No newline at end of file