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
2cad277d
Commit
2cad277d
authored
Sep 09, 2016
by
Ruben Davila
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into 8-12-stable
parents
e36534db
2b3a1da6
Changes
89
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
89 changed files
with
952 additions
and
139 deletions
+952
-139
app/assets/javascripts/LabelManager.js
app/assets/javascripts/LabelManager.js
+5
-0
app/assets/javascripts/api.js
app/assets/javascripts/api.js
+6
-0
app/assets/javascripts/application.js
app/assets/javascripts/application.js
+21
-0
app/assets/javascripts/autosave.js
app/assets/javascripts/autosave.js
+3
-3
app/assets/javascripts/awards_handler.js
app/assets/javascripts/awards_handler.js
+5
-0
app/assets/javascripts/behaviors/autosize.js
app/assets/javascripts/behaviors/autosize.js
+0
-2
app/assets/javascripts/behaviors/details_behavior.js
app/assets/javascripts/behaviors/details_behavior.js
+6
-0
app/assets/javascripts/behaviors/quick_submit.js
app/assets/javascripts/behaviors/quick_submit.js
+19
-1
app/assets/javascripts/behaviors/requires_input.js
app/assets/javascripts/behaviors/requires_input.js
+18
-1
app/assets/javascripts/behaviors/toggler_behavior.js
app/assets/javascripts/behaviors/toggler_behavior.js
+7
-0
app/assets/javascripts/blob/blob_file_dropzone.js
app/assets/javascripts/blob/blob_file_dropzone.js
+3
-0
app/assets/javascripts/blob/template_selector.js
app/assets/javascripts/blob/template_selector.js
+3
-0
app/assets/javascripts/blob_edit/edit_blob.js
app/assets/javascripts/blob_edit/edit_blob.js
+2
-0
app/assets/javascripts/breakpoints.js
app/assets/javascripts/breakpoints.js
+2
-0
app/assets/javascripts/build.js
app/assets/javascripts/build.js
+8
-0
app/assets/javascripts/commit/image-file.js
app/assets/javascripts/commit/image-file.js
+2
-0
app/assets/javascripts/commits.js
app/assets/javascripts/commits.js
+1
-0
app/assets/javascripts/copy_to_clipboard.js
app/assets/javascripts/copy_to_clipboard.js
+6
-1
app/assets/javascripts/diff.js
app/assets/javascripts/diff.js
+3
-0
app/assets/javascripts/dispatcher.js
app/assets/javascripts/dispatcher.js
+4
-0
app/assets/javascripts/due_date_select.js
app/assets/javascripts/due_date_select.js
+3
-0
app/assets/javascripts/extensions/jquery.js
app/assets/javascripts/extensions/jquery.js
+2
-0
app/assets/javascripts/gfm_auto_complete.js.es6
app/assets/javascripts/gfm_auto_complete.js.es6
+24
-0
app/assets/javascripts/gl_dropdown.js
app/assets/javascripts/gl_dropdown.js
+64
-0
app/assets/javascripts/gl_form.js
app/assets/javascripts/gl_form.js
+6
-0
app/assets/javascripts/graphs/graphs_bundle.js
app/assets/javascripts/graphs/graphs_bundle.js
+6
-2
app/assets/javascripts/graphs/stat_graph_contributors_graph.js
...ssets/javascripts/graphs/stat_graph_contributors_graph.js
+1
-0
app/assets/javascripts/groups_select.js
app/assets/javascripts/groups_select.js
+1
-0
app/assets/javascripts/issuable.js.es6
app/assets/javascripts/issuable.js.es6
+2
-0
app/assets/javascripts/issue.js
app/assets/javascripts/issue.js
+5
-4
app/assets/javascripts/issues-bulk-assignment.js
app/assets/javascripts/issues-bulk-assignment.js
+6
-0
app/assets/javascripts/labels.js
app/assets/javascripts/labels.js
+3
-0
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+9
-0
app/assets/javascripts/lib/chart.js
app/assets/javascripts/lib/chart.js
+0
-1
app/assets/javascripts/lib/cropper.js
app/assets/javascripts/lib/cropper.js
+0
-1
app/assets/javascripts/lib/d3.js
app/assets/javascripts/lib/d3.js
+0
-1
app/assets/javascripts/lib/raphael.js
app/assets/javascripts/lib/raphael.js
+0
-5
app/assets/javascripts/lib/utils/datetime_utility.js
app/assets/javascripts/lib/utils/datetime_utility.js
+1
-0
app/assets/javascripts/lib/utils/emoji_aliases.js.coffee.erb
app/assets/javascripts/lib/utils/emoji_aliases.js.coffee.erb
+0
-2
app/assets/javascripts/lib/utils/emoji_aliases.js.erb
app/assets/javascripts/lib/utils/emoji_aliases.js.erb
+6
-0
app/assets/javascripts/lib/utils/notify.js
app/assets/javascripts/lib/utils/notify.js
+5
-0
app/assets/javascripts/lib/utils/text_utility.js
app/assets/javascripts/lib/utils/text_utility.js
+3
-2
app/assets/javascripts/lib/utils/url_utility.js
app/assets/javascripts/lib/utils/url_utility.js
+6
-0
app/assets/javascripts/line_highlighter.js
app/assets/javascripts/line_highlighter.js
+68
-1
app/assets/javascripts/merge_request.js
app/assets/javascripts/merge_request.js
+11
-4
app/assets/javascripts/merge_request_tabs.js
app/assets/javascripts/merge_request_tabs.js
+83
-1
app/assets/javascripts/merge_request_widget.js
app/assets/javascripts/merge_request_widget.js
+8
-0
app/assets/javascripts/milestone.js
app/assets/javascripts/milestone.js
+1
-0
app/assets/javascripts/milestone_select.js
app/assets/javascripts/milestone_select.js
+1
-0
app/assets/javascripts/network/branch-graph.js
app/assets/javascripts/network/branch-graph.js
+13
-0
app/assets/javascripts/network/network_bundle.js
app/assets/javascripts/network/network_bundle.js
+6
-1
app/assets/javascripts/notes.js
app/assets/javascripts/notes.js
+62
-12
app/assets/javascripts/preview_markdown.js
app/assets/javascripts/preview_markdown.js
+10
-0
app/assets/javascripts/profile/gl_crop.js
app/assets/javascripts/profile/gl_crop.js
+10
-2
app/assets/javascripts/profile/profile.js
app/assets/javascripts/profile/profile.js
+4
-0
app/assets/javascripts/profile/profile_bundle.js
app/assets/javascripts/profile/profile_bundle.js
+0
-1
app/assets/javascripts/project.js
app/assets/javascripts/project.js
+6
-0
app/assets/javascripts/project_find_file.js
app/assets/javascripts/project_find_file.js
+9
-0
app/assets/javascripts/project_show.js
app/assets/javascripts/project_show.js
+2
-0
app/assets/javascripts/projects_list.js
app/assets/javascripts/projects_list.js
+1
-0
app/assets/javascripts/protected_branch_dropdown.js.es6
app/assets/javascripts/protected_branch_dropdown.js.es6
+1
-0
app/assets/javascripts/search_autocomplete.js
app/assets/javascripts/search_autocomplete.js
+22
-0
app/assets/javascripts/shortcuts.js
app/assets/javascripts/shortcuts.js
+1
-0
app/assets/javascripts/shortcuts_find_file.js
app/assets/javascripts/shortcuts_find_file.js
+2
-0
app/assets/javascripts/shortcuts_issuable.js
app/assets/javascripts/shortcuts_issuable.js
+4
-2
app/assets/javascripts/syntax_highlight.js
app/assets/javascripts/syntax_highlight.js
+11
-0
app/assets/javascripts/todos.js
app/assets/javascripts/todos.js
+6
-0
app/assets/javascripts/tree.js
app/assets/javascripts/tree.js
+3
-0
app/assets/javascripts/u2f/authenticate.js
app/assets/javascripts/u2f/authenticate.js
+18
-0
app/assets/javascripts/u2f/register.js
app/assets/javascripts/u2f/register.js
+7
-0
app/assets/javascripts/user_tabs.js
app/assets/javascripts/user_tabs.js
+69
-0
app/assets/javascripts/users/calendar.js
app/assets/javascripts/users/calendar.js
+7
-0
app/assets/javascripts/users/users_bundle.js
app/assets/javascripts/users/users_bundle.js
+0
-1
app/assets/javascripts/users_select.js
app/assets/javascripts/users_select.js
+8
-0
app/assets/javascripts/zen_mode.js
app/assets/javascripts/zen_mode.js
+26
-11
spec/javascripts/awards_handler_spec.js
spec/javascripts/awards_handler_spec.js
+1
-6
spec/javascripts/behaviors/quick_submit_spec.js
spec/javascripts/behaviors/quick_submit_spec.js
+3
-0
spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
.../javascripts/graphs/stat_graph_contributors_graph_spec.js
+4
-4
spec/javascripts/issue_spec.js
spec/javascripts/issue_spec.js
+0
-2
spec/javascripts/new_branch_spec.js
spec/javascripts/new_branch_spec.js
+0
-2
spec/javascripts/project_title_spec.js
spec/javascripts/project_title_spec.js
+0
-12
spec/javascripts/right_sidebar_spec.js
spec/javascripts/right_sidebar_spec.js
+0
-4
spec/javascripts/search_autocomplete_spec.js
spec/javascripts/search_autocomplete_spec.js
+4
-10
spec/javascripts/shortcuts_issuable_spec.js
spec/javascripts/shortcuts_issuable_spec.js
+1
-0
spec/javascripts/spec_helper.js
spec/javascripts/spec_helper.js
+29
-9
spec/javascripts/u2f/authenticate_spec.js
spec/javascripts/u2f/authenticate_spec.js
+0
-8
spec/javascripts/u2f/register_spec.js
spec/javascripts/u2f/register_spec.js
+0
-8
spec/javascripts/zen_mode_spec.js
spec/javascripts/zen_mode_spec.js
+3
-1
vendor/assets/javascripts/task_list.js
vendor/assets/javascripts/task_list.js
+150
-11
No files found.
app/assets/javascripts/LabelManager.js
View file @
2cad277d
...
...
@@ -3,6 +3,7 @@
LabelManager
.
prototype
.
errorMessage
=
'
Unable to update label prioritization at this time
'
;
function
LabelManager
(
opts
)
{
// Defaults
var
ref
,
ref1
,
ref2
;
if
(
opts
==
null
)
{
opts
=
{};
...
...
@@ -28,6 +29,7 @@
$btn
=
$
(
e
.
currentTarget
);
$label
=
$
(
"
#
"
+
(
$btn
.
data
(
'
domId
'
)));
action
=
$btn
.
parents
(
'
.js-prioritized-labels
'
).
length
?
'
remove
'
:
'
add
'
;
// Make sure tooltip will hide
$tooltip
=
$
(
"
#
"
+
(
$btn
.
find
(
'
.has-tooltip:visible
'
).
attr
(
'
aria-describedby
'
)));
$tooltip
.
tooltip
(
'
destroy
'
);
return
_this
.
toggleLabelPriority
(
$label
,
action
);
...
...
@@ -42,6 +44,7 @@
url
=
$label
.
find
(
'
.js-toggle-priority
'
).
data
(
'
url
'
);
$target
=
this
.
prioritizedLabels
;
$from
=
this
.
otherLabels
;
// Optimistic update
if
(
action
===
'
remove
'
)
{
$target
=
this
.
otherLabels
;
$from
=
this
.
prioritizedLabels
;
...
...
@@ -53,6 +56,7 @@
$target
.
find
(
'
.empty-message
'
).
addClass
(
'
hidden
'
);
}
$label
.
detach
().
appendTo
(
$target
);
// Return if we are not persisting state
if
(
!
persistState
)
{
return
;
}
...
...
@@ -61,6 +65,7 @@
url
:
url
,
type
:
'
DELETE
'
});
// Restore empty message
if
(
!
$from
.
find
(
'
li
'
).
length
)
{
$from
.
find
(
'
.empty-message
'
).
removeClass
(
'
hidden
'
);
}
...
...
app/assets/javascripts/api.js
View file @
2cad277d
...
...
@@ -24,6 +24,8 @@
return
callback
(
group
);
});
},
// Return groups list. Filtered by query
// Only active groups retrieved
groups
:
function
(
query
,
skip_ldap
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
groupsPath
);
return
$
.
ajax
({
...
...
@@ -38,6 +40,7 @@
return
callback
(
groups
);
});
},
// Return namespaces list. Filtered by query
namespaces
:
function
(
query
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
namespacesPath
);
return
$
.
ajax
({
...
...
@@ -52,6 +55,7 @@
return
callback
(
namespaces
);
});
},
// Return projects list. Filtered by query
projects
:
function
(
query
,
order
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
projectsPath
);
return
$
.
ajax
({
...
...
@@ -82,6 +86,7 @@
return
callback
(
message
.
responseJSON
);
});
},
// Return group projects list. Filtered by query
groupProjects
:
function
(
group_id
,
query
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
groupProjectsPath
)
.
replace
(
'
:id
'
,
group_id
);
...
...
@@ -97,6 +102,7 @@
return
callback
(
projects
);
});
},
// Return text for a specific license
licenseText
:
function
(
key
,
data
,
callback
)
{
var
url
=
Api
.
buildUrl
(
Api
.
licensePath
)
.
replace
(
'
:key
'
,
key
);
...
...
app/assets/javascripts/application.js
View file @
2cad277d
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require jquery2 */
/*= require jquery-ui/autocomplete */
/*= require jquery-ui/datepicker */
...
...
@@ -76,6 +82,7 @@
}
};
// Disable button if text field is empty
window
.
disableButtonIfEmptyField
=
function
(
field_selector
,
button_selector
)
{
var
closest_submit
,
field
;
field
=
$
(
field_selector
);
...
...
@@ -92,6 +99,7 @@
});
};
// Disable button if any input field with given selector is empty
window
.
disableButtonIfAnyEmptyField
=
function
(
form
,
form_selector
,
button_selector
)
{
var
closest_submit
,
updateButtons
;
closest_submit
=
form
.
find
(
button_selector
);
...
...
@@ -128,6 +136,8 @@
window
.
addEventListener
(
"
hashchange
"
,
shiftWindow
);
window
.
onload
=
function
()
{
// Scroll the window to avoid the topnav bar
// https://github.com/twitter/bootstrap/issues/1768
if
(
location
.
hash
)
{
return
setTimeout
(
shiftWindow
,
100
);
}
...
...
@@ -149,6 +159,8 @@
return
$
(
this
).
select
().
one
(
'
mouseup
'
,
function
(
e
)
{
return
e
.
preventDefault
();
});
// Click a .js-select-on-focus field, select the contents
// Prevent a mouseup event from deselecting the input
});
$
(
'
.remove-row
'
).
bind
(
'
ajax:success
'
,
function
()
{
$
(
this
).
tooltip
(
'
destroy
'
)
...
...
@@ -163,6 +175,7 @@
});
$
(
'
select.select2
'
).
select2
({
width
:
'
resolve
'
,
// Initialize select2 selects
dropdownAutoWidth
:
true
});
$
(
'
.js-select2
'
).
bind
(
'
select2-close
'
,
function
()
{
...
...
@@ -170,7 +183,9 @@
$
(
'
.select2-container-active
'
).
removeClass
(
'
select2-container-active
'
);
return
$
(
'
:focus
'
).
blur
();
}),
1
);
// Close select2 on escape
});
// Initialize tooltips
$body
.
tooltip
({
selector
:
'
.has-tooltip, [data-toggle="tooltip"]
'
,
placement
:
function
(
_
,
el
)
{
...
...
@@ -179,14 +194,17 @@
});
$
(
'
.trigger-submit
'
).
on
(
'
change
'
,
function
()
{
return
$
(
this
).
parents
(
'
form
'
).
submit
();
// Form submitter
});
gl
.
utils
.
localTimeAgo
(
$
(
'
abbr.timeago, .js-timeago
'
),
true
);
// Flash
if
((
flash
=
$
(
"
.flash-container
"
)).
length
>
0
)
{
flash
.
click
(
function
()
{
return
$
(
this
).
fadeOut
();
});
flash
.
show
();
}
// Disable form buttons while a form is submitting
$body
.
on
(
'
ajax:complete, ajax:beforeSend, submit
'
,
'
form
'
,
function
(
e
)
{
var
buttons
;
buttons
=
$
(
'
[type="submit"]
'
,
this
);
...
...
@@ -207,6 +225,7 @@
}
});
$
(
'
.account-box
'
).
hover
(
function
()
{
// Show/Hide the profile menu when hovering the account box
return
$
(
this
).
toggleClass
(
'
hover
'
);
});
$document
.
on
(
'
click
'
,
'
.diff-content .js-show-suppressed-diff
'
,
function
()
{
...
...
@@ -214,6 +233,7 @@
$container
=
$
(
this
).
parent
();
$container
.
next
(
'
table
'
).
show
();
return
$container
.
remove
();
// Commit show suppressed diff
});
$
(
'
.navbar-toggle
'
).
on
(
'
click
'
,
function
()
{
$
(
'
.header-content .title
'
).
toggle
();
...
...
@@ -221,6 +241,7 @@
$
(
'
.header-content .navbar-collapse
'
).
toggle
();
return
$
(
'
.navbar-toggle
'
).
toggleClass
(
'
active
'
);
});
// Show/hide comments on diff
$body
.
on
(
"
click
"
,
"
.js-toggle-diff-comments
"
,
function
(
e
)
{
var
$this
=
$
(
this
);
$this
.
toggleClass
(
'
active
'
);
...
...
app/assets/javascripts/autosave.js
View file @
2cad277d
...
...
@@ -16,7 +16,7 @@
}
Autosave
.
prototype
.
restore
=
function
()
{
var
e
,
error
,
text
;
var
e
,
text
;
if
(
window
.
localStorage
==
null
)
{
return
;
}
...
...
@@ -41,7 +41,7 @@
if
((
text
!=
null
?
text
.
length
:
void
0
)
>
0
)
{
try
{
return
window
.
localStorage
.
setItem
(
this
.
key
,
text
);
}
catch
(
undefined
)
{}
}
catch
(
error
)
{}
}
else
{
return
this
.
reset
();
}
...
...
@@ -53,7 +53,7 @@
}
try
{
return
window
.
localStorage
.
removeItem
(
this
.
key
);
}
catch
(
undefined
)
{}
}
catch
(
error
)
{}
};
return
Autosave
;
...
...
app/assets/javascripts/awards_handler.js
View file @
2cad277d
...
...
@@ -86,6 +86,8 @@
AwardsHandler
.
prototype
.
positionMenu
=
function
(
$menu
,
$addBtn
)
{
var
css
,
position
;
position
=
$addBtn
.
data
(
'
position
'
);
// The menu could potentially be off-screen or in a hidden overflow element
// So we position the element absolute in the body
css
=
{
top
:
(
$addBtn
.
offset
().
top
+
$addBtn
.
outerHeight
())
+
"
px
"
};
...
...
@@ -284,6 +286,7 @@
if
(
emojiIcon
.
length
>
0
)
{
unicodeName
=
emojiIcon
.
data
(
'
unicode-name
'
);
}
else
{
// Find by alias
unicodeName
=
$
(
"
.emoji-menu-content [data-aliases*=':
"
+
emoji
+
"
:']
"
).
data
(
'
unicode-name
'
);
}
return
"
emoji-
"
+
unicodeName
;
...
...
@@ -350,8 +353,10 @@
return
function
(
ev
)
{
var
found_emojis
,
h5
,
term
,
ul
;
term
=
$
(
ev
.
target
).
val
();
// Clean previous search results
$
(
'
ul.emoji-menu-search, h5.emoji-search
'
).
remove
();
if
(
term
)
{
// Generate a search result block
h5
=
$
(
'
<h5>
'
).
text
(
'
Search results
'
);
found_emojis
=
_this
.
searchEmojis
(
term
).
show
();
ul
=
$
(
'
<ul>
'
).
addClass
(
'
emoji-menu-list emoji-menu-search
'
).
append
(
found_emojis
);
...
...
app/assets/javascripts/behaviors/autosize.js
View file @
2cad277d
/*= require jquery.ba-resize */
/*= require autosize */
(
function
()
{
...
...
app/assets/javascripts/behaviors/details_behavior.js
View file @
2cad277d
...
...
@@ -5,6 +5,12 @@
container
=
$
(
this
).
closest
(
"
.js-details-container
"
);
return
container
.
toggleClass
(
"
open
"
);
});
// Show details content. Hides link after click.
//
// %div
// %a.js-details-expand
// %div.js-details-content
//
return
$
(
"
body
"
).
on
(
"
click
"
,
"
.js-details-expand
"
,
function
(
e
)
{
$
(
this
).
next
(
'
.js-details-content
'
).
removeClass
(
"
hide
"
);
$
(
this
).
hide
();
...
...
app/assets/javascripts/behaviors/quick_submit.js
View file @
2cad277d
// Quick Submit behavior
//
// When a child field of a form with a `js-quick-submit` class receives a
// "Meta+Enter" (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, the form
// is submitted.
//
/*= require extensions/jquery */
//
// ### Example Markup
//
// <form action="/foo" class="js-quick-submit">
// <input type="text" />
// <textarea></textarea>
// <input type="submit" value="Submit" />
// </form>
//
(
function
()
{
var
isMac
,
keyCodeIs
;
...
...
@@ -17,6 +31,7 @@
$
(
document
).
on
(
'
keydown.quick_submit
'
,
'
.js-quick-submit
'
,
function
(
e
)
{
var
$form
,
$submit_button
;
// Enter
if
(
!
keyCodeIs
(
e
,
13
))
{
return
;
}
...
...
@@ -33,8 +48,11 @@
return
$form
.
submit
();
});
// If the user tabs to a submit button on a `js-quick-submit` form, display a
// tooltip to let them know they could've used the hotkey
$
(
document
).
on
(
'
keyup.quick_submit
'
,
'
.js-quick-submit input[type=submit], .js-quick-submit button[type=submit]
'
,
function
(
e
)
{
var
$this
,
title
;
// Tab
if
(
!
keyCodeIs
(
e
,
9
))
{
return
;
}
...
...
app/assets/javascripts/behaviors/requires_input.js
View file @
2cad277d
// Requires Input behavior
//
// When called on a form with input fields with the `required` attribute, the
// form's submit button will be disabled until all required fields have values.
//
/*= require extensions/jquery */
//
// ### Example Markup
//
// <form class="js-requires-input">
// <input type="text" required="required">
// <input type="submit" value="Submit">
// </form>
//
(
function
()
{
$
.
fn
.
requiresInput
=
function
()
{
var
$button
,
$form
,
fieldSelector
,
requireInput
,
required
;
...
...
@@ -11,14 +23,17 @@
requireInput
=
function
()
{
var
values
;
values
=
_
.
map
(
$
(
fieldSelector
,
$form
),
function
(
field
)
{
// Collect the input values of *all* required fields
return
field
.
value
;
});
// Disable the button if any required fields are empty
if
(
values
.
length
&&
_
.
any
(
values
,
_
.
isEmpty
))
{
return
$button
.
disable
();
}
else
{
return
$button
.
enable
();
}
};
// Set initial button state
requireInput
();
return
$form
.
on
(
'
change input
'
,
fieldSelector
,
requireInput
);
};
...
...
@@ -27,6 +42,8 @@
var
$form
,
hideOrShowHelpBlock
;
$form
=
$
(
'
form.js-requires-input
'
);
$form
.
requiresInput
();
// Hide or Show the help block when creating a new project
// based on the option selected
hideOrShowHelpBlock
=
function
(
form
)
{
var
selected
;
selected
=
$
(
'
.js-select-namespace option:selected
'
);
...
...
app/assets/javascripts/behaviors/toggler_behavior.js
View file @
2cad277d
(
function
(
w
)
{
$
(
function
()
{
// Toggle button. Show/hide content inside parent container.
// Button does not change visibility. If button has icon - it changes chevron style.
//
// %div.js-toggle-container
// %a.js-toggle-button
// %div.js-toggle-content
//
$
(
'
body
'
).
on
(
'
click
'
,
'
.js-toggle-button
'
,
function
(
e
)
{
e
.
preventDefault
();
$
(
this
)
...
...
app/assets/javascripts/blob/blob_file_dropzone.js
View file @
2cad277d
...
...
@@ -8,6 +8,8 @@
autoDiscover
:
false
,
autoProcessQueue
:
false
,
url
:
form
.
attr
(
'
action
'
),
// Rails uses a hidden input field for PUT
// http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
method
:
method
,
clickable
:
true
,
uploadMultiple
:
false
,
...
...
@@ -36,6 +38,7 @@
formData
.
append
(
'
commit_message
'
,
form
.
find
(
'
.js-commit-message
'
).
val
());
});
},
// Override behavior of adding error underneath preview
error
:
function
(
file
,
errorMessage
)
{
var
stripped
;
stripped
=
$
(
"
<div/>
"
).
html
(
errorMessage
).
text
();
...
...
app/assets/javascripts/blob/template_selector.js
View file @
2cad277d
...
...
@@ -66,6 +66,9 @@
// be added by all subclasses.
};
// To be implemented on the extending class
// e.g.
// Api.gitignoreText item.name, @requestFileSuccess.bind(@)
TemplateSelector
.
prototype
.
requestFileSuccess
=
function
(
file
,
skipFocus
)
{
this
.
editor
.
setValue
(
file
.
content
,
1
);
if
(
!
skipFocus
)
this
.
editor
.
focus
();
...
...
app/assets/javascripts/blob_edit/edit_blob.js
View file @
2cad277d
...
...
@@ -18,6 +18,8 @@
return
function
()
{
return
$
(
"
#file-content
"
).
val
(
_this
.
editor
.
getValue
());
};
// Before a form submission, move the content from the Ace editor into the
// submitted textarea
})(
this
));
this
.
initModePanesAndLinks
();
new
BlobLicenseSelectors
({
...
...
app/assets/javascripts/breakpoints.js
View file @
2cad277d
...
...
@@ -23,6 +23,7 @@
if
(
$
(
allDeviceSelector
.
join
(
"
,
"
)).
length
)
{
return
;
}
// Create all the elements
els
=
$
.
map
(
BREAKPOINTS
,
function
(
breakpoint
)
{
return
"
<div class='device-
"
+
breakpoint
+
"
visible-
"
+
breakpoint
+
"
'></div>
"
;
});
...
...
@@ -40,6 +41,7 @@
BreakpointInstance
.
prototype
.
getBreakpointSize
=
function
()
{
var
$visibleDevice
;
$visibleDevice
=
this
.
visibleDevice
;
// the page refreshed via turbolinks
if
(
!
$visibleDevice
().
length
)
{
this
.
setup
();
}
...
...
app/assets/javascripts/build.js
View file @
2cad277d
...
...
@@ -16,6 +16,7 @@
this
.
toggleSidebar
=
bind
(
this
.
toggleSidebar
,
this
);
this
.
updateDropdown
=
bind
(
this
.
updateDropdown
,
this
);
clearInterval
(
Build
.
interval
);
// Init breakpoint checker
this
.
bp
=
Breakpoints
.
get
();
$
(
'
.js-build-sidebar
'
).
niceScroll
();
...
...
@@ -42,6 +43,9 @@
$
(
this
).
data
(
"
state
"
,
"
enabled
"
);
return
$
(
this
).
text
(
"
disable autoscroll
"
);
}
//
// Bind autoscroll button to follow build output
//
});
Build
.
interval
=
setInterval
((
function
(
_this
)
{
return
function
()
{
...
...
@@ -49,6 +53,10 @@
return
_this
.
getBuildTrace
();
}
};
//
// Check for new build output if user still watching build page
// Only valid for runnig build when output changes during time
//
})(
this
),
4000
);
}
}
...
...
app/assets/javascripts/commit/image-file.js
View file @
2cad277d
...
...
@@ -2,6 +2,7 @@
this
.
ImageFile
=
(
function
()
{
var
prepareFrames
;
// Width where images must fits in, for 2-up this gets divided by 2
ImageFile
.
availWidth
=
900
;
ImageFile
.
viewModes
=
[
'
two-up
'
,
'
swipe
'
];
...
...
@@ -9,6 +10,7 @@
function
ImageFile
(
file
)
{
this
.
file
=
file
;
this
.
requestImageInfo
(
$
(
'
.two-up.view .frame.deleted img
'
,
this
.
file
),
(
function
(
_this
)
{
// Determine if old and new file has same dimensions, if not show 'two-up' view
return
function
(
deletedWidth
,
deletedHeight
)
{
return
_this
.
requestImageInfo
(
$
(
'
.two-up.view .frame.added img
'
,
_this
.
file
),
function
(
width
,
height
)
{
if
(
width
===
deletedWidth
&&
height
===
deletedHeight
)
{
...
...
app/assets/javascripts/commits.js
View file @
2cad277d
...
...
@@ -45,6 +45,7 @@
CommitsList
.
content
.
html
(
data
.
html
);
return
history
.
replaceState
({
page
:
commitsUrl
// Change url so if user reload a page - search results are saved
},
document
.
title
,
commitsUrl
);
},
dataType
:
"
json
"
...
...
app/assets/javascripts/copy_to_clipboard.js
View file @
2cad277d
...
...
@@ -6,14 +6,19 @@
genericSuccess
=
function
(
e
)
{
showTooltip
(
e
.
trigger
,
'
Copied!
'
);
// Clear the selection and blur the trigger so it loses its border
e
.
clearSelection
();
return
$
(
e
.
trigger
).
blur
();
};
// Safari doesn't support `execCommand`, so instead we inform the user to
// copy manually.
//
// See http://clipboardjs.com/#browser-support
genericError
=
function
(
e
)
{
var
key
;
if
(
/Mac/i
.
test
(
navigator
.
userAgent
))
{
key
=
'
⌘
'
;
key
=
'
⌘
'
;
// Command
}
else
{
key
=
'
Ctrl
'
;
}
...
...
app/assets/javascripts/diff.js
View file @
2cad277d
...
...
@@ -39,6 +39,9 @@
bottom
:
unfoldBottom
,
offset
:
offset
,
unfold
:
unfold
,
// indent is used to compensate for single space indent to fit
// '+' and '-' prepended to diff lines,
// see https://gitlab.com/gitlab-org/gitlab-ce/issues/707
indent
:
1
,
view
:
file
.
data
(
'
view
'
)
};
...
...
app/assets/javascripts/dispatcher.js
View file @
2cad277d
...
...
@@ -164,6 +164,8 @@
}
break
;
case
'
projects:network:show
'
:
// Ensure we don't create a particular shortcut handler here. This is
// already created, where the network graph is created.
shortcut_handler
=
true
;
break
;
case
'
projects:forks:new
'
:
...
...
@@ -260,12 +262,14 @@
shortcut_handler
=
new
ShortcutsNavigation
();
}
}
// If we haven't installed a custom shortcut handler, install the default one
if
(
!
shortcut_handler
)
{
return
new
Shortcuts
();
}
};
Dispatcher
.
prototype
.
initSearch
=
function
()
{
// Only when search form is present
if
(
$
(
'
.search
'
).
length
)
{
return
new
SearchAutocomplete
();
}
...
...
app/assets/javascripts/due_date_select.js
View file @
2cad277d
...
...
@@ -2,6 +2,7 @@
this
.
DueDateSelect
=
(
function
()
{
function
DueDateSelect
()
{
var
$datePicker
,
$dueDate
,
$loading
;
// Milestone edit/new form
$datePicker
=
$
(
'
.datepicker
'
);
if
(
$datePicker
.
length
)
{
$dueDate
=
$
(
'
#milestone_due_date
'
);
...
...
@@ -16,6 +17,7 @@
e
.
preventDefault
();
return
$
.
datepicker
.
_clearDate
(
$datePicker
);
});
// Issuable sidebar
$loading
=
$
(
'
.js-issuable-update .due_date
'
).
find
(
'
.block-loading
'
).
hide
();
$
(
'
.js-due-date-select
'
).
each
(
function
(
i
,
dropdown
)
{
var
$block
,
$dropdown
,
$dropdownParent
,
$selectbox
,
$sidebarValue
,
$value
,
$valueContent
,
abilityName
,
addDueDate
,
fieldName
,
issueUpdateURL
;
...
...
@@ -38,6 +40,7 @@
});
addDueDate
=
function
(
isDropdown
)
{
var
data
,
date
,
mediumDate
,
value
;
// Create the post date
value
=
$
(
"
input[name='
"
+
fieldName
+
"
']
"
).
val
();
if
(
value
!==
''
)
{
date
=
new
Date
(
value
.
replace
(
new
RegExp
(
'
-
'
,
'
g
'
),
'
,
'
));
...
...
app/assets/javascripts/extensions/jquery.js
View file @
2cad277d
// Disable an element and add the 'disabled' Bootstrap class
(
function
()
{
$
.
fn
.
extend
({
disable
:
function
()
{
...
...
@@ -5,6 +6,7 @@
}
});
// Enable an element and remove the 'disabled' Bootstrap class
$
.
fn
.
extend
({
enable
:
function
()
{
return
$
(
this
).
removeAttr
(
'
disabled
'
).
removeClass
(
'
disabled
'
);
...
...
app/assets/javascripts/gfm_auto_complete.js.es6
View file @
2cad277d
// Creates the variables for setting up GFM auto-completion
(function() {
if (window.GitLab == null) {
window.GitLab = {};
...
...
@@ -8,18 +9,22 @@
dataLoaded: false,
cachedData: {},
dataSource: '',
// Emoji
Emoji: {
template: '<li>${name} <img alt="${name}" height="20" src="${path}" width="20" /></li>'
},
// Team Members
Members: {
template: '<li>${username} <small>${title}</small></li>'
},
Labels: {
template: '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>'
},
// Issues and MergeRequests
Issues: {
template: '<li><small>${id}</small> ${title}</li>'
},
// Milestones
Milestones: {
template: '<li>${title}</li>'
},
...
...
@@ -48,8 +53,11 @@
}
},
setup: function(input) {
// Add GFM auto-completion to all input fields, that accept GFM input.
this.input = input || $('.js-gfm-input');
// destroy previous instances
this.destroyAtWho();
// set up instances
this.setupAtWho();
if (this.dataSource) {
if (!this.dataLoading && !this.cachedData) {
...
...
@@ -63,6 +71,11 @@
return _this.loadData(data);
});
};
// We should wait until initializations are done
// and only trigger the last .setup since
// The previous .dataSource belongs to the previous issuable
// and the last one will have the **proper** .dataSource property
// TODO: Make this a singleton and turn off events when moving to another page
})(this), 1000);
}
if (this.cachedData != null) {
...
...
@@ -71,6 +84,7 @@
}
},
setupAtWho: function() {
// Emoji
this.input.atwho({
at: ':',
displayTpl: (function(_this) {
...
...
@@ -90,6 +104,7 @@
beforeInsert: this.DefaultOptions.beforeInsert
}
});
// Team Members
this.input.atwho({
at: '@',
displayTpl: (function(_this) {
...
...
@@ -321,13 +336,22 @@
loadData: function(data) {
this.cachedData = data;
this.dataLoaded = true;
// load members
this.input.atwho('load', '@', data.members);
// load issues
this.input.atwho('load', 'issues', data.issues);
// load milestones
this.input.atwho('load', 'milestones', data.milestones);
// load merge requests
this.input.atwho('load', 'mergerequests', data.mergerequests);
// load emojis
this.input.atwho('load', ':', data.emojis);
// load labels
this.input.atwho('load', '~', data.labels);
// load commands
this.input.atwho('load', '/', data.commands);
// This trigger at.js again
// otherwise we would be stuck with loading until the user types
return $(':focus').trigger('keyup');
}
};
...
...
app/assets/javascripts/gl_dropdown.js
View file @
2cad277d
This diff is collapsed.
Click to expand it.
app/assets/javascripts/gl_form.js
View file @
2cad277d
...
...
@@ -3,12 +3,15 @@
function
GLForm
(
form
)
{
this
.
form
=
form
;
this
.
textarea
=
this
.
form
.
find
(
'
textarea.js-gfm-input
'
);
// Before we start, we should clean up any previous data for this form
this
.
destroy
();
// Setup the form
this
.
setupForm
();
this
.
form
.
data
(
'
gl-form
'
,
this
);
}
GLForm
.
prototype
.
destroy
=
function
()
{
// Clean form listeners
this
.
clearEventListeners
();
return
this
.
form
.
data
(
'
gl-form
'
,
null
);
};
...
...
@@ -21,12 +24,15 @@
this
.
form
.
find
(
'
.div-dropzone
'
).
remove
();
this
.
form
.
addClass
(
'
gfm-form
'
);
disableButtonIfEmptyField
(
this
.
form
.
find
(
'
.js-note-text
'
),
this
.
form
.
find
(
'
.js-comment-button
'
));
// remove notify commit author checkbox for non-commit notes
GitLab
.
GfmAutoComplete
.
setup
(
this
.
form
.
find
(
'
.js-gfm-input
'
));
new
DropzoneInput
(
this
.
form
);
autosize
(
this
.
textarea
);
// form and textarea event listeners
this
.
addEventListeners
();
gl
.
text
.
init
(
this
.
form
);
}
// hide discard button
this
.
form
.
find
(
'
.js-note-discard
'
).
hide
();
return
this
.
form
.
show
();
};
...
...
app/assets/javascripts/graphs/graphs_bundle.js
View file @
2cad277d
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require_tree . */
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/graphs/stat_graph_contributors_graph.js
View file @
2cad277d
...
...
@@ -204,6 +204,7 @@
function
ContributorsAuthorGraph
(
data1
)
{
this
.
data
=
data1
;
// Don't split graph size in half for mobile devices.
if
(
$
(
window
).
width
()
<
768
)
{
this
.
width
=
$
(
'
.content
'
).
width
()
-
80
;
}
else
{
...
...
app/assets/javascripts/groups_select.js
View file @
2cad277d
...
...
@@ -38,6 +38,7 @@
return
_this
.
formatSelection
.
apply
(
_this
,
args
);
},
dropdownCssClass
:
"
ajax-groups-dropdown
"
,
// we do not want to escape markup since we are displaying html in results
escapeMarkup
:
function
(
m
)
{
return
m
;
}
...
...
app/assets/javascripts/issuable.js.es6
View file @
2cad277d
...
...
@@ -38,9 +38,11 @@
return $(document).off('click', '.js-label-filter-remove').on('click', '.js-label-filter-remove', function(e) {
var $button;
$button = $(this);
// Remove the label input box
$('input[name="label_name[]"]').filter(function() {
return this.value === $button.data('label');
}).remove();
// Submit the form to get new data
Issuable.filterResults($('.filter-form'));
return $('.js-label-select').trigger('update.label');
});
...
...
app/assets/javascripts/issue.js
View file @
2cad277d
/*= require flash */
/*= require jquery.waitforimages */
/*= require task_list */
(
function
()
{
...
...
@@ -13,6 +9,7 @@
this
.
Issue
=
(
function
()
{
function
Issue
()
{
this
.
submitNoteForm
=
bind
(
this
.
submitNoteForm
,
this
);
// Prevent duplicate event bindings
this
.
disableTaskList
();
if
(
$
(
'
a.btn-close
'
).
length
)
{
this
.
initTaskList
();
...
...
@@ -99,6 +96,8 @@
url
:
$
(
'
form.js-issuable-update
'
).
attr
(
'
action
'
),
data
:
patchData
});
// TODO (rspeicher): Make the issue description inline-editable like a note so
// that we can re-use its form here
};
Issue
.
prototype
.
initMergeRequests
=
function
()
{
...
...
@@ -128,6 +127,8 @@
Issue
.
prototype
.
initCanCreateBranch
=
function
()
{
var
$container
;
$container
=
$
(
'
#new-branch
'
);
// If the user doesn't have the required permissions the container isn't
// rendered at all.
if
(
$container
.
length
===
0
)
{
return
;
}
...
...
app/assets/javascripts/issues-bulk-assignment.js
View file @
2cad277d
(
function
()
{
this
.
IssuableBulkActions
=
(
function
()
{
function
IssuableBulkActions
(
opts
)
{
// Set defaults
var
ref
,
ref1
,
ref2
;
if
(
opts
==
null
)
{
opts
=
{};
}
this
.
container
=
(
ref
=
opts
.
container
)
!=
null
?
ref
:
$
(
'
.content
'
),
this
.
form
=
(
ref1
=
opts
.
form
)
!=
null
?
ref1
:
this
.
getElement
(
'
.bulk-update
'
),
this
.
issues
=
(
ref2
=
opts
.
issues
)
!=
null
?
ref2
:
this
.
getElement
(
'
.issuable-list > li
'
);
// Save instance
this
.
form
.
data
(
'
bulkActions
'
,
this
);
this
.
willUpdateLabels
=
false
;
this
.
bindEvents
();
// Fixes bulk-assign not working when navigating through pages
Issuable
.
initChecks
();
}
...
...
@@ -86,6 +89,7 @@
ref1
=
this
.
getLabelsFromSelection
();
for
(
j
=
0
,
len1
=
ref1
.
length
;
j
<
len1
;
j
++
)
{
id
=
ref1
[
j
];
// Only the ones that we are not going to keep
if
(
labelsToKeep
.
indexOf
(
id
)
===
-
1
)
{
result
.
push
(
id
);
}
...
...
@@ -147,6 +151,8 @@
indeterminatedLabels
=
this
.
getUnmarkedIndeterminedLabels
();
labelsToApply
=
this
.
getLabelsToApply
();
indeterminatedLabels
.
map
(
function
(
id
)
{
// We need to exclude label IDs that will be applied
// By not doing this will cause issues from selection to not add labels at all
if
(
labelsToApply
.
indexOf
(
id
)
===
-
1
)
{
return
result
.
push
(
id
);
}
...
...
app/assets/javascripts/labels.js
View file @
2cad277d
...
...
@@ -26,13 +26,16 @@
var
previewColor
;
previewColor
=
$
(
'
input#label_color
'
).
val
();
return
$
(
'
div.label-color-preview
'
).
css
(
'
background-color
'
,
previewColor
);
// Updates the the preview color with the hex-color input
};
// Updates the preview color with a click on a suggested color
Labels
.
prototype
.
setSuggestedColor
=
function
(
e
)
{
var
color
;
color
=
$
(
e
.
currentTarget
).
data
(
'
color
'
);
$
(
'
input#label_color
'
).
val
(
color
);
this
.
updateColorPreview
();
// Notify the form, that color has changed
$
(
'
.label-form
'
).
trigger
(
'
keyup
'
);
return
e
.
preventDefault
();
};
...
...
app/assets/javascripts/labels_select.js
View file @
2cad277d
...
...
@@ -156,11 +156,13 @@
selectedClass
.
push
(
'
is-indeterminate
'
);
}
if
(
active
.
indexOf
(
label
.
id
)
!==
-
1
)
{
// Remove is-indeterminate class if the item will be marked as active
i
=
selectedClass
.
indexOf
(
'
is-indeterminate
'
);
if
(
i
!==
-
1
)
{
selectedClass
.
splice
(
i
,
1
);
}
selectedClass
.
push
(
'
is-active
'
);
// Add input manually
instance
.
addInput
(
this
.
fieldName
,
label
.
id
);
}
}
...
...
@@ -172,6 +174,7 @@
}
if
(
label
.
duplicate
)
{
spacing
=
100
/
label
.
color
.
length
;
// Reduce the colors to 4
label
.
color
=
label
.
color
.
filter
(
function
(
color
,
i
)
{
return
i
<
4
;
});
...
...
@@ -192,11 +195,13 @@
}
else
{
colorEl
=
''
;
}
// We need to identify which items are actually labels
if
(
label
.
id
)
{
selectedClass
.
push
(
'
label-item
'
);
$a
.
attr
(
'
data-label-id
'
,
label
.
id
);
}
$a
.
addClass
(
selectedClass
.
join
(
'
'
)).
html
(
colorEl
+
"
"
+
label
.
title
);
// Return generated html
return
$li
.
html
(
$a
).
prop
(
'
outerHTML
'
);
},
persistWhenHide
:
$dropdown
.
data
(
'
persistWhenHide
'
),
...
...
@@ -238,6 +243,7 @@
isIssueIndex
=
page
===
'
projects:issues:index
'
;
isMRIndex
=
page
===
'
projects:merge_requests:index
'
;
$selectbox
.
hide
();
// display:block overrides the hide-collapse rule
$value
.
removeAttr
(
'
style
'
);
if
(
page
===
'
projects:boards:show
'
)
{
return
;
...
...
@@ -255,6 +261,7 @@
}
}
if
(
$dropdown
.
hasClass
(
'
js-filter-bulk-update
'
))
{
// If we are persisting state we need the classes
if
(
!
this
.
options
.
persistWhenHide
)
{
return
$dropdown
.
parent
().
find
(
'
.is-active, .is-indeterminate
'
).
removeClass
();
}
...
...
@@ -324,7 +331,9 @@
if
(
$
(
'
.selected_issue:checked
'
).
length
)
{
return
;
}
// Remove inputs
$
(
'
.issues_bulk_update .labels-filter input[type="hidden"]
'
).
remove
();
// Also restore button text
return
$
(
'
.issues_bulk_update .labels-filter .dropdown-toggle-text
'
).
text
(
'
Label
'
);
};
...
...
app/assets/javascripts/lib/chart.js
View file @
2cad277d
...
...
@@ -3,5 +3,4 @@
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/lib/cropper.js
View file @
2cad277d
...
...
@@ -3,5 +3,4 @@
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/lib/d3.js
View file @
2cad277d
...
...
@@ -3,5 +3,4 @@
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/lib/raphael.js
View file @
2cad277d
/*= require raphael */
/*= require g.raphael */
/*= require g.bar */
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/lib/utils/datetime_utility.js
View file @
2cad277d
...
...
@@ -29,6 +29,7 @@
if
(
setTimeago
)
{
$timeagoEls
.
timeago
();
$timeagoEls
.
tooltip
(
'
destroy
'
);
// Recreate with custom template
return
$timeagoEls
.
tooltip
({
template
:
'
<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>
'
});
...
...
app/assets/javascripts/lib/utils/emoji_aliases.js.coffee.erb
deleted
100644 → 0
View file @
e36534db
gl.emojiAliases = ->
JSON.parse('
<%=
Gitlab
::
AwardEmoji
.
aliases
.
to_json
%>
')
app/assets/javascripts/lib/utils/emoji_aliases.js.erb
0 → 100644
View file @
2cad277d
(function() {
gl.emojiAliases = function() {
return JSON.parse('
<%=
Gitlab
::
AwardEmoji
.
aliases
.
to_json
%>
');
};
}).call(this);
app/assets/javascripts/lib/utils/notify.js
View file @
2cad277d
...
...
@@ -6,6 +6,7 @@
notification
=
new
Notification
(
message
,
opts
);
setTimeout
(
function
()
{
return
notification
.
close
();
// Hide the notification after X amount of seconds
},
8000
);
if
(
onclick
)
{
return
notification
.
onclick
=
onclick
;
...
...
@@ -22,12 +23,16 @@
body
:
body
,
icon
:
icon
};
// Let's check if the browser supports notifications
if
(
!
(
'
Notification
'
in
window
))
{
// do nothing
}
else
if
(
Notification
.
permission
===
'
granted
'
)
{
// If it's okay let's create a notification
return
notificationGranted
(
message
,
opts
,
onclick
);
}
else
if
(
Notification
.
permission
!==
'
denied
'
)
{
return
Notification
.
requestPermission
(
function
(
permission
)
{
// If the user accepts, let's create a notification
if
(
permission
===
'
granted
'
)
{
return
notificationGranted
(
message
,
opts
,
onclick
);
}
...
...
app/assets/javascripts/lib/utils/text_utility.js
View file @
2cad277d
...
...
@@ -29,6 +29,7 @@
lineBefore
=
this
.
lineBefore
(
text
,
textArea
);
lineAfter
=
this
.
lineAfter
(
text
,
textArea
);
if
(
lineBefore
===
blockTag
&&
lineAfter
===
blockTag
)
{
// To remove the block tag we have to select the line before & after
if
(
blockTag
!=
null
)
{
textArea
.
selectionStart
=
textArea
.
selectionStart
-
(
blockTag
.
length
+
1
);
textArea
.
selectionEnd
=
textArea
.
selectionEnd
+
(
blockTag
.
length
+
1
);
...
...
@@ -63,11 +64,11 @@
if
(
!
inserted
)
{
try
{
document
.
execCommand
(
"
ms-beginUndoUnit
"
);
}
catch
(
undefined
)
{}
}
catch
(
error
)
{}
textArea
.
value
=
this
.
replaceRange
(
text
,
textArea
.
selectionStart
,
textArea
.
selectionEnd
,
insertText
);
try
{
document
.
execCommand
(
"
ms-endUndoUnit
"
);
}
catch
(
undefined
)
{}
}
catch
(
error
)
{}
}
return
this
.
moveCursor
(
textArea
,
tag
,
wrap
);
};
...
...
app/assets/javascripts/lib/utils/url_utility.js
View file @
2cad277d
...
...
@@ -7,6 +7,8 @@
if
((
base
=
w
.
gl
).
utils
==
null
)
{
base
.
utils
=
{};
}
// Returns an array containing the value(s) of the
// of the key passed as an argument
w
.
gl
.
utils
.
getParameterValues
=
function
(
sParam
)
{
var
i
,
sPageURL
,
sParameterName
,
sURLVariables
,
values
;
sPageURL
=
decodeURIComponent
(
window
.
location
.
search
.
substring
(
1
));
...
...
@@ -23,6 +25,8 @@
}
return
values
;
};
// @param {Object} params - url keys and value to merge
// @param {String} url
w
.
gl
.
utils
.
mergeUrlParams
=
function
(
params
,
url
)
{
var
lastChar
,
newUrl
,
paramName
,
paramValue
,
pattern
;
newUrl
=
decodeURIComponent
(
url
);
...
...
@@ -37,12 +41,14 @@
newUrl
=
""
+
newUrl
+
(
newUrl
.
indexOf
(
'
?
'
)
>
0
?
'
&
'
:
'
?
'
)
+
paramName
+
"
=
"
+
paramValue
;
}
}
// Remove a trailing ampersand
lastChar
=
newUrl
[
newUrl
.
length
-
1
];
if
(
lastChar
===
'
&
'
)
{
newUrl
=
newUrl
.
slice
(
0
,
-
1
);
}
return
newUrl
;
};
// removes parameter query string from url. returns the modified url
w
.
gl
.
utils
.
removeParamQueryString
=
function
(
url
,
param
)
{
var
urlVariables
,
variables
;
url
=
decodeURIComponent
(
url
);
...
...
app/assets/javascripts/line_highlighter.js
View file @
2cad277d
// LineHighlighter
//
// Handles single- and multi-line selection and highlight for blob views.
//
/*= require jquery.scrollTo */
//
// ### Example Markup
//
// <div id="blob-content-holder">
// <div class="file-content">
// <div class="line-numbers">
// <a href="#L1" id="L1" data-line-number="1">1</a>
// <a href="#L2" id="L2" data-line-number="2">2</a>
// <a href="#L3" id="L3" data-line-number="3">3</a>
// <a href="#L4" id="L4" data-line-number="4">4</a>
// <a href="#L5" id="L5" data-line-number="5">5</a>
// </div>
// <pre class="code highlight">
// <code>
// <span id="LC1" class="line">...</span>
// <span id="LC2" class="line">...</span>
// <span id="LC3" class="line">...</span>
// <span id="LC4" class="line">...</span>
// <span id="LC5" class="line">...</span>
// </code>
// </pre>
// </div>
// </div>
//
(
function
()
{
var
bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
};
this
.
LineHighlighter
=
(
function
()
{
// CSS class applied to highlighted lines
LineHighlighter
.
prototype
.
highlightClass
=
'
hll
'
;
// Internal copy of location.hash so we're not dependent on `location` in tests
LineHighlighter
.
prototype
.
_hash
=
''
;
function
LineHighlighter
(
hash
)
{
var
range
;
if
(
hash
==
null
)
{
// Initialize a LineHighlighter object
//
// hash - String URL hash for dependency injection in tests
hash
=
location
.
hash
;
}
this
.
setHash
=
bind
(
this
.
setHash
,
this
);
...
...
@@ -24,6 +56,8 @@
if
(
range
[
0
])
{
this
.
highlightRange
(
range
);
$
.
scrollTo
(
"
#L
"
+
range
[
0
],
{
// Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context
offset
:
-
150
});
}
...
...
@@ -32,6 +66,12 @@
LineHighlighter
.
prototype
.
bindEvents
=
function
()
{
$
(
'
#blob-content-holder
'
).
on
(
'
mousedown
'
,
'
a[data-line-number]
'
,
this
.
clickHandler
);
// While it may seem odd to bind to the mousedown event and then throw away
// the click event, there is a method to our madness.
//
// If not done this way, the line number anchor will sometimes keep its
// active state even when the event is cancelled, resulting in an ugly border
// around the link and/or a persisted underline text decoration.
return
$
(
'
#blob-content-holder
'
).
on
(
'
click
'
,
'
a[data-line-number]
'
,
function
(
event
)
{
return
event
.
preventDefault
();
});
...
...
@@ -44,6 +84,8 @@
lineNumber
=
$
(
event
.
target
).
closest
(
'
a
'
).
data
(
'
line-number
'
);
current
=
this
.
hashToRange
(
this
.
_hash
);
if
(
!
(
current
[
0
]
&&
event
.
shiftKey
))
{
// If there's no current selection, or there is but Shift wasn't held,
// treat this like a single-line selection.
this
.
setHash
(
lineNumber
);
return
this
.
highlightLine
(
lineNumber
);
}
else
if
(
event
.
shiftKey
)
{
...
...
@@ -59,10 +101,23 @@
LineHighlighter
.
prototype
.
clearHighlight
=
function
()
{
return
$
(
"
.
"
+
this
.
highlightClass
).
removeClass
(
this
.
highlightClass
);
// Unhighlight previously highlighted lines
};
// Convert a URL hash String into line numbers
//
// hash - Hash String
//
// Examples:
//
// hashToRange('#L5') # => [5, null]
// hashToRange('#L5-15') # => [5, 15]
// hashToRange('#foo') # => [null, null]
//
// Returns an Array
LineHighlighter
.
prototype
.
hashToRange
=
function
(
hash
)
{
var
first
,
last
,
matches
;
//?L(\d+)(?:-(\d+))?$/)
matches
=
hash
.
match
(
/^#
?
L
(\d
+
)(?:
-
(\d
+
))?
$/
);
if
(
matches
&&
matches
.
length
)
{
first
=
parseInt
(
matches
[
1
]);
...
...
@@ -73,10 +128,16 @@
}
};
// Highlight a single line
//
// lineNumber - Line number to highlight
LineHighlighter
.
prototype
.
highlightLine
=
function
(
lineNumber
)
{
return
$
(
"
#LC
"
+
lineNumber
).
addClass
(
this
.
highlightClass
);
};
// Highlight all lines within a range
//
// range - Array containing the starting and ending line numbers
LineHighlighter
.
prototype
.
highlightRange
=
function
(
range
)
{
var
i
,
lineNumber
,
ref
,
ref1
,
results
;
if
(
range
[
1
])
{
...
...
@@ -90,6 +151,7 @@
}
};
// Set the URL hash string
LineHighlighter
.
prototype
.
setHash
=
function
(
firstLineNumber
,
lastLineNumber
)
{
var
hash
;
if
(
lastLineNumber
)
{
...
...
@@ -101,10 +163,15 @@
return
this
.
__setLocationHash__
(
hash
);
};
// Make the actual hash change in the browser
//
// This method is stubbed in tests.
LineHighlighter
.
prototype
.
__setLocationHash__
=
function
(
value
)
{
return
history
.
pushState
({
turbolinks
:
false
,
url
:
value
// We're using pushState instead of assigning location.hash directly to
// prevent the page from scrolling on the hashchange event
},
document
.
title
,
value
);
};
...
...
app/assets/javascripts/merge_request.js
View file @
2cad277d
/*= require jquery.waitforimages */
/*= require task_list */
/*= require merge_request_tabs */
(
function
()
{
...
...
@@ -12,6 +8,11 @@
this
.
MergeRequest
=
(
function
()
{
function
MergeRequest
(
opts
)
{
// Initialize MergeRequest behavior
//
// Options:
// action - String, current controller action
//
this
.
opts
=
opts
!=
null
?
opts
:
{};
this
.
submitNoteForm
=
bind
(
this
.
submitNoteForm
,
this
);
this
.
$el
=
$
(
'
.merge-request
'
);
...
...
@@ -21,6 +22,7 @@
};
})(
this
));
this
.
initTabs
();
// Prevent duplicate event bindings
this
.
disableTaskList
();
this
.
initMRBtnListeners
();
if
(
$
(
"
a.btn-close
"
).
length
)
{
...
...
@@ -28,14 +30,17 @@
}
}
// Local jQuery finder
MergeRequest
.
prototype
.
$
=
function
(
selector
)
{
return
this
.
$el
.
find
(
selector
);
};
MergeRequest
.
prototype
.
initTabs
=
function
()
{
if
(
this
.
opts
.
action
!==
'
new
'
)
{
// `MergeRequests#new` has no tab-persisting or lazy-loading behavior
window
.
mrTabs
=
new
MergeRequestTabs
(
this
.
opts
);
}
else
{
// Show the first tab (Commits)
return
$
(
'
.merge-request-tabs a[data-toggle="tab"]:first
'
).
tab
(
'
show
'
);
}
};
...
...
@@ -96,6 +101,8 @@
url
:
$
(
'
form.js-issuable-update
'
).
attr
(
'
action
'
),
data
:
patchData
});
// TODO (rspeicher): Make the merge request description inline-editable like a
// note so that we can re-use its form here
};
return
MergeRequest
;
...
...
app/assets/javascripts/merge_request_tabs.js
View file @
2cad277d
// MergeRequestTabs
//
// Handles persisting and restoring the current tab selection and lazily-loading
// content on the MergeRequests#show page.
//
/*= require jquery.cookie */
//
// ### Example Markup
//
// <ul class="nav-links merge-request-tabs">
// <li class="notes-tab active">
// <a data-action="notes" data-target="#notes" data-toggle="tab" href="/foo/bar/merge_requests/1">
// Discussion
// </a>
// </li>
// <li class="commits-tab">
// <a data-action="commits" data-target="#commits" data-toggle="tab" href="/foo/bar/merge_requests/1/commits">
// Commits
// </a>
// </li>
// <li class="diffs-tab">
// <a data-action="diffs" data-target="#diffs" data-toggle="tab" href="/foo/bar/merge_requests/1/diffs">
// Diffs
// </a>
// </li>
// </ul>
//
// <div class="tab-content">
// <div class="notes tab-pane active" id="notes">
// Notes Content
// </div>
// <div class="commits tab-pane" id="commits">
// Commits Content
// </div>
// <div class="diffs tab-pane" id="diffs">
// Diffs Content
// </div>
// </div>
//
// <div class="mr-loading-status">
// <div class="loading">
// Loading Animation
// </div>
// </div>
//
(
function
()
{
var
bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
};
...
...
@@ -19,6 +62,7 @@
this
.
setCurrentAction
=
bind
(
this
.
setCurrentAction
,
this
);
this
.
tabShown
=
bind
(
this
.
tabShown
,
this
);
this
.
showTab
=
bind
(
this
.
showTab
,
this
);
// Store the `location` object, allowing for easier stubbing in tests
this
.
_location
=
location
;
this
.
bindEvents
();
this
.
activateTab
(
this
.
opts
.
action
);
...
...
@@ -77,6 +121,7 @@
}
};
// Activate a tab based on the current action
MergeRequestTabs
.
prototype
.
activateTab
=
function
(
action
)
{
if
(
action
===
'
show
'
)
{
action
=
'
notes
'
;
...
...
@@ -84,20 +129,48 @@
return
$
(
"
.merge-request-tabs a[data-action='
"
+
action
+
"
']
"
).
tab
(
'
show
'
);
};
// Replaces the current Merge Request-specific action in the URL with a new one
//
// If the action is "notes", the URL is reset to the standard
// `MergeRequests#show` route.
//
// Examples:
//
// location.pathname # => "/namespace/project/merge_requests/1"
// setCurrentAction('diffs')
// location.pathname # => "/namespace/project/merge_requests/1/diffs"
//
// location.pathname # => "/namespace/project/merge_requests/1/diffs"
// setCurrentAction('notes')
// location.pathname # => "/namespace/project/merge_requests/1"
//
// location.pathname # => "/namespace/project/merge_requests/1/diffs"
// setCurrentAction('commits')
// location.pathname # => "/namespace/project/merge_requests/1/commits"
//
// Returns the new URL String
MergeRequestTabs
.
prototype
.
setCurrentAction
=
function
(
action
)
{
var
new_state
;
// Normalize action, just to be safe
if
(
action
===
'
show
'
)
{
action
=
'
notes
'
;
}
this
.
currentAction
=
action
;
// Remove a trailing '/commits' or '/diffs'
new_state
=
this
.
_location
.
pathname
.
replace
(
/
\/(
commits|diffs|builds|pipelines
)(\.
html
)?\/?
$/
,
''
);
// Append the new action if we're on a tab other than 'notes'
if
(
action
!==
'
notes
'
)
{
new_state
+=
"
/
"
+
action
;
}
// Ensure parameters and hash come along for the ride
new_state
+=
this
.
_location
.
search
+
this
.
_location
.
hash
;
history
.
replaceState
({
turbolinks
:
true
,
url
:
new_state
// Replace the current history state with the new one without breaking
// Turbolinks' history.
//
// See https://github.com/rails/turbolinks/issues/363
},
document
.
title
,
new_state
);
return
new_state
;
};
...
...
@@ -206,6 +279,9 @@
});
};
// Show or hide the loading spinner
//
// status - Boolean, true to show, false to hide
MergeRequestTabs
.
prototype
.
toggleLoading
=
function
(
status
)
{
return
$
(
'
.mr-loading-status .loading
'
).
toggle
(
status
);
};
...
...
@@ -232,6 +308,7 @@
MergeRequestTabs
.
prototype
.
diffViewType
=
function
()
{
return
$
(
'
.inline-parallel-buttons a.active
'
).
data
(
'
view-type
'
);
// Returns diff view type
};
MergeRequestTabs
.
prototype
.
expandViewContainer
=
function
()
{
...
...
@@ -245,6 +322,8 @@
if
(
$gutterIcon
.
is
(
'
.fa-angle-double-right
'
))
{
return
$gutterIcon
.
closest
(
'
a
'
).
trigger
(
'
click
'
,
[
true
]);
}
// Wait until listeners are set
// Only when sidebar is expanded
},
0
);
};
...
...
@@ -259,6 +338,9 @@
return
$gutterIcon
.
closest
(
'
a
'
).
trigger
(
'
click
'
,
[
true
]);
}
},
0
);
// Expand the issuable sidebar unless the user explicitly collapsed it
// Wait until listeners are set
// Only when sidebar is collapsed
};
return
MergeRequestTabs
;
...
...
app/assets/javascripts/merge_request_widget.js
View file @
2cad277d
...
...
@@ -3,6 +3,12 @@
this
.
MergeRequestWidget
=
(
function
()
{
function
MergeRequestWidget
(
opts
)
{
// Initialize MergeRequestWidget behavior
//
// check_enable - Boolean, whether to check automerge status
// merge_check_url - String, URL to use to check automerge status
// ci_status_url - String, URL to use to check CI status
//
this
.
opts
=
opts
;
$
(
'
#modal_merge_info
'
).
modal
({
show
:
false
...
...
@@ -118,6 +124,8 @@
if
(
data
.
coverage
)
{
_this
.
showCICoverage
(
data
.
coverage
);
}
// The first check should only update the UI, a notification
// should only be displayed on status changes
if
(
showNotification
&&
!
_this
.
firstCICheck
)
{
status
=
_this
.
ciLabelForStatus
(
data
.
status
);
if
(
status
===
"
preparing
"
)
{
...
...
app/assets/javascripts/milestone.js
View file @
2cad277d
...
...
@@ -110,6 +110,7 @@
},
update
:
function
(
event
,
ui
)
{
var
data
;
// Prevents sorting from container which element has been removed.
if
(
$
(
this
).
find
(
ui
.
item
).
length
>
0
)
{
data
=
$
(
this
).
sortable
(
"
serialize
"
);
return
Milestone
.
sortIssues
(
data
);
...
...
app/assets/javascripts/milestone_select.js
View file @
2cad277d
...
...
@@ -92,6 +92,7 @@
},
hidden
:
function
()
{
$selectbox
.
hide
();
// display:block overrides the hide-collapse rule
return
$value
.
css
(
'
display
'
,
''
);
},
clicked
:
function
(
selected
,
$el
,
e
)
{
...
...
app/assets/javascripts/network/branch-graph.js
View file @
2cad277d
...
...
@@ -90,6 +90,7 @@
results
=
[];
while
(
k
<
this
.
mspace
)
{
this
.
colors
.
push
(
Raphael
.
getColor
(.
8
));
// Skipping a few colors in the spectrum to get more contrast between colors
Raphael
.
getColor
();
Raphael
.
getColor
();
results
.
push
(
k
++
);
...
...
@@ -112,6 +113,7 @@
for
(
mm
=
j
=
0
,
len
=
ref
.
length
;
j
<
len
;
mm
=
++
j
)
{
day
=
ref
[
mm
];
if
(
cuday
!==
day
[
0
]
||
cumonth
!==
day
[
1
])
{
// Dates
r
.
text
(
55
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
0
]).
attr
({
font
:
"
12px Monaco, monospace
"
,
fill
:
"
#BBB
"
...
...
@@ -119,6 +121,7 @@
cuday
=
day
[
0
];
}
if
(
cumonth
!==
day
[
1
])
{
// Months
r
.
text
(
20
,
this
.
offsetY
+
this
.
unitTime
*
mm
,
day
[
1
]).
attr
({
font
:
"
12px Monaco, monospace
"
,
fill
:
"
#EEE
"
...
...
@@ -207,6 +210,7 @@
}
r
=
this
.
r
;
shortrefs
=
commit
.
refs
;
// Truncate if longer than 15 chars
if
(
shortrefs
.
length
>
17
)
{
shortrefs
=
shortrefs
.
substr
(
0
,
15
)
+
"
…
"
;
}
...
...
@@ -217,6 +221,7 @@
title
:
commit
.
refs
});
textbox
=
text
.
getBBox
();
// Create rectangle based on the size of the textbox
rect
=
r
.
rect
(
x
,
y
-
7
,
textbox
.
width
+
5
,
textbox
.
height
+
5
,
4
).
attr
({
fill
:
"
#000
"
,
"
fill-opacity
"
:
.
5
,
...
...
@@ -229,6 +234,7 @@
});
label
=
r
.
set
(
rect
,
text
);
label
.
transform
([
"
t
"
,
-
rect
.
getBBox
().
width
-
15
,
0
]);
// Set text to front
return
text
.
toFront
();
};
...
...
@@ -283,11 +289,13 @@
parentY
=
this
.
offsetY
+
this
.
unitTime
*
parentCommit
.
time
;
parentX1
=
this
.
offsetX
+
this
.
unitSpace
*
(
this
.
mspace
-
parentCommit
.
space
);
parentX2
=
this
.
offsetX
+
this
.
unitSpace
*
(
this
.
mspace
-
parent
[
1
]);
// Set line color
if
(
parentCommit
.
space
<=
commit
.
space
)
{
color
=
this
.
colors
[
commit
.
space
];
}
else
{
color
=
this
.
colors
[
parentCommit
.
space
];
}
// Build line shape
if
(
parent
[
1
]
===
commit
.
space
)
{
offset
=
[
0
,
5
];
arrow
=
"
l-2,5,4,0,-2,-5,0,5
"
;
...
...
@@ -298,13 +306,17 @@
offset
=
[
-
3
,
3
];
arrow
=
"
l-5,0,2,4,3,-4,-4,2
"
;
}
// Start point
route
=
[
"
M
"
,
x
+
offset
[
0
],
y
+
offset
[
1
]];
// Add arrow if not first parent
if
(
i
>
0
)
{
route
.
push
(
arrow
);
}
// Circumvent if overlap
if
(
commit
.
space
!==
parentCommit
.
space
||
commit
.
space
!==
parent
[
1
])
{
route
.
push
(
"
L
"
,
parentX2
,
y
+
10
,
"
L
"
,
parentX2
,
parentY
-
5
);
}
// End point
route
.
push
(
"
L
"
,
parentX1
,
parentY
);
results
.
push
(
r
.
path
(
route
).
attr
({
stroke
:
color
,
...
...
@@ -325,6 +337,7 @@
"
fill-opacity
"
:
.
5
,
stroke
:
"
none
"
});
// Displayed in the center
return
this
.
element
.
scrollTop
(
y
-
this
.
graphHeight
/
2
);
}
};
...
...
app/assets/javascripts/network/network_bundle.js
View file @
2cad277d
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
/*= require_tree . */
(
function
()
{
...
...
app/assets/javascripts/notes.js
View file @
2cad277d
This diff is collapsed.
Click to expand it.
app/assets/javascripts/preview_markdown.js
View file @
2cad277d
// MarkdownPreview
//
// Handles toggling the "Write" and "Preview" tab clicks, rendering the preview,
// and showing a warning when more than `x` users are referenced.
//
(
function
()
{
var
lastTextareaPreviewed
,
markdownPreview
,
previewButtonSelector
,
writeButtonSelector
;
this
.
MarkdownPreview
=
(
function
()
{
function
MarkdownPreview
()
{}
// Minimum number of users referenced before triggering a warning
MarkdownPreview
.
prototype
.
referenceThreshold
=
10
;
MarkdownPreview
.
prototype
.
ajaxCache
=
{};
...
...
@@ -101,8 +107,10 @@
return
;
}
lastTextareaPreviewed
=
$form
.
find
(
'
textarea.markdown-area
'
);
// toggle tabs
$form
.
find
(
writeButtonSelector
).
parent
().
removeClass
(
'
active
'
);
$form
.
find
(
previewButtonSelector
).
parent
().
addClass
(
'
active
'
);
// toggle content
$form
.
find
(
'
.md-write-holder
'
).
hide
();
$form
.
find
(
'
.md-preview-holder
'
).
show
();
return
markdownPreview
.
showPreview
(
$form
);
...
...
@@ -113,8 +121,10 @@
return
;
}
lastTextareaPreviewed
=
null
;
// toggle tabs
$form
.
find
(
writeButtonSelector
).
parent
().
addClass
(
'
active
'
);
$form
.
find
(
previewButtonSelector
).
parent
().
removeClass
(
'
active
'
);
// toggle content
$form
.
find
(
'
.md-write-holder
'
).
show
();
$form
.
find
(
'
textarea.markdown-area
'
).
focus
();
return
$form
.
find
(
'
.md-preview-holder
'
).
hide
();
...
...
app/assets/javascripts/profile/gl_crop.js
View file @
2cad277d
...
...
@@ -5,6 +5,7 @@
GitLabCrop
=
(
function
()
{
var
FILENAMEREGEX
;
// Matches everything but the file name
FILENAMEREGEX
=
/^.*
[\\\/]
/
;
function
GitLabCrop
(
input
,
opts
)
{
...
...
@@ -17,11 +18,18 @@
this
.
onModalShow
=
bind
(
this
.
onModalShow
,
this
);
this
.
onPickImageClick
=
bind
(
this
.
onPickImageClick
,
this
);
this
.
fileInput
=
$
(
input
);
// We should rename to avoid spec to fail
// Form will submit the proper input filed with a file using FormData
this
.
fileInput
.
attr
(
'
name
'
,
(
this
.
fileInput
.
attr
(
'
name
'
))
+
"
-trigger
"
).
attr
(
'
id
'
,
(
this
.
fileInput
.
attr
(
'
id
'
))
+
"
-trigger
"
);
// Set defaults
this
.
exportWidth
=
(
ref
=
opts
.
exportWidth
)
!=
null
?
ref
:
200
,
this
.
exportHeight
=
(
ref1
=
opts
.
exportHeight
)
!=
null
?
ref1
:
200
,
this
.
cropBoxWidth
=
(
ref2
=
opts
.
cropBoxWidth
)
!=
null
?
ref2
:
200
,
this
.
cropBoxHeight
=
(
ref3
=
opts
.
cropBoxHeight
)
!=
null
?
ref3
:
200
,
this
.
form
=
(
ref4
=
opts
.
form
)
!=
null
?
ref4
:
this
.
fileInput
.
parents
(
'
form
'
),
this
.
filename
=
opts
.
filename
,
this
.
previewImage
=
opts
.
previewImage
,
this
.
modalCrop
=
opts
.
modalCrop
,
this
.
pickImageEl
=
opts
.
pickImageEl
,
this
.
uploadImageBtn
=
opts
.
uploadImageBtn
,
this
.
modalCropImg
=
opts
.
modalCropImg
;
// Required params
// Ensure needed elements are jquery objects
// If selector is provided we will convert them to a jQuery Object
this
.
filename
=
this
.
getElement
(
this
.
filename
);
this
.
previewImage
=
this
.
getElement
(
this
.
previewImage
);
this
.
pickImageEl
=
this
.
getElement
(
this
.
pickImageEl
);
// Modal elements usually are outside the @form element
this
.
modalCrop
=
_
.
isString
(
this
.
modalCrop
)
?
$
(
this
.
modalCrop
)
:
this
.
modalCrop
;
this
.
uploadImageBtn
=
_
.
isString
(
this
.
uploadImageBtn
)
?
$
(
this
.
uploadImageBtn
)
:
this
.
uploadImageBtn
;
this
.
modalCropImg
=
_
.
isString
(
this
.
modalCropImg
)
?
$
(
this
.
modalCropImg
)
:
this
.
modalCropImg
;
...
...
@@ -93,8 +101,8 @@
return
this
.
modalCropImg
.
attr
(
'
src
'
,
''
).
cropper
(
'
destroy
'
);
};
GitLabCrop
.
prototype
.
onUploadImageBtnClick
=
function
(
e
)
{
e
.
preventDefault
();
GitLabCrop
.
prototype
.
onUploadImageBtnClick
=
function
(
e
)
{
// Remove attached image
e
.
preventDefault
();
// Destroy cropper instance
this
.
setBlob
();
this
.
setPreview
();
this
.
modalCrop
.
modal
(
'
hide
'
);
...
...
app/assets/javascripts/profile/profile.js
View file @
2cad277d
...
...
@@ -11,9 +11,11 @@
this
.
form
=
(
ref
=
opts
.
form
)
!=
null
?
ref
:
$
(
'
.edit-user
'
);
$
(
'
.js-preferences-form
'
).
on
(
'
change.preference
'
,
'
input[type=radio]
'
,
function
()
{
return
$
(
this
).
parents
(
'
form
'
).
submit
();
// Automatically submit the Preferences form when any of its radio buttons change
});
$
(
'
#user_notification_email
'
).
on
(
'
change
'
,
function
()
{
return
$
(
this
).
parents
(
'
form
'
).
submit
();
// Automatically submit email form when it changes
});
$
(
'
.update-username
'
).
on
(
'
ajax:before
'
,
function
()
{
$
(
'
.loading-username
'
).
show
();
...
...
@@ -76,6 +78,7 @@
},
complete
:
function
()
{
window
.
scrollTo
(
0
,
0
);
// Enable submit button after requests ends
return
self
.
form
.
find
(
'
:input[disabled]
'
).
enable
();
}
});
...
...
@@ -93,6 +96,7 @@
if
(
comment
&&
comment
.
length
>
1
&&
$title
.
val
()
===
''
)
{
return
$title
.
val
(
comment
[
1
]).
change
();
}
// Extract the SSH Key title from its comment
});
if
(
gl
.
utils
.
getPagePath
()
===
'
profiles
'
)
{
return
new
Profile
();
...
...
app/assets/javascripts/profile/profile_bundle.js
View file @
2cad277d
...
...
@@ -3,5 +3,4 @@
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/project.js
View file @
2cad277d
...
...
@@ -11,7 +11,13 @@
url
=
$
(
"
#project_clone
"
).
val
();
$
(
'
#project_clone
'
).
val
(
url
);
return
$
(
'
.clone
'
).
text
(
url
);
// Git protocol switcher
// Remove the active class for all buttons (ssh, http, kerberos if shown)
// Add the active class for the clicked button
// Update the input field
// Update the command line instructions
});
// Ref switcher
this
.
initRefSwitcher
();
$
(
'
.project-refs-select
'
).
on
(
'
change
'
,
function
()
{
return
$
(
this
).
parents
(
'
form
'
).
submit
();
...
...
app/assets/javascripts/project_find_file.js
View file @
2cad277d
...
...
@@ -13,8 +13,11 @@
this
.
selectRowUp
=
bind
(
this
.
selectRowUp
,
this
);
this
.
filePaths
=
{};
this
.
inputElement
=
this
.
element
.
find
(
"
.file-finder-input
"
);
// init event
this
.
initEvent
();
// focus text input box
this
.
inputElement
.
focus
();
// load file list
this
.
load
(
this
.
options
.
url
);
}
...
...
@@ -42,6 +45,7 @@
}
}
});
// init event
};
ProjectFindFile
.
prototype
.
findFile
=
function
()
{
...
...
@@ -49,8 +53,10 @@
searchText
=
this
.
inputElement
.
val
();
result
=
searchText
.
length
>
0
?
fuzzaldrinPlus
.
filter
(
this
.
filePaths
,
searchText
)
:
this
.
filePaths
;
return
this
.
renderList
(
result
,
searchText
);
// find file
};
// files pathes load
ProjectFindFile
.
prototype
.
load
=
function
(
url
)
{
return
$
.
ajax
({
url
:
url
,
...
...
@@ -67,6 +73,7 @@
});
};
// render result
ProjectFindFile
.
prototype
.
renderList
=
function
(
filePaths
,
searchText
)
{
var
blobItemUrl
,
filePath
,
html
,
i
,
j
,
len
,
matches
,
results
;
this
.
element
.
find
(
"
.tree-table > tbody
"
).
empty
();
...
...
@@ -86,6 +93,7 @@
return
results
;
};
// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
highlighter
=
function
(
element
,
text
,
matches
)
{
var
highlightText
,
j
,
lastIndex
,
len
,
matchIndex
,
matchedChars
,
unmatched
;
lastIndex
=
0
;
...
...
@@ -110,6 +118,7 @@
return
element
.
append
(
document
.
createTextNode
(
text
.
substring
(
lastIndex
)));
};
// make tbody row html
ProjectFindFile
.
prototype
.
makeHtml
=
function
(
filePath
,
matches
,
blobItemUrl
)
{
var
$tr
;
$tr
=
$
(
"
<tr class='tree-item'><td class='tree-item-file-name'><i class='fa fa-file-text-o fa-fw'></i><span class='str-truncated'><a></a></span></td></tr>
"
);
...
...
app/assets/javascripts/project_show.js
View file @
2cad277d
...
...
@@ -7,3 +7,5 @@
})();
}).
call
(
this
);
// I kept class for future
app/assets/javascripts/projects_list.js
View file @
2cad277d
...
...
@@ -33,6 +33,7 @@
$
(
'
.projects-list-holder
'
).
replaceWith
(
data
.
html
);
return
history
.
replaceState
({
page
:
project_filter_url
// Change url so if user reload a page - search results are saved
},
document
.
title
,
project_filter_url
);
},
dataType
:
"
json
"
...
...
app/assets/javascripts/protected_branch_dropdown.js.es6
View file @
2cad277d
...
...
@@ -45,6 +45,7 @@ class ProtectedBranchDropdown {
}
onClickCreateWildcard() {
// Refresh the dropdown's data, which ends up calling `getProtectedBranches`
this.$dropdown.data('glDropdown').remote.execute();
this.$dropdown.data('glDropdown').selectRowAtIndex(0);
}
...
...
app/assets/javascripts/search_autocomplete.js
View file @
2cad277d
...
...
@@ -24,6 +24,7 @@
this
.
onSearchInputKeyUp
=
bind
(
this
.
onSearchInputKeyUp
,
this
);
this
.
onSearchInputKeyDown
=
bind
(
this
.
onSearchInputKeyDown
,
this
);
this
.
wrap
=
(
ref
=
opts
.
wrap
)
!=
null
?
ref
:
$
(
'
.search
'
),
this
.
optsEl
=
(
ref1
=
opts
.
optsEl
)
!=
null
?
ref1
:
this
.
wrap
.
find
(
'
.search-autocomplete-opts
'
),
this
.
autocompletePath
=
(
ref2
=
opts
.
autocompletePath
)
!=
null
?
ref2
:
this
.
optsEl
.
data
(
'
autocomplete-path
'
),
this
.
projectId
=
(
ref3
=
opts
.
projectId
)
!=
null
?
ref3
:
this
.
optsEl
.
data
(
'
autocomplete-project-id
'
)
||
''
,
this
.
projectRef
=
(
ref4
=
opts
.
projectRef
)
!=
null
?
ref4
:
this
.
optsEl
.
data
(
'
autocomplete-project-ref
'
)
||
''
;
// Dropdown Element
this
.
dropdown
=
this
.
wrap
.
find
(
'
.dropdown
'
);
this
.
dropdownContent
=
this
.
dropdown
.
find
(
'
.dropdown-content
'
);
this
.
locationBadgeEl
=
this
.
getElement
(
'
.location-badge
'
);
...
...
@@ -35,6 +36,7 @@
this
.
repositoryInputEl
=
this
.
getElement
(
'
#repository_ref
'
);
this
.
clearInput
=
this
.
getElement
(
'
.js-clear-input
'
);
this
.
saveOriginalState
();
// Only when user is logged in
if
(
gon
.
current_user_id
)
{
this
.
createAutocomplete
();
}
...
...
@@ -43,6 +45,7 @@
this
.
bindEvents
();
}
// Finds an element inside wrapper element
SearchAutocomplete
.
prototype
.
getElement
=
function
(
selector
)
{
return
this
.
wrap
.
find
(
selector
);
};
...
...
@@ -82,6 +85,7 @@
}
return
;
}
// Prevent multiple ajax calls
if
(
this
.
loadingSuggestions
)
{
return
;
}
...
...
@@ -92,14 +96,17 @@
term
:
term
},
function
(
response
)
{
var
data
,
firstCategory
,
i
,
lastCategory
,
len
,
suggestion
;
// Hide dropdown menu if no suggestions returns
if
(
!
response
.
length
)
{
_this
.
disableAutocomplete
();
return
;
}
data
=
[];
// List results
firstCategory
=
true
;
for
(
i
=
0
,
len
=
response
.
length
;
i
<
len
;
i
++
)
{
suggestion
=
response
[
i
];
// Add group header before list each group
if
(
lastCategory
!==
suggestion
.
category
)
{
if
(
!
firstCategory
)
{
data
.
push
(
'
separator
'
);
...
...
@@ -119,6 +126,7 @@
url
:
suggestion
.
url
});
}
// Add option to proceed with the search
if
(
data
.
length
)
{
data
.
push
(
'
separator
'
);
data
.
push
({
...
...
@@ -169,11 +177,13 @@
SearchAutocomplete
.
prototype
.
serializeState
=
function
()
{
return
{
// Search Criteria
search_project_id
:
this
.
projectInputEl
.
val
(),
group_id
:
this
.
groupInputEl
.
val
(),
search_code
:
this
.
searchCodeInputEl
.
val
(),
repository_ref
:
this
.
repositoryInputEl
.
val
(),
scope
:
this
.
scopeInputEl
.
val
(),
// Location badge
_location
:
this
.
locationBadgeEl
.
text
()
};
};
...
...
@@ -194,6 +204,7 @@
SearchAutocomplete
.
prototype
.
enableAutocomplete
=
function
()
{
var
_this
;
// No need to enable anything if user is not logged in
if
(
!
gon
.
current_user_id
)
{
return
;
}
...
...
@@ -206,18 +217,22 @@
};
SearchAutocomplete
.
prototype
.
onSearchInputKeyDown
=
function
()
{
// Saves last length of the entered text
return
this
.
saveTextLength
();
};
SearchAutocomplete
.
prototype
.
onSearchInputKeyUp
=
function
(
e
)
{
switch
(
e
.
keyCode
)
{
case
KEYCODE
.
BACKSPACE
:
// when trying to remove the location badge
if
(
this
.
lastTextLength
===
0
&&
this
.
badgePresent
())
{
this
.
removeLocationBadge
();
}
// When removing the last character and no badge is present
if
(
this
.
lastTextLength
===
1
)
{
this
.
disableAutocomplete
();
}
// When removing any character from existin value
if
(
this
.
lastTextLength
>
1
)
{
this
.
enableAutocomplete
();
}
...
...
@@ -232,9 +247,12 @@
case
KEYCODE
.
DOWN
:
return
;
default
:
// Handle the case when deleting the input value other than backspace
// e.g. Pressing ctrl + backspace or ctrl + x
if
(
this
.
searchInput
.
val
()
===
''
)
{
this
.
disableAutocomplete
();
}
else
{
// We should display the menu only when input is not empty
if
(
e
.
keyCode
!==
KEYCODE
.
ENTER
)
{
this
.
enableAutocomplete
();
}
...
...
@@ -243,7 +261,9 @@
this
.
wrap
.
toggleClass
(
'
has-value
'
,
!!
e
.
target
.
value
);
};
// Avoid falsy value to be returned
SearchAutocomplete
.
prototype
.
onSearchInputClick
=
function
(
e
)
{
// Prevents closing the dropdown menu
return
e
.
stopImmediatePropagation
();
};
...
...
@@ -267,6 +287,7 @@
SearchAutocomplete
.
prototype
.
onSearchInputBlur
=
function
(
e
)
{
this
.
isFocused
=
false
;
this
.
wrap
.
removeClass
(
'
search-active
'
);
// If input is blank then restore state
if
(
this
.
searchInput
.
val
()
===
''
)
{
return
this
.
restoreOriginalState
();
}
...
...
@@ -311,6 +332,7 @@
results
=
[];
for
(
i
=
0
,
len
=
inputs
.
length
;
i
<
len
;
i
++
)
{
input
=
inputs
[
i
];
// _location isnt a input
if
(
input
===
'
_location
'
)
{
break
;
}
...
...
app/assets/javascripts/shortcuts.js
View file @
2cad277d
...
...
@@ -86,6 +86,7 @@
var
defaultStopCallback
;
defaultStopCallback
=
Mousetrap
.
stopCallback
;
return
function
(
e
,
element
,
combo
)
{
// allowed shortcuts if textarea, input, contenteditable are focused
if
([
'
ctrl+shift+p
'
,
'
command+shift+p
'
].
indexOf
(
combo
)
!==
-
1
)
{
return
false
;
}
else
{
...
...
app/assets/javascripts/shortcuts_find_file.js
View file @
2cad277d
...
...
@@ -14,8 +14,10 @@
ShortcutsFindFile
.
__super__
.
constructor
.
call
(
this
);
_oldStopCallback
=
Mousetrap
.
stopCallback
;
Mousetrap
.
stopCallback
=
(
function
(
_this
)
{
// override to fire shortcuts action when focus in textbox
return
function
(
event
,
element
,
combo
)
{
if
(
element
===
_this
.
projectFindFile
.
inputElement
[
0
]
&&
(
combo
===
'
up
'
||
combo
===
'
down
'
||
combo
===
'
esc
'
||
combo
===
'
enter
'
))
{
// when press up/down key in textbox, cusor prevent to move to home/end
event
.
preventDefault
();
return
false
;
}
...
...
app/assets/javascripts/shortcuts_issuable.js
View file @
2cad277d
/*= require mousetrap */
/*= require shortcuts_navigation */
(
function
()
{
...
...
@@ -43,16 +41,20 @@
if
(
selected
.
trim
()
===
""
)
{
return
;
}
// Put a '>' character before each non-empty line in the selection
quote
=
_
.
map
(
selected
.
split
(
"
\n
"
),
function
(
val
)
{
if
(
val
.
trim
()
!==
''
)
{
return
"
>
"
+
val
+
"
\n
"
;
}
});
// If replyField already has some content, add a newline before our quote
separator
=
replyField
.
val
().
trim
()
!==
""
&&
"
\n
"
||
''
;
replyField
.
val
(
function
(
_
,
current
)
{
return
current
+
separator
+
quote
.
join
(
''
)
+
"
\n
"
;
});
// Trigger autosave for the added text
replyField
.
trigger
(
'
input
'
);
// Focus the input field
return
replyField
.
focus
();
}
};
...
...
app/assets/javascripts/syntax_highlight.js
View file @
2cad277d
// Syntax Highlighter
//
// Applies a syntax highlighting color scheme CSS class to any element with the
// `js-syntax-highlight` class
//
// ### Example Markup
//
// <div class="js-syntax-highlight"></div>
//
(
function
()
{
$
.
fn
.
syntaxHighlight
=
function
()
{
var
$children
;
if
(
$
(
this
).
hasClass
(
'
js-syntax-highlight
'
))
{
// Given the element itself, apply highlighting
return
$
(
this
).
addClass
(
gon
.
user_color_scheme
);
}
else
{
// Given a parent element, recurse to any of its applicable children
$children
=
$
(
this
).
find
(
'
.js-syntax-highlight
'
);
if
(
$children
.
length
)
{
return
$children
.
syntaxHighlight
();
...
...
app/assets/javascripts/todos.js
View file @
2cad277d
...
...
@@ -129,16 +129,21 @@
var
currPage
,
currPages
,
newPages
,
pageParams
,
url
;
currPages
=
this
.
getTotalPages
();
currPage
=
this
.
getCurrentPage
();
// Refresh if no remaining Todos
if
(
!
total
)
{
location
.
reload
();
return
;
}
// Do nothing if no pagination
if
(
!
currPages
)
{
return
;
}
newPages
=
Math
.
ceil
(
total
/
this
.
getTodosPerPage
());
// Includes query strings
url
=
location
.
href
;
// If new total of pages is different than we have now
if
(
newPages
!==
currPages
)
{
// Redirect to previous page if there's one available
if
(
currPages
>
1
&&
currPage
===
currPages
)
{
pageParams
=
{
page
:
currPages
-
1
...
...
@@ -155,6 +160,7 @@
if
(
!
todoLink
)
{
return
;
}
// Allow Meta-Click or Mouse3-click to open in a new tab
if
(
e
.
metaKey
||
e
.
which
===
2
)
{
e
.
preventDefault
();
return
window
.
open
(
todoLink
,
'
_blank
'
);
...
...
app/assets/javascripts/tree.js
View file @
2cad277d
...
...
@@ -2,6 +2,8 @@
this
.
TreeView
=
(
function
()
{
function
TreeView
()
{
this
.
initKeyNav
();
// Code browser tree slider
// Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
$
(
"
.tree-content-holder .tree-item
"
).
on
(
'
click
'
,
function
(
e
)
{
var
$clickedEl
,
path
;
$clickedEl
=
$
(
e
.
target
);
...
...
@@ -15,6 +17,7 @@
}
}
});
// Show the "Loading commit data" for only the first element
$
(
'
span.log_loading:first
'
).
removeClass
(
'
hide
'
);
}
...
...
app/assets/javascripts/u2f/authenticate.js
View file @
2cad277d
// Authenticate U2F (universal 2nd factor) devices for users to authenticate with.
//
// State Flow #1: setup -> in_progress -> authenticated -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup
(
function
()
{
var
bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
};
...
...
@@ -15,6 +19,17 @@
this
.
appId
=
u2fParams
.
app_id
;
this
.
challenge
=
u2fParams
.
challenge
;
this
.
signRequests
=
u2fParams
.
sign_requests
.
map
(
function
(
request
)
{
// The U2F Javascript API v1.1 requires a single challenge, with
// _no challenges per-request_. The U2F Javascript API v1.0 requires a
// challenge per-request, which is done by copying the single challenge
// into every request.
//
// In either case, we don't need the per-request challenges that the server
// has generated, so we can remove them.
//
// Note: The server library fixes this behaviour in (unreleased) version 1.0.0.
// This can be removed once we upgrade.
// https://github.com/castle/ruby-u2f/commit/103f428071a81cd3d5f80c2e77d522d5029946a4
return
_
(
request
).
omit
(
'
challenge
'
);
});
}
...
...
@@ -41,6 +56,7 @@
})(
this
),
10
);
};
// Rendering #
U2FAuthenticate
.
prototype
.
templates
=
{
"
notSupported
"
:
"
#js-authenticate-u2f-not-supported
"
,
"
setup
"
:
'
#js-authenticate-u2f-setup
'
,
...
...
@@ -75,6 +91,8 @@
U2FAuthenticate
.
prototype
.
renderAuthenticated
=
function
(
deviceResponse
)
{
this
.
renderTemplate
(
'
authenticated
'
);
// Prefer to do this instead of interpolating using Underscore templates
// because of JSON escaping issues.
return
this
.
container
.
find
(
"
#js-device-response
"
).
val
(
deviceResponse
);
};
...
...
app/assets/javascripts/u2f/register.js
View file @
2cad277d
// Register U2F (universal 2nd factor) devices for users to authenticate with.
//
// State Flow #1: setup -> in_progress -> registered -> POST to server
// State Flow #2: setup -> in_progress -> error -> setup
(
function
()
{
var
bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
};
...
...
@@ -39,6 +43,7 @@
})(
this
),
10
);
};
// Rendering #
U2FRegister
.
prototype
.
templates
=
{
"
notSupported
"
:
"
#js-register-u2f-not-supported
"
,
"
setup
"
:
'
#js-register-u2f-setup
'
,
...
...
@@ -73,6 +78,8 @@
U2FRegister
.
prototype
.
renderRegistered
=
function
(
deviceResponse
)
{
this
.
renderTemplate
(
'
registered
'
);
// Prefer to do this instead of interpolating using Underscore templates
// because of JSON escaping issues.
return
this
.
container
.
find
(
"
#js-device-response
"
).
val
(
deviceResponse
);
};
...
...
app/assets/javascripts/user_tabs.js
View file @
2cad277d
// UserTabs
//
// Handles persisting and restoring the current tab selection and lazily-loading
// content on the Users#show page.
//
// ### Example Markup
//
// <ul class="nav-links">
// <li class="activity-tab active">
// <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
// Activity
// </a>
// </li>
// <li class="groups-tab">
// <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
// Groups
// </a>
// </li>
// <li class="contributed-tab">
// <a data-action="contributed" data-target="#contributed" data-toggle="tab" href="/u/username/contributed">
// Contributed projects
// </a>
// </li>
// <li class="projects-tab">
// <a data-action="projects" data-target="#projects" data-toggle="tab" href="/u/username/projects">
// Personal projects
// </a>
// </li>
// <li class="snippets-tab">
// <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
// </a>
// </li>
// </ul>
//
// <div class="tab-content">
// <div class="tab-pane" id="activity">
// Activity Content
// </div>
// <div class="tab-pane" id="groups">
// Groups Content
// </div>
// <div class="tab-pane" id="contributed">
// Contributed projects content
// </div>
// <div class="tab-pane" id="projects">
// Projects content
// </div>
// <div class="tab-pane" id="snippets">
// Snippets content
// </div>
// </div>
//
// <div class="loading-status">
// <div class="loading">
// Loading Animation
// </div>
// </div>
//
(
function
()
{
var
bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
};
...
...
@@ -6,18 +64,23 @@
this
.
tabShown
=
bind
(
this
.
tabShown
,
this
);
var
i
,
item
,
len
,
ref
,
ref1
,
ref2
,
ref3
;
this
.
action
=
(
ref
=
opts
.
action
)
!=
null
?
ref
:
'
activity
'
,
this
.
defaultAction
=
(
ref1
=
opts
.
defaultAction
)
!=
null
?
ref1
:
'
activity
'
,
this
.
parentEl
=
(
ref2
=
opts
.
parentEl
)
!=
null
?
ref2
:
$
(
document
);
// Make jQuery object if selector is provided
if
(
typeof
this
.
parentEl
===
'
string
'
)
{
this
.
parentEl
=
$
(
this
.
parentEl
);
}
// Store the `location` object, allowing for easier stubbing in tests
this
.
_location
=
location
;
// Set tab states
this
.
loaded
=
{};
ref3
=
this
.
parentEl
.
find
(
'
.nav-links a
'
);
for
(
i
=
0
,
len
=
ref3
.
length
;
i
<
len
;
i
++
)
{
item
=
ref3
[
i
];
this
.
loaded
[
$
(
item
).
attr
(
'
data-action
'
)]
=
false
;
}
// Actions
this
.
actions
=
Object
.
keys
(
this
.
loaded
);
this
.
bindEvents
();
// Set active tab
if
(
this
.
action
===
'
show
'
)
{
this
.
action
=
this
.
defaultAction
;
}
...
...
@@ -25,6 +88,7 @@
}
UserTabs
.
prototype
.
bindEvents
=
function
()
{
// Toggle event listeners
return
this
.
parentEl
.
off
(
'
shown.bs.tab
'
,
'
.nav-links a[data-toggle="tab"]
'
).
on
(
'
shown.bs.tab
'
,
'
.nav-links a[data-toggle="tab"]
'
,
this
.
tabShown
);
};
...
...
@@ -74,6 +138,7 @@
tabSelector
=
'
div#
'
+
action
;
_this
.
parentEl
.
find
(
tabSelector
).
html
(
data
.
html
);
_this
.
loaded
[
action
]
=
true
;
// Fix tooltips
return
gl
.
utils
.
localTimeAgo
(
$
(
'
.js-timeago
'
,
tabSelector
));
};
})(
this
)
...
...
@@ -97,13 +162,17 @@
UserTabs
.
prototype
.
setCurrentAction
=
function
(
action
)
{
var
new_state
,
regExp
;
// Remove possible actions from URL
regExp
=
new
RegExp
(
'
\
/(
'
+
this
.
actions
.
join
(
'
|
'
)
+
'
)(
\
.html)?
\
/?$
'
);
new_state
=
this
.
_location
.
pathname
;
// remove trailing slashes
new_state
=
new_state
.
replace
(
/
\/
+$/
,
""
);
new_state
=
new_state
.
replace
(
regExp
,
''
);
// Append the new action if we're on a tab other than 'activity'
if
(
action
!==
this
.
defaultAction
)
{
new_state
+=
"
/
"
+
action
;
}
// Ensure parameters and hash come along for the ride
new_state
+=
this
.
_location
.
search
+
this
.
_location
.
hash
;
history
.
replaceState
({
turbolinks
:
true
,
...
...
app/assets/javascripts/users/calendar.js
View file @
2cad277d
...
...
@@ -11,6 +11,8 @@
this
.
daySizeWithSpace
=
this
.
daySize
+
(
this
.
daySpace
*
2
);
this
.
monthNames
=
[
'
Jan
'
,
'
Feb
'
,
'
Mar
'
,
'
Apr
'
,
'
May
'
,
'
Jun
'
,
'
Jul
'
,
'
Aug
'
,
'
Sep
'
,
'
Oct
'
,
'
Nov
'
,
'
Dec
'
];
this
.
months
=
[];
// Loop through the timestamps to create a group of objects
// The group of objects will be grouped based on the day of the week they are
this
.
timestampsTmp
=
[];
var
group
=
0
;
...
...
@@ -29,12 +31,15 @@
var
day
=
date
.
getDay
();
var
count
=
timestamps
[
date
.
getTime
()
*
0.001
];
// Create a new group array if this is the first day of the week
// or if is first object
if
((
day
===
0
&&
i
!==
0
)
||
i
===
0
)
{
this
.
timestampsTmp
.
push
([]);
group
++
;
}
var
innerArray
=
this
.
timestampsTmp
[
group
-
1
];
// Push to the inner array the values that will be used to render map
innerArray
.
push
({
count
:
count
||
0
,
date
:
date
,
...
...
@@ -42,8 +47,10 @@
});
}
// Init color functions
this
.
colorKey
=
this
.
initColorKey
();
this
.
color
=
this
.
initColor
();
// Init the svg element
this
.
renderSvg
(
group
);
this
.
renderDays
();
this
.
renderMonths
();
...
...
app/assets/javascripts/users/users_bundle.js
View file @
2cad277d
...
...
@@ -3,5 +3,4 @@
(
function
()
{
}).
call
(
this
);
app/assets/javascripts/users_select.js
View file @
2cad277d
...
...
@@ -81,6 +81,7 @@
if
(
term
.
length
===
0
)
{
showDivider
=
0
;
if
(
firstUser
)
{
// Move current user to the front of the list
for
(
index
=
j
=
0
,
len
=
users
.
length
;
j
<
len
;
index
=
++
j
)
{
obj
=
users
[
index
];
if
(
obj
.
username
===
firstUser
)
{
...
...
@@ -115,6 +116,7 @@
if
(
showDivider
)
{
users
.
splice
(
showDivider
,
0
,
"
divider
"
);
}
// Send the data back
return
callback
(
users
);
});
},
...
...
@@ -139,6 +141,7 @@
inputId
:
'
issue_assignee_id
'
,
hidden
:
function
(
e
)
{
$selectbox
.
hide
();
// display:block overrides the hide-collapse rule
return
$value
.
css
(
'
display
'
,
''
);
},
clicked
:
function
(
user
,
$el
,
e
)
{
...
...
@@ -177,6 +180,7 @@
img
=
"
<img src='
"
+
avatar
+
"
' class='avatar avatar-inline' width='30' />
"
;
}
}
// split into three parts so we can remove the username section if nessesary
listWithName
=
"
<li> <a href='#' class='dropdown-menu-user-link
"
+
selected
+
"
'>
"
+
img
+
"
<strong class='dropdown-menu-user-full-name'>
"
+
user
.
name
+
"
</strong>
"
;
listWithUserName
=
"
<span class='dropdown-menu-user-username'>
"
+
username
+
"
</span>
"
;
listClosingTags
=
"
</a> </li>
"
;
...
...
@@ -215,6 +219,7 @@
};
if
(
query
.
term
.
length
===
0
)
{
if
(
firstUser
)
{
// Move current user to the front of the list
ref
=
data
.
results
;
for
(
index
=
j
=
0
,
len
=
ref
.
length
;
j
<
len
;
index
=
++
j
)
{
obj
=
ref
[
index
];
...
...
@@ -271,6 +276,7 @@
return
_this
.
formatSelection
.
apply
(
_this
,
args
);
},
dropdownCssClass
:
"
ajax-users-dropdown
"
,
// we do not want to escape markup since we are displaying html in results
escapeMarkup
:
function
(
m
)
{
return
m
;
}
...
...
@@ -318,6 +324,8 @@
});
};
// Return users list. Filtered by query
// Only active users retrieved
UsersSelect
.
prototype
.
users
=
function
(
query
,
options
,
callback
)
{
var
url
;
url
=
this
.
buildUrl
(
this
.
usersPath
);
...
...
app/assets/javascripts/zen_mode.js
View file @
2cad277d
// Zen Mode (full screen) textarea
//
/*= provides zen_mode:enter */
/*= provides zen_mode:leave */
//
/*= require jquery.scrollTo */
/*= require dropzone */
/*= require mousetrap */
/*= require mousetrap/pause */
//
// ### Events
//
// `zen_mode:enter`
//
// Fired when the "Edit in fullscreen" link is clicked.
//
// **Synchronicity** Sync
// **Bubbles** Yes
// **Cancelable** No
// **Target** a.js-zen-enter
//
// `zen_mode:leave`
//
// Fired when the "Leave Fullscreen" link is clicked.
//
// **Synchronicity** Sync
// **Bubbles** Yes
// **Cancelable** No
// **Target** a.js-zen-leave
//
(
function
()
{
this
.
ZenMode
=
(
function
()
{
function
ZenMode
()
{
...
...
@@ -40,6 +53,7 @@
};
})(
this
));
$
(
document
).
on
(
'
keydown
'
,
function
(
e
)
{
// Esc
if
(
e
.
keyCode
===
27
)
{
e
.
preventDefault
();
return
$
(
document
).
trigger
(
'
zen_mode:leave
'
);
...
...
@@ -52,6 +66,7 @@
this
.
active_backdrop
=
$
(
backdrop
);
this
.
active_backdrop
.
addClass
(
'
fullscreen
'
);
this
.
active_textarea
=
this
.
active_backdrop
.
find
(
'
textarea
'
);
// Prevent a user-resized textarea from persisting to fullscreen
this
.
active_textarea
.
removeAttr
(
'
style
'
);
return
this
.
active_textarea
.
focus
();
};
...
...
spec/javascripts/awards_handler_spec.js
View file @
2cad277d
/*= require awards_handler */
/*= require jquery */
/*= require jquery.cookie */
/*= require ./fixtures/emoji_menu */
(
function
()
{
...
...
@@ -33,6 +27,7 @@
return
setTimeout
(
function
()
{
assertFn
();
return
done
();
// Maybe jasmine.clock here?
},
333
);
};
...
...
spec/javascripts/behaviors/quick_submit_spec.js
View file @
2cad277d
...
...
@@ -8,6 +8,7 @@
beforeEach
(
function
()
{
fixture
.
load
(
'
behaviors/quick_submit.html
'
);
$
(
'
form
'
).
submit
(
function
(
e
)
{
// Prevent a form submit from moving us off the testing page
return
e
.
preventDefault
();
});
return
this
.
spies
=
{
...
...
@@ -38,6 +39,8 @@
expect
(
$
(
'
input[type=submit]
'
)).
toBeDisabled
();
return
expect
(
$
(
'
button[type=submit]
'
)).
toBeDisabled
();
});
// We cannot stub `navigator.userAgent` for CI's `rake teaspoon` task, so we'll
// only run the tests that apply to the current platform
if
(
navigator
.
userAgent
.
match
(
/Macintosh/
))
{
it
(
'
responds to Meta+Enter
'
,
function
()
{
$
(
'
input.quick-submit-input
'
).
trigger
(
keydownEvent
());
...
...
spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
View file @
2cad277d
...
...
@@ -7,7 +7,7 @@ describe("ContributorsGraph", function () {
expect
(
ContributorsGraph
.
prototype
.
x_domain
).
toEqual
(
20
)
})
})
describe
(
"
#set_y_domain
"
,
function
()
{
it
(
"
sets the y_domain
"
,
function
()
{
ContributorsGraph
.
set_y_domain
([{
commits
:
30
}])
...
...
@@ -89,7 +89,7 @@ describe("ContributorsGraph", function () {
})
describe
(
"
ContributorsMasterGraph
"
,
function
()
{
// TODO: fix or remove
//describe("#process_dates", function () {
//it("gets and parses dates", function () {
...
...
@@ -103,7 +103,7 @@ describe("ContributorsMasterGraph", function () {
//expect(graph.get_dates).toHaveBeenCalledWith(data)
//expect(ContributorsGraph.set_dates).toHaveBeenCalledWith("get")
//})
//})
//})
describe
(
"
#get_dates
"
,
function
()
{
it
(
"
plucks the date field from data collection
"
,
function
()
{
...
...
@@ -124,5 +124,5 @@ describe("ContributorsMasterGraph", function () {
})
})
})
spec/javascripts/issue_spec.js
View file @
2cad277d
/*= require lib/utils/text_utility */
/*= require issue */
(
function
()
{
...
...
spec/javascripts/new_branch_spec.js
View file @
2cad277d
/*= require jquery-ui/autocomplete */
/*= require new_branch_form */
(
function
()
{
...
...
spec/javascripts/project_title_spec.js
View file @
2cad277d
/*= require bootstrap */
/*= require select2 */
/*= require lib/utils/type_utility */
/*= require gl_dropdown */
/*= require api */
/*= require project_select */
/*= require project */
(
function
()
{
...
...
spec/javascripts/right_sidebar_spec.js
View file @
2cad277d
/*= require right_sidebar */
/*= require jquery */
/*= require jquery.cookie */
(
function
()
{
...
...
spec/javascripts/search_autocomplete_spec.js
View file @
2cad277d
/*= require gl_dropdown */
/*= require search_autocomplete */
/*= require jquery */
/*= require lib/utils/common_utils */
/*= require lib/utils/type_utility */
/*= require fuzzaldrin-plus */
(
function
()
{
...
...
@@ -43,6 +33,8 @@
groupName
=
'
Gitlab Org
'
;
// Add required attributes to body before starting the test.
// section would be dashboard|group|project
addBodyAttributes
=
function
(
section
)
{
var
$body
;
if
(
section
==
null
)
{
...
...
@@ -64,6 +56,7 @@
}
};
// Mock `gl` object in window for dashboard specific page. App code will need it.
mockDashboardOptions
=
function
()
{
window
.
gl
||
(
window
.
gl
=
{});
return
window
.
gl
.
dashboardOptions
=
{
...
...
@@ -72,6 +65,7 @@
};
};
// Mock `gl` object in window for project specific page. App code will need it.
mockProjectOptions
=
function
()
{
window
.
gl
||
(
window
.
gl
=
{});
return
window
.
gl
.
projectOptions
=
{
...
...
spec/javascripts/shortcuts_issuable_spec.js
View file @
2cad277d
...
...
@@ -10,6 +10,7 @@
});
return
describe
(
'
#replyWithSelectedText
'
,
function
()
{
var
stubSelection
;
// Stub window.getSelection to return the provided String.
stubSelection
=
function
(
text
)
{
return
window
.
getSelection
=
function
()
{
return
text
;
...
...
spec/javascripts/spec_helper.js
View file @
2cad277d
// PhantomJS (Teaspoons default driver) doesn't have support for
// Function.prototype.bind, which has caused confusion. Use this polyfill to
// avoid the confusion.
/*= require support/bind-poly */
// You can require your own javascript files here. By default this will include
// everything in application, however you may get better load performance if you
// require the specific files that are being used in the spec that tests them.
/*= require jquery */
/*= require jquery.turbolinks */
/*= require bootstrap */
/*= require underscore */
// Teaspoon includes some support files, but you can use anything from your own
// support path too.
// require support/jasmine-jquery-1.7.0
// require support/jasmine-jquery-2.0.0
/*= require support/jasmine-jquery-2.1.0 */
// require support/sinon
// require support/your-support-file
// Deferring execution
// If you're using CommonJS, RequireJS or some other asynchronous library you can
// defer execution. Call Teaspoon.execute() after everything has been loaded.
// Simple example of a timeout:
// Teaspoon.defer = true
// setTimeout(Teaspoon.execute, 1000)
// Matching files
// By default Teaspoon will look for files that match
// _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your spec path
// and it'll be included in the default suite automatically. If you want to
// customize suites, check out the configuration in teaspoon_env.rb
// Manifest
// If you'd rather require your spec files manually (to control order for
// instance) you can disable the suite matcher in the configuration and use this
// file as a manifest.
// For more information: http://github.com/modeset/teaspoon
(
function
()
{
...
...
spec/javascripts/u2f/authenticate_spec.js
View file @
2cad277d
/*= require u2f/authenticate */
/*= require u2f/util */
/*= require u2f/error */
/*= require u2f */
/*= require ./mock_u2f_device */
(
function
()
{
...
...
spec/javascripts/u2f/register_spec.js
View file @
2cad277d
/*= require u2f/register */
/*= require u2f/util */
/*= require u2f/error */
/*= require u2f */
/*= require ./mock_u2f_device */
(
function
()
{
...
...
spec/javascripts/zen_mode_spec.js
View file @
2cad277d
...
...
@@ -14,8 +14,10 @@
return
true
;
}
};
// Stub Dropzone.forElement(...).enable()
});
this
.
zen
=
new
ZenMode
();
// Set this manually because we can't actually scroll the window
return
this
.
zen
.
scroll_position
=
456
;
});
describe
(
'
on enter
'
,
function
()
{
...
...
@@ -60,7 +62,7 @@
return
$
(
'
a.js-zen-enter
'
).
click
();
};
exitZen
=
function
()
{
exitZen
=
function
()
{
// Ohmmmmmmm
return
$
(
'
a.js-zen-leave
'
).
click
();
};
...
...
vendor/assets/javascripts/task_list.js
View file @
2cad277d
// The MIT License (MIT)
//
// Copyright (c) 2014 GitHub, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TaskList Behavior
//
/*= provides tasklist:enabled */
/*= provides tasklist:disabled */
/*= provides tasklist:change */
/*= provides tasklist:changed */
//
//
// Enables Task List update behavior.
//
// ### Example Markup
//
// <div class="js-task-list-container">
// <ul class="task-list">
// <li class="task-list-item">
// <input type="checkbox" class="js-task-list-item-checkbox" disabled />
// text
// </li>
// </ul>
// <form>
// <textarea class="js-task-list-field">- [ ] text</textarea>
// </form>
// </div>
//
// ### Specification
//
// TaskLists MUST be contained in a `(div).js-task-list-container`.
//
// TaskList Items SHOULD be an a list (`UL`/`OL`) element.
//
// Task list items MUST match `(input).task-list-item-checkbox` and MUST be
// `disabled` by default.
//
// TaskLists MUST have a `(textarea).js-task-list-field` form element whose
// `value` attribute is the source (Markdown) to be udpated. The source MUST
// follow the syntax guidelines.
//
// TaskList updates trigger `tasklist:change` events. If the change is
// successful, `tasklist:changed` is fired. The change can be canceled.
//
// jQuery is required.
//
// ### Methods
//
// `.taskList('enable')` or `.taskList()`
//
// Enables TaskList updates for the container.
//
// `.taskList('disable')`
//
// Disables TaskList updates for the container.
//
//# ### Events
//
// `tasklist:enabled`
//
// Fired when the TaskList is enabled.
//
// * **Synchronicity** Sync
// * **Bubbles** Yes
// * **Cancelable** No
// * **Target** `.js-task-list-container`
//
// `tasklist:disabled`
//
// Fired when the TaskList is disabled.
//
// * **Synchronicity** Sync
// * **Bubbles** Yes
// * **Cancelable** No
// * **Target** `.js-task-list-container`
//
// `tasklist:change`
//
// Fired before the TaskList item change takes affect.
//
// * **Synchronicity** Sync
// * **Bubbles** Yes
// * **Cancelable** Yes
// * **Target** `.js-task-list-field`
//
// `tasklist:changed`
//
// Fired once the TaskList item change has taken affect.
//
// * **Synchronicity** Sync
// * **Bubbles** Yes
// * **Cancelable** No
// * **Target** `.js-task-list-field`
//
// ### NOTE
//
// Task list checkboxes are rendered as disabled by default because rendered
// user content is cached without regard for the viewer.
(
function
()
{
var
codeFencesPattern
,
complete
,
completePattern
,
disableTaskList
,
disableTaskLists
,
enableTaskList
,
enableTaskLists
,
escapePattern
,
incomplete
,
incompletePattern
,
itemPattern
,
itemsInParasPattern
,
updateTaskList
,
updateTaskListItem
,
indexOf
=
[].
indexOf
||
function
(
item
)
{
for
(
var
i
=
0
,
l
=
this
.
length
;
i
<
l
;
i
++
)
{
if
(
i
in
this
&&
this
[
i
]
===
item
)
return
i
;
}
return
-
1
;
};
...
...
@@ -18,20 +121,48 @@
complete
=
"
[x]
"
;
// Escapes the String for regular expression matching.
escapePattern
=
function
(
str
)
{
return
str
.
replace
(
/
([\[\]])
/g
,
"
\\
$1
"
).
replace
(
/
\s
/
,
"
\\
s
"
).
replace
(
"
x
"
,
"
[xX]
"
);
};
incompletePattern
=
RegExp
(
""
+
(
escapePattern
(
incomplete
)));
completePattern
=
RegExp
(
""
+
(
escapePattern
(
complete
)));
incompletePattern
=
RegExp
(
""
+
(
escapePattern
(
incomplete
)));
// escape square brackets
// match all white space
completePattern
=
RegExp
(
""
+
(
escapePattern
(
complete
)));
// match all cases
// Pattern used to identify all task list items.
// Useful when you need iterate over all items.
itemPattern
=
RegExp
(
"
^(?:
\\
s*(?:>
\\
s*)*(?:[-+*]|(?:
\\
d+
\\
.)))
\\
s*(
"
+
(
escapePattern
(
complete
))
+
"
|
"
+
(
escapePattern
(
incomplete
))
+
"
)
\\
s+(?!
\\
(.*?
\\
))(?=(?:
\\
[.*?
\\
]
\\
s*(?:
\\
[.*?
\\
]|
\\
(.*?
\\
))
\\
s*)*(?:[^
\\
[]|$))
"
);
// prefix, consisting of
// optional leading whitespace
// zero or more blockquotes
// list item indicator
// optional whitespace prefix
// checkbox
// is followed by whitespace
// is not part of a [foo](url) link
// and is followed by zero or more links
// and either a non-link or the end of the string
// Used to filter out code fences from the source for comparison only.
// http://rubular.com/r/x5EwZVrloI
// Modified slightly due to issues with JS
codeFencesPattern
=
/^`
{3}(?:\s
*
\w
+
)?[\S\s]
.*
[\S\s]
^`
{3}
$/mg
;
// ```
// followed by optional language
// whitespace
// code
// whitespace
// ```
// Used to filter out potential mismatches (items not in lists).
// http://rubular.com/r/OInl6CiePy
itemsInParasPattern
=
RegExp
(
"
^(
"
+
(
escapePattern
(
complete
))
+
"
|
"
+
(
escapePattern
(
incomplete
))
+
"
).+$
"
,
"
g
"
);
// Given the source text, updates the appropriate task list item to match the
// given checked value.
//
// Returns the updated String text.
updateTaskListItem
=
function
(
source
,
itemIndex
,
checked
)
{
var
clean
,
index
,
line
,
result
;
clean
=
source
.
replace
(
/
\r
/g
,
''
).
replace
(
codeFencesPattern
,
''
).
replace
(
itemsInParasPattern
,
''
).
split
(
"
\n
"
);
...
...
@@ -55,6 +186,9 @@
return
result
.
join
(
"
\n
"
);
};
// Updates the $field value to reflect the state of $item.
// Triggers the `tasklist:change` event before the value has changed, and fires
// a `tasklist:changed` event once the value has changed.
updateTaskList
=
function
(
$item
)
{
var
$container
,
$field
,
checked
,
event
,
index
;
$container
=
$item
.
closest
(
'
.js-task-list-container
'
);
...
...
@@ -70,10 +204,12 @@
}
};
// When the task list item checkbox is updated, submit the change
$
(
document
).
on
(
'
change
'
,
'
.task-list-item-checkbox
'
,
function
()
{
return
updateTaskList
(
$
(
this
));
});
// Enables TaskList item changes.
enableTaskList
=
function
(
$container
)
{
if
(
$container
.
find
(
'
.js-task-list-field
'
).
length
>
0
)
{
$container
.
find
(
'
.task-list-item
'
).
addClass
(
'
enabled
'
).
find
(
'
.task-list-item-checkbox
'
).
attr
(
'
disabled
'
,
null
);
...
...
@@ -81,6 +217,7 @@
}
};
// Enables a collection of TaskList containers.
enableTaskLists
=
function
(
$containers
)
{
var
container
,
i
,
len
,
results
;
results
=
[];
...
...
@@ -91,11 +228,13 @@
return
results
;
};
// Disable TaskList item changes.
disableTaskList
=
function
(
$container
)
{
$container
.
find
(
'
.task-list-item
'
).
removeClass
(
'
enabled
'
).
find
(
'
.task-list-item-checkbox
'
).
attr
(
'
disabled
'
,
'
disabled
'
);
return
$container
.
removeClass
(
'
is-task-list-enabled
'
).
trigger
(
'
tasklist:disabled
'
);
};
// Disables a collection of TaskList containers.
disableTaskLists
=
function
(
$containers
)
{
var
container
,
i
,
len
,
results
;
results
=
[];
...
...
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