horizon/horizon/static/horizon/js/horizon.tables_inline_edit.js

272 lines
9.5 KiB
JavaScript

horizon.inline_edit = {
get_cell_id: function (td_element) {
return (td_element.parents("tr").first().data("object-id")
+ "__" + td_element.data("cell-name"));
},
get_object_container: function (td_element) {
// global cell object container
if (!window.cell_object_container) {
window.cell_object_container = new Array();
}
return window.cell_object_container;
},
get_cell_object: function (td_element) {
var cell_id = horizon.inline_edit.get_cell_id(td_element);
var id = "cell__" + cell_id;
var container = horizon.inline_edit.get_object_container(td_element);
if (container && container[id]){
// if cell object exists, I will reuse it
var cell_object = container[id];
cell_object.reset_with(td_element);
return cell_object;
} else {
// or I will create new cell object
var cell_object = new horizon.inline_edit.Cell(td_element);
// saving cell object to global container
container[id] = cell_object;
return cell_object;
}
},
Cell: function (td_element){
var self = this;
// setting initial attributes
self.reset_with = function(td_element){
self.td_element = td_element;
self.form_element = td_element.find("input, textarea");
self.url = td_element.data('update-url');
self.inline_edit_mod = false;
self.successful_update = false;
};
self.reset_with(td_element);
self.refresh = function () {
horizon.ajax.queue({
url: self.url,
data: {'inline_edit_mod': self.inline_edit_mod},
beforeSend: function () {
self.start_loading();
},
complete: function () {
// Bug in Jquery tool-tip, if I hover tool-tip, then confirm the field with
// enter and the cell is reloaded, tool-tip stays. So just to be sure, I am
// removing tool-tips manually
$(".tooltip.fade.top.in").remove();
self.stop_loading();
if (self.successful_update) {
// if cell was updated successfully, I will show fading check sign
var success = $('<div class="success"></div>');
self.td_element.find('.inline-edit-status').append(success);
var background_color = self.td_element.css('background-color');
// edit pencil will disappear and appear again once the check sign has faded
// also green background will disappear
self.td_element.addClass("no-transition");
self.td_element.addClass("success");
self.td_element.removeClass("no-transition");
self.td_element.removeClass("inline_edit_available");
success.fadeOut(1300, function () {
self.td_element.addClass("inline_edit_available");
self.td_element.removeClass("success");
});
}
},
error: function(jqXHR, status, errorThrown) {
if (jqXHR.status === 401){
var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
if (redir_url){
location.href = redir_url;
} else {
horizon.alert("error", gettext("Not authorized to do this operation."));
}
}
else {
if (!horizon.ajax.get_messages(jqXHR)) {
// Generic error handler. Really generic.
horizon.alert("error", gettext("An error occurred. Please try again later."));
}
}
},
success: function (data, textStatus, jqXHR) {
var td_element = $(data);
self.form_element = self.get_form_element(td_element);
if (self.inline_edit_mod) {
// if cell is in inline edit mode
var table_cell_wrapper = td_element.find(".table_cell_wrapper");
width = self.td_element.outerWidth();
height = self.td_element.outerHeight();
td_element.width(width);
td_element.height(height);
td_element.css('margin', 0).css('padding', 0);
table_cell_wrapper.css('margin', 0).css('padding', 0);
if (self.form_element.attr('type')=='checkbox'){
var inline_edit_form = td_element.find(".inline-edit-form");
inline_edit_form.css('padding-top', '11px').css('padding-left', '4px');
inline_edit_form.width(width - 40);
} else {
// setting CSS of element, so the cell remains the same size in editing mode
self.form_element.width(width - 40);
self.form_element.height(height - 2);
self.form_element.css('margin', 0).css('padding', 0);
}
}
// saving old td_element for cancel and loading purposes
self.cached_presentation_view = self.td_element;
// replacing old td with the new td element returned from the server
self.rewrite_cell(td_element);
// focusing the form element inside the cell
if (self.inline_edit_mod) {
self.form_element.focus();
}
}
});
};
self.update = function(post_data){
// make the update request
horizon.ajax.queue({
type: 'POST',
url: self.url,
data: post_data,
beforeSend: function () {
self.start_loading();
},
complete: function () {
if (!self.successful_update){
self.stop_loading();
}
},
error: function(jqXHR, status, errorThrown) {
if (jqXHR.status === 400){
// make place for error icon, only if the error icon is not already present
if (self.td_element.find(".inline-edit-error .error").length <= 0) {
self.form_element.css('padding-left', '20px');
self.form_element.width(self.form_element.width() - 20);
}
// obtain the error message from response body
error_message = $.parseJSON(jqXHR.responseText).message;
// insert the error icon
var error = $('<div title="' + error_message + '" class="error"></div>')
self.td_element.find(".inline-edit-error").html(error);
error.tooltip({'placement':'top'});
}
else if (jqXHR.status === 401){
var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
if (redir_url){
location.href = redir_url;
} else {
horizon.alert("error", gettext("Not authorized to do this operation."));
}
}
else {
if (!horizon.ajax.get_messages(jqXHR)) {
// Generic error handler. Really generic.
horizon.alert("error", gettext("An error occurred. Please try again later."));
}
}
},
success: function (data, textStatus, jqXHR) {
// if update was successful
self.successful_update = true;
self.refresh();
}
});
};
self.cancel = function() {
self.rewrite_cell(self.cached_presentation_view);
self.stop_loading();
};
self.get_form_element = function(td_element){
return td_element.find("input, textarea");
};
self.rewrite_cell = function(td_element){
self.td_element.replaceWith(td_element);
self.td_element = td_element;
};
self.start_loading = function() {
self.td_element.addClass("no-transition");
var spinner = $('<div class="loading"></div>');
self.td_element.find('.inline-edit-status').append(spinner);
self.td_element.addClass("loading");
self.td_element.removeClass("inline_edit_available");
self.get_form_element(self.td_element).attr("disabled", "disabled");
};
self.stop_loading = function() {
self.td_element.find('div.inline-edit-status div.loading').remove();
self.td_element.removeClass("loading");
self.td_element.addClass("inline_edit_available");
self.get_form_element(self.td_element).removeAttr("disabled");
};
}
};
horizon.addInitFunction(function() {
$('table').on('click', '.ajax-inline-edit', function (evt) {
var $this = $(this);
var td_element = $this.parents('td').first();
var cell = horizon.inline_edit.get_cell_object(td_element);
cell.inline_edit_mod = true;
cell.refresh();
evt.preventDefault();
});
var submit_form = function(evt, el){
var $submit = $(el);
var td_element = $submit.parents('td').first();
var post_data = $submit.parents('form').first().serialize();
var cell = horizon.inline_edit.get_cell_object(td_element);
cell.update(post_data);
evt.preventDefault();
}
$('table').on('click', '.inline-edit-submit', function (evt) {
submit_form(evt, this);
});
$('table').on('keypress', '.inline-edit-form', function (evt) {
if (evt.which == 13 && !evt.shiftKey) {
submit_form(evt, this);
}
});
$('table').on('click', '.inline-edit-cancel', function (evt) {
var $cancel = $(this);
var td_element = $cancel.parents('td').first();
var cell = horizon.inline_edit.get_cell_object(td_element);
cell.cancel();
evt.preventDefault();
});
$('table').on('mouseenter', '.inline_edit_available', function (evt) {
$(this).find(".table_cell_action").fadeIn(100);
});
$('table').on('mouseleave', '.inline_edit_available', function (evt) {
$(this).find(".table_cell_action").fadeOut(200);
});
$('table').on('mouseenter', '.table_cell_action', function (evt) {
$(this).addClass("hovered");
});
$('table').on('mouseleave', '.table_cell_action', function (evt) {
$(this).removeClass("hovered");
});
});