mirror of
https://github.com/silverstripe/silverstripe-widgets
synced 2024-10-22 17:05:54 +02:00
BUGFIX Include missing css, image, and javascript resources
This commit is contained in:
parent
552a5006da
commit
70a58c8e02
@ -23,6 +23,11 @@ class WidgetAreaEditor extends FormField {
|
||||
Requirements::css('widgets/css/WidgetAreaEditor.css');
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/prototype/prototype.js");
|
||||
Requirements::javascript(THIRDPARTY_DIR . '/behaviour/behaviour.js');
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/builder.js");
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/effects.js");
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/dragdrop.js");
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/control.js");
|
||||
Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/slider.js");
|
||||
Requirements::javascript('widgets/javascript/WidgetAreaEditor.js');
|
||||
|
||||
return $this->renderWith("WidgetAreaEditor");
|
||||
|
68
css/WidgetAreaEditor.css
Normal file
68
css/WidgetAreaEditor.css
Normal file
@ -0,0 +1,68 @@
|
||||
div.availableWidgetsHolder {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
div.usedWidgetsHolder {
|
||||
width: 66%;
|
||||
}
|
||||
|
||||
div.availableWidgetsHolder {
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.usedWidgetsHolder {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.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: 5px;
|
||||
}
|
||||
div.widgetDescription p,
|
||||
div.widgetFields {
|
||||
padding: 0 8px;
|
||||
color: #666;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
p.deleteWidget {
|
||||
margin: 0;
|
||||
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;
|
||||
}
|
BIN
images/add-bg-hover.png
Normal file
BIN
images/add-bg-hover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 621 B |
BIN
images/add-bg.png
Normal file
BIN
images/add-bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 578 B |
BIN
images/delete.gif
Normal file
BIN
images/delete.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 356 B |
BIN
images/handled-bg.png
Normal file
BIN
images/handled-bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.7 KiB |
282
javascript/WidgetAreaEditor.js
Normal file
282
javascript/WidgetAreaEditor.js
Normal file
@ -0,0 +1,282 @@
|
||||
// Shortcut-function (until we update to Prototye v1.5)
|
||||
if(typeof $$ != "Function") $$ = document.getElementsBySelector;
|
||||
|
||||
/**
|
||||
* File: WidgetAreaEditor.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class: WidgetAreaEditorClass
|
||||
*/
|
||||
WidgetAreaEditorClass = Class.create();
|
||||
WidgetAreaEditorClass.prototype = {
|
||||
initialize: function() {
|
||||
this.name = this.getAttribute('name');
|
||||
this.rewriteWidgetAreaAttributes();
|
||||
UsedWidget.applyToChildren(document.getElementById('usedWidgets-'+this.name), 'div.Widget');
|
||||
|
||||
var availableWidgets = document.getElementById('availableWidgets-'+this.name).childNodes;
|
||||
|
||||
for(var i = 0; i < availableWidgets.length; i++) {
|
||||
var widget = availableWidgets[i];
|
||||
// Don't run on comments, whitespace, etc
|
||||
if (widget.nodeType == 1) {
|
||||
// Gotta change their ID's because otherwise we get clashes between two tabs
|
||||
widget.id = widget.id + '-'+this.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create dummy sortable to prevent javascript errors
|
||||
Sortable.create('availableWidgets-'+this.name, {
|
||||
tag: 'li',
|
||||
handle: 'handle',
|
||||
containment: []
|
||||
});
|
||||
|
||||
// Used widgets are sortable
|
||||
Sortable.create('usedWidgets-'+this.name, {
|
||||
tag: 'div',
|
||||
handle: 'handle',
|
||||
containment: ['availableWidgets-'+this.name, 'usedWidgets-'+this.name],
|
||||
onUpdate: this.updateWidgets
|
||||
});
|
||||
|
||||
// Figure out maxid, this is used when creating new widgets
|
||||
this.maxid = 0;
|
||||
|
||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
||||
for(var i = 0; i < usedWidgets.length; i++) {
|
||||
var widget = usedWidgets[i];
|
||||
if(widget.id) {
|
||||
widgetid = widget.id.match(/\Widget\[(.+?)\]\[([0-9]+)\]/i);
|
||||
if(widgetid && parseInt(widgetid[2]) > this.maxid) {
|
||||
this.maxid = parseInt(widgetid[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure correct sort values are written when page is saved
|
||||
// TODO Adjust to new event listeners
|
||||
jQuery('.cms-edit-form').bind('ajaxsubmit', this.beforeSave.bind(this));
|
||||
},
|
||||
|
||||
rewriteWidgetAreaAttributes: function() {
|
||||
this.name = this.getAttribute('name');
|
||||
|
||||
var monkeyWith = function(widgets, name) {
|
||||
if (!widgets) {
|
||||
return;
|
||||
}
|
||||
for(var i = 0; i < widgets.length; i++) {
|
||||
widget = widgets[i];
|
||||
if (!widget.getAttribute('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.setAttribute('rewritten', 'yes');
|
||||
}
|
||||
else {
|
||||
//console.log('Skipping '+(widget.id ? widget.id : (widget.name ? widget.name : 'unknown '+widget.tagName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
monkeyWith($$('#WidgetAreaEditor-'+this.name+' .Widget'), this.name);
|
||||
monkeyWith($$('#WidgetAreaEditor-'+this.name+' .Widget *'), this.name);
|
||||
},
|
||||
|
||||
beforeSave: function() {
|
||||
// Ensure correct sort values are written when page is saved
|
||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name);
|
||||
|
||||
if(usedWidgets) {
|
||||
this.sortWidgets();
|
||||
|
||||
var children = usedWidgets.childNodes;
|
||||
|
||||
for( var i = 0; i < children.length; ++i ) {
|
||||
var child = children[i];
|
||||
|
||||
if(child.beforeSave) {
|
||||
child.beforeSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addWidget: function(className, holder) {
|
||||
|
||||
if (document.getElementById('WidgetAreaEditor-'+holder).getAttribute('maxwidgets')) {
|
||||
var maxCount = document.getElementById('WidgetAreaEditor-'+holder).getAttribute('maxwidgets');
|
||||
var count = $$('#usedWidgets-'+holder+' .Widget').length;
|
||||
if (count+1 > maxCount) {
|
||||
alert(ss.i18n._t('WidgetAreaEditor.TOOMANY'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.name = holder;
|
||||
jQuery.ajax({
|
||||
'url': 'Widget_Controller/EditableSegment/' + className,
|
||||
'success' : document.getElementById('usedWidgets-'+holder).parentNode.parentNode.insertWidgetEditor.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
updateWidgets: function() {
|
||||
var self = this;
|
||||
|
||||
// Gotta get the name of the current dohickey based off the ID
|
||||
this.name = this.element.id.split('-').pop();
|
||||
|
||||
// alert(this.name);
|
||||
|
||||
// Gotta get the name of the current dohickey based off the ID
|
||||
this.name = this.element.id.split('-').pop();
|
||||
|
||||
|
||||
// This is called when an available widgets is dragged over to used widgets.
|
||||
// It inserts the editor form into the new used widget
|
||||
|
||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
||||
for(var i = 0; i < usedWidgets.length; i++) {
|
||||
var widget = usedWidgets[i];
|
||||
if(widget.id && (widget.id.indexOf("Widget[") != 0) && (widget.id != 'NoWidgets-'+this.name)) {
|
||||
// Need to remove the -$Name part.
|
||||
var wIdArray = widget.id.split('-');
|
||||
wIdArray.pop();
|
||||
|
||||
jQuery.ajax({
|
||||
'url': 'Widget_Controller/EditableSegment/' + wIdArray.join('-'),
|
||||
'success' : function() {
|
||||
document.getElementById('usedWidgets-'+self.name).parentNode.parentNode.insertWidgetEditor();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
insertWidgetEditor: function(response) {
|
||||
// Remove placeholder text
|
||||
if(document.getElementById('NoWidgets-'+this.name)) {
|
||||
document.getElementById('usedWidgets-'+this.name).removeChild(document.getElementById('NoWidgets-'+this.name));
|
||||
}
|
||||
|
||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name).childNodes;
|
||||
|
||||
// Give the widget a unique id
|
||||
widgetContent = response.replace(/Widget\[0\]/gi, "Widget[new-" + (++document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.maxid) + "]");
|
||||
new Insertion.Top(document.getElementById('usedWidgets-'+this.name), widgetContent);
|
||||
|
||||
document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.rewriteWidgetAreaAttributes();
|
||||
UsedWidget.applyToChildren(document.getElementById('usedWidgets-'+this.name), 'div.Widget');
|
||||
|
||||
// Repply some common form controls
|
||||
WidgetTreeDropdownField.applyTo('div.usedWidgets .TreeDropdownField');
|
||||
|
||||
Sortable.create('usedWidgets-'+this.name, {
|
||||
tag: 'div',
|
||||
handle: 'handle',
|
||||
containment: ['availableWidgets-'+this.name, 'usedWidgets-'+this.name],
|
||||
onUpdate: document.getElementById('usedWidgets-'+this.name).parentNode.parentNode.updateWidgets
|
||||
});
|
||||
},
|
||||
|
||||
sortWidgets: function() {
|
||||
// Order the sort by the order the widgets are in the list
|
||||
var usedWidgets = document.getElementById('usedWidgets-'+this.name);
|
||||
|
||||
if(usedWidgets) {
|
||||
widgets = usedWidgets.childNodes;
|
||||
|
||||
for(i = 0; i < widgets.length; i++) {
|
||||
var div = widgets[i];
|
||||
|
||||
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
|
||||
document.getElementById('usedWidgets-'+this.name).removeChild(widgetToRemove);
|
||||
// TODO ... re-create NoWidgets div?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class: UsedWidget
|
||||
*/
|
||||
UsedWidget = Class.create();
|
||||
UsedWidget.prototype = {
|
||||
initialize: function() {
|
||||
// Call deleteWidget when delete button is pushed
|
||||
this.deleteButton = this.findDescendant('span', 'widgetDelete');
|
||||
if(this.deleteButton)
|
||||
this.deleteButton.onclick = this.deleteWidget.bind(this);
|
||||
},
|
||||
|
||||
// Taken from FieldEditor
|
||||
findDescendant: function(tag, clsName, element) {
|
||||
if(!element)
|
||||
element = this;
|
||||
|
||||
var descendants = element.getElementsByTagName(tag);
|
||||
|
||||
for(var i = 0; i < descendants.length; i++) {
|
||||
var el = descendants[i];
|
||||
|
||||
if(tag.toUpperCase() == el.tagName && el.className.indexOf( clsName ) != -1)
|
||||
return el;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
deleteWidget: function() {
|
||||
this.parentNode.parentNode.parentNode.deleteWidget(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class: AvailableWidgetHeader
|
||||
*/
|
||||
AvailableWidgetHeader = Class.create();
|
||||
AvailableWidgetHeader.prototype = {
|
||||
onclick: function(event) {
|
||||
parts = this.parentNode.id.split('-');
|
||||
var widgetArea = parts.pop();
|
||||
var className = parts.pop();
|
||||
document.getElementById('WidgetAreaEditor-'+widgetArea).addWidget(className, widgetArea);
|
||||
}
|
||||
}
|
||||
AvailableWidgetHeader.applyTo('div.availableWidgets .Widget h3');
|
||||
|
||||
/**
|
||||
* Class: WidgetTreeDropdownField
|
||||
*/
|
||||
WidgetTreeDropdownField = Class.extend('TreeDropdownField');
|
||||
WidgetTreeDropdownField.prototype = {
|
||||
getName: function() {
|
||||
return 'Widget_TDF_Endpoint';
|
||||
}
|
||||
}
|
||||
WidgetTreeDropdownField.applyTo('div.usedWidgets .TreeDropdownField');
|
||||
WidgetAreaEditorClass.applyTo('.WidgetAreaEditor');
|
Loading…
Reference in New Issue
Block a user