-2

私は、Javascriptを使用してクライアント側で解釈できるテンプレートシステムを作成して、顧客への手紙などの空白フォームへの入力を作成しています。

テンプレートを作成し、ロジックを擬似コードで設定しましたが、jQueryに慣れていないため、何らかの方向性を使用して開始することができました。

基本的な考え方は、フィールドを示すマークアップがテキストノードにあることです。たとえば、$ {prologue}は、「fields」という配列に追加され、xml内の対応するノード名を検索するために使用されます。

XML

    <?xml version="1.0" encoding="UTF-8"?>
<message>

    <text>${Prologue} - Dear ${Title} ${Surname}. This is a message from FUBAR. An engineer called but was unable to gain access, a new appointment has been made for ${ProductName} with order number ${VOLNumber}, on ${AppointmentDate} between ${AppointmentSlot}.
Please ensure you are available at your premises for the engineer. If this is not convenient, go to fubar.com or call 124125121515 before 12:00 noon the day before your appointment. Please refer to your order confirmation for details on what will happen on the day. ${Epilogue} - Free text field for advisor input<
</text>

    <inputTypes>
        <textBox type="text" fixed="n" size="100" alt="Enter a value">
            <Prologue size="200" value="BT ENG Appt Reschedule 254159" alt="Prologue field"></Prologue>
            <Surname value="Hoskins"></Surname>
            <ProductName value=""></ProductName>
            <VOLNumber size="8" value="" ></VOLNumber>
            <Epilogue value=""></Epilogue>  
        </textBox>
        <date type="datePicker" fixed="n" size="8" alt="Select a suitable appointment date">
            <AppointmentDate></AppointmentDate>
        </date>
        <select type="select" >
            <Title alt="Select the customers title">
                <values>
                    <Mr selected="true">Mr</Mr>
                    <Miss>Miss</Miss>
                    <Mrs>Mrs</Mrs>
                    <Dr>Dr</Dr>
                    <Sir>Sir</Sir>                  
                </values>
            </Title>
            <AppointmentSlot alt="Select the appointment slot">
                <values>
                    <Morning>9:30am - 12:00pm</Morning>
                    <Afternoon>1:00pm - 5:00pm</Afternoon>
                    <Evening>6:00pm - 9:00pm</Evening>
                </values>
            </AppointmentSlot>
        </select>
    </inputTypes>
</message>

擬似コード

Get list of tags from text node and build array called "fields"
For each item in "fields" array:
Find node in xml that equals array item's name
Get attributes of that node
Jump to parent node
Get attributes of parent node
If attributes of parent node != child node then ignore
Else add the parent attributes to the result
Build html for field using all the data gathered from above

補遺

このロジックは大丈夫ですか、ノードの親から開始して、代わりに下に移動することは可能ですか?

また、継承に関して、親属性を取得できますか?子属性が異なる場合は、それらを結果に追加できますか?親の属性の数が子の属性の数と等しくない場合はどうでしょうか。

完全にコード化されたソリューションを提供するのではなく、私が始めるためのちょっとしたお誘いを提供してください。

これが私がこれまでに持っているもので、テキストノードからタグを抽出しています

//get value of node "text" in xml
    var start = $(xml).find("text").text().indexOf('$');
    var end = $(xml).find("text").text().indexOf('}');
    var tag = "";
    var inputType;

    // find all tags and add them to a tag array
    while (start >= 0)
    {
        //console.log("Reach In Loop " + start)
        tag = theLetter.slice(start + 2, end);
        tagArray.push(tag);
        tagReplaceArray.push(theLetter.slice(start, end + 1));
        start = theLetter.indexOf('$', start + 1);
        end = theLetter.indexOf('}', end + 1);
    }

他の推奨事項や同様の問題へのリンクを歓迎します。

ありがとうございました!

4

3 に答える 3

5

I am using a similar technique to do html templating.

Instead of working with elements, I find it easier to work with a string and then convert it to html. In your case with jQuery, you could do something similar:

Have your xml as a string:

var xmlString='<?xml version="1.0" encoding="UTF-8"?><message><text>${Prologue} - Dear ${Title} ${Surname}... ';

Iterate through the string to do the replacements with a regex ($1 is the captured placeholder, for example Surname):

xmlString.replace(/$\{([^}]+)}/g,function($0,$1)...}

Convert to nodes if needed:

var xml=$(xmlString);

The benefits of the regex:

  • faster (just a string, you're not walking the DOM)
  • global replace (for example if Surname appears several times), just loop through your object properties once
  • simple regex /${([^}]+)}/ to target the placeholder
于 2013-02-06T21:50:55.837 に答える
1

あなたが尋ねたように、これはあなたを動かすための単なるフレームワークです。

最初の概念は、正規表現を使用して ${ } のすべての一致を見つけることです。["${one}","${tw 0 }","${ three}"] のような配列を返します。

2 番目の概念は、"inputTypes-->childname" を html 出力を担当する関数にマッピングする htmlGenerator json オブジェクトです。

3 つ目は、自然な JavaScript を忘れないことです。.localnamexml 要素の名前が返され、namedNodeMapが返されます (jquery オブジェクトに対して自然な JavaScript を実行しないことを忘れないでください。jQuery が見つけたノード要素を参照していることを確認してください) node.attributes

実際の流れは単純です。

すべての「${}」トークンを見つけて、結果を配列に格納します。

xml ドキュメント内のすべてのトークンを検索し、それらの親情報を使用して、html をマップに保存します{"${one}":"<input type='text' .../>","${two}":"<select><option value='hello'>world!</option></select>" ...}

マップを反復処理し、ソース テキスト内のすべてのトークンを必要な html に置き換えます。

JavaScript

    var $xmlDoc = $(xml); //store the xml document
    var tokenSource =$xmlDoc.find("message text").text(); 
    var tokenizer=/${[^}]+/g; //used to find replacement locations
    var htmlGenerators = {
      "textBox":function(name,$elementParent){
    //default javascript .attributes returns a namedNodeMap, I think jquery can handle it, otherwise parse the .attributes return into an array or json obj first.
      var parentAttributes = ($elementParent[0] && $elementParent.attributes)?$elementParent.attributes:null;
    //this may be not enough null check work, but you get the idea
      var specificAttributes =$elementParent.find(name)[0].attributes;
      var combinedAttributes = {};
      if(parentAttributes && specificAttributes){
    //extend or overwrite the contents of the first obj with contents from 2nd, then 3rd, ... then nth [$.extend()](http://api.jquery.com/jQuery.extend/)
          $.extend(combinedAttributes,parentAttributes,specificAttributes);
      }
      return $("<input>",combinedAttributes);
    },
      "date":function(name,$elementParent){
       //whatever you want to do for a 'date' text input
    },
      "select":function(name,$elementParent){
      //put in a default select box implementation, obviously you'll need to copy options attributes too in addition to their value / visible value.
    }
    };
    var html={};
    var tokens = tokenSource.match(tokenizer); //pull out each ${elementKey}
    for(index in tokens){
      var elementKey = tokens[index].replace("${","").replace("}"),"");//chomp${,}
      var $elementParent = $xmlDoc.find(elementKey).parent();//we need parent attributes.  javascript .localname should have the element name of your xml node, in this case "textBox","date" or "select".  might need a [0].localname....
      var elementFunction = ($elementParent.localname)?htmlGenerators[elementParent.localname]:null; //lookup the html generator function
      if(elementFunction != null){ //make sure we found one
        html[tokens[index]] = elementFunction(elementKey,elementParent);//store the result
      }
    }
  

      for(index in html){
       //for every html result, replace it's token
          tokenSource = tokenSource.replace(index,html[index]);
        }
于 2013-02-06T21:29:14.637 に答える
1

テキスト ノードからタグのリストを取得し、「fields」という配列を作成します

配列を作成するには、むしろ正規表現を使用したいと思います。実際にパターンを検索しているため、これは (私の意見では) 最良の使用方法の 1 つです。

var reg = /\$\{(\w+)\}/gm;
var i = 0;
var fields = new Array();

while (  (m = reg.exec(txt)) !== null)
{
    fields[i++] = m[1];
}

「fields」配列の各項目について

jQuery はいくつかのユーティリティ関数を提供します:

フィールドを反復処理するには、次のようにします。$.each(fields, function(index, value){});

ノードをナビゲートして値を取得する

すでに行っているように、 jQuery 関数を使用するだけです。

HTML の構築

担当する各タイプのテンプレート オブジェクトを作成します (この例では : TextSelect) 。

次に、上記のテンプレートを使用して、トークンをテンプレートの HTML に置き換えることができます。

HTML の表示

最後のステップは、結果の文字列を解析し、適切な場所に追加することです。

var ResultForm = $.parseHTML(txt); 

$("#DisplayDiv").append(ResultForm);

結論

あなたが尋ねたように、箱から出してすぐに動作するものは何も準備していません。あなた自身の答えを準備するのに役立つことを願っています. (そして、コミュニティと共有していただければ幸いです)

于 2013-02-07T03:16:31.573 に答える