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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
75ac2699
Commit
75ac2699
authored
Apr 06, 2017
by
Luke "Jared" Bennett
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'update-droplab-to-webpack-version' into new-resolvable-discussion
parents
7083d381
7db45ca3
Changes
23
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1898 additions
and
101 deletions
+1898
-101
app/assets/javascripts/droplab/constants.js
app/assets/javascripts/droplab/constants.js
+11
-0
app/assets/javascripts/droplab/drop_down.js
app/assets/javascripts/droplab/drop_down.js
+137
-0
app/assets/javascripts/droplab/drop_lab.js
app/assets/javascripts/droplab/drop_lab.js
+152
-0
app/assets/javascripts/droplab/droplab_filter.js
app/assets/javascripts/droplab/droplab_filter.js
+0
-76
app/assets/javascripts/droplab/hook.js
app/assets/javascripts/droplab/hook.js
+22
-0
app/assets/javascripts/droplab/hook_button.js
app/assets/javascripts/droplab/hook_button.js
+65
-0
app/assets/javascripts/droplab/hook_input.js
app/assets/javascripts/droplab/hook_input.js
+119
-0
app/assets/javascripts/droplab/keyboard.js
app/assets/javascripts/droplab/keyboard.js
+113
-0
app/assets/javascripts/droplab/plugins/ajax.js
app/assets/javascripts/droplab/plugins/ajax.js
+71
-0
app/assets/javascripts/droplab/plugins/ajax_filter.js
app/assets/javascripts/droplab/plugins/ajax_filter.js
+133
-0
app/assets/javascripts/droplab/plugins/filter.js
app/assets/javascripts/droplab/plugins/filter.js
+95
-0
app/assets/javascripts/droplab/plugins/input_setter.js
app/assets/javascripts/droplab/plugins/input_setter.js
+51
-0
app/assets/javascripts/droplab/utils.js
app/assets/javascripts/droplab/utils.js
+38
-0
app/assets/javascripts/filtered_search/dropdown_hint.js
app/assets/javascripts/filtered_search/dropdown_hint.js
+1
-1
app/assets/javascripts/filtered_search/dropdown_non_user.js
app/assets/javascripts/filtered_search/dropdown_non_user.js
+2
-2
app/assets/javascripts/filtered_search/dropdown_user.js
app/assets/javascripts/filtered_search/dropdown_user.js
+1
-1
app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
...ripts/filtered_search/filtered_search_dropdown_manager.js
+1
-1
spec/javascripts/droplab/constants.js
spec/javascripts/droplab/constants.js
+29
-0
spec/javascripts/droplab/drop_down.js
spec/javascripts/droplab/drop_down.js
+578
-0
spec/javascripts/droplab/hook.js
spec/javascripts/droplab/hook.js
+82
-0
spec/javascripts/droplab/plugins/input_setter.js
spec/javascripts/droplab/plugins/input_setter.js
+177
-0
spec/javascripts/filtered_search/dropdown_user_spec.js
spec/javascripts/filtered_search/dropdown_user_spec.js
+4
-4
yarn.lock
yarn.lock
+16
-16
No files found.
app/assets/javascripts/droplab/constants.js
0 → 100644
View file @
75ac2699
const
DATA_TRIGGER
=
'
data-dropdown-trigger
'
;
const
DATA_DROPDOWN
=
'
data-dropdown
'
;
const
SELECTED_CLASS
=
'
droplab-item-selected
'
;
const
ACTIVE_CLASS
=
'
droplab-item-active
'
;
export
{
DATA_TRIGGER
,
DATA_DROPDOWN
,
SELECTED_CLASS
,
ACTIVE_CLASS
,
};
app/assets/javascripts/droplab/drop_down.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
utils
from
'
./utils
'
;
import
{
SELECTED_CLASS
}
from
'
./constants
'
;
var
DropDown
=
function
(
list
)
{
this
.
currentIndex
=
0
;
this
.
hidden
=
true
;
this
.
list
=
typeof
list
===
'
string
'
?
document
.
querySelector
(
list
)
:
list
;
this
.
items
=
[];
this
.
eventWrapper
=
{};
this
.
getItems
();
this
.
initTemplateString
();
this
.
addEvents
();
this
.
initialState
=
list
.
innerHTML
;
};
Object
.
assign
(
DropDown
.
prototype
,
{
getItems
:
function
()
{
this
.
items
=
[].
slice
.
call
(
this
.
list
.
querySelectorAll
(
'
li
'
));
return
this
.
items
;
},
initTemplateString
:
function
()
{
var
items
=
this
.
items
||
this
.
getItems
();
var
templateString
=
''
;
if
(
items
.
length
>
0
)
templateString
=
items
[
items
.
length
-
1
].
outerHTML
;
this
.
templateString
=
templateString
;
return
this
.
templateString
;
},
clickEvent
:
function
(
e
)
{
var
selected
=
utils
.
closest
(
e
.
target
,
'
LI
'
);
if
(
!
selected
)
return
;
this
.
addSelectedClass
(
selected
);
e
.
preventDefault
();
this
.
hide
();
var
listEvent
=
new
CustomEvent
(
'
click.dl
'
,
{
detail
:
{
list
:
this
,
selected
:
selected
,
data
:
e
.
target
.
dataset
,
},
});
this
.
list
.
dispatchEvent
(
listEvent
);
},
addSelectedClass
:
function
(
selected
)
{
this
.
removeSelectedClasses
();
selected
.
classList
.
add
(
SELECTED_CLASS
);
},
removeSelectedClasses
:
function
()
{
const
items
=
this
.
items
||
this
.
getItems
();
items
.
forEach
(
item
=>
item
.
classList
.
remove
(
SELECTED_CLASS
));
},
addEvents
:
function
()
{
this
.
eventWrapper
.
clickEvent
=
this
.
clickEvent
.
bind
(
this
)
this
.
list
.
addEventListener
(
'
click
'
,
this
.
eventWrapper
.
clickEvent
);
},
toggle
:
function
()
{
this
.
hidden
?
this
.
show
()
:
this
.
hide
();
},
setData
:
function
(
data
)
{
this
.
data
=
data
;
this
.
render
(
data
);
},
addData
:
function
(
data
)
{
this
.
data
=
(
this
.
data
||
[]).
concat
(
data
);
this
.
render
(
this
.
data
);
},
render
:
function
(
data
)
{
const
children
=
data
?
data
.
map
(
this
.
renderChildren
.
bind
(
this
))
:
[];
const
renderableList
=
this
.
list
.
querySelector
(
'
ul[data-dynamic]
'
)
||
this
.
list
;
renderableList
.
innerHTML
=
children
.
join
(
''
);
},
renderChildren
:
function
(
data
)
{
var
html
=
utils
.
t
(
this
.
templateString
,
data
);
var
template
=
document
.
createElement
(
'
div
'
);
template
.
innerHTML
=
html
;
this
.
setImagesSrc
(
template
);
template
.
firstChild
.
style
.
display
=
data
.
droplab_hidden
?
'
none
'
:
'
block
'
;
return
template
.
firstChild
.
outerHTML
;
},
setImagesSrc
:
function
(
template
)
{
const
images
=
[].
slice
.
call
(
template
.
querySelectorAll
(
'
img[data-src]
'
));
images
.
forEach
((
image
)
=>
{
image
.
src
=
image
.
getAttribute
(
'
data-src
'
);
image
.
removeAttribute
(
'
data-src
'
);
});
},
show
:
function
()
{
if
(
!
this
.
hidden
)
return
;
this
.
list
.
style
.
display
=
'
block
'
;
this
.
currentIndex
=
0
;
this
.
hidden
=
false
;
},
hide
:
function
()
{
if
(
this
.
hidden
)
return
;
this
.
list
.
style
.
display
=
'
none
'
;
this
.
currentIndex
=
0
;
this
.
hidden
=
true
;
},
toggle
:
function
()
{
this
.
hidden
?
this
.
show
()
:
this
.
hide
();
},
destroy
:
function
()
{
this
.
hide
();
this
.
list
.
removeEventListener
(
'
click
'
,
this
.
eventWrapper
.
clickEvent
);
}
});
export
default
DropDown
;
app/assets/javascripts/droplab/drop_lab.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
HookButton
from
'
./hook_button
'
;
import
HookInput
from
'
./hook_input
'
;
import
utils
from
'
./utils
'
;
import
Keyboard
from
'
./keyboard
'
;
import
{
DATA_TRIGGER
}
from
'
./constants
'
;
var
DropLab
=
function
()
{
this
.
ready
=
false
;
this
.
hooks
=
[];
this
.
queuedData
=
[];
this
.
config
=
{};
this
.
eventWrapper
=
{};
};
Object
.
assign
(
DropLab
.
prototype
,
{
loadStatic
:
function
(){
var
dropdownTriggers
=
[].
slice
.
apply
(
document
.
querySelectorAll
(
`[
${
DATA_TRIGGER
}
]`
));
this
.
addHooks
(
dropdownTriggers
);
},
addData
:
function
()
{
var
args
=
[].
slice
.
apply
(
arguments
);
this
.
applyArgs
(
args
,
'
_addData
'
);
},
setData
:
function
()
{
var
args
=
[].
slice
.
apply
(
arguments
);
this
.
applyArgs
(
args
,
'
_setData
'
);
},
destroy
:
function
()
{
this
.
hooks
.
forEach
(
hook
=>
hook
.
destroy
());
this
.
hooks
=
[];
this
.
removeEvents
();
},
applyArgs
:
function
(
args
,
methodName
)
{
if
(
this
.
ready
)
return
this
[
methodName
].
apply
(
this
,
args
);
this
.
queuedData
=
this
.
queuedData
||
[];
this
.
queuedData
.
push
(
args
);
},
_addData
:
function
(
trigger
,
data
)
{
this
.
_processData
(
trigger
,
data
,
'
addData
'
);
},
_setData
:
function
(
trigger
,
data
)
{
this
.
_processData
(
trigger
,
data
,
'
setData
'
);
},
_processData
:
function
(
trigger
,
data
,
methodName
)
{
this
.
hooks
.
forEach
((
hook
)
=>
{
if
(
Array
.
isArray
(
trigger
))
hook
.
list
[
methodName
](
trigger
);
if
(
hook
.
trigger
.
id
===
trigger
)
hook
.
list
[
methodName
](
data
);
});
},
addEvents
:
function
()
{
this
.
eventWrapper
.
documentClicked
=
this
.
documentClicked
.
bind
(
this
)
document
.
addEventListener
(
'
click
'
,
this
.
eventWrapper
.
documentClicked
);
},
documentClicked
:
function
(
e
)
{
let
thisTag
=
e
.
target
;
if
(
thisTag
.
tagName
!==
'
UL
'
)
thisTag
=
utils
.
closest
(
thisTag
,
'
UL
'
);
if
(
utils
.
isDropDownParts
(
thisTag
,
this
.
hooks
)
||
utils
.
isDropDownParts
(
e
.
target
,
this
.
hooks
))
return
;
this
.
hooks
.
forEach
(
hook
=>
hook
.
list
.
hide
());
},
removeEvents
:
function
(){
document
.
removeEventListener
(
'
click
'
,
this
.
eventWrapper
.
documentClicked
);
},
changeHookList
:
function
(
trigger
,
list
,
plugins
,
config
)
{
const
availableTrigger
=
typeof
trigger
===
'
string
'
?
document
.
getElementById
(
trigger
)
:
trigger
;
this
.
hooks
.
forEach
((
hook
,
i
)
=>
{
hook
.
list
.
list
.
dataset
.
dropdownActive
=
false
;
if
(
hook
.
trigger
!==
availableTrigger
)
return
;
hook
.
destroy
();
this
.
hooks
.
splice
(
i
,
1
);
this
.
addHook
(
availableTrigger
,
list
,
plugins
,
config
);
});
},
addHook
:
function
(
hook
,
list
,
plugins
,
config
)
{
const
availableHook
=
typeof
hook
===
'
string
'
?
document
.
querySelector
(
hook
)
:
hook
;
let
availableList
;
if
(
typeof
list
===
'
string
'
)
{
availableList
=
document
.
querySelector
(
list
);
}
else
if
(
list
instanceof
Element
)
{
availableList
=
list
;
}
else
{
availableList
=
document
.
querySelector
(
hook
.
dataset
[
utils
.
toCamelCase
(
DATA_TRIGGER
)]);
}
availableList
.
dataset
.
dropdownActive
=
true
;
const
HookObject
=
availableHook
.
tagName
===
'
INPUT
'
?
HookInput
:
HookButton
;
this
.
hooks
.
push
(
new
HookObject
(
availableHook
,
availableList
,
plugins
,
config
));
return
this
;
},
addHooks
:
function
(
hooks
,
plugins
,
config
)
{
hooks
.
forEach
(
hook
=>
this
.
addHook
(
hook
,
null
,
plugins
,
config
));
return
this
;
},
setConfig
:
function
(
obj
){
this
.
config
=
obj
;
},
fireReady
:
function
()
{
const
readyEvent
=
new
CustomEvent
(
'
ready.dl
'
,
{
detail
:
{
dropdown
:
this
,
},
});
document
.
dispatchEvent
(
readyEvent
);
this
.
ready
=
true
;
},
init
:
function
(
hook
,
list
,
plugins
,
config
)
{
hook
?
this
.
addHook
(
hook
,
list
,
plugins
,
config
)
:
this
.
loadStatic
();
this
.
addEvents
();
Keyboard
();
this
.
fireReady
();
this
.
queuedData
.
forEach
(
data
=>
this
.
addData
(
data
));
this
.
queuedData
=
[];
return
this
;
},
});
export
default
DropLab
;
app/assets/javascripts/droplab/droplab_filter.js
deleted
100644 → 0
View file @
7083d381
/* eslint-disable */
(
function
(
f
){
if
(
typeof
exports
===
"
object
"
&&
typeof
module
!==
"
undefined
"
){
module
.
exports
=
f
()}
else
if
(
typeof
define
===
"
function
"
&&
define
.
amd
){
define
([],
f
)}
else
{
var
g
;
if
(
typeof
window
!==
"
undefined
"
){
g
=
window
}
else
if
(
typeof
global
!==
"
undefined
"
){
g
=
global
}
else
if
(
typeof
self
!==
"
undefined
"
){
g
=
self
}
else
{
g
=
this
}
g
=
(
g
.
droplab
||
(
g
.
droplab
=
{}));
g
=
(
g
.
filter
||
(
g
.
filter
=
{}));
g
.
js
=
f
()}})(
function
(){
var
define
,
module
,
exports
;
return
(
function
e
(
t
,
n
,
r
){
function
s
(
o
,
u
){
if
(
!
n
[
o
]){
if
(
!
t
[
o
]){
var
a
=
typeof
require
==
"
function
"
&&
require
;
if
(
!
u
&&
a
)
return
a
(
o
,
!
0
);
if
(
i
)
return
i
(
o
,
!
0
);
var
f
=
new
Error
(
"
Cannot find module '
"
+
o
+
"
'
"
);
throw
f
.
code
=
"
MODULE_NOT_FOUND
"
,
f
}
var
l
=
n
[
o
]
=
{
exports
:{}};
t
[
o
][
0
].
call
(
l
.
exports
,
function
(
e
){
var
n
=
t
[
o
][
1
][
e
];
return
s
(
n
?
n
:
e
)},
l
,
l
.
exports
,
e
,
t
,
n
,
r
)}
return
n
[
o
].
exports
}
var
i
=
typeof
require
==
"
function
"
&&
require
;
for
(
var
o
=
0
;
o
<
r
.
length
;
o
++
)
s
(
r
[
o
]);
return
s
})({
1
:[
function
(
require
,
module
,
exports
){
/* global droplab */
require
(
'
../window
'
)(
function
(
w
){
w
.
droplabFilter
=
{
keydownWrapper
:
function
(
e
){
var
hiddenCount
=
0
;
var
dataHiddenCount
=
0
;
var
list
=
e
.
detail
.
hook
.
list
;
var
data
=
list
.
data
;
var
value
=
e
.
detail
.
hook
.
trigger
.
value
.
toLowerCase
();
var
config
=
e
.
detail
.
hook
.
config
.
droplabFilter
;
var
matches
=
[];
var
filterFunction
;
// will only work on dynamically set data
if
(
!
data
){
return
;
}
if
(
config
&&
config
.
filterFunction
&&
typeof
config
.
filterFunction
===
'
function
'
)
{
filterFunction
=
config
.
filterFunction
;
}
else
{
filterFunction
=
function
(
o
){
// cheap string search
o
.
droplab_hidden
=
o
[
config
.
template
].
toLowerCase
().
indexOf
(
value
)
===
-
1
;
return
o
;
};
}
dataHiddenCount
=
data
.
filter
(
function
(
o
)
{
return
!
o
.
droplab_hidden
;
}).
length
;
matches
=
data
.
map
(
function
(
o
)
{
return
filterFunction
(
o
,
value
);
});
hiddenCount
=
matches
.
filter
(
function
(
o
)
{
return
!
o
.
droplab_hidden
;
}).
length
;
if
(
dataHiddenCount
!==
hiddenCount
)
{
list
.
render
(
matches
);
list
.
currentIndex
=
0
;
}
},
init
:
function
init
(
hookInput
)
{
var
config
=
hookInput
.
config
.
droplabFilter
;
if
(
!
config
||
(
!
config
.
template
&&
!
config
.
filterFunction
))
{
return
;
}
this
.
hookInput
=
hookInput
;
this
.
hookInput
.
trigger
.
addEventListener
(
'
keyup.dl
'
,
this
.
keydownWrapper
);
this
.
hookInput
.
trigger
.
addEventListener
(
'
mousedown.dl
'
,
this
.
keydownWrapper
);
},
destroy
:
function
destroy
(){
this
.
hookInput
.
trigger
.
removeEventListener
(
'
keyup.dl
'
,
this
.
keydownWrapper
);
this
.
hookInput
.
trigger
.
removeEventListener
(
'
mousedown.dl
'
,
this
.
keydownWrapper
);
}
};
});
},{
"
../window
"
:
2
}],
2
:[
function
(
require
,
module
,
exports
){
module
.
exports
=
function
(
callback
)
{
return
(
function
()
{
callback
(
this
);
}).
call
(
null
);
};
},{}]},{},[
1
])(
1
)
});
app/assets/javascripts/droplab/hook.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
DropDown
from
'
./drop_down
'
;
var
Hook
=
function
(
trigger
,
list
,
plugins
,
config
){
this
.
trigger
=
trigger
;
this
.
list
=
new
DropDown
(
list
);
this
.
type
=
'
Hook
'
;
this
.
event
=
'
click
'
;
this
.
plugins
=
plugins
||
[];
this
.
config
=
config
||
{};
this
.
id
=
trigger
.
id
;
};
Object
.
assign
(
Hook
.
prototype
,
{
addEvents
:
function
(){},
constructor
:
Hook
,
});
export
default
Hook
;
app/assets/javascripts/droplab/hook_button.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
Hook
from
'
./hook
'
;
var
HookButton
=
function
(
trigger
,
list
,
plugins
,
config
)
{
Hook
.
call
(
this
,
trigger
,
list
,
plugins
,
config
);
this
.
type
=
'
button
'
;
this
.
event
=
'
click
'
;
this
.
eventWrapper
=
{};
this
.
addEvents
();
this
.
addPlugins
();
};
HookButton
.
prototype
=
Object
.
create
(
Hook
.
prototype
);
Object
.
assign
(
HookButton
.
prototype
,
{
addPlugins
:
function
()
{
this
.
plugins
.
forEach
(
plugin
=>
plugin
.
init
(
this
));
},
clicked
:
function
(
e
){
var
buttonEvent
=
new
CustomEvent
(
'
click.dl
'
,
{
detail
:
{
hook
:
this
,
},
bubbles
:
true
,
cancelable
:
true
});
e
.
target
.
dispatchEvent
(
buttonEvent
);
this
.
list
.
toggle
();
},
addEvents
:
function
(){
this
.
eventWrapper
.
clicked
=
this
.
clicked
.
bind
(
this
);
this
.
trigger
.
addEventListener
(
'
click
'
,
this
.
eventWrapper
.
clicked
);
},
removeEvents
:
function
(){
this
.
trigger
.
removeEventListener
(
'
click
'
,
this
.
eventWrapper
.
clicked
);
},
restoreInitialState
:
function
()
{
this
.
list
.
list
.
innerHTML
=
this
.
list
.
initialState
;
},
removePlugins
:
function
()
{
this
.
plugins
.
forEach
(
plugin
=>
plugin
.
destroy
());
},
destroy
:
function
()
{
this
.
restoreInitialState
();
this
.
removeEvents
();
this
.
removePlugins
();
},
constructor
:
HookButton
,
});
export
default
HookButton
;
app/assets/javascripts/droplab/hook_input.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
Hook
from
'
./hook
'
;
var
HookInput
=
function
(
trigger
,
list
,
plugins
,
config
)
{
Hook
.
call
(
this
,
trigger
,
list
,
plugins
,
config
);
this
.
type
=
'
input
'
;
this
.
event
=
'
input
'
;
this
.
eventWrapper
=
{};
this
.
addEvents
();
this
.
addPlugins
();
};
Object
.
assign
(
HookInput
.
prototype
,
{
addPlugins
:
function
()
{
this
.
plugins
.
forEach
(
plugin
=>
plugin
.
init
(
this
));
},
addEvents
:
function
(){
this
.
eventWrapper
.
mousedown
=
this
.
mousedown
.
bind
(
this
);
this
.
eventWrapper
.
input
=
this
.
input
.
bind
(
this
);
this
.
eventWrapper
.
keyup
=
this
.
keyup
.
bind
(
this
);
this
.
eventWrapper
.
keydown
=
this
.
keydown
.
bind
(
this
);
this
.
trigger
.
addEventListener
(
'
mousedown
'
,
this
.
eventWrapper
.
mousedown
);
this
.
trigger
.
addEventListener
(
'
input
'
,
this
.
eventWrapper
.
input
);
this
.
trigger
.
addEventListener
(
'
keyup
'
,
this
.
eventWrapper
.
keyup
);
this
.
trigger
.
addEventListener
(
'
keydown
'
,
this
.
eventWrapper
.
keydown
);
},
removeEvents
:
function
()
{
this
.
hasRemovedEvents
=
true
;
this
.
trigger
.
removeEventListener
(
'
mousedown
'
,
this
.
eventWrapper
.
mousedown
);
this
.
trigger
.
removeEventListener
(
'
input
'
,
this
.
eventWrapper
.
input
);
this
.
trigger
.
removeEventListener
(
'
keyup
'
,
this
.
eventWrapper
.
keyup
);
this
.
trigger
.
removeEventListener
(
'
keydown
'
,
this
.
eventWrapper
.
keydown
);
},
input
:
function
(
e
)
{
if
(
this
.
hasRemovedEvents
)
return
;
this
.
list
.
show
();
const
inputEvent
=
new
CustomEvent
(
'
input.dl
'
,
{
detail
:
{
hook
:
this
,
text
:
e
.
target
.
value
,
},
bubbles
:
true
,
cancelable
:
true
});
e
.
target
.
dispatchEvent
(
inputEvent
);
},
mousedown
:
function
(
e
)
{
if
(
this
.
hasRemovedEvents
)
return
;
const
mouseEvent
=
new
CustomEvent
(
'
mousedown.dl
'
,
{
detail
:
{
hook
:
this
,
text
:
e
.
target
.
value
,
},
bubbles
:
true
,
cancelable
:
true
,
});
e
.
target
.
dispatchEvent
(
mouseEvent
);
},
keyup
:
function
(
e
)
{
if
(
this
.
hasRemovedEvents
)
return
;
this
.
keyEvent
(
e
,
'
keyup.dl
'
);
},
keydown
:
function
(
e
)
{
if
(
this
.
hasRemovedEvents
)
return
;
this
.
keyEvent
(
e
,
'
keydown.dl
'
);
},
keyEvent
:
function
(
e
,
eventName
)
{
this
.
list
.
show
();
const
keyEvent
=
new
CustomEvent
(
eventName
,
{
detail
:
{
hook
:
this
,
text
:
e
.
target
.
value
,
which
:
e
.
which
,
key
:
e
.
key
,
},
bubbles
:
true
,
cancelable
:
true
,
});
e
.
target
.
dispatchEvent
(
keyEvent
);
},
restoreInitialState
:
function
()
{
this
.
list
.
list
.
innerHTML
=
this
.
list
.
initialState
;
},
removePlugins
:
function
()
{
this
.
plugins
.
forEach
(
plugin
=>
plugin
.
destroy
());
},
destroy
:
function
()
{
this
.
restoreInitialState
();
this
.
removeEvents
();
this
.
removePlugins
();
this
.
list
.
destroy
();
}
});
export
default
HookInput
;
app/assets/javascripts/droplab/keyboard.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
{
ACTIVE_CLASS
}
from
'
./constants
'
;
const
Keyboard
=
function
()
{
var
currentKey
;
var
currentFocus
;
var
isUpArrow
=
false
;
var
isDownArrow
=
false
;
var
removeHighlight
=
function
removeHighlight
(
list
)
{
var
itemElements
=
Array
.
prototype
.
slice
.
call
(
list
.
list
.
querySelectorAll
(
'
li:not(.divider)
'
),
0
);
var
listItems
=
[];
for
(
var
i
=
0
;
i
<
itemElements
.
length
;
i
++
)
{
var
listItem
=
itemElements
[
i
];
listItem
.
classList
.
remove
(
ACTIVE_CLASS
);
if
(
listItem
.
style
.
display
!==
'
none
'
)
{
listItems
.
push
(
listItem
);
}
}
return
listItems
;
};
var
setMenuForArrows
=
function
setMenuForArrows
(
list
)
{
var
listItems
=
removeHighlight
(
list
);
if
(
list
.
currentIndex
>
0
){
if
(
!
listItems
[
list
.
currentIndex
-
1
]){
list
.
currentIndex
=
list
.
currentIndex
-
1
;
}
if
(
listItems
[
list
.
currentIndex
-
1
])
{
var
el
=
listItems
[
list
.
currentIndex
-
1
];
var
filterDropdownEl
=
el
.
closest
(
'
.filter-dropdown
'
);
el
.
classList
.
add
(
ACTIVE_CLASS
);
if
(
filterDropdownEl
)
{
var
filterDropdownBottom
=
filterDropdownEl
.
offsetHeight
;
var
elOffsetTop
=
el
.
offsetTop
-
30
;
if
(
elOffsetTop
>
filterDropdownBottom
)
{
filterDropdownEl
.
scrollTop
=
elOffsetTop
-
filterDropdownBottom
;
}
}
}
}
};
var
mousedown
=
function
mousedown
(
e
)
{
var
list
=
e
.
detail
.
hook
.
list
;
removeHighlight
(
list
);
list
.
show
();
list
.
currentIndex
=
0
;
isUpArrow
=
false
;
isDownArrow
=
false
;
};
var
selectItem
=
function
selectItem
(
list
)
{
var
listItems
=
removeHighlight
(
list
);
var
currentItem
=
listItems
[
list
.
currentIndex
-
1
];
var
listEvent
=
new
CustomEvent
(
'
click.dl
'
,
{
detail
:
{
list
:
list
,
selected
:
currentItem
,
data
:
currentItem
.
dataset
,
},
});
list
.
list
.
dispatchEvent
(
listEvent
);
list
.
hide
();
}
var
keydown
=
function
keydown
(
e
){
var
typedOn
=
e
.
target
;
var
list
=
e
.
detail
.
hook
.
list
;
var
currentIndex
=
list
.
currentIndex
;
isUpArrow
=
false
;
isDownArrow
=
false
;
if
(
e
.
detail
.
which
){
currentKey
=
e
.
detail
.
which
;
if
(
currentKey
===
13
){
selectItem
(
e
.
detail
.
hook
.
list
);
return
;
}
if
(
currentKey
===
38
)
{
isUpArrow
=
true
;
}
if
(
currentKey
===
40
)
{
isDownArrow
=
true
;
}
}
else
if
(
e
.
detail
.
key
)
{
currentKey
=
e
.
detail
.
key
;
if
(
currentKey
===
'
Enter
'
){
selectItem
(
e
.
detail
.
hook
.
list
);
return
;
}
if
(
currentKey
===
'
ArrowUp
'
)
{
isUpArrow
=
true
;
}
if
(
currentKey
===
'
ArrowDown
'
)
{
isDownArrow
=
true
;
}
}
if
(
isUpArrow
){
currentIndex
--
;
}
if
(
isDownArrow
){
currentIndex
++
;
}
if
(
currentIndex
<
0
){
currentIndex
=
0
;
}
list
.
currentIndex
=
currentIndex
;
setMenuForArrows
(
e
.
detail
.
hook
.
list
);
};
document
.
addEventListener
(
'
mousedown.dl
'
,
mousedown
);
document
.
addEventListener
(
'
keydown.dl
'
,
keydown
);
};
export
default
Keyboard
;
app/assets/javascripts/droplab/plugins/ajax.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
function
droplabAjaxException
(
message
)
{
this
.
message
=
message
;
}
const
Ajax
=
{
_loadUrlData
:
function
_loadUrlData
(
url
)
{
var
self
=
this
;
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
xhr
=
new
XMLHttpRequest
;
xhr
.
open
(
'
GET
'
,
url
,
true
);
xhr
.
onreadystatechange
=
function
()
{
if
(
xhr
.
readyState
===
XMLHttpRequest
.
DONE
)
{
if
(
xhr
.
status
===
200
)
{
var
data
=
JSON
.
parse
(
xhr
.
responseText
);
self
.
cache
[
url
]
=
data
;
return
resolve
(
data
);
}
else
{
return
reject
([
xhr
.
responseText
,
xhr
.
status
]);
}
}
};
xhr
.
send
();
});
},
_loadData
:
function
_loadData
(
data
,
config
,
self
)
{
if
(
config
.
loadingTemplate
)
{
var
dataLoadingTemplate
=
self
.
hook
.
list
.
list
.
querySelector
(
'
[data-loading-template]
'
);
if
(
dataLoadingTemplate
)
dataLoadingTemplate
.
outerHTML
=
self
.
listTemplate
;
}
if
(
!
self
.
destroyed
)
self
.
hook
.
list
[
config
.
method
].
call
(
self
.
hook
.
list
,
data
);
},
init
:
function
init
(
hook
)
{
var
self
=
this
;
self
.
destroyed
=
false
;
self
.
cache
=
self
.
cache
||
{};
var
config
=
hook
.
config
.
Ajax
;
this
.
hook
=
hook
;
if
(
!
config
||
!
config
.
endpoint
||
!
config
.
method
)
{
return
;
}
if
(
config
.
method
!==
'
setData
'
&&
config
.
method
!==
'
addData
'
)
{
return
;
}
if
(
config
.
loadingTemplate
)
{
var
dynamicList
=
hook
.
list
.
list
.
querySelector
(
'
[data-dynamic]
'
);
var
loadingTemplate
=
document
.
createElement
(
'
div
'
);
loadingTemplate
.
innerHTML
=
config
.
loadingTemplate
;
loadingTemplate
.
setAttribute
(
'
data-loading-template
'
,
''
);
this
.
listTemplate
=
dynamicList
.
outerHTML
;
dynamicList
.
outerHTML
=
loadingTemplate
.
outerHTML
;
}
if
(
self
.
cache
[
config
.
endpoint
])
{
self
.
_loadData
(
self
.
cache
[
config
.
endpoint
],
config
,
self
);
}
else
{
this
.
_loadUrlData
(
config
.
endpoint
)
.
then
(
function
(
d
)
{
self
.
_loadData
(
d
,
config
,
self
);
},
config
.
onError
).
catch
(
function
(
e
)
{
throw
new
droplabAjaxException
(
e
.
message
||
e
);
});
}
},
destroy
:
function
()
{
this
.
destroyed
=
true
;
}
};
export
default
Ajax
;
app/assets/javascripts/droplab/plugins/ajax_filter.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
const
AjaxFilter
=
{
init
:
function
(
hook
)
{
this
.
destroyed
=
false
;
this
.
hook
=
hook
;
this
.
notLoading
();
this
.
eventWrapper
=
{};
this
.
eventWrapper
.
debounceTrigger
=
this
.
debounceTrigger
.
bind
(
this
);
this
.
hook
.
trigger
.
addEventListener
(
'
keydown.dl
'
,
this
.
eventWrapper
.
debounceTrigger
);
this
.
hook
.
trigger
.
addEventListener
(
'
focus
'
,
this
.
eventWrapper
.
debounceTrigger
);
this
.
trigger
(
true
);
},
notLoading
:
function
notLoading
()
{
this
.
loading
=
false
;
},
debounceTrigger
:
function
debounceTrigger
(
e
)
{
var
NON_CHARACTER_KEYS
=
[
16
,
17
,
18
,
20
,
37
,
38
,
39
,
40
,
91
,
93
];
var
invalidKeyPressed
=
NON_CHARACTER_KEYS
.
indexOf
(
e
.
detail
.
which
||
e
.
detail
.
keyCode
)
>
-
1
;
var
focusEvent
=
e
.
type
===
'
focus
'
;
if
(
invalidKeyPressed
||
this
.
loading
)
{
return
;
}
if
(
this
.
timeout
)
{
clearTimeout
(
this
.
timeout
);
}
this
.
timeout
=
setTimeout
(
this
.
trigger
.
bind
(
this
,
focusEvent
),
200
);
},
trigger
:
function
trigger
(
getEntireList
)
{
var
config
=
this
.
hook
.
config
.
AjaxFilter
;
var
searchValue
=
this
.
trigger
.
value
;
if
(
!
config
||
!
config
.
endpoint
||
!
config
.
searchKey
)
{
return
;
}
if
(
config
.
searchValueFunction
)
{
searchValue
=
config
.
searchValueFunction
();
}
if
(
config
.
loadingTemplate
&&
this
.
hook
.
list
.
data
===
undefined
||
this
.
hook
.
list
.
data
.
length
===
0
)
{
var
dynamicList
=
this
.
hook
.
list
.
list
.
querySelector
(
'
[data-dynamic]
'
);
var
loadingTemplate
=
document
.
createElement
(
'
div
'
);
loadingTemplate
.
innerHTML
=
config
.
loadingTemplate
;
loadingTemplate
.
setAttribute
(
'
data-loading-template
'
,
true
);
this
.
listTemplate
=
dynamicList
.
outerHTML
;
dynamicList
.
outerHTML
=
loadingTemplate
.
outerHTML
;
}
if
(
getEntireList
)
{
searchValue
=
''
;
}
if
(
config
.
searchKey
===
searchValue
)
{
return
this
.
list
.
show
();
}
this
.
loading
=
true
;
var
params
=
config
.
params
||
{};
params
[
config
.
searchKey
]
=
searchValue
;
var
self
=
this
;
self
.
cache
=
self
.
cache
||
{};
var
url
=
config
.
endpoint
+
this
.
buildParams
(
params
);
var
urlCachedData
=
self
.
cache
[
url
];
if
(
urlCachedData
)
{
self
.
_loadData
(
urlCachedData
,
config
,
self
);
}
else
{
this
.
_loadUrlData
(
url
)
.
then
(
function
(
data
)
{
self
.
_loadData
(
data
,
config
,
self
);
},
config
.
onError
);
}
},
_loadUrlData
:
function
_loadUrlData
(
url
)
{
var
self
=
this
;
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
xhr
=
new
XMLHttpRequest
;
xhr
.
open
(
'
GET
'
,
url
,
true
);
xhr
.
onreadystatechange
=
function
()
{
if
(
xhr
.
readyState
===
XMLHttpRequest
.
DONE
)
{
if
(
xhr
.
status
===
200
)
{
var
data
=
JSON
.
parse
(
xhr
.
responseText
);
self
.
cache
[
url
]
=
data
;
return
resolve
(
data
);
}
else
{
return
reject
([
xhr
.
responseText
,
xhr
.
status
]);
}
}
};
xhr
.
send
();
});
},
_loadData
:
function
_loadData
(
data
,
config
,
self
)
{
const
list
=
self
.
hook
.
list
;
if
(
config
.
loadingTemplate
&&
list
.
data
===
undefined
||
list
.
data
.
length
===
0
)
{
const
dataLoadingTemplate
=
list
.
list
.
querySelector
(
'
[data-loading-template]
'
);
if
(
dataLoadingTemplate
)
{
dataLoadingTemplate
.
outerHTML
=
self
.
listTemplate
;
}
}
if
(
!
self
.
destroyed
)
{
var
hookListChildren
=
list
.
list
.
children
;
var
onlyDynamicList
=
hookListChildren
.
length
===
1
&&
hookListChildren
[
0
].
hasAttribute
(
'
data-dynamic
'
);
if
(
onlyDynamicList
&&
data
.
length
===
0
)
{
list
.
hide
();
}
list
.
setData
.
call
(
list
,
data
);
}
self
.
notLoading
();
list
.
currentIndex
=
0
;
},
buildParams
:
function
(
params
)
{
if
(
!
params
)
return
''
;
var
paramsArray
=
Object
.
keys
(
params
).
map
(
function
(
param
)
{
return
param
+
'
=
'
+
(
params
[
param
]
||
''
);
});
return
'
?
'
+
paramsArray
.
join
(
'
&
'
);
},
destroy
:
function
destroy
()
{
if
(
this
.
timeout
)
clearTimeout
(
this
.
timeout
);
this
.
destroyed
=
true
;
this
.
hook
.
trigger
.
removeEventListener
(
'
keydown.dl
'
,
this
.
eventWrapper
.
debounceTrigger
);
this
.
hook
.
trigger
.
removeEventListener
(
'
focus
'
,
this
.
eventWrapper
.
debounceTrigger
);
}
};
export
default
AjaxFilter
;
app/assets/javascripts/droplab/plugins/filter.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
const
Filter
=
{
keydown
:
function
(
e
){
if
(
this
.
destroyed
)
return
;
var
hiddenCount
=
0
;
var
dataHiddenCount
=
0
;
var
list
=
e
.
detail
.
hook
.
list
;
var
data
=
list
.
data
;
var
value
=
e
.
detail
.
hook
.
trigger
.
value
.
toLowerCase
();
var
config
=
e
.
detail
.
hook
.
config
.
Filter
;
var
matches
=
[];
var
filterFunction
;
// will only work on dynamically set data
if
(
!
data
){
return
;
}
if
(
config
&&
config
.
filterFunction
&&
typeof
config
.
filterFunction
===
'
function
'
)
{
filterFunction
=
config
.
filterFunction
;
}
else
{
filterFunction
=
function
(
o
){
// cheap string search
o
.
droplab_hidden
=
o
[
config
.
template
].
toLowerCase
().
indexOf
(
value
)
===
-
1
;
return
o
;
};
}
dataHiddenCount
=
data
.
filter
(
function
(
o
)
{
return
!
o
.
droplab_hidden
;
}).
length
;
matches
=
data
.
map
(
function
(
o
)
{
return
filterFunction
(
o
,
value
);
});
hiddenCount
=
matches
.
filter
(
function
(
o
)
{
return
!
o
.
droplab_hidden
;
}).
length
;
if
(
dataHiddenCount
!==
hiddenCount
)
{
list
.
setData
(
matches
);
list
.
currentIndex
=
0
;
}
},
debounceKeydown
:
function
debounceKeydown
(
e
)
{
if
([
13
,
// enter
16
,
// shift
17
,
// ctrl
18
,
// alt
20
,
// caps lock
37
,
// left arrow
38
,
// up arrow
39
,
// right arrow
40
,
// down arrow
91
,
// left window
92
,
// right window
93
,
// select
].
indexOf
(
e
.
detail
.
which
||
e
.
detail
.
keyCode
)
>
-
1
)
return
;
if
(
this
.
timeout
)
clearTimeout
(
this
.
timeout
);
this
.
timeout
=
setTimeout
(
this
.
keydown
.
bind
(
this
,
e
),
200
);
},
init
:
function
init
(
hook
)
{
var
config
=
hook
.
config
.
Filter
;
if
(
!
config
||
!
config
.
template
)
return
;
this
.
hook
=
hook
;
this
.
destroyed
=
false
;
this
.
eventWrapper
=
{};
this
.
eventWrapper
.
debounceKeydown
=
this
.
debounceKeydown
.
bind
(
this
);
this
.
hook
.
trigger
.
addEventListener
(
'
keydown.dl
'
,
this
.
eventWrapper
.
debounceKeydown
);
this
.
hook
.
trigger
.
addEventListener
(
'
mousedown.dl
'
,
this
.
eventWrapper
.
debounceKeydown
);
this
.
debounceKeydown
({
detail
:
{
hook
:
this
.
hook
}
});
},
destroy
:
function
destroy
()
{
if
(
this
.
timeout
)
clearTimeout
(
this
.
timeout
);
this
.
destroyed
=
true
;
this
.
hook
.
trigger
.
removeEventListener
(
'
keydown.dl
'
,
this
.
eventWrapper
.
debounceKeydown
);
this
.
hook
.
trigger
.
removeEventListener
(
'
mousedown.dl
'
,
this
.
eventWrapper
.
debounceKeydown
);
}
};
export
default
Filter
;
app/assets/javascripts/droplab/plugins/input_setter.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
const
InputSetter
=
{
init
(
hook
)
{
this
.
hook
=
hook
;
this
.
destroyed
=
false
;
this
.
config
=
hook
.
config
.
InputSetter
||
(
this
.
hook
.
config
.
InputSetter
=
{});
this
.
eventWrapper
=
{};
this
.
addEvents
();
},
addEvents
()
{
this
.
eventWrapper
.
setInputs
=
this
.
setInputs
.
bind
(
this
);
this
.
hook
.
list
.
list
.
addEventListener
(
'
click.dl
'
,
this
.
eventWrapper
.
setInputs
);
},
removeEvents
()
{
this
.
hook
.
list
.
list
.
removeEventListener
(
'
click.dl
'
,
this
.
eventWrapper
.
setInputs
);
},
setInputs
(
e
)
{
if
(
this
.
destroyed
)
return
;
const
selectedItem
=
e
.
detail
.
selected
;
if
(
!
Array
.
isArray
(
this
.
config
))
this
.
config
=
[
this
.
config
];
this
.
config
.
forEach
(
config
=>
this
.
setInput
(
config
,
selectedItem
));
},
setInput
(
config
,
selectedItem
)
{
const
input
=
config
.
input
||
this
.
hook
.
trigger
;
const
newValue
=
selectedItem
.
getAttribute
(
config
.
valueAttribute
);
if
(
input
.
tagName
===
'
INPUT
'
)
{
input
.
value
=
newValue
;
}
else
{
input
.
textContent
=
newValue
;
}
},
destroy
()
{
this
.
destroyed
=
true
;
this
.
removeEvents
();
},
};
export
default
InputSetter
;
app/assets/javascripts/droplab/utils.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
{
DATA_TRIGGER
,
DATA_DROPDOWN
}
from
'
./constants
'
;
const
utils
=
{
toCamelCase
(
attr
)
{
return
this
.
camelize
(
attr
.
split
(
'
-
'
).
slice
(
1
).
join
(
'
'
));
},
t
(
s
,
d
)
{
for
(
const
p
in
d
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
d
,
p
))
{
s
=
s
.
replace
(
new
RegExp
(
`{{
${
p
}
}}`
,
'
g
'
),
d
[
p
]);
}
}
return
s
;
},
camelize
(
str
)
{
return
str
.
replace
(
/
(?:
^
\w
|
[
A-Z
]
|
\b\w)
/g
,
(
letter
,
index
)
=>
{
return
index
===
0
?
letter
.
toLowerCase
()
:
letter
.
toUpperCase
();
}).
replace
(
/
\s
+/g
,
''
);
},
closest
(
thisTag
,
stopTag
)
{
while
(
thisTag
&&
thisTag
.
tagName
!==
stopTag
&&
thisTag
.
tagName
!==
'
HTML
'
)
{
thisTag
=
thisTag
.
parentNode
;
}
return
thisTag
;
},
isDropDownParts
(
target
)
{
if
(
!
target
||
target
.
tagName
===
'
HTML
'
)
return
false
;
return
target
.
hasAttribute
(
DATA_TRIGGER
)
||
target
.
hasAttribute
(
DATA_DROPDOWN
);
},
};
export
default
utils
;
app/assets/javascripts/filtered_search/dropdown_hint.js
View file @
75ac2699
import
Filter
from
'
@gitlab-org/droplab/dist/plugins/F
ilter
'
;
import
Filter
from
'
~/droplab/plugins/f
ilter
'
;
require
(
'
./filtered_search_dropdown
'
);
require
(
'
./filtered_search_dropdown
'
);
...
...
app/assets/javascripts/filtered_search/dropdown_non_user.js
View file @
75ac2699
import
Ajax
from
'
@gitlab-org/droplab/dist/plugins/A
jax
'
;
import
Ajax
from
'
~/droplab/plugins/a
jax
'
;
import
Filter
from
'
@gitlab-org/droplab/dist/plugins/F
ilter
'
;
import
Filter
from
'
~/droplab/plugins/f
ilter
'
;
require
(
'
./filtered_search_dropdown
'
);
require
(
'
./filtered_search_dropdown
'
);
...
...
app/assets/javascripts/filtered_search/dropdown_user.js
View file @
75ac2699
import
AjaxFilter
from
'
@gitlab-org/droplab/dist/plugins/AjaxF
ilter
'
;
import
AjaxFilter
from
'
~/droplab/plugins/ajax_f
ilter
'
;
require
(
'
./filtered_search_dropdown
'
);
require
(
'
./filtered_search_dropdown
'
);
...
...
app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
View file @
75ac2699
import
DropLab
from
'
@gitlab-org/drop
lab
'
;
import
DropLab
from
'
~/droplab/drop_
lab
'
;
import
FilteredSearchContainer
from
'
./container
'
;
import
FilteredSearchContainer
from
'
./container
'
;
(()
=>
{
(()
=>
{
...
...
spec/javascripts/droplab/constants.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
*
as
constants
from
'
~/droplab/constants
'
;
describe
(
'
constants
'
,
function
()
{
describe
(
'
DATA_TRIGGER
'
,
function
()
{
it
(
'
should be `data-dropdown-trigger`
'
,
function
()
{
expect
(
constants
.
DATA_TRIGGER
).
toBe
(
'
data-dropdown-trigger
'
);
});
});
describe
(
'
DATA_DROPDOWN
'
,
function
()
{
it
(
'
should be `data-dropdown`
'
,
function
()
{
expect
(
constants
.
DATA_DROPDOWN
).
toBe
(
'
data-dropdown
'
);
});
});
describe
(
'
SELECTED_CLASS
'
,
function
()
{
it
(
'
should be `droplab-item-selected`
'
,
function
()
{
expect
(
constants
.
SELECTED_CLASS
).
toBe
(
'
droplab-item-selected
'
);
});
});
describe
(
'
ACTIVE_CLASS
'
,
function
()
{
it
(
'
should be `droplab-item-active`
'
,
function
()
{
expect
(
constants
.
ACTIVE_CLASS
).
toBe
(
'
droplab-item-active
'
);
});
});
});
spec/javascripts/droplab/drop_down.js
0 → 100644
View file @
75ac2699
This diff is collapsed.
Click to expand it.
spec/javascripts/droplab/hook.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
Hook
from
'
~/droplab/hook
'
;
import
*
as
dropdownSrc
from
'
~/droplab/drop_down
'
;
describe
(
'
Hook
'
,
function
()
{
describe
(
'
class constructor
'
,
function
()
{
beforeEach
(
function
()
{
this
.
trigger
=
{
id
:
'
id
'
};
this
.
list
=
{};
this
.
plugins
=
{};
this
.
config
=
{};
this
.
dropdown
=
{};
spyOn
(
dropdownSrc
,
'
default
'
).
and
.
returnValue
(
this
.
dropdown
);
this
.
hook
=
new
Hook
(
this
.
trigger
,
this
.
list
,
this
.
plugins
,
this
.
config
);
});
it
(
'
should set .trigger
'
,
function
()
{
expect
(
this
.
hook
.
trigger
).
toBe
(
this
.
trigger
);
});
it
(
'
should set .list
'
,
function
()
{
expect
(
this
.
hook
.
list
).
toBe
(
this
.
dropdown
);
});
it
(
'
should call DropDown constructor
'
,
function
()
{
expect
(
dropdownSrc
.
default
).
toHaveBeenCalledWith
(
this
.
list
);
});
it
(
'
should set .type
'
,
function
()
{
expect
(
this
.
hook
.
type
).
toBe
(
'
Hook
'
);
});
it
(
'
should set .event
'
,
function
()
{
expect
(
this
.
hook
.
event
).
toBe
(
'
click
'
);
});
it
(
'
should set .plugins
'
,
function
()
{
expect
(
this
.
hook
.
plugins
).
toBe
(
this
.
plugins
);
});
it
(
'
should set .config
'
,
function
()
{
expect
(
this
.
hook
.
config
).
toBe
(
this
.
config
);
});
it
(
'
should set .id
'
,
function
()
{
expect
(
this
.
hook
.
id
).
toBe
(
this
.
trigger
.
id
);
});
describe
(
'
if config argument is undefined
'
,
function
()
{
beforeEach
(
function
()
{
this
.
config
=
undefined
;
this
.
hook
=
new
Hook
(
this
.
trigger
,
this
.
list
,
this
.
plugins
,
this
.
config
);
});
it
(
'
should set .config to an empty object
'
,
function
()
{
expect
(
this
.
hook
.
config
).
toEqual
({});
});
});
describe
(
'
if plugins argument is undefined
'
,
function
()
{
beforeEach
(
function
()
{
this
.
plugins
=
undefined
;
this
.
hook
=
new
Hook
(
this
.
trigger
,
this
.
list
,
this
.
plugins
,
this
.
config
);
});
it
(
'
should set .plugins to an empty array
'
,
function
()
{
expect
(
this
.
hook
.
plugins
).
toEqual
([]);
});
});
});
describe
(
'
addEvents
'
,
function
()
{
it
(
'
should exist
'
,
function
()
{
expect
(
Hook
.
prototype
.
hasOwnProperty
(
'
addEvents
'
)).
toBe
(
true
);
});
});
});
spec/javascripts/droplab/plugins/input_setter.js
0 → 100644
View file @
75ac2699
/* eslint-disable */
import
InputSetter
from
'
~/droplab/plugins/input_setter
'
;
describe
(
'
InputSetter
'
,
function
()
{
describe
(
'
init
'
,
function
()
{
beforeEach
(
function
()
{
this
.
config
=
{
InputSetter
:
{}
};
this
.
hook
=
{
config
:
this
.
config
};
this
.
inputSetter
=
jasmine
.
createSpyObj
(
'
inputSetter
'
,
[
'
addEvents
'
]);
InputSetter
.
init
.
call
(
this
.
inputSetter
,
this
.
hook
);
});
it
(
'
should set .hook
'
,
function
()
{
expect
(
this
.
inputSetter
.
hook
).
toBe
(
this
.
hook
);
});
it
(
'
should set .config
'
,
function
()
{
expect
(
this
.
inputSetter
.
config
).
toBe
(
this
.
config
.
InputSetter
);
});
it
(
'
should set .eventWrapper
'
,
function
()
{
expect
(
this
.
inputSetter
.
eventWrapper
).
toEqual
({});
});
it
(
'
should call .addEvents
'
,
function
()
{
expect
(
this
.
inputSetter
.
addEvents
).
toHaveBeenCalled
();
});
describe
(
'
if config.InputSetter is not set
'
,
function
()
{
beforeEach
(
function
()
{
this
.
config
=
{
InputSetter
:
undefined
};
this
.
hook
=
{
config
:
this
.
config
};
InputSetter
.
init
.
call
(
this
.
inputSetter
,
this
.
hook
);
});
it
(
'
should set .config to an empty object
'
,
function
()
{
expect
(
this
.
inputSetter
.
config
).
toEqual
({});
});
it
(
'
should set hook.config to an empty object
'
,
function
()
{
expect
(
this
.
hook
.
config
.
InputSetter
).
toEqual
({});
});
})
});
describe
(
'
addEvents
'
,
function
()
{
beforeEach
(
function
()
{
this
.
hook
=
{
list
:
{
list
:
jasmine
.
createSpyObj
(
'
list
'
,
[
'
addEventListener
'
])
}
};
this
.
inputSetter
=
{
eventWrapper
:
{},
hook
:
this
.
hook
,
setInputs
:
()
=>
{}
};
InputSetter
.
addEvents
.
call
(
this
.
inputSetter
);
});
it
(
'
should set .eventWrapper.setInputs
'
,
function
()
{
expect
(
this
.
inputSetter
.
eventWrapper
.
setInputs
).
toEqual
(
jasmine
.
any
(
Function
));
});
it
(
'
should call .addEventListener
'
,
function
()
{
expect
(
this
.
hook
.
list
.
list
.
addEventListener
)
.
toHaveBeenCalledWith
(
'
click.dl
'
,
this
.
inputSetter
.
eventWrapper
.
setInputs
);
});
});
describe
(
'
removeEvents
'
,
function
()
{
beforeEach
(
function
()
{
this
.
hook
=
{
list
:
{
list
:
jasmine
.
createSpyObj
(
'
list
'
,
[
'
removeEventListener
'
])
}
};
this
.
eventWrapper
=
jasmine
.
createSpyObj
(
'
eventWrapper
'
,
[
'
setInputs
'
]);
this
.
inputSetter
=
{
eventWrapper
:
this
.
eventWrapper
,
hook
:
this
.
hook
};
InputSetter
.
removeEvents
.
call
(
this
.
inputSetter
);
});
it
(
'
should call .removeEventListener
'
,
function
()
{
expect
(
this
.
hook
.
list
.
list
.
removeEventListener
)
.
toHaveBeenCalledWith
(
'
click.dl
'
,
this
.
eventWrapper
.
setInputs
);
});
});
describe
(
'
setInputs
'
,
function
()
{
beforeEach
(
function
()
{
this
.
event
=
{
detail
:
{
selected
:
{}
}
};
this
.
config
=
[
0
,
1
];
this
.
inputSetter
=
{
config
:
this
.
config
,
setInput
:
()
=>
{}
};
spyOn
(
this
.
inputSetter
,
'
setInput
'
);
InputSetter
.
setInputs
.
call
(
this
.
inputSetter
,
this
.
event
);
});
it
(
'
should call .setInput for each config element
'
,
function
()
{
const
allArgs
=
this
.
inputSetter
.
setInput
.
calls
.
allArgs
();
expect
(
allArgs
.
length
).
toEqual
(
2
);
allArgs
.
forEach
((
args
,
i
)
=>
{
expect
(
args
[
0
]).
toBe
(
this
.
config
[
i
]);
expect
(
args
[
1
]).
toBe
(
this
.
event
.
detail
.
selected
);
});
});
describe
(
'
if config isnt an array
'
,
function
()
{
beforeEach
(
function
()
{
this
.
inputSetter
=
{
config
:
{},
setInput
:
()
=>
{}
};
InputSetter
.
setInputs
.
call
(
this
.
inputSetter
,
this
.
event
);
});
it
(
'
should set .config to an array with .config as the first element
'
,
function
()
{
expect
(
this
.
inputSetter
.
config
).
toEqual
([{}]);
});
});
});
describe
(
'
setInput
'
,
function
()
{
beforeEach
(
function
()
{
this
.
selectedItem
=
{
getAttribute
:
()
=>
{}
};
this
.
input
=
{
value
:
'
oldValue
'
,
tagName
:
'
INPUT
'
};
this
.
config
=
{
valueAttribute
:
{},
input
:
this
.
input
};
this
.
inputSetter
=
{
hook
:
{
trigger
:
{}
}
};
this
.
newValue
=
'
newValue
'
;
spyOn
(
this
.
selectedItem
,
'
getAttribute
'
).
and
.
returnValue
(
this
.
newValue
);
InputSetter
.
setInput
.
call
(
this
.
inputSetter
,
this
.
config
,
this
.
selectedItem
);
});
it
(
'
should call .getAttribute
'
,
function
()
{
expect
(
this
.
selectedItem
.
getAttribute
).
toHaveBeenCalledWith
(
this
.
config
.
valueAttribute
);
});
it
(
'
should set the value of the input
'
,
function
()
{
expect
(
this
.
input
.
value
).
toBe
(
this
.
newValue
);
})
describe
(
'
if no config.input is provided
'
,
function
()
{
beforeEach
(
function
()
{
this
.
config
=
{
valueAttribute
:
{}
};
this
.
trigger
=
{
value
:
'
oldValue
'
,
tagName
:
'
INPUT
'
};
this
.
inputSetter
=
{
hook
:
{
trigger
:
this
.
trigger
}
};
InputSetter
.
setInput
.
call
(
this
.
inputSetter
,
this
.
config
,
this
.
selectedItem
);
});
it
(
'
should set the value of the hook.trigger
'
,
function
()
{
expect
(
this
.
trigger
.
value
).
toBe
(
this
.
newValue
);
});
});
describe
(
'
if the input tag is not INPUT
'
,
function
()
{
beforeEach
(
function
()
{
this
.
input
=
{
textContent
:
'
oldValue
'
,
tagName
:
'
SPAN
'
};
this
.
config
=
{
valueAttribute
:
{},
input
:
this
.
input
};
InputSetter
.
setInput
.
call
(
this
.
inputSetter
,
this
.
config
,
this
.
selectedItem
);
});
it
(
'
should set the textContent of the input
'
,
function
()
{
expect
(
this
.
config
.
input
.
textContent
).
toBe
(
this
.
newValue
);
});
});
});
describe
(
'
destroy
'
,
function
()
{
beforeEach
(
function
()
{
this
.
inputSetter
=
jasmine
.
createSpyObj
(
'
inputSetter
'
,
[
'
removeEvents
'
]);
InputSetter
.
destroy
.
call
(
this
.
inputSetter
);
});
it
(
'
should call .removeEvents
'
,
function
()
{
expect
(
this
.
inputSetter
.
removeEvents
).
toHaveBeenCalled
();
});
});
});
spec/javascripts/filtered_search/dropdown_user_spec.js
View file @
75ac2699
...
@@ -33,7 +33,7 @@ require('~/filtered_search/dropdown_user');
...
@@ -33,7 +33,7 @@ require('~/filtered_search/dropdown_user');
});
});
});
});
describe
(
'
config
droplab
AjaxFilter
\'
s endpoint
'
,
()
=>
{
describe
(
'
config AjaxFilter
\'
s endpoint
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
spyOn
(
gl
.
DropdownUser
.
prototype
,
'
bindEvents
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
DropdownUser
.
prototype
,
'
bindEvents
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
DropdownUser
.
prototype
,
'
getProjectId
'
).
and
.
callFake
(()
=>
{});
spyOn
(
gl
.
DropdownUser
.
prototype
,
'
getProjectId
'
).
and
.
callFake
(()
=>
{});
...
@@ -45,13 +45,13 @@ require('~/filtered_search/dropdown_user');
...
@@ -45,13 +45,13 @@ require('~/filtered_search/dropdown_user');
};
};
const
dropdown
=
new
gl
.
DropdownUser
();
const
dropdown
=
new
gl
.
DropdownUser
();
expect
(
dropdown
.
config
.
droplab
AjaxFilter
.
endpoint
).
toBe
(
'
/autocomplete/users.json
'
);
expect
(
dropdown
.
config
.
AjaxFilter
.
endpoint
).
toBe
(
'
/autocomplete/users.json
'
);
});
});
it
(
'
should return endpoint when relative_url_root is undefined
'
,
()
=>
{
it
(
'
should return endpoint when relative_url_root is undefined
'
,
()
=>
{
const
dropdown
=
new
gl
.
DropdownUser
();
const
dropdown
=
new
gl
.
DropdownUser
();
expect
(
dropdown
.
config
.
droplab
AjaxFilter
.
endpoint
).
toBe
(
'
/autocomplete/users.json
'
);
expect
(
dropdown
.
config
.
AjaxFilter
.
endpoint
).
toBe
(
'
/autocomplete/users.json
'
);
});
});
it
(
'
should return endpoint with relative url when available
'
,
()
=>
{
it
(
'
should return endpoint with relative url when available
'
,
()
=>
{
...
@@ -60,7 +60,7 @@ require('~/filtered_search/dropdown_user');
...
@@ -60,7 +60,7 @@ require('~/filtered_search/dropdown_user');
};
};
const
dropdown
=
new
gl
.
DropdownUser
();
const
dropdown
=
new
gl
.
DropdownUser
();
expect
(
dropdown
.
config
.
droplab
AjaxFilter
.
endpoint
).
toBe
(
'
/gitlab_directory/autocomplete/users.json
'
);
expect
(
dropdown
.
config
.
AjaxFilter
.
endpoint
).
toBe
(
'
/gitlab_directory/autocomplete/users.json
'
);
});
});
afterEach
(()
=>
{
afterEach
(()
=>
{
...
...
yarn.lock
View file @
75ac2699
...
@@ -2905,8 +2905,8 @@ karma-webpack@^2.0.2:
...
@@ -2905,8 +2905,8 @@ karma-webpack@^2.0.2:
webpack-dev-middleware "^1.0.11"
webpack-dev-middleware "^1.0.11"
karma@^1.4.1:
karma@^1.4.1:
version "1.
5
.0"
version "1.
6
.0"
resolved "https://registry.yarnpkg.com/karma/-/karma-1.
5.0.tgz#9c4c14f0400bef2c04c8e8e6bff59371025cc009
"
resolved "https://registry.yarnpkg.com/karma/-/karma-1.
6.0.tgz#0e871d4527d5eac56c41d181f03c5c0a7e6dbf3e
"
dependencies:
dependencies:
bluebird "^3.3.0"
bluebird "^3.3.0"
body-parser "^1.16.1"
body-parser "^1.16.1"
...
@@ -2925,7 +2925,7 @@ karma@^1.4.1:
...
@@ -2925,7 +2925,7 @@ karma@^1.4.1:
lodash "^3.8.0"
lodash "^3.8.0"
log4js "^0.6.31"
log4js "^0.6.31"
mime "^1.3.4"
mime "^1.3.4"
minimatch "^3.0.
0
"
minimatch "^3.0.
2
"
optimist "^0.6.1"
optimist "^0.6.1"
qjobs "^1.1.4"
qjobs "^1.1.4"
range-parser "^1.2.0"
range-parser "^1.2.0"
...
@@ -3222,8 +3222,8 @@ mute-stream@0.0.5:
...
@@ -3222,8 +3222,8 @@ mute-stream@0.0.5:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
nan@^2.0.0, nan@^2.3.0:
nan@^2.0.0, nan@^2.3.0:
version "2.
5
.1"
version "2.
6
.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.
5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2
"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.
6.1.tgz#8c84f7b14c96b89f57fbc838012180ec8ca39a01
"
natural-compare@^1.4.0:
natural-compare@^1.4.0:
version "1.4.0"
version "1.4.0"
...
@@ -3773,7 +3773,7 @@ read-pkg@^1.0.0:
...
@@ -3773,7 +3773,7 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
normalize-package-data "^2.3.2"
path-type "^1.0.0"
path-type "^1.0.0"
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.
1, readable-stream@^2.0.2, readable-stream@^2.0.5
, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.
2
, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
version "2.2.6"
version "2.2.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816"
dependencies:
dependencies:
...
@@ -3785,16 +3785,7 @@ read-pkg@^1.0.0:
...
@@ -3785,16 +3785,7 @@ read-pkg@^1.0.0:
string_decoder "~0.10.x"
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
util-deprecate "~1.0.1"
readable-stream@~1.0.2:
readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@~2.0.0, readable-stream@~2.0.6:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@~2.0.0, readable-stream@~2.0.6:
version "2.0.6"
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
dependencies:
dependencies:
...
@@ -3805,6 +3796,15 @@ readable-stream@~2.0.0, readable-stream@~2.0.6:
...
@@ -3805,6 +3796,15 @@ readable-stream@~2.0.0, readable-stream@~2.0.6:
string_decoder "~0.10.x"
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
util-deprecate "~1.0.1"
readable-stream@~1.0.2:
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readdirp@^2.0.0:
readdirp@^2.0.0:
version "2.1.0"
version "2.1.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
...
...
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