Components can now be dragged on to a page or layout

This commit is contained in:
Sam Georges 2014-05-24 15:18:59 +10:00
parent bc824ed021
commit c593123700
6 changed files with 321 additions and 26 deletions

View File

@ -1,26 +1,35 @@
div.control-componentlist div.components div.layout-cell,
.component-list .components div.layout-cell {
.draggable-component-item,
.component-list .components div.layout-cell,
div.control-componentlist div.components div.layout-cell {
font-size: 11px;
cursor: pointer;
background: #ffffff;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
div.control-componentlist div.components div.layout-cell:hover,
.component-list .components div.layout-cell:hover {
.draggable-component-item:hover,
.component-list .components div.layout-cell:hover,
div.control-componentlist div.components div.layout-cell:hover {
background: #3382b6;
}
div.control-componentlist div.components div.layout-cell > div,
.component-list .components div.layout-cell > div {
.draggable-component-item > div,
.component-list .components div.layout-cell > div,
div.control-componentlist div.components div.layout-cell > div {
white-space: normal;
color: #475354;
position: relative;
border-right: 1px solid #ecf0f1;
}
div.control-componentlist div.components div.layout-cell > div:hover,
.component-list .components div.layout-cell > div:hover {
.draggable-component-item > div:hover,
.component-list .components div.layout-cell > div:hover,
div.control-componentlist div.components div.layout-cell > div:hover {
color: #ffffff;
}
div.control-componentlist div.components div.layout-cell > div:before,
.component-list .components div.layout-cell > div:before {
.draggable-component-item > div:before,
.component-list .components div.layout-cell > div:before,
div.control-componentlist div.components div.layout-cell > div:before {
position: absolute;
font-size: 16px;
left: 15px;
@ -28,8 +37,9 @@ div.control-componentlist div.components div.layout-cell > div:before,
opacity: 0.7;
filter: alpha(opacity=70);
}
div.control-componentlist div.components div.layout-cell > div:after,
.component-list .components div.layout-cell > div:after {
.draggable-component-item > div:after,
.component-list .components div.layout-cell > div:after,
div.control-componentlist div.components div.layout-cell > div:after {
position: absolute;
font-size: 37px;
top: 1px;
@ -48,31 +58,50 @@ div.control-componentlist div.components div.layout-cell > div:after,
*margin-right: .3em;
content: "\f12e";
}
div.control-componentlist div.components div.layout-cell > div:hover:after,
.component-list .components div.layout-cell > div:hover:after {
.draggable-component-item > div:hover:after,
.component-list .components div.layout-cell > div:hover:after,
div.control-componentlist div.components div.layout-cell > div:hover:after {
text-shadow: none;
color: #3382b6;
}
div.control-componentlist div.components div.layout-cell > div span,
.component-list .components div.layout-cell > div span {
.draggable-component-item > div span,
.component-list .components div.layout-cell > div span,
div.control-componentlist div.components div.layout-cell > div span {
display: block;
}
div.control-componentlist div.components div.layout-cell > div span.name,
.component-list .components div.layout-cell > div span.name {
.draggable-component-item > div span.name,
.component-list .components div.layout-cell > div span.name,
div.control-componentlist div.components div.layout-cell > div span.name {
white-space: nowrap;
padding: 8px 15px 0;
font-weight: 400;
line-height: 20px;
font-size: 12px;
}
div.control-componentlist div.components div.layout-cell > div span.description,
.component-list .components div.layout-cell > div span.description {
.draggable-component-item > div span.description,
.component-list .components div.layout-cell > div span.description,
div.control-componentlist div.components div.layout-cell > div span.description {
padding: 0 15px 10px;
margin-top: 8px;
font-weight: 100;
font-size: 11px;
line-height: 150%;
}
.draggable-component-item.placeholder > div,
.component-list .components div.layout-cell.placeholder > div,
div.control-componentlist div.components div.layout-cell.placeholder > div {
background: #e0e0e0;
color: #e0e0e0;
}
.draggable-component-item.placeholder > div:before,
.component-list .components div.layout-cell.placeholder > div:before,
div.control-componentlist div.components div.layout-cell.placeholder > div:before,
.draggable-component-item.placeholder > div:after,
.component-list .components div.layout-cell.placeholder > div:after,
div.control-componentlist div.components div.layout-cell.placeholder > div:after {
color: #e0e0e0 !important;
text-shadow: none !important;
}
div.control-componentlist {
position: relative;
background-color: #2c3e50;
@ -172,6 +201,12 @@ div.control-componentlist div.components div.layout-cell.adding > div {
-ms-transform: translate(0, -100px) !important;
transform: translate(0, -100px) !important;
}
.draggable-component-item span.alias {
display: none;
}
.draggable-component-item a.remove {
display: none;
}
.component-list .components div.layout div.layout-row div.layout-cell {
border-top: 1px solid #ecf0f1;
}

View File

@ -509,6 +509,9 @@
counter++
}
// Set the last alias used so dragComponents can use it
$('input[name="component_aliases[]"]', $(this)).val(alias)
$componentContainer.addClass($iconInput.val())
$iconInput.remove()
$componentContainer.attr('data-inspectable', '')

View File

@ -0,0 +1,238 @@
/*
* DragComponents plugin
*
* Data attributes:
* - data-control="dragcomponents" - enables the plugin on an element
* - data-option="value" - an option with a value
*
* JavaScript API:
* $('a#someElement').dragComponents({ option: 'value' })
*
* Dependences:
* - Some other plugin (filename.js)
*/
+function ($) { "use strict";
// DRAGCOMPONENTS CLASS DEFINITION
// ============================
var DragComponents = function(element, options) {
var self = this
this.options = options
this.$el = $(element)
var $el = this.$el,
$clone,
$editorArea,
$editor,
adjX = 0,
adjY = 0,
dragging = false,
startPos,
editorPos
$el.mousedown(function(event){
startDrag(event)
return false
})
$el.on('touchstart', function(event){
var touchEvent = event.originalEvent;
if (touchEvent.touches.length == 1) {
startDrag(touchEvent.touches[0])
event.stopPropagation()
}
})
function initDrag(event) {
$el.addClass(self.options.placeholderClass)
$clone.show()
$editorArea = $('[data-control="codeeditor"]:visible')
if (!$editorArea.length) return
$editor = $editorArea.codeEditor('getEditorObject')
$editor.focus()
$editor.on('mousemove', function (event) {
editorPos = event.getDocumentPosition()
$editor.clearSelection()
$editor.moveCursorToPosition(editorPos)
});
}
/*
* Internal event, drag has started
*/
function startDrag(event) {
startPos = $el.offset()
$clone = $el.clone().appendTo($(document.body))
$clone
.css({
zIndex: '99999',
position: 'absolute',
pointerEvents: 'none'
})
.addClass('draggable-component-item')
.width($el.width())
.height($el.height())
.hide()
var objX = (event.pageX - startPos.left),
objY = (event.pageY - startPos.top)
$clone.data('dragComponents', { x: objX, y: objY })
if (Modernizr.touch) {
$(window).on('touchmove.oc.dragcomponents', function(event){
var touchEvent = event.originalEvent
moveDrag(touchEvent.touches[0])
event.preventDefault()
})
$(window).on('touchend.oc.dragcomponents', function(event) {
stopDrag()
})
}
else {
$(window).on('mousemove.oc.dragcomponents', function(event){
moveDrag(event)
$(document.body).addClass(self.options.dragClass)
return false
})
$(window).on('mouseup.oc.dragcomponents', function(mouseUpEvent){
var isClick = event.pageX == mouseUpEvent.pageX && event.pageY == mouseUpEvent.pageY
stopDrag(isClick)
return false
})
}
}
/*
* Internal event, drag is active
*/
function moveDrag(event) {
if (!dragging) {
dragging = true
initDrag(event)
}
adjY = $(window).scrollTop()
adjX = $(window).scrollLeft()
var offset = $clone.data('dragComponents')
$clone.css({
left: (event.pageX - adjX - offset.x),
top: (event.pageY - adjY - offset.y)
})
}
/*
* Internal event, drag has ended
*/
function stopDrag(click) {
dragging = false
if (click)
$(document.body).removeClass(self.options.dragClass)
$el.removeClass(self.options.placeholderClass)
$(window)
.off('mousemove.oc.dragcomponents mouseup.oc.dragcomponents')
.removeData('dragComponents')
if (!click)
finishDrag()
$clone.remove()
window.setTimeout(function(){
if (!click) {
$(document.body).removeClass(self.options.dragClass)
}
}, 100)
}
function finishDrag() {
if (collision($clone, $editorArea)) {
// Add the component to the page
$el.click()
// Can only attach to page or layouts
var $componentList = $('#cms-master-tabs > div.tab-content > .tab-pane.active .control-componentlist .layout')
if (!$componentList.length || !$editor)
return;
// Inject {% component %} tag
var alias = $('input[name="component_aliases[]"]', $el).val()
$editor.insert("{% component '" + alias + "' %}")
}
$editor.removeAllListeners('mousemove')
$editor.blur()
}
function collision($div1, $div2) {
if (!$div1.length || !$div2.length)
return false
var x1 = $div1.offset().left,
y1 = $div1.offset().top,
h1 = $div1.outerHeight(true),
w1 = $div1.outerWidth(true),
b1 = y1 + h1,
r1 = x1 + w1,
x2 = $div2.offset().left,
y2 = $div2.offset().top,
h2 = $div2.outerHeight(true),
w2 = $div2.outerWidth(true),
b2 = y2 + h2,
r2 = x2 + w2
return !(b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2)
}
}
DragComponents.DEFAULTS = {
dragClass: 'drag',
placeholderClass: 'placeholder'
}
// DRAGCOMPONENTS PLUGIN DEFINITION
// ============================
var old = $.fn.dragComponents
$.fn.dragComponents = function (option) {
var args = Array.prototype.slice.call(arguments, 1)
return this.each(function () {
var $this = $(this)
var data = $this.data('oc.dragcomponents')
var options = $.extend({}, DragComponents.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('oc.dragcomponents', (data = new DragComponents(this, options)))
else if (typeof option == 'string') data[option].apply(data, args)
})
}
$.fn.dragComponents.Constructor = DragComponents
// DRAGCOMPONENTS NO CONFLICT
// =================
$.fn.dragComponents.noConflict = function () {
$.fn.dragComponents = old
return this
}
// DRAGCOMPONENTS DATA-API
// ===============
$(document).on('mouseenter.oc.dragcomponents', '[data-control="dragcomponent"]', function() {
$(this).dragComponents()
});
}(window.jQuery);

View File

@ -9,6 +9,7 @@
@color-component-text: #475354;
@color-component-hover-bg: #3382b6;
@color-component-hover-text: #ffffff;
@color-component-placeholder: #e0e0e0;
@color-group-bg: #f1f3f4;
.component-lego-icon() {
@ -26,10 +27,13 @@
.icon(@puzzle-piece);
}
div.control-componentlist div.components div.layout-cell, .component-list .components div.layout-cell {
.draggable-component-item,
.component-list .components div.layout-cell,
div.control-componentlist div.components div.layout-cell {
font-size: 11px;
cursor: pointer;
background: @color-component-bg;
.user-select(none);
&:hover {
background: @color-component-hover-bg;
@ -82,6 +86,15 @@ div.control-componentlist div.components div.layout-cell, .component-list .compo
}
}
}
&.placeholder > div {
background: @color-component-placeholder;
color: @color-component-placeholder;
&:before, &:after {
color: @color-component-placeholder !important;
text-shadow: none !important;
}
}
}
div.control-componentlist {
@ -199,13 +212,18 @@ div.control-componentlist {
}
}
.draggable-component-item {
span.alias { display: none; }
a.remove { display: none; }
}
.component-list .components {
div.layout {
div.layout-row {
div.layout-cell {
border-top: 1px solid @color-panel-light;
span.alias {display: none;}
a.remove {display: none;}
span.alias { display: none; }
a.remove { display: none; }
&:last-child > div {
border-right: none;

View File

@ -77,6 +77,7 @@ class Index extends Controller
}
$this->addJs('/modules/cms/assets/js/october.cmspage.js');
$this->addJs('/modules/cms/assets/js/october.dragcomponents.js');
$this->addCss('/modules/cms/assets/css/october.components.css');
// Preload Ace editor modes explicitly, because they could be changed dynamically

View File

@ -1,10 +1,10 @@
<div class="components subitems">
<div class="layout">
<div class="layout-row">
<?php
<?php
$count = count($components);
foreach ($components as $index => $component):
?>
<?php foreach ($components as $index => $component): ?>
<?php if ($index > 0 && ($index % 2) == 0): ?>
</div>
@ -15,7 +15,7 @@
<div class="layout-row">
<?php endif ?>
<div class="layout-cell" data-component>
<div class="layout-cell" data-control="dragcomponent" data-component>
<div class="layout-relative">
<span class="name"><?= e($component->title) ?></span>
<span class="description"><?= e($component->description) ?></span>