diff --git a/app/assets/javascripts/copy_to_clipboard.js.coffee b/app/assets/javascripts/copy_to_clipboard.js.coffee
index 9c68c5cc1bcdf377edf3a958c7dc5ffc2dc50554..24301e01b10de7394f68498b8f1c1627274acba3 100644
--- a/app/assets/javascripts/copy_to_clipboard.js.coffee
+++ b/app/assets/javascripts/copy_to_clipboard.js.coffee
@@ -1,32 +1,37 @@
 #= require clipboard
 
-$ ->
-  clipboard = new Clipboard '.js-clipboard-trigger',
-    text: (trigger) ->
-      $target = $(trigger.nextElementSibling || trigger.previousElementSibling)
-      $target.data('clipboard-text') || $target.text().trim()
+genericSuccess = (e) ->
+  showTooltip(e.trigger, 'Copied!')
+
+  # Clear the selection and blur the trigger so it loses its border
+  e.clearSelection()
+  $(e.trigger).blur()
 
-  clipboard.on 'success', (e) ->
-    $(e.trigger).
-      tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
-      tooltip('show').
-      one('mouseleave', -> $(this).tooltip('hide'))
+# Safari doesn't support `execCommand`, so instead we inform the user to
+# copy manually.
+#
+# See http://clipboardjs.com/#browser-support
+genericError = (e) ->
+  if /Mac/i.test(navigator.userAgent)
+    key = '⌘' # Command
+  else
+    key = 'Ctrl'
 
-    # Clear the selection and blur the trigger so it loses its border
-    e.clearSelection()
-    $(e.trigger).blur()
+  showTooltip(e.trigger, "Press #{key}-C to copy")
 
-  # Safari doesn't support `execCommand`, so instead we inform the user to
-  # copy manually.
-  #
-  # See http://clipboardjs.com/#browser-support
-  clipboard.on 'error', (e) ->
-    if /Mac/i.test(navigator.userAgent)
-      title = "Press ⌘-C to copy"
-    else
-      title = "Press Ctrl-C to copy"
+showTooltip = (target, title) ->
+  $(target).
+    tooltip(
+      container: 'body'
+      html: 'true'
+      placement: 'auto bottom'
+      title: title
+      trigger: 'manual'
+    ).
+    tooltip('show').
+    one('mouseleave', -> $(this).tooltip('hide'))
 
-    $(e.trigger).
-      tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title).
-      tooltip('show').
-      one('mouseleave', -> $(this).tooltip('hide'))
+$ ->
+  clipboard = new Clipboard '[data-clipboard-target], [data-clipboard-text]'
+  clipboard.on 'success', genericSuccess
+  clipboard.on 'error',   genericError
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index bbb35afca89e0d9335169c0af3df9b0123ebc924..b9bb1ac8d88f4e830e13b7fce9627b99da9ef614 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -1,8 +1,24 @@
 module ButtonHelper
-  def clipboard_button
+  # Output a "Copy to Clipboard" button
+  #
+  # data - Data attributes passed to `content_tag`
+  #
+  # Examples:
+  #
+  #   # Define the clipboard's text
+  #   clipboard_button(clipboard_text: "Foo")
+  #   # => "<button class='...' data-clipboard-text='Foo'>...</button>"
+  #
+  #   # Define the target element
+  #   clipboard_button(clipboard_target: "#foo")
+  #   # => "<button class='...' data-clipboard-target='#foo'>...</button>"
+  #
+  # See http://clipboardjs.com/#usage
+  def clipboard_button(data = {})
     content_tag :button,
       icon('clipboard'),
-      class: 'btn btn-xs btn-clipboard js-clipboard-trigger',
+      class: 'btn btn-xs btn-clipboard',
+      data: data,
       type: :button
   end
 
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 805be332e64510002ec7d9f7a754fe4a0a78387c..2e489a0a4d5b6646b105e7948b75349a6279a411 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -20,8 +20,8 @@
         - if ci_commit
           = render_ci_status(ci_commit)
           &nbsp;
-        = clipboard_button
-        = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id", data: {clipboard_text: commit.id}
+        = clipboard_button(clipboard_text: commit.id)
+        = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
 
       .notes_count
         - if note_count > 0
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 020952dd0016978a95fd8af1c0bfa3b26da2667b..8f0a1ed9be2f3ede2e47fe7a3e1a0991921ef42a 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -18,9 +18,9 @@
           = link_to_member(@project, participant, name: false, size: 24)
     .col-md-3
       .input-group.cross-project-reference
-        %span.slead.has_tooltip{title: 'Cross-project reference'}
+        %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
           = cross_project_reference(@project, @issue)
-        = clipboard_button
+        = clipboard_button(clipboard_target: '#cross-project-reference')
 
 .row
   %section.col-md-9
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index cb75bd8c5bae19348e21a029f42abad92bef0580..2b3c3eff5e4e3166f88ebb2868c6379da25b1bdc 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -15,9 +15,9 @@
       = render "projects/merge_requests/show/participants"
     .col-md-3
       .input-group.cross-project-reference
-        %span.slead.has_tooltip{title: 'Cross-project reference'}
+        %span#cross-project-reference.slead.has_tooltip{title: 'Cross-project reference'}
           = cross_project_reference(@project, @merge_request)
-        = clipboard_button
+        = clipboard_button(clipboard_target: '#cross-project-reference')
 
 .row
   %section.col-md-9