Components can now be dragged on to a page or layout
This commit is contained in:
parent
bc824ed021
commit
c593123700
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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', '')
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue