Merge pull request #2726 from tchak/less-jquery

Remove jQuery from new design
This commit is contained in:
gregoirenovel 2018-10-10 15:20:54 +02:00 committed by GitHub
commit 165feb20b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 121 additions and 83 deletions

View file

@ -65,7 +65,6 @@
} }
.confidentiel-explanation { .confidentiel-explanation {
display: none;
font-size: 14px; font-size: 14px;
color: $grey; color: $grey;
margin-top: -$default-padding; margin-top: -$default-padding;

View file

@ -2,7 +2,6 @@
@import "constants"; @import "constants";
.motivation { .motivation {
display: none;
padding: $default-padding; padding: $default-padding;
color: $black; color: $black;
width: 450px; width: 450px;

View file

@ -1,5 +1,5 @@
import $ from 'jquery'; import { toggle } from '@utils';
export function toggleCondidentielExplanation() { export function toggleCondidentielExplanation() {
$('.confidentiel-explanation').toggle(); toggle(document.querySelector('.confidentiel-explanation'));
} }

View file

@ -1,5 +1,5 @@
import $ from 'jquery';
import L from 'leaflet'; import L from 'leaflet';
import { getJSON } from '@utils';
import { getData } from '../shared/data'; import { getData } from '../shared/data';
import { DEFAULT_POSITION } from '../shared/carto'; import { DEFAULT_POSITION } from '../shared/carto';
@ -11,8 +11,8 @@ import {
} from './carto/draw'; } from './carto/draw';
function initialize() { function initialize() {
if ($('#map').length > 0) { if (document.getElementById('map')) {
$.getJSON(getData('carto').getPositionUrl).then( getJSON(getData('carto').getPositionUrl).then(
position => initializeWithPosition(position), position => initializeWithPosition(position),
() => initializeWithPosition(DEFAULT_POSITION) () => initializeWithPosition(DEFAULT_POSITION)
); );

View file

@ -1,8 +1,6 @@
import Rails from 'rails-ujs'; import { delegate } from '@utils';
const { delegate } = Rails; delegate('click', 'body', event => {
delegate(document, 'body', 'click', event => {
if (!event.target.closest('.dropdown')) { if (!event.target.closest('.dropdown')) {
[...document.querySelectorAll('.dropdown')].forEach(element => [...document.querySelectorAll('.dropdown')].forEach(element =>
element.classList.remove('open', 'fade-in-down') element.classList.remove('open', 'fade-in-down')
@ -10,7 +8,7 @@ delegate(document, 'body', 'click', event => {
} }
}); });
delegate(document, '.dropdown-button', 'click', event => { delegate('click', '.dropdown-button', event => {
event.stopPropagation(); event.stopPropagation();
const parent = event.target.closest('.dropdown-button').parentElement; const parent = event.target.closest('.dropdown-button').parentElement;
if (parent.classList.contains('dropdown')) { if (parent.classList.contains('dropdown')) {

View file

@ -1,10 +1,19 @@
import $ from 'jquery'; import { delegate } from '@utils';
$(document).on('blur keydown', 'input, textarea', () => { delegate('blur keydown', 'input, textarea', ({ target }) => {
$(this).addClass('touched'); touch(target);
}); });
$(document).on('click', 'input[type="submit"]:not([formnovalidate])', () => { delegate(
const $form = $(this).closest('form'); 'click',
$('input, textarea', $form).addClass('touched'); 'input[type="submit"]:not([formnovalidate])',
}); ({ target }) => {
let form = target.closest('form');
let inputs = form ? form.querySelectorAll('input, textarea') : [];
[...inputs].forEach(touch);
}
);
function touch({ classList }) {
classList.add('touched');
}

View file

@ -1,27 +1,17 @@
import $ from 'jquery'; import { scrollTo, scrollToBottom } from '@utils';
export function scrollMessagerie() { export function scrollMessagerie() {
const $ul = $('.messagerie ul').first(); const ul = document.querySelector('.messagerie ul');
if ($ul.length) { if (ul) {
const $elementToScroll = $('.date.highlighted').first(); const elementToScroll = document.querySelector('.date.highlighted');
if ($elementToScroll.length != 0) { if (elementToScroll) {
scrollTo($ul, $elementToScroll); scrollTo(ul, elementToScroll);
} else { } else {
scrollToBottom($ul); scrollToBottom(ul);
} }
} }
} }
function scrollTo($container, $scrollTo) {
$container.scrollTop(
$scrollTo.offset().top - $container.offset().top + $container.scrollTop()
);
}
function scrollToBottom($container) {
$container.scrollTop($container.prop('scrollHeight'));
}
addEventListener('turbolinks:load', scrollMessagerie); addEventListener('turbolinks:load', scrollMessagerie);

View file

@ -1,7 +1,4 @@
import Rails from 'rails-ujs'; import { show, hide, delegate } from '@utils';
import { show, hide } from '../shared/utils';
const { delegate } = Rails;
function showSpinner() { function showSpinner() {
[...document.querySelectorAll('.spinner')].forEach(show); [...document.querySelectorAll('.spinner')].forEach(show);
@ -11,6 +8,6 @@ function hideSpinner() {
[...document.querySelectorAll('.spinner')].forEach(hide); [...document.querySelectorAll('.spinner')].forEach(hide);
} }
delegate(document, '[data-spinner]', 'ajax:complete', hideSpinner); delegate('ajax:complete', '[data-spinner]', hideSpinner);
delegate(document, '[data-spinner]', 'ajax:stopped', hideSpinner); delegate('ajax:stopped', '[data-spinner]', hideSpinner);
delegate(document, '[data-spinner]', 'ajax:send', showSpinner); delegate('ajax:send', '[data-spinner]', showSpinner);

View file

@ -1,12 +1,12 @@
import $ from 'jquery'; import { show, hide } from '@utils';
export function showMotivation(event, state) { export function showMotivation(event, state) {
event.preventDefault(); event.preventDefault();
$(`.motivation.${state}`).show(); show(document.querySelector(`.motivation.${state}`));
$('.dropdown-items').hide(); hide(document.querySelector('.dropdown-items'));
} }
export function motivationCancel() { export function motivationCancel() {
$('.motivation').hide(); document.querySelectorAll('.motivation').forEach(hide);
$('.dropdown-items').show(); show(document.querySelector('.dropdown-items'));
} }

View file

@ -1,28 +1,24 @@
import $ from 'jquery';
import Chartkick from 'chartkick'; import Chartkick from 'chartkick';
import { toggle } from '@utils';
export function toggleChart(event, chartClass) { export function toggleChart(event, chartClass) {
const nextSelectorItem = $(event.target), const nextSelectorItem = event.target,
nextChart = $(chartClass), nextChart = document.querySelector(chartClass),
nextChartId = nextChart nextChartId = nextChart.children[0].id,
.children() currentSelectorItem = nextSelectorItem.parentElement.querySelector(
.first() '.segmented-control-item-active'
.attr('id'), ),
currentSelectorItem = nextSelectorItem currentChart = nextSelectorItem.parentElement.parentElement.querySelector(
.parent() '.chart:not(.hidden)'
.find('.segmented-control-item-active'), );
currentChart = nextSelectorItem
.parent()
.parent()
.find('.chart:not(.hidden)');
// Change the current selector and the next selector states // Change the current selector and the next selector states
currentSelectorItem.toggleClass('segmented-control-item-active'); currentSelectorItem.classList.toggle('segmented-control-item-active');
nextSelectorItem.toggleClass('segmented-control-item-active'); nextSelectorItem.classList.toggle('segmented-control-item-active');
// Hide the currently shown chart and show the new one // Hide the currently shown chart and show the new one
currentChart.toggleClass('hidden'); toggle(currentChart);
nextChart.toggleClass('hidden'); toggle(nextChart);
// Reflow needed, see https://github.com/highcharts/highcharts/issues/1979 // Reflow needed, see https://github.com/highcharts/highcharts/issues/1979
Chartkick.charts[nextChartId].getChartObject().reflow(); Chartkick.charts[nextChartId].getChartObject().reflow();

View file

@ -4,7 +4,6 @@ import Rails from 'rails-ujs';
import ActiveStorage from '../shared/activestorage/ujs'; import ActiveStorage from '../shared/activestorage/ujs';
import Chartkick from 'chartkick'; import Chartkick from 'chartkick';
import Highcharts from 'highcharts'; import Highcharts from 'highcharts';
import jQuery from 'jquery';
import '../shared/sentry'; import '../shared/sentry';
import '../shared/rails-ujs-fix'; import '../shared/rails-ujs-fix';
@ -41,11 +40,6 @@ Rails.start();
Turbolinks.start(); Turbolinks.start();
ActiveStorage.start(); ActiveStorage.start();
// Disable jQuery-driven animations during tests
if (process.env['RAILS_ENV'] === 'test') {
jQuery.fx.off = true;
}
// Expose globals // Expose globals
window.DS = window.DS || DS; window.DS = window.DS || DS;
window.Chartkick = Chartkick; window.Chartkick = Chartkick;

View file

@ -1,5 +1,5 @@
import $ from 'jquery';
import autocomplete from 'autocomplete.js'; import autocomplete from 'autocomplete.js';
import { getJSON, fire } from '@utils';
const sources = [ const sources = [
{ {
@ -24,7 +24,7 @@ function selector(type) {
function source(url) { function source(url) {
return { return {
source(query, callback) { source(query, callback) {
$.getJSON(url, { request: query }).then(callback); getJSON(url, { request: query }).then(callback);
}, },
templates: { templates: {
suggestion({ label, mine }) { suggestion({ label, mine }) {
@ -41,7 +41,7 @@ addEventListener('turbolinks:load', function() {
for (let target of document.querySelectorAll(selector(type))) { for (let target of document.querySelectorAll(selector(type))) {
let select = autocomplete(target, options, [source(url)]); let select = autocomplete(target, options, [source(url)]);
select.on('autocomplete:selected', ({ target }, suggestion) => { select.on('autocomplete:selected', ({ target }, suggestion) => {
$(target).trigger('autocomplete:select', suggestion); fire(target, 'autocomplete:select', suggestion);
select.autocomplete.setVal(suggestion.label); select.autocomplete.setVal(suggestion.label);
}); });
} }

View file

@ -1,12 +1,13 @@
import Rails from 'rails-ujs'; import Rails from 'rails-ujs';
import jQuery from 'jquery'; import jQuery from 'jquery';
import { delegate } from '@utils';
// We use `jQuery.active` in our capybara suit to wait for ajax requests. // We use `jQuery.active` in our capybara suit to wait for ajax requests.
// Newer jQuery-less version of rails-ujs is breaking it. // Newer jQuery-less version of rails-ujs is breaking it.
// We have to set `ajax:complete` listener on the same element as the one // We have to set `ajax:complete` listener on the same element as the one
// we catch ajax:send on as by the end of the request // we catch ajax:send on as by the end of the request
// the old element may be removed from DOM. // the old element may be removed from DOM.
Rails.delegate(document, '[data-remote]', 'ajax:send', ({ target }) => { delegate('ajax:send', '[data-remote]', ({ target }) => {
let callback = () => { let callback = () => {
jQuery.active--; jQuery.active--;
target.removeEventListener('ajax:complete', callback); target.removeEventListener('ajax:complete', callback);

View file

@ -1,7 +1,4 @@
import Rails from 'rails-ujs'; import { delegate, fire, debounce } from '@utils';
import debounce from 'debounce';
const { delegate, fire } = Rails;
const remote = 'data-remote'; const remote = 'data-remote';
const inputChangeSelector = `input[${remote}], textarea[${remote}]`; const inputChangeSelector = `input[${remote}], textarea[${remote}]`;
@ -21,4 +18,4 @@ function isRemote(element) {
return value && value !== 'false'; return value && value !== 'false';
} }
delegate(document, inputChangeSelector, 'input', debounce(handleRemote, 200)); delegate('input', inputChangeSelector, debounce(handleRemote, 200));

View file

@ -1,3 +1,10 @@
import Rails from 'rails-ujs';
import $ from 'jquery';
import debounce from 'debounce';
export { debounce };
export const { fire } = Rails;
export function show({ classList }) { export function show({ classList }) {
classList.remove('hidden'); classList.remove('hidden');
} }
@ -9,3 +16,45 @@ export function hide({ classList }) {
export function toggle({ classList }) { export function toggle({ classList }) {
classList.toggle('hidden'); classList.toggle('hidden');
} }
export function delegate(eventNames, selector, callback) {
eventNames
.split(' ')
.forEach(eventName =>
Rails.delegate(document, selector, eventName, callback)
);
}
export function getJSON(url, data, method = 'get') {
data = method !== 'get' ? JSON.stringify(data) : data;
return $.ajax({
method,
url,
data,
contentType: 'application/json',
dataType: 'json'
});
}
export function scrollTo(container, scrollTo) {
container.scrollTop =
offset(scrollTo).top - offset(container).top + container.scrollTop;
}
export function scrollToBottom(container) {
container.scrollTop = container.scrollHeight;
}
export function on(selector, eventName, fn) {
[...document.querySelectorAll(selector)].forEach(element =>
element.addEventListener(eventName, event => fn(event, event.detail))
);
}
function offset(element) {
const rect = element.getBoundingClientRect();
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
};
}

View file

@ -1,4 +1,4 @@
.motivation{ class: popup_class } .motivation.hidden{ class: popup_class }
%h3 %h3
%span.icon{ class: popup_class } %span.icon{ class: popup_class }
#{popup_title} #{popup_title}

View file

@ -17,7 +17,7 @@
.confidentiel-wrapper .confidentiel-wrapper
= f.label :confidentiel, 'Cet avis est' = f.label :confidentiel, 'Cet avis est'
= f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);" = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);"
.confidentiel-explanation .confidentiel-explanation.hidden
Il ne sera pas affiché aux autres experts consultés mais sera visible par les instructeurs Il ne sera pas affiché aux autres experts consultés mais sera visible par les instructeurs
.send-wrapper .send-wrapper
= f.submit 'Demander un avis', class: 'button send' = f.submit 'Demander un avis', class: 'button send'

View file

@ -1,3 +1,4 @@
const path = require('path');
const { environment } = require('@rails/webpacker'); const { environment } = require('@rails/webpacker');
// By default don't transpile JS files in ./node_modules except for some specific modules. // By default don't transpile JS files in ./node_modules except for some specific modules.
@ -14,4 +15,12 @@ babelLoader.exclude = function(modulePath) {
); );
}; };
const resolve = {
alias: {
'@utils': path.resolve(__dirname, '..', '..', 'app/javascript/shared/utils')
}
};
environment.config.merge({ resolve });
module.exports = environment; module.exports = environment;