Zamień omniauth facebook login w wyskakujące okienko
Używam omniauth gem z rails i działa świetnie z logowaniem użytkowników, ale za każdym razem, gdy przenosi Cię na stronę logowania na fb, przekierowuje cię z powrotem. Zastanawiałem się, czy jest sposób, aby zrobić to, co robi większość stron i pokazać FB login w popup, a następnie przeładować rodzic div po zakończeniu. Jakieś pomysły?
Dzięki!
4 answers
Pewnie, że możesz.
Według Ciebie:
=link_to "Log in with Facebook", omniauth_authorize_path(:user, :facebook), :class => "popup", :"data-width" => 600, :"data-height" => 400
W Twojej aplikacji.js:
function popupCenter(url, width, height, name) {
var left = (screen.width/2)-(width/2);
var top = (screen.height/2)-(height/2);
return window.open(url, name, "menubar=no,toolbar=no,status=no,width="+width+",height="+height+",toolbar=no,left="+left+",top="+top);
}
$("a.popup").click(function(e) {
popupCenter($(this).attr("href"), $(this).attr("data-width"), $(this).attr("data-height"), "authPopup");
e.stopPropagation(); return false;
});
A następnie w widoku oddzwaniania:
:javascript
if(window.opener) {
window.opener.location.reload(true);
window.close()
}
Spowoduje to wyświetlenie auth Facebook w wyśrodkowanym wyskakującym okienku 600x400, a następnie, gdy użytkownik powróci z uwierzytelniania, widok zamknie wyskakujące okienko i odświeży Stronę nadrzędną. Rozkłada się wdzięcznie, jeśli użytkownik kliknie ctrl łącze lub nie ma włączonej obsługi Javascript.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-29 01:00:34
Ok, więc jest problem z rozwiązaniem Chrisa Healda, jeśli używasz OmniAuth w połączeniu z Devise. Problem polega na tym, że po ponownym załadowaniu okna (które znajduje się na stronie logowania) Devise przeniesie Cię do ścieżki root_path, całkowicie ignorując adres URL, do którego próbowałeś uzyskać dostęp i wyświetli komunikat o błędzie "jesteś już zalogowany". Ma to sens, ponieważ Devise chroni zalogowanego użytkownika przed dostępem do strony logowania poprzez przekierowanie na stronę główną. Przeładowując strona logowania natychmiast po zalogowaniu się pojawi się ten problem.
Więc moje rozwiązanie dla kogoś używającego Devise jest następujące:
# add this wherever needed in your_authentications_or_callbacks_controller.rb
sign_in user
@after_sign_in_url = after_sign_in_path_for(user)
render 'callback', :layout => false
Tak więc zwykle, po znalezieniu lub utworzeniu użytkownika za pomocą hasha zwróconego przez określonego dostawcę (Facebook, Twitter itp..), nazywamy funkcję Devise sign_in_and_redirect
. Ale nie możemy jeszcze przekierować (pamiętaj, że w tej chwili użytkownik znajduje się w wyskakującym oknie), więc po prostu sign_in
użytkownik.
Następnie musimy podać adres url Użytkownik próbował uzyskać dostęp do widoku i możemy uzyskać ten adres url za pomocą metody Devise after_sign_in_path_for
.
Wreszcie, musimy renderować widok. Ponieważ będziemy używać widoku tylko do wywoływania JavaScript, nie ma potrzeby renderowania układu, więc wyłączamy go, aby nie spowalniać nas. Oto ten widok:
# views/your_authentications_or_callbacks/callback.html.erb
<script type="text/javascript">
window.opener.location = '<%= @after_sign_in_url %>';
window.close();
</script>
W ten sposób użytkownik jest przekierowywany na właściwy adres url po zalogowaniu i wyświetlana jest prawidłowa wiadomość flash.
Z wyłączonym JavaScript
Po kilku testach I zdałem sobie sprawę, że to rozwiązanie nie pozwala na uwierzytelnianie bez JavaScript, więc chciałbym zrobić dodatek.
function popupCenter(linkUrl, width, height, name) {
var separator = (linkUrl.indexOf('?') !== -1) ? '&' : '?',
url = linkUrl + separator + 'popup=true',
left = (screen.width - width) / 2,
top = (screen.height - height) / 2,
windowFeatures = 'menubar=no,toolbar=no,status=no,width=' + width +
',height=' + height + ',left=' + left + ',top=' + top;
return window.open(url, name, windowFeatures);
}
Zmiana polega na dodaniu prostego parametru o nazwie popup
do adresu URL przy użyciu JavaScript. OmniAuth będzie na tyle uprzejmy, aby przechowywać wszelkie paramy zapytań dodane do adresu URL żądania. Więc w końcu sprawdzamy ten param w kontrolerze. Jeśli istnieje, to dlatego, że JavaScript jest włączony:
if request.env['omniauth.params']['popup']
render 'callback', :layout => false
else
redirect_to @after_sign_in_url
end
Również, nie zapomnij zrobić tego samego dla swojej failure
akcji, która jest wywoływana, gdy użytkownik nie akceptuje logowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-28 13:42:31
Publikowanie w przypadku, gdy pomaga innym. Korzystałem z odpowiedzi Chrisa Healda, ale napotkałem problemy z ostatnim bitem javascript zamykającym nowe linki do okien. Na przykład, jeśli opublikowałem link do mojej witryny na Facebook, gdy użytkownicy kliknęli link, nowe okno automatycznie zamknie się w Chrome, ponieważ warunek sprawdza tylko " if (window.otwieracz) "
Rozwiązałem to za pomocą zmiennej globalnej (popupValue). Mogą być bardziej eleganckie rozwiązania, ale pomyślałem, że podzielę się w przypadek, w którym inni trafiają w ten sam problem:
function popupCenter(url, width, height, name) {
var left = (screen.width/2)-(width/2);
var top = (screen.height/2)-(height/2);
popupValue = "on";
return window.open(url, name, "menubar=no,toolbar=no,status=no,width="+width+",height="+height+",toolbar=no,left="+left+",top="+top );
}
$(document).ready(function(){
$("a.popup").click(function(e) {
popupCenter($(this).attr("href"), $(this).attr("data-width"), $(this).attr("data-height"), "authPopup");
e.stopPropagation(); return false;
});
if(window.opener && window.opener.popupValue === 'on') {
delete window.opener.popupValue;
window.opener.location.reload(true);
window.close()
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-28 17:59:08
Skończyłem używając Facebook JS SDK, ponieważ jest to łatwiejsze.
# In facebook.js.coffee
jQuery ->
$('body').prepend('<div id="fb-root"></div>')
$.ajax
url: "#{window.location.protocol}//connect.facebook.net/en_US/all.js"
dataType: 'script'
cache: true
window.fbAsyncInit = ->
FB.init(appId: 'YOUR-APP-ID', cookie: true)
$('#sign_in').click (e) ->
e.preventDefault()
FB.login (response) ->
window.location = '/auth/facebook/callback' if response.authResponse
$('#sign_out').click (e) ->
FB.getLoginStatus (response) ->
FB.logout() if response.authResponse
true
Następnie w Twoich poglądach:
<%= link_to "Sign in with Facebook", "/auth/facebook", id: "sign_in" %>
<%= link_to "Sign out", signout_path, id: "sign_out" %>
To prosto z podpowiedzi Sergio Gutierreza. https://coderwall.com/p/bsfitwWarning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-20 22:06:35