123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- /**
- * @file display_editor.js
- *
- * Contains the javascript for the Panels display editor.
- */
- (function ($) {
- // randomly lock a pane.
- // @debug only
- Drupal.settings.Panels = Drupal.settings.Panels || {};
- /** Delete pane button **/
- Drupal.Panels.bindClickDelete = function(context) {
- $('a.pane-delete:not(.pane-delete-processed)', context)
- .addClass('pane-delete-processed')
- .click(function() {
- if (confirm(Drupal.t('Remove this pane?'))) {
- var id = '#' + $(this).attr('id').replace('pane-delete-', '');
- $(id).remove();
- Drupal.Panels.Draggable.savePositions();
- }
- return false;
- });
- };
- Drupal.Panels.bindPortlet = function() {
- var handle = $(this).find('.panel-pane-collapsible > div.pane-title');
- var content = $(this).find('.panel-pane-collapsible > div.pane-content');
- if (content.length) {
- var toggle = $('<span class="toggle toggle-collapsed"></span>');
- handle.before(toggle);
- toggle.click(function() {
- content.slideToggle(20);
- toggle.toggleClass('toggle-collapsed');
- });
- handle.click(function() {
- content.slideToggle(20);
- toggle.toggleClass('toggle-collapsed');
- });
- content.hide();
- }
- };
- Drupal.Panels.Draggable = {
- // The draggable object
- object: null,
- // Where objects can be dropped
- dropzones: [],
- current_dropzone: null,
- // positions within dropzones where an object can be plazed
- landing_pads: [],
- current_pad: null,
- // Where the object is
- mouseOffset: { x: 0, y: 0 },
- windowOffset: { x: 0, y: 0 },
- offsetDivHeight: 0,
- // original settings to be restored
- original: {},
- // a placeholder so that if the object is let go but not over a drop zone,
- // it can be put back where it belongs
- placeholder: {},
- hoverclass: 'hoverclass',
- helperclass: 'helperclass',
- accept: 'div.panel-region',
- handle: 'div.grabber',
- draggable: 'div.panel-portlet',
- main: 'div#panels-dnd-main',
- // part of the id to remove to get just the number
- draggableId: 'panel-pane-',
- // part of the id to remove to get just the number
- regionId: 'panel-region-',
- // What to add to the front of a the id to get the form id for a panel
- formId: '#edit-',
- maxWidth: 250,
- unsetDropZone: function() {
- $(this.current_dropzone.obj).removeClass(this.hoverclass);
- this.current_dropzone = null;
- for (var i in this.landing_pads) {
- $(this.landing_pads[i].obj).remove();
- }
- this.landing_pads = [];
- this.current_pad = null;
- },
- createLandingPad: function(where, append) {
- var obj = $('<div class="' + this.helperclass +'" id="' +
- $(where).attr('id') + '-dropzone"> </div>');
- if (append) {
- $(where).append(obj);
- }
- else {
- $(where).before(obj);
- }
- var offset = $(obj).offset();
- $(obj).css({
- display: 'none'
- });
- this.landing_pads.push({
- centerX: offset.left + ($(obj).innerWidth() / 2),
- centerY: offset.top + ($(obj).innerHeight() / 2),
- obj: obj
- });
- return obj;
- },
- calculateDropZones: function(event, dropzone) {
- var draggable = Drupal.Panels.Draggable;
- var dropzones = [];
- $(this.accept).each(function() {
- var offset = $(this).offset();
- offset.obj = this;
- offset.region = this.id.replace(draggable.regionId, '');
- offset.width = $(this).outerWidth();
- offset.height = $(this).outerHeight();
- dropzones.push(offset);
- });
- this.dropzones = dropzones;
- },
- reCalculateDropZones: function() {
- for (var i in this.dropzones) {
- var offset = $(this.dropzones[i].obj).offset();
- offset.width = $(this.dropzones[i].obj).outerWidth();
- offset.height = $(this.dropzones[i].obj).outerHeight();
- $.extend(this.dropzones[i], offset);
- }
- },
- changeDropZone: function(new_dropzone) {
- // Unset our old dropzone.
- if (this.current_dropzone) {
- this.unsetDropZone();
- }
- // Set up our new dropzone.
- this.current_dropzone = new_dropzone;
- $(this.current_dropzone.obj).addClass(this.hoverclass);
- // add a landing pad
- this.createLandingPad(this.current_dropzone.obj, true);
- var that = this;
- // Create a landing pad before each existing portlet.
- $(this.current_dropzone.obj).find(this.draggable).each(function() {
- if (that.object.id != this.id) {
- that.createLandingPad(this, false);
- }
- });
- },
- findLandingPad: function(x, y) {
- var shortest_distance = null;
- var nearest_pad = null;
- // find the nearest pad.
- for (var i in this.landing_pads) {
- // This isn't the real distance, this is the square of the
- // distance -- no point in spending processing time on
- // sqrt.
- var dstx = Math.abs(x - this.landing_pads[i].centerX);
- var dsty = Math.abs(y - this.landing_pads[i].centerY);
- var distance = (dstx * dstx) + (dsty * dsty);
- if (shortest_distance == null || distance < shortest_distance) {
- shortest_distance = distance;
- nearest_pad = this.landing_pads[i];
- }
- }
- if (nearest_pad != this.current_pad) {
- if (this.current_pad) {
- $(this.current_pad.obj).hide();
- }
- this.current_pad = nearest_pad;
- $(nearest_pad.obj).show();
- }
- },
- findDropZone: function(x, y) {
- // Go through our dropzones and see if we're over one.
- var new_dropzone = null;
- for (var i in this.dropzones) {
- // console.log('x:' + x + ' left:' + this.dropzones[i].left + ' right: ' + this.dropzones[i].left + this.dropzones[i].width);
- if (this.dropzones[i].left < x &&
- x < this.dropzones[i].left + this.dropzones[i].width &&
- this.dropzones[i].top < y &&
- y < this.dropzones[i].top + this.dropzones[i].height) {
- new_dropzone = this.dropzones[i];
- break;
- }
- }
- // If we're over one, see if it's different.
- if (new_dropzone && (!this.regionLock || this.regionLockRegions[new_dropzone.region])) {
- var changed = false;
- if (!this.current_dropzone || new_dropzone.obj.id != this.current_dropzone.obj.id) {
- this.changeDropZone(new_dropzone);
- changed = true;
- }
- this.findLandingPad(x, y);
- if (changed) {
- // recalculate the size of our drop zones due to the fact that we're drawing landing pads.
- this.reCalculateDropZones();
- }
- }
- // If we're not over one, be sure to unhilite one if we were just
- // over it.
- else if (this.current_dropzone) {
- this.unsetDropZone();
- }
- },
- /** save button clicked, or pane deleted **/
- savePositions: function() {
- var draggable = Drupal.Panels.Draggable;
- $(draggable.accept).each(function() {
- var val = '';
- $(this).find(draggable.draggable).each(function() {
- if (val) {
- val += ',';
- }
- val += this.id.replace(draggable.draggableId, '');
- });
- var region = this.id.replace(draggable.regionId, '');
- $('input[name="panel[pane][' + region + ']"]').val(val);
- });
- return false;
- }
- };
- Drupal.Panels.DraggableHandler = function() {
- $(this).addClass('panel-draggable');
- var draggable = Drupal.Panels.Draggable;
- var scrollBuffer = 10;
- var scrollDistance = 10;
- var scrollTimer = 30;
- getMouseOffset = function(docPos, mousePos, windowPos) {
- return { x: mousePos.x - docPos.x + windowPos.x, y: mousePos.y - docPos.y + windowPos.y};
- };
- getMousePos = function(ev) {
- ev = ev || window.event;
- if (ev.pageX || ev.pageY) {
- return { x:ev.pageX, y:ev.pageY };
- }
- return {
- x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
- y:ev.clientY + document.body.scrollTop - document.body.clientTop
- };
- };
- getPosition = function(e) {
- /*
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(e, null);
- return {
- x: parseInt(css.getPropertyValue('left')),
- y: parseInt(css.getPropertyValue('top'))
- };
- }
- */
- var left = 0;
- var top = 0;
- while (e.offsetParent) {
- left += e.offsetLeft;
- top += e.offsetTop;
- e = e.offsetParent;
- }
- left += e.offsetLeft;
- top += e.offsetTop;
- return { x:left, y:top };
- };
- mouseUp = function(e) {
- clearTimeout(draggable.timeoutId);
- draggable.dropzones = [];
- if (draggable.current_pad) {
- // Drop the object where we're hovering
- $(draggable.object).insertAfter($(draggable.current_pad.obj));
- Drupal.Panels.changed($(draggable.object));
- }
- else {
- // or put it back where it came from
- $(draggable.object).insertAfter(draggable.placeholder);
- }
- // remove the placeholder
- draggable.placeholder.remove();
- // restore original settings.
- $(draggable.object).css(draggable.original);
- if (draggable.current_dropzone) {
- draggable.unsetDropZone();
- }
- $(document).unbind('mouseup').unbind('mousemove');
- draggable.savePositions();
- };
- mouseMove = function(e) {
- draggable.mousePos = getMousePos(e);
- draggable.findDropZone(draggable.mousePos.x, draggable.mousePos.y);
- var windowMoved = parseInt(draggable.offsetDivHeight - $(draggable.main).innerHeight());
- draggable.object.style.top = draggable.mousePos.y - draggable.mouseOffset.y + windowMoved + 'px';
- draggable.object.style.left = draggable.mousePos.x - draggable.mouseOffset.x + 'px';
- $(draggable.object).toggleClass('moving');
- };
- mouseDown = function(e) {
- // If we mouse-downed over something clickable, don't drag!
- if (e.target.nodeName == 'A' || e.target.nodeName == 'INPUT' || e.target.parentNode.nodeName == 'A' || e.target.nodeName.nodeName == 'INPUT') {
- return;
- }
- draggable.object = $(this).parent(draggable.draggable).get(0);
- draggable.paneId = draggable.object.id.replace(draggable.draggableId, '');
- // create a placeholder so we can put this object back if dropped in an invalid location.
- draggable.placeholder = $('<div class="draggable-placeholder-object" style="display:none"></div>"');
- $(draggable.object).after(draggable.placeholder);
- // Store original CSS so we can put it back.
- draggable.original = {
- position: $(draggable.object).css('position'),
- width: 'auto',
- left: $(draggable.object).css('left'),
- top: $(draggable.object).css('top'),
- 'z-index': $(draggable.object).css('z-index'),
- 'margin-bottom': $(draggable.object).css('margin-bottom'),
- 'margin-top': $(draggable.object).css('margin-top'),
- 'margin-left': $(draggable.object).css('margin-left'),
- 'margin-right': $(draggable.object).css('margin-right'),
- 'padding-bottom': $(draggable.object).css('padding-bottom'),
- 'padding-top': $(draggable.object).css('padding-top'),
- 'padding-left': $(draggable.object).css('padding-left'),
- 'padding-right': $(draggable.object).css('padding-right')
- };
- draggable.mousePos = getMousePos(e);
- var originalPos = $(draggable.object).offset();
- var width = Math.min($(draggable.object).innerWidth(), draggable.maxWidth);
- draggable.offsetDivHeight = $(draggable.main).innerHeight();
- draggable.findDropZone(draggable.mousePos.x, draggable.mousePos.y);
- // Make copies of these because in FF3, they actually change when we
- // move the item, whereas they did not in FF2.
- if (e.layerX || e.layerY) {
- var layerX = e.layerX;
- var layerY = e.layerY;
- }
- else if (e.originalEvent && e.originalEvent.layerX) {
- var layerX = e.originalEvent.layerX;
- var layerY = e.originalEvent.layerY;
- }
- // Make the draggable relative, get it out of the way and make it
- // invisible.
- $(draggable.object).css({
- position: 'relative',
- 'z-index': 100,
- width: width + 'px',
- 'margin-bottom': (-1 * parseInt($(draggable.object).outerHeight())) + 'px',
- 'margin-top': 0,
- 'margin-left': 0,
- 'margin-right': (-1 * parseInt($(draggable.object).outerWidth())) + 'px',
- 'padding-bottom': 0,
- 'padding-top': 0,
- 'padding-left': 0,
- 'padding-right': 0,
- 'left': 0,
- 'top': 0
- })
- .insertAfter($(draggable.main));
- var newPos = $(draggable.object).offset();
- var windowOffset = { left: originalPos.left - newPos.left, top: originalPos.top - newPos.top }
- // if they grabbed outside the area where we make the draggable smaller, move it
- // closer to the cursor.
- if (layerX != 'undefined' && layerX > width) {
- windowOffset.left += layerX - 10;
- }
- else if (layerX != 'undefined' && e.offsetX > width) {
- windowOffset.left += e.offsetX - 10;
- }
- // This is stored so we can move with it.
- draggable.mouseOffset = { x: draggable.mousePos.x - windowOffset.left, y: draggable.mousePos.y - windowOffset.top};
- draggable.offsetDivHeight = $(draggable.main).innerHeight();
- draggable.object.style.top = windowOffset.top + 'px';
- draggable.object.style.left = windowOffset.left + 'px';
- $(document).unbind('mouseup').unbind('mousemove').mouseup(mouseUp).mousemove(mouseMove);
- draggable.calculateDropZones(draggable.mousePos, e);
- draggable.timeoutId = setTimeout('timer()', scrollTimer);
- // If locking to a particular set of regions, set that:
- if (Drupal.settings.Panels && Drupal.settings.Panels.RegionLock && Drupal.settings.Panels.RegionLock[draggable.paneId]) {
- draggable.regionLock = true;
- draggable.regionLockRegions = Drupal.settings.Panels.RegionLock[draggable.paneId];
- }
- else {
- draggable.regionLock = false;
- draggable.regionLockRegions = null;
- }
- return false;
- };
- timer = function() {
- if (!draggable.timeCount) {
- draggable.timeCount = 0;
- }
- draggable.timeCount = draggable.timeCount + 1;
- var left = $(window).scrollLeft();
- var right = left + $(window).width();
- var top = $(window).scrollTop();
- var bottom = top + $(window).height();
- if (draggable.mousePos.x < left + scrollBuffer && left > 0) {
- window.scrollTo(left - scrollDistance, top);
- draggable.mousePos.x -= scrollDistance;
- draggable.object.style.top = draggable.mousePos.y - draggable.mouseOffset.y + 'px';
- }
- else if (draggable.mousePos.x > right - scrollBuffer) {
- window.scrollTo(left + scrollDistance, top);
- draggable.mousePos.x += scrollDistance;
- draggable.object.style.top = draggable.mousePos.y - draggable.mouseOffset.y + 'px';
- }
- else if (draggable.mousePos.y < top + scrollBuffer && top > 0) {
- window.scrollTo(left, top - scrollDistance);
- draggable.mousePos.y -= scrollDistance;
- draggable.object.style.top = draggable.mousePos.y - draggable.mouseOffset.y + 'px';
- }
- else if (draggable.mousePos.y > bottom - scrollBuffer) {
- window.scrollTo(left, top + scrollDistance);
- draggable.mousePos.y += scrollDistance;
- draggable.object.style.top = draggable.mousePos.y - draggable.mouseOffset.y + 'px';
- }
- draggable.timeoutId = setTimeout('timer()', scrollTimer);
- }
- $(this).mousedown(mouseDown);
- };
- $.fn.extend({
- panelsDraggable: Drupal.Panels.DraggableHandler
- });
- /**
- * Implement Drupal behavior for autoattach
- */
- Drupal.behaviors.PanelsDisplayEditor = {
- attach: function(context) {
- // Show javascript only items.
- $('span#panels-js-only').css('display', 'inline');
- $('#panels-dnd-main div.panel-pane:not(.panel-portlet)')
- .addClass('panel-portlet')
- .each(Drupal.Panels.bindPortlet);
- // The above doesn't work if context IS the pane, so do this to catch that.
- if ($(context).hasClass('panel-pane') && !$(context).hasClass('panel-portlet')) {
- $(context)
- .addClass('panel-portlet')
- .each(Drupal.Panels.bindPortlet);
- }
- // Make draggables and make sure their positions are saved.
- $(context).find('div.grabber:not(.panel-draggable)').panelsDraggable();
- Drupal.Panels.Draggable.savePositions();
- // Bind buttons.
- $('#panels-hide-all', context).click(Drupal.Panels.clickHideAll);
- $('#panels-show-all', context).click(Drupal.Panels.clickShowAll);
- Drupal.Panels.bindClickDelete(context);
- $('#panels-live-preview-button:not(.panels-preview-processed)')
- .addClass('panels-preview-processed')
- .click(function () {
- if (!$('#panels-preview').size()) {
- $('#panels-dnd-main').parents('form').after('<div id="panels-preview" class="clearfix"></div>');
- }
- var html = '';
- html += ' <div id="modal-throbber">';
- html += ' <div class="modal-throbber-wrapper">';
- html += Drupal.settings.CToolsModal.throbber;
- html += ' </div>';
- html += ' </div>';
- $('#panels-preview').html(html);
- });
- // Bind modal detach behaviors to cancel current form.
- $(document).bind('CToolsDetachBehaviors', function(event, context) {
- $('#edit-cancel-style', context).trigger('click');
- });
- var setTitleClass = function () {
- if ($('#edit-display-title-hide-title').val() == 2) {
- $('#panels-dnd-main').removeClass('panels-set-title-hide');
- }
- else {
- $('#panels-dnd-main').addClass('panels-set-title-hide');
- }
- }
- // The panes have an option to set the display title, but only if
- // a select is set to the proper value. This sets a class on the
- // main edit div so that the option to set the display title
- // is hidden if that is not selected, and visible if it is.
- $('#edit-display-title-hide-title:not(.panels-title-processed)')
- .addClass('panels-title-processed')
- .change(setTitleClass);
- setTitleClass();
- }
- }
- $(function() {
- /**
- * AJAX responder command to render the preview.
- */
- Drupal.ajax.prototype.commands.panel_preview = function(ajax, command, status) {
- $('#panels-preview').html(command.output);
- }
- });
- })(jQuery);
|