
44 changed files with 1691 additions and 686 deletions
@ -0,0 +1,3 @@ |
|||
# Place all the behaviors and hooks related to the matching controller here. |
|||
# All this logic will automatically be available in application.js. |
|||
# You can use CoffeeScript in this file: http://coffeescript.org/ |
File diff suppressed because it is too large
@ -1,37 +0,0 @@ |
|||
# Place all the behaviors and hooks related to the matching controller here. |
|||
# All this logic will automatically be available in application.js. |
|||
# You can use CoffeeScript in this file: http://coffeescript.org/ |
|||
|
|||
$('#livres').Tabledit({ |
|||
url: '/livres/index', |
|||
editButton: true, |
|||
buttons: { |
|||
edit: { |
|||
class: 'btn btn-sm btn-default', |
|||
html: '<span class="glyphicon glyphicon-pencil"></span>', |
|||
action: 'edit' |
|||
}, |
|||
delete: { |
|||
class: 'btn btn-sm btn-default', |
|||
html: '<span class="glyphicon glyphicon-trash"></span>', |
|||
action: 'delete' |
|||
}, |
|||
save: { |
|||
class: 'btn btn-sm btn-success', |
|||
html: 'Save' |
|||
}, |
|||
restore: { |
|||
class: 'btn btn-sm btn-warning', |
|||
html: 'Restore', |
|||
action: 'restore' |
|||
}, |
|||
confirm: { |
|||
class: 'btn btn-sm btn-danger', |
|||
html: 'Confirm' |
|||
} |
|||
}, |
|||
columns: { |
|||
identifier: [0, 'id'], |
|||
editable: [[1, 'titre'], [2, 'auteur'], [3, 'synopsis'], [4, 'style'], [5, 'isbn']] |
|||
} |
|||
}); |
@ -0,0 +1,47 @@ |
|||
$('#livres').Tabledit({ |
|||
url: '/livres/tabledit', |
|||
editButton: true, |
|||
deleteButton: true, |
|||
buttons: { |
|||
edit: { |
|||
class: 'btn btn-dark', |
|||
html: '<span class="fa fa-edit"></span> Edit', |
|||
action: '/livres/tabledit' |
|||
}, |
|||
delete: { |
|||
class: 'btn btn-dark', |
|||
html: '<span class="fa fa-trash"></span> Delete', |
|||
action: 'delete' |
|||
}, |
|||
save: { |
|||
class: 'btn btn-success btn-sm', |
|||
html: '<span class="fa fa-save"></span> Save', |
|||
action: '/livres/update' |
|||
}, |
|||
restore: { |
|||
class: 'btn btn-warning', |
|||
html: '<span class="fa fa-trash-restore"></span> Restore', |
|||
action: 'restore' |
|||
}, |
|||
confirm: { |
|||
class: 'btn btn-danger btn-sm', |
|||
html: '<span class="fa fa-check"></span> Confirm' |
|||
} |
|||
}, |
|||
hideIdentifier: true, |
|||
columns: { |
|||
identifier: [0, 'id'], |
|||
editable: [[1, 'titre'], [2, 'auteur'], [3, 'synopsis'], [4, 'style'], [5, 'isbn']] |
|||
}, |
|||
onSuccess: function(data, textStatus, jqXHR) { |
|||
console.log('onSuccess(data, textStatus, jqXHR)'); |
|||
console.log(data); |
|||
console.log(textStatus); |
|||
console.log(jqXHR); |
|||
}, |
|||
onAjax: function(action, serialize) { |
|||
console.log('onAjax(action, serialize)'); |
|||
console.log(action); |
|||
console.log(serialize); |
|||
} |
|||
}); |
@ -0,0 +1,613 @@ |
|||
/*! |
|||
* Tabledit v1.2.3 (https://github.com/markcell/jQuery-Tabledit)
|
|||
* Copyright (c) 2015 Celso Marques |
|||
* Licensed under MIT (https://github.com/markcell/jQuery-Tabledit/blob/master/LICENSE)
|
|||
*/ |
|||
|
|||
/** |
|||
* @description Inline editor for HTML tables compatible with Bootstrap 4 and Rails |
|||
* @version 1.0 |
|||
* @author Nolwenn Lavielle |
|||
* @origin jQuery-Tabledit |
|||
*/ |
|||
|
|||
if (typeof jQuery === 'undefined') { |
|||
throw new Error('Tabledit requires jQuery library.'); |
|||
} |
|||
|
|||
(function($) { |
|||
'use strict'; |
|||
|
|||
$.fn.Tabledit = function(options) { |
|||
if (!this.is('table')) { |
|||
throw new Error('Tabledit only works when applied to a table.'); |
|||
} |
|||
|
|||
var $table = this; |
|||
|
|||
var defaults = { |
|||
url: window.location.href, |
|||
inputClass: 'form-control input-sm', |
|||
toolbarClass: 'btn-toolbar', |
|||
groupClass: 'btn-group btn-group-sm', |
|||
dangerClass: 'danger', |
|||
warningClass: 'warning', |
|||
mutedClass: 'text-muted', |
|||
eventType: 'click', |
|||
rowIdentifier: 'id', |
|||
hideIdentifier: false, |
|||
autoFocus: true, |
|||
editButton: true, |
|||
deleteButton: true, |
|||
saveButton: true, |
|||
restoreButton: true, |
|||
buttons: { |
|||
edit: { |
|||
class: 'btn btn-sm btn-primary', |
|||
html: '<span class="glyphicon glyphicon-pencil"></span>', |
|||
action: 'edit' |
|||
}, |
|||
delete: { |
|||
class: 'btn btn-sm btn-primary', |
|||
html: '<span class="glyphicon glyphicon-trash"></span>', |
|||
action: 'delete' |
|||
}, |
|||
save: { |
|||
class: 'btn btn-sm btn-success', |
|||
html: 'Save' |
|||
}, |
|||
restore: { |
|||
class: 'btn btn-sm btn-warning', |
|||
html: 'Restore', |
|||
action: 'restore' |
|||
}, |
|||
confirm: { |
|||
class: 'btn btn-sm btn-danger', |
|||
html: 'Confirm' |
|||
} |
|||
}, |
|||
onDraw: function() { return; }, |
|||
onSuccess: function() { return; }, |
|||
onFail: function() { return; }, |
|||
onAlways: function() { return; }, |
|||
onAjax: function() { return; } |
|||
}; |
|||
|
|||
var settings = $.extend(true, defaults, options); |
|||
|
|||
var $lastEditedRow = 'undefined'; |
|||
var $lastDeletedRow = 'undefined'; |
|||
var $lastRestoredRow = 'undefined'; |
|||
|
|||
/** |
|||
* Draw Tabledit structure (identifier column, editable columns, toolbar column). |
|||
* |
|||
* @type {object} |
|||
*/ |
|||
var Draw = { |
|||
columns: { |
|||
identifier: function() { |
|||
// Hide identifier column.
|
|||
if (settings.hideIdentifier) { |
|||
$table.find('th:nth-child(' + parseInt(settings.columns.identifier[0]) + 1 + '), tbody td:nth-child(' + parseInt(settings.columns.identifier[0]) + 1 + ')').hide(); |
|||
} |
|||
|
|||
var $td = $table.find('tbody td:nth-child(' + (parseInt(settings.columns.identifier[0]) + 1) + ')'); |
|||
|
|||
$td.each(function() { |
|||
// Create hidden input with row identifier.
|
|||
var span = '<span class="tabledit-span tabledit-identifier">' + $(this).text() + '</span>'; |
|||
var input = '<input class="tabledit-input tabledit-identifier" type="hidden" name="' + settings.columns.identifier[1] + '" value="' + $(this).text() + '" disabled>'; |
|||
|
|||
// Add elements to table cell.
|
|||
$(this).html(span + input); |
|||
|
|||
// Add attribute "id" to table row.
|
|||
$(this).parent('tr').attr(settings.rowIdentifier, $(this).text()); |
|||
}); |
|||
}, |
|||
editable: function() { |
|||
for (var i = 0; i < settings.columns.editable.length; i++) { |
|||
var $td = $table.find('tbody td:nth-child(' + (parseInt(settings.columns.editable[i][0]) + 1) + ')'); |
|||
|
|||
$td.each(function() { |
|||
// Get text of this cell.
|
|||
var text = $(this).text(); |
|||
|
|||
// Add pointer as cursor.
|
|||
if (!settings.editButton) { |
|||
$(this).css('cursor', 'pointer'); |
|||
} |
|||
|
|||
// Create span element.
|
|||
var span = '<span class="tabledit-span">' + text + '</span>'; |
|||
|
|||
// Check if exists the third parameter of editable array.
|
|||
if (typeof settings.columns.editable[i][2] !== 'undefined') { |
|||
// Create select element.
|
|||
var input = '<select class="tabledit-input ' + settings.inputClass + '" name="' + settings.columns.editable[i][1] + '" style="display: none;" disabled>'; |
|||
|
|||
// Create options for select element.
|
|||
$.each(jQuery.parseJSON(settings.columns.editable[i][2]), function(index, value) { |
|||
if (text === value) { |
|||
input += '<option value="' + index + '" selected>' + value + '</option>'; |
|||
} else { |
|||
input += '<option value="' + index + '">' + value + '</option>'; |
|||
} |
|||
}); |
|||
|
|||
// Create last piece of select element.
|
|||
input += '</select>'; |
|||
} else { |
|||
// Create text input element.
|
|||
var input = '<input class="tabledit-input ' + settings.inputClass + '" type="text" name="' + settings.columns.editable[i][1] + '" value="' + $(this).text() + '" style="display: none;" disabled>'; |
|||
} |
|||
|
|||
// Add elements and class "view" to table cell.
|
|||
$(this).html(span + input); |
|||
$(this).addClass('tabledit-view-mode'); |
|||
}); |
|||
} |
|||
}, |
|||
toolbar: function() { |
|||
if (settings.editButton || settings.deleteButton) { |
|||
var editButton = ''; |
|||
var deleteButton = ''; |
|||
var saveButton = ''; |
|||
var restoreButton = ''; |
|||
var confirmButton = ''; |
|||
|
|||
// Add toolbar column header if not exists.
|
|||
if ($table.find('th.tabledit-toolbar-column').length === 0) { |
|||
$table.find('tr:first').append('<th class="tabledit-toolbar-column"></th>'); |
|||
} |
|||
|
|||
// Create edit button.
|
|||
if (settings.editButton) { |
|||
editButton = '<button type="button" class="tabledit-edit-button ' + settings.buttons.edit.class + '" style="float: none;">' + settings.buttons.edit.html + '</button>'; |
|||
} |
|||
|
|||
// Create delete button.
|
|||
if (settings.deleteButton) { |
|||
deleteButton = '<button type="button" class="tabledit-delete-button ' + settings.buttons.delete.class + '" style="float: none;">' + settings.buttons.delete.html + '</button>'; |
|||
confirmButton = '<button type="button" class="tabledit-confirm-button ' + settings.buttons.confirm.class + '" style="display: none; float: none;">' + settings.buttons.confirm.html + '</button>'; |
|||
} |
|||
|
|||
// Create save button.
|
|||
if (settings.editButton && settings.saveButton) { |
|||
saveButton = '<button type="button" class="tabledit-save-button ' + settings.buttons.save.class + '" style="display: none; float: none;">' + settings.buttons.save.html + '</button>'; |
|||
} |
|||
|
|||
// Create restore button.
|
|||
if (settings.deleteButton && settings.restoreButton) { |
|||
restoreButton = '<button type="button" class="tabledit-restore-button ' + settings.buttons.restore.class + '" style="display: none; float: none;">' + settings.buttons.restore.html + '</button>'; |
|||
} |
|||
|
|||
var toolbar = '<div class="tabledit-toolbar ' + settings.toolbarClass + '" style="text-align: left;">\n\ |
|||
<div class="' + settings.groupClass + '" style="float: none;">' + editButton + deleteButton + '</div>\n\ |
|||
' + saveButton + '\n\ |
|||
' + confirmButton + '\n\ |
|||
' + restoreButton + '\n\ |
|||
</div></div>'; |
|||
|
|||
// Add toolbar column cells.
|
|||
$table.find('tbody>tr').append('<td style="white-space: nowrap; width: 1%;">' + toolbar + '</td>'); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Change to view mode or edit mode with table td element as parameter. |
|||
* |
|||
* @type object |
|||
*/ |
|||
var Mode = { |
|||
view: function(td) { |
|||
// Get table row.
|
|||
var $tr = $(td).parent('tr'); |
|||
// Disable identifier.
|
|||
$(td).parent('tr').find('.tabledit-input.tabledit-identifier').prop('disabled', true); |
|||
// Hide and disable input element.
|
|||
$(td).find('.tabledit-input').blur().hide().prop('disabled', true); |
|||
// Show span element.
|
|||
$(td).find('.tabledit-span').show(); |
|||
// Add "view" class and remove "edit" class in td element.
|
|||
$(td).addClass('tabledit-view-mode').removeClass('tabledit-edit-mode'); |
|||
// Update toolbar buttons.
|
|||
if (settings.editButton) { |
|||
$tr.find('button.tabledit-save-button').hide(); |
|||
$tr.find('button.tabledit-edit-button').removeClass('active').blur(); |
|||
} |
|||
}, |
|||
edit: function(td) { |
|||
Delete.reset(td); |
|||
// Get table row.
|
|||
var $tr = $(td).parent('tr'); |
|||
// Enable identifier.
|
|||
$tr.find('.tabledit-input.tabledit-identifier').prop('disabled', false); |
|||
// Hide span element.
|
|||
$(td).find('.tabledit-span').hide(); |
|||
// Get input element.
|
|||
var $input = $(td).find('.tabledit-input'); |
|||
// Enable and show input element.
|
|||
$input.prop('disabled', false).show(); |
|||
// Focus on input element.
|
|||
if (settings.autoFocus) { |
|||
$input.focus(); |
|||
} |
|||
// Add "edit" class and remove "view" class in td element.
|
|||
$(td).addClass('tabledit-edit-mode').removeClass('tabledit-view-mode'); |
|||
// Update toolbar buttons.
|
|||
if (settings.editButton) { |
|||
$tr.find('button.tabledit-edit-button').addClass('active'); |
|||
$tr.find('button.tabledit-save-button').show(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Available actions for edit function, with table td element as parameter or set of td elements. |
|||
* |
|||
* @type object |
|||
*/ |
|||
var Edit = { |
|||
reset: function(td) { |
|||
$(td).each(function() { |
|||
// Get input element.
|
|||
var $input = $(this).find('.tabledit-input'); |
|||
// Get span text.
|
|||
var text = $(this).find('.tabledit-span').text(); |
|||
// Set input/select value with span text.
|
|||
if ($input.is('select')) { |
|||
$input.find('option').filter(function() { |
|||
return $.trim($(this).text()) === text; |
|||
}).attr('selected', true); |
|||
} else { |
|||
$input.val(text); |
|||
} |
|||
// Change to view mode.
|
|||
Mode.view(this); |
|||
}); |
|||
}, |
|||
submit: function(td) { |
|||
// Send AJAX request to server.
|
|||
var ajaxResult = ajax(settings.buttons.edit.action); |
|||
|
|||
if (ajaxResult === false) { |
|||
return; |
|||
} |
|||
|
|||
$(td).each(function() { |
|||
// Get input element.
|
|||
var $input = $(this).find('.tabledit-input'); |
|||
// Set span text with input/select new value.
|
|||
if ($input.is('select')) { |
|||
$(this).find('.tabledit-span').text($input.find('option:selected').text()); |
|||
} else { |
|||
$(this).find('.tabledit-span').text($input.val()); |
|||
} |
|||
// Change to view mode.
|
|||
Mode.view(this); |
|||
}); |
|||
|
|||
// Set last edited column and row.
|
|||
$lastEditedRow = $(td).parent('tr'); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Available actions for delete function, with button as parameter. |
|||
* |
|||
* @type object |
|||
*/ |
|||
var Delete = { |
|||
reset: function(td) { |
|||
// Reset delete button to initial status.
|
|||
$table.find('.tabledit-confirm-button').hide(); |
|||
// Remove "active" class in delete button.
|
|||
$table.find('.tabledit-delete-button').removeClass('active').blur(); |
|||
}, |
|||
submit: function(td) { |
|||
Delete.reset(td); |
|||
// Enable identifier hidden input.
|
|||
$(td).parent('tr').find('input.tabledit-identifier').attr('disabled', false); |
|||
// Send AJAX request to server.
|
|||
var ajaxResult = ajax(settings.buttons.delete.action); |
|||
// Disable identifier hidden input.
|
|||
$(td).parents('tr').find('input.tabledit-identifier').attr('disabled', true); |
|||
|
|||
if (ajaxResult === false) { |
|||
return; |
|||
} |
|||
|
|||
// Add class "deleted" to row.
|
|||
$(td).parent('tr').addClass('tabledit-deleted-row'); |
|||
// Hide table row.
|
|||
$(td).parent('tr').addClass(settings.mutedClass).find('.tabledit-toolbar button:not(.tabledit-restore-button)').attr('disabled', true); |
|||
// Show restore button.
|
|||
$(td).find('.tabledit-restore-button').show(); |
|||
// Set last deleted row.
|
|||
$lastDeletedRow = $(td).parent('tr'); |
|||
}, |
|||
confirm: function(td) { |
|||
// Reset all cells in edit mode.
|
|||
$table.find('td.tabledit-edit-mode').each(function() { |
|||
Edit.reset(this); |
|||
}); |
|||
// Add "active" class in delete button.
|
|||
$(td).find('.tabledit-delete-button').addClass('active'); |
|||
// Show confirm button.
|
|||
$(td).find('.tabledit-confirm-button').show(); |
|||
}, |
|||
restore: function(td) { |
|||
// Enable identifier hidden input.
|
|||
$(td).parent('tr').find('input.tabledit-identifier').attr('disabled', false); |
|||
// Send AJAX request to server.
|
|||
var ajaxResult = ajax(settings.buttons.restore.action); |
|||
// Disable identifier hidden input.
|
|||
$(td).parents('tr').find('input.tabledit-identifier').attr('disabled', true); |
|||
|
|||
if (ajaxResult === false) { |
|||
return; |
|||
} |
|||
|
|||
// Remove class "deleted" to row.
|
|||
$(td).parent('tr').removeClass('tabledit-deleted-row'); |
|||
// Hide table row.
|
|||
$(td).parent('tr').removeClass(settings.mutedClass).find('.tabledit-toolbar button').attr('disabled', false); |
|||
// Hide restore button.
|
|||
$(td).find('.tabledit-restore-button').hide(); |
|||
// Set last restored row.
|
|||
$lastRestoredRow = $(td).parent('tr'); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Send AJAX request to server. |
|||
* |
|||
* @param {string} action |
|||
*/ |
|||
function ajax(action) |
|||
{ |
|||
var serialize = $table.find('.tabledit-input').serialize() |
|||
|
|||
if (!serialize) { |
|||
return false; |
|||
} |
|||
|
|||
serialize += '&action=' + action; |
|||
|
|||
var result = settings.onAjax(action, serialize); |
|||
|
|||
if (result === false) { |
|||
return false; |
|||
} |
|||
|
|||
var jqXHR = $.post(settings.url, serialize, function(data, textStatus, jqXHR) { |
|||
if (action === settings.buttons.edit.action) { |
|||
$lastEditedRow.removeClass(settings.dangerClass).addClass(settings.warningClass); |
|||
setTimeout(function() { |
|||
//$lastEditedRow.removeClass(settings.warningClass);
|
|||
$table.find('tr.' + settings.warningClass).removeClass(settings.warningClass); |
|||
}, 1400); |
|||
} |
|||
|
|||
settings.onSuccess(data, textStatus, jqXHR); |
|||
}, 'json'); |
|||
|
|||
jqXHR.fail(function(jqXHR, textStatus, errorThrown) { |
|||
if (action === settings.buttons.delete.action) { |
|||
$lastDeletedRow.removeClass(settings.mutedClass).addClass(settings.dangerClass); |
|||
$lastDeletedRow.find('.tabledit-toolbar button').attr('disabled', false); |
|||
$lastDeletedRow.find('.tabledit-toolbar .tabledit-restore-button').hide(); |
|||
} else if (action === settings.buttons.edit.action) { |
|||
$lastEditedRow.addClass(settings.dangerClass); |
|||
} |
|||
|
|||
settings.onFail(jqXHR, textStatus, errorThrown); |
|||
}); |
|||
|
|||
jqXHR.always(function() { |
|||
settings.onAlways(); |
|||
}); |
|||
|
|||
return jqXHR; |
|||
} |
|||
|
|||
Draw.columns.identifier(); |
|||
Draw.columns.editable(); |
|||
Draw.columns.toolbar(); |
|||
|
|||
settings.onDraw(); |
|||
|
|||
if (settings.deleteButton) { |
|||
/** |
|||
* Delete one row. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('click', 'button.tabledit-delete-button', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
// Get current state before reset to view mode.
|
|||
var activated = $(this).hasClass('active'); |
|||
|
|||
var $td = $(this).parents('td'); |
|||
|
|||
Delete.reset($td); |
|||
|
|||
if (!activated) { |
|||
Delete.confirm($td); |
|||
} |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
|
|||
/** |
|||
* Delete one row (confirm). |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('click', 'button.tabledit-confirm-button', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
var $td = $(this).parents('td'); |
|||
|
|||
Delete.submit($td); |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
if (settings.restoreButton) { |
|||
/** |
|||
* Restore one row. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('click', 'button.tabledit-restore-button', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
Delete.restore($(this).parents('td')); |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
if (settings.editButton) { |
|||
/** |
|||
* Activate edit mode on all columns. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('click', 'button.tabledit-edit-button', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
var $button = $(this); |
|||
|
|||
// Get current state before reset to view mode.
|
|||
var activated = $button.hasClass('active'); |
|||
|
|||
// Change to view mode columns that are in edit mode.
|
|||
Edit.reset($table.find('td.tabledit-edit-mode')); |
|||
|
|||
if (!activated) { |
|||
// Change to edit mode for all columns in reverse way.
|
|||
$($button.parents('tr').find('td.tabledit-view-mode').get().reverse()).each(function() { |
|||
Mode.edit(this); |
|||
}); |
|||
} |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
|
|||
/** |
|||
* Save edited row. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('click', 'button.tabledit-save-button', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
// Submit and update all columns.
|
|||
Edit.submit($(this).parents('tr').find('td.tabledit-edit-mode')); |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
} else { |
|||
/** |
|||
* Change to edit mode on table td element. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on(settings.eventType, 'tr:not(.tabledit-deleted-row) td.tabledit-view-mode', function(event) { |
|||
if (event.handled !== true) { |
|||
event.preventDefault(); |
|||
|
|||
// Reset all td's in edit mode.
|
|||
Edit.reset($table.find('td.tabledit-edit-mode')); |
|||
|
|||
// Change to edit mode.
|
|||
Mode.edit(this); |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
|
|||
/** |
|||
* Change event when input is a select element. |
|||
*/ |
|||
$table.on('change', 'select.tabledit-input:visible', function(event) { |
|||
if (event.handled !== true) { |
|||
// Submit and update the column.
|
|||
Edit.submit($(this).parent('td')); |
|||
|
|||
event.handled = true; |
|||
} |
|||
}); |
|||
|
|||
/** |
|||
* Click event on document element. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$(document).on('click', function(event) { |
|||
var $editMode = $table.find('.tabledit-edit-mode'); |
|||
// Reset visible edit mode column.
|
|||
if (!$editMode.is(event.target) && $editMode.has(event.target).length === 0) { |
|||
Edit.reset($table.find('.tabledit-input:visible').parent('td')); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Keyup event on table element. |
|||
* |
|||
* @param {object} event |
|||
*/ |
|||
$table.on('keyup', function(event) { |
|||
// Get input element with focus or confirmation button.
|
|||
var $input = $table.find('.tabledit-input:visible'); |
|||
var $button = $table.find('.tabledit-confirm-button'); |
|||
|
|||
if ($input.length > 0) { |
|||
var $td = $input.parents('td'); |
|||
} else if ($button.length > 0) { |
|||
var $td = $button.parents('td'); |
|||
} else { |
|||
return; |
|||
} |
|||
|
|||
// Key?
|
|||
switch (event.keyCode) { |
|||
case 9: // Tab.
|
|||
if (!settings.editButton) { |
|||
Edit.submit($td); |
|||
Mode.edit($td.closest('td').next()); |
|||
} |
|||
break; |
|||
case 13: // Enter.
|
|||
Edit.submit($td); |
|||
break; |
|||
case 27: // Escape.
|
|||
Edit.reset($td); |
|||
Delete.reset($td); |
|||
break; |
|||
} |
|||
}); |
|||
|
|||
return this; |
|||
}; |
|||
}(jQuery)); |
|||
|
@ -1,3 +1,3 @@ |
|||
$main-background: #AF6D36 |
|||
//$main-background: #AF6D36 |
|||
|
|||
$link-color: #AF6D36 |
|||
//$link-color: #AF6D36 |
|||
|
@ -1,7 +1,9 @@ |
|||
/* |
|||
*= require font-awesome |
|||
*= require_tree . |
|||
*= require_self |
|||
*/ |
|||
|
|||
@import 'mixin' |
|||
@import 'bootstrap' |
|||
@import 'font-awesome' |
|||
|
@ -0,0 +1,3 @@ |
|||
// Place all the styles related to the Emprunts controller here. |
|||
// They will automatically be included in application.css. |
|||
// You can use Sass (SCSS) here: http://sass-lang.com/ |
@ -0,0 +1 @@ |
|||
|
@ -0,0 +1,74 @@ |
|||
class EmpruntsController < ApplicationController |
|||
before_action :set_emprunt, only: [:show, :edit, :update, :destroy] |
|||
|
|||
# GET /emprunts |
|||
# GET /emprunts.json |
|||
def index |
|||
@emprunts = Emprunt.all |
|||
end |
|||
|
|||
# GET /emprunts/1 |
|||
# GET /emprunts/1.json |
|||
def show |
|||
end |
|||
|
|||
# GET /emprunts/new |
|||
def new |
|||
@emprunt = Emprunt.new |
|||
end |
|||
|
|||
# GET /emprunts/1/edit |
|||
def edit |
|||
end |
|||
|
|||
# POST /emprunts |
|||
# POST /emprunts.json |
|||
def create |
|||
@emprunt = Emprunt.new(emprunt_params) |
|||
|
|||
respond_to do |format| |
|||
if @emprunt.save |
|||
format.html { redirect_to @emprunt, notice: 'Emprunt was successfully created.' } |
|||
format.json { render :show, status: :created, location: @emprunt } |
|||
else |
|||
format.html { render :new } |
|||
format.json { render json: @emprunt.errors, status: :unprocessable_entity } |
|||
end |
|||
end |
|||
end |
|||
|
|||
# PATCH/PUT /emprunts/1 |
|||
# PATCH/PUT /emprunts/1.json |
|||
def update |
|||
respond_to do |format| |
|||
if @emprunt.update(emprunt_params) |
|||
format.html { redirect_to @emprunt, notice: 'Emprunt was successfully updated.' } |
|||
format.json { render :show, status: :ok, location: @emprunt } |
|||
else |
|||
format.html { render :edit } |
|||
format.json { render json: @emprunt.errors, status: :unprocessable_entity } |
|||
end |
|||
end |
|||
end |
|||
|
|||
# DELETE /emprunts/1 |
|||
# DELETE /emprunts/1.json |
|||
def destroy |
|||
@emprunt.destroy |
|||
respond_to do |format| |
|||
format.html { redirect_to emprunts_url, notice: 'Emprunt was successfully destroyed.' } |
|||
format.json { head :no_content } |
|||
end |
|||
end |
|||
|
|||
private |
|||
# Use callbacks to share common setup or constraints between actions. |
|||
def set_emprunt |
|||
@emprunt = Emprunt.find(params[:id]) |
|||
end |
|||
|
|||
# Only allow a list of trusted parameters through. |
|||
def emprunt_params |
|||
params.require(:emprunt).permit(:idlivre, :nombre) |
|||
end |
|||
end |
@ -0,0 +1,2 @@ |
|||
module EmpruntsHelper |
|||
end |
@ -1,2 +1,11 @@ |
|||
module LivresHelper |
|||
def link_to_add_book(name, f, association) |
|||
new_object = f.object.send(association).klass.new |
|||
id = new_object.object_id |
|||
fields = f.fields_for(association, new_object, child_index: id) do |builder| |
|||
render(association.to_s.singularize + "_fields", f: builder) |
|||
end |
|||
|
|||
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")}) |
|||
end |
|||
end |
|||
|
@ -0,0 +1,2 @@ |
|||
class Emprunt < ApplicationRecord |
|||
end |
@ -0,0 +1,2 @@ |
|||
json.extract! emprunt, :id, :idlivre, :nombre, :created_at, :updated_at |
|||
json.url emprunt_url(emprunt, format: :json) |
@ -0,0 +1,27 @@ |
|||
<%= form_with(model: emprunt, local: true) do |form| %> |
|||
<% if emprunt.errors.any? %> |
|||
<div id="error_explanation"> |
|||
<h2><%= pluralize(emprunt.errors.count, "error") %> prohibited this emprunt from being saved:</h2> |
|||
|
|||
<ul> |
|||
<% emprunt.errors.full_messages.each do |message| %> |
|||
<li><%= message %></li> |
|||
<% end %> |
|||
</ul> |
|||
</div> |
|||
<% end %> |
|||
|
|||
<div class="field"> |
|||
<%= form.label :idlivre %> |
|||
<%= form.number_field :idlivre %> |
|||
</div> |
|||
|
|||
<div class="field"> |
|||
<%= form.label :nombre %> |
|||
<%= form.number_field :nombre %> |
|||
</div> |
|||
|
|||
<div class="actions"> |
|||
<%= form.submit %> |
|||
</div> |
|||
<% end %> |
@ -0,0 +1,6 @@ |
|||
<h1>Editing Emprunt</h1> |
|||
|
|||
<%= render 'form', emprunt: @emprunt %> |
|||
|
|||
<%= link_to 'Show', @emprunt %> | |
|||
<%= link_to 'Back', emprunts_path %> |
@ -0,0 +1,29 @@ |
|||
<p id="notice"><%= notice %></p> |
|||
|
|||
<h1>Emprunts</h1> |
|||
|
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>Idlivre</th> |
|||
<th>Nombre</th> |
|||
<th colspan="3"></th> |
|||
</tr> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<% @emprunts.each do |emprunt| %> |
|||
<tr> |
|||
<td><%= emprunt.idlivre %></td> |
|||
<td><%= emprunt.nombre %></td> |
|||
<td><%= link_to 'Show', emprunt %></td> |
|||
<td><%= link_to 'Edit', edit_emprunt_path(emprunt) %></td> |
|||
<td><%= link_to 'Destroy', emprunt, method: :delete, data: { confirm: 'Are you sure?' } %></td> |
|||
</tr> |
|||
<% end %> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<br> |
|||
|
|||
<%= link_to 'New Emprunt', new_emprunt_path %> |
@ -0,0 +1 @@ |
|||
json.array! @emprunts, partial: "emprunts/emprunt", as: :emprunt |
@ -0,0 +1,5 @@ |
|||
<h1>New Emprunt</h1> |
|||
|
|||
<%= render 'form', emprunt: @emprunt %> |
|||
|
|||
<%= link_to 'Back', emprunts_path %> |
@ -0,0 +1,14 @@ |
|||
<p id="notice"><%= notice %></p> |
|||
|
|||
<p> |
|||
<strong>Idlivre:</strong> |
|||
<%= @emprunt.idlivre %> |
|||
</p> |
|||
|
|||
<p> |
|||
<strong>Nombre:</strong> |
|||
<%= @emprunt.nombre %> |
|||
</p> |
|||
|
|||
<%= link_to 'Edit', edit_emprunt_path(@emprunt) %> | |
|||
<%= link_to 'Back', emprunts_path %> |
@ -0,0 +1 @@ |
|||
json.partial! "emprunts/emprunt", emprunt: @emprunt |
@ -0,0 +1,11 @@ |
|||
<tr> |
|||
<td><%= livre.titre %></td> |
|||
<td><%= livre.auteur %></td> |
|||
<td><%= livre.synopsis[0..120] %></td> |
|||
<td><%= livre.style %></td> |
|||
<td><%= livre.isbn %></td> |
|||
<td> |
|||
<%= link_to 'Edit', edit_livre_path(livre), remote: true %> |
|||
<%= link_to 'Destroy', livre, method: :delete, data: { confirm: 'Supprimer la donnée de façon définitive ?', remote: true }, class: 'delete' %> |
|||
</td> |
|||
</tr> |
@ -0,0 +1,2 @@ |
|||
json.extract! livre, :id, :titre, :auteur, :synopsis, :style, :isbn |
|||
json.url livre_url(livre, format: :json) |
@ -0,0 +1,3 @@ |
|||
$('table#livres > tbody form').remove(); |
|||
$('#new-book a').show(); |
|||
$('table#livres tbody').prepend('<%= j render @livre %>'); |
@ -0,0 +1,3 @@ |
|||
$('.delete').bind('ajax:success', function() { |
|||
$(this).closest('tr').fadeOut(); |
|||
}); |
@ -1,35 +1,26 @@ |
|||
<h1>Tableau de mes livres</h1> |
|||
|
|||
<% if @livres.size > 0 %> |
|||
|
|||
<table id="livres" class="table table-bordered"> |
|||
<thead class="thead-dark"> |
|||
<tr> |
|||
<th>#</th> |
|||
<th>Titre</th> |
|||
<th>Auteur</th> |
|||
<th>Synopsis</th> |
|||
<th>Style</th> |
|||
<th>ISBN</th> |
|||
<th>Action</th> |
|||
</tr> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<% @livres.each do |livre| %> |
|||
<div class="table-responsive"> |
|||
<table id="livres" class="table table-bordered"> |
|||
<thead class="thead-dark"> |
|||
<tr> |
|||
<td><%= livre.id %></td> |
|||
<td><%= livre.titre %></td> |
|||
<td><%= livre.auteur %></td> |
|||
<td><%= livre.synopsis[0..120] %></td> |
|||
<td><%= livre.style %></td> |
|||
<td><%= livre.isbn %></td> |
|||
<td><%= link_to 'Edit', edit_livre_path(livre) %></td> |
|||
<th>Titre</th> |
|||
<th>Auteur</th> |
|||
<th>Synopsis</th> |
|||
<th>Style</th> |
|||
<th>ISBN</th> |
|||
<th>Action</th> |
|||
</tr> |
|||
<% end %> |
|||
</tbody> |
|||
</table> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<%= render @livres %> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<% end %> |
|||
|
|||
<%= link_to 'Nouveau livre', new_livre_path %> |
|||
<div id="new-book"> |
|||
<%= link_to 'Nouveau livre', new_livre_path, remote: true %> |
|||
</div> |
|||
|
@ -0,0 +1 @@ |
|||
json.array! @livres, partial: "livres/livre", as: :livre |
@ -0,0 +1 @@ |
|||
$('#new-book a').hide().parent().append("<%= j render 'form', livre: @livre %>"); |
@ -0,0 +1,29 @@ |
|||
<p id="notice"><%= notice %></p> |
|||
|
|||
<p> |
|||
<strong>Titre :</strong> |
|||
<%= @livre.titre %> |
|||
</p> |
|||
|
|||
<p> |
|||
<strong>Auteur :</strong> |
|||
<%= @livre.auteur %> |
|||
</p> |
|||
|
|||
<p> |
|||
<strong>Synopsis :</strong> |
|||
<%= @livre.synopsis %> |
|||
</p> |
|||
|
|||
<p> |
|||
<strong>Style :</strong> |
|||
<%= @livre.style %> |
|||
</p> |
|||
|
|||
<p> |
|||
<strong>ISBN :</strong> |
|||
<%= @livre.isbn %> |
|||
</p> |
|||
|
|||
<%= link_to 'Edit', edit_livre_path(@livre) %> | |
|||
<%= link_to 'Back', livres_path %> |
@ -0,0 +1 @@ |
|||
json.partial! "livres/livre", livre: @livre |
@ -1,6 +1,6 @@ |
|||
Rails.application.routes.draw do |
|||
get 'livres/index' |
|||
resources :emprunts |
|||
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html |
|||
resources :livres |
|||
|
|||
post '/livres/tabledit' => 'livres#tabledit' |
|||
end |
|||
|
@ -0,0 +1,10 @@ |
|||
class CreateEmprunts < ActiveRecord::Migration[5.2] |
|||
def change |
|||
create_table :emprunts do |t| |
|||
t.integer :idlivre |
|||
t.integer :nombre |
|||
|
|||
t.timestamps |
|||
end |
|||
end |
|||
end |
@ -0,0 +1,48 @@ |
|||
require 'test_helper' |
|||
|
|||
class EmpruntsControllerTest < ActionDispatch::IntegrationTest |
|||
setup do |
|||
@emprunt = emprunts(:one) |
|||
end |
|||
|
|||
test "should get index" do |
|||
get emprunts_url |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should get new" do |
|||
get new_emprunt_url |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should create emprunt" do |
|||
assert_difference('Emprunt.count') do |
|||
post emprunts_url, params: { emprunt: { idlivre: @emprunt.idlivre, nombre: @emprunt.nombre } } |
|||
end |
|||
|
|||
assert_redirected_to emprunt_url(Emprunt.last) |
|||
end |
|||
|
|||
test "should show emprunt" do |
|||
get emprunt_url(@emprunt) |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should get edit" do |
|||
get edit_emprunt_url(@emprunt) |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should update emprunt" do |
|||
patch emprunt_url(@emprunt), params: { emprunt: { idlivre: @emprunt.idlivre, nombre: @emprunt.nombre } } |
|||
assert_redirected_to emprunt_url(@emprunt) |
|||
end |
|||
|
|||
test "should destroy emprunt" do |
|||
assert_difference('Emprunt.count', -1) do |
|||
delete emprunt_url(@emprunt) |
|||
end |
|||
|
|||
assert_redirected_to emprunts_url |
|||
end |
|||
end |
@ -0,0 +1,9 @@ |
|||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html |
|||
|
|||
one: |
|||
idlivre: 1 |
|||
nombre: 1 |
|||
|
|||
two: |
|||
idlivre: 1 |
|||
nombre: 1 |
@ -0,0 +1,7 @@ |
|||
require 'test_helper' |
|||
|
|||
class EmpruntTest < ActiveSupport::TestCase |
|||
# test "the truth" do |
|||
# assert true |
|||
# end |
|||
end |
@ -0,0 +1,45 @@ |
|||
require "application_system_test_case" |
|||
|
|||
class EmpruntsTest < ApplicationSystemTestCase |
|||
setup do |
|||
@emprunt = emprunts(:one) |
|||
end |
|||
|
|||
test "visiting the index" do |
|||
visit emprunts_url |
|||
assert_selector "h1", text: "Emprunts" |
|||
end |
|||
|
|||
test "creating a Emprunt" do |
|||
visit emprunts_url |
|||
click_on "New Emprunt" |
|||
|
|||
fill_in "Idlivre", with: @emprunt.idlivre |
|||
fill_in "Nombre", with: @emprunt.nombre |
|||
click_on "Create Emprunt" |
|||
|
|||
assert_text "Emprunt was successfully created" |
|||
click_on "Back" |
|||
end |
|||
|
|||
test "updating a Emprunt" do |
|||
visit emprunts_url |
|||
click_on "Edit", match: :first |
|||
|
|||
fill_in "Idlivre", with: @emprunt.idlivre |
|||
fill_in "Nombre", with: @emprunt.nombre |
|||
click_on "Update Emprunt" |
|||
|
|||
assert_text "Emprunt was successfully updated" |
|||
click_on "Back" |
|||
end |
|||
|
|||
test "destroying a Emprunt" do |
|||
visit emprunts_url |
|||
page.accept_confirm do |
|||
click_on "Destroy", match: :first |
|||
end |
|||
|
|||
assert_text "Emprunt was successfully destroyed" |
|||
end |
|||
end |
Loading…
Reference in new issue