Index: trunk/extensions/Collection/Collection.php |
— | — | @@ -279,6 +279,24 @@ |
280 | 280 | |
281 | 281 | $wgAjaxExportList[] = 'wfAjaxCollectionClear'; |
282 | 282 | |
| 283 | +function wfAjaxCollectionGetPopupData( $title ) { |
| 284 | + wfLoadExtensionMessages( 'CollectionCore' ); |
| 285 | + $json = new Services_JSON(); |
| 286 | + $result = array(); |
| 287 | + if ( CollectionSession::findArticle( $title ) == -1 ) { |
| 288 | + $result['action'] = 'add'; |
| 289 | + $result['text'] = wfMsg( 'coll-add_linked_article', $title ); |
| 290 | + } else { |
| 291 | + $result['action'] = 'remove'; |
| 292 | + $result['text'] = wfMsg( 'coll-remove_linked_article', $title ); |
| 293 | + } |
| 294 | + $r = new AjaxResponse( $json->encode( $result ) ); |
| 295 | + $r->setContentType( 'application/json' ); |
| 296 | + return $r; |
| 297 | +} |
| 298 | + |
| 299 | +$wgAjaxExportList[] = 'wfAjaxCollectionGetPopupData'; |
| 300 | + |
283 | 301 | /** |
284 | 302 | * Backend of several following SAJAX function handlers... |
285 | 303 | * @param String $action provided by the specific handlers internally |
Index: trunk/extensions/Collection/Collection.hooks.php |
— | — | @@ -240,6 +240,7 @@ |
241 | 241 | global $wgCollectionStyleVersion; |
242 | 242 | global $wgCollectionVersion; |
243 | 243 | global $wgJsMimeType; |
| 244 | + global $wgOut; |
244 | 245 | global $wgScriptPath; |
245 | 246 | global $wgTitle; |
246 | 247 | global $wgUser; |
— | — | @@ -259,8 +260,21 @@ |
260 | 261 | $oldid = 0; |
261 | 262 | } |
262 | 263 | } |
| 264 | + |
263 | 265 | $html = ''; |
264 | 266 | |
| 267 | + if ( false && method_exists( $wgOut, 'includeJQuery' ) ) { |
| 268 | + $wgOut->includeJQuery(); |
| 269 | + } else { |
| 270 | + $html .= Xml::element( 'script', |
| 271 | + array( |
| 272 | + 'type' => $wgJsMimeType, |
| 273 | + 'src' => "$jsPath/jquery.js?$wgCollectionStyleVersion", |
| 274 | + ), |
| 275 | + '', false |
| 276 | + ); |
| 277 | + } |
| 278 | + |
265 | 279 | $html .= Xml::element( 'script', |
266 | 280 | array( |
267 | 281 | 'type' => $wgJsMimeType, |
— | — | @@ -268,6 +282,20 @@ |
269 | 283 | ), |
270 | 284 | '', false |
271 | 285 | ); |
| 286 | + $html .= Xml::element( 'style', |
| 287 | + array( 'type' => 'text/css' ), |
| 288 | + <<<EOS |
| 289 | +#collectionpopup { |
| 290 | + position: absolute; |
| 291 | + padding: 4px; |
| 292 | + border: 1px solid #000; |
| 293 | + background-color: #fea; |
| 294 | + z-index: 9999; |
| 295 | + display: inline; |
| 296 | +} |
| 297 | +EOS |
| 298 | + , false |
| 299 | + ); |
272 | 300 | |
273 | 301 | $addRemoveState = $mode; |
274 | 302 | |
Index: trunk/extensions/Collection/CollectionCore.i18n.php |
— | — | @@ -36,6 +36,8 @@ |
37 | 37 | 'coll-disable' => 'disable', |
38 | 38 | 'coll-book_creator_disable' => 'Disable book creator', |
39 | 39 | 'coll-book_creator_disable_tooltip' => 'Stop using the book creator', |
| 40 | + 'coll-add_linked_article' => 'Add page $1 to your book', |
| 41 | + 'coll-remove_linked_article' => 'Remove page $1 from your book', |
40 | 42 | 'coll-add_category' => 'Add this category to your book', |
41 | 43 | 'coll-add_category_tooltip' => 'Add all wiki pages in this category to your book', |
42 | 44 | 'coll-add_this_page' => 'Add this page to your book', |
Index: trunk/extensions/Collection/js/bookcreator.js |
— | — | @@ -24,20 +24,14 @@ |
25 | 25 | function refreshBookCreatorBox(hint, oldid) { |
26 | 26 | sajax_request_type = 'GET'; |
27 | 27 | sajax_do_call('wfAjaxCollectionGetBookCreatorBoxContent', [hint, oldid], function(xhr) { |
28 | | - document.getElementById('coll-book_creator_box').innerHTML = xhr.responseText; |
29 | | - if (hint && typeof wgCollectionAddRemoveState != 'undefined') { |
30 | | - wgCollectionAddRemoveState = hint; |
31 | | - } |
32 | | - if (typeof refreshCollectionArticleList == 'function') { |
33 | | - refreshCollectionArticleList(); |
34 | | - } |
| 28 | + $('#coll-book_creator_box').html(xhr.responseText); |
35 | 29 | }); |
36 | 30 | } |
37 | 31 | |
38 | 32 | function collectionCall(func, args) { |
39 | 33 | var hint = args.shift(); |
40 | 34 | sajax_request_type = 'POST'; |
41 | | - sajax_do_call('wfAjaxCollection' + func, args, function(xhr) { |
| 35 | + sajax_do_call('wfAjaxCollection' + func, args, function() { |
42 | 36 | var oldid = null; |
43 | 37 | if (args.length == 3) { |
44 | 38 | oldid = args[2]; |
— | — | @@ -48,4 +42,123 @@ |
49 | 43 | |
50 | 44 | window.collectionCall = collectionCall; // public |
51 | 45 | |
| 46 | + |
| 47 | +var mouse_pos = {}; |
| 48 | +var popup_div = null; |
| 49 | +var addremove_link = null; |
| 50 | +var visible = false; |
| 51 | +var show_soon_timeout = null; |
| 52 | +var get_data_xhr = null; |
| 53 | +var script_url = wgServer + ((wgScript == null) ? (wgScriptPath + "/index.php") : wgScript); |
| 54 | + |
| 55 | +function createDiv() { |
| 56 | + addremove_link = $('<a href="javascript:void(0)" />'); |
| 57 | + popup_div = $('<div id="collectionpopup" />'); |
| 58 | + popup_div.append(addremove_link) |
| 59 | + $('body').append(popup_div); |
| 60 | + popup_div.hide(); |
| 61 | +} |
| 62 | + |
| 63 | +function addremove_article(action, title) { |
| 64 | + $.post(script_url, { |
| 65 | + 'action': 'ajax', |
| 66 | + 'rs': 'wfAjaxCollection' + action.charAt(0).toUpperCase() + action.slice(1) + 'Article', |
| 67 | + 'rsargs[]': [0, title, ''] |
| 68 | + }, function() { |
| 69 | + hide(); |
| 70 | + refreshBookCreatorBox(null, null); |
| 71 | + }); |
| 72 | +} |
| 73 | + |
| 74 | +function show(link) { |
| 75 | + if (visible) { |
| 76 | + return; |
| 77 | + } |
| 78 | + var title = link.attr('title'); |
| 79 | + show_soon_timeout = setTimeout(function() { |
| 80 | + get_data_xhr = $.post(script_url, { |
| 81 | + 'action': 'ajax', |
| 82 | + 'rs': 'wfAjaxCollectionGetPopupData', |
| 83 | + 'rsargs[]': [title] |
| 84 | + }, function(result) { |
| 85 | + visible = true; |
| 86 | + addremove_link |
| 87 | + .text(result.text) |
| 88 | + .unbind('click') |
| 89 | + .click(function(e) { addremove_article(result.action, title); }); |
| 90 | + popup_div |
| 91 | + .css({left: mouse_pos.x + 2 + 'px', |
| 92 | + top: mouse_pos.y + 2 + 'px'}) |
| 93 | + .show(); |
| 94 | + }, 'json'); |
| 95 | + }, 300); |
| 96 | +} |
| 97 | + |
| 98 | +function cancel_asyncs() { |
| 99 | + if (show_soon_timeout) { |
| 100 | + clearTimeout(show_soon_timeout); |
| 101 | + show_soon_timeout = null; |
| 102 | + } |
| 103 | + if (get_data_xhr) { |
| 104 | + get_data_xhr.abort(); |
| 105 | + get_data_xhr = null; |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +function hide() { |
| 110 | + cancel_asyncs(); |
| 111 | + if (!visible) { |
| 112 | + return; |
| 113 | + } |
| 114 | + visible = false; |
| 115 | + popup_div.hide(); |
| 116 | +} |
| 117 | + |
| 118 | +function is_inside(x, y, left, top, width, height) { |
| 119 | + var fuzz = 5; |
| 120 | + return x + fuzz >= left && x - fuzz <= left + width |
| 121 | + && y + fuzz >= top && y - fuzz <= top + height; |
| 122 | +} |
| 123 | + |
| 124 | +function check_popup_hide() { |
| 125 | + if (!visible) { |
| 126 | + return; |
| 127 | + } |
| 128 | + var pos = popup_div.offset(); |
| 129 | + if (!is_inside(mouse_pos.x, mouse_pos.y, |
| 130 | + pos.left, pos.top, popup_div.width(), popup_div.height())) { |
| 131 | + hide(); |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +$(function() { |
| 136 | + $(document).mousemove(function(e) { |
| 137 | + mouse_pos.x = e.pageX; |
| 138 | + mouse_pos.y = e.pageY; |
| 139 | + }); |
| 140 | + setInterval(check_popup_hide, 300); |
| 141 | + createDiv(); |
| 142 | + var prefix = wgArticlePath.replace(/\$1/, ''); |
| 143 | + $('#bodyContent ' |
| 144 | + + 'a[href^=' + prefix + ']' // URL starts with prefix of wgArticlePath |
| 145 | + + ':not(a[href~=index.php])' // URL doesn't contain index.php (simplification!) |
| 146 | + + '[title!=]' // title attribute is not empty |
| 147 | + + ':not([title~=:])' // title doesn't contain a ':' (simplification!) |
| 148 | + + '[rel!=nofollow]' |
| 149 | + + ':not(.external)' |
| 150 | + + ':not(.sortheader)' |
| 151 | + + ':not([accesskey])' |
| 152 | + + ':not(.nopopup)' |
| 153 | + ).each(function(i, link) { |
| 154 | + if (this.onmousedown) { |
| 155 | + return; |
| 156 | + } |
| 157 | + var $this = $(this); |
| 158 | + if ($this.parents('.nopopups').length) { |
| 159 | + return; |
| 160 | + } |
| 161 | + $this.hover(function() { show($this); }, cancel_asyncs); |
| 162 | + }); |
| 163 | +}); |
| 164 | + |
52 | 165 | })(); |