Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
6e12c008
Commit
6e12c008
authored
Nov 20, 2019
by
Marvin Karegyeya
Committed by
Kushal Pandya
Nov 20, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove-IIFEs-from-gl_dropdown.js
parent
7de8ee9f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
804 additions
and
878 deletions
+804
-878
app/assets/javascripts/gl_dropdown.js
app/assets/javascripts/gl_dropdown.js
+799
-878
changelogs/unreleased/Remove-IIFEs-from-gl_dropdown-js.yml
changelogs/unreleased/Remove-IIFEs-from-gl_dropdown-js.yml
+5
-0
No files found.
app/assets/javascripts/gl_dropdown.js
View file @
6e12c008
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-
shadow, no-
cond-assign, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, no-param-reassign, no-loop-func */
/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-cond-assign, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, no-param-reassign, no-loop-func */
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
...
...
@@ -8,984 +8,905 @@ import { visitUrl } from './lib/utils/url_utility';
import
{
isObject
}
from
'
./lib/utils/type_utility
'
;
import
renderItem
from
'
./gl_dropdown/render
'
;
var
GitLabDropdown
,
GitLabDropdownFilter
,
GitLabDropdownRemote
,
GitLabDropdownInput
;
GitLabDropdownInput
=
(
function
()
{
function
GitLabDropdownInput
(
input
,
options
)
{
var
$inputContainer
,
$clearButton
;
var
_this
=
this
;
this
.
input
=
input
;
this
.
options
=
options
;
this
.
fieldName
=
this
.
options
.
fieldName
||
'
field-name
'
;
$inputContainer
=
this
.
input
.
parent
();
$clearButton
=
$inputContainer
.
find
(
'
.js-dropdown-input-clear
'
);
$clearButton
.
on
(
'
click
'
,
(
function
(
_this
)
{
// Clear click
return
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
return
_this
.
input
.
val
(
''
)
.
trigger
(
'
input
'
)
.
focus
();
};
})(
this
),
);
const
BLUR_KEYCODES
=
[
27
,
40
];
this
.
input
.
on
(
'
keydown
'
,
e
=>
{
var
keyCode
=
e
.
which
;
if
(
keyCode
===
13
&&
!
options
.
elIsInput
)
{
e
.
preventDefault
();
}
})
.
on
(
'
input
'
,
e
=>
{
var
val
=
e
.
currentTarget
.
value
||
_this
.
options
.
inputFieldName
;
val
=
val
.
split
(
'
'
)
.
join
(
'
-
'
)
// replaces space with dash
.
replace
(
/
[^
a-zA-Z0-9 -
]
/g
,
''
)
.
toLowerCase
()
// replace non alphanumeric
.
replace
(
/
(
-
)\1
+/g
,
'
-
'
);
// replace repeated dashes
_this
.
cb
(
_this
.
options
.
fieldName
,
val
,
{},
true
);
_this
.
input
.
closest
(
'
.dropdown
'
)
.
find
(
'
.dropdown-toggle-text
'
)
.
text
(
val
);
});
}
const
HAS_VALUE_CLASS
=
'
has-value
'
;
GitLabDropdownInput
.
prototype
.
onInput
=
function
(
cb
)
{
this
.
cb
=
cb
;
};
return
GitLabDropdownInput
;
})();
GitLabDropdownFilter
=
(
function
()
{
var
BLUR_KEYCODES
,
HAS_VALUE_CLASS
;
BLUR_KEYCODES
=
[
27
,
40
];
HAS_VALUE_CLASS
=
'
has-value
'
;
function
GitLabDropdownFilter
(
input
,
options
)
{
var
$clearButton
,
$inputContainer
,
ref
,
timeout
;
this
.
input
=
input
;
this
.
options
=
options
;
this
.
filterInputBlur
=
(
ref
=
this
.
options
.
filterInputBlur
)
!=
null
?
ref
:
true
;
$inputContainer
=
this
.
input
.
parent
();
$clearButton
=
$inputContainer
.
find
(
'
.js-dropdown-input-clear
'
);
$clearButton
.
on
(
'
click
'
,
(
function
(
_this
)
{
// Clear click
return
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
return
_this
.
input
.
val
(
''
)
.
trigger
(
'
input
'
)
.
focus
();
};
})(
this
),
);
// Key events
timeout
=
''
;
this
.
input
.
on
(
'
keydown
'
,
e
=>
{
var
keyCode
=
e
.
which
;
if
(
keyCode
===
13
&&
!
options
.
elIsInput
)
{
e
.
preventDefault
();
}
})
.
on
(
'
input
'
,
()
=>
{
if
(
this
.
input
.
val
()
!==
''
&&
!
$inputContainer
.
hasClass
(
HAS_VALUE_CLASS
))
{
$inputContainer
.
addClass
(
HAS_VALUE_CLASS
);
}
else
if
(
this
.
input
.
val
()
===
''
&&
$inputContainer
.
hasClass
(
HAS_VALUE_CLASS
))
{
$inputContainer
.
removeClass
(
HAS_VALUE_CLASS
);
}
// Only filter asynchronously only if option remote is set
if
(
this
.
options
.
remote
)
{
clearTimeout
(
timeout
);
return
(
timeout
=
setTimeout
(()
=>
{
$inputContainer
.
parent
().
addClass
(
'
is-loading
'
);
return
this
.
options
.
query
(
this
.
input
.
val
(),
data
=>
{
$inputContainer
.
parent
().
removeClass
(
'
is-loading
'
);
return
this
.
options
.
callback
(
data
);
});
},
250
));
}
else
{
return
this
.
filter
(
this
.
input
.
val
());
}
});
}
const
LOADING_CLASS
=
'
is-loading
'
;
GitLabDropdownFilter
.
prototype
.
shouldBlur
=
function
(
keyCode
)
{
return
BLUR_KEYCODES
.
indexOf
(
keyCode
)
!==
-
1
;
};
const
PAGE_TWO_CLASS
=
'
is-page-two
'
;
GitLabDropdownFilter
.
prototype
.
filter
=
function
(
search_text
)
{
var
data
,
elements
,
group
,
key
,
results
,
tmp
;
if
(
this
.
options
.
onFilter
)
{
this
.
options
.
onFilter
(
search_text
);
}
data
=
this
.
options
.
data
();
if
(
data
!=
null
&&
!
this
.
options
.
filterByText
)
{
results
=
data
;
if
(
search_text
!==
''
)
{
// When data is an array of objects therefore [object Array] e.g.
// [
// { prop: 'foo' },
// { prop: 'baz' }
// ]
if
(
_
.
isArray
(
data
))
{
results
=
fuzzaldrinPlus
.
filter
(
data
,
search_text
,
{
key
:
this
.
options
.
keys
,
const
ACTIVE_CLASS
=
'
is-active
'
;
const
INDETERMINATE_CLASS
=
'
is-indeterminate
'
;
let
currentIndex
=
-
1
;
const
NON_SELECTABLE_CLASSES
=
'
.divider, .separator, .dropdown-header, .dropdown-menu-empty-item
'
;
const
SELECTABLE_CLASSES
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
, .option-hidden)`
;
const
CURSOR_SELECT_SCROLL_PADDING
=
5
;
const
FILTER_INPUT
=
'
.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)
'
;
const
NO_FILTER_INPUT
=
'
.dropdown-input .dropdown-input-field.dropdown-no-filter
'
;
function
GitLabDropdownInput
(
input
,
options
)
{
var
$inputContainer
,
$clearButton
;
var
_this
=
this
;
this
.
input
=
input
;
this
.
options
=
options
;
this
.
fieldName
=
this
.
options
.
fieldName
||
'
field-name
'
;
$inputContainer
=
this
.
input
.
parent
();
$clearButton
=
$inputContainer
.
find
(
'
.js-dropdown-input-clear
'
);
$clearButton
.
on
(
'
click
'
,
e
=>
{
// Clear click
e
.
preventDefault
();
e
.
stopPropagation
();
return
this
.
input
.
val
(
''
)
.
trigger
(
'
input
'
)
.
focus
();
});
this
.
input
.
on
(
'
keydown
'
,
e
=>
{
var
keyCode
=
e
.
which
;
if
(
keyCode
===
13
&&
!
options
.
elIsInput
)
{
e
.
preventDefault
();
}
})
.
on
(
'
input
'
,
e
=>
{
var
val
=
e
.
currentTarget
.
value
||
_this
.
options
.
inputFieldName
;
val
=
val
.
split
(
'
'
)
.
join
(
'
-
'
)
// replaces space with dash
.
replace
(
/
[^
a-zA-Z0-9 -
]
/g
,
''
)
.
toLowerCase
()
// replace non alphanumeric
.
replace
(
/
(
-
)\1
+/g
,
'
-
'
);
// replace repeated dashes
_this
.
cb
(
_this
.
options
.
fieldName
,
val
,
{},
true
);
_this
.
input
.
closest
(
'
.dropdown
'
)
.
find
(
'
.dropdown-toggle-text
'
)
.
text
(
val
);
});
}
GitLabDropdownInput
.
prototype
.
onInput
=
function
(
cb
)
{
this
.
cb
=
cb
;
};
function
GitLabDropdownFilter
(
input
,
options
)
{
var
$clearButton
,
$inputContainer
,
ref
,
timeout
;
this
.
input
=
input
;
this
.
options
=
options
;
this
.
filterInputBlur
=
(
ref
=
this
.
options
.
filterInputBlur
)
!=
null
?
ref
:
true
;
$inputContainer
=
this
.
input
.
parent
();
$clearButton
=
$inputContainer
.
find
(
'
.js-dropdown-input-clear
'
);
$clearButton
.
on
(
'
click
'
,
e
=>
{
// Clear click
e
.
preventDefault
();
e
.
stopPropagation
();
return
this
.
input
.
val
(
''
)
.
trigger
(
'
input
'
)
.
focus
();
});
// Key events
timeout
=
''
;
this
.
input
.
on
(
'
keydown
'
,
e
=>
{
var
keyCode
=
e
.
which
;
if
(
keyCode
===
13
&&
!
options
.
elIsInput
)
{
e
.
preventDefault
();
}
})
.
on
(
'
input
'
,
()
=>
{
if
(
this
.
input
.
val
()
!==
''
&&
!
$inputContainer
.
hasClass
(
HAS_VALUE_CLASS
))
{
$inputContainer
.
addClass
(
HAS_VALUE_CLASS
);
}
else
if
(
this
.
input
.
val
()
===
''
&&
$inputContainer
.
hasClass
(
HAS_VALUE_CLASS
))
{
$inputContainer
.
removeClass
(
HAS_VALUE_CLASS
);
}
// Only filter asynchronously only if option remote is set
if
(
this
.
options
.
remote
)
{
clearTimeout
(
timeout
);
return
(
timeout
=
setTimeout
(()
=>
{
$inputContainer
.
parent
().
addClass
(
'
is-loading
'
);
return
this
.
options
.
query
(
this
.
input
.
val
(),
data
=>
{
$inputContainer
.
parent
().
removeClass
(
'
is-loading
'
);
return
this
.
options
.
callback
(
data
);
});
}
else
{
// If data is grouped therefore an [object Object]. e.g.
// {
// groupName1: [
// { prop: 'foo' },
// { prop: 'baz' }
// ],
// groupName2: [
// { prop: 'abc' },
// { prop: 'def' }
// ]
// }
if
(
isObject
(
data
))
{
results
=
{};
for
(
key
in
data
)
{
group
=
data
[
key
];
tmp
=
fuzzaldrinPlus
.
filter
(
group
,
search_text
,
{
key
:
this
.
options
.
keys
,
});
if
(
tmp
.
length
)
{
results
[
key
]
=
tmp
.
map
(
item
=>
item
);
}
},
250
));
}
else
{
return
this
.
filter
(
this
.
input
.
val
());
}
});
}
GitLabDropdownFilter
.
prototype
.
shouldBlur
=
function
(
keyCode
)
{
return
BLUR_KEYCODES
.
indexOf
(
keyCode
)
!==
-
1
;
};
GitLabDropdownFilter
.
prototype
.
filter
=
function
(
search_text
)
{
var
data
,
elements
,
group
,
key
,
results
,
tmp
;
if
(
this
.
options
.
onFilter
)
{
this
.
options
.
onFilter
(
search_text
);
}
data
=
this
.
options
.
data
();
if
(
data
!=
null
&&
!
this
.
options
.
filterByText
)
{
results
=
data
;
if
(
search_text
!==
''
)
{
// When data is an array of objects therefore [object Array] e.g.
// [
// { prop: 'foo' },
// { prop: 'baz' }
// ]
if
(
_
.
isArray
(
data
))
{
results
=
fuzzaldrinPlus
.
filter
(
data
,
search_text
,
{
key
:
this
.
options
.
keys
,
});
}
else
{
// If data is grouped therefore an [object Object]. e.g.
// {
// groupName1: [
// { prop: 'foo' },
// { prop: 'baz' }
// ],
// groupName2: [
// { prop: 'abc' },
// { prop: 'def' }
// ]
// }
if
(
isObject
(
data
))
{
results
=
{};
for
(
key
in
data
)
{
group
=
data
[
key
];
tmp
=
fuzzaldrinPlus
.
filter
(
group
,
search_text
,
{
key
:
this
.
options
.
keys
,
});
if
(
tmp
.
length
)
{
results
[
key
]
=
tmp
.
map
(
item
=>
item
);
}
}
}
}
return
this
.
options
.
callback
(
results
);
}
else
{
elements
=
this
.
options
.
elements
();
if
(
search_text
)
{
elements
.
each
(
function
(
)
{
var
$el
,
matches
;
$el
=
$
(
this
)
;
matches
=
fuzzaldrinPlus
.
match
(
$el
.
text
().
trim
(),
search_text
);
if
(
!
$el
.
is
(
'
.dropdown-header
'
))
{
if
(
matches
.
length
)
{
return
$el
.
show
().
removeClass
(
'
option-hidden
'
);
}
else
{
return
$el
.
hide
().
addClass
(
'
option-hidden
'
);
}
}
return
this
.
options
.
callback
(
results
);
}
else
{
elements
=
this
.
options
.
elements
();
if
(
search_text
)
{
elements
.
each
(
function
()
{
var
$el
,
matches
;
$el
=
$
(
this
);
matches
=
fuzzaldrinPlus
.
match
(
$el
.
text
().
trim
(),
search_text
);
if
(
!
$el
.
is
(
'
.dropdown-header
'
)
)
{
if
(
matches
.
length
)
{
return
$el
.
show
().
removeClass
(
'
option-hidden
'
);
}
else
{
return
$el
.
hide
().
addClass
(
'
option-hidden
'
);
}
});
}
else
{
elements
.
show
().
removeClass
(
'
option-hidden
'
);
}
elements
.
parent
()
.
find
(
'
.dropdown-menu-empty-item
'
)
.
toggleClass
(
'
hidden
'
,
elements
.
is
(
'
:visible
'
));
}
});
}
else
{
elements
.
show
().
removeClass
(
'
option-hidden
'
);
}
};
return
GitLabDropdownFilter
;
})();
GitLabDropdownRemote
=
(
function
()
{
function
GitLabDropdownRemote
(
dataEndpoint
,
options
)
{
this
.
dataEndpoint
=
dataEndpoint
;
this
.
options
=
options
;
elements
.
parent
()
.
find
(
'
.dropdown-menu-empty-item
'
)
.
toggleClass
(
'
hidden
'
,
elements
.
is
(
'
:visible
'
))
;
}
};
GitLabDropdownRemote
.
prototype
.
execute
=
function
()
{
if
(
typeof
this
.
dataEndpoint
===
'
string
'
)
{
return
this
.
fetchData
();
}
else
if
(
typeof
this
.
dataEndpoint
===
'
function
'
)
{
if
(
this
.
options
.
beforeSend
)
{
this
.
options
.
beforeSend
();
}
return
this
.
dataEndpoint
(
''
,
(
function
(
_this
)
{
// Fetch the data by calling the data funcfion
return
function
(
data
)
{
if
(
_this
.
options
.
success
)
{
_this
.
options
.
success
(
data
);
}
if
(
_this
.
options
.
beforeSend
)
{
return
_this
.
options
.
beforeSend
();
}
};
})(
this
),
);
}
};
function
GitLabDropdownRemote
(
dataEndpoint
,
options
)
{
this
.
dataEndpoint
=
dataEndpoint
;
this
.
options
=
options
;
}
GitLabDropdownRemote
.
prototype
.
fetchData
=
function
()
{
GitLabDropdownRemote
.
prototype
.
execute
=
function
()
{
if
(
typeof
this
.
dataEndpoint
===
'
string
'
)
{
return
this
.
fetchData
();
}
else
if
(
typeof
this
.
dataEndpoint
===
'
function
'
)
{
if
(
this
.
options
.
beforeSend
)
{
this
.
options
.
beforeSend
();
}
// Fetch the data through ajax if the data is a string
return
axios
.
get
(
this
.
dataEndpoint
).
then
(({
data
})
=>
{
return
this
.
dataEndpoint
(
''
,
data
=>
{
// Fetch the data by calling the data function
if
(
this
.
options
.
success
)
{
return
this
.
options
.
success
(
data
);
this
.
options
.
success
(
data
);
}
if
(
this
.
options
.
beforeSend
)
{
return
this
.
options
.
beforeSend
();
}
});
};
return
GitLabDropdownRemote
;
})();
GitLabDropdown
=
(
function
()
{
var
ACTIVE_CLASS
,
FILTER_INPUT
,
NO_FILTER_INPUT
,
INDETERMINATE_CLASS
,
LOADING_CLASS
,
PAGE_TWO_CLASS
,
NON_SELECTABLE_CLASSES
,
SELECTABLE_CLASSES
,
CURSOR_SELECT_SCROLL_PADDING
,
currentIndex
;
LOADING_CLASS
=
'
is-loading
'
;
PAGE_TWO_CLASS
=
'
is-page-two
'
;
ACTIVE_CLASS
=
'
is-active
'
;
INDETERMINATE_CLASS
=
'
is-indeterminate
'
;
}
};
currentIndex
=
-
1
;
GitLabDropdownRemote
.
prototype
.
fetchData
=
function
()
{
if
(
this
.
options
.
beforeSend
)
{
this
.
options
.
beforeSend
();
}
NON_SELECTABLE_CLASSES
=
'
.divider, .separator, .dropdown-header, .dropdown-menu-empty-item
'
;
SELECTABLE_CLASSES
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
, .option-hidden)`
;
CURSOR_SELECT_SCROLL_PADDING
=
5
;
FILTER_INPUT
=
'
.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)
'
;
NO_FILTER_INPUT
=
'
.dropdown-input .dropdown-input-field.dropdown-no-filter
'
;
function
GitLabDropdown
(
el1
,
options
)
{
var
searchFields
,
selector
,
self
;
this
.
el
=
el1
;
this
.
options
=
options
;
this
.
updateLabel
=
this
.
updateLabel
.
bind
(
this
);
this
.
hidden
=
this
.
hidden
.
bind
(
this
);
this
.
opened
=
this
.
opened
.
bind
(
this
);
this
.
shouldPropagate
=
this
.
shouldPropagate
.
bind
(
this
);
self
=
this
;
selector
=
$
(
this
.
el
).
data
(
'
target
'
);
this
.
dropdown
=
selector
!=
null
?
$
(
selector
)
:
$
(
this
.
el
).
parent
();
// Set Defaults
this
.
filterInput
=
this
.
options
.
filterInput
||
this
.
getElement
(
FILTER_INPUT
);
this
.
noFilterInput
=
this
.
options
.
noFilterInput
||
this
.
getElement
(
NO_FILTER_INPUT
);
this
.
highlight
=
Boolean
(
this
.
options
.
highlight
);
this
.
icon
=
Boolean
(
this
.
options
.
icon
);
this
.
filterInputBlur
=
this
.
options
.
filterInputBlur
!=
null
?
this
.
options
.
filterInputBlur
:
true
;
// If no input is passed create a default one
self
=
this
;
// If selector was passed
if
(
_
.
isString
(
this
.
filterInput
))
{
this
.
filterInput
=
this
.
getElement
(
this
.
filterInput
);
// Fetch the data through ajax if the data is a string
return
axios
.
get
(
this
.
dataEndpoint
).
then
(({
data
})
=>
{
if
(
this
.
options
.
success
)
{
return
this
.
options
.
success
(
data
);
}
searchFields
=
this
.
options
.
search
?
this
.
options
.
search
.
fields
:
[];
if
(
this
.
options
.
data
)
{
// If we provided data
// data could be an array of objects or a group of arrays
if
(
_
.
isObject
(
this
.
options
.
data
)
&&
!
_
.
isFunction
(
this
.
options
.
data
))
{
this
.
fullData
=
this
.
options
.
data
;
currentIndex
=
-
1
;
this
.
parseData
(
this
.
options
.
data
);
this
.
focusTextInput
();
}
else
{
this
.
remote
=
new
GitLabDropdownRemote
(
this
.
options
.
data
,
{
dataType
:
this
.
options
.
dataType
,
beforeSend
:
this
.
toggleLoading
.
bind
(
this
),
success
:
(
function
(
_this
)
{
return
function
(
data
)
{
_this
.
fullData
=
data
;
_this
.
parseData
(
_this
.
fullData
);
_this
.
focusTextInput
();
// Update dropdown position since remote data may have changed dropdown size
_this
.
dropdown
.
find
(
'
.dropdown-menu-toggle
'
).
dropdown
(
'
update
'
);
if
(
_this
.
options
.
filterable
&&
_this
.
filter
&&
_this
.
filter
.
input
&&
_this
.
filter
.
input
.
val
()
&&
_this
.
filter
.
input
.
val
().
trim
()
!==
''
)
{
return
_this
.
filter
.
input
.
trigger
(
'
input
'
);
}
};
// Remote data
})(
this
),
instance
:
this
,
});
}
}
if
(
this
.
noFilterInput
.
length
)
{
this
.
plainInput
=
new
GitLabDropdownInput
(
this
.
noFilterInput
,
this
.
options
);
this
.
plainInput
.
onInput
(
this
.
addInput
.
bind
(
this
));
}
// Init filterable
if
(
this
.
options
.
filterable
)
{
this
.
filter
=
new
GitLabDropdownFilter
(
this
.
filterInput
,
{
elIsInput
:
$
(
this
.
el
).
is
(
'
input
'
),
filterInputBlur
:
this
.
filterInputBlur
,
filterByText
:
this
.
options
.
filterByText
,
onFilter
:
this
.
options
.
onFilter
,
remote
:
this
.
options
.
filterRemote
,
query
:
this
.
options
.
data
,
keys
:
searchFields
,
});
};
function
GitLabDropdown
(
el1
,
options
)
{
var
searchFields
,
selector
,
self
;
this
.
el
=
el1
;
this
.
options
=
options
;
this
.
updateLabel
=
this
.
updateLabel
.
bind
(
this
);
this
.
hidden
=
this
.
hidden
.
bind
(
this
);
this
.
opened
=
this
.
opened
.
bind
(
this
);
this
.
shouldPropagate
=
this
.
shouldPropagate
.
bind
(
this
);
self
=
this
;
selector
=
$
(
this
.
el
).
data
(
'
target
'
);
this
.
dropdown
=
selector
!=
null
?
$
(
selector
)
:
$
(
this
.
el
).
parent
();
// Set Defaults
this
.
filterInput
=
this
.
options
.
filterInput
||
this
.
getElement
(
FILTER_INPUT
);
this
.
noFilterInput
=
this
.
options
.
noFilterInput
||
this
.
getElement
(
NO_FILTER_INPUT
);
this
.
highlight
=
Boolean
(
this
.
options
.
highlight
);
this
.
icon
=
Boolean
(
this
.
options
.
icon
);
this
.
filterInputBlur
=
this
.
options
.
filterInputBlur
!=
null
?
this
.
options
.
filterInputBlur
:
true
;
// If no input is passed create a default one
self
=
this
;
// If selector was passed
if
(
_
.
isString
(
this
.
filterInput
))
{
this
.
filterInput
=
this
.
getElement
(
this
.
filterInput
);
}
searchFields
=
this
.
options
.
search
?
this
.
options
.
search
.
fields
:
[];
if
(
this
.
options
.
data
)
{
// If we provided data
// data could be an array of objects or a group of arrays
if
(
_
.
isObject
(
this
.
options
.
data
)
&&
!
_
.
isFunction
(
this
.
options
.
data
))
{
this
.
fullData
=
this
.
options
.
data
;
currentIndex
=
-
1
;
this
.
parseData
(
this
.
options
.
data
);
this
.
focusTextInput
();
}
else
{
this
.
remote
=
new
GitLabDropdownRemote
(
this
.
options
.
data
,
{
dataType
:
this
.
options
.
dataType
,
beforeSend
:
this
.
toggleLoading
.
bind
(
this
),
success
:
data
=>
{
this
.
fullData
=
data
;
this
.
parseData
(
this
.
fullData
);
this
.
focusTextInput
();
// Update dropdown position since remote data may have changed dropdown size
this
.
dropdown
.
find
(
'
.dropdown-menu-toggle
'
).
dropdown
(
'
update
'
);
if
(
this
.
options
.
filterable
&&
this
.
filter
&&
this
.
filter
.
input
&&
this
.
filter
.
input
.
val
()
&&
this
.
filter
.
input
.
val
().
trim
()
!==
''
)
{
return
this
.
filter
.
input
.
trigger
(
'
input
'
);
}
},
instance
:
this
,
elements
:
(
function
(
_this
)
{
return
function
()
{
selector
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
)`
;
if
(
_this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
return
$
(
selector
,
this
.
instance
.
dropdown
);
};
})(
this
),
data
:
(
function
(
_this
)
{
return
function
()
{
return
_this
.
fullData
;
};
})(
this
),
callback
:
(
function
(
_this
)
{
return
function
(
data
)
{
_this
.
parseData
(
data
);
if
(
_this
.
filterInput
.
val
()
!==
''
)
{
selector
=
SELECTABLE_CLASSES
;
if
(
_this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
if
(
$
(
_this
.
el
).
is
(
'
input
'
))
{
currentIndex
=
-
1
;
}
else
{
$
(
selector
,
_this
.
dropdown
)
.
first
()
.
find
(
'
a
'
)
.
addClass
(
'
is-focused
'
);
currentIndex
=
0
;
}
}
};
})(
this
),
});
}
// Event listeners
this
.
dropdown
.
on
(
'
shown.bs.dropdown
'
,
this
.
opened
);
this
.
dropdown
.
on
(
'
hidden.bs.dropdown
'
,
this
.
hidden
);
$
(
this
.
el
).
on
(
'
update.label
'
,
this
.
updateLabel
);
this
.
dropdown
.
on
(
'
click
'
,
'
.dropdown-menu, .dropdown-menu-close
'
,
this
.
shouldPropagate
);
this
.
dropdown
.
on
(
'
keyup
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
// Escape key
if
(
e
.
which
===
27
)
{
return
$
(
'
.dropdown-menu-close
'
,
_this
.
dropdown
).
trigger
(
'
click
'
);
}
if
(
this
.
noFilterInput
.
length
)
{
this
.
plainInput
=
new
GitLabDropdownInput
(
this
.
noFilterInput
,
this
.
options
);
this
.
plainInput
.
onInput
(
this
.
addInput
.
bind
(
this
));
}
// Init filterable
if
(
this
.
options
.
filterable
)
{
this
.
filter
=
new
GitLabDropdownFilter
(
this
.
filterInput
,
{
elIsInput
:
$
(
this
.
el
).
is
(
'
input
'
),
filterInputBlur
:
this
.
filterInputBlur
,
filterByText
:
this
.
options
.
filterByText
,
onFilter
:
this
.
options
.
onFilter
,
remote
:
this
.
options
.
filterRemote
,
query
:
this
.
options
.
data
,
keys
:
searchFields
,
instance
:
this
,
elements
:
()
=>
{
selector
=
`.dropdown-content li:not(
${
NON_SELECTABLE_CLASSES
}
)`
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
return
$
(
selector
,
this
.
dropdown
);
},
data
:
()
=>
this
.
fullData
,
callback
:
data
=>
{
this
.
parseData
(
data
);
if
(
this
.
filterInput
.
val
()
!==
''
)
{
selector
=
SELECTABLE_CLASSES
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
};
})(
this
),
);
this
.
dropdown
.
on
(
'
blur
'
,
'
a
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
var
$dropdownMenu
,
$relatedTarget
;
if
(
e
.
relatedTarget
!=
null
)
{
$relatedTarget
=
$
(
e
.
relatedTarget
);
$dropdownMenu
=
$relatedTarget
.
closest
(
'
.dropdown-menu
'
);
if
(
$dropdownMenu
.
length
===
0
)
{
return
_this
.
dropdown
.
removeClass
(
'
show
'
);
}
if
(
$
(
this
.
el
).
is
(
'
input
'
))
{
currentIndex
=
-
1
;
}
else
{
$
(
selector
,
this
.
dropdown
)
.
first
()
.
find
(
'
a
'
)
.
addClass
(
'
is-focused
'
);
currentIndex
=
0
;
}
};
})(
this
),
);
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
this
.
dropdown
.
find
(
'
.dropdown-toggle-page, .dropdown-menu-back
'
).
on
(
'
click
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
e
.
preventDefault
();
e
.
stopPropagation
();
return
_this
.
togglePage
();
};
})(
this
),
);
}
},
});
}
// Event listeners
this
.
dropdown
.
on
(
'
shown.bs.dropdown
'
,
this
.
opened
);
this
.
dropdown
.
on
(
'
hidden.bs.dropdown
'
,
this
.
hidden
);
$
(
this
.
el
).
on
(
'
update.label
'
,
this
.
updateLabel
);
this
.
dropdown
.
on
(
'
click
'
,
'
.dropdown-menu, .dropdown-menu-close
'
,
this
.
shouldPropagate
);
this
.
dropdown
.
on
(
'
keyup
'
,
e
=>
{
// Escape key
if
(
e
.
which
===
27
)
{
return
$
(
'
.dropdown-menu-close
'
,
this
.
dropdown
).
trigger
(
'
click
'
);
}
if
(
this
.
options
.
selectable
)
{
selector
=
'
.dropdown-content a
'
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one .dropdown-content a
'
;
});
this
.
dropdown
.
on
(
'
blur
'
,
'
a
'
,
e
=>
{
var
$dropdownMenu
,
$relatedTarget
;
if
(
e
.
relatedTarget
!=
null
)
{
$relatedTarget
=
$
(
e
.
relatedTarget
);
$dropdownMenu
=
$relatedTarget
.
closest
(
'
.dropdown-menu
'
);
if
(
$dropdownMenu
.
length
===
0
)
{
return
this
.
dropdown
.
removeClass
(
'
show
'
);
}
}
});
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
this
.
dropdown
.
find
(
'
.dropdown-toggle-page, .dropdown-menu-back
'
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
e
.
stopPropagation
();
return
this
.
togglePage
();
});
}
if
(
this
.
options
.
selectable
)
{
selector
=
'
.dropdown-content a
'
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
'
.dropdown-page-one .dropdown-content a
'
;
}
this
.
dropdown
.
on
(
'
click
'
,
selector
,
e
=>
{
var
$el
,
selected
,
selectedObj
,
isMarking
;
$el
=
$
(
e
.
currentTarget
);
selected
=
self
.
rowClicked
(
$el
);
selectedObj
=
selected
?
selected
[
0
]
:
null
;
isMarking
=
selected
?
selected
[
1
]
:
null
;
if
(
this
.
options
.
clicked
)
{
this
.
options
.
clicked
.
call
(
this
,
{
selectedObj
,
$el
,
e
,
isMarking
,
});
}
this
.
dropdown
.
on
(
'
click
'
,
selector
,
e
=>
{
var
$el
,
selected
,
selectedObj
,
isMarking
;
$el
=
$
(
e
.
currentTarget
);
selected
=
self
.
rowClicked
(
$el
);
selectedObj
=
selected
?
selected
[
0
]
:
null
;
isMarking
=
selected
?
selected
[
1
]
:
null
;
if
(
this
.
options
.
clicked
)
{
this
.
options
.
clicked
.
call
(
this
,
{
selectedObj
,
$el
,
e
,
isMarking
,
});
}
// Update label right after all modifications in dropdown has been done
if
(
this
.
options
.
toggleLabel
)
{
this
.
updateLabel
(
selectedObj
,
$el
,
this
);
}
// Update label right after all modifications in dropdown has been done
if
(
this
.
options
.
toggleLabel
)
{
this
.
updateLabel
(
selectedObj
,
$el
,
this
);
}
$el
.
trigger
(
'
blur
'
);
});
}
$el
.
trigger
(
'
blur
'
);
});
}
}
// Finds an element inside wrapper element
GitLabDropdown
.
prototype
.
getElement
=
function
(
selector
)
{
return
this
.
dropdown
.
find
(
selector
);
};
// Finds an element inside wrapper element
GitLabDropdown
.
prototype
.
getElement
=
function
(
selector
)
{
return
this
.
dropdown
.
find
(
selector
);
};
GitLabDropdown
.
prototype
.
toggleLoading
=
function
()
{
return
$
(
'
.dropdown-menu
'
,
this
.
dropdown
).
toggleClass
(
LOADING_CLASS
);
};
GitLabDropdown
.
prototype
.
toggleLoading
=
function
()
{
return
$
(
'
.dropdown-menu
'
,
this
.
dropdown
).
toggleClass
(
LOADING_CLASS
);
};
GitLabDropdown
.
prototype
.
togglePage
=
function
()
{
var
menu
;
menu
=
$
(
'
.dropdown-menu
'
,
this
.
dropdown
);
if
(
menu
.
hasClass
(
PAGE_TWO_CLASS
))
{
if
(
this
.
remote
)
{
this
.
remote
.
execute
();
}
GitLabDropdown
.
prototype
.
togglePage
=
function
()
{
var
menu
;
menu
=
$
(
'
.dropdown-menu
'
,
this
.
dropdown
);
if
(
menu
.
hasClass
(
PAGE_TWO_CLASS
))
{
if
(
this
.
remote
)
{
this
.
remote
.
execute
();
}
menu
.
toggleClass
(
PAGE_TWO_CLASS
);
// Focus first visible input on active page
return
this
.
dropdown
.
find
(
'
[class^="dropdown-page-"]:visible :text:visible:first
'
).
focus
();
};
GitLabDropdown
.
prototype
.
parseData
=
function
(
data
)
{
var
full_html
,
groupData
,
html
,
name
;
this
.
renderedData
=
data
;
if
(
this
.
options
.
filterable
&&
data
.
length
===
0
)
{
// render no matching results
html
=
[
this
.
noResults
()];
}
else
{
// Handle array groups
if
(
isObject
(
data
))
{
html
=
[];
for
(
name
in
data
)
{
groupData
=
data
[
name
];
html
.
push
(
this
.
renderItem
(
{
content
:
name
,
type
:
'
header
'
,
},
name
,
),
);
this
.
renderData
(
groupData
,
name
).
map
(
item
=>
html
.
push
(
item
));
}
}
else
{
// Render each row
html
=
this
.
renderData
(
data
);
}
menu
.
toggleClass
(
PAGE_TWO_CLASS
);
// Focus first visible input on active page
return
this
.
dropdown
.
find
(
'
[class^="dropdown-page-"]:visible :text:visible:first
'
).
focus
();
};
GitLabDropdown
.
prototype
.
parseData
=
function
(
data
)
{
var
full_html
,
groupData
,
html
,
name
;
this
.
renderedData
=
data
;
if
(
this
.
options
.
filterable
&&
data
.
length
===
0
)
{
// render no matching results
html
=
[
this
.
noResults
()];
}
else
{
// Handle array groups
if
(
isObject
(
data
))
{
html
=
[];
for
(
name
in
data
)
{
groupData
=
data
[
name
];
html
.
push
(
this
.
renderItem
(
{
content
:
name
,
type
:
'
header
'
,
},
name
,
),
);
this
.
renderData
(
groupData
,
name
).
map
(
item
=>
html
.
push
(
item
));
}
}
else
{
// Render each row
html
=
this
.
renderData
(
data
);
}
// Render the full menu
full_html
=
this
.
renderMenu
(
html
);
return
this
.
appendMenu
(
full_html
);
};
GitLabDropdown
.
prototype
.
renderData
=
function
(
data
,
group
)
{
return
data
.
map
((
obj
,
index
)
=>
this
.
renderItem
(
obj
,
group
||
false
,
index
));
};
GitLabDropdown
.
prototype
.
shouldPropagate
=
function
(
e
)
{
var
$target
;
if
(
this
.
options
.
multiSelect
||
this
.
options
.
shouldPropagate
===
false
)
{
$target
=
$
(
e
.
target
);
if
(
$target
&&
!
$target
.
hasClass
(
'
dropdown-menu-close
'
)
&&
!
$target
.
hasClass
(
'
dropdown-menu-close-icon
'
)
&&
!
$target
.
data
(
'
isLink
'
)
)
{
e
.
stopPropagation
();
// This prevents automatic scrolling to the top
if
(
$target
.
closest
(
'
a
'
).
length
)
{
return
false
;
}
}
}
// Render the full menu
full_html
=
this
.
renderMenu
(
html
);
return
this
.
appendMenu
(
full_html
);
};
return
true
;
GitLabDropdown
.
prototype
.
renderData
=
function
(
data
,
group
)
{
return
data
.
map
((
obj
,
index
)
=>
this
.
renderItem
(
obj
,
group
||
false
,
index
));
};
GitLabDropdown
.
prototype
.
shouldPropagate
=
function
(
e
)
{
var
$target
;
if
(
this
.
options
.
multiSelect
||
this
.
options
.
shouldPropagate
===
false
)
{
$target
=
$
(
e
.
target
);
if
(
$target
&&
!
$target
.
hasClass
(
'
dropdown-menu-close
'
)
&&
!
$target
.
hasClass
(
'
dropdown-menu-close-icon
'
)
&&
!
$target
.
data
(
'
isLink
'
)
)
{
e
.
stopPropagation
();
// This prevents automatic scrolling to the top
if
(
$target
.
closest
(
'
a
'
).
length
)
{
return
false
;
}
}
};
GitLabDropdown
.
prototype
.
filteredFullData
=
function
()
{
return
this
.
fullData
.
filter
(
r
=>
typeof
r
===
'
object
'
&&
!
Object
.
prototype
.
hasOwnProperty
.
call
(
r
,
'
beforeDivider
'
)
&&
!
Object
.
prototype
.
hasOwnProperty
.
call
(
r
,
'
header
'
),
);
};
GitLabDropdown
.
prototype
.
opened
=
function
(
e
)
{
var
contentHtml
;
this
.
resetRows
();
this
.
addArrowKeyEvent
();
return
true
;
}
};
const
dropdownToggle
=
this
.
dropdown
.
find
(
'
.dropdown-menu-toggle
'
);
const
hasFilterBulkUpdate
=
dropdownToggle
.
hasClass
(
'
js-filter-bulk-update
'
);
const
shouldRefreshOnOpen
=
dropdownToggle
.
hasClass
(
'
js-gl-dropdown-refresh-on-open
'
);
const
hasMultiSelect
=
dropdownToggle
.
hasClass
(
'
js-multiselect
'
);
GitLabDropdown
.
prototype
.
filteredFullData
=
function
()
{
return
this
.
fullData
.
filter
(
r
=>
typeof
r
===
'
object
'
&&
!
Object
.
prototype
.
hasOwnProperty
.
call
(
r
,
'
beforeDivider
'
)
&&
!
Object
.
prototype
.
hasOwnProperty
.
call
(
r
,
'
header
'
),
);
};
// Makes indeterminate items effective
if
(
this
.
fullData
&&
(
shouldRefreshOnOpen
||
hasFilterBulkUpdate
))
{
this
.
parseData
(
this
.
fullData
);
}
GitLabDropdown
.
prototype
.
opened
=
function
(
e
)
{
var
contentHtml
;
this
.
resetRows
(
);
this
.
addArrowKeyEvent
();
// Process the data to make sure rendered data
// matches the correct layout
const
inputValue
=
this
.
filterInput
.
val
();
if
(
this
.
fullData
&&
hasMultiSelect
&&
this
.
options
.
processData
&&
inputValue
.
length
===
0
)
{
this
.
options
.
processData
.
call
(
this
.
options
,
inputValue
,
this
.
filteredFullData
(),
this
.
parseData
.
bind
(
this
),
);
}
const
dropdownToggle
=
this
.
dropdown
.
find
(
'
.dropdown-menu-toggle
'
);
const
hasFilterBulkUpdate
=
dropdownToggle
.
hasClass
(
'
js-filter-bulk-update
'
);
const
shouldRefreshOnOpen
=
dropdownToggle
.
hasClass
(
'
js-gl-dropdown-refresh-on-open
'
);
const
hasMultiSelect
=
dropdownToggle
.
hasClass
(
'
js-multiselect
'
);
contentHtml
=
$
(
'
.dropdown-content
'
,
this
.
dropdown
).
html
();
if
(
this
.
remote
&&
contentHtml
===
''
)
{
this
.
remote
.
execute
();
// Makes indeterminate items effective
if
(
this
.
fullData
&&
(
shouldRefreshOnOpen
||
hasFilterBulkUpdate
))
{
this
.
parseData
(
this
.
fullData
);
}
// Process the data to make sure rendered data
// matches the correct layout
const
inputValue
=
this
.
filterInput
.
val
();
if
(
this
.
fullData
&&
hasMultiSelect
&&
this
.
options
.
processData
&&
inputValue
.
length
===
0
)
{
this
.
options
.
processData
.
call
(
this
.
options
,
inputValue
,
this
.
filteredFullData
(),
this
.
parseData
.
bind
(
this
),
);
}
contentHtml
=
$
(
'
.dropdown-content
'
,
this
.
dropdown
).
html
();
if
(
this
.
remote
&&
contentHtml
===
''
)
{
this
.
remote
.
execute
();
}
else
{
this
.
focusTextInput
();
}
if
(
this
.
options
.
showMenuAbove
)
{
this
.
positionMenuAbove
();
}
if
(
this
.
options
.
opened
)
{
if
(
this
.
options
.
preserveContext
)
{
this
.
options
.
opened
(
e
);
}
else
{
this
.
focusTextInput
(
);
this
.
options
.
opened
.
call
(
this
,
e
);
}
}
if
(
this
.
options
.
showMenuAbove
)
{
this
.
positionMenuAbove
();
}
return
this
.
dropdown
.
trigger
(
'
shown.gl.dropdown
'
);
};
if
(
this
.
options
.
opened
)
{
if
(
this
.
options
.
preserveContext
)
{
this
.
options
.
opened
(
e
);
}
else
{
this
.
options
.
opened
.
call
(
this
,
e
);
}
}
GitLabDropdown
.
prototype
.
positionMenuAbove
=
function
()
{
var
$menu
=
this
.
dropdown
.
find
(
'
.dropdown-menu
'
);
return
this
.
dropdown
.
trigger
(
'
shown.gl.dropdown
'
);
};
$menu
.
addClass
(
'
dropdown-open-top
'
);
$menu
.
css
(
'
top
'
,
'
initial
'
);
$menu
.
css
(
'
bottom
'
,
'
100%
'
);
};
GitLabDropdown
.
prototype
.
positionMenuAbove
=
function
()
{
var
$menu
=
this
.
dropdown
.
find
(
'
.dropdown-menu
'
);
GitLabDropdown
.
prototype
.
hidden
=
function
(
e
)
{
var
$input
;
this
.
resetRows
();
this
.
removeArrowKeyEvent
();
$input
=
this
.
dropdown
.
find
(
'
.dropdown-input-field
'
);
if
(
this
.
options
.
filterable
)
{
$input
.
blur
();
}
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
$
(
'
.dropdown-menu
'
,
this
.
dropdown
).
removeClass
(
PAGE_TWO_CLASS
);
}
if
(
this
.
options
.
hidden
)
{
this
.
options
.
hidden
.
call
(
this
,
e
);
}
return
this
.
dropdown
.
trigger
(
'
hidden.gl.dropdown
'
);
};
$menu
.
addClass
(
'
dropdown-open-top
'
);
$menu
.
css
(
'
top
'
,
'
initial
'
);
$menu
.
css
(
'
bottom
'
,
'
100%
'
);
};
// Render the full menu
GitLabDropdown
.
prototype
.
renderMenu
=
function
(
html
)
{
if
(
this
.
options
.
renderMenu
)
{
return
this
.
options
.
renderMenu
(
html
);
}
else
{
return
$
(
'
<ul>
'
).
append
(
html
);
}
};
GitLabDropdown
.
prototype
.
hidden
=
function
(
e
)
{
var
$input
;
this
.
resetRows
();
this
.
removeArrowKeyEvent
();
$input
=
this
.
dropdown
.
find
(
'
.dropdown-input-field
'
);
if
(
this
.
options
.
filterable
)
{
$input
.
blur
();
}
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
$
(
'
.dropdown-menu
'
,
this
.
dropdown
).
removeClass
(
PAGE_TWO_CLASS
);
}
if
(
this
.
options
.
hidden
)
{
this
.
options
.
hidden
.
call
(
this
,
e
);
}
return
this
.
dropdown
.
trigger
(
'
hidden.gl.dropdown
'
);
};
// Append the menu into the dropdown
GitLabDropdown
.
prototype
.
appendMenu
=
function
(
html
)
{
return
this
.
clearMenu
().
append
(
html
);
};
// Render the full menu
GitLabDropdown
.
prototype
.
renderMenu
=
function
(
html
)
{
if
(
this
.
options
.
renderMenu
)
{
return
this
.
options
.
renderMenu
(
html
);
GitLabDropdown
.
prototype
.
clearMenu
=
function
()
{
var
selector
;
selector
=
'
.dropdown-content
'
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
if
(
this
.
options
.
containerSelector
)
{
selector
=
this
.
options
.
containerSelector
;
}
else
{
return
$
(
'
<ul>
'
).
append
(
html
)
;
selector
=
'
.dropdown-page-one .dropdown-content
'
;
}
}
;
}
// Append the menu into the dropdown
GitLabDropdown
.
prototype
.
appendMenu
=
function
(
html
)
{
return
this
.
clearMenu
().
append
(
html
);
};
return
$
(
selector
,
this
.
dropdown
).
empty
();
};
GitLabDropdown
.
prototype
.
clearMenu
=
function
()
{
var
selector
;
selector
=
'
.dropdown-content
'
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
if
(
this
.
options
.
containerSelector
)
{
selector
=
this
.
options
.
containerSelector
;
}
else
{
selector
=
'
.dropdown-page-one .dropdown-content
'
;
}
}
GitLabDropdown
.
prototype
.
renderItem
=
function
(
data
,
group
,
index
)
{
let
parent
;
return
$
(
selector
,
this
.
dropdown
).
empty
();
};
if
(
this
.
dropdown
&&
this
.
dropdown
[
0
])
{
parent
=
this
.
dropdown
[
0
].
parentNode
;
}
GitLabDropdown
.
prototype
.
renderItem
=
function
(
data
,
group
,
index
)
{
let
parent
;
return
renderItem
({
instance
:
this
,
options
:
Object
.
assign
({},
this
.
options
,
{
icon
:
this
.
icon
,
highlight
:
this
.
highlight
,
highlightText
:
text
=>
this
.
highlightTextMatches
(
text
,
this
.
filterInput
.
val
()),
highlightTemplate
:
this
.
highlightTemplate
.
bind
(
this
),
parent
,
}),
data
,
group
,
index
,
});
};
if
(
this
.
dropdown
&&
this
.
dropdown
[
0
]
)
{
parent
=
this
.
dropdown
[
0
].
parentNode
;
}
GitLabDropdown
.
prototype
.
highlightTemplate
=
function
(
text
,
template
)
{
return
`"<b>
${
_
.
escape
(
text
)}
</b>"
${
template
}
`
;
};
return
renderItem
({
instance
:
this
,
options
:
Object
.
assign
({},
this
.
options
,
{
icon
:
this
.
icon
,
highlight
:
this
.
highlight
,
highlightText
:
text
=>
this
.
highlightTextMatches
(
text
,
this
.
filterInput
.
val
()),
highlightTemplate
:
this
.
highlightTemplate
.
bind
(
this
),
parent
,
}),
data
,
group
,
index
,
});
};
GitLabDropdown
.
prototype
.
highlightTemplate
=
function
(
text
,
template
)
{
return
`"<b>
${
_
.
escape
(
text
)}
</b>"
${
template
}
`
;
};
GitLabDropdown
.
prototype
.
highlightTextMatches
=
function
(
text
,
term
)
{
const
occurrences
=
fuzzaldrinPlus
.
match
(
text
,
term
);
const
{
indexOf
}
=
[];
return
text
.
split
(
''
)
.
map
((
character
,
i
)
=>
{
if
(
indexOf
.
call
(
occurrences
,
i
)
!==
-
1
)
{
return
`<b>
${
character
}
</b>`
;
}
else
{
return
character
;
}
})
.
join
(
''
);
};
GitLabDropdown
.
prototype
.
noResults
=
function
()
{
return
'
<li class="dropdown-menu-empty-item"><a>No matching results</a></li>
'
;
};
GitLabDropdown
.
prototype
.
rowClicked
=
function
(
el
)
{
var
field
,
groupName
,
isInput
,
selectedIndex
,
selectedObject
,
value
,
isMarking
;
const
{
fieldName
}
=
this
.
options
;
isInput
=
$
(
this
.
el
).
is
(
'
input
'
);
if
(
this
.
renderedData
)
{
groupName
=
el
.
data
(
'
group
'
);
if
(
groupName
)
{
selectedIndex
=
el
.
data
(
'
index
'
);
selectedObject
=
this
.
renderedData
[
groupName
][
selectedIndex
];
}
else
{
selectedIndex
=
el
.
closest
(
'
li
'
).
index
();
this
.
selectedIndex
=
selectedIndex
;
selectedObject
=
this
.
renderedData
[
selectedIndex
];
}
}
GitLabDropdown
.
prototype
.
highlightTextMatches
=
function
(
text
,
term
)
{
const
occurrences
=
fuzzaldrinPlus
.
match
(
text
,
term
);
const
{
indexOf
}
=
[];
if
(
this
.
options
.
vue
)
{
if
(
el
.
hasClass
(
ACTIVE_CLASS
))
{
el
.
removeClass
(
ACTIVE_CLASS
);
return
text
.
split
(
''
)
.
map
((
character
,
i
)
=>
{
if
(
indexOf
.
call
(
occurrences
,
i
)
!==
-
1
)
{
return
`<b>
${
character
}
</b>`
;
}
else
{
el
.
addClass
(
ACTIVE_CLASS
)
;
return
character
;
}
})
.
join
(
''
);
};
return
[
selectedObject
];
}
GitLabDropdown
.
prototype
.
noResults
=
function
()
{
return
'
<li class="dropdown-menu-empty-item"><a>No matching results</a></li>
'
;
};
field
=
[];
value
=
this
.
options
.
id
?
this
.
options
.
id
(
selectedObject
,
el
)
:
selectedObject
.
id
;
if
(
isInput
)
{
field
=
$
(
this
.
el
);
}
else
if
(
value
!=
null
)
{
field
=
this
.
dropdown
.
parent
()
.
find
(
`input[name='
${
fieldName
}
'][value='
${
value
.
toString
().
replace
(
/'/g
,
"
\\
'
"
)}
']`
);
}
GitLabDropdown
.
prototype
.
rowClicked
=
function
(
el
)
{
var
field
,
groupName
,
isInput
,
selectedIndex
,
selectedObject
,
value
,
isMarking
;
if
(
this
.
options
.
isSelectable
&&
!
this
.
options
.
isSelectable
(
selectedObject
,
el
))
{
return
[
selectedObject
];
const
{
fieldName
}
=
this
.
options
;
isInput
=
$
(
this
.
el
).
is
(
'
input
'
);
if
(
this
.
renderedData
)
{
groupName
=
el
.
data
(
'
group
'
);
if
(
groupName
)
{
selectedIndex
=
el
.
data
(
'
index
'
);
selectedObject
=
this
.
renderedData
[
groupName
][
selectedIndex
];
}
else
{
selectedIndex
=
el
.
closest
(
'
li
'
).
index
();
this
.
selectedIndex
=
selectedIndex
;
selectedObject
=
this
.
renderedData
[
selectedIndex
];
}
}
if
(
el
.
hasClass
(
ACTIVE_CLASS
)
&&
value
!==
0
)
{
isMarking
=
false
;
if
(
this
.
options
.
vue
)
{
if
(
el
.
hasClass
(
ACTIVE_CLASS
))
{
el
.
removeClass
(
ACTIVE_CLASS
);
if
(
field
&&
field
.
length
)
{
this
.
clearField
(
field
,
isInput
);
}
}
else
if
(
el
.
hasClass
(
INDETERMINATE_CLASS
))
{
isMarking
=
true
;
el
.
addClass
(
ACTIVE_CLASS
);
el
.
removeClass
(
INDETERMINATE_CLASS
);
if
(
field
&&
field
.
length
&&
value
==
null
)
{
this
.
clearField
(
field
,
isInput
);
}
if
((
!
field
||
!
field
.
length
)
&&
fieldName
)
{
this
.
addInput
(
fieldName
,
value
,
selectedObject
);
}
}
else
{
isMarking
=
true
;
if
(
!
this
.
options
.
multiSelect
||
el
.
hasClass
(
'
dropdown-clear-active
'
))
{
this
.
dropdown
.
find
(
`.
${
ACTIVE_CLASS
}
`
).
removeClass
(
ACTIVE_CLASS
);
if
(
!
isInput
)
{
this
.
dropdown
.
parent
()
.
find
(
`input[name='
${
fieldName
}
']`
)
.
remove
();
}
}
if
(
field
&&
field
.
length
&&
value
==
null
)
{
this
.
clearField
(
field
,
isInput
);
}
// Toggle active class for the tick mark
el
.
addClass
(
ACTIVE_CLASS
);
if
(
value
!=
null
)
{
if
((
!
field
||
!
field
.
length
)
&&
fieldName
)
{
this
.
addInput
(
fieldName
,
value
,
selectedObject
);
}
else
if
(
field
&&
field
.
length
)
{
field
.
val
(
value
).
trigger
(
'
change
'
);
}
}
}
return
[
selectedObject
,
isMarking
];
};
return
[
selectedObject
];
}
field
=
[];
value
=
this
.
options
.
id
?
this
.
options
.
id
(
selectedObject
,
el
)
:
selectedObject
.
id
;
if
(
isInput
)
{
field
=
$
(
this
.
el
);
}
else
if
(
value
!=
null
)
{
field
=
this
.
dropdown
.
parent
()
.
find
(
`input[name='
${
fieldName
}
'][value='
${
value
.
toString
().
replace
(
/'/g
,
"
\\
'
"
)}
']`
);
}
GitLabDropdown
.
prototype
.
focusTextInput
=
function
(
)
{
if
(
this
.
options
.
filterable
)
{
const
initialScrollTop
=
$
(
window
).
scrollTop
();
if
(
this
.
options
.
isSelectable
&&
!
this
.
options
.
isSelectable
(
selectedObject
,
el
)
)
{
return
[
selectedObject
];
}
if
(
this
.
dropdown
.
is
(
'
.show
'
)
&&
!
this
.
filterInput
.
is
(
'
:focus
'
))
{
this
.
filterInput
.
focus
();
if
(
el
.
hasClass
(
ACTIVE_CLASS
)
&&
value
!==
0
)
{
isMarking
=
false
;
el
.
removeClass
(
ACTIVE_CLASS
);
if
(
field
&&
field
.
length
)
{
this
.
clearField
(
field
,
isInput
);
}
}
else
if
(
el
.
hasClass
(
INDETERMINATE_CLASS
))
{
isMarking
=
true
;
el
.
addClass
(
ACTIVE_CLASS
);
el
.
removeClass
(
INDETERMINATE_CLASS
);
if
(
field
&&
field
.
length
&&
value
==
null
)
{
this
.
clearField
(
field
,
isInput
);
}
if
((
!
field
||
!
field
.
length
)
&&
fieldName
)
{
this
.
addInput
(
fieldName
,
value
,
selectedObject
);
}
}
else
{
isMarking
=
true
;
if
(
!
this
.
options
.
multiSelect
||
el
.
hasClass
(
'
dropdown-clear-active
'
))
{
this
.
dropdown
.
find
(
`.
${
ACTIVE_CLASS
}
`
).
removeClass
(
ACTIVE_CLASS
);
if
(
!
isInput
)
{
this
.
dropdown
.
parent
()
.
find
(
`input[name='
${
fieldName
}
']`
)
.
remove
();
}
if
(
$
(
window
).
scrollTop
()
<
initialScrollTop
)
{
$
(
window
).
scrollTop
(
initialScrollTop
);
}
if
(
field
&&
field
.
length
&&
value
==
null
)
{
this
.
clearField
(
field
,
isInput
);
}
// Toggle active class for the tick mark
el
.
addClass
(
ACTIVE_CLASS
);
if
(
value
!=
null
)
{
if
((
!
field
||
!
field
.
length
)
&&
fieldName
)
{
this
.
addInput
(
fieldName
,
value
,
selectedObject
);
}
else
if
(
field
&&
field
.
length
)
{
field
.
val
(
value
).
trigger
(
'
change
'
);
}
}
}
;
}
GitLabDropdown
.
prototype
.
addInput
=
function
(
fieldName
,
value
,
selectedObject
,
single
)
{
var
$input
;
// Create hidden input for form
if
(
single
)
{
$
(
`input[name="
${
fieldName
}
"]`
).
remove
();
}
return
[
selectedObject
,
isMarking
];
};
$input
=
$
(
'
<input>
'
)
.
attr
(
'
type
'
,
'
hidden
'
)
.
attr
(
'
name
'
,
fieldName
)
.
val
(
value
);
if
(
this
.
options
.
inputId
!=
null
)
{
$input
.
attr
(
'
id
'
,
this
.
options
.
inputId
);
}
GitLabDropdown
.
prototype
.
focusTextInput
=
function
()
{
if
(
this
.
options
.
filterable
)
{
const
initialScrollTop
=
$
(
window
).
scrollTop
();
if
(
this
.
options
.
multiSelect
)
{
Object
.
keys
(
selectedObject
).
forEach
(
attribute
=>
{
$input
.
attr
(
`data-
${
attribute
}
`
,
selectedObject
[
attribute
]);
});
if
(
this
.
dropdown
.
is
(
'
.show
'
)
&&
!
this
.
filterInput
.
is
(
'
:focus
'
))
{
this
.
filterInput
.
focus
();
}
if
(
this
.
options
.
inputMeta
)
{
$
input
.
attr
(
'
data-meta
'
,
selectedObject
[
this
.
options
.
inputMeta
]
);
if
(
$
(
window
).
scrollTop
()
<
initialScrollTop
)
{
$
(
window
).
scrollTop
(
initialScrollTop
);
}
}
};
GitLabDropdown
.
prototype
.
addInput
=
function
(
fieldName
,
value
,
selectedObject
,
single
)
{
var
$input
;
// Create hidden input for form
if
(
single
)
{
$
(
`input[name="
${
fieldName
}
"]`
).
remove
();
}
$input
=
$
(
'
<input>
'
)
.
attr
(
'
type
'
,
'
hidden
'
)
.
attr
(
'
name
'
,
fieldName
)
.
val
(
value
);
if
(
this
.
options
.
inputId
!=
null
)
{
$input
.
attr
(
'
id
'
,
this
.
options
.
inputId
);
}
this
.
dropdown
.
before
(
$input
).
trigger
(
'
change
'
);
};
if
(
this
.
options
.
multiSelect
)
{
Object
.
keys
(
selectedObject
).
forEach
(
attribute
=>
{
$input
.
attr
(
`data-
${
attribute
}
`
,
selectedObject
[
attribute
]);
});
}
if
(
this
.
options
.
inputMeta
)
{
$input
.
attr
(
'
data-meta
'
,
selectedObject
[
this
.
options
.
inputMeta
]);
}
GitLabDropdown
.
prototype
.
selectRowAtIndex
=
function
(
index
)
{
var
$el
,
selector
;
// If we pass an option index
if
(
typeof
index
!==
'
undefined
'
)
{
selector
=
`
${
SELECTABLE_CLASSES
}
:eq(
${
index
}
) a`
;
this
.
dropdown
.
before
(
$input
).
trigger
(
'
change
'
);
};
GitLabDropdown
.
prototype
.
selectRowAtIndex
=
function
(
index
)
{
var
$el
,
selector
;
// If we pass an option index
if
(
typeof
index
!==
'
undefined
'
)
{
selector
=
`
${
SELECTABLE_CLASSES
}
:eq(
${
index
}
) a`
;
}
else
{
selector
=
'
.dropdown-content .is-focused
'
;
}
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
// simulate a click on the first link
$el
=
$
(
selector
,
this
.
dropdown
);
if
(
$el
.
length
)
{
var
href
=
$el
.
attr
(
'
href
'
);
if
(
href
&&
href
!==
'
#
'
)
{
visitUrl
(
href
);
}
else
{
selector
=
'
.dropdown-content .is-focused
'
;
$el
.
trigger
(
'
click
'
)
;
}
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
// simulate a click on the first link
$el
=
$
(
selector
,
this
.
dropdown
);
if
(
$el
.
length
)
{
var
href
=
$el
.
attr
(
'
href
'
);
if
(
href
&&
href
!==
'
#
'
)
{
visitUrl
(
href
);
}
else
{
$el
.
trigger
(
'
click
'
);
}
}
};
}
};
GitLabDropdown
.
prototype
.
addArrowKeyEvent
=
function
()
{
var
ARROW_KEY_CODES
,
selector
;
ARROW_KEY_CODES
=
[
38
,
40
];
selector
=
SELECTABLE_CLASSES
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
GitLabDropdown
.
prototype
.
addArrowKeyEvent
=
function
()
{
var
ARROW_KEY_CODES
,
selector
;
ARROW_KEY_CODES
=
[
38
,
40
];
selector
=
SELECTABLE_CLASSES
;
if
(
this
.
dropdown
.
find
(
'
.dropdown-toggle-page
'
).
length
)
{
selector
=
`.dropdown-page-one
${
selector
}
`
;
}
return
$
(
'
body
'
).
on
(
'
keydown
'
,
e
=>
{
var
$listItems
,
PREV_INDEX
,
currentKeyCode
;
currentKeyCode
=
e
.
which
;
if
(
ARROW_KEY_CODES
.
indexOf
(
currentKeyCode
)
!==
-
1
)
{
e
.
preventDefault
();
e
.
stopImmediatePropagation
();
PREV_INDEX
=
currentIndex
;
$listItems
=
$
(
selector
,
this
.
dropdown
);
// if @options.filterable
// $input.blur()
if
(
currentKeyCode
===
40
)
{
// Move down
if
(
currentIndex
<
$listItems
.
length
-
1
)
{
currentIndex
+=
1
;
}
}
else
if
(
currentKeyCode
===
38
)
{
// Move up
if
(
currentIndex
>
0
)
{
currentIndex
-=
1
;
}
}
if
(
currentIndex
!==
PREV_INDEX
)
{
this
.
highlightRowAtIndex
(
$listItems
,
currentIndex
);
}
return
false
;
}
return
$
(
'
body
'
).
on
(
'
keydown
'
,
(
function
(
_this
)
{
return
function
(
e
)
{
var
$listItems
,
PREV_INDEX
,
currentKeyCode
;
currentKeyCode
=
e
.
which
;
if
(
ARROW_KEY_CODES
.
indexOf
(
currentKeyCode
)
!==
-
1
)
{
e
.
preventDefault
();
e
.
stopImmediatePropagation
();
PREV_INDEX
=
currentIndex
;
$listItems
=
$
(
selector
,
_this
.
dropdown
);
// if @options.filterable
// $input.blur()
if
(
currentKeyCode
===
40
)
{
// Move down
if
(
currentIndex
<
$listItems
.
length
-
1
)
{
currentIndex
+=
1
;
}
}
else
if
(
currentKeyCode
===
38
)
{
// Move up
if
(
currentIndex
>
0
)
{
currentIndex
-=
1
;
}
}
if
(
currentIndex
!==
PREV_INDEX
)
{
_this
.
highlightRowAtIndex
(
$listItems
,
currentIndex
);
}
return
false
;
}
if
(
currentKeyCode
===
13
&&
currentIndex
!==
-
1
)
{
e
.
preventDefault
();
_this
.
selectRowAtIndex
();
}
};
})(
this
),
);
};
GitLabDropdown
.
prototype
.
removeArrowKeyEvent
=
function
()
{
return
$
(
'
body
'
).
off
(
'
keydown
'
);
};
GitLabDropdown
.
prototype
.
resetRows
=
function
resetRows
()
{
currentIndex
=
-
1
;
$
(
'
.is-focused
'
,
this
.
dropdown
).
removeClass
(
'
is-focused
'
);
};
GitLabDropdown
.
prototype
.
highlightRowAtIndex
=
function
(
$listItems
,
index
)
{
var
$dropdownContent
,
$listItem
,
dropdownContentBottom
,
dropdownContentHeight
,
dropdownContentTop
,
dropdownScrollTop
,
listItemBottom
,
listItemHeight
,
listItemTop
;
if
(
!
$listItems
)
{
$listItems
=
$
(
SELECTABLE_CLASSES
,
this
.
dropdown
);
if
(
currentKeyCode
===
13
&&
currentIndex
!==
-
1
)
{
e
.
preventDefault
();
this
.
selectRowAtIndex
();
}
});
};
// Remove the class for the previously focused row
$
(
'
.is-focused
'
,
this
.
dropdown
).
removeClass
(
'
is-focused
'
);
// Update the class for the row at the specific index
$listItem
=
$listItems
.
eq
(
index
);
$listItem
.
find
(
'
a:first-child
'
).
addClass
(
'
is-focused
'
);
// Dropdown content scroll area
$dropdownContent
=
$listItem
.
closest
(
'
.dropdown-content
'
);
dropdownScrollTop
=
$dropdownContent
.
scrollTop
();
dropdownContentHeight
=
$dropdownContent
.
outerHeight
();
dropdownContentTop
=
$dropdownContent
.
prop
(
'
offsetTop
'
);
dropdownContentBottom
=
dropdownContentTop
+
dropdownContentHeight
;
// Get the offset bottom of the list item
listItemHeight
=
$listItem
.
outerHeight
();
listItemTop
=
$listItem
.
prop
(
'
offsetTop
'
);
listItemBottom
=
listItemTop
+
listItemHeight
;
if
(
!
index
)
{
// Scroll the dropdown content to the top
$dropdownContent
.
scrollTop
(
0
);
}
else
if
(
index
===
$listItems
.
length
-
1
)
{
// Scroll the dropdown content to the bottom
$dropdownContent
.
scrollTop
(
$dropdownContent
.
prop
(
'
scrollHeight
'
));
}
else
if
(
listItemBottom
>
dropdownContentBottom
+
dropdownScrollTop
)
{
// Scroll the dropdown content down
$dropdownContent
.
scrollTop
(
listItemBottom
-
dropdownContentBottom
+
CURSOR_SELECT_SCROLL_PADDING
,
);
}
else
if
(
listItemTop
<
dropdownContentTop
+
dropdownScrollTop
)
{
// Scroll the dropdown content up
return
$dropdownContent
.
scrollTop
(
listItemTop
-
dropdownContentTop
-
CURSOR_SELECT_SCROLL_PADDING
,
);
}
};
GitLabDropdown
.
prototype
.
removeArrowKeyEvent
=
function
()
{
return
$
(
'
body
'
).
off
(
'
keydown
'
);
};
GitLabDropdown
.
prototype
.
updateLabel
=
function
(
selected
,
el
,
instance
)
{
if
(
selected
==
null
)
{
selected
=
null
;
}
if
(
el
==
null
)
{
el
=
null
;
}
if
(
instance
==
null
)
{
instance
=
null
;
}
GitLabDropdown
.
prototype
.
resetRows
=
function
resetRows
()
{
currentIndex
=
-
1
;
$
(
'
.is-focused
'
,
this
.
dropdown
).
removeClass
(
'
is-focused
'
);
};
let
toggleText
=
this
.
options
.
toggleLabel
(
selected
,
el
,
instance
);
if
(
this
.
options
.
updateLabel
)
{
// Option to override the dropdown label text
toggleText
=
this
.
options
.
updateLabel
;
}
GitLabDropdown
.
prototype
.
highlightRowAtIndex
=
function
(
$listItems
,
index
)
{
var
$dropdownContent
,
$listItem
,
dropdownContentBottom
,
dropdownContentHeight
,
dropdownContentTop
,
dropdownScrollTop
,
listItemBottom
,
listItemHeight
,
listItemTop
;
if
(
!
$listItems
)
{
$listItems
=
$
(
SELECTABLE_CLASSES
,
this
.
dropdown
);
}
// Remove the class for the previously focused row
$
(
'
.is-focused
'
,
this
.
dropdown
).
removeClass
(
'
is-focused
'
);
// Update the class for the row at the specific index
$listItem
=
$listItems
.
eq
(
index
);
$listItem
.
find
(
'
a:first-child
'
).
addClass
(
'
is-focused
'
);
// Dropdown content scroll area
$dropdownContent
=
$listItem
.
closest
(
'
.dropdown-content
'
);
dropdownScrollTop
=
$dropdownContent
.
scrollTop
();
dropdownContentHeight
=
$dropdownContent
.
outerHeight
();
dropdownContentTop
=
$dropdownContent
.
prop
(
'
offsetTop
'
);
dropdownContentBottom
=
dropdownContentTop
+
dropdownContentHeight
;
// Get the offset bottom of the list item
listItemHeight
=
$listItem
.
outerHeight
();
listItemTop
=
$listItem
.
prop
(
'
offsetTop
'
);
listItemBottom
=
listItemTop
+
listItemHeight
;
if
(
!
index
)
{
// Scroll the dropdown content to the top
$dropdownContent
.
scrollTop
(
0
);
}
else
if
(
index
===
$listItems
.
length
-
1
)
{
// Scroll the dropdown content to the bottom
$dropdownContent
.
scrollTop
(
$dropdownContent
.
prop
(
'
scrollHeight
'
));
}
else
if
(
listItemBottom
>
dropdownContentBottom
+
dropdownScrollTop
)
{
// Scroll the dropdown content down
$dropdownContent
.
scrollTop
(
listItemBottom
-
dropdownContentBottom
+
CURSOR_SELECT_SCROLL_PADDING
,
);
}
else
if
(
listItemTop
<
dropdownContentTop
+
dropdownScrollTop
)
{
// Scroll the dropdown content up
return
$dropdownContent
.
scrollTop
(
listItemTop
-
dropdownContentTop
-
CURSOR_SELECT_SCROLL_PADDING
,
);
}
};
GitLabDropdown
.
prototype
.
updateLabel
=
function
(
selected
,
el
,
instance
)
{
if
(
selected
==
null
)
{
selected
=
null
;
}
if
(
el
==
null
)
{
el
=
null
;
}
if
(
instance
==
null
)
{
instance
=
null
;
}
return
$
(
this
.
el
)
.
find
(
'
.dropdown-toggle-text
'
)
.
text
(
toggleText
);
};
let
toggleText
=
this
.
options
.
toggleLabel
(
selected
,
el
,
instance
);
if
(
this
.
options
.
updateLabel
)
{
// Option to override the dropdown label text
toggleText
=
this
.
options
.
updateLabel
;
}
GitLabDropdown
.
prototype
.
clearField
=
function
(
field
,
isInput
)
{
return
isInput
?
field
.
val
(
''
)
:
field
.
remove
();
};
return
$
(
this
.
el
)
.
find
(
'
.dropdown-toggle-text
'
)
.
text
(
toggleText
);
};
return
GitLabDropdown
;
})();
GitLabDropdown
.
prototype
.
clearField
=
function
(
field
,
isInput
)
{
return
isInput
?
field
.
val
(
''
)
:
field
.
remove
();
};
$
.
fn
.
glDropdown
=
function
(
opts
)
{
return
this
.
each
(
function
()
{
...
...
changelogs/unreleased/Remove-IIFEs-from-gl_dropdown-js.yml
0 → 100644
View file @
6e12c008
---
title
:
Remove IIFEs from gl_dropdown.js
merge_request
:
19983
author
:
nuwe1
type
:
other
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment