parent
419c42b0aa
commit
6b885bbc56
@ -1,49 +0,0 @@ |
||||
.js-gs-share, .gs-share [aria-hidden="true"], .gs-share-form[aria-hidden="true"] { |
||||
display: none; |
||||
} |
||||
|
||||
.js-gs-share-enabled .js-gs-share { |
||||
display: inline; |
||||
float: left; |
||||
} |
||||
|
||||
.gs-share .js-gs-share[href] { |
||||
display: inline; |
||||
} |
||||
|
||||
.gs-share [aria-hidden="false"], .gs-share-form[aria-hidden="false"] { |
||||
display: block; |
||||
margin-top: 40px; |
||||
} |
||||
|
||||
.gs-share { |
||||
position: relative; |
||||
} |
||||
|
||||
.gs-share-form { |
||||
background: #FFF; |
||||
border: 1px solid #000; |
||||
border-radius: 5px; |
||||
padding: 5px; |
||||
position: absolute; |
||||
z-index: 1; |
||||
} |
||||
|
||||
.gs-share [for="gs-account"], .gs-share [type="text"] { |
||||
display: block; |
||||
margin-bottom: 8px; |
||||
} |
||||
|
||||
.gs-share [type="submit"] { |
||||
display: block; |
||||
margin-top: 8px; |
||||
} |
||||
|
||||
.gs-share--icon { |
||||
border: none; |
||||
cursor: pointer; |
||||
min-height: 32px; |
||||
padding: 0; |
||||
padding-left: 33px; |
||||
background: transparent url('../../../img/gs-share.png') no-repeat left center; |
||||
} |
||||
|
Before Width: | Height: | Size: 3.8 KiB |
@ -1,206 +0,0 @@ |
||||
/* This Source Code Form is subject to the terms of the Mozilla Public |
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// @license magnet:?xt=urn:btih:3877d6d54b3accd4bc32f8a48bf32ebc0901502a&dn=mpl-2.0.txt MPL 2.0
|
||||
document.addEventListener('DOMContentLoaded', function () { |
||||
'use strict'; |
||||
/** |
||||
* 'Share' widget for GNU social |
||||
* http://code.chromic.org/project/view/2/
|
||||
* |
||||
* We make a few assumptions about the target instance: |
||||
* 1) The API root is in the default location |
||||
* 2) Fancy URLs are enabled |
||||
* 3) CORS is allowed |
||||
* 4) The Bookmark plugin is enabled |
||||
* |
||||
* If 1), 3) or 4) are wrong, we fall back to a regular |
||||
* notice (instead of a bookmark notice) |
||||
* |
||||
* If 2) is wrong the user will be directed to a 404 :( |
||||
*/ |
||||
|
||||
// TODO: input sanitation [1], [2]
|
||||
// TODO: server-side fallback if JS is disabled
|
||||
|
||||
var createForm, |
||||
bindClicks, |
||||
frm, |
||||
shareAsNotice, |
||||
shareAsBookmark, |
||||
extractURLParams, |
||||
shareURL, |
||||
shareTitle, |
||||
closest, |
||||
i18n = window.i18n; |
||||
|
||||
/** |
||||
* Internationalization |
||||
*/ |
||||
if (i18n === undefined) { |
||||
i18n = { |
||||
invalidId: 'The account id provided is invalid', |
||||
yourAcctId: 'Your account ID:', |
||||
idPlaceholder: 'user@example.org', |
||||
shareAsBookmark: 'Share as a bookmark' |
||||
}; |
||||
} |
||||
|
||||
shareAsNotice = function (title, url, domain) { |
||||
window.open('http://' + domain + '/notice/new?status_textarea=' + title + ' ' + url); // [1]
|
||||
}; |
||||
|
||||
shareAsBookmark = function (title, url, domain) { |
||||
window.open('http://' + domain + '/main/bookmark/new?url=' + url + '&title=' + title); // [2]
|
||||
}; |
||||
|
||||
/** |
||||
* Extract parameters from query string |
||||
* |
||||
* ex: |
||||
* ?foo=bar&baz=test |
||||
* will return: |
||||
* {foo: 'bar', baz: 'test'} |
||||
*/ |
||||
extractURLParams = function (queryStr) { |
||||
var parts = queryStr.substr(1).split('&'), |
||||
i, len, keyVal, params = {}; |
||||
|
||||
for (i = 0, len = parts.length; i < len; i += 1) { |
||||
keyVal = parts[i].split('='); |
||||
params[keyVal[0]] = keyVal[1]; |
||||
} |
||||
|
||||
return params; |
||||
}; |
||||
|
||||
// Create the form that we'll re-use throughout the page
|
||||
createForm = function () { |
||||
var err = document.createElement('div'); |
||||
err.setAttribute('class', 'gs-share-err'); |
||||
err.setAttribute('tabindex', '-1'); |
||||
err.setAttribute('aria-hidden', 'true'); |
||||
err.textContent = i18n.invalidId; |
||||
|
||||
frm = document.createElement('form'); |
||||
|
||||
frm.setAttribute('class', 'gs-share-form'); |
||||
frm.setAttribute('tabindex', '-1'); |
||||
frm.setAttribute('aria-hidden', 'true'); |
||||
|
||||
frm.innerHTML = '<label for="gs-account">' + i18n.yourAcctId + '</label>' + |
||||
'<input type="text" id="gs-account" placeholder="' + i18n.idPlaceholder + '" />' + |
||||
'<input type="checkbox" id="gs-bookmark" /> <label for="gs-bookmark">' + i18n.shareAsBookmark + '</label>' + |
||||
'<input type="submit" value="Share"/>'; |
||||
frm.insertBefore(err, frm.firstChild); |
||||
|
||||
// Submit handler
|
||||
frm.addEventListener('submit', function (e) { |
||||
e.preventDefault(); |
||||
|
||||
var accountParts = document.getElementById('gs-account').value.split('@'), |
||||
username, domain, xhr, bookmarkURL; |
||||
|
||||
if (accountParts.length === 2) { |
||||
err.setAttribute('aria-hidden', 'true'); |
||||
|
||||
username = accountParts[0]; |
||||
domain = accountParts[1]; |
||||
bookmarkURL = 'http://' + domain + '/api/bookmarks/' + username + '.json'; |
||||
|
||||
// Try bookmark
|
||||
if (document.getElementById('gs-bookmark').checked) { |
||||
xhr = new XMLHttpRequest(); |
||||
|
||||
xhr.onreadystatechange = function () { |
||||
if (xhr.readyState === 4) { |
||||
if (xhr.status === 200) { // Success
|
||||
shareAsBookmark(shareTitle, shareURL, domain); |
||||
} else { // Failure, fallback to regular notice
|
||||
shareAsNotice(shareTitle, shareURL, domain); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
xhr.open('GET', bookmarkURL, true); |
||||
xhr.send(); |
||||
} else { // Regular notice
|
||||
shareAsNotice(shareTitle, shareURL, domain); |
||||
} |
||||
} else { // Invalid account id
|
||||
err.setAttribute('aria-hidden', 'false'); |
||||
err.focus(); |
||||
} |
||||
}); |
||||
|
||||
// Keydown handler
|
||||
frm.addEventListener('keydown', function (e) { |
||||
if (e.keyCode === 27) { // Escape key closes the dialog
|
||||
frm.parentElement.getElementsByClassName('js-gs-share')[0].focus(); |
||||
frm.setAttribute('aria-hidden', 'true'); |
||||
} |
||||
}); |
||||
|
||||
document.body.appendChild(frm); |
||||
}; |
||||
|
||||
/** |
||||
* Something similar to jQuery.closest |
||||
* |
||||
* Given `elm`, return the closest parent with class `cls` |
||||
* or false if there is no matching ancestor. |
||||
*/ |
||||
closest = function (elm, cls) { |
||||
while (elm !== document) { |
||||
if (elm.classList.contains(cls)) { |
||||
return elm; |
||||
} |
||||
|
||||
elm = elm.parentNode; |
||||
} |
||||
|
||||
return false; |
||||
}; |
||||
|
||||
bindClicks = function () { |
||||
document.addEventListener('click', function (e) { |
||||
var target = e.target, |
||||
urlParams, |
||||
lnk = closest(target, 'js-gs-share'); |
||||
|
||||
// Don't do anything on right/middle click or if ctrl or shift was pressed while left-clicking
|
||||
if (!e.button && !e.ctrlKey && !e.shiftKey && lnk) { |
||||
e.preventDefault(); |
||||
|
||||
// Check for submission information in href first
|
||||
if (lnk.search !== undefined) { |
||||
urlParams = extractURLParams(lnk.search); |
||||
shareURL = urlParams.url; |
||||
shareTitle = urlParams.title; |
||||
} else { // If it's not there, try data-* attributes. If not, use current document url and title
|
||||
shareURL = lnk.getAttribute('data-url') || window.location.href; |
||||
shareTitle = lnk.getAttribute('data-title') || document.title; |
||||
} |
||||
|
||||
// Move form after the clicked link
|
||||
lnk.parentNode.appendChild(frm); |
||||
|
||||
// Show form
|
||||
frm.setAttribute('aria-hidden', 'false'); |
||||
|
||||
// Focus on form
|
||||
frm.focus(); |
||||
} else if (!frm.contains(target)) { |
||||
frm.setAttribute('aria-hidden', 'true'); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
// Flag that js is enabled
|
||||
document.body.classList.add('js-gs-share-enabled'); |
||||
|
||||
createForm(); |
||||
bindClicks(); |
||||
}); |
||||
// @license-end
|
||||
Loading…
Reference in new issue