123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- (function($){
- Drupal.behaviors.contextReactionBlock = {attach: function(context) {
- $('form.context-editor:not(.context-block-processed)')
- .addClass('context-block-processed')
- .each(function() {
- var id = $(this).attr('id');
- Drupal.contextBlockEditor = Drupal.contextBlockEditor || {};
- $(this).bind('init.pageEditor', function(event) {
- Drupal.contextBlockEditor[id] = new DrupalContextBlockEditor($(this));
- });
- $(this).bind('start.pageEditor', function(event, context) {
- // Fallback to first context if param is empty.
- if (!context) {
- context = $(this).data('defaultContext');
- }
- Drupal.contextBlockEditor[id].editStart($(this), context);
- });
- $(this).bind('end.pageEditor', function(event) {
- Drupal.contextBlockEditor[id].editFinish();
- });
- });
- //
- // Admin Form =======================================================
- //
- // ContextBlockForm: Init.
- $('#context-blockform:not(.processed)').each(function() {
- $(this).addClass('processed');
- Drupal.contextBlockForm = new DrupalContextBlockForm($(this));
- Drupal.contextBlockForm.setState();
- });
- // ContextBlockForm: Attach block removal handlers.
- // Lives in behaviors as it may be required for attachment to new DOM elements.
- $('#context-blockform a.remove:not(.processed)').each(function() {
- $(this).addClass('processed');
- $(this).click(function() {
- $(this).parents('tr').eq(0).remove();
- Drupal.contextBlockForm.setState();
- return false;
- });
- });
- // Conceal Section title, subtitle and class
- $('div.context-block-browser', context).nextAll('.form-item').hide();
- }};
- /**
- * Context block form. Default form for editing context block reactions.
- */
- DrupalContextBlockForm = function(blockForm) {
- this.state = {};
- this.setState = function() {
- $('table.context-blockform-region', blockForm).each(function() {
- var region = $(this).attr('id').split('context-blockform-region-')[1];
- var blocks = [];
- $('tr', $(this)).each(function() {
- var bid = $(this).attr('id');
- var weight = $(this).find('select,input').first().val();
- blocks.push({'bid' : bid, 'weight' : weight});
- });
- Drupal.contextBlockForm.state[region] = blocks;
- });
- // Serialize here and set form element value.
- $('form input.context-blockform-state').val(JSON.stringify(this.state));
- // Hide enabled blocks from selector that are used
- $('table.context-blockform-region tr').each(function() {
- var bid = Drupal.checkPlain($(this).attr('id'));
- $('div.context-blockform-selector input[value="'+bid+'"]').parents('div.form-item').eq(0).hide();
- });
- // Show blocks in selector that are unused
- $('div.context-blockform-selector input').each(function() {
- var bid = $(this).val();
- if ($('table.context-blockform-region tr#'+bid).size() === 0) {
- $(this).parents('div.form-item').eq(0).show();
- }
- });
- };
- // make sure we update the state right before submits, this takes care of an
- // apparent race condition between saving the state and the weights getting set
- // by tabledrag
- $('#ctools-export-ui-edit-item-form').submit(function() { Drupal.contextBlockForm.setState(); });
- // Tabledrag
- // Add additional handlers to update our blocks.
- $.each(Drupal.settings.tableDrag, function(base) {
- var table = $('#' + base + ':not(.processed)', blockForm);
- if (table && table.is('.context-blockform-region')) {
- table.addClass('processed');
- table.bind('mouseup', function(event) {
- Drupal.contextBlockForm.setState();
- return;
- });
- }
- });
- // Add blocks to a region
- $('td.blocks a', blockForm).each(function() {
- $(this).click(function() {
- var region = $(this).attr('href').split('#')[1];
- var base = "context-blockform-region-"+ region;
- var selected = $("div.context-blockform-selector input:checked");
- if (selected.size() > 0) {
- var weight_warn = false;
- var min_weight_option = -10;
- var max_weight_option = 10;
- var max_observed_weight = min_weight_option - 1;
- $('table#' + base + ' tr').each(function() {
- var weight_input_val = $(this).find('select,input').first().val();
- if (+weight_input_val > +max_observed_weight) {
- max_observed_weight = weight_input_val;
- }
- });
- selected.each(function() {
- // create new block markup
- var block = document.createElement('tr');
- var text = $(this).parents('div.form-item').eq(0).hide().children('label').text();
- var select = '<div class="form-item form-type-select"><select class="tabledrag-hide form-select">';
- var i;
- weight_warn = true;
- var selected_weight = max_weight_option;
- if (max_weight_option >= (1 + +max_observed_weight)) {
- selected_weight = ++max_observed_weight;
- weight_warn = false;
- }
- for (i = min_weight_option; i <= max_weight_option; ++i) {
- select += '<option';
- if (i == selected_weight) {
- select += ' selected=selected';
- }
- select += '>' + i + '</option>';
- }
- select += '</select></div>';
- $(block).attr('id', $(this).attr('value')).addClass('draggable');
- $(block).html("<td>"+ text + "</td><td>" + select + "</td><td><a href='' class='remove'>X</a></td>");
- // add block item to region
- //TODO : Fix it so long blocks don't get stuck when added to top regions and dragged towards bottom regions
- Drupal.tableDrag[base].makeDraggable(block);
- $('table#'+base).append(block);
- if ($.cookie('Drupal.tableDrag.showWeight') == 1) {
- $('table#'+base).find('.tabledrag-hide').css('display', '');
- $('table#'+base).find('.tabledrag-handle').css('display', 'none');
- }
- else {
- $('table#'+base).find('.tabledrag-hide').css('display', 'none');
- $('table#'+base).find('.tabledrag-handle').css('display', '');
- }
- Drupal.attachBehaviors($('table#'+base));
- Drupal.contextBlockForm.setState();
- $(this).removeAttr('checked');
- });
- if (weight_warn) {
- alert(Drupal.t('Desired block weight exceeds available weight options, please check weights for blocks before saving.'));
- }
- }
- return false;
- });
- });
- };
- /**
- * Context block editor. AHAH editor for live block reaction editing.
- */
- DrupalContextBlockEditor = function(editor) {
- this.editor = editor;
- this.state = {};
- this.blocks = {};
- this.regions = {};
- return this;
- };
- DrupalContextBlockEditor.prototype = {
- initBlocks : function(blocks) {
- var self = this;
- this.blocks = blocks;
- blocks.each(function() {
- if($(this).hasClass('context-block-empty')) {
- $(this).removeClass('context-block-hidden');
- }
- $(this).addClass('draggable');
- $(this).prepend($('<a class="context-block-handle"></a>'));
- $(this).prepend($('<a class="context-block-remove"></a>').click(function() {
- $(this).parent ('.block').eq(0).fadeOut('medium', function() {
- $(this).remove();
- self.updateBlocks();
- });
- return false;
- }));
- });
- },
- initRegions : function(regions) {
- this.regions = regions;
- var ref = this;
- $(regions).not('.context-ui-processed')
- .each(function(index, el) {
- $('.context-ui-add-link', el).click(function(e){
- ref.showBlockBrowser($(this).parent());
- }).addClass('context-ui-processed');
- });
- $('.context-block-browser').hide();
- },
- showBlockBrowser : function(region) {
- var toggled = false;
- //figure out the id of the context
- var activeId = $('.context-editing', this.editor).attr('id').replace('-trigger', ''),
- context = $('#' + activeId)[0];
- this.browser = $('.context-block-browser', context).addClass('active');
- //add the filter element to the block browser
- if (!this.browser.has('input.filter').size()) {
- var parent = $('.block-browser-sidebar .filter', this.browser);
- var list = $('.blocks', this.browser);
- new Drupal.Filter (list, false, '.context-block-addable', parent);
- }
- //show a dialog for the blocks list
- this.browser.show().dialog({
- modal : true,
- close : function() {
- $(this).dialog('destroy');
- //reshow all the categories
- $('.category', this).show();
- $(this).hide().appendTo(context).removeClass('active');
- },
- height: (.8 * $(window).height()),
- minHeight:400,
- minWidth:680,
- width:680
- });
- //handle showing / hiding block items when a different category is selected
- $('.context-block-browser-categories', this.browser).change(function(e) {
- //if no category is selected we want to show all the items
- if ($(this).val() == 0) {
- $('.category', self.browser).show();
- } else {
- $('.category', self.browser).hide();
- $('.category-' + $(this).val(), self.browser).show();
- }
- });
- //if we already have the function for a different context, rebind it so we don't get dupes
- if(this.addToRegion) {
- $('.context-block-addable', this.browser).unbind('click.addToRegion')
- }
- //protected function for adding a clicked block to a region
- var self = this;
- this.addToRegion = function(e){
- var ui = {
- 'item' : $(this).clone(),
- 'sender' : $(region)
- };
- $(this).parents('.context-block-browser.active').dialog('close');
- $(region).after(ui.item);
- self.addBlock(e, ui, this.editor, activeId.replace('context-editable-', ''));
- };
- $('.context-block-addable', this.browser).bind('click.addToRegion', this.addToRegion);
- },
- // Update UI to match the current block states.
- updateBlocks : function() {
- var browser = $('div.context-block-browser');
- // For all enabled blocks, mark corresponding addables as having been added.
- $('.block, .admin-block').each(function() {
- var bid = $(this).attr('id').split('block-')[1]; // Ugh.
- });
- // For all hidden addables with no corresponding blocks, mark as addable.
- $('.context-block-item', browser).each(function() {
- var bid = $(this).attr('id').split('context-block-addable-')[1];
- });
- // Mark empty regions.
- $(this.regions).each(function() {
- if ($('.block:has(a.context-block)', this).size() > 0) {
- $(this).removeClass('context-block-region-empty');
- }
- else {
- $(this).addClass('context-block-region-empty');
- }
- });
- },
- // Live update a region
- updateRegion : function(event, ui, region, op) {
- switch (op) {
- case 'over':
- $(region).removeClass('context-block-region-empty');
- break;
- case 'out':
- if (
- // jQuery UI 1.8
- $('.draggable-placeholder', region).size() === 1 &&
- $('.block:has(a.context-block)', region).size() == 0
- ) {
- $(region).addClass('context-block-region-empty');
- }
- break;
- }
- },
- // Remove script elements while dragging & dropping.
- scriptFix : function(event, ui, editor, context) {
- if ($('script', ui.item)) {
- var placeholder = $(Drupal.settings.contextBlockEditor.scriptPlaceholder);
- var label = $('div.handle label', ui.item).text();
- placeholder.children('strong').html(label);
- $('script', ui.item).parent().empty().append(placeholder);
- }
- },
- // Add a block to a region through an AJAX load of the block contents.
- addBlock : function(event, ui, editor, context) {
- var self = this;
- if (ui.item.is('.context-block-addable')) {
- var bid = ui.item.attr('id').split('context-block-addable-')[1];
- // Construct query params for our AJAX block request.
- var params = Drupal.settings.contextBlockEditor.params;
- params.context_block = bid + ',' + context;
- // Replace item with loading block.
- //ui.sender.append(ui.item);
- var blockLoading = $('<div class="context-block-item context-block-loading"><span class="icon"></span></div>');
- ui.item.addClass('context-block-added');
- ui.item.after(blockLoading);
- $.getJSON(Drupal.settings.contextBlockEditor.path, params, function(data) {
- if (data.status) {
- var newBlock = $(data.block);
- if ($('script', newBlock)) {
- $('script', newBlock).remove();
- }
- blockLoading.fadeOut(function() {
- $(this).replaceWith(newBlock);
- self.initBlocks(newBlock);
- self.updateBlocks();
- Drupal.attachBehaviors(newBlock);
- });
- }
- else {
- blockLoading.fadeOut(function() { $(this).remove(); });
- }
- });
- }
- else if (ui.item.is(':has(a.context-block)')) {
- self.updateBlocks();
- }
- },
- // Update form hidden field with JSON representation of current block visibility states.
- setState : function() {
- var self = this;
- $(this.regions).each(function() {
- var region = $('.context-block-region', this).attr('id').split('context-block-region-')[1];
- var blocks = [];
- $('a.context-block', $(this)).each(function() {
- if ($(this).attr('class').indexOf('edit-') != -1) {
- var bid = $(this).attr('id').split('context-block-')[1];
- var context = $(this).attr('class').split('edit-')[1].split(' ')[0];
- context = context ? context : 0;
- var block = {'bid': bid, 'context': context};
- blocks.push(block);
- }
- });
- self.state[region] = blocks;
- });
- // Serialize here and set form element value.
- $('input.context-block-editor-state', this.editor).val(JSON.stringify(this.state));
- },
- //Disable text selection.
- disableTextSelect : function() {
- if ($.browser.safari) {
- $('.block:has(a.context-block):not(:has(input,textarea))').css('WebkitUserSelect','none');
- }
- else if ($.browser.mozilla) {
- $('.block:has(a.context-block):not(:has(input,textarea))').css('MozUserSelect','none');
- }
- else if ($.browser.msie) {
- $('.block:has(a.context-block):not(:has(input,textarea))').bind('selectstart.contextBlockEditor', function() { return false; });
- }
- else {
- $(this).bind('mousedown.contextBlockEditor', function() { return false; });
- }
- },
- //Enable text selection.
- enableTextSelect : function() {
- if ($.browser.safari) {
- $('*').css('WebkitUserSelect','');
- }
- else if ($.browser.mozilla) {
- $('*').css('MozUserSelect','');
- }
- else if ($.browser.msie) {
- $('*').unbind('selectstart.contextBlockEditor');
- }
- else {
- $(this).unbind('mousedown.contextBlockEditor');
- }
- },
- // Start editing. Attach handlers, begin draggable/sortables.
- editStart : function(editor, context) {
- var self = this;
- // This is redundant to the start handler found in context_ui.js.
- // However it's necessary that we trigger this class addition before
- // we call .sortable() as the empty regions need to be visible.
- $(document.body).addClass('context-editing');
- this.editor.addClass('context-editing');
- this.disableTextSelect();
- this.initBlocks($('.block:has(a.context-block.edit-'+context+')'));
- this.initRegions($('.context-block-region').parent());
- this.updateBlocks();
- $('a.context_ui_dialog-stop').hide();
- $('.editing-context-label').remove();
- var label = $('#context-editable-trigger-'+context+' .label').text();
- label = Drupal.t('Now editing: @label', {'@label': label});
- editor.parent().parent().prepend('<div class="editing-context-label">' + label + '</div>');
- // First pass, enable sortables on all regions.
- $(this.regions).each(function() {
- var region = $(this);
- var params = {
- revert: true,
- dropOnEmpty: true,
- placeholder: 'draggable-placeholder',
- forcePlaceholderSize: true,
- items: '> *:has(a.context-block.editable)',
- handle: 'a.context-block-handle',
- start: function(event, ui) { self.scriptFix(event, ui, editor, context); },
- stop: function(event, ui) { self.addBlock(event, ui, editor, context); },
- receive: function(event, ui) { self.addBlock(event, ui, editor, context); },
- over: function(event, ui) { self.updateRegion(event, ui, region, 'over'); },
- out: function(event, ui) { self.updateRegion(event, ui, region, 'out'); },
- cursorAt: {left: 300, top: 0}
- };
- region.sortable(params);
- });
- // Second pass, hook up all regions via connectWith to each other.
- $(this.regions).each(function() {
- $(this).sortable('option', 'connectWith', ['.ui-sortable']);
- });
- // Terrible, terrible workaround for parentoffset issue in Safari.
- // The proper fix for this issue has been committed to jQuery UI, but was
- // not included in the 1.6 release. Therefore, we do a browser agent hack
- // to ensure that Safari users are covered by the offset fix found here:
- // http://dev.jqueryui.com/changeset/2073.
- if ($.ui.version === '1.6' && $.browser.safari) {
- $.browser.mozilla = true;
- }
- },
- // Finish editing. Remove handlers.
- editFinish : function() {
- this.editor.removeClass('context-editing');
- this.enableTextSelect();
- $('.editing-context-label').remove();
- // Remove UI elements.
- $(this.blocks).each(function() {
- $('a.context-block-handle, a.context-block-remove', this).remove();
- if($(this).hasClass('context-block-empty')) {
- $(this).addClass('context-block-hidden');
- }
- $(this).removeClass('draggable');
- });
- $('a.context_ui_dialog-stop').show();
- this.regions.sortable('destroy');
- this.setState();
- // Unhack the user agent.
- if ($.ui.version === '1.6' && $.browser.safari) {
- $.browser.mozilla = false;
- }
- }
- }; //End of DrupalContextBlockEditor prototype
- })(jQuery);
|