first import
This commit is contained in:
144
sites/all/modules/media/js/media.admin.js
Normal file
144
sites/all/modules/media/js/media.admin.js
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @file
|
||||
* Javascript for the interface at admin/content/media and also for interfaces
|
||||
* related to setting up media fields and for media type administration.
|
||||
*
|
||||
* Basically, if it's on the /admin path, it's probably here.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
/**
|
||||
* Functionality for the thumbnail display
|
||||
*/
|
||||
Drupal.behaviors.mediaAdmin = {
|
||||
attach: function (context) {
|
||||
// Show a javascript confirmation dialog if a user has files selected and
|
||||
// they try to switch between the "Thumbnail" and "List" local tasks.
|
||||
$('.media-display-switch a').bind('click', function () {
|
||||
if ($(':checkbox:checked', $('form#media-admin')).length != 0) {
|
||||
return confirm(Drupal.t('If you switch views, you will lose your selection.'));
|
||||
}
|
||||
});
|
||||
|
||||
// Configure the "Add file" link to fire the media browser popup.
|
||||
var $launcherLink = $('<a class="media-launcher" href="#"></a>').html(Drupal.t('Add file'));
|
||||
$launcherLink.bind('click', function () {
|
||||
// This option format needs *serious* work.
|
||||
// Not even bothering documenting it because it needs to be thrown.
|
||||
// See media.browser.js and media.browser.inc - media_browser()
|
||||
// For how it gets passed.
|
||||
var options = {
|
||||
disabledPlugins: ['library'],
|
||||
multiselect: true
|
||||
};
|
||||
Drupal.media.popups.mediaBrowser(function (mediaFiles) {
|
||||
// When the media browser succeeds, we refresh
|
||||
// @TODO: Should jump to the new media file and perhaps highlight it.
|
||||
parent.window.location.reload();
|
||||
return false;
|
||||
}, options);
|
||||
});
|
||||
|
||||
$('ul.action-links', context).prepend($('<li></li>').append($launcherLink));
|
||||
|
||||
if ($('.media-display-thumbnails').length) {
|
||||
// Implements 'select all/none' for thumbnail view.
|
||||
// @TODO: Support grabbing more than one page of thumbnails.
|
||||
var allLink = $('<a href="#">' + Drupal.t('all') + '</a>')
|
||||
.click(function () {
|
||||
$('.media-display-thumbnails', $(this).parents('form')).find(':checkbox').attr('checked', true).change();
|
||||
return false;
|
||||
});
|
||||
var noneLink = $('<a href="#">' + Drupal.t('none') + '</a>')
|
||||
.click(function () {
|
||||
$('.media-display-thumbnails', $(this).parents('form')).find(':checkbox').attr('checked', false).change();
|
||||
return false;
|
||||
});
|
||||
$('<div class="media-thumbnails-select" />')
|
||||
.append('<strong>' + Drupal.t('Select') + ':</strong> ')
|
||||
.append(allLink)
|
||||
.append(', ')
|
||||
.append(noneLink)
|
||||
.prependTo('#media-admin > div')
|
||||
// If the media item is clicked anywhere other than on the image itself
|
||||
// check the checkbox. For the record, JS thinks this is wonky.
|
||||
$('.media-item').bind('click', function (e) {
|
||||
if ($(e.target).is('img, a')) {
|
||||
return;
|
||||
}
|
||||
var checkbox = $(this).parent().find(':checkbox');
|
||||
if (checkbox.is(':checked')) {
|
||||
checkbox.attr('checked', false).change();
|
||||
} else {
|
||||
checkbox.attr('checked', true).change();
|
||||
}
|
||||
});
|
||||
|
||||
// Add an extra class to selected thumbnails.
|
||||
$('.media-display-thumbnails :checkbox').each(function () {
|
||||
var checkbox = $(this);
|
||||
if (checkbox.is(':checked')) {
|
||||
$(checkbox.parents('li').find('.media-item')).addClass('selected');
|
||||
}
|
||||
|
||||
checkbox.bind('change.media', function () {
|
||||
if (checkbox.is(':checked')) {
|
||||
$(checkbox.parents('li').find('.media-item')).addClass('selected');
|
||||
}
|
||||
else {
|
||||
$(checkbox.parents('li').find('.media-item')).removeClass('selected');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// When any checkboxes are clicked on this form check to see if any are checked.
|
||||
// If any checkboxes are checked, show the edit options (@todo rename to edit-actions).
|
||||
$('#media-admin :checkbox').bind('change', function () {
|
||||
Drupal.behaviors.mediaAdmin.showOrHideEditOptions();
|
||||
});
|
||||
|
||||
Drupal.behaviors.mediaAdmin.showOrHideEditOptions();
|
||||
},
|
||||
|
||||
// Checks if any checkboxes on the form are checked, if so it will show the
|
||||
// edit-options panel.
|
||||
showOrHideEditOptions: function() {
|
||||
var fieldset = $('#edit-options');
|
||||
if (!$('#media-admin input[type=checkbox]:checked').size()) {
|
||||
fieldset.slideUp('fast');
|
||||
}
|
||||
else {
|
||||
fieldset.slideDown('fast');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* JavaScript for the Media types administrative form.
|
||||
*/
|
||||
Drupal.behaviors.mediaTypesAdmin = {
|
||||
attach: function (context) {
|
||||
if ($('.form-item-match-type', context).length == 0) {
|
||||
return;
|
||||
}
|
||||
// Toggle the 'other' text field on Match type.
|
||||
if ($('.form-item-match-type input:checked').val() != 'other') {
|
||||
$('.form-item-match-type-other').hide();
|
||||
}
|
||||
$('.form-item-match-type input').change(function () {
|
||||
if ($(this).val() == 'other') {
|
||||
$('.form-item-match-type-other').slideDown('fast');
|
||||
}
|
||||
else {
|
||||
$('.form-item-match-type-other').slideUp('fast');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
})(jQuery);
|
100
sites/all/modules/media/js/media.browser.js
Normal file
100
sites/all/modules/media/js/media.browser.js
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.browser');
|
||||
|
||||
Drupal.media.browser.selectedMedia = [];
|
||||
Drupal.media.browser.mediaAdded = function () {};
|
||||
Drupal.media.browser.selectionFinalized = function (selectedMedia) {
|
||||
// This is intended to be overridden if a callee wants to be triggered
|
||||
// when the media selection is finalized from inside the browser.
|
||||
// This is used for the file upload form for instance.
|
||||
};
|
||||
|
||||
Drupal.behaviors.experimentalMediaBrowser = {
|
||||
attach: function (context) {
|
||||
if (Drupal.settings.media.selectedMedia) {
|
||||
Drupal.media.browser.selectMedia(Drupal.settings.media.selectedMedia);
|
||||
// Fire a confirmation of some sort.
|
||||
Drupal.media.browser.finalizeSelection();
|
||||
}
|
||||
$('#media-browser-tabset').tabs({
|
||||
show: Drupal.media.browser.resizeIframe
|
||||
});
|
||||
|
||||
$('.media-browser-tab').each( Drupal.media.browser.validateButtons );
|
||||
|
||||
}
|
||||
// Wait for additional params to be passed in.
|
||||
};
|
||||
|
||||
Drupal.media.browser.launch = function () {
|
||||
|
||||
};
|
||||
|
||||
Drupal.media.browser.validateButtons = function() {
|
||||
// The media browser runs in an IFRAME. The Drupal.media.popups.mediaBrowser()
|
||||
// function sets up the IFRAME and "OK" and "Cancel" buttons that are outside
|
||||
// of the IFRAME, so that their click handlers can destroy the IFRAME while
|
||||
// retaining information about what media items were selected. However,
|
||||
// Drupal UI convention is to place all action buttons on the same "line"
|
||||
// at the bottom of the form, so if the form within the IFRAME contains a
|
||||
// "Submit" button or other action buttons, then the "OK" and "Cancel"
|
||||
// buttons below the IFRAME break this convention and confuse the user.
|
||||
// Therefore, we add "Submit" and "Cancel" buttons inside the IFRAME, and
|
||||
// have their click action trigger the click action of the corresonding
|
||||
// "OK" and "Cancel" buttons that are outside the IFRAME. media.css contains
|
||||
// CSS rules that hide the outside buttons.
|
||||
//
|
||||
// We don't add a "Submit" button if the form already has one, since in these
|
||||
// cases, another round-trip to the server is needed before the user's
|
||||
// selection is finalized. For these cases, when the form's real Submit
|
||||
// button is clicked, the server either returns another form for the user to
|
||||
// fill out, or else a completion page that contains or sets the
|
||||
// Drupal.media.browser.selectedMedia variable. If the latter, then
|
||||
// Drupal.media.popups.mediaBrowser.mediaBrowserOnLoad() auto-triggers the
|
||||
// "OK" button action to finalize the selection and remove the IFRAME.
|
||||
//
|
||||
// @todo An alternate, less hacky solution would be most welcome.
|
||||
if (!($('.form-submit', this).length > 0)) {
|
||||
$('<a class="button button-yes fake-ok">' + Drupal.t('Submit') + '</a>').appendTo(this).bind('click', Drupal.media.browser.submit);
|
||||
if (!($('.fake-cancel', this).length > 0)) {
|
||||
$('<a class="button button-no fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo(this).bind('click', Drupal.media.browser.submit);
|
||||
}
|
||||
} else if (!($('.fake-cancel', this).length > 0)) {
|
||||
var parent = $('.form-actions', this);
|
||||
if (!parent.length) {
|
||||
parent = $('form > div', this);
|
||||
}
|
||||
$('<a class="button button-no fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo(parent).bind('click', Drupal.media.browser.submit);
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.browser.submit = function () {
|
||||
// @see Drupal.media.browser.validateButtons().
|
||||
var buttons = $(parent.window.document.body).find('#mediaBrowser').parent('.ui-dialog').find('.ui-dialog-buttonpane button');
|
||||
if ($(this).hasClass('fake-cancel')) {
|
||||
buttons[1].click();
|
||||
} else {
|
||||
buttons[0].click();
|
||||
}
|
||||
}
|
||||
|
||||
Drupal.media.browser.selectMedia = function (selectedMedia) {
|
||||
Drupal.media.browser.selectedMedia = selectedMedia;
|
||||
};
|
||||
|
||||
Drupal.media.browser.finalizeSelection = function () {
|
||||
if (!Drupal.media.browser.selectedMedia) {
|
||||
throw new exception(Drupal.t('Cannot continue, nothing selected'));
|
||||
}
|
||||
else {
|
||||
Drupal.media.browser.selectionFinalized(Drupal.media.browser.selectedMedia);
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.browser.resizeIframe = function (event) {
|
||||
var h = $('body').height();
|
||||
$(parent.window.document).find('#mediaBrowser').height(h);
|
||||
};
|
||||
|
||||
}(jQuery));
|
19
sites/all/modules/media/js/media.core.js
Normal file
19
sites/all/modules/media/js/media.core.js
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
/**
|
||||
* Creates a namespace.
|
||||
*
|
||||
* @return
|
||||
* The created namespace object.
|
||||
*/
|
||||
function namespace () {
|
||||
var a=arguments, o=null, i, j, d;
|
||||
for (i=0; i<a.length; i=i+1) {
|
||||
d=a[i].split(".");
|
||||
o=window;
|
||||
for (j=0; j<d.length; j=j+1) {
|
||||
o[d[j]]=o[d[j]] || {};
|
||||
o=o[d[j]];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
};
|
48
sites/all/modules/media/js/media.format_form.js
Normal file
48
sites/all/modules/media/js/media.format_form.js
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Attach behaviors to formatter radio select when selecting a media's display
|
||||
* formatter.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.formatForm');
|
||||
|
||||
Drupal.media.mediaFormatSelected = {};
|
||||
|
||||
Drupal.behaviors.mediaFormatForm = {
|
||||
attach: function (context, settings) {
|
||||
// Add "Submit" and "Cancel" buttons inside the IFRAME that trigger the
|
||||
// behavior of the hidden "OK" and "Cancel" buttons that are outside the
|
||||
// IFRAME. See Drupal.media.browser.validateButtons() for more details.
|
||||
$('<a class="button fake-ok">' + Drupal.t('Submit') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
|
||||
$('<a class="button fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
|
||||
|
||||
if (Drupal.settings.media_format_form.autosubmit) {
|
||||
$('.button.fake-ok').click();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.formatForm.getOptions = function () {
|
||||
// Get all the values
|
||||
var ret = {}; $.each($('#media-format-form fieldset#edit-options *').serializeArray(), function (i, field) { ret[field.name] = field.value; });
|
||||
return ret;
|
||||
};
|
||||
|
||||
Drupal.media.formatForm.getFormattedMedia = function () {
|
||||
var formatType = $("select#edit-format option:selected").val();
|
||||
return { type: formatType, options: Drupal.media.formatForm.getOptions(), html: Drupal.settings.media.formatFormFormats[formatType] };
|
||||
};
|
||||
|
||||
Drupal.media.formatForm.submit = function () {
|
||||
// @see Drupal.behaviors.mediaFormatForm.attach().
|
||||
var buttons = $(parent.window.document.body).find('#mediaStyleSelector').parent('.ui-dialog').find('.ui-dialog-buttonpane button');
|
||||
if ($(this).hasClass('fake-cancel')) {
|
||||
buttons[1].click();
|
||||
} else {
|
||||
buttons[0].click();
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
75
sites/all/modules/media/js/media.js
Normal file
75
sites/all/modules/media/js/media.js
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file handles the JS for Media Module functions.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
/**
|
||||
* Loads media browsers and callbacks, specifically for media as a field.
|
||||
*/
|
||||
Drupal.behaviors.mediaElement = {
|
||||
attach: function (context, settings) {
|
||||
// Options set from media.fields.inc for the types, etc to show in the browser.
|
||||
|
||||
// For each widget (in case of multi-entry)
|
||||
$('.media-widget', context).once('mediaBrowserLaunch', function () {
|
||||
var options = settings.media.elements[this.id];
|
||||
globalOptions = {};
|
||||
if (options.global != undefined) {
|
||||
var globalOptions = options.global;
|
||||
}
|
||||
//options = Drupal.settings.media.fields[this.id];
|
||||
var fidField = $('.fid', this);
|
||||
var previewField = $('.preview', this);
|
||||
var removeButton = $('.remove', this); // Actually a link, but looks like a button.
|
||||
|
||||
// Show the Remove button if there's an already selected media.
|
||||
if (fidField.val() != 0) {
|
||||
removeButton.css('display', 'inline-block');
|
||||
}
|
||||
|
||||
// When someone clicks the link to pick media (or clicks on an existing thumbnail)
|
||||
$('.launcher', this).bind('click', function () {
|
||||
// Launch the browser, providing the following callback function
|
||||
// @TODO: This should not be an anomyous function.
|
||||
Drupal.media.popups.mediaBrowser(function (mediaFiles) {
|
||||
if (mediaFiles.length < 0) {
|
||||
return;
|
||||
}
|
||||
var mediaFile = mediaFiles[0];
|
||||
// Set the value of the filefield fid (hidden).
|
||||
fidField.val(mediaFile.fid);
|
||||
// Set the preview field HTML.
|
||||
previewField.html(mediaFile.preview);
|
||||
// Show the Remove button.
|
||||
removeButton.show();
|
||||
}, globalOptions);
|
||||
return false;
|
||||
});
|
||||
|
||||
// When someone clicks the Remove button.
|
||||
$('.remove', this).bind('click', function () {
|
||||
// Set the value of the filefield fid (hidden).
|
||||
fidField.val(0);
|
||||
// Set the preview field HTML.
|
||||
previewField.html('');
|
||||
// Hide the Remove button.
|
||||
removeButton.hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.media-edit-link', this).bind('click', function () {
|
||||
var fid = fidField.val();
|
||||
if (fid) {
|
||||
Drupal.media.popups.mediaFieldEditor(fid, function (r) { alert(r); });
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
358
sites/all/modules/media/js/media.popups.js
Normal file
358
sites/all/modules/media/js/media.popups.js
Normal file
@@ -0,0 +1,358 @@
|
||||
|
||||
/**
|
||||
* @file: Popup dialog interfaces for the media project.
|
||||
*
|
||||
* Drupal.media.popups.mediaBrowser
|
||||
* Launches the media browser which allows users to pick a piece of media.
|
||||
*
|
||||
* Drupal.media.popups.mediaStyleSelector
|
||||
* Launches the style selection form where the user can choose
|
||||
* what format / style they want their media in.
|
||||
*
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.popups');
|
||||
|
||||
/**
|
||||
* Media browser popup. Creates a media browser dialog.
|
||||
*
|
||||
* @param {function}
|
||||
* onSelect Callback for when dialog is closed, received (Array
|
||||
* media, Object extra);
|
||||
* @param {Object}
|
||||
* globalOptions Global options that will get passed upon initialization of the browser.
|
||||
* @see Drupal.media.popups.mediaBrowser.getDefaults();
|
||||
*
|
||||
* @param {Object}
|
||||
* pluginOptions Options for specific plugins. These are passed
|
||||
* to the plugin upon initialization. If a function is passed here as
|
||||
* a callback, it is obviously not passed, but is accessible to the plugin
|
||||
* in Drupal.settings.variables.
|
||||
*
|
||||
* Example
|
||||
* pluginOptions = {library: {url_include_patterns:'/foo/bar'}};
|
||||
*
|
||||
* @param {Object}
|
||||
* widgetOptions Options controlling the appearance and behavior of the
|
||||
* modal dialog.
|
||||
* @see Drupal.media.popups.mediaBrowser.getDefaults();
|
||||
*/
|
||||
Drupal.media.popups.mediaBrowser = function (onSelect, globalOptions, pluginOptions, widgetOptions) {
|
||||
var options = Drupal.media.popups.mediaBrowser.getDefaults();
|
||||
options.global = $.extend({}, options.global, globalOptions);
|
||||
options.plugins = pluginOptions;
|
||||
options.widget = $.extend({}, options.widget, widgetOptions);
|
||||
|
||||
// Create it as a modal window.
|
||||
var browserSrc = options.widget.src;
|
||||
if ($.isArray(browserSrc) && browserSrc.length) {
|
||||
browserSrc = browserSrc[browserSrc.length - 1];
|
||||
}
|
||||
// Params to send along to the iframe. WIP.
|
||||
var params = {};
|
||||
$.extend(params, options.global);
|
||||
params.plugins = options.plugins;
|
||||
|
||||
browserSrc += '&' + $.param(params);
|
||||
var mediaIframe = Drupal.media.popups.getPopupIframe(browserSrc, 'mediaBrowser');
|
||||
// Attach the onLoad event
|
||||
mediaIframe.bind('load', options, options.widget.onLoad);
|
||||
/**
|
||||
* Setting up the modal dialog
|
||||
*/
|
||||
|
||||
var ok = 'OK';
|
||||
var cancel = 'Cancel';
|
||||
var notSelected = 'You have not selected anything!';
|
||||
|
||||
if (Drupal && Drupal.t) {
|
||||
ok = Drupal.t(ok);
|
||||
cancel = Drupal.t(cancel);
|
||||
notSelected = Drupal.t(notSelected);
|
||||
}
|
||||
|
||||
// @todo: let some options come through here. Currently can't be changed.
|
||||
var dialogOptions = options.dialog;
|
||||
|
||||
dialogOptions.buttons[ok] = function () {
|
||||
var selected = this.contentWindow.Drupal.media.browser.selectedMedia;
|
||||
if (selected.length < 1) {
|
||||
alert(notSelected);
|
||||
return;
|
||||
}
|
||||
onSelect(selected);
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
dialogOptions.buttons[cancel] = function () {
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
|
||||
// Remove the title bar.
|
||||
mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
|
||||
Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
|
||||
return mediaIframe;
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaBrowser.mediaBrowserOnLoad = function (e) {
|
||||
var options = e.data;
|
||||
if (this.contentWindow.Drupal.media.browser.selectedMedia.length > 0) {
|
||||
var ok = $(this).dialog('option', 'buttons')['OK'];
|
||||
ok.call(this);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaBrowser.getDefaults = function () {
|
||||
return {
|
||||
global: {
|
||||
types: [], // Types to allow, defaults to all.
|
||||
activePlugins: [] // If provided, a list of plugins which should be enabled.
|
||||
},
|
||||
widget: { // Settings for the actual iFrame which is launched.
|
||||
src: Drupal.settings.media.browserUrl, // Src of the media browser (if you want to totally override it)
|
||||
onLoad: Drupal.media.popups.mediaBrowser.mediaBrowserOnLoad // Onload function when iFrame loads.
|
||||
},
|
||||
dialog: Drupal.media.popups.getDialogOptions()
|
||||
};
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaBrowser.finalizeSelection = function () {
|
||||
var selected = this.contentWindow.Drupal.media.browser.selectedMedia;
|
||||
if (selected.length < 1) {
|
||||
alert(notSelected);
|
||||
return;
|
||||
}
|
||||
onSelect(selected);
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Style chooser Popup. Creates a dialog for a user to choose a media style.
|
||||
*
|
||||
* @param mediaFile
|
||||
* The mediaFile you are requesting this formatting form for.
|
||||
* @todo: should this be fid? That's actually all we need now.
|
||||
*
|
||||
* @param Function
|
||||
* onSubmit Function to be called when the user chooses a media
|
||||
* style. Takes one parameter (Object formattedMedia).
|
||||
*
|
||||
* @param Object
|
||||
* options Options for the mediaStyleChooser dialog.
|
||||
*/
|
||||
Drupal.media.popups.mediaStyleSelector = function (mediaFile, onSelect, options) {
|
||||
var defaults = Drupal.media.popups.mediaStyleSelector.getDefaults();
|
||||
// @todo: remove this awful hack :(
|
||||
defaults.src = defaults.src.replace('-media_id-', mediaFile.fid);
|
||||
options = $.extend({}, defaults, options);
|
||||
// Create it as a modal window.
|
||||
var mediaIframe = Drupal.media.popups.getPopupIframe(options.src, 'mediaStyleSelector');
|
||||
// Attach the onLoad event
|
||||
mediaIframe.bind('load', options, options.onLoad);
|
||||
|
||||
/**
|
||||
* Set up the button text
|
||||
*/
|
||||
var ok = 'OK';
|
||||
var cancel = 'Cancel';
|
||||
var notSelected = 'Very sorry, there was an unknown error embedding media.';
|
||||
|
||||
if (Drupal && Drupal.t) {
|
||||
ok = Drupal.t(ok);
|
||||
cancel = Drupal.t(cancel);
|
||||
notSelected = Drupal.t(notSelected);
|
||||
}
|
||||
|
||||
// @todo: let some options come through here. Currently can't be changed.
|
||||
var dialogOptions = Drupal.media.popups.getDialogOptions();
|
||||
|
||||
dialogOptions.buttons[ok] = function () {
|
||||
|
||||
var formattedMedia = this.contentWindow.Drupal.media.formatForm.getFormattedMedia();
|
||||
if (!formattedMedia) {
|
||||
alert(notSelected);
|
||||
return;
|
||||
}
|
||||
onSelect(formattedMedia);
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
dialogOptions.buttons[cancel] = function () {
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
|
||||
// Remove the title bar.
|
||||
mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
|
||||
Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
|
||||
return mediaIframe;
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaStyleSelector.mediaBrowserOnLoad = function (e) {
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaStyleSelector.getDefaults = function () {
|
||||
return {
|
||||
src: Drupal.settings.media.styleSelectorUrl,
|
||||
onLoad: Drupal.media.popups.mediaStyleSelector.mediaBrowserOnLoad
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Style chooser Popup. Creates a dialog for a user to choose a media style.
|
||||
*
|
||||
* @param mediaFile
|
||||
* The mediaFile you are requesting this formatting form for.
|
||||
* @todo: should this be fid? That's actually all we need now.
|
||||
*
|
||||
* @param Function
|
||||
* onSubmit Function to be called when the user chooses a media
|
||||
* style. Takes one parameter (Object formattedMedia).
|
||||
*
|
||||
* @param Object
|
||||
* options Options for the mediaStyleChooser dialog.
|
||||
*/
|
||||
Drupal.media.popups.mediaFieldEditor = function (fid, onSelect, options) {
|
||||
var defaults = Drupal.media.popups.mediaFieldEditor.getDefaults();
|
||||
// @todo: remove this awful hack :(
|
||||
defaults.src = defaults.src.replace('-media_id-', fid);
|
||||
options = $.extend({}, defaults, options);
|
||||
// Create it as a modal window.
|
||||
var mediaIframe = Drupal.media.popups.getPopupIframe(options.src, 'mediaFieldEditor');
|
||||
// Attach the onLoad event
|
||||
// @TODO - This event is firing too early in IE on Windows 7,
|
||||
// - so the height being calculated is too short for the content.
|
||||
mediaIframe.bind('load', options, options.onLoad);
|
||||
|
||||
/**
|
||||
* Set up the button text
|
||||
*/
|
||||
var ok = 'OK';
|
||||
var cancel = 'Cancel';
|
||||
var notSelected = 'Very sorry, there was an unknown error embedding media.';
|
||||
|
||||
if (Drupal && Drupal.t) {
|
||||
ok = Drupal.t(ok);
|
||||
cancel = Drupal.t(cancel);
|
||||
notSelected = Drupal.t(notSelected);
|
||||
}
|
||||
|
||||
// @todo: let some options come through here. Currently can't be changed.
|
||||
var dialogOptions = Drupal.media.popups.getDialogOptions();
|
||||
|
||||
dialogOptions.buttons[ok] = function () {
|
||||
alert('hell yeah');
|
||||
return "poo";
|
||||
|
||||
var formattedMedia = this.contentWindow.Drupal.media.formatForm.getFormattedMedia();
|
||||
if (!formattedMedia) {
|
||||
alert(notSelected);
|
||||
return;
|
||||
}
|
||||
onSelect(formattedMedia);
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
dialogOptions.buttons[cancel] = function () {
|
||||
$(this).dialog("destroy");
|
||||
$(this).remove();
|
||||
};
|
||||
|
||||
Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
|
||||
// Remove the title bar.
|
||||
mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
|
||||
Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
|
||||
return mediaIframe;
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaFieldEditor.mediaBrowserOnLoad = function (e) {
|
||||
|
||||
};
|
||||
|
||||
Drupal.media.popups.mediaFieldEditor.getDefaults = function () {
|
||||
return {
|
||||
// @todo: do this for real
|
||||
src: '/media/-media_id-/edit?render=media-popup',
|
||||
onLoad: Drupal.media.popups.mediaFieldEditor.mediaBrowserOnLoad
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generic functions to both the media-browser and style selector
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the commonly used options for the dialog.
|
||||
*/
|
||||
Drupal.media.popups.getDialogOptions = function () {
|
||||
return {
|
||||
buttons: {},
|
||||
dialogClass: 'media-wrapper',
|
||||
modal: true,
|
||||
draggable: false,
|
||||
resizable: false,
|
||||
minWidth: 600,
|
||||
width: 800,
|
||||
height: 550,
|
||||
position: 'center',
|
||||
overlay: {
|
||||
backgroundColor: '#000000',
|
||||
opacity: 0.4
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Created padding on a dialog
|
||||
*
|
||||
* @param jQuery dialogElement
|
||||
* The element which has .dialog() attached to it.
|
||||
*/
|
||||
Drupal.media.popups.setDialogPadding = function (dialogElement) {
|
||||
// @TODO: Perhaps remove this hardcoded reference to height.
|
||||
// - It's included to make IE on Windows 7 display the dialog without
|
||||
// collapsing. 550 is the height that displays all of the tab panes
|
||||
// within the Add Media overlay. This is either a bug in the jQuery
|
||||
// UI library, a bug in IE on Windows 7 or a bug in the way the
|
||||
// dialog is instantiated. Or a combo of the three.
|
||||
// All browsers except IE on Win7 ignore these defaults and adjust
|
||||
// the height of the iframe correctly to match the content in the panes
|
||||
dialogElement.height(dialogElement.dialog('option', 'height'));
|
||||
dialogElement.width(dialogElement.dialog('option', 'width'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an iframe to serve as the dialog's contents. Common to both plugins.
|
||||
*/
|
||||
Drupal.media.popups.getPopupIframe = function (src, id, options) {
|
||||
var defaults = {width: '800px', scrolling: 'no'};
|
||||
var options = $.extend({}, defaults, options);
|
||||
|
||||
return $('<iframe class="media-modal-frame"/>')
|
||||
.attr('src', src)
|
||||
.attr('width', options.width)
|
||||
.attr('id', id)
|
||||
.attr('scrolling', options.scrolling);
|
||||
};
|
||||
|
||||
Drupal.media.popups.overlayDisplace = function (dialog) {
|
||||
if (parent.window.Drupal.overlay) {
|
||||
var overlayDisplace = parent.window.Drupal.overlay.getDisplacement('top');
|
||||
if (dialog.offset().top < overlayDisplace) {
|
||||
dialog.css('top', overlayDisplace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
29
sites/all/modules/media/js/plugins/media.fromurl.js
Normal file
29
sites/all/modules/media/js/plugins/media.fromurl.js
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.browser.plugin');
|
||||
|
||||
Drupal.media.browser.plugin.fromurl = function (mediaBrowser, options) {
|
||||
return {
|
||||
init: function () {
|
||||
tabset = mediaBrowser.getTabset();
|
||||
tabset.tabs('add', '#fromurl', 'From URL');
|
||||
mediaBrowser.listen('tabs.show', function (e, id) {
|
||||
if (id == 'fromurl') {
|
||||
// We only need to set this once.
|
||||
// We probably could set it upon load.
|
||||
if (mediaBrowser.getActivePanel().html() == '') {
|
||||
mediaBrowser.getActivePanel().html(options.fromUrlForm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// For now, I guess self registration makes sense.
|
||||
// Really though, we should be doing it via drupal_add_js and some settings
|
||||
// from the drupal variable.
|
||||
// @todo: needs a review.
|
||||
Drupal.media.browser.register('fromurl', Drupal.media.browser.plugin.fromurl, {});
|
||||
|
||||
})(jQuery);
|
23
sites/all/modules/media/js/plugins/media.library.css
Normal file
23
sites/all/modules/media/js/plugins/media.library.css
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
ul#media-browser-library-list {
|
||||
list-style: none;
|
||||
margin: -10px 0 0 0;
|
||||
padding: 0px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#media-tab-library #container{
|
||||
padding:20px 0;
|
||||
}
|
||||
|
||||
#media-tab-library #scrollbox{
|
||||
height: 300px;
|
||||
overflow:auto;
|
||||
overflow-x:hidden;
|
||||
}
|
||||
|
||||
#scrollbox #status {
|
||||
clear: both;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
184
sites/all/modules/media/js/plugins/media.library.js
Normal file
184
sites/all/modules/media/js/plugins/media.library.js
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.browser');
|
||||
|
||||
Drupal.behaviors.mediaLibrary = {
|
||||
attach: function (context, settings) {
|
||||
var library = new Drupal.media.browser.library(Drupal.settings.media.browser.library);
|
||||
$('#media-browser-tabset').bind('tabsshow', function (event, ui) {
|
||||
if (ui.tab.hash === '#media-tab-library') {
|
||||
// Grab the parameters from the Drupal.settings object
|
||||
var params = {};
|
||||
for (var parameter in Drupal.settings.media.browser.library) {
|
||||
params[parameter] = Drupal.settings.media.browser.library[parameter];
|
||||
}
|
||||
library.start($(ui.panel), params);
|
||||
$('#scrollbox').bind('scroll', library, library.scrollUpdater);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.browser.library = function (settings) {
|
||||
this.settings = Drupal.media.browser.library.getDefaults();
|
||||
$.extend(this.settings, settings);
|
||||
|
||||
this.done = false; // Keeps track of if the last request for media returned 0 results.
|
||||
|
||||
this.cursor = 0; // keeps track of what the last requested media object was.
|
||||
this.mediaFiles = []; // An array of loaded media files from the server.
|
||||
this.selectedMediaFiles = [];
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.getDefaults = function () {
|
||||
return {
|
||||
emtpyMessage: Drupal.t('There is nothing in your media library. Select the Upload tab above to add a file.'),
|
||||
limit: 15
|
||||
};
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.prototype.start = function (renderElement, params) {
|
||||
this.renderElement = renderElement;
|
||||
this.params = params;
|
||||
// Change the behavior dependent on multiselect
|
||||
if (params.multiselect) {
|
||||
this.clickFunction = this.multiSelect;
|
||||
} else {
|
||||
this.clickFunction = this.singleSelect;
|
||||
}
|
||||
this.loadMedia();
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends more media onto the list
|
||||
*/
|
||||
Drupal.media.browser.library.prototype.loadMedia = function () {
|
||||
var that = this;
|
||||
$('#status').text(Drupal.t('Loading...')).show();
|
||||
$.extend(this.params, {start: this.cursor, limit: this.settings.limit});
|
||||
|
||||
var gotMedia = function (data, status) {
|
||||
$('#status').text('').hide();
|
||||
if (data.media.length < that.params.limit) {
|
||||
// We remove the scroll event listener, nothing more to load after this.
|
||||
$('#scrollbox').unbind('scroll');
|
||||
}
|
||||
that.mediaFiles = that.mediaFiles.concat(data.media);
|
||||
that.render(that.renderElement);
|
||||
// Remove the flag that prevents loading of more media
|
||||
that.loading = false;
|
||||
};
|
||||
|
||||
var errorCallback = function () {
|
||||
alert(Drupal.t('Error getting media.'));
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: this.settings.getMediaUrl,
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
data: this.params,
|
||||
error: errorCallback,
|
||||
success: gotMedia
|
||||
});
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.prototype.scrollUpdater = function (e){
|
||||
if (!e.data.loading) {
|
||||
var scrollbox = $('#scrollbox');
|
||||
var scrolltop = scrollbox.attr('scrollTop');
|
||||
var scrollheight = scrollbox.attr('scrollHeight');
|
||||
var windowheight = scrollbox.attr('clientHeight');
|
||||
var scrolloffset = 20;
|
||||
|
||||
if(scrolltop >= (scrollheight - (windowheight + scrolloffset))) {
|
||||
// Set a flag so we don't make multiple concurrent AJAX calls
|
||||
e.data.loading = true;
|
||||
// Fetch new items
|
||||
e.data.loadMedia();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the next media object and increments the cursor.
|
||||
*/
|
||||
Drupal.media.browser.library.prototype.getNextMedia = function () {
|
||||
if (this.cursor >= this.mediaFiles.length) {
|
||||
return false;
|
||||
}
|
||||
var ret = this.mediaFiles[this.cursor];
|
||||
this.cursor += 1;
|
||||
return ret;
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.prototype.render = function (renderElement) {
|
||||
|
||||
if (this.mediaFiles.length < 1) {
|
||||
$('<div id="media-empty-message" class="media-empty-message"></div>').appendTo(renderElement)
|
||||
.html(this.emptyMessage);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
var mediaList = $('#media-browser-library-list', renderElement);
|
||||
// If the list doesn't exist, bail.
|
||||
if (mediaList.length === 0) {
|
||||
throw('Cannot continue, list element is missing');
|
||||
}
|
||||
}
|
||||
|
||||
while (this.cursor < this.mediaFiles.length) {
|
||||
var mediaFile = this.getNextMedia();
|
||||
|
||||
var data = {};
|
||||
data.obj = this;
|
||||
data.file = mediaFile;
|
||||
|
||||
var listItem = $('<li></li>').appendTo(mediaList)
|
||||
.attr('id', 'media-item-' + mediaFile.fid)
|
||||
.html(mediaFile.preview)
|
||||
.bind('click', data, this.clickFunction);
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.prototype.mediaSelected = function (media) {
|
||||
Drupal.media.browser.selectMedia(media);
|
||||
};
|
||||
|
||||
Drupal.media.browser.library.prototype.singleSelect = function (event) {
|
||||
var lib = event.data.obj;
|
||||
var file = event.data.file;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
$('.media-item').removeClass('selected');
|
||||
$('.media-item', $(this)).addClass('selected');
|
||||
lib.mediaSelected([event.data.file]);
|
||||
return false;
|
||||
}
|
||||
|
||||
Drupal.media.browser.library.prototype.multiSelect = function (event) {
|
||||
var lib = event.data.obj
|
||||
var file = event.data.file;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Turn off or on the selection of this item
|
||||
$('.media-item', $(this)).toggleClass('selected');
|
||||
|
||||
// Add or remove the media file from the array
|
||||
var index = $.inArray(file, lib.selectedMediaFiles);
|
||||
if (index == -1) {
|
||||
// Media file isn't selected, add it
|
||||
lib.selectedMediaFiles.push(file);
|
||||
} else {
|
||||
// Media file has previously been selected, remove it
|
||||
lib.selectedMediaFiles.splice(index, 1);
|
||||
}
|
||||
|
||||
// Pass the array of selected media files to the invoker
|
||||
lib.mediaSelected(lib.selectedMediaFiles);
|
||||
return false;
|
||||
}
|
||||
|
||||
}(jQuery));
|
30
sites/all/modules/media/js/plugins/media.upload.js
Normal file
30
sites/all/modules/media/js/plugins/media.upload.js
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
(function ($) {
|
||||
namespace('Drupal.media.browser.plugin');
|
||||
|
||||
Drupal.media.browser.plugin.upload = function (mediaBrowser, options) {
|
||||
return {
|
||||
/* Abstract */
|
||||
init: function () {
|
||||
tabset = mediaBrowser.getTabset();
|
||||
tabset.tabs('add', '#upload', Drupal.t('Upload'));
|
||||
mediaBrowser.listen('tabs.show', function (e, id) {
|
||||
if (id == 'upload') {
|
||||
// We only need to set this once.
|
||||
// We probably could set it upon load.
|
||||
if (mediaBrowser.getActivePanel().html() == '') {
|
||||
mediaBrowser.getActivePanel().html(options.uploadForm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// For now, I guess self registration makes sense.
|
||||
// Really though, we should be doing it via drupal_add_js and some settings
|
||||
// from the drupal variable.
|
||||
// @todo: needs a review.
|
||||
Drupal.media.browser.register('upload', Drupal.media.browser.plugin.upload, {});
|
||||
|
||||
})(jQuery);
|
21
sites/all/modules/media/js/plugins/media.upload_multiple.js
Normal file
21
sites/all/modules/media/js/plugins/media.upload_multiple.js
Normal file
@@ -0,0 +1,21 @@
|
||||
Drupal.behaviors.mediaUploadMultiple = {};
|
||||
|
||||
Drupal.behaviors.mediaUploadMultiple.attach = function (context, settings) {
|
||||
// When the plupload element initializes, it expands the size of the elements
|
||||
// it has created, so we need to resize the browser iframe after it's done.
|
||||
var uploader = jQuery('#edit-upload').pluploadQueue();
|
||||
if (uploader) {
|
||||
// Handle the case in which the uploader has already finished initializing.
|
||||
Drupal.media.browser.resizeIframe();
|
||||
// Handle the case in which the uploader has not yet initialized.
|
||||
uploader.bind("PostInit", Drupal.media.browser.resizeIframe);
|
||||
|
||||
uploader.bind('StateChanged', Drupal.behaviors.mediaUploadMultiple.submit);
|
||||
}
|
||||
};
|
||||
|
||||
Drupal.behaviors.mediaUploadMultiple.submit = function (uploader, file) {
|
||||
if (uploader.state == 2) {
|
||||
jQuery('#media-add-upload-multiple .form-submit').val(Drupal.t('Loading...'));
|
||||
}
|
||||
};
|
12
sites/all/modules/media/js/util/ba-debug.min.js
vendored
Normal file
12
sites/all/modules/media/js/util/ba-debug.min.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* debug - v0.3 - 6/8/2009
|
||||
* http://benalman.com/projects/javascript-debug-console-log/
|
||||
*
|
||||
* Copyright (c) 2009 "Cowboy" Ben Alman
|
||||
* Licensed under the MIT license
|
||||
* http://benalman.com/about/license/
|
||||
*
|
||||
* With lots of help from Paul Irish!
|
||||
* http://paulirish.com/
|
||||
*/
|
||||
window.debug=(function(){var c=this,e=Array.prototype.slice,b=c.console,i={},f,g,j=9,d=["error","warn","info","debug","log"],m="assert clear count dir dirxml group groupEnd profile profileEnd time timeEnd trace".split(" "),k=m.length,a=[];while(--k>=0){(function(n){i[n]=function(){j!==0&&b&&b[n]&&b[n].apply(b,arguments)}})(m[k])}k=d.length;while(--k>=0){(function(n,o){i[o]=function(){var q=e.call(arguments),p=[o].concat(q);a.push(p);h(p);if(!b||!l(n)){return}b.firebug?b[o].apply(c,q):b[o]?b[o](q):b.log(q)}})(k,d[k])}function h(n){if(f&&(g||!b||!b.log)){f.apply(c,n)}}i.setLevel=function(n){j=typeof n==="number"?n:9};function l(n){return j>0?j>n:d.length+j<=n}i.setCallback=function(){var o=e.call(arguments),n=a.length,p=n;f=o.shift()||null;g=typeof o[0]==="boolean"?o.shift():false;p-=typeof o[0]==="number"?o.shift():n;while(p<n){h(a[p++])}};return i})();
|
481
sites/all/modules/media/js/util/json2.js
Normal file
481
sites/all/modules/media/js/util/json2.js
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2009-09-29
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
*/
|
||||
|
||||
/*jslint evil: true, strict: false */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
if (!this.JSON) {
|
||||
this.JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf()) ?
|
||||
this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z' : null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ?
|
||||
'"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string' ? c :
|
||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' :
|
||||
'"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0 ? '[]' :
|
||||
gap ? '[\n' + gap +
|
||||
partial.join(',\n' + gap) + '\n' +
|
||||
mind + ']' :
|
||||
'[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
k = rep[i];
|
||||
if (typeof k === 'string') {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0 ? '{}' :
|
||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
||||
mind + '}' : '{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/.
|
||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function' ?
|
||||
walk({'': j}, '') : j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
369
sites/all/modules/media/js/wysiwyg-media.js
Normal file
369
sites/all/modules/media/js/wysiwyg-media.js
Normal file
@@ -0,0 +1,369 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Attach Media WYSIWYG behaviors.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
Drupal.media = Drupal.media || {};
|
||||
|
||||
// Define the behavior.
|
||||
Drupal.wysiwyg.plugins.media = {
|
||||
|
||||
/**
|
||||
* Initializes the tag map.
|
||||
*/
|
||||
initializeTagMap: function () {
|
||||
if (typeof Drupal.settings.tagmap == 'undefined') {
|
||||
Drupal.settings.tagmap = { };
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Execute the button.
|
||||
* @TODO: Debug calls from this are never called. What's its function?
|
||||
*/
|
||||
invoke: function (data, settings, instanceId) {
|
||||
if (data.format == 'html') {
|
||||
Drupal.media.popups.mediaBrowser(function (mediaFiles) {
|
||||
Drupal.wysiwyg.plugins.media.mediaBrowserOnSelect(mediaFiles, instanceId);
|
||||
}, settings['global']);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Respond to the mediaBrowser's onSelect event.
|
||||
* @TODO: Debug calls from this are never called. What's its function?
|
||||
*/
|
||||
mediaBrowserOnSelect: function (mediaFiles, instanceId) {
|
||||
var mediaFile = mediaFiles[0];
|
||||
var options = {};
|
||||
Drupal.media.popups.mediaStyleSelector(mediaFile, function (formattedMedia) {
|
||||
Drupal.wysiwyg.plugins.media.insertMediaFile(mediaFile, formattedMedia.type, formattedMedia.html, formattedMedia.options, Drupal.wysiwyg.instances[instanceId]);
|
||||
}, options);
|
||||
|
||||
return;
|
||||
},
|
||||
|
||||
insertMediaFile: function (mediaFile, viewMode, formattedMedia, options, wysiwygInstance) {
|
||||
|
||||
this.initializeTagMap();
|
||||
// @TODO: the folks @ ckeditor have told us that there is no way
|
||||
// to reliably add wrapper divs via normal HTML.
|
||||
// There is some method of adding a "fake element"
|
||||
// But until then, we're just going to embed to img.
|
||||
// This is pretty hacked for now.
|
||||
//
|
||||
var imgElement = $(this.stripDivs(formattedMedia));
|
||||
this.addImageAttributes(imgElement, mediaFile.fid, viewMode, options);
|
||||
|
||||
var toInsert = this.outerHTML(imgElement);
|
||||
// Create an inline tag
|
||||
var inlineTag = Drupal.wysiwyg.plugins.media.createTag(imgElement);
|
||||
// Add it to the tag map in case the user switches input formats
|
||||
Drupal.settings.tagmap[inlineTag] = toInsert;
|
||||
wysiwygInstance.insert(toInsert);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the HTML content of an element
|
||||
*
|
||||
* @param jQuery element
|
||||
*/
|
||||
outerHTML: function (element) {
|
||||
return $('<div>').append( element.eq(0).clone() ).html();
|
||||
},
|
||||
|
||||
addImageAttributes: function (imgElement, fid, view_mode, additional) {
|
||||
// imgElement.attr('fid', fid);
|
||||
// imgElement.attr('view_mode', view_mode);
|
||||
// Class so we can find this image later.
|
||||
imgElement.addClass('media-image');
|
||||
this.forceAttributesIntoClass(imgElement, fid, view_mode, additional);
|
||||
if (additional) {
|
||||
for (k in additional) {
|
||||
if (additional.hasOwnProperty(k)) {
|
||||
if (k === 'attr') {
|
||||
imgElement.attr(k, additional[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Due to problems handling wrapping divs in ckeditor, this is needed.
|
||||
*
|
||||
* Going forward, if we don't care about supporting other editors
|
||||
* we can use the fakeobjects plugin to ckeditor to provide cleaner
|
||||
* transparency between what Drupal will output <div class="field..."><img></div>
|
||||
* instead of just <img>, for now though, we're going to remove all the stuff surrounding the images.
|
||||
*
|
||||
* @param String formattedMedia
|
||||
* Element containing the image
|
||||
*
|
||||
* @return HTML of <img> tag inside formattedMedia
|
||||
*/
|
||||
stripDivs: function (formattedMedia) {
|
||||
// Check to see if the image tag has divs to strip
|
||||
var stripped = null;
|
||||
if ($(formattedMedia).is('img')) {
|
||||
stripped = this.outerHTML($(formattedMedia));
|
||||
} else {
|
||||
stripped = this.outerHTML($('img', $(formattedMedia)));
|
||||
}
|
||||
// This will fail if we pass the img tag without anything wrapping it, like we do when re-enabling WYSIWYG
|
||||
return stripped;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attach function, called when a rich text editor loads.
|
||||
* This finds all [[tags]] and replaces them with the html
|
||||
* that needs to show in the editor.
|
||||
*
|
||||
*/
|
||||
attach: function (content, settings, instanceId) {
|
||||
var matches = content.match(/\[\[.*?\]\]/g);
|
||||
this.initializeTagMap();
|
||||
var tagmap = Drupal.settings.tagmap;
|
||||
if (matches) {
|
||||
var inlineTag = "";
|
||||
for (i = 0; i < matches.length; i++) {
|
||||
inlineTag = matches[i];
|
||||
if (tagmap[inlineTag]) {
|
||||
// This probably needs some work...
|
||||
// We need to somehow get the fid propogated here.
|
||||
// We really want to
|
||||
var tagContent = tagmap[inlineTag];
|
||||
var mediaMarkup = this.stripDivs(tagContent); // THis is <div>..<img>
|
||||
|
||||
var _tag = inlineTag;
|
||||
_tag = _tag.replace('[[','');
|
||||
_tag = _tag.replace(']]','');
|
||||
try {
|
||||
mediaObj = JSON.parse(_tag);
|
||||
}
|
||||
catch(err) {
|
||||
mediaObj = null;
|
||||
}
|
||||
if(mediaObj) {
|
||||
var imgElement = $(mediaMarkup);
|
||||
this.addImageAttributes(imgElement, mediaObj.fid, mediaObj.view_mode);
|
||||
var toInsert = this.outerHTML(imgElement);
|
||||
content = content.replace(inlineTag, toInsert);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug.debug("Could not find content for " + inlineTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Detach function, called when a rich text editor detaches
|
||||
*/
|
||||
detach: function (content, settings, instanceId) {
|
||||
// Replace all Media placeholder images with the appropriate inline json
|
||||
// string. Using a regular expression instead of jQuery manipulation to
|
||||
// prevent <script> tags from being displaced.
|
||||
// @see http://drupal.org/node/1280758.
|
||||
if (matches = content.match(/<img[^>]+class=([\'"])media-image[^>]*>/gi)) {
|
||||
for (var i = 0; i < matches.length; i++) {
|
||||
var imageTag = matches[i];
|
||||
var inlineTag = Drupal.wysiwyg.plugins.media.createTag($(imageTag));
|
||||
Drupal.settings.tagmap[inlineTag] = imageTag;
|
||||
content = content.replace(imageTag, inlineTag);
|
||||
}
|
||||
}
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param jQuery imgNode
|
||||
* Image node to create tag from
|
||||
*/
|
||||
createTag: function (imgNode) {
|
||||
// Currently this is the <img> itself
|
||||
// Collect all attribs to be stashed into tagContent
|
||||
var mediaAttributes = {};
|
||||
var imgElement = imgNode[0];
|
||||
var sorter = [];
|
||||
|
||||
// @todo: this does not work in IE, width and height are always 0.
|
||||
for (i=0; i< imgElement.attributes.length; i++) {
|
||||
var attr = imgElement.attributes[i];
|
||||
if (attr.specified == true) {
|
||||
if (attr.name !== 'class') {
|
||||
sorter.push(attr);
|
||||
}
|
||||
else {
|
||||
// Exctract expando properties from the class field.
|
||||
var attributes = this.getAttributesFromClass(attr.value);
|
||||
for (var name in attributes) {
|
||||
if (attributes.hasOwnProperty(name)) {
|
||||
var value = attributes[name];
|
||||
if (value.type && value.type === 'attr') {
|
||||
sorter.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sorter.sort(this.sortAttributes);
|
||||
|
||||
for (var prop in sorter) {
|
||||
mediaAttributes[sorter[prop].name] = sorter[prop].value;
|
||||
}
|
||||
|
||||
// The following 5 ifs are dedicated to IE7
|
||||
// If the style is null, it is because IE7 can't read values from itself
|
||||
if (jQuery.browser.msie && jQuery.browser.version == '7.0') {
|
||||
if (mediaAttributes.style === "null") {
|
||||
var imgHeight = imgNode.css('height');
|
||||
var imgWidth = imgNode.css('width');
|
||||
mediaAttributes.style = {
|
||||
height: imgHeight,
|
||||
width: imgWidth
|
||||
}
|
||||
if (!mediaAttributes['width']) {
|
||||
mediaAttributes['width'] = imgWidth;
|
||||
}
|
||||
if (!mediaAttributes['height']) {
|
||||
mediaAttributes['height'] = imgHeight;
|
||||
}
|
||||
}
|
||||
// If the attribute width is zero, get the CSS width
|
||||
if (Number(mediaAttributes['width']) === 0) {
|
||||
mediaAttributes['width'] = imgNode.css('width');
|
||||
}
|
||||
// IE7 does support 'auto' as a value of the width attribute. It will not
|
||||
// display the image if this value is allowed to pass through
|
||||
if (mediaAttributes['width'] === 'auto') {
|
||||
delete mediaAttributes['width'];
|
||||
}
|
||||
// If the attribute height is zero, get the CSS height
|
||||
if (Number(mediaAttributes['height']) === 0) {
|
||||
mediaAttributes['height'] = imgNode.css('height');
|
||||
}
|
||||
// IE7 does support 'auto' as a value of the height attribute. It will not
|
||||
// display the image if this value is allowed to pass through
|
||||
if (mediaAttributes['height'] === 'auto') {
|
||||
delete mediaAttributes['height'];
|
||||
}
|
||||
}
|
||||
|
||||
// Remove elements from attribs using the blacklist
|
||||
for (var blackList in Drupal.settings.media.blacklist) {
|
||||
delete mediaAttributes[Drupal.settings.media.blacklist[blackList]];
|
||||
}
|
||||
tagContent = {
|
||||
"type": 'media',
|
||||
// @todo: This will be selected from the format form
|
||||
"view_mode": attributes['view_mode'].value,
|
||||
"fid" : attributes['fid'].value,
|
||||
"attributes": mediaAttributes
|
||||
};
|
||||
return '[[' + JSON.stringify(tagContent) + ']]';
|
||||
},
|
||||
|
||||
/**
|
||||
* Forces custom attributes into the class field of the specified image.
|
||||
*
|
||||
* Due to a bug in some versions of Firefox
|
||||
* (http://forums.mozillazine.org/viewtopic.php?f=9&t=1991855), the
|
||||
* custom attributes used to share information about the image are
|
||||
* being stripped as the image markup is set into the rich text
|
||||
* editor. Here we encode these attributes into the class field so
|
||||
* the data survives.
|
||||
*
|
||||
* @param imgElement
|
||||
* The image
|
||||
* @fid
|
||||
* The file id.
|
||||
* @param view_mode
|
||||
* The view mode.
|
||||
* @param additional
|
||||
* Additional attributes to add to the image.
|
||||
*/
|
||||
forceAttributesIntoClass: function (imgElement, fid, view_mode, additional) {
|
||||
var wysiwyg = imgElement.attr('wysiwyg');
|
||||
if (wysiwyg) {
|
||||
imgElement.addClass('attr__wysiwyg__' + wysiwyg);
|
||||
}
|
||||
var format = imgElement.attr('format');
|
||||
if (format) {
|
||||
imgElement.addClass('attr__format__' + format);
|
||||
}
|
||||
var typeOf = imgElement.attr('typeof');
|
||||
if (typeOf) {
|
||||
imgElement.addClass('attr__typeof__' + typeOf);
|
||||
}
|
||||
if (fid) {
|
||||
imgElement.addClass('img__fid__' + fid);
|
||||
}
|
||||
if (view_mode) {
|
||||
imgElement.addClass('img__view_mode__' + view_mode);
|
||||
}
|
||||
if (additional) {
|
||||
for (var name in additional) {
|
||||
if (additional.hasOwnProperty(name)) {
|
||||
if (name !== 'alt') {
|
||||
imgElement.addClass('attr__' + name + '__' + additional[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves encoded attributes from the specified class string.
|
||||
*
|
||||
* @param classString
|
||||
* A string containing the value of the class attribute.
|
||||
* @return
|
||||
* An array containing the attribute names as keys, and an object
|
||||
* with the name, value, and attribute type (either 'attr' or
|
||||
* 'img', depending on whether it is an image attribute or should
|
||||
* be it the attributes section)
|
||||
*/
|
||||
getAttributesFromClass: function (classString) {
|
||||
var actualClasses = [];
|
||||
var otherAttributes = [];
|
||||
var classes = classString.split(' ');
|
||||
var regexp = new RegExp('^(attr|img)__([^\S]*)__([^\S]*)$');
|
||||
for (var index = 0; index < classes.length; index++) {
|
||||
var matches = classes[index].match(regexp);
|
||||
if (matches && matches.length === 4) {
|
||||
otherAttributes[matches[2]] = {name: matches[2], value: matches[3], type: matches[1]};
|
||||
}
|
||||
else {
|
||||
actualClasses.push(classes[index]);
|
||||
}
|
||||
}
|
||||
if (actualClasses.length > 0) {
|
||||
otherAttributes['class'] = {name: 'class', value: actualClasses.join(' '), type: 'attr'};
|
||||
}
|
||||
return otherAttributes;
|
||||
},
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
sortAttributes: function (a, b) {
|
||||
var nameA = a.name.toLowerCase();
|
||||
var nameB = b.name.toLowerCase();
|
||||
if (nameA < nameB) {
|
||||
return -1;
|
||||
}
|
||||
if (nameA > nameB) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
Reference in New Issue
Block a user