Commit 40a04bc7 authored by Tim Zallmann's avatar Tim Zallmann

Wraps Select 2 Import into its own webpack bundle

Wraps all imports for select 2 to deferred imports,
especially in the main.js we are actually checking if there 
is any select 2 element on the page or not.
parent 2bb0d089
......@@ -7,4 +7,3 @@ import 'vendor/jquery.caret';
import 'vendor/jquery.atwho';
import 'vendor/jquery.scrollTo';
import 'jquery.waitforimages';
import 'select2/select2';
......@@ -4,93 +4,97 @@ import Api from './api';
import { normalizeHeaders } from './lib/utils/common_utils';
export default function groupsSelect() {
// Needs to be accessible in rspec
window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this);
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
const groupsPath = parentGroupID
? Api.subgroupsPath.replace(':id', parentGroupID)
: Api.groupsPath;
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
// Needs to be accessible in rspec
window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this);
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
const groupsPath = parentGroupID
? Api.subgroupsPath.replace(':id', parentGroupID)
: Api.groupsPath;
$select.select2({
placeholder: 'Search for a group',
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
.then(res => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
$select.select2({
placeholder: 'Search for a group',
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
.then(res => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
},
data(search, page) {
return {
search,
page,
per_page: window.GROUP_SELECT_PER_PAGE,
all_available: allAvailable,
};
},
results(data, page) {
if (data.length) return { results: [] };
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
},
data(search, page) {
return {
search,
page,
per_page: window.GROUP_SELECT_PER_PAGE,
all_available: allAvailable,
};
},
results(data, page) {
if (data.length) return { results: [] };
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
return {
results,
page,
more,
};
},
},
// eslint-disable-next-line consistent-return
initSelection(element, callback) {
const id = $(element).val();
if (id !== '') {
return Api.group(id, callback);
}
},
formatResult(object) {
return `<div class='group-result'> <div class='group-name'>${
object.full_name
}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
},
dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
// we do not want to escape markup since we are displaying html in results
escapeMarkup(m) {
return m;
},
});
return {
results,
page,
more,
};
},
},
// eslint-disable-next-line consistent-return
initSelection(element, callback) {
const id = $(element).val();
if (id !== '') {
return Api.group(id, callback);
}
},
formatResult(object) {
return `<div class='group-result'> <div class='group-name'>${
object.full_name
}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
},
dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
// we do not want to escape markup since we are displaying html in results
escapeMarkup(m) {
return m;
},
});
$select.on('select2-loaded', () => {
const dropdown = document.querySelector('.select2-infinite .select2-results');
dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
});
});
$select.on('select2-loaded', () => {
const dropdown = document.querySelector('.select2-infinite .select2-results');
dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
});
});
})
.catch(() => {});
}
......@@ -11,10 +11,14 @@ class AutoWidthDropdownSelect {
init() {
const { dropdownClass } = this;
this.$selectElement.select2({
dropdownCssClass: dropdownClass,
...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
});
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
this.$selectElement.select2({
dropdownCssClass: dropdownClass,
...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
});
})
.catch(() => {});
return this;
}
......
......@@ -7,10 +7,14 @@ export default class IssuableContext {
constructor(currentUser) {
this.userSelect = new UsersSelect(currentUser);
$('select.select2').select2({
width: 'resolve',
dropdownAutoWidth: true,
});
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
$('select.select2').select2({
width: 'resolve',
dropdownAutoWidth: true,
});
})
.catch(() => {});
$('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
return $(this).submit();
......
......@@ -120,35 +120,39 @@ export default class IssuableForm {
}
initTargetBranchDropdown() {
this.$targetBranchSelect.select2({
...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
ajax: {
url: this.$targetBranchSelect.data('endpoint'),
dataType: 'JSON',
quietMillis: 250,
data(search) {
return {
search,
};
},
results(data) {
return {
// `data` keys are translated so we can't just access them with a string based key
results: data[Object.keys(data)[0]].map(name => ({
id: name,
text: name,
})),
};
},
},
initSelection(el, callback) {
const val = el.val();
callback({
id: val,
text: val,
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
this.$targetBranchSelect.select2({
...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
ajax: {
url: this.$targetBranchSelect.data('endpoint'),
dataType: 'JSON',
quietMillis: 250,
data(search) {
return {
search,
};
},
results(data) {
return {
// `data` keys are translated so we can't just access them with a string based key
results: data[Object.keys(data)[0]].map(name => ({
id: name,
text: name,
})),
};
},
},
initSelection(el, callback) {
const val = el.val();
callback({
id: val,
text: val,
});
},
});
},
});
})
.catch(() => {});
}
}
......@@ -100,18 +100,24 @@ function deferredInitialisation() {
});
// Initialize select2 selects
$('select.select2').select2({
width: 'resolve',
dropdownAutoWidth: true,
});
// Close select2 on escape
$('.js-select2').on('select2-close', () => {
setTimeout(() => {
$('.select2-container-active').removeClass('select2-container-active');
$(':focus').blur();
}, 1);
});
if ($('select.select2').length) {
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
$('select.select2').select2({
width: 'resolve',
dropdownAutoWidth: true,
});
// Close select2 on escape
$('.js-select2').on('select2-close', () => {
setTimeout(() => {
$('.select2-container-active').removeClass('select2-container-active');
$(':focus').blur();
}, 1);
});
})
.catch(() => {});
}
// Initialize tooltips
$body.tooltip({
......
......@@ -5,97 +5,101 @@ import Api from './api';
import ProjectSelectComboButton from './project_select_combo_button';
export default function projectSelect() {
$('.ajax-project-select').each(function(i, select) {
var placeholder;
const simpleFilter = $(select).data('simpleFilter') || false;
this.groupId = $(select).data('groupId');
this.includeGroups = $(select).data('includeGroups');
this.allProjects = $(select).data('allProjects') || false;
this.orderBy = $(select).data('orderBy') || 'id';
this.withIssuesEnabled = $(select).data('withIssuesEnabled');
this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
this.withShared =
$(select).data('withShared') === undefined ? true : $(select).data('withShared');
this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
this.allowClear = $(select).data('allowClear') || false;
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
$('.ajax-project-select').each(function(i, select) {
var placeholder;
const simpleFilter = $(select).data('simpleFilter') || false;
this.groupId = $(select).data('groupId');
this.includeGroups = $(select).data('includeGroups');
this.allProjects = $(select).data('allProjects') || false;
this.orderBy = $(select).data('orderBy') || 'id';
this.withIssuesEnabled = $(select).data('withIssuesEnabled');
this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
this.withShared =
$(select).data('withShared') === undefined ? true : $(select).data('withShared');
this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
this.allowClear = $(select).data('allowClear') || false;
placeholder = 'Search for project';
if (this.includeGroups) {
placeholder += ' or group';
}
placeholder = 'Search for project';
if (this.includeGroups) {
placeholder += ' or group';
}
$(select).select2({
placeholder: placeholder,
minimumInputLength: 0,
query: (function(_this) {
return function(query) {
var finalCallback, projectsCallback;
finalCallback = function(projects) {
var data;
data = {
results: projects,
};
return query.callback(data);
};
if (_this.includeGroups) {
projectsCallback = function(projects) {
var groupsCallback;
groupsCallback = function(groups) {
$(select).select2({
placeholder: placeholder,
minimumInputLength: 0,
query: (function(_this) {
return function(query) {
var finalCallback, projectsCallback;
finalCallback = function(projects) {
var data;
data = groups.concat(projects);
return finalCallback(data);
data = {
results: projects,
};
return query.callback(data);
};
return Api.groups(query.term, {}, groupsCallback);
if (_this.includeGroups) {
projectsCallback = function(projects) {
var groupsCallback;
groupsCallback = function(groups) {
var data;
data = groups.concat(projects);
return finalCallback(data);
};
return Api.groups(query.term, {}, groupsCallback);
};
} else {
projectsCallback = finalCallback;
}
if (_this.groupId) {
return Api.groupProjects(
_this.groupId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
{
order_by: _this.orderBy,
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
membership: !_this.allProjects,
},
projectsCallback,
);
}
};
} else {
projectsCallback = finalCallback;
}
if (_this.groupId) {
return Api.groupProjects(
_this.groupId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
{
order_by: _this.orderBy,
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
membership: !_this.allProjects,
},
projectsCallback,
);
}
};
})(this),
id: function(project) {
if (simpleFilter) return project.id;
return JSON.stringify({
name: project.name,
url: project.web_url,
});
},
text: function(project) {
return project.name_with_namespace || project.name;
},
})(this),
id: function(project) {
if (simpleFilter) return project.id;
return JSON.stringify({
name: project.name,
url: project.web_url,
});
},
text: function(project) {
return project.name_with_namespace || project.name;
},
initSelection: function(el, callback) {
return Api.project(el.val()).then(({ data }) => callback(data));
},
initSelection: function(el, callback) {
return Api.project(el.val()).then(({ data }) => callback(data));
},
allowClear: this.allowClear,
allowClear: this.allowClear,
dropdownCssClass: 'ajax-project-dropdown',
});
if (simpleFilter) return select;
return new ProjectSelectComboButton(select);
});
dropdownCssClass: 'ajax-project-dropdown',
});
if (simpleFilter) return select;
return new ProjectSelectComboButton(select);
});
})
.catch(() => {});
}
......@@ -44,9 +44,13 @@ export default class ProjectSelectComboButton {
// eslint-disable-next-line class-methods-use-this
openDropdown(event) {
$(event.currentTarget)
.siblings('.project-item-select')
.select2('open');
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
$(event.currentTarget)
.siblings('.project-item-select')
.select2('open');
})
.catch(() => {});
}
selectProject() {
......
......@@ -579,101 +579,109 @@ function UsersSelect(currentUser, els, options = {}) {
};
})(this),
);
$('.ajax-users-select').each(
(function(_this) {
return function(i, select) {
var firstUser, showAnyUser, showEmailUser, showNullUser;
var options = {};
options.skipLdap = $(select).hasClass('skip_ldap');
options.projectId = $(select).data('projectId');
options.groupId = $(select).data('groupId');
options.showCurrentUser = $(select).data('currentUser');
options.authorId = $(select).data('authorId');
options.skipUsers = $(select).data('skipUsers');
showNullUser = $(select).data('nullUser');
showAnyUser = $(select).data('anyUser');
showEmailUser = $(select).data('emailUser');
firstUser = $(select).data('firstUser');
return $(select).select2({
placeholder: 'Search for a user',
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
return _this.users(query.term, options, function(users) {
var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
data = {
results: users,
};
if (query.term.length === 0) {
if (firstUser) {
// Move current user to the front of the list
ref = data.results;
for (index = 0, len = ref.length; index < len; index += 1) {
obj = ref[index];
if (obj.username === firstUser) {
data.results.splice(index, 1);
data.results.unshift(obj);
break;
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
$('.ajax-users-select').each(
(function(_this) {
return function(i, select) {
var firstUser, showAnyUser, showEmailUser, showNullUser;
var options = {};
options.skipLdap = $(select).hasClass('skip_ldap');
options.projectId = $(select).data('projectId');
options.groupId = $(select).data('groupId');
options.showCurrentUser = $(select).data('currentUser');
options.authorId = $(select).data('authorId');
options.skipUsers = $(select).data('skipUsers');
showNullUser = $(select).data('nullUser');
showAnyUser = $(select).data('anyUser');
showEmailUser = $(select).data('emailUser');
firstUser = $(select).data('firstUser');
return $(select).select2({
placeholder: 'Search for a user',
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
return _this.users(query.term, options, function(users) {
var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
data = {
results: users,
};
if (query.term.length === 0) {
if (firstUser) {
// Move current user to the front of the list
ref = data.results;
for (index = 0, len = ref.length; index < len; index += 1) {
obj = ref[index];
if (obj.username === firstUser) {
data.results.splice(index, 1);
data.results.unshift(obj);
break;
}
}
}
if (showNullUser) {
nullUser = {
name: 'Unassigned',
id: 0,
};
data.results.unshift(nullUser);
}
if (showAnyUser) {
name = showAnyUser;
if (name === true) {
name = 'Any User';
}
anyUser = {
name: name,
id: null,
};
data.results.unshift(anyUser);
}
}
}
if (showNullUser) {
nullUser = {
name: 'Unassigned',
id: 0,
};
data.results.unshift(nullUser);
}
if (showAnyUser) {
name = showAnyUser;
if (name === true) {
name = 'Any User';
if (
showEmailUser &&
data.results.length === 0 &&
query.term.match(/^[^@]+@[^@]+$/)
) {
var trimmed = query.term.trim();
emailUser = {
name: 'Invite "' + trimmed + '" by email',
username: trimmed,
id: trimmed,
invite: true,
};
data.results.unshift(emailUser);
}
anyUser = {
name: name,
id: null,
};
data.results.unshift(anyUser);
}
}
if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
var trimmed = query.term.trim();
emailUser = {
name: 'Invite "' + trimmed + '" by email',
username: trimmed,
id: trimmed,
invite: true,
};
data.results.unshift(emailUser);
}
return query.callback(data);
return query.callback(data);
});
},
initSelection: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.initSelection.apply(_this, args);
},
formatResult: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.formatResult.apply(_this, args);
},
formatSelection: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.formatSelection.apply(_this, args);
},
dropdownCssClass: 'ajax-users-dropdown',
// we do not want to escape markup since we are displaying html in results
escapeMarkup: function(m) {
return m;
},
});
},
initSelection: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.initSelection.apply(_this, args);
},
formatResult: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.formatResult.apply(_this, args);
},
formatSelection: function() {
var args;
args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
return _this.formatSelection.apply(_this, args);
},
dropdownCssClass: 'ajax-users-dropdown',
// we do not want to escape markup since we are displaying html in results
escapeMarkup: function(m) {
return m;
},
});
};
})(this),
);
};
})(this),
);
})
.catch(() => {});
}
UsersSelect.prototype.initSelection = function(element, callback) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment