13

すべての列から可能なすべての LI 要素を含む十分な大きさが必要な N 列を含む Html/JavaScript アプリケーションがあります。

簡単な解決策は、各列のすべてのアイテムの高さをカウントし、パディングを補正してから、各列の高さをその合計に設定するようです。

これは、LI 要素にプレーン テキストが含まれている場合にうまく機能します。残念ながら、LI 要素に代わりに画像が含まれている場合、さまざまなブラウザーで問題が発生します。たとえば、FireFox で最初にページを読み込んだときは、次のスクリーンショットのように見えますが、もう一度更新すると問題なく動作します。Chrome でも期待どおりに動作しません。

UL 要素の高さが LI 要素と同期していないことを示すスクリーンショット

私のアプリケーションは、ページの読み込み時に LI 要素を事前設定しません。次のように JavaScript を使用します。

function populateUnsetAnswers(unsetCategoryAnswers) {
    for (i in unsetCategoryAnswers) {
        if (unsetCategoryAnswers.hasOwnProperty(i.toString())) {
            $('#categoryQuestionArea #possibleAnswers').append(
                categoryAnswerLiTag(unsetCategoryAnswers[i])
            );
        }
    }
}

function categoryAnswerLiTag(unsetCategoryAnswer) {
    var html = '<li id="' + unsetCategoryAnswer.id + '">';

    if (unsetCategoryAnswer.image) {
        html += '<img class="categoryAnswerImage" title="';
        html += unsetCategoryAnswer.text;
        html += '" src="/trainingdividend/rest/streaming/';
        html += unsetCategoryAnswer.image.fileName;
        html += '" style="height: ';
        html += unsetCategoryAnswer.image.height;
        html += ';';
        html += '" />';
    } else {
        html += unsetCategoryAnswer.text
    }

    html += '</li>';

    return html;
}

ページの読み込みが完了すると、ajax リクエストがすべてのオブジェクトを取得して LI 要素に配置し、上記の最初の関数を呼び出します。

すべての LI 要素が作成されたら、その直後にこの関数を呼び出します。

function resize() {
    var currentHeight, totalHeight;
    totalHeight = 0;

    $("#categoryQuestionArea ul").children().each(function() {
        currentHeight = $(this).height();

        totalHeight += currentHeight + 13;
    });

    $("#categoryQuestionArea ul").height(totalHeight);
    $("#categoryQuestionArea div#separator").css("padding-top", (totalHeight / 2) + "px");
}

jQueryに「すべてのLIが完全にロードされ、画像がレンダリングされるまで resize() を呼び出さないでください」と伝える方法はありますか?

最初のページの読み込み時に、これらの LI 要素の高さが 0 または小さい値になっているのは、画像が含まれていないためだと思います。そのため、サイズ変更関数が間違った結果を計算しています (いくつかのアラート ステートメントでこれをテストしました)。 )。LI が設定され、画像が読み込まれている限り、高さの合計は問題なく計算されます。

何か助けはありますか?ありがとう

4

10 に答える 10

3

あなたが尋ねた質問に文字通り答えるには、resize()すべての画像の読み込みが完了したときにのみ呼び出したい場合はonload、それらの画像のハンドラーをインストールする必要があり、最後の画像が読み込まれたことを記録したら、resize()関数を呼び出すことができます。次のようにすることができます (以下のコードの説明)。

var remainingAnswerImages = 0;

function categoryAnswerImageLoadHandler() {
    --remainingAnswerImages;
    if (remainingAnswerImages === 0) {
        resize();
    }
}

function populateUnsetAnswers(unsetCategoryAnswers) {
    // add one extra to the image count so we won't have any chance 
    // at getting to zero  before loading all the images
    ++remainingAnswerImages;
    var possibleAnswers$ = $('#categoryQuestionArea #possibleAnswers');
    for (i in unsetCategoryAnswers) {
        if (unsetCategoryAnswers.hasOwnProperty(i.toString())) {
            possibleAnswers$.append(categoryAnswerLiTag(unsetCategoryAnswers[i]));
        }
    }
    // remove the one extra
    --remainingAnswerImages;
    // if we hit zero on the count, then there either were no images 
    // or all of them loaded immediately from the cache
    // if the count isn't zero here, then the 
    // categoryAnswerImageLoadHandler() function will detect when it does hit zero
    if (remainingAnswerImages === 0) {
        resize();
    }
}

function categoryAnswerLiTag(unsetCategoryAnswer) {
    var obj = document.createElement("li");
    obj.id = unsetCategoryAnswer.id;

    if (unsetCategoryAnswer.image) {
        // count this image
        ++remainingAnswerImages;
        var img = new Image();
        img.onload = img.onerror = img.onabort = categoryAnswerImageLoadHandler;
        img.title = unsetCategoryAnswer.text;
        img.style.height = unsetCategoryAnswer.image.height;
        img.src = "/trainingdividend/rest/streaming/" + unsetCategoryAnswer.image.fileName;
        obj.appendChild(img);
    } else {
        obj.innerHTML = unsetCategoryAnswer.text;
    }
    return obj;
}

説明として、このコードは次の変更を行います。

  • remainingAnswerImages読み込む必要がある画像の数を追跡する変数を追加します。
  • 作成されたタグごとに onload ハンドラーを追加して<img>、いつ読み込まれたかを追跡できるようにします。
  • onload ハンドラーでタグの HTML を生成するたびに、インクリメントしますremainingAnswerImages
  • すべての HTML の追加が完了したら、remainingAnswerImagesカウントがゼロかどうかを確認します (これは、画像がない場合、またはすべての画像がブラウザーのキャッシュからすぐに読み込まれた場合にのみ発生します)。その場合は、すぐに resize() を呼び出します。
  • 画像ごとに呼び出される onload ハンドラでデクリメントremainingAnswerImagesし、カウントがゼロになった場合は を呼び出しますresize()
  • 画像を追加している間、画像の追加remainingAnswerImagesが完了するまでカウントがゼロにならないように、ゲートとして 1 つ余分に追加します。画像の追加が完了したら、余分なものを 1 つ取り出します。
  • categoryAnswerLiTag()また、一連の文字列を連結して HTML にするのではなく、DOM オブジェクトを直接作成するように関数を書き直しました。この場合、コードは読みやすく維持しやすくなります。
  • 毎回同じことに解決されるため、ループから$('#categoryQuestionArea #possibleAnswers')も移動しました。forループの前に一度実行することをお勧めします。また、ほとんどの場合、$('#possibleAnswers')ID はページ内で一意であると想定されているため、これは次のように単純化できます。
于 2012-04-25T20:28:18.373 に答える
2

画像が読み込まれたことを確認するjqueryプラグインは次のとおりです:https ://github.com/alexanderdickson/waitForImages

ケースの使用例は次のとおりです。

$('#categoryQuestionArea').waitForImages(function() {
   resize();
});

<ul>また、リストアイテムのパディング、マージン、または境界線のいずれかが後で変更された場合にスクリプトを手動で変更する必要があるため、リストアイテムをループするのではなく、全体の高さを確認します。

于 2012-04-21T12:30:42.797 に答える
1

最初のページ読み込み時に画像に問題がある場合は、画像がキャッシュされていないためにすぐに利用できないことが原因である可能性があります。そのため、高さを測定すると悪い結果が得られます... jQuery を介してフェッチされた高さをデバッグしましたか (たとえば、

currentHeight = $(this).height();
console.log(currentHeight);

それを行う唯一の方法は、すべての画像のロードイベント(およびおそらくエラーも)を観察し、すべてのリクエストが終了したかどうかをカウントすることだと思います

于 2012-04-19T17:09:24.853 に答える
0

使ってみてください

$('img').load(function(){
    //put code here
});
于 2012-04-19T17:48:19.723 に答える
0

これはどちらかというと CSS の問題であり、アイテムがフロートまたは絶対位置に固定されていることが原因である可能性が最も高いです。

これを修正する方法はいくつかあります。

  1. min-height高さを固定する代わりにaを指定します。

    #container { min-height: 100px; }
    
  2. をクリアし、float高さを設定しない

    #container { overflow: hidden; }
    
  3. すべての要素が追加されたら、スクリプトを使用して高さを追加します。以下の jQuery スニペットのように

    $("#container").append($("#theimg"));
    $("#container").height($("#container").height()+$("#theimg").height());
    
于 2012-04-24T10:18:01.120 に答える
0

これは、SudoSlider のコーディング時に発生した問題の 1 つとまったく同じように聞こえます。

以下に、解決したコードをコピーしました。autoheightwidth(i, 0, true)resize() 関数内で 呼び出すだけです。

基本的な考え方は、ブラウザーがいつ画像の読み込みを完了したかがわからないため、単一の高さ調整に頼るのではなく、何かが起こるたびに高さを調整するというものです (ほとんどの場合、画像が読み込まれただけです)。

最初の 2 つのメソッドで "obj" と "li" の参照を変更すると機能するはずです。

あまり読みやすいわけではありませんが、コード化するときはサイズに重点が置かれていました。

// Automaticly adjust the height and width, i love this function. 
// Before i had one function for adjusting height, and one for width.
function autoheightwidth(i, speed, axis) // Axis: true == height, false == width.
{
    obj.ready(function() {// Not using .load(), because that only triggers when something is loaded.
        adjustHeightWidth (i, speed, axis);
        // Then i run it again after the images has been loaded. (If any)
        // I know everything should be loaded, but just in case. 
        runOnImagesLoaded (li.eq(i), falsev, function(){
            adjustHeightWidth (i, speed, axis);
        });
    });
};
function adjustHeightWidth (i, speed, axis)
{
    var i = getRealPos(i); // I assume that the continuous clones, and the original element is the same height. So i allways adjust acording to the original element.
    var target = li.eq(i);
    // First i run it. In case there are no images to be loaded. 
    var b = target[axis ? "height" : "width"]();
    obj.animate(
        axis ? {height : b} : {width : b},
        {
            queue:falsev,
            duration:speed,
            easing:option[8]/*ease*/
        }
    );
}
function runOnImagesLoaded (target, allSlides, callback) // This function have to be rock stable, cause i use it ALL the time!
{
    var elems = target.add(target.find('img')).filter('img');
    var len = elems.length;
    if (!len)
    {
        callback();
        // No need to do anything else. 
        return this;
    }
    function loadFunction(that)
    {
        $(that).unbind('load').unbind('error');
        // Webkit/Chrome (not sure) fix. 
        if (that.naturalHeight && !that.clientHeight)
        {
            $(that).height(that.naturalHeight).width(that.naturalWidth);
        }
        if (allSlides)
        {
            len--;
            if (len == 0)
            {
                callback();
            }
        }
        else
        {
            callback();
        }
    }
    elems.each(function(){
        var that = this;
        $(that).load(function () {
            loadFunction(that);
        }).error(function () {
            loadFunction(that);
        });
        /*
         * Start ugly working IE fix. 
         */
        if (that.readyState == "complete") 
        {
            $(that).trigger("load");    
        }
        else if (that.readyState)
        {
            // Sometimes IE doesn't fire the readystatechange, even though the readystate has been changed to complete. AARRGHH!! I HATE IE, I HATE IT, I HATE IE!
            that.src = that.src; // Do not ask me why this works, ask the IE team!
        }
        /*
         * End ugly working IE fix. 
         */
        else if (that.complete)
        {
            $(that).trigger("load");
        }
        else if (that.complete === undefined)
        {
            var src = that.src;
            // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
            // data uri bypasses webkit log warning (thx doug jones)
            that.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; // This is about the smallest image you can make. 
            that.src = src;
        }
    }); 
}   
于 2012-04-26T14:13:33.137 に答える
0

私はあなたのための解決策を持っているかもしれないと思います.

私のソリューションの主なアイデアは CSS にあります。同じ高さの 3 つの列が必要ですよね? 次のようなものを持つことができます: http://jsfiddle.net/agilius/NvzZp/46/

そこには非常に多くの CSS がありますが、主なアイデアは次のとおりです。

  1. .inner クラスと .column クラスを使用して、実際のコンテンツの下に 3 列のレイアウトをシミュレートします。
  2. コンテンツは (z-index 2 > .inner zindex 1 を介して) 上に配置され、下にある列と同じ幅になります。
  3. コンテンツ ゾーンにコンテンツが追加されると、メイン #container の高さが更新されます。
  4. .inner は top,left,right,bottom = 0 であるため更新され、.columns の高さは 100% であるため、#containers の高さと一致するように高さを更新します。

観察。

.column クラスには、必要に応じてパディング、ボーダー、マージンを設定できます。

JavaScript は必要ありません。

于 2012-04-24T11:56:38.917 に答える
0

別のシンプルな等高 CSS ソリューション:

LOGICは非常に単純です。すべての列/LI は.eH{ padding-bottom: X;でフローティングされます。margin-bottom: -X }および wrapper/UL は.eW{overflow: hidden}

X = 安全率の px の大きな任意の量

例: http://jsfiddle.net/rahen/TXVYD/4/

于 2012-04-25T21:39:29.517 に答える
0

あなたのHTMLが台無しになっていると思います。特に、あなたの<img>タグ。

widthおよびheight属性を<img>タグに追加します。すべてが魔法のように解決されます。

私が何を意味するかを理解するには、この jsfiddle を参照してください: http://jsfiddle.net/Ralt/Vwg7P/

そこには画像がありませんが、属性widthheight属性は画像に必要なスペースを占有します。DOM がロードされるとすぐに。

于 2012-04-19T18:14:36.370 に答える
-1

画像が読み込まれていないため、ブラウザは画像の寸法を認識していないと思います。

の呼び出しをラップしてみてresizeください

jQuery(document).load( function funcName() {
   ...
} )

または、HTMLタグで画像widthと属性を指定します。heightimg

多分両方

于 2012-04-23T17:15:12.450 に答える