Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagehtml
<html>
<head>

  <style>                        
    #sortable1, #sortable2 {
      border: 1px solid #eee;
      width: 142px;
      min-height: 20px;
      list-style-type: none;
      margin: 0;
      padding: 5px 0 0 0;
      float: left;
      margin-right: 10px;
    }
    #sortable1 li, #sortable2 li {
      margin: 0 5px 5px 5px;
      padding: 5px;
      font-size: 1.2em;
      width: 120px;
    }
  </style>   

</head>

<script type='text/javascript' src='FRToolBox.js'></script>
<script src="jquery-3.4.1.min.js"></script>
<script src="jquery-ui.min.js"></script>

<script>

  FMLink = 'FM.link';
  FMTableOccurrenceName = '<?Reactor bbdev_TO( $PlanetIDField ) Reactor?>';
  FunctionWhereClause = '<?Reactor bbdev_Relationship( bbdev_TO( $PlanetIDField  ) ) Reactor?>';
  CreationValues = '<?reactor bbdev_relationshipKeyBuilder ( $FMTableOccurrenceName ) reactor?>';
  PlanetIDField = '<?Reactor bbdev_Field( $PlanetIDField ) Reactor?>';
  PlanetNameField = '<?Reactor bbdev_Field( $PlanetNameField ) Reactor?>';
  PlanetDescriptionField = '<?Reactor bbdev_Field( $PlanetDescriptionField ) Reactor?>';
  PlanetTripNoField = '<?Reactor bbdev_Field( $PlanetTripNoField ) Reactor?>';
  PlanetSortNoField = '<?Reactor bbdev_Field( $PlanetSortNoField ) Reactor?>';
  Columns = '<?Reactor $Columns Reactor?>';

  $( function() {
  $( "#sortable1, #sortable2" ).sortable({
  connectWith: ".connectedSortable"
  }).disableSelection();
  } );

</script>

<body>          
  <ul id="sortable1" class="connectedSortable">
    <li class="ui-state-default">Item 1</li>
    <li class="ui-state-default">Item 2</li>
    <li class="ui-state-default">Item 3</li>
    <li class="ui-state-default">Item 4</li>
    <li class="ui-state-default">Item 5</li>
  </ul>
  
  <ul id="sortable2" class="connectedSortable">
    <li class="ui-state-highlight">Item 1</li>
    <li class="ui-state-highlight">Item 2</li>
    <li class="ui-state-highlight">Item 3</li>
    <li class="ui-state-highlight">Item 4</li>
    <li class="ui-state-highlight">Item 5</li>
  </ul>        
</body>

</html>   

Now switch to the ‘Preview’ screen and click the Compile button. You should see your new BlackBox appear before your eyes:

...

Next, in our Kanban board we’re going to want to show a planet name, and a planet description. So change the HTML so that each <li> element contains a second line of text:

<ul 「プレビュー」画面に切り替えて、「コンパイル」ボタンをクリックします。新しい BlackBox が目の前に表示されるはずです。:

...

次に、かんばんボードに惑星名と惑星の説明を表示します。したがって、各 <li> 要素に 2 行目のテキストが含まれるように HTML を変更します。:

Code Block
<ul id="sortable1" class="connectedSortable">

...


  <li><div class=name>Item 1</div><div class=desc>The first item</div></li>

...


  <li><div class=name>Item 2</div><div class=desc>The second item</div></li>

...


  <li><div class=name>Item 3</div><div class=desc>The third item</div></li>

...


  <li><div class=name>Item 4</div><div class=desc>The fourth item</div></li>

...


  <li><div class=name>Item 5</div><div class=desc>The fifth item</div></li>

...


</ul>

...



<ul id="sortable2" class="connectedSortable">

...


  <li><div class=name>Item 1</div><div class=desc>The first item</div></li>

...


  <li><div class=name>Item 2</div><div class=desc>The second item</div></li>

...


  <li><div class=name>Item 3</div><div class=desc>The third item</div></li>

...


  <li><div class=name>Item 4</div><div class=desc>The fourth item</div></li>

...


  <li><div class=name>Item 5</div><div class=desc>The fifth item</div></li>

...


</ul>

...

       

...

Great. Doesn’t quite ‘pop’ though does it? Replace the いいですね。しかし、それはかなり「ポップ」ではありませんか? CSS ( contents of your <style> block) with this: ブロックの内容) を次のように置き換えます。:

Code Block
#sortable1, #sortable2 {

...


  width: 142px;

...


  min-height: 20px;

...


  list-style-type: none;

...


  margin: 0;

...


  padding: 5px 0 0 0;

...


  float: left;

...


  margin-right: 10px;

...


}

...


#sortable1 li, #sortable2 li {

...


  margin: 0 5px 5px 5px;

...


  padding: 5px;

...


  width: 120px;

...


  border:black solid 1px;

...


  background-color:#123a53;

...


  color:white;

...


  font-size:16px;

...


}

Recompile and take a look:再コンパイルして見てみましょう:

...

There, that’s looking a bit better. Feel free to make further CSS adjustments.

Ok, we have our base UI sorted, let’s start putting some data into it.

Accessing Planet Data

First, replace the contents inside our <body> tags with this:

<div ほら、少し良くなっています。さらにCSSを自由に調整してください。

OK、ベース UI がソートされたので、いくつかのデータを入力してみましょう。

惑星データへのアクセス

まず、 <body> タグ内のコンテンツを次のように置き換えます:

Code Block
<div id=Kanban></div>

We need to dynamically generate the HTML content from our Planet records, so this just provides us with a place to put it.

Now, for getting the data in. We need to:

  1. Query Reactor for the Planet records

  2. Create an ‘Unassigned’ column for records that don’t have a Trip No value

    1. Add an HTML element for each of these records to the ‘Unassigned’ column

  3. For each column provided in our parameter:

    1. Check our query response for records that belong in this column (based on the Trip No field, and add an HTML element for each of these records to the column

So, replace the contents inside our <script> tags with the following:

FMLink = Planet レコードから HTML コンテンツを動的に生成する必要があるため、これは単にそれを配置する場所を提供するだけです。

次に、データを取得します。次のことを行う必要があります。:

  1. Reactor で Planetレコードへのクエリを行う

  2. Trip Noの値を持たないレコードの「未割り当て」列を作成します

    1. これらの各レコードの HTML 要素を [未割り当て] 列に追加します

  3. パラメータで指定された各列について:

    1. この列に属するレコードのクエリ応答を確認します。 (Trip No フィールドに基づいて、これらの各レコードの HTML 要素を列に追加します)

したがって、 <script> タグ内のコンテンツを次のように置き換えます。:

Code Block
FMLink = 'FM.link';

...



// This is where variables are set from the given parameters

...


FMTableOccurrenceName = '<?Reactor bbdev_TO( $PlanetIDField ) Reactor?>';

...


FunctionWhereClause = '<?Reactor bbdev_Relationship( bbdev_TO( $PlanetIDField

...

  ) ) Reactor?>';

...


CreationValues = '<?reactor bbdev_relationshipKeyBuilder ( $FMTableOccurrenceName ) reactor?>';

...



PlanetIDField = '<?Reactor bbdev_Field( $PlanetIDField ) Reactor?>';

...


PlanetNameField = '<?Reactor bbdev_Field( $PlanetNameField ) Reactor?>';

...


PlanetDescriptionField = '<?Reactor bbdev_Field( $PlanetDescriptionField ) Reactor?>';

...


PlanetTripNoField = '<?Reactor bbdev_Field( $PlanetTripNoField ) Reactor?>';

...


PlanetSortNoField = '<?Reactor bbdev_Field( $PlanetSortNoField ) Reactor?>';

...


Columns = '<?Reactor $Columns Reactor?>';

...


var PlanetsArr = new Array();

...



// Populate columns

...



function findPlanets()

...

  FRTB.find(

...

 {                        
  FRTB.find(
    FMTableOccurrenceName + "::" + PlanetIDField,

...


    FMTableOccurrenceName + "::" + PlanetNameField,

...


    FMTableOccurrenceName + "::" + PlanetDescriptionField,

...


    FMTableOccurrenceName + "::" + PlanetTripNoField,

...


    FMTableOccurrenceName + "::" + PlanetSortNoField

...


  ).where(FunctionWhereClause).send(function(response)

...

 {                                  
    for ( var i=0; i < response.data.length; i++)

...

 {
      ThisPlanetObj = new Object();

...


      ThisPlanetObj.id          = response.data[i][FMTableOccurrenceName + "::" + PlanetIDField];

...


     ThisPlanetObj.name        = response.data[i][FMTableOccurrenceName + "::" + PlanetNameField];

...


     ThisPlanetObj.description = response.data[i][FMTableOccurrenceName + "::" + PlanetDescriptionField];

...


     ThisPlanetObj.trip_no

...

     = response.data[i][FMTableOccurrenceName + "::" + PlanetTripNoField];

...


     ThisPlanetObj.sort_no

...

     = response.data[i][FMTableOccurrenceName + "::" + PlanetSortNoField];

...


     PlanetsArr.push(ThisPlanetObj);

...

    }        

...


    }        
    buildHtml();

...

  
    PlanetsArr.sort(function(a, b){

...


      return a.sort_no > b.sort_no;

...

    });              

  });

}

function buildHtml() {

...


    });              
  });
}

function buildHtml() {
  ColumnsArr = Columns.split(",");

...


  htmlString = "";

...


  columnsIDsArray = Array();

...


  htmlString += "<ul id='sortable_unassigned' class='connectedSortable'>";

...

        
  htmlString += "<div class=Column>Unassigned</div>";

...

        
    for ( var i=0; i < PlanetsArr.length; i++)

...

 {
    if (PlanetsArr[i].trip_no == "")

...

 {
      htmlString += "<li class=name id='" + PlanetsArr[i].id + "'><div>";

...


     htmlString += PlanetsArr[i].name;

...


     htmlString += "</div><div class=desc>";

...


     htmlString += PlanetsArr[i].description;

...

                        
     htmlString += "</div></li>";

...

    }

  }

...


    }
  }
  htmlString += "</ul>";

...


  columnsIDsArray[0] = "#sortable_unassigned";

...



  for ( var i=0; i < ColumnsArr.length; i++)

...

 {
    htmlString += "<ul id='sortable_" + i + "' class='connectedSortable'>";

...

        
   htmlString += "<div class=Column>" + ColumnsArr[i] + "</div>";

...

        
   for ( var j=0; j < PlanetsArr.length; j++)

...

 {
      if (PlanetsArr[j].trip_no == (i+1))

...

 {
        htmlString += "<li class=name id='" + PlanetsArr[j].id + "'><div>";

...


        htmlString += PlanetsArr[j].name;

...


        htmlString += "</div><div class=desc>";

...


        htmlString += PlanetsArr[j].description;

...

                        
        htmlString += "</div></li>";

...

      }

    }

...


      }
    }
    htmlString += "</ul>";

...


    columnsIDsArray[i+1] = "#sortable_" + i;

...

  }

...


  }
  $('#Kanban').html(htmlString);

...


  $( columnsIDsArray.join() ).sortable({

...


    connectWith: ".connectedSortable"

...


  }).disableSelection();

...



}

...



$( function() {

...


  findPlanets();

...


});

Quite a lot of code isn’t it? Let’s go through it bit-by-bit.

かなりたくさんのコードですね。少しずつ見ていきましょう。

惑星データのクエリ Query Planet Data

Code Block
function findPlanets()

...

  FRTB.find(

...

 {                        
  FRTB.find(
    FMTableOccurrenceName + "::" + PlanetIDField,

...


    FMTableOccurrenceName + "::" + PlanetNameField,

...


    FMTableOccurrenceName + "::" + PlanetDescriptionField,

...


    FMTableOccurrenceName + "::" + PlanetTripNoField,

...


    FMTableOccurrenceName + "::" + PlanetSortNoField

...


  ).where(FunctionWhereClause).send(function(response)

...

 {                                   $('#Kanban').html("");

...


    PlanetsArr = new Array();

...


    for ( var i=0; i < response.data.length; i++)

...

 {
      ThisPlanetObj = new Object();

...


      ThisPlanetObj.id          = response.data[i][FMTableOccurrenceName + "::" + PlanetIDField];

...


     ThisPlanetObj.name        = response.data[i][FMTableOccurrenceName + "::" + PlanetNameField];

...


     ThisPlanetObj.description = response.data[i][FMTableOccurrenceName + "::" + PlanetDescriptionField];

...


     ThisPlanetObj.trip_no

...

     = response.data[i][FMTableOccurrenceName + "::" + PlanetTripNoField];

...


     ThisPlanetObj.sort_no

...

     = response.data[i][FMTableOccurrenceName + "::" + PlanetSortNoField];

...


     PlanetsArr.push(ThisPlanetObj);

...

    }        

...


    }        
    PlanetsArr.sort(function(a, b){

...


      return a.sort_no > b.sort_no;

...


    });

...

   buildHtml();           

  });

}

First we set up our find request, accessing the following fields:

  • Planet ID

  • Planet Name

  • Planet Description

  • Trip No

  • Sort No

When a response comes back, we loop through the different records in the response. We create an object for each record, assign each object the above properties, and push the object onto an array of Planet objects.

We then sort the array of Planet objects based on the Sort No value.

Then we run the buildHtml() function.

   
   buildHtml();             
  });
}

まず、次のフィールドにアクセスして検索条件を設定します。:

  • Planet ID (惑星ID)

  • Planet Name (惑星名)

  • Planet Description (惑星の説明)

  • Trip No (旅行番号)

  • Sort No (ソート番号)

応答が返ってきたら、応答内のさまざまなレコードをループします。レコードごとにオブジェクトを作成し、各オブジェクトに上記のプロパティを割り当て、そのオブジェクトを Planet オブジェクトの配列にプッシュします。

次に、Sort No の値に基づいて Planet オブジェクトの配列を並べ替えます。

次に、buildHtml() 関数を実行します。

Trip Noのないレコードの列を追加し、それに惑星を割り当てる Add column for records without a Trip No and assign planets to it 

Code Block
ColumnsArr = Columns.split(",");

...


htmlString = "";

...


columnsIDsArray = Array();

...


htmlString += "<ul id='sortable_unassigned' class='connectedSortable'>";

...

        
htmlString += "<div class=Column>Unassigned</div>";

...

        
  for ( var i=0; i < PlanetsArr.length; i++)

...

 {
    if (PlanetsArr[i].trip_no == "")

...

 {
      htmlString += "<li class=name id='" + PlanetsArr[i].id + "'><div>";

...


      htmlString += PlanetsArr[i].name;

...


      htmlString += "</div><div class=desc>";

...


      htmlString += PlanetsArr[i].description;

...

                        
      htmlString += "</div></li>";

...

    }

  }

...


    }
  }
htmlString += "</ul>";

...


columnsIDsArray[0] = "#sortable_unassigned";

Now we take our comma separated list of columns and turn them into an array - this allows us to easily iterate through it later. We also start to generate our HTML for our Unassigned column.

Then we loop through our array of Planet records. For each, each check to see if there isn’t a Trip No set, and if not we add it to our Unassigned column by appending the HTML for each of these Planets. We also create a columnsIDArray array and pop our new Unassigned column into it as its first value. We’ll use this later to instruct the JavaScript library to treat it as a draggable box.

次に、コンマ区切りの列のリストを取得して配列に変換します。これにより、後で簡単に反復処理を行うことができます。Unassigned 列の HTML の生成も開始します。

次に、Planet レコードの配列をループします。それぞれについて、Trip No セットがないかどうかを確認し、そうでない場合は、これらの惑星のそれぞれに HTML を追加することによって、それを Unassigned 列に追加します。また、columnsIDArray 配列を作成し、新しい Unassigned 列を最初の値としてそこに取り込みます。後でこれを使用して、ドラッグ可能なボックスとして扱うように JavaScript ライブラリに指示します。

各列に目を通し、Planet レコードを分類します Go through each column, and categorise our Planet records 

Code Block
for ( var i=0; i < ColumnsArr.length; i++) {

...


  htmlString += "<ul id='sortable_" + i + "' class='connectedSortable'>";

...

        
  htmlString += "<div class=Column>" + ColumnsArr[i] + "</div>";

...

        
  for ( var j=0; j < PlanetsArr.length; j++)

...

 {
    if (PlanetsArr[j].trip_no == (i+1))

...

 {
      htmlString += "<li class=name id='" + PlanetsArr[j].id + "'><div>";

...


      htmlString += PlanetsArr[j].name;

...


      htmlString += "</div><div class=desc>";

...


      htmlString += PlanetsArr[j].description;

...

                        
      htmlString += "</div></li>";

...

    }

  }

...


    }
  }
  htmlString += "</ul>";

...


  columnsIDsArray[i+1] = "#sortable_" + i;

...

}

...


}

最初に各Columnをループし、Unassigned列に対して行った方法と同様に、その列の HTML の生成を開始します。

次に、Column ごとに Planet レコードの配列をループし、Planet レコードがこの Column に属している場合は、これらの惑星ごとに HTML を追加して、その列に追加します。次の列にループする前に、columnsIDArray に挿入します。

Then for each Column we loop through our array of Planet records, and if a Planet record belongs in this Column we add it to that column by appending the HTML for each of these planets. Before we loop to the next Column we pop it onto our columnsIDArray.

ドラッグ可能なリストをインスタンス化する Instantiate our draggable list

Code Block

...

  $('#Kanban').html(htmlString);

...


  $( columnsIDsArray.join() ).sortable({

...


    connectWith: ".connectedSortable"

...


  }).disableSelection();

Now we tell the JavaScript to place the variable containing our generated HTML into our 次に、生成された HTML を含む変数を <div id="Kanban"> element. 要素に配置するよう JavaScript に指示します。

(Just a quick note on the technique we’re using to populate the HTML - this is quite primitive. There are much more elegant ways using the JQuery library to change or append to HTML elements, this technique we’re employing - of building a single string bit-by-bit - makes it clear what we’re actually doing).

Then we tell the JQuery library to instantiate the .sortable() method on our array of Column IDs (this is the IDs of our HTML elements)- although first we have to use the join() method to transform our array of ColumnIDs into a comma separated list of Column IDs - as this is the form that the method expects. This is what ‘activates’ our planet boxes - makes them draggable.

Now, ensure your JavaScript matches the JavaScript as above, recompile your BlackBox, and set the following parameters over on the Preview tab:

...

Fantastic!

The Planets might appear under different columns depending on whether they have Trip No values set. If there are none set, you should see them all under Unassigned.

If you’re seeing something completely different, or nothing at all, make sure you’ve entered the JavaScript exactly as above. Ensure you’ve imported all required JavaScript libraries - the order matters too. You must import the core JQuery library before importing the JQuery-UI library.

Failing that, enter debugging mode by popping the following into your FM data viewer:

...

And click the Reactor icon in the bottom-right of your web-viewer, and click Browser.

...

This will open the BlackBox in your default web browser, where you can use the Developers Tools to debug it.

Changing sort order

So now we’ve got our Kanban board pulling in our Planet records and sorting them into the right columns. We can move these Planets around - but these changes are not recorded. The next time you load the web-viewer, your changes will be lost (unless you also change the data back in FileMaker Pro).

The first thing we need is a way to intercept when a Planet has been moved. We can do this with an event handler.

An Event is something a user, or your browser, does. Handlers can be attached to particular events to capture when they happen, and the details of what’s happened.

To proceed, we need to consult the documentation.HTML に入力するために使用している手法について簡単に説明します。これは非常に原始的です。JQuery ライブラリを使用して、HTML 要素を変更または追加するためのはるかに洗練された方法がありますが、この手法を採用しています。単一の文字列ビットごと - 実際に何をしているかを明確にします)。

次に、列 ID の配列 (これは HTML 要素の ID) で .sortable() メソッドをインスタンス化するように JQuery ライブラリに指示しますが、最初に join() メソッドを使用して列 ID の配列を列 ID のコンマ区切りリスト - これはメソッドが期待する形式です。これがプラネット ボックスを「アクティブ化」し、ドラッグ可能にします。

ここで、JavaScript が上記の JavaScript と一致することを確認し、BlackBox を再コンパイルして、[プレビュー] タブで次のパラメーターを設定します。:

...

素晴らしい!

惑星は、Trip No 値が設定されているかどうかに応じて、異なる列の下に表示される場合があります。何も設定されていない場合は、未割り当ての下にすべて表示されます。

まったく異なるもの、またはまったく何も表示されない場合は、上記のように JavaScript を正確に入力したことを確認してください。必要なすべての JavaScript ライブラリをインポートしたことを確認してください。順序も重要です。 JQuery-UI ライブラリをインポートする前に、コア JQuery ライブラリをインポートする必要があります。

それができない場合は、FM データビューアに次のコードを入力してデバッグ モードに入ります。:

...

Web ビューアの右下にある Reactor アイコンをクリックし、Browser をクリックします。

...

これにより、デフォルトの Web ブラウザで BlackBox が開き、開発者ツールを使用してデバッグできます。

ソート順の変更 Changing sort order

これで、かんばんボードに Planet レコードを取り込み、正しい列に並べ替えることができました。これらの惑星を移動することはできますが、これらの変更は記録されません。次に Webビューアを読み込むと、変更は失われます (FileMaker Pro でデータを元に戻さない限り)

最初に必要なのは、Planet が移動したときにインターセプトする方法です。これは、イベントハンドラーを使用して実行できます。

イベントとは、ユーザまたはブラウザが行うことです。ハンドラーを特定のイベントにアタッチして、イベントがいつ発生したか、および何が起こったかの詳細をキャプチャできます。

続行するには、ドキュメントを参照する必要があります。

https://api.jqueryui.com/sortable/#event-receive

https://api.jqueryui.com/sortable/#event-stop

These two events are useful to us. The recieve event fires when a Planet is moved into another list, and we need to update the Trip No and Sort No. The stop event fires when a Planet is moved within its own list, and we need to update the Sort No.

To capture an event, change this:

$( この 2 つのイベントは、私たちにとって有益です。惑星が別のリストに移動すると、recieve 受信イベントが発生し、Trip NoSort Noを更新する必要があります。惑星が独自のリスト内で移動すると、stop 停止イベントが発生し、Sort Noを更新する必要があります。

イベントをキャプチャするには、次のように変更します。:

Code Block
$( columnsIDsArray.join() ).sortable({

...


  connectWith: ".connectedSortable"

...


}).disableSelection();

これに:To this:

Code Block
$( columnsIDsArray.join() ).sortable({

...


  connectWith: ".connectedSortable",

...


  receive: function (event,ui)

...

 {
    // Do something

...

  }


  }
}).disableSelection();

So let’s have a think about what we need to tell FileMaker when dragging a Planet to a different location. First off, we’re changing what column it’s assigned to, so we need to write that back. But just as importantly, we have effectively changed the sort order in the target column, as the Planets that sit below where we’re dragging to are now pushed down the sort order.

...