/** * Yobi, Project Hosting SW * * Copyright 2014 NAVER Corp. * http://yobi.io * * @author Jihan Kim * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * yobi.ui.Select2 * * @requires select2.js (http://ivaynberg.github.io/select2/) */ (function(ns){ "use strict"; var oNS = $yobi.createNamespace(ns); oNS.container[oNS.name] = function(element, options){ var targetElement = $(element); var select2Option = $.extend({ "width" : "resolve", "allowClear" : targetElement.data("allowClear"), "closeOnSelect" : targetElement.data("closeOnSelect"), "dropdownCssClass" : targetElement.data("dropdownCssClass"), "containerCssClass": targetElement.data("containerCssClass") }, options); // Customized formats var formatters = { "projects": function(itemObject){ var itemElement = $(itemObject.element); var avatarURL = itemElement.data("avatarUrl"); function _doesntHaveProjectAvatar() { return !avatarURL || avatarURL.indexOf("project_default_logo.png") !== -1; } var owner = itemElement.data("owner") ? itemElement.data("owner") : ""; if(_doesntHaveProjectAvatar()){ return $.tmpl($("#tplSelect2ProjectsWithoutAvatar").text(), { "name" : itemObject.text, "owner" : owner }); } else { return $.tmpl($("#tplSelect2Projects").text(), { "avatarURL": avatarURL, "name" : itemObject.text.trim(), "owner" : owner }); } }, "issues": function(itemObject){ return $.tmpl($("#tplSelect2FormatIssues").text(), { "name" : itemObject.text }); }, "user": function(itemObject){ var itemElement = $(itemObject.element); var avatarURL = itemElement.data("avatarUrl"); if(!avatarURL){ return '
' + itemObject.text + '
'; } // Template text var tplUserItem = $("#tplSelect2FormatUser").text() || '
' + '' + '${name}' + '${loginId}
'; var loginId = itemElement.data("loginId") ? "@" + itemElement.data("loginId") : ""; var formattedResult = $.tmpl(tplUserItem, { "avatarURL": avatarURL, "name" : itemObject.text.trim(), "loginId" : loginId }); return formattedResult; }, "milestone": function(itemObject){ var itemElement = $(itemObject.element); var milestoneState = itemElement.data("state"); if(!milestoneState){ return itemObject.text; } milestoneState = milestoneState.toLowerCase(); var milestoneStateLabel = Messages("milestone.state." + milestoneState); var tplMilestoneItem = $("#tplSElect2FormatMilestone").text() || '
${name}
'; var formattedResult = $.tmpl(tplMilestoneItem, { "name" : itemObject.text.trim().replace('<', '<'), "state": milestoneState, "stateLabel": milestoneStateLabel }); return formattedResult; }, "issuelabel": function(itemObject){ var element = $(itemObject.element); var labelId = element.val(); var text = $.trim($('
').text(itemObject.text).html()); if(!labelId){ // = optgroup var isCategoryExclusive = element.data("categoryIsExclusive"); var data = { "text" : text, "title": Messages("label.category.option") + '
' + (isCategoryExclusive ? Messages("label.category.option.single") : Messages("label.category.option.multiple")), "css" : isCategoryExclusive ? 'yobicon-tag category-exclusive single' : 'yobicon-tags category-exclusive multiple' }; var tpl = '${text}'; return $.tmpl(tpl, data); } return '' + text + ''; }, "branch": function(itemObject){ var branchType = "unknown"; var branchName = itemObject.text.trim(); var branchNameRegex = /refs\/(.[a-z]+)\/(.+)/i; // parse branchName with regular expression branchNameRegex // e.g.'refs/heads/feature/review-10' // -> ["refs/heads/feature/review-10", "heads", "feature/review-10"] var parsedBranchName = branchName.match(branchNameRegex); var branchTypeMapByName = { "heads": "branch", "tags" : "tag" }; if(parsedBranchName){ branchType = branchTypeMapByName[parsedBranchName[1]] || parsedBranchName[1]; branchName = parsedBranchName[2]; } var tplBranchItem = $("#tplSelect2FormatBranch").text() || '${branchType} ${branchName}'; // branchType will be "unknown" // if selected branch name doesn't starts with /refs var formattedResult = $.tmpl(tplBranchItem, { "branchType": branchType, "branchName": branchName }); return formattedResult; } }; // Custom matchers var matchers = { "user": function(term, formattedResult, itemElement){ term = term.toLowerCase(); formattedResult = formattedResult.toLowerCase(); var loginId = itemElement.data("loginId") + ""; loginId = (typeof loginId !== "undefined") ? loginId.toLowerCase() : ""; return (loginId.indexOf(term) > -1) || (formattedResult.indexOf(term) > -1); }, "projects": function(term, formattedResult, itemElement){ term = term.toLowerCase(); formattedResult = formattedResult.toLowerCase(); var owner = itemElement.data("owner") + ""; owner = (typeof owner !== "undefined") ? owner.toLowerCase() : ""; return (owner.indexOf(term) > -1) || (formattedResult.indexOf(term) > -1); } }; // Custom behaviors var behaviors = { "issuelabel": function(select2Element){ select2Element.on({ "select2-selecting": _onSelectingIssueLabel, "select2-open" : _onOpenIssueLabel }); function _onSelectingIssueLabel(evt){ var data = [evt.object]; var element = $(evt.object.element); var select2Object = $(evt.target).data("select2"); var oldData = select2Object.data() // Remove label which category is same with selected label from current data // if selected label belonged exclusive category if(element.data("categoryIsExclusive")){ var categoryId = $(evt.object.element).data("categoryId"); var filtered = _filterLabelInSameCategory(categoryId, oldData); data = data.concat(filtered); if(oldData.length != filtered.length){ _unselect(select2Object, categoryId); } } else { data = data.concat(oldData); } _rememberLastScrollTop(); // Set data as filtered // and trigger "change" event select2Object.data(data, true); if(select2Object.opts.closeOnSelect !== false){ select2Object.close(); } evt.preventDefault(); return false; } function _filterLabelInSameCategory(categoryId, currentData){ return currentData.filter(function(data){ return (categoryId !== $(data.element).data("categoryId")); }); } function _rememberLastScrollTop(){ var lastScrollTop = $("#select2-drop").find(".select2-results").scrollTop(); select2Element.data("lastScrollTop", lastScrollTop); } function _restoreLastScrollTop(){ var lastScrollTop = select2Element.data("lastScrollTop"); if(lastScrollTop){ $("#select2-drop").find(".select2-results").scrollTop(lastScrollTop); select2Element.data("lastScrollTop", null); } } function _onOpenIssueLabel(){ _restoreLastScrollTop(); } // When select2 v3.x is migrated to v4.x, it will probably need to be updated. function _unselect(select2Object, categoryId){ select2Object.results.find(".select2-selected").filter(function(){ var optionElement = $(this).data("select2-data").element; return $(optionElement).data("categoryId") === categoryId; }).removeClass("select2-selected"); } } }; // Use customized format if specified format exists var formatName = targetElement.data("format"); var formatter = formatName ? formatters[formatName.toLowerCase()] : null; var matcher = formatName ? matchers[formatName.toLowerCase()] : null; var behavior = formatName ? behaviors[formatName.toLowerCase()] : null; if(typeof formatter === "function"){ select2Option = $.extend(select2Option, { "formatResult" : formatter, "formatSelection": formatter }); } if(typeof matcher === "function"){ select2Option.matcher = matcher; } if(typeof behavior === "function"){ behavior(targetElement); } $(document).on("mousewheel", ".select2-results", _stopScrollOnBothEnds); function _stopScrollOnBothEnds(evt){ if((evt.originalEvent.deltaY > 0 && _isScrollEndOfList(evt.currentTarget)) || (evt.originalEvent.deltaY < 0 && _isScrollTopOfList(evt.currentTarget))){ evt.preventDefault(); evt.stopPropagation(); return false; } } function _isScrollTopOfList(element){ return ($(element).scrollTop() === 0); } function _isScrollEndOfList(element){ return ($(element).scrollTop() + $(element).height() === element.scrollHeight); } return targetElement.select2(select2Option); }; })("yobi.ui.Select2"); $(function(){ $('[data-toggle="select2"]').each(function(i, el){ yobi.ui.Select2(el); }); });