Skip to content

Instantly share code, notes, and snippets.

@jraddaoui
Last active August 9, 2020 12:12
Show Gist options
  • Save jraddaoui/85c7b8583af51158e6fabffa773f0890 to your computer and use it in GitHub Desktop.
Save jraddaoui/85c7b8583af51158e6fabffa773f0890 to your computer and use it in GitHub Desktop.
AtoM clipboard with ES6 classes (no arrow functions and others yet)
(function($)
{
'use strict';
class Clipboard
{
constructor(element)
{
this.$element = element;
this.$menuButton = this.$element.find('> button');
this.$menuHeaderCount = this.$element.find('.top-dropdown-header > span');
this.onClipboardPage = $('body').is('.user.clipboard');
this.storage = localStorage;
this.types = ['informationObject', 'actor', 'repository'];
this.initialItems = {'informationObject': [], 'actor': [], 'repository': []};
this.items = JSON.parse(this.storage.getItem('clipboard'));
this.exportTokens = JSON.parse(this.storage.getItem('exportTokens'));
if (!this.items)
{
this.items = this.initialItems;
}
if (!this.exportTokens)
{
this.exportTokens = [];
}
this.init();
}
init()
{
// Listeners added to the document to affect elements added dynamically
$(document).on('click', 'button.clipboard', $.proxy(this.toggle, this, true));
$(document).on('click', 'button.clipboard-wide', $.proxy(this.toggle, this, false));
$(document).on('click', 'button#clipboard-clear, li#node_clearClipboard a', $.proxy(this.clear, this));
$(document).on('click', 'a#clipboard-save, li#node_saveClipboard a', $.proxy(this.save, this));
$(document).on('click', 'button#clipboard-send', $.proxy(this.send, this));
$(document).on('submit', '#clipboard-load-form', $.proxy(this.load, this));
$(document).on('submit', '#clipboard-export-form', $.proxy(this.export, this));
this.updateCounts();
if (this.onClipboardPage)
{
this.loadClipboardContent();
}
else
{
this.updateAllButtons();
}
this.checkExports();
}
load(event)
{
event.preventDefault();
var $form = $(event.target);
var mode = $form.find('select#mode').val();
$.ajax({
url: $form.attr('action'),
type: 'POST',
cache: false,
data: $form.serialize(),
context: this,
success: function(data)
{
if (mode === 'merge')
{
this.types.map(function(type)
{
if (data.clipboard[type])
{
data.clipboard[type].map(function(slug)
{
if (this.items[type].indexOf(slug) === -1)
{
this.items[type].push(slug);
}
}, this);
}
}, this);
}
else if (mode === 'replace')
{
this.items = data.clipboard;
}
this.storage.setItem('clipboard', JSON.stringify(this.items));
this.updateCounts();
this.showAlert(data.success, 'alert-info');
},
error: function(xhr)
{
var data = JSON.parse(xhr.responseText);
this.showAlert(data.error, 'alert-error');
}
});
}
loadClipboardContent()
{
var url = new URL(window.location.href);
var type = url.searchParams.get('type');
if (!type || !this.types.includes(type))
{
type = 'informationObject';
}
// Get clipboard content, use post instead of get to
// reduce URL length and simplify cache proxy config.
$.ajax({
url: url,
type: 'POST',
cache: false,
data: { slugs: this.items[type] },
context: this,
success: function(data)
{
// Replace page content
$('body > #wrapper').replaceWith($(data).filter('#wrapper'));
// Attach expander from qubit.js and other behaviors to new content
Drupal.attachBehaviors('#wrapper');
this.updateAllButtons();
},
error: function()
{
this.showAlert(this.$element.data('load-alert-message'), 'alert-error');
}
});
}
save(event)
{
event.preventDefault();
// Avoid request if there are no slugs in the clipboard
if (
this.items['informationObject'].length === 0 &&
this.items['actor'].length === 0 &&
this.items['repository'].length === 0
)
{
return;
}
$.ajax({
url: $(event.target).attr('href'),
type: 'POST',
cache: false,
data: { slugs: this.items },
context: this,
success: function(data)
{
this.showAlert(data.success, 'alert-info');
},
error: function(xhr)
{
var data = JSON.parse(xhr.responseText);
this.showAlert(data.error, 'alert-error');
}
});
}
send(event)
{
var $sendButton = $(event.target);
// Avoid request if there are no slugs in the clipboard
if (
this.items['informationObject'].length === 0 &&
this.items['actor'].length === 0 &&
this.items['repository'].length === 0
)
{
this.showAlert($sendButton.data('empty-message'), 'alert-error');
return;
}
// Generate clipboard send data
var data = {base_url: $sendButton.data('site-base-url')};
if (this.items['informationObject'].length !== 0)
{
data.informationobject_slugs = JSON.stringify(this.items['informationObject']);
}
if (this.items['actor'].length !== 0)
{
data.actor_slugs = JSON.stringify(this.items['actor']);
}
if (this.items['repository'].length !== 0)
{
data.repository_slugs = JSON.stringify(this.items['repository']);
}
// Show sending alert and assign it to a variable
var $sendingAlert = this.showAlert($sendButton.data('message'), 'alert-info');
$.ajax({
url: $sendButton.data('url'),
type: $sendButton.data('method'),
cache: false,
data: data,
context: this,
complete: function()
{
// Remove alert on error and success
$sendingAlert.remove();
}
});
}
export(event)
{
event.preventDefault();
var $form = $(event.target);
var type = $form.find('select#type').val();
// Avoid request if there are no slugs for the type
if (this.items[type].length === 0)
{
this.showAlert(this.$element.data('export-alert-message'), 'alert-error');
return;
}
// Merge form data and slugs
var data = $form.serializeArray();
this.items[type].map(function(slug)
{
data.push({name: 'slugs[]', value: slug});
});
$.ajax({
url: $form.attr('action'),
type: 'POST',
cache: false,
data: data,
context: this,
success: function(responseData)
{
this.showAlert(responseData.success, 'alert-info');
// Unauthenticated users will get a token to check the export
if (responseData.token)
{
this.exportTokens.push(responseData.token);
this.storage.setItem('exportTokens', JSON.stringify(this.exportTokens));
}
},
error: function(xhr)
{
var data = JSON.parse(xhr.responseText);
this.showAlert(data.error, 'alert-error');
}
});
}
checkExports()
{
if (this.exportTokens.length === 0)
{
return;
}
// Use post instead of get to send the tokens
// in the body and simplify cache proxy config.
$.ajax({
url: this.$element.data('export-check-url'),
type: 'POST',
cache: false,
data: { tokens: this.exportTokens },
context: this,
success: function(data)
{
// Show status alerts
if (data.alerts)
{
data.alerts.map(function(alert)
{
this.showAlert(alert.message, 'alert-' + alert.type, alert.deleteUrl);
}, this);
}
// Clear missing tokens
if (data.missingTokens)
{
data.missingTokens.map(function(token)
{
var index = this.exportTokens.indexOf(token);
if (index !== -1)
{
this.exportTokens.splice(index, 1);
}
}, this);
this.storage.setItem('exportTokens', JSON.stringify(this.exportTokens));
}
},
error: function(xhr)
{
var data = JSON.parse(xhr.responseText);
this.showAlert(data.error, 'alert-error');
}
});
}
toggle(reloadTooltip, event)
{
if (typeof event.preventDefault === 'function')
{
event.preventDefault();
}
var $button = $(event.target);
if (reloadTooltip)
{
$button.tooltip('hide');
}
var type = $button.data('clipboard-type');
var slug = $button.data('clipboard-slug');
var index = this.items[type].indexOf(slug);
if (index === -1)
{
this.items[type].push(slug);
this.updateButton($button, true, reloadTooltip);
}
else
{
this.items[type].splice(index, 1);
this.updateButton($button, false, reloadTooltip);
}
this.storage.setItem('clipboard', JSON.stringify(this.items));
this.updateCounts();
}
clear(event)
{
event.preventDefault();
this.showRemoveAlert();
var $target = $(event.target);
var type = $target.data('clipboard-type');
if (type && this.types.includes(type))
{
this.items[type] = [];
}
else
{
this.items = this.initialItems;
}
this.storage.setItem('clipboard', JSON.stringify(this.items));
this.updateCounts();
this.updateAllButtons();
}
updateButton($button, added, reloadTooltip)
{
// If previous and current status don't match,
// change status, tooltip and button content
if ((!$button.hasClass('added') && added)
|| ($button.hasClass('added') && !added))
{
// Show alert when removing
if (!added)
{
this.showRemoveAlert();
}
$button.toggleClass('added');
var label = $button.attr('data-title');
var altLabel = $button.attr('data-alt-title');
$button.attr('data-alt-title', label);
$button.attr('data-title', altLabel);
$button.text(altLabel);
// Fix tooltip only in small buttons
if (reloadTooltip)
{
$button.tooltip()
.attr('data-original-title', altLabel)
.tooltip('fixTitle');
}
}
}
updateCounts()
{
var iosCount = this.items['informationObject'].length;
var actorsCount = this.items['actor'].length;
var reposCount = this.items['repository'].length;
var totalCount = iosCount + actorsCount + reposCount;
// Menu button count
var $buttonSpan = this.$menuButton.find('> span');
if (!$buttonSpan.length && totalCount > 0)
{
this.$menuButton.append('<span>' + totalCount + '</span>');
}
else if (totalCount > 0)
{
$buttonSpan.text(totalCount);
}
else if ($buttonSpan.length)
{
$buttonSpan.remove();
}
// Menu dropdown header count
var countText = this.$menuHeaderCount.data('information-object-label');
countText += ' count: ' + iosCount + '<br />';
countText += this.$menuHeaderCount.data('actor-object-label');
countText += ' count: ' + actorsCount + '<br />';
countText += this.$menuHeaderCount.data('repository-object-label');
countText += ' count: ' + reposCount + '<br />';
this.$menuHeaderCount.html(countText);
}
updateAllButtons()
{
$('button.clipboard').tooltip({'placement': 'bottom', 'container': 'body'});
var self = this;
$('button[class*="clipboard"]').each(function()
{
var $button = $(this);
var type = $button.data('clipboard-type');
var slug = $button.data('clipboard-slug');
var reloadTooltip = $button.hasClass('clipboard');
var added = self.items[type].indexOf(slug) !== -1;
self.updateButton($button, added, reloadTooltip);
});
}
showAlert(message, type, deleteUrl)
{
if (!type)
{
type = '';
}
var $alert = $('<div class="alert ' + type + '">');
if (deleteUrl)
{
$alert.append('<a href="' + deleteUrl + '"><button type="button" class="close">&times;</button></a>');
}
else
{
$alert.append('<button type="button" data-dismiss="alert" class="close">&times;</button>');
}
$alert.append(message).prependTo($('#wrapper.container'));
return $alert;
}
showRemoveAlert()
{
// Show remove alert only in clipboard page if it is not already added
if (this.onClipboardPage && $('#wrapper.container > .alert-clipboard-remove').length == 0)
{
this.showAlert(this.$element.data('delete-alert-message'), 'alert-clipboard-remove');
}
}
};
$(function()
{
var $clipboard = $('#clipboard-menu');
if ($clipboard.length)
{
$clipboard.data('clipboard', new Clipboard($clipboard));
}
});
})(jQuery);
diff --git a/js/clipboard.js b/js/clipboard.js
index 892cc6a69..32190c2fd 100644
--- a/js/clipboard.js
+++ b/js/clipboard.js
@@ -2,35 +2,35 @@
{
'use strict';
- function Clipboard(element)
+ class Clipboard
{
- this.$element = element;
- this.$menuButton = this.$element.find('> button');
- this.$menuHeaderCount = this.$element.find('.top-dropdown-header > span');
- this.onClipboardPage = $('body').is('.user.clipboard');
-
- this.storage = localStorage;
- this.types = ['informationObject', 'actor', 'repository'];
- this.initialItems = {'informationObject': [], 'actor': [], 'repository': []};
- this.items = JSON.parse(this.storage.getItem('clipboard'));
- this.exportTokens = JSON.parse(this.storage.getItem('exportTokens'));
-
- if (!this.items)
+ constructor(element)
{
- this.items = this.initialItems;
- }
-
- if (!this.exportTokens)
- {
- this.exportTokens = [];
- }
+ this.$element = element;
+ this.$menuButton = this.$element.find('> button');
+ this.$menuHeaderCount = this.$element.find('.top-dropdown-header > span');
+ this.onClipboardPage = $('body').is('.user.clipboard');
+
+ this.storage = localStorage;
+ this.types = ['informationObject', 'actor', 'repository'];
+ this.initialItems = {'informationObject': [], 'actor': [], 'repository': []};
+ this.items = JSON.parse(this.storage.getItem('clipboard'));
+ this.exportTokens = JSON.parse(this.storage.getItem('exportTokens'));
+
+ if (!this.items)
+ {
+ this.items = this.initialItems;
+ }
- this.init();
- };
+ if (!this.exportTokens)
+ {
+ this.exportTokens = [];
+ }
- Clipboard.prototype = {
+ this.init();
+ }
- init: function()
+ init()
{
// Listeners added to the document to affect elements added dynamically
$(document).on('click', 'button.clipboard', $.proxy(this.toggle, this, true));
@@ -53,8 +53,9 @@
}
this.checkExports();
- },
- load: function(event)
+ }
+
+ load(event)
{
event.preventDefault();
@@ -100,8 +101,9 @@
this.showAlert(data.error, 'alert-error');
}
});
- },
- loadClipboardContent: function()
+ }
+
+ loadClipboardContent()
{
var url = new URL(window.location.href);
var type = url.searchParams.get('type');
@@ -134,8 +136,9 @@
this.showAlert(this.$element.data('load-alert-message'), 'alert-error');
}
});
- },
- save: function(event)
+ }
+
+ save(event)
{
event.preventDefault();
@@ -165,8 +168,9 @@
this.showAlert(data.error, 'alert-error');
}
});
- },
- send: function(event)
+ }
+
+ send(event)
{
var $sendButton = $(event.target);
@@ -215,8 +219,9 @@
$sendingAlert.remove();
}
});
- },
- export: function(event)
+ }
+
+ export(event)
{
event.preventDefault();
@@ -261,8 +266,9 @@
this.showAlert(data.error, 'alert-error');
}
});
- },
- checkExports: function()
+ }
+
+ checkExports()
{
if (this.exportTokens.length === 0)
{
@@ -310,8 +316,9 @@
this.showAlert(data.error, 'alert-error');
}
});
- },
- toggle: function(reloadTooltip, event)
+ }
+
+ toggle(reloadTooltip, event)
{
if (typeof event.preventDefault === 'function')
{
@@ -342,8 +349,9 @@
this.storage.setItem('clipboard', JSON.stringify(this.items));
this.updateCounts();
- },
- clear: function(event)
+ }
+
+ clear(event)
{
event.preventDefault();
@@ -365,8 +373,9 @@
this.updateCounts();
this.updateAllButtons();
- },
- updateButton: function($button, added, reloadTooltip)
+ }
+
+ updateButton($button, added, reloadTooltip)
{
// If previous and current status don't match,
// change status, tooltip and button content
@@ -396,8 +405,9 @@
.tooltip('fixTitle');
}
}
- },
- updateCounts: function()
+ }
+
+ updateCounts()
{
var iosCount = this.items['informationObject'].length;
var actorsCount = this.items['actor'].length;
@@ -428,8 +438,9 @@
countText += ' count: ' + reposCount + '<br />';
this.$menuHeaderCount.html(countText);
- },
- updateAllButtons: function()
+ }
+
+ updateAllButtons()
{
$('button.clipboard').tooltip({'placement': 'bottom', 'container': 'body'});
@@ -445,8 +456,9 @@
self.updateButton($button, added, reloadTooltip);
});
- },
- showAlert: function(message, type, deleteUrl)
+ }
+
+ showAlert(message, type, deleteUrl)
{
if (!type)
{
@@ -467,8 +479,9 @@
$alert.append(message).prependTo($('#wrapper.container'));
return $alert;
- },
- showRemoveAlert: function()
+ }
+
+ showRemoveAlert()
{
// Show remove alert only in clipboard page if it is not already added
if (this.onClipboardPage && $('#wrapper.container > .alert-clipboard-remove').length == 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment