Ajaxを使用してコンテンツを読み込むページがいくつかあり、ページにディープリンクする必要がある場合がいくつかあります。 「ユーザー」へのリンクを持ち、「設定」をクリックするように人々に伝える代わりに、人々をser.aspx#settingsにリンクできると便利です。
ユーザーがセクションへの正しいリンクを提供できるようにするため(テクニカルサポートなど)、ボタンがクリックされるたびにURLのハッシュを自動的に変更するように設定しました。もちろん、唯一の問題は、これが発生すると、ページをこの要素にスクロールすることです。
これを無効にする方法はありますか?以下は、これまで私がこれをどのように行っているかです。
$(function(){
//This emulates a click on the correct button on page load
if(document.location.hash){
$("#buttons li a").removeClass('selected');
s=$(document.location.hash).addClass('selected').attr("href").replace("javascript:","");
eval(s);
}
//Click a button to change the hash
$("#buttons li a").click(function(){
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
document.location.hash=$(this).attr("id")
//return false;
});
});
return false;
がページのスクロールを停止することを期待していましたが、リンクがまったく機能しなくなるだけです。そのため、今はコメントアウトしているので、ナビゲートできます。
何か案は?
私はかなり簡単な解決策を見つけたかもしれないと思う。問題は、URL内のハッシュもスクロールするページ上の要素であるということです。ハッシュにテキストを追加するだけで、既存の要素を参照しなくなりました!
$(function(){
//This emulates a click on the correct button on page load
if(document.location.hash){
$("#buttons li a").removeClass('selected');
s=$(document.location.hash.replace("btn_","")).addClass('selected').attr("href").replace("javascript:","");
eval(s);
}
//Click a button to change the hash
$("#buttons li a").click(function(){
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
document.location.hash="btn_"+$(this).attr("id")
//return false;
});
});
これで、URLはpage.aspx#btn_elementID
として表示されますが、これはページ上の実際のIDではありません。 「btn_」を削除して、実際の要素IDを取得するだけです
ステップ1:ハッシュが設定されるまで、ノードIDを解除する必要があります。これは、ハッシュの設定中にノードからIDを削除してから、追加し直すことで実行されます。
hash = hash.replace( /^#/, '' );
var node = $( '#' + hash );
if ( node.length ) {
node.attr( 'id', '' );
}
document.location.hash = hash;
if ( node.length ) {
node.attr( 'id', hash );
}
ステップ2:一部のブラウザーは、IDが付与されたノードが最後に表示された場所に基づいてスクロールをトリガーするため、少し手助けする必要があります。ビューポートの上部にdiv
を追加し、そのIDをハッシュに設定してから、すべてをロールバックする必要があります。
hash = hash.replace( /^#/, '' );
var fx, node = $( '#' + hash );
if ( node.length ) {
node.attr( 'id', '' );
fx = $( '<div></div>' )
.css({
position:'absolute',
visibility:'hidden',
top: $(document).scrollTop() + 'px'
})
.attr( 'id', hash )
.appendTo( document.body );
}
document.location.hash = hash;
if ( node.length ) {
fx.remove();
node.attr( 'id', hash );
}
ステップ3:プラグインでラップし、location.hash
...に書き込む代わりにそれを使用する.
history.replaceState
またはhistory.pushState
*を使用して、ハッシュを変更します。これは、関連する要素へのジャンプをトリガーしません。
$(document).on('click', 'a[href^=#]', function(event) {
event.preventDefault();
history.pushState({}, '', this.href);
});
*履歴の前方および後方サポートが必要な場合
history.pushState
を使用していて、ユーザーがブラウザの履歴ボタンを使用するときに(前方/後方)ページをスクロールしたくない場合は、実験的なscrollRestoration
設定(Chrome 46+のみ)。
history.scrollRestoration = 'manual';
私は最近、状態を維持するためにwindow.location.hash
に依存するカルーセルを構築し、ChromeおよびWebkitブラウザーがwindow.onhashchange
イベントが発生したときに厄介なジャークでスクロールを強制します(目に見えないターゲットでも)。
伝播を停止するハンドラーを登録しようとしても:
$(window).on("hashchange", function(e) {
e.stopPropogation();
e.preventDefault();
});
デフォルトのブラウザの動作を止めるものは何もありませんでした。私が見つけた解決策は、 window.history.pushState
を使用して、望ましくない副作用を引き起こさずにハッシュを変更することでした。
$("#buttons li a").click(function(){
var $self, id, oldUrl;
$self = $(this);
id = $self.attr('id');
$self.siblings().removeClass('selected'); // Don't re-query the DOM!
$self.addClass('selected');
if (window.history.pushState) {
oldUrl = window.location.toString();
// Update the address bar
window.history.pushState({}, '', '#' + id);
// Trigger a custom event which mimics hashchange
$(window).trigger('my.hashchange', [window.location.toString(), oldUrl]);
} else {
// Fallback for the poors browsers which do not have pushState
window.location.hash = id;
}
// prevents the default action of clicking on a link.
return false;
});
その後、通常のhashchangeイベントとmy.hashchange
の両方をリッスンできます。
$(window).on('hashchange my.hashchange', function(e, newUrl, oldUrl){
// @todo - do something awesome!
});
元のコードのスニペット:
$("#buttons li a").click(function(){
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
document.location.hash=$(this).attr("id")
});
これを次のように変更します。
$("#buttons li a").click(function(e){
// need to pass in "e", which is the actual click event
e.preventDefault();
// the preventDefault() function ... prevents the default action.
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
document.location.hash=$(this).attr("id")
});
さて、これはかなり古いトピックですが、「正しい」答えがCSSでうまく機能しないので、私はチップを入れると思いました。
このソリューションは、基本的に防止ページを移動するクリックイベントにより、最初にスクロール位置を取得できます。次に、手動でハッシュを追加すると、ブラウザーはhashchangeイベントを自動的にトリガーします。 hashchangeイベントをキャプチャし、正しい位置までスクロールバックします。コールバックは、ハッシュハッキングを1か所に保持することにより、コードが分離し、遅延の原因となるのを防ぎます。
var hashThis = function( $elem, callback ){
var scrollLocation;
$( $elem ).on( "click", function( event ){
event.preventDefault();
scrollLocation = $( window ).scrollTop();
window.location.hash = $( event.target ).attr('href').substr(1);
});
$( window ).on( "hashchange", function( event ){
$( window ).scrollTop( scrollLocation );
if( typeof callback === "function" ){
callback();
}
});
}
hashThis( $( ".myAnchor" ), function(){
// do something useful!
});
えー、私はやや粗雑ですが、間違いなく動作する方法を持っています。
現在のスクロール位置を一時変数に保存し、ハッシュの変更後にリセットします。 :)
元の例の場合:
$("#buttons li a").click(function(){
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
var scrollPos = $(document).scrollTop();
document.location.hash=$(this).attr("id")
$(document).scrollTop(scrollPos);
});
hashchangeイベントをハッシュパーサーで使用する場合、リンクのデフォルトアクションを防止し、location.hashを変更して要素のidプロパティとの違いを持たせることができます。
$('a[href^=#]').on('click', function(e){
e.preventDefault();
location.hash = $(this).attr('href')+'/';
});
$(window).on('hashchange', function(){
var a = /^#?chapter(\d+)-section(\d+)\/?$/i.exec(location.hash);
});
より関連性の高い質問はすべて、ここを指す重複としてマークされているため、ここに追加します…
私の状況は簡単です:
a[href='#something']
)e.preventDefault()
$("html,body").stop(true,true).animate({ "scrollTop": linkoffset.top }, scrollspeed, "swing" );
window.location = link;
これにより、スクロールが発生し、場所が更新されてもジャンプしません。
これは可能だとは思いません。私の知る限り、ブラウザーが変更されたdocument.location.hash
にスクロールしないのは、ページ内にハッシュが存在しない場合だけです。
この記事 はあなたの質問とは直接関係ありませんが、document.location.hash
を変更する典型的なブラウザーの動作について説明します
これを行うもう1つの方法は、ビューポートの上部に非表示のdivを追加することです。このdivには、ハッシュにURLが追加される前にハッシュのIDが割り当てられます。そのため、スクロールは取得されません。
履歴対応タブのソリューションは次のとおりです。
var tabContainer = $(".tabs"),
tabsContent = tabContainer.find(".tabsection").hide(),
tabNav = $(".tab-nav"), tabs = tabNav.find("a").on("click", function (e) {
e.preventDefault();
var href = this.href.split("#")[1]; //mydiv
var target = "#" + href; //#myDiv
tabs.each(function() {
$(this)[0].className = ""; //reset class names
});
tabsContent.hide();
$(this).addClass("active");
var $target = $(target).show();
if ($target.length === 0) {
console.log("Could not find associated tab content for " + target);
}
$target.removeAttr("id");
// TODO: You could add smooth scroll to element
document.location.hash = target;
$target.attr("id", href);
return false;
});
最後に選択したタブを表示するには:
var currentHashURL = document.location.hash;
if (currentHashURL != "") { //a tab was set in hash earlier
// show selected
$(currentHashURL).show();
}
else { //default to show first tab
tabsContent.first().show();
}
// Now set the tab to active
tabs.filter("[href*='" + currentHashURL + "']").addClass("active");
filter
呼び出しの*=
に注意してください。これはjQuery固有のものであり、これがないと、履歴対応タブは失敗します。
Hashchangeの前にスクロールをその位置にリセットする必要があると思います。
$(function(){
//This emulates a click on the correct button on page load
if(document.location.hash) {
$("#buttons li a").removeClass('selected');
s=$(document.location.hash).addClass('selected').attr("href").replace("javascript:","");
eval(s);
}
//Click a button to change the hash
$("#buttons li a").click(function() {
var scrollLocation = $(window).scrollTop();
$("#buttons li a").removeClass('selected');
$(this).addClass('selected');
document.location.hash = $(this).attr("id");
$(window).scrollTop( scrollLocation );
});
});
このソリューションは、実際のscrollTopにdivを作成し、ハッシュを変更した後にそれを削除します。
$('#menu a').on('click',function(){
//your anchor event here
var href = $(this).attr('href');
window.location.hash = href;
if(window.location.hash == href)return false;
var $jumpTo = $('body').find(href);
$('body').append(
$('<div>')
.attr('id',$jumpTo.attr('id'))
.addClass('fakeDivForHash')
.data('realElementForHash',$jumpTo.removeAttr('id'))
.css({'position':'absolute','top':$(window).scrollTop()})
);
window.location.hash = href;
});
$(window).on('hashchange', function(){
var $fakeDiv = $('.fakeDivForHash');
if(!$fakeDiv.length)return true;
$fakeDiv.data('realElementForHash').attr('id',$fakeDiv.attr('id'));
$fakeDiv.remove();
});
オプションで、ページのロード時にアンカーイベントをトリガーします。
$('#menu a[href='+window.location.hash+']').click();
私にはもっと簡単な方法があります。基本的に、HTMLで実際にハッシュが何であるかを覚えておいてください。これは、Nameタグへのアンカーリンクです。それがスクロールする理由です...ブラウザはアンカーリンクまでスクロールしようとしています。だから、それを与えてください!
<a name="home"> </a> <a name="firstsection"> </a> <a name="secondsection"> </a> <a name="thirdsection"> </a>
IDの代わりにクラスを使用してセクションdivに名前を付けます。
処理コードで、ハッシュマークを取り除き、ドットに置き換えます。
var trimPanel = loadhash.substring(1); //ハッシュを失います var dotSelect = '。' + trimPanel; //ハッシュをドット に置き換えます$(dotSelect).addClass( "activepanel")。show(); //ハッシュに関連付けられたdivを表示します。
最後に、element.preventDefaultを削除するか、falseを返し、navを発生させます。ウィンドウは上部にとどまり、ハッシュがアドレスバーのURLに追加され、正しいパネルが開きます。
ページでidをアンカーポイントとして使用し、ユーザーがURLの末尾に#somethingを追加し、独自の定義済みアニメーションを使用してその#somethingセクションにページをスクロールさせるシナリオがある場合javascript関数、hashchangeイベントリスナーはそれを行うことができません。
たとえば、hashchangeイベントの直後にデバッガーをすぐに配置すると、次のようになります(まあ、jqueryを使用しますが、ポイントは得られます)。
$(window).on('hashchange', function(){debugger});
URLを変更してEnterボタンを押すとすぐに、ページが対応するセクションで停止し、その後すぐに、独自の定義されたスクロール機能がトリガーされ、そのセクションへのスクロールが行われます。ひどい。
私の提案は次のとおりです。
idをスクロール先のセクションへのアンカーポイントとして使用しないでください。
私のようにIDを使用する必要がある場合。代わりに「popstate」イベントリスナーを使用してください。URLに追加するセクションまで自動的にスクロールすることはありません。代わりに、popstateイベント内で独自の定義済み関数を呼び出すことができます。
$(window).on('popstate', function(){myscrollfunction()});
最後に、独自に定義されたスクロール関数でちょっとしたトリックを行う必要があります。
let hash = window.location.hash.replace(/^#/, '');
let node = $('#' + hash);
if (node.length) {
node.attr('id', '');
}
if (node.length) {
node.attr('id', hash);
}
タグのIDを削除してリセットします。
これでうまくいくはずです。