diff --git a/app/assets/javascripts/application.coffee b/app/assets/javascripts/application.coffee deleted file mode 100644 index 4e724e8bc..000000000 --- a/app/assets/javascripts/application.coffee +++ /dev/null @@ -1,148 +0,0 @@ -#= require jquery2 -#= require jquery_ujs -#= require jquery.autocomplete -#= require jquery.caret-range -#= require jquery.cookie -#= require jquery.hotkeys -#= require jquery.notice -#= require jquery.markitup -#= require markitup-markdown -#= require_tree . - -$ = window.jQuery - -$("body").on "ajax:success", "form[data-remote]", (e, data) -> - $.noticeAdd text: data.notice if data and data.notice - $("#nb_votes").text data.nb_votes if data and data.nb_votes - $(@).parent().hide() unless $(@).data("hidden") - -$(".markItUp").markItUp window.markItUpSettings - -$("a.hit_counter[data-hit]").each -> - @href = "/redirect/" + $(@).data("hit") - -# Ready to moule -$("input[autofocus=autofocus]").focus() -$(".board").chat() -$("#news_revisions").redaction() - -# Force people to preview their modified contents -$("textarea, #form_answers input").keypress (event) -> - $(@).parents("form").find("input[value=Prévisualiser]").next("input[type=submit]").hide() - $(@).off event - -# Add/Remove dynamically links in the news form -langs = - xx: "!? hmmm ?!" - fr: "Français" - de: "Allemand" - en: "Anglais" - eu: "Basque" - ct: "Catalan" - cn: "Chinois" - wq: "Code/binaire" - ko: "Coréen" - da: "Danois" - es: "Espagnol" - ee: "Estonien" - fi: "Finnois" - el: "Grec" - it: "Italien" - ja: "Japonais" - nl: "Néerlandais" - no: "Norvégien" - pl: "Polonais" - pt: "Portugais" - ru: "Russe" - sv: "Suédois" - -$("#form_links").nested_fields "news", "link", "lien", "fieldset", title: "text", url: "url", lang: langs -$("#form_answers").nested_fields "poll", "answer", "choix", "p", answer: "text" - -# Mask the contributors if they are too many -$("article.news .edited_by").each -> - field = $(@) - nb = field.find("a").length - if nb > 3 - was = field.html() - field.html "#{nb} personnes" - field.one "click", -> field.html was - -# Toolbar preferences -$("#account_visible_toolbar") - .prop("checked", Toolbar.storage.visible != "false") - .click -> - Toolbar.storage.visible = $(@).is(":checked") - true - -# Show the toolbar -$.fn.reverse = [].reverse -if $("body").hasClass("logged") - if $("#comments").length - $("#comments .new-comment") - .toolbar("Nouveaux commentaires", folding: "#comments .comment") - .additional $("#comments .comment").sort((a,b) -> a.id.localeCompare(b.id)), "Commentaires par ordre chronologique" - else if $("main .node").length - $("#phare .new-node, main .new-node:not(.ppp)") - .toolbar("Contenus jamais visités") - .additional $("#phare .new_comments, main .node:not(.ppp) .new_comments").parents("article").reverse(), "Contenus lus avec + de commentaires" - -# Redaction -$(".edition_in_place").editionInPlace() -$("#redaction .new_link").editionInPlace() -$("#redaction .new_paragraph").on "ajax:success", false -$("#redaction .link, #redaction .paragraph").lockableEditionInPlace() - -# Tags -$.fn.autocompleter = () -> - @each -> - input = $(@) - input.autocomplete input.data("url"), - multiple: true - multipleSeparator: " " - dataType: "text" - matchSubset: false - @ -$("input#tags").autocompleter() -$(".tag_in_place").on("in_place:form", -> - $("input.autocomplete").autocompleter().focus() -).on("in_place:success", -> - $.noticeAdd text: "Étiquettes ajoutées" -).editionInPlace() -$(".add_tag, .remove_tag").click( -> - $(@).blur().parents("form").data hidden: "true" -).parents("form").on "ajax:success", -> - $(@).find("input").attr disabled: "disabled" - -# Hotkeys -$(document).bind("keypress", "g", -> - $("html,body").animate scrollTop: 0, 500 - false -).bind("keypress", "shift+g", -> - $("html,body").animate scrollTop: $("body").attr("scrollHeight"), 500 - false -).bind "keypress", "shift+?", -> - $.noticeAdd - text: """ - Raccourcis clavier : - """ - stay: true - false - -$("#account_user_attributes_avatar").change -> - return if window.URL? - url = window.URL.createObjectURL(@files[0]) - $(@).parents("form").find(".avatar").attr "src", url - -# Follow-up, admins, plonk... -$("button.more").click -> - $(@).next('.more_actions').show() - $(@).hide() - false diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 000000000..d203f8390 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,211 @@ +//= require jquery2 +//= require jquery_ujs +//= require jquery.autocomplete +//= require jquery.caret-range +//= require jquery.cookie +//= require jquery.hotkeys +//= require jquery.notice +//= require jquery.markitup +//= require markitup-markdown +//= require_tree . + +$ = window.jQuery; + +$("body").on("ajax:success", "form[data-remote]", function(e, data) { + if (data && data.notice) { + $.noticeAdd({ text: data.notice }); + } + if (data && data.nb_votes) { + $("#nb_votes").text(data.nb_votes); + } + if (!$(this).data("hidden")) { + $(this) + .parent() + .hide(); + } +}); + +$(".markItUp").markItUp(window.markItUpSettings); + +$("a.hit_counter[data-hit]").each(function() { + this.href = "/redirect/" + $(this).data("hit"); +}); + +// Ready to moule +$("input[autofocus=autofocus]").focus(); +$(".board").chat(); +$("#news_revisions").redaction(); + +// Force people to preview their modified contents +$("textarea, #form_answers input").keypress(function(event) { + $(this) + .parents("form") + .find("input[value=Prévisualiser]") + .next("input[type=submit]") + .hide(); + $(this).off(event); +}); + +// Add/Remove dynamically links in the news form +const langs = { + xx: "!? hmmm ?!", + fr: "Français", + de: "Allemand", + en: "Anglais", + eu: "Basque", + ct: "Catalan", + cn: "Chinois", + wq: "Code/binaire", + ko: "Coréen", + da: "Danois", + es: "Espagnol", + ee: "Estonien", + fi: "Finnois", + el: "Grec", + it: "Italien", + ja: "Japonais", + nl: "Néerlandais", + no: "Norvégien", + pl: "Polonais", + pt: "Portugais", + ru: "Russe", + sv: "Suédois" +}; + +$("#form_links").nested_fields("news", "link", "lien", "fieldset", { + title: "text", + url: "url", + lang: langs +}); +$("#form_answers").nested_fields("poll", "answer", "choix", "p", { + answer: "text" +}); + +// Mask the contributors if they are too many +$("article.news .edited_by").each(function() { + const field = $(this); + const nb = field.find("a").length; + if (nb > 3) { + const was = field.html(); + field.html(`${nb} personnes`); + field.one("click", () => field.html(was)); + } +}); + +// Toolbar preferences +$("#account_visible_toolbar") + .prop("checked", Toolbar.storage.visible !== "false") + .click(function() { + Toolbar.storage.visible = $(this).is(":checked"); + return true; + }); + +// Show the toolbar +$.fn.reverse = [].reverse; +if ($("body").hasClass("logged")) { + if ($("#comments").length) { + $("#comments .new-comment") + .toolbar("Nouveaux commentaires", { folding: "#comments .comment" }) + .additional( + $("#comments .comment").sort((a, b) => a.id.localeCompare(b.id)), + "Commentaires par ordre chronologique" + ); + } else if ($("main .node").length) { + $("#phare .new-node, main .new-node:not(.ppp)") + .toolbar("Contenus jamais visités") + .additional( + $("#phare .new_comments, main .node:not(.ppp) .new_comments") + .parents("article") + .reverse(), + "Contenus lus avec + de commentaires" + ); + } +} + +// Redaction +$(".edition_in_place").editionInPlace(); +$("#redaction .new_link").editionInPlace(); +$("#redaction .new_paragraph").on("ajax:success", false); +$("#redaction .link, #redaction .paragraph").lockableEditionInPlace(); + +// Tags +$.fn.autocompleter = function() { + return this.each(function() { + const input = $(this); + return input.autocomplete(input.data("url"), { + multiple: true, + multipleSeparator: " ", + dataType: "text", + matchSubset: false + }); + }); + return this; +}; +$("input#tags").autocompleter(); +$(".tag_in_place") + .on("in_place:form", () => + $("input.autocomplete") + .autocompleter() + .focus() + ) + .on("in_place:success", () => $.noticeAdd({ text: "Étiquettes ajoutées" })) + .editionInPlace(); +$(".add_tag, .remove_tag") + .click(function() { + $(this) + .blur() + .parents("form") + .data({ hidden: "true" }); + }) + .parents("form") + .on("ajax:success", function() { + $(this) + .find("input") + .attr({ disabled: "disabled" }); + }); + +// Hotkeys +$(document) + .bind("keypress", "g", function() { + $("html,body").animate({ scrollTop: 0 }, 500); + return false; + }) + .bind("keypress", "shift+g", function() { + $("html,body").animate({ scrollTop: document.body.offsetHeight }, 500); + return false; + }) + .bind("keypress", "shift+?", function() { + $.noticeAdd({ + text: `\ +Raccourcis clavier : \ +`, + stay: true + }); + return false; + }); + +$("#account_user_attributes_avatar").change(function() { + if (!window.URL) { + return; + } + const url = window.URL.createObjectURL(this.files[0]); + return $(this) + .parents("form") + .find(".avatar") + .attr("src", url); +}); + +// Follow-up, admins, plonk... +$("button.more").click(function() { + $(this) + .next(".more_actions") + .show(); + $(this).hide(); +}); diff --git a/app/assets/javascripts/chat.coffee b/app/assets/javascripts/chat.coffee deleted file mode 100644 index 0d1a06899..000000000 --- a/app/assets/javascripts/chat.coffee +++ /dev/null @@ -1,158 +0,0 @@ -#= require push - -$ = window.jQuery - -class Chat - constructor: (@board) -> - @input = @board.find("input[type=text]") - @inbox = @board.find(".inbox") - @isInboxLarge = @inbox.hasClass("large") - @inboxContainer = @board.find(".inbox-container") - @inboxContainer.scrollTop(@inbox.height()) - @chan = @board.data("chan") - @board.find(".board-left .norloge").click @norloge - @board.find("form").submit @postMessage - @totoz_type = $.cookie("totoz-type") - @totoz_url = $.cookie("totoz-url") or "https://totoz.eu/img/" - @norlogize right for right in @board.find(".board-right") - @norlogize_left left for left in @board.find(".board-left time").get().reverse() - @board.on("mouseenter", ".board-left time", @left_highlitizer) - .on("mouseleave", "time", @deshighlitizer) - @board.on("mouseenter", ".board-right time", @right_highlitizer) - .on("mouseleave", "time", @deshighlitizer) - if @totoz_type == "popup" - @totoz = @board.append($("
")).find("#les-totoz") - @board.on("mouseenter", ".totoz", @createTotoz) - .on("mouseleave", ".totoz", @destroyTotoz) - $.push(@chan).on("chat", @onChat).start() - - onChat: (msg) => - existing = $("#board_" + msg.id) - return if existing.length > 0 - if @isInboxLarge - @inbox.append(msg.large).find(".board-left:last .norloge").click @norloge - @inboxContainer.scrollTop(@inbox.height()) - @norlogize right for right in @inbox.find(".board-right:last") - @norlogize_left left for left in @inbox.find(".board-left time:last") - else - @inbox.prepend(msg.message).find(".board-left:first .norloge").click @norloge - @norlogize right for right in @inbox.find(".board-right:first") - @norlogize_left left for left in @inbox.find(".board-left time:first") - - postMessage: (event) => - form = $(event.target) - data = form.serialize() - @input.val("").select() - $.ajax url: form.attr("action"), data: data, type: "POST", dataType: "script" - false - - norloge: (event) => - string = $(event.target).attr("norloge") - index = $(event.target).data("clockIndex") - if index > 1 || (index == 1 && @board.find(".board-left time[data-clock-time=\"" + $(event.target).data("clockTime") + "\"]").length > 1) - switch index - when 1 then string += "¹" - when 2 then string += "²" - when 3 then string += "³" - else string += ":" + index - value = @input.val() - range = @input.caret() - unless range.start? - range.start = 0 - range.end = 0 - @input.val value.substr(0, range.start) + string + " " + value.substr(range.end, value.length) - @input.caret range.start + string.length + 1 - @input.focus() - - norlogize: (x) -> - tmp = $('
') - escape = (txt) -> tmp.text(txt).html() - $(x).contents().filter(-> @nodeType == 3).each -> - r = /(\d{4}-\d{2}-\d{2} )?(\d{2}:\d{2}(:\d{2})?)([⁰¹²³⁴⁵⁶⁷⁸⁹]+|[:\^]\d+)?/g - orig = escape @data - html = "" - while matches = r.exec orig - [match, datematch, timematch, minutes, index] = matches - if index - switch index.substr(0, 1) - when ":", "^" then index = index.substr(1) - when "¹" then index = 1 - when "²" then index = 2 - when "³" then index = 3 - when "⁴" then index = 4 - when "⁵" then index = 5 - when "⁶" then index = 6 - when "⁷" then index = 7 - when "⁸" then index = 8 - when "⁹" then index = 9 - else index = 1 - else - index = 1 - stop = matches.index - html = html + orig.slice(idx, stop) + "" - idx = r.lastIndex - $(@).replaceWith html+orig.slice(idx) if html - if @totoz_type == "popup" || @totoz_type == "inline" - cfg = @ - $(x).contents().filter(-> @nodeType == 3).each -> - totoz = /\[:([0-9a-zA-Z \*\$@':_-]+)\]/g - orig = escape @data - html = "" - while matches = totoz.exec orig - [title, name] = matches - stop = matches.index - html = html + orig.slice(idx, stop) + - if cfg.totoz_type == "popup" - "#{title}" - else if cfg.totoz_type == "inline" - "\"#{title}\"" - idx = totoz.lastIndex - $(@).replaceWith html+orig.slice(idx) if html - - norlogize_left: (x) -> - norlogeDatetime = $(x).attr("datetime") - date = /\d{4}-\d{2}-\d{2}/.exec(norlogeDatetime) - time = /\d{2}:\d{2}:\d{2}/.exec(norlogeDatetime) - index = @board.find(".board-left time[data-clock-date=\"" + date + "\"][data-clock-time=\"" + time + "\"]").length + 1 - $(x).attr("data-clock-date", date) - $(x).attr("data-clock-time", time) - $(x).attr("data-clock-index", index) - - left_highlitizer: (event) => - time = $(event.target).data("clockTime") - index = $(event.target).data("clockIndex") - @inbox.find("time[data-clock-time=\"" + time + "\"][data-clock-index=\"" + index + "\"]").addClass "highlighted" - @inbox.find("time[data-clock-time=\"" + time.substr(0, 5) + "\"][data-clock-index=\"" + index + "\"]").addClass "highlighted" - - right_highlitizer: (event) => - time = $(event.target).data("clockTime") - index = $(event.target).data("clockIndex") - if time.length = 5 - @inbox.find("time[data-clock-time*=\"" + time + "\"]").addClass "highlighted" - else - @inbox.find("time[data-clock-time=\"" + time + "\"][data-clock-index=\"" + index + "\"]").addClass "highlighted" - - deshighlitizer: => - @inbox.find("time.highlighted").removeClass "highlighted" - - createTotoz: (event) => - totozName = event.target.getAttribute("data-totoz-name") - totozId = encodeURIComponent(totozName).replace(/[%']/g, "") - totoz = @totoz.find("#totoz-" + totozId).first() - if totoz.size() == 0 - totoz = $("
") - .css(display: "none", position: "absolute") - .append("") - @totoz.append totoz - position = $(event.target).position() - [x, y] = [position.left, position.top + event.target.offsetHeight] - totoz.css "z-index": "15", display: "block", top: y + 5, left: x + 5 - - destroyTotoz: (event) => - totozId = encodeURIComponent(event.target.getAttribute("data-totoz-name")).replace(/[%']/g, "") - totoz = @totoz.find("#totoz-" + totozId).first() - totoz.css display: "none" - -$.fn.chat = -> - @each -> - new Chat($(@)) diff --git a/app/assets/javascripts/chat.js b/app/assets/javascripts/chat.js new file mode 100644 index 000000000..458751281 --- /dev/null +++ b/app/assets/javascripts/chat.js @@ -0,0 +1,344 @@ +//= require push + +$ = window.jQuery; + +class Chat { + constructor(board) { + this.onChat = this.onChat.bind(this); + this.postMessage = this.postMessage.bind(this); + this.norloge = this.norloge.bind(this); + this.left_highlitizer = this.left_highlitizer.bind(this); + this.right_highlitizer = this.right_highlitizer.bind(this); + this.deshighlitizer = this.deshighlitizer.bind(this); + this.createTotoz = this.createTotoz.bind(this); + this.destroyTotoz = this.destroyTotoz.bind(this); + this.board = board; + this.input = this.board.find("input[type=text]"); + this.inbox = this.board.find(".inbox"); + this.isInboxLarge = this.inbox.hasClass("large"); + this.inboxContainer = this.board.find(".inbox-container"); + this.inboxContainer.scrollTop(this.inbox.height()); + this.chan = this.board.data("chan"); + this.board.find(".board-left .norloge").click(this.norloge); + this.board.find("form").submit(this.postMessage); + this.totoz_type = $.cookie("totoz-type"); + this.totoz_url = $.cookie("totoz-url") || "https://totoz.eu/img/"; + for (var right of this.board.find(".board-right")) { + this.norlogize(right); + } + for (var left of this.board + .find(".board-left time") + .get() + .reverse()) { + this.norlogize_left(left); + } + this.board + .on("mouseenter", ".board-left time", this.left_highlitizer) + .on("mouseleave", "time", this.deshighlitizer); + this.board + .on("mouseenter", ".board-right time", this.right_highlitizer) + .on("mouseleave", "time", this.deshighlitizer); + if (this.totoz_type === "popup") { + this.totoz = this.board + .append($('
')) + .find("#les-totoz"); + this.board + .on("mouseenter", ".totoz", this.createTotoz) + .on("mouseleave", ".totoz", this.destroyTotoz); + } + $.push(this.chan) + .on("chat", this.onChat) + .start(); + } + + onChat(msg) { + let right; + const existing = $("#board_" + msg.id); + if (existing.length > 0) { + return; + } + if (this.isInboxLarge) { + this.inbox + .append(msg.large) + .find(".board-left:last .norloge") + .click(this.norloge); + this.inboxContainer.scrollTop(this.inbox.height()); + for (right of this.inbox.find(".board-right:last")) { + this.norlogize(right); + } + for (var left of this.inbox.find(".board-left time:last")) { + this.norlogize_left(left); + } + } else { + this.inbox + .prepend(msg.message) + .find(".board-left:first .norloge") + .click(this.norloge); + for (right of this.inbox.find(".board-right:first")) { + this.norlogize(right); + } + for (var left of this.inbox.find(".board-left time:first")) { + this.norlogize_left(left); + } + } + } + + postMessage(event) { + const form = $(event.target); + const data = form.serialize(); + this.input.val("").select(); + $.ajax({ + url: form.attr("action"), + data, + type: "POST", + dataType: "script" + }); + return false; + } + + norloge(event) { + let string = $(event.target).attr("norloge"); + const index = $(event.target).data("clockIndex"); + if ( + index > 1 || + (index === 1 && + this.board.find( + '.board-left time[data-clock-time="' + + $(event.target).data("clockTime") + + '"]' + ).length > 1) + ) { + switch (index) { + case 1: + string += "¹"; + break; + case 2: + string += "²"; + break; + case 3: + string += "³"; + break; + default: + string += ":" + index; + } + } + const value = this.input.val(); + const range = this.input.caret(); + if (!range.start) { + range.start = 0; + range.end = 0; + } + this.input.val( + value.substr(0, range.start) + + string + + " " + + value.substr(range.end, value.length) + ); + this.input.caret(range.start + string.length + 1); + return this.input.focus(); + } + + norlogize(x) { + const tmp = $("
"); + const escape = txt => tmp.text(txt).html(); + $(x) + .contents() + .filter(function() { + return this.nodeType === 3; + }) + .each(function() { + let matches; + let idx; + const r = /(\d{4}-\d{2}-\d{2} )?(\d{2}:\d{2}(:\d{2})?)([⁰¹²³⁴⁵⁶⁷⁸⁹]+|[:\^]\d+)?/g; + const orig = escape(this.data); + let html = ""; + while ((matches = r.exec(orig))) { + var [match, datematch, timematch, minutes, index] = matches; + if (index) { + switch (index.substr(0, 1)) { + case ":": + case "^": + index = index.substr(1); + break; + case "¹": + index = 1; + break; + case "²": + index = 2; + break; + case "³": + index = 3; + break; + case "⁴": + index = 4; + break; + case "⁵": + index = 5; + break; + case "⁶": + index = 6; + break; + case "⁷": + index = 7; + break; + case "⁸": + index = 8; + break; + case "⁹": + index = 9; + break; + default: + index = 1; + } + } else { + index = 1; + } + var stop = matches.index; + html = + html + + orig.slice(idx, stop) + + '"; + idx = r.lastIndex; + } + if (html) { + return $(this).replaceWith(html + orig.slice(idx)); + } + }); + if (this.totoz_type === "popup" || this.totoz_type === "inline") { + const cfg = this; + return $(x) + .contents() + .filter(function() { + return this.nodeType === 3; + }) + .each(function() { + let matches; + let idx; + const totoz = /\[:([0-9a-zA-Z \*\$@':_-]+)\]/g; + const orig = escape(this.data); + let html = ""; + while ((matches = totoz.exec(orig))) { + var [title, name] = matches; + var stop = matches.index; + html = + html + + orig.slice(idx, stop) + + (() => { + if (cfg.totoz_type === "popup") { + return `${title}`; + } else if (cfg.totoz_type === "inline") { + return `\"${title}\"`; + } + })(); + idx = totoz.lastIndex; + } + if (html) { + return $(this).replaceWith(html + orig.slice(idx)); + } + }); + } + } + + norlogize_left(x) { + const norlogeDatetime = $(x).attr("datetime"); + const date = /\d{4}-\d{2}-\d{2}/.exec(norlogeDatetime); + const time = /\d{2}:\d{2}:\d{2}/.exec(norlogeDatetime); + const index = + this.board.find( + '.board-left time[data-clock-date="' + + date + + '"][data-clock-time="' + + time + + '"]' + ).length + 1; + $(x).attr("data-clock-date", date); + $(x).attr("data-clock-time", time); + return $(x).attr("data-clock-index", index); + } + + left_highlitizer(event) { + const time = $(event.target).data("clockTime"); + const index = $(event.target).data("clockIndex"); + this.inbox + .find( + 'time[data-clock-time="' + time + '"][data-clock-index="' + index + '"]' + ) + .addClass("highlighted"); + return this.inbox + .find( + 'time[data-clock-time="' + + time.substr(0, 5) + + '"][data-clock-index="' + + index + + '"]' + ) + .addClass("highlighted"); + } + + right_highlitizer(event) { + const time = $(event.target).data("clockTime"); + const index = $(event.target).data("clockIndex"); + if ((time.length = 5)) { + return this.inbox + .find('time[data-clock-time*="' + time + '"]') + .addClass("highlighted"); + } else { + return this.inbox + .find( + 'time[data-clock-time="' + + time + + '"][data-clock-index="' + + index + + '"]' + ) + .addClass("highlighted"); + } + } + + deshighlitizer() { + return this.inbox.find("time.highlighted").removeClass("highlighted"); + } + + createTotoz(event) { + const totozName = event.target.getAttribute("data-totoz-name"); + const totozId = encodeURIComponent(totozName).replace(/[%']/g, ""); + let totoz = this.totoz.find("#totoz-" + totozId).first(); + if (totoz.size() === 0) { + totoz = $(`
`) + .css({ display: "none", position: "absolute" }) + .append(``); + this.totoz.append(totoz); + } + const position = $(event.target).position(); + const x = position.left; + const y = position.top + event.target.offsetHeight; + return totoz.css({ + "z-index": "15", + display: "block", + top: y + 5, + left: x + 5 + }); + } + + destroyTotoz(event) { + const totozId = encodeURIComponent( + event.target.getAttribute("data-totoz-name") + ).replace(/[%']/g, ""); + const totoz = this.totoz.find("#totoz-" + totozId).first(); + return totoz.css({ display: "none" }); + } +} + +$.fn.chat = function() { + return this.each(function() { + return new Chat($(this)); + }); +}; diff --git a/app/assets/javascripts/edition_in_place.coffee b/app/assets/javascripts/edition_in_place.coffee deleted file mode 100644 index 9436b2843..000000000 --- a/app/assets/javascripts/edition_in_place.coffee +++ /dev/null @@ -1,70 +0,0 @@ -$ = window.jQuery - -class EditionInPlace - constructor: (@el, @edit) -> - @url = @el.data("url") or (document.location.pathname + "/modifier") - @button().click @loadForm - - button: -> - if @edit then @el.find(@edit) else @el - - loadForm: => - @button().off "click" - @old = @el.html() - @xhr = $.ajax(url: @url, type: "get", dataType: "html").fail(@cantEdit).done(@showForm) - false - - cantEdit: => - @el.trigger "in_place:cant_edit", @xhr - @button().click @loadForm - @xhr = null - - showForm: => - form = @el.html(@xhr.responseText).find("form") - form.find(".cancel").click @reset - form.find("textarea, input, select")[0].select() - form.find(".markItUp").markItUp window.markItUpSettings - form.submit @submitForm - @el.trigger "in_place:form", @xhr - @xhr = null - - reset: (event) => - @el.html @old - @button().click @loadForm - @el.trigger "in_place:reset", event - false - - submitForm: => - form = @el.find("form") - url = form.attr("action") - data = form.serialize() - @xhr = $.ajax(url: url, type: "post", data: data, dataType: "html").fail(@error).done(@success) - false - - error: => - try - error = @el.find("ul.error") - response = $.parseJSON(@xhr.responseText) - messages = [] - for attribute, errors of response.errors - for message in errors - messages.push(message) - if messages.length == 1 - error.text("Erreur : " + messages[0]) - else - error.text("Erreurs :") - for message in messages - error.append($("
  • ").append(message)) - error.show() - @el.trigger "in_place:error", @xhr - @xhr = null - - success: => - @el = $(@xhr.responseText).replaceAll @el - @button().click @loadForm - @el.trigger "in_place:success", @xhr - @xhr = null - -$.fn.editionInPlace = (edit_selector) -> - @each -> - new EditionInPlace($(@), edit_selector) diff --git a/app/assets/javascripts/edition_in_place.js b/app/assets/javascripts/edition_in_place.js new file mode 100644 index 000000000..58b6dda8e --- /dev/null +++ b/app/assets/javascripts/edition_in_place.js @@ -0,0 +1,106 @@ +$ = window.jQuery; + +class EditionInPlace { + constructor(el, edit) { + this.loadForm = this.loadForm.bind(this); + this.cantEdit = this.cantEdit.bind(this); + this.showForm = this.showForm.bind(this); + this.reset = this.reset.bind(this); + this.submitForm = this.submitForm.bind(this); + this.error = this.error.bind(this); + this.success = this.success.bind(this); + this.el = el; + this.edit = edit; + this.url = this.el.data("url") || document.location.pathname + "/modifier"; + this.button().click(this.loadForm); + } + + button() { + if (this.edit) { + return this.el.find(this.edit); + } else { + return this.el; + } + } + + loadForm() { + this.button().off("click"); + this.old = this.el.html(); + this.xhr = $.ajax({ url: this.url, type: "get", dataType: "html" }) + .fail(this.cantEdit) + .done(this.showForm); + return false; + } + + cantEdit() { + this.el.trigger("in_place:cant_edit", this.xhr); + this.button().click(this.loadForm); + this.xhr = null; + } + + showForm() { + const form = this.el.html(this.xhr.responseText).find("form"); + form.find(".cancel").click(this.reset); + form.find("textarea, input, select")[0].select(); + form.find(".markItUp").markItUp(window.markItUpSettings); + form.submit(this.submitForm); + this.el.trigger("in_place:form", this.xhr); + this.xhr = null; + } + + reset(event) { + this.el.html(this.old); + this.button().click(this.loadForm); + this.el.trigger("in_place:reset", event); + return false; + } + + submitForm() { + const form = this.el.find("form"); + const url = form.attr("action"); + const data = form.serialize(); + this.xhr = $.ajax({ url, type: "post", data, dataType: "html" }) + .fail(this.error) + .done(this.success); + return false; + } + + error() { + try { + let message; + const error = this.el.find("ul.error"); + const response = $.parseJSON(this.xhr.responseText); + const messages = []; + for (var attribute in response.errors) { + var errors = response.errors[attribute]; + for (message of errors) { + messages.push(message); + } + } + if (messages.length === 1) { + error.text("Erreur : " + messages[0]); + } else { + error.text("Erreurs :"); + for (message of messages) { + error.append($("
  • ").append(message)); + } + } + error.show(); + } catch (error1) {} + this.el.trigger("in_place:error", this.xhr); + this.xhr = null; + } + + success() { + this.el = $(this.xhr.responseText).replaceAll(this.el); + this.button().click(this.loadForm); + this.el.trigger("in_place:success", this.xhr); + this.xhr = null; + } +} + +$.fn.editionInPlace = function(edit_selector) { + return this.each(function() { + return new EditionInPlace($(this), edit_selector); + }); +}; diff --git a/app/assets/javascripts/lockable_edition_in_place.coffee b/app/assets/javascripts/lockable_edition_in_place.coffee deleted file mode 100644 index 9213b45a4..000000000 --- a/app/assets/javascripts/lockable_edition_in_place.coffee +++ /dev/null @@ -1,13 +0,0 @@ -$ = window.jQuery - -$.fn.lockableEditionInPlace = -> - $(@).on("in_place:form", -> - self = $(@) - self.data cancel: self.find(".cancel").data("url") - self.data token: self.find('input[name="authenticity_token"]').serialize() - ).on("in_place:reset", -> - self = $(@) - $.ajax url: self.data("cancel"), type: "post", data: self.data("token") - ).on("in_place:cant_edit", (event, xhr) -> - $.noticeAdd text: xhr.responseText - ).editionInPlace("button.edit") diff --git a/app/assets/javascripts/lockable_edition_in_place.js b/app/assets/javascripts/lockable_edition_in_place.js new file mode 100644 index 000000000..82ae1dc17 --- /dev/null +++ b/app/assets/javascripts/lockable_edition_in_place.js @@ -0,0 +1,24 @@ +$ = window.jQuery; + +$.fn.lockableEditionInPlace = function() { + return $(this) + .on("in_place:form", function() { + const self = $(this); + self.data({ cancel: self.find(".cancel").data("url") }); + self.data({ + token: self.find('input[name="authenticity_token"]').serialize() + }); + }) + .on("in_place:reset", function() { + const self = $(this); + $.ajax({ + url: self.data("cancel"), + type: "post", + data: self.data("token") + }); + }) + .on("in_place:cant_edit", (event, xhr) => + $.noticeAdd({ text: xhr.responseText }) + ) + .editionInPlace("button.edit"); +}; diff --git a/app/assets/javascripts/nested_fields.coffee b/app/assets/javascripts/nested_fields.coffee deleted file mode 100644 index 4f4f29ca0..000000000 --- a/app/assets/javascripts/nested_fields.coffee +++ /dev/null @@ -1,48 +0,0 @@ -$ = window.jQuery - -class NestedFields - constructor: (@el, @parent, @nested, @text, @tag, @attributes) -> - @create() - - create: -> - items = @el.children(".#{@nested}") - @counter = items.length - @bind_item item, i for item, i in items - @el.append $("<#{@tag}/>", html: $("""" - it.children(".remove").click => - if counter - name = "#{@parent}[#{@nested}s_attributes][#{counter}][_destroy]" - it.replaceWith $("", name: name, type: "hidden", value: 1) - else - it.remove() - false - - add_item: => - last = @el.children(".#{@nested}:last") - last = @el.children("#{@tag}:first") if last.length == 0 - fset = $("<#{@tag}/>", class: @nested) - last.after fset - for i,type of @attributes - name = "#{@parent}[#{@nested}s_attributes][#{@counter}][#{i}]" - if typeof (type) == "string" - elem = $("", name: name, type: type, size: 30, autocomplete: "off") - else - elem = $("", { name, type: "hidden", value: 1 })); + } else { + it.remove(); + } + return false; + }); + } + + add_item() { + let last = this.el.children(`.${this.nested}:last`); + if (last.length === 0) { + last = this.el.children(`${this.tag}:first`); + } + const fset = $(`<${this.tag}/>`, { class: this.nested }); + last.after(fset); + for (var i in this.attributes) { + var elem; + var type = this.attributes[i]; + var name = `${this.parent}[${this.nested}s_attributes][${ + this.counter + }][${i}]`; + if (typeof type === "string") { + elem = $("", { name, type, size: 30, autocomplete: "off" }); + } else { + elem = $("