mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Added sticky positioning to layout editor toolbox.
This commit is contained in:
@@ -113,7 +113,6 @@
|
|||||||
<Content Include="Scripts\LayoutEditor\Services\ScopeConfigurator.js" />
|
<Content Include="Scripts\LayoutEditor\Services\ScopeConfigurator.js" />
|
||||||
<Content Include="Scripts\Lib.js" />
|
<Content Include="Scripts\Lib.js" />
|
||||||
<Content Include="Scripts\Lib.min.js" />
|
<Content Include="Scripts\Lib.min.js" />
|
||||||
<Content Include="Scripts\Lib\affix.js" />
|
|
||||||
<Content Include="Scripts\Lib\angular-resource.js" />
|
<Content Include="Scripts\Lib\angular-resource.js" />
|
||||||
<Content Include="Scripts\Lib\angular-sanitize.js" />
|
<Content Include="Scripts\Lib\angular-sanitize.js" />
|
||||||
<Content Include="Scripts\Lib\angular.js" />
|
<Content Include="Scripts\Lib\angular.js" />
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -166,7 +166,29 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
templateUrl: environment.templateUrl("Toolbox"),
|
templateUrl: environment.templateUrl("Toolbox"),
|
||||||
replace: true
|
replace: true,
|
||||||
|
link: function (scope, element) {
|
||||||
|
var toolbox = element.find(".layout-toolbox");
|
||||||
|
$(window).on("resize scroll", function (e) {
|
||||||
|
var canvas = element.parent().find(".layout-canvas");
|
||||||
|
// If the canvas is taller than the toolbox, make the toolbox sticky-positioned within the editor
|
||||||
|
// to help the user avoid excessive vertical scrolling.
|
||||||
|
var canvasIsTaller = !!canvas && canvas.height() > toolbox.height();
|
||||||
|
var windowPos = $(window).scrollTop();
|
||||||
|
if (canvasIsTaller && windowPos > element.offset().top + element.height() - toolbox.height()) {
|
||||||
|
toolbox.addClass("sticky-bottom");
|
||||||
|
toolbox.removeClass("sticky-top");
|
||||||
|
}
|
||||||
|
else if (canvasIsTaller && windowPos > element.offset().top) {
|
||||||
|
toolbox.addClass("sticky-top");
|
||||||
|
toolbox.removeClass("sticky-bottom");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toolbox.removeClass("sticky-top");
|
||||||
|
toolbox.removeClass("sticky-bottom");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,162 +0,0 @@
|
|||||||
/* ========================================================================
|
|
||||||
* Bootstrap: affix.js v3.3.1
|
|
||||||
* http://getbootstrap.com/javascript/#affix
|
|
||||||
* ========================================================================
|
|
||||||
* Copyright 2011-2014 Twitter, Inc.
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
||||||
* ======================================================================== */
|
|
||||||
|
|
||||||
|
|
||||||
+function ($) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// AFFIX CLASS DEFINITION
|
|
||||||
// ======================
|
|
||||||
|
|
||||||
var Affix = function (element, options) {
|
|
||||||
this.options = $.extend({}, Affix.DEFAULTS, options)
|
|
||||||
|
|
||||||
this.$target = $(this.options.target)
|
|
||||||
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
|
|
||||||
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
|
|
||||||
|
|
||||||
this.$element = $(element)
|
|
||||||
this.affixed =
|
|
||||||
this.unpin =
|
|
||||||
this.pinnedOffset = null
|
|
||||||
|
|
||||||
this.checkPosition()
|
|
||||||
}
|
|
||||||
|
|
||||||
Affix.VERSION = '3.3.1'
|
|
||||||
|
|
||||||
Affix.RESET = 'affix affix-top affix-bottom'
|
|
||||||
|
|
||||||
Affix.DEFAULTS = {
|
|
||||||
offset: 0,
|
|
||||||
target: window
|
|
||||||
}
|
|
||||||
|
|
||||||
Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
|
|
||||||
var scrollTop = this.$target.scrollTop()
|
|
||||||
var position = this.$element.offset()
|
|
||||||
var targetHeight = this.$target.height()
|
|
||||||
|
|
||||||
if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
|
|
||||||
|
|
||||||
if (this.affixed == 'bottom') {
|
|
||||||
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
|
|
||||||
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
|
|
||||||
}
|
|
||||||
|
|
||||||
var initializing = this.affixed == null
|
|
||||||
var colliderTop = initializing ? scrollTop : position.top
|
|
||||||
var colliderHeight = initializing ? targetHeight : height
|
|
||||||
|
|
||||||
if (offsetTop != null && colliderTop <= offsetTop) return 'top'
|
|
||||||
if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
Affix.prototype.getPinnedOffset = function () {
|
|
||||||
if (this.pinnedOffset) return this.pinnedOffset
|
|
||||||
this.$element.removeClass(Affix.RESET).addClass('affix')
|
|
||||||
var scrollTop = this.$target.scrollTop()
|
|
||||||
var position = this.$element.offset()
|
|
||||||
return (this.pinnedOffset = position.top - scrollTop)
|
|
||||||
}
|
|
||||||
|
|
||||||
Affix.prototype.checkPositionWithEventLoop = function () {
|
|
||||||
setTimeout($.proxy(this.checkPosition, this), 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
Affix.prototype.checkPosition = function () {
|
|
||||||
if (!this.$element.is(':visible')) return
|
|
||||||
|
|
||||||
var height = this.$element.height()
|
|
||||||
var offset = this.options.offset
|
|
||||||
var offsetTop = offset.top
|
|
||||||
var offsetBottom = offset.bottom
|
|
||||||
var scrollHeight = $('body').height()
|
|
||||||
|
|
||||||
if (typeof offset != 'object') offsetBottom = offsetTop = offset
|
|
||||||
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
|
|
||||||
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
|
|
||||||
|
|
||||||
var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
|
|
||||||
|
|
||||||
if (this.affixed != affix) {
|
|
||||||
if (this.unpin != null) this.$element.css('top', '')
|
|
||||||
|
|
||||||
var affixType = 'affix' + (affix ? '-' + affix : '')
|
|
||||||
var e = $.Event(affixType + '.bs.affix')
|
|
||||||
|
|
||||||
this.$element.trigger(e)
|
|
||||||
|
|
||||||
if (e.isDefaultPrevented()) return
|
|
||||||
|
|
||||||
this.affixed = affix
|
|
||||||
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
|
|
||||||
|
|
||||||
this.$element
|
|
||||||
.removeClass(Affix.RESET)
|
|
||||||
.addClass(affixType)
|
|
||||||
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (affix == 'bottom') {
|
|
||||||
this.$element.offset({
|
|
||||||
top: scrollHeight - height - offsetBottom
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// AFFIX PLUGIN DEFINITION
|
|
||||||
// =======================
|
|
||||||
|
|
||||||
function Plugin(option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
var data = $this.data('bs.affix')
|
|
||||||
var options = typeof option == 'object' && option
|
|
||||||
|
|
||||||
if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
|
|
||||||
if (typeof option == 'string') data[option]()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var old = $.fn.affix
|
|
||||||
|
|
||||||
$.fn.affix = Plugin
|
|
||||||
$.fn.affix.Constructor = Affix
|
|
||||||
|
|
||||||
|
|
||||||
// AFFIX NO CONFLICT
|
|
||||||
// =================
|
|
||||||
|
|
||||||
$.fn.affix.noConflict = function () {
|
|
||||||
$.fn.affix = old
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// AFFIX DATA-API
|
|
||||||
// ==============
|
|
||||||
|
|
||||||
$(window).on('load', function () {
|
|
||||||
$('[data-spy="affix"]').each(function () {
|
|
||||||
var $spy = $(this)
|
|
||||||
var data = $spy.data()
|
|
||||||
|
|
||||||
data.offset = data.offset || {}
|
|
||||||
|
|
||||||
if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
|
|
||||||
if (data.offsetTop != null) data.offset.top = data.offsetTop
|
|
||||||
|
|
||||||
Plugin.call($spy, data)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
}(jQuery);
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
font-size: @font-size;
|
font-size: @font-size;
|
||||||
align-items: flex-start;
|
align-items: stretch;
|
||||||
|
|
||||||
> .layout-canvas-wrapper {
|
> .layout-canvas-wrapper {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|||||||
@@ -1,66 +1,81 @@
|
|||||||
@import "Variables.less";
|
@import "Variables.less";
|
||||||
|
|
||||||
.layout-editor {
|
.layout-editor {
|
||||||
> .layout-toolbox {
|
> .layout-toolbox-wrapper {
|
||||||
|
position: relative;
|
||||||
margin-left: @container-padding;
|
margin-left: @container-padding;
|
||||||
border: 1px solid @gray-border;
|
|
||||||
width: 220px;
|
width: 220px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
min-height: 400px;
|
|
||||||
padding: @container-padding / 2;
|
|
||||||
background-color: @gray-bg;
|
|
||||||
|
|
||||||
.layout-toolbox-group {
|
> .layout-toolbox {
|
||||||
margin-top: @container-padding;
|
border: 1px solid @gray-border;
|
||||||
|
width: 220px;
|
||||||
|
min-height: 400px;
|
||||||
|
padding: @container-padding / 2;
|
||||||
|
background-color: @gray-bg;
|
||||||
|
|
||||||
.layout-toolbox-group-heading {
|
&.sticky-top {
|
||||||
display: block;
|
position: fixed;
|
||||||
margin-bottom: @container-padding / 3;
|
top: 0;
|
||||||
text-decoration: none;
|
}
|
||||||
|
|
||||||
|
&.sticky-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-toolbox-group {
|
||||||
|
margin-top: @container-padding;
|
||||||
|
|
||||||
|
.layout-toolbox-group-heading {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: @container-padding / 3;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
margin-right: @container-padding / 3;
|
margin-right: @container-padding / 3;
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
font: normal normal normal 14px/1 FontAwesome;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
content: "\f0d7";
|
content: "\f0d7";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.collapsed {
|
&.collapsed {
|
||||||
.layout-toolbox-group-heading:before {
|
.layout-toolbox-group-heading:before {
|
||||||
content: "\f0da";
|
content: "\f0da";
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-toolbox-items {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-toolbox-items {
|
.layout-toolbox-section + .layout-toolbox-section {
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-toolbox-section + .layout-toolbox-section {
|
|
||||||
margin-top: @container-padding / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-toolbox-item {
|
|
||||||
border: 1px solid @gray-border;
|
|
||||||
background-color: #fff;
|
|
||||||
padding: (@container-padding - 3) @container-padding;
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
i {
|
|
||||||
display: inline-block;
|
|
||||||
width: 16px;
|
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ .layout-toolbox-item {
|
|
||||||
margin-top: @container-padding / 3;
|
margin-top: @container-padding / 3;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
+ .layout-toolbox-group {
|
.layout-toolbox-item {
|
||||||
margin-top: @container-padding / 2;
|
border: 1px solid @gray-border;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: (@container-padding - 3) @container-padding;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
i {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
font: normal normal normal 14px/1 FontAwesome;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .layout-toolbox-item {
|
||||||
|
margin-top: @container-padding / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .layout-toolbox-group {
|
||||||
|
margin-top: @container-padding / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
<div class="layout-toolbox">
|
<div class="layout-toolbox-wrapper">
|
||||||
<label>
|
<div class="layout-toolbox">
|
||||||
<input type="checkbox" ng-checked="element.inlineEditingIsActive" ng-click="toggleInlineEditing()" />
|
<label>
|
||||||
@T("Edit HTML content inline")
|
<input type="checkbox" ng-checked="element.inlineEditingIsActive" ng-click="toggleInlineEditing()" />
|
||||||
</label>
|
@T("Edit HTML content inline")
|
||||||
<ul class="layout-toolbox-groups" ng-hide="element.inlineEditingIsActive">
|
</label>
|
||||||
<li class="layout-toolbox-group" ng-class="{collapsed: layoutIsCollapsed}">
|
<ul class="layout-toolbox-groups" ng-hide="element.inlineEditingIsActive">
|
||||||
<a href="#" class="layout-toolbox-group-heading" ng-click="toggleLayoutIsCollapsed($event)">@T("Layout")</a>
|
<li class="layout-toolbox-group" ng-class="{collapsed: layoutIsCollapsed}">
|
||||||
<ul class="layout-toolbox-items">
|
<a href="#" class="layout-toolbox-group-heading" ng-click="toggleLayoutIsCollapsed($event)">@T("Layout")</a>
|
||||||
<section class="layout-toolbox-section layout-toolbox-section-grid" ng-model="gridElements" ui-sortable="getSortableOptions('Grid')">
|
<ul class="layout-toolbox-items">
|
||||||
<li class="layout-toolbox-item layout-toolbox-item-grid" title="{{item.toolboxDescription}}" ng-repeat="item in gridElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
<section class="layout-toolbox-section layout-toolbox-section-grid" ng-model="gridElements" ui-sortable="getSortableOptions('Grid')">
|
||||||
</section>
|
<li class="layout-toolbox-item layout-toolbox-item-grid" title="{{item.toolboxDescription}}" ng-repeat="item in gridElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
||||||
<section class="layout-toolbox-section layout-toolbox-section-row" ng-model="rowElements" ui-sortable="getSortableOptions('Row')">
|
</section>
|
||||||
<li class="layout-toolbox-item layout-toolbox-item-row" title="{{item.toolboxDescription}}" ng-repeat="item in rowElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
<section class="layout-toolbox-section layout-toolbox-section-row" ng-model="rowElements" ui-sortable="getSortableOptions('Row')">
|
||||||
</section>
|
<li class="layout-toolbox-item layout-toolbox-item-row" title="{{item.toolboxDescription}}" ng-repeat="item in rowElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
||||||
<section class="layout-toolbox-section layout-toolbox-section-column" ng-model="columnElements" ui-sortable="getSortableOptions('Column')">
|
</section>
|
||||||
<li class="layout-toolbox-item layout-toolbox-item-column" title="{{item.toolboxDescription}}" ng-repeat="item in columnElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
<section class="layout-toolbox-section layout-toolbox-section-column" ng-model="columnElements" ui-sortable="getSortableOptions('Column')">
|
||||||
</section>
|
<li class="layout-toolbox-item layout-toolbox-item-column" title="{{item.toolboxDescription}}" ng-repeat="item in columnElements"><i>{{item.toolboxIcon}}</i> {{item.toolboxLabel}}</li>
|
||||||
</ul>
|
</section>
|
||||||
</li>
|
</ul>
|
||||||
<orc-layout-toolbox-group category="category" ng-repeat="category in contentElementCategories" />
|
</li>
|
||||||
</ul>
|
<orc-layout-toolbox-group category="category" ng-repeat="category in contentElementCategories" />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,8 +96,7 @@ var srcJsLib = [
|
|||||||
"Scripts/Lib/angular.js",
|
"Scripts/Lib/angular.js",
|
||||||
"Scripts/Lib/angular-sanitize.js",
|
"Scripts/Lib/angular-sanitize.js",
|
||||||
"Scripts/Lib/angular-resource.js",
|
"Scripts/Lib/angular-resource.js",
|
||||||
"Scripts/Lib/sortable.js",
|
"Scripts/Lib/sortable.js"
|
||||||
"Scripts/Lib/affix.js"
|
|
||||||
];
|
];
|
||||||
|
|
||||||
var srcJsLayoutEditor = [
|
var srcJsLayoutEditor = [
|
||||||
|
|||||||
Reference in New Issue
Block a user