| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- (function() {
- var Candidate, Candidates, CandidatesView, Connection, Connections, ConnectionsView, CreatePostView, ENTER_KEY, MetaboxView, get_mustache_template, remove_row, row_wait;
-
- ENTER_KEY = 13;
-
- row_wait = function($td) {
- return $td.find('.p2p-icon').css('background-image', 'url(' + P2PAdminL10n.spinner + ')');
- };
-
- remove_row = function($td) {
- var $table;
- $table = $td.closest('table');
- $td.closest('tr').remove();
- if (!$table.find('tbody tr').length) {
- return $table.hide();
- }
- };
-
- get_mustache_template = function(name) {
- return jQuery('#p2p-template-' + name).html();
- };
-
- // Class for representing a single connection candidate
- Candidate = Backbone.Model.extend({});
-
- // Class for representing a single connection
- Connection = Backbone.Model.extend({});
-
- // Class for holding search parameters; not really a model
- Candidates = Backbone.Model.extend({
-
- // (Re)perform a search with the current parameters
- sync: function() {
- var params, _this = this;
- params = {
- subaction: 'search'
- };
- return this.ajax_request(params, function(response) {
- var _ref = response.navigation;
- _this.total_pages = (_ref ? _ref['total-pages-raw'] : void 0) || 1;
- _this.trigger('sync', response);
- });
- },
-
- // Validation function, called by Backbone when parameters are changed
- validate: function(attrs) {
- var _ref = attrs.paged;
- if (0 < _ref && _ref <= this.total_pages) {
- return null;
- }
- return 'invalid page';
- }
- });
-
- // Class for holding a list of connections
- Connections = Backbone.Collection.extend({
- model: Connection,
-
- // Create both a candidate item and a connection
- createItemAndConnect: function(title) {
- var data, _this = this;
- data = {
- subaction: 'create_post',
- post_title: title
- };
- return this.ajax_request(data, function(response) {
- _this.trigger('create', response);
- });
- },
-
- // Create a connection from a candidate
- create: function(candidate) {
- var data, _this = this;
- data = {
- subaction: 'connect',
- to: candidate.get('id')
- };
- return this.ajax_request(data, function(response) {
- _this.trigger('create', response);
- });
- },
-
- // Delete a connection
- "delete": function(connection) {
- var data, _this = this;
- data = {
- subaction: 'disconnect',
- p2p_id: connection.get('id')
- };
- return this.ajax_request(data, function(response) {
- _this.trigger('delete', response, connection);
- });
- },
-
- // Delete all connections
- clear: function() {
- var data, _this = this;
- data = {
- subaction: 'clear_connections'
- };
- return this.ajax_request(data, function(response) {
- _this.trigger('clear', response);
- });
- }
- });
-
- // View responsible for the connection list
- ConnectionsView = Backbone.View.extend({
-
- events: {
- 'click th.p2p-col-delete .p2p-icon': 'clear',
- 'click td.p2p-col-delete .p2p-icon': 'delete'
- },
-
- initialize: function(options) {
- this.options = options;
- this.maybe_make_sortable();
- this.collection.on('create', this.afterCreate, this);
- this.collection.on('clear', this.afterClear, this);
- },
-
- maybe_make_sortable: function() {
- if (this.$('th.p2p-col-order').length) {
- this.$('tbody').sortable({
- handle: 'td.p2p-col-order',
- helper: function(e, ui) {
- ui.children().each(function() {
- var $this;
- $this = jQuery(this);
- $this.width($this.width());
- });
- return ui;
- }
- });
- }
- },
-
- clear: function(ev) {
- var $td;
- ev.preventDefault();
- if (!confirm(P2PAdminL10n.deleteConfirmMessage)) {
- return;
- }
- $td = jQuery(ev.target).closest('td');
- row_wait($td);
- this.collection.clear();
- },
-
- afterClear: function() {
- this.$el.hide().find('tbody').html('');
- },
-
- "delete": function(ev) {
- var $td, req;
- ev.preventDefault();
- $td = jQuery(ev.target).closest('td');
- row_wait($td);
- req = this.collection["delete"](new Connection({
- id: $td.find('input').val()
- }));
- req.done(function() {
- remove_row($td);
- });
- },
-
- afterCreate: function(response) {
- this.$el.show().find('tbody').append(response.row);
- this.collection.trigger('append', response);
- }
- });
-
- // View responsible for the candidate list
- CandidatesView = Backbone.View.extend({
-
- template: Mustache.compile(get_mustache_template('tab-list')),
-
- events: {
- 'keypress :text': 'handleReturn',
- 'keyup :text': 'handleSearch',
- 'click .p2p-prev, .p2p-next': 'changePage',
- 'click td.p2p-col-create div': 'promote'
- },
-
- initialize: function(options) {
- this.options = options;
- this.spinner = options.spinner;
- options.connections.on('delete', this.afterCandidatesRefreshed, this);
- options.connections.on('clear', this.afterCandidatesRefreshed, this);
- this.collection.on('sync', this.afterCandidatesRefreshed, this);
- this.collection.on('error', this.afterInvalid, this);
- this.collection.on('invalid', this.afterInvalid, this);
- },
-
- promote: function(ev) {
- var $td, req, _this = this;
- ev.preventDefault();
- $td = jQuery(ev.target).closest('td');
- row_wait($td);
- var candidate = new Candidate({
- id: $td.find('div').data('item-id')
- });
- req = this.options.connections.create(candidate);
- req.done(function() {
- if (_this.options.duplicate_connections) {
- $td.find('.p2p-icon').css('background-image', '');
- } else {
- remove_row($td);
- }
- });
- },
-
- handleReturn: function(ev) {
- if (ev.keyCode === ENTER_KEY) {
- ev.preventDefault();
- }
- },
-
- handleSearch: function(ev) {
- var $searchInput, delayed,
- _this = this;
- if (delayed !== void 0) {
- clearTimeout(delayed);
- }
- $searchInput = jQuery(ev.target);
- delayed = setTimeout(function() {
- var searchStr;
- searchStr = $searchInput.val();
- if (searchStr === _this.collection.get('s')) {
- return;
- }
- _this.spinner.insertAfter($searchInput).show();
- _this.collection.save({
- 's': searchStr,
- 'paged': 1
- });
- }, 400);
- },
-
- changePage: function(ev) {
- var $navButton, new_page;
- $navButton = jQuery(ev.currentTarget);
- new_page = this.collection.get('paged');
- if ($navButton.hasClass('p2p-prev')) {
- new_page--;
- } else {
- new_page++;
- }
- this.spinner.appendTo(this.$('.p2p-navigation'));
- this.collection.save('paged', new_page);
- },
-
- afterCandidatesRefreshed: function(response) {
- this.spinner.remove();
- this.$('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
- if ('string' !== typeof response) {
- response = this.template(response);
- }
- this.$el.append(response);
- },
- afterInvalid: function() {
- this.spinner.remove();
- }
- });
-
- // View responsible for the post creation UI
- CreatePostView = Backbone.View.extend({
-
- events: {
- 'click button': 'createItem',
- 'keypress :text': 'handleReturn'
- },
-
- initialize: function(options) {
- this.options = options;
- this.createButton = this.$('button');
- this.createInput = this.$(':text');
- },
-
- handleReturn: function(ev) {
- if (ev.keyCode === ENTER_KEY) {
- this.createButton.click();
- ev.preventDefault();
- }
- },
-
- createItem: function(ev) {
- var req, title, _this = this;
- ev.preventDefault();
- if (this.createButton.hasClass('inactive')) {
- return false;
- }
- title = this.createInput.val();
- if (title === '') {
- this.createInput.focus();
- return;
- }
- this.createButton.addClass('inactive');
- req = this.collection.createItemAndConnect(title);
- req.done(function() {
- _this.createInput.val('');
- _this.createButton.removeClass('inactive');
- });
- }
- });
-
- // View responsible for the entire metabox
- MetaboxView = Backbone.View.extend({
-
- events: {
- 'click .p2p-toggle-tabs': 'toggleTabs',
- 'click .wp-tab-bar li': 'setActiveTab'
- },
-
- initialize: function(options) {
- this.options = options;
- this.spinner = options.spinner;
- this.initializedCandidates = false;
- options.connections.on('append', this.afterConnectionAppended, this);
- options.connections.on('clear', this.afterConnectionDeleted, this);
- options.connections.on('delete', this.afterConnectionDeleted, this);
- },
-
- toggleTabs: function(ev) {
- var $tabs;
- ev.preventDefault();
- $tabs = this.$('.p2p-create-connections-tabs');
- $tabs.toggle();
- if (!this.initializedCandidates && $tabs.is(':visible')) {
- this.options.candidates.sync();
- this.initializedCandidates = true;
- }
- },
-
- setActiveTab: function(ev) {
- var $tab;
- ev.preventDefault();
- $tab = jQuery(ev.currentTarget);
- this.$('.wp-tab-bar li').removeClass('wp-tab-active');
- $tab.addClass('wp-tab-active');
- this.$el.find('.tabs-panel').hide().end().find($tab.data('ref')).show().find(':text').focus();
- },
-
- afterConnectionAppended: function(response) {
- if ('one' === this.options.cardinality) {
- this.$('.p2p-create-connections').hide();
- }
- },
-
- afterConnectionDeleted: function(response) {
- if ('one' === this.options.cardinality) {
- this.$('.p2p-create-connections').show();
- }
- }
- });
-
- window.P2PAdmin = {
- Candidate: Candidate,
- Connection: Connection,
- boxes: {}
- };
-
- jQuery(function() {
- // Polyfill for browsers that don't support the placeholder attribute
- if (!jQuery('<input placeholder="1" />')[0].placeholder) {
- function setVal() {
- var $this;
- $this = jQuery(this);
- if (!$this.val()) {
- $this.val($this.attr('placeholder'));
- $this.addClass('p2p-placeholder');
- }
- };
-
- function clearVal() {
- var $this;
- $this = jQuery(this);
- if ($this.hasClass('p2p-placeholder')) {
- $this.val('');
- $this.removeClass('p2p-placeholder');
- }
- };
- jQuery('.p2p-search input[placeholder]').each(setVal).focus(clearVal).blur(setVal);
- }
-
- Mustache.compilePartial('table-row', get_mustache_template('table-row'));
-
- jQuery('.p2p-box').each(function() {
- var $metabox, $spinner, candidates, candidatesView, connections, connectionsView, createPostView, ctype, metaboxView;
-
- $metabox = jQuery(this);
-
- $spinner = jQuery('<img>', {
- 'src': P2PAdminL10n.spinner,
- 'class': 'p2p-spinner'
- });
-
- candidates = new Candidates({
- 's': '',
- 'paged': 1
- });
- candidates.total_pages = $metabox.find('.p2p-total').data('num') || 1;
-
- ctype = {
- p2p_type: $metabox.data('p2p_type'),
- direction: $metabox.data('direction'),
- from: jQuery('#post_ID').val()
- };
-
- // All ajax requests should be done through this function
- function ajax_request(options, callback) {
- var params = _.extend({}, options, candidates.attributes, ctype, {
- action: 'p2p_box',
- nonce: P2PAdminL10n.nonce
- });
-
- return jQuery.post(ajaxurl, params, function(response) {
- var e;
- try {
- response = jQuery.parseJSON(response);
- } catch (_error) {
- e = _error;
- if (typeof console !== "undefined" && console !== null) {
- console.error('Malformed response', response);
- }
- return;
- }
- if (response.error) {
- return alert(response.error);
- } else {
- return callback(response);
- }
- });
- }
-
- candidates.ajax_request = ajax_request;
-
- connections = new Connections();
- connections.ajax_request = ajax_request;
-
- connectionsView = new ConnectionsView({
- el: $metabox.find('.p2p-connections'),
- collection: connections,
- candidates: candidates
- });
-
- candidatesView = new CandidatesView({
- el: $metabox.find('.p2p-tab-search'),
- collection: candidates,
- connections: connections,
- spinner: $spinner,
- duplicate_connections: $metabox.data('duplicate_connections')
- });
-
- createPostView = new CreatePostView({
- el: $metabox.find('.p2p-tab-create-post'),
- collection: connections
- });
-
- metaboxView = new MetaboxView({
- el: $metabox,
- spinner: $spinner,
- cardinality: $metabox.data('cardinality'),
- candidates: candidates,
- connections: connections
- });
-
- P2PAdmin.boxes[ctype.p2p_type] = {
- candidates: candidates,
- connections: connections
- };
- });
- });
- }());
|