1

私は検索してきましたが、私のものと似たような質問を見つけましたが、私がやろうとしていることと完全に一致するものはありません (または、少なくとも解決策は私にとってはうまくいきませんでした)。私はデュランダルに本当に慣れていないので、これを達成するためにどこから始めるべきかほとんど手がかりがありません. 私はテストアプリケーションに取り組んでおり、次のようにhtmlを表示するためにデータバインドされたdivを持っています:

ビューでのデータバインド

<div class="active-document-text" id="document-text" data-bind="html: documentBody">

ビュー モデルの JavaScript では、AJAX 呼び出しを使用して外部 HTML ファイルを取得します。正常に動作し、ビューに適切にバインドされ、ドキュメントが表示されます。私の問題は、外部 HTML にも 1 つ以上のデータ バインドが含まれることです。

外部.html

Lorem ipsum dolor 
<div class="selectable" id="selectable-1"
 data-bind="event: { click: $parent.onmouseClick }" >
sit amet, consectetur adipiscing</div> elit.
Integer nec odio. Praesent libero. Sed cursus ante dapibus diam.
Sed nisi. Nulla quis sem at nibh elementum imperdiet.

それらのインスタンスを現在のビューモデルにデータバインドしてそこで処理するように、どのように設定できるのか疑問に思っています。アイデアは、テキストの選択可能な領域 (単純なマウスオーバーの強調表示) を用意し、現在選択されているインデックスと比較することです。より簡単な説明は、文を提供するアプリケーションに似ており、ユーザーは名詞カテゴリをクリックして文中の名詞を選択するというものです。上記の例に示すように、選択可能な領域はテキストのどこにでもあります。すべての html をレンダリングすることはできましたが、データ バインディングを機能させることができませんでした。動的に生成された要素のノックアウト データ バインドに従って、その後 ko.applyBindings() を適用しようとしました、しかし、未定義のルーターエラーが発生します。動的htmlをデュランダルビューに挿入するなど、データを渡す構成を作成しようとしましたが、外部htmlには独自の.jsモデル/ビューモデルがあるようです。私はこれを完全に間違った方法で行っていますか?おそらくそれを過度に複雑にしていますか?もともと、テキストの各セクションが選択可能なプロパティを持つモデルに分割していましたが、かなりのサイズのドキュメントを分割するのは非常に扱いにくく、HTML 形式の悪夢なので、より洗練された解決策を見つけようとしています。私はあなたの助けに感謝します!

編集

次の問題は、この質問を拡張し ます。外部 html ファイルにイベント バインディングを組み込むために必要な長い div タグは、ドキュメントの作成者である可能性が高い非開発者にとって友好的ではありません。現在、AJAX呼び出しでhtmlファイルを再度取得し、単純なカスタム「[selectable]」タグを長いdivタグに置き換えて、それをオブザーバブルに保存していますが、それを組み込む方法はまだわかりません現在のビューにバインドします。

これは、それを機能させようとしている現在の外観です。特に重要な行の先頭に二重アスタリスクを追加しました。

景色:

<h3 data-bind="html: displayName"></h3>
<div class="document-analysis document-analysis-border">
    <span class="title-bar">Analyze Documents</span>
    <img src="./assets/images/arrow_minimize.jpg" class="minimize-button" />
    <div class="container">
        <div class="document-bar">
            <span class="title">Documents to Analyze</span><br />
            <img class="arrow-up" src="./assets/images/arrow_up.jpg" alt="Up Arrow" />
            <div data-bind="foreach: documentData()" class="documents scroll-bar">
                **<div data-bind="event: { click: function () { $parent.changeDocument($data); } }, attr: { id: 'document-' + id }" class="document">
                    <img data-bind="attr: { alt: title }" src="./assets/images/document_image.gif" class="document-image" />
                    <span data-bind="text: title" class="document-name"></span>
                </div>
            </div>
            <img class="arrow-down" src="./assets/images/arrow_down.jpg" alt="Down Arrow" />
        </div>
        <div class="inner-container">
            <div class="active-document">
                **<!--<div class="scroll-bar text" id="document-text" data-bind="compose: { view: currentDocument().url, transition: 'entrance' }"></div>-->
                **<div class="scroll-bar text" id="document-text" data-bind="compose: { view: documentFormatted, transition: 'entrance' }"></div>
                <button class="submit">Submit</button>
            </div>
            <div data-bind="foreach: bucketData()" class="buckets">
                <div data-bind="event: { click: function () { $parent.changeBucket($data); } }" class="bucket">
                    <img data-bind="attr: { id: 'bucket-' + id, src: image, alt: title }" src="//:0" class="bucket-image" />
                    <span data-bind="text: title" class="bucket-name"></span>
                </div>
            </div>
        </div>
    </div>
</div>

最初のマークされた行は、新しいドキュメントがクリックされると、changeDocument() 関数を呼び出します。2 行目と 3 行目は、外部ドキュメントを機能させる試みです。コメントアウトされた構成は正常に機能しますが、mouseOver と mouseOut でテキストを強調表示しやすくするために、長いタグを使用する必要があります。クリックは、現時点では主にデバッグに使用されます。バケット (カテゴリ) の 1 つをクリックしてから、外部ドキュメントの選択可能な領域をクリックすると、データがチェックされ、テキスト選択に適切なカテゴリを選択した場合、ポイントが獲得されます。

関連するビューモデル情報は次のとおりです。

var vm = {
        displayName: 'Document Analysis',
        currentDocument: ko.observable(docAnalysisObj.documents[0]),
        documentData: ko.observableArray(docAnalysisObj.documents),
        documentFormatted: ko.observable(),

        $init: $init,
        activate: activate,
        onmouseOver: onmouseOver,
        onmouseOut: onmouseOut,
        mouseClick: mouseClick,
        changeDocument: changeDocument,
        canDeactivate: canDeactivate,
        viewAttached: viewAttached
    };
    return vm;

function changeDocument(newDocument) {
        var self = this;
        // If they clicked the same document, ignore and return
        if (!newDocument || (self.currentDocument() && self.currentDocument().id === newDocument.id)) {
            return;
        }

        // Set the id selector name
        var docElementSelector = '#document-' + newDocument.id;

        // Remove the highlight from the previous class if it exists
        if (self.currentDocument()) {
            $('#document-' + self.currentDocument().id).removeClass('document-selected');
        }
        // Set the document to the new one
        self.currentDocument(newDocument);
        // Use data service to pull the html into self.documentFormatted
        dataservice.getDocument(self.documentFormatted, self.currentDocument().url);

        // Highlight the new current document
        $(docElementSelector).addClass('document-selected');

    }

mouseOver と mouseOut は、選択可能な領域にマウスを置いたときに CSS クラスを追加および削除するだけです。changeDocument() は、次のデータ サービス オブジェクトを使用して html をロードし、CSS の変更を処理する私の試みです。

Dataservice オブジェクト:

var getDocument = function (documentObservable, url) {
        documentObservable([]);

        if (!url) {
            console.log('Error: No url provided for document');
            documentObservable('<h1>Error: Document Not Found</h1>Document source was undefined.');
            return;
        }

        url = './app/views/' + url;

        var options = {
            url: url,
            type: 'GET',
            dataType: 'html',
            cache: false,
            error: queryFailed
        };

        return $.ajax(options)
            .then(querySucceeded);

        function querySucceeded(data) {
            console.log('Document \'' + url + '\' retrieval succeeded.');
            documentObservable(data);

            var currentID = 1;
            while (documentObservable().match(/\[selectable\]/g)) {
                documentObservable(documentObservable().replace('[selectable]', '<div class="selectable" selectID="' + currentID + '" data-bind="event: { mouseover: function () { $root.onmouseOver(' + currentID + '); }, mouseout: function () { $root.onmouseOut(' + currentID + '); }, click: function () { $root.mouseClick(' + currentID + '); } }">'));
                currentID++;
            }
        }

        function queryFailed(jqXHR, textStatus) {
            console.log('Error getting document ' + url + ': ' + textStatus);
            documentObservable('<h1>Error: Document Not Found</h1>' + textStatus);
        }

    };

データサービスは、これの肉とじゃがいものです。これは、html をロードし、[selectable] の出現箇所をすべて、データ バインディングに使用される長いタグに置き換えます。終了タグの置き換えはまだ実装していませんが、それは簡単なことです。div が ID の代わりにカスタム属性 selectID を使用する理由は、カスタム属性が発生する可能性が低いのに対し、ドキュメント全体で ID を複製できるため、ID を使用することは悪い考えであると上司が言っているためです。

サンプル文書:

[selectable]
            &bull; This is a sample selectable area. This will be highlighted<br />
            when someone mouses over it.
            <br />[/selectable]

長い div は [selectable] タグに置き換えられ、基本的な HTML スキルを持つユーザーがサンプル ドキュメントを簡単に作成できるようになりました。

最終的な目標は、長いタグを貼り付けて個々の ID を追跡するのではなく、ドキュメントの作成者が簡単に操作できるタグを提供することです。マウス イベントはすべて同じアクティビティであるため、viewmodel に結び付けておきたいと思います (そして、すべてのドキュメントのポイントが合計されて最終スコアが算出されます)。ユーザーの観点からは、選択可能なテキストの上にマウスを置くと、色が変わるだけです (単純な jQuery)。彼らがそれをクリックすると、正しいカテゴリが選択されているかどうかがチェックされます(私はすでにこれを機能させています)。私の現在の問題は、テキストの置換を行い、イベントをビューの関数にバインドできるようにすることです。

4

1 に答える 1

3

knockoutjs html バインディングは使用しません。

代わりに durandals compose バインディングを使用して、新しい要素を dom に挿入します。バインディングもデュランダルが担当します。

この記事を参照してください: http://durandaljs.com/documentation/Using-Composition/

于 2013-06-27T23:32:51.130 に答える