<commit_before>var wordcloudGlobal;
$("#get-nodes").on("click", function() {
  $.get('/getGraph', function(graph) {
    var container = document.getElementById('mynetwork');
    if (graph) {
      var options = {
        nodes: {
          shape: 'dot',
          size: 20,
          font: {
            size: 22
          },
          borderWidth: 2,
          shadow: true,
        },
        edges: {
          width: 2,
          shadow: true
        },
        physics: {
          maxVelocity: 50,
          minVelocity: 0.5
          //,          solver: "hierarchicalRepulsion"
        }
      };
      network = new vis.Network(container, graph, options);
      networkGlobal = network;
    } else {
      container.innerHTML = "Unable to construct graph.";
    }
  });
});
$("#get-wordcloud").on("click", function() {
  $.get('/getWordCloud', function(list) {
    var wordcloud = document.getElementById('my_wordcloud');
    if (list) {
      console.log(list);
      var option = {
        color: '#15a4fa',
        noDataLoadingOption: {
          backgroundColor: '#eee',
          text: '',
          textStyle: {
            color: function(item) {
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    return array[2];
                  }
                }
              }
            },
            fontWeight: function(item) {
              console.log(item);
              var fontWeightList;
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    if (array[4]) {
                      fontWeightList.push('\'' + array[4] + " " + '\'');
                    } else {
                      console.log("Error en fontWeight!");
                    }
                  }
                }
              }
              return fontWeightList;
            },
            fontFamily: function(item) {
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    return '\'' + array[3] + '\'';
                  }
                }
              }
              console.log(item);
            },
            fontSize: 1
          }
        }
      }
      var wc = new Js2WordCloud(wordcloud);
      wc.showLoading()
      setTimeout(function() {
        wc.hideLoading()
        wc.setOption(option)
      }, 10)
      var option8 = {
        tooltip: {
          show: true,
          formatter: function(item) {
            var resultFormat = 'Name: ' + item[0] + ', Size: ' + item[1] + ', Color: ' + item[2] + ', Font Family: ' + item[3];
            if (item[4])
              resultFormat += ', Font Weight: ' + item[4];
            resultFormat += '
' + ''
            return resultFormat;
          }
        },
        list: list,
        color: function(item) {
          for (var i = 0; i < list.length; i++) {
            var array = list[i];
            for (var j = 0; j < array.length; j++) {
              if (array[j] == item) {
                return array[2];
              }
            }
          }
        },
        // fontWeight: function(item) {
        //   console.log(item);
        //   for (var i = 0; i < list.length; i++) {
        //     var array = list[i];
        //     for (var j = 0; j < array.length; j++) {
        //       if (array[j] == item) {
        //         console.log("fontWeight: " + array[4]);
        //         if (array[4]) {
        //           return '\'' + array[4] + " " + '\'';
        //         } else {
        //           console.log("Error en fontWeight!");
        //         }
        //       }
        //     }
        //   }
        // },
        // fontFamily: function(item) {
        //   for (var i = 0; i < list.length; i++) {
        //     var array = list[i];
        //     for (var j = 0; j < array.length; j++) {
        //       if (array[j] == item) {
        //         console.log(array[3]);
        //         //return '\'' + array[2] + '\'';
        //         return '\'' + array[3] + '\'';
        //       }
        //     }
        //   }
        //   console.log(item);
        // },
        shape: 'circle',
        ellipticity: 1
      }
      setTimeout(function() {
        wc.setOption(option8)
      }, 4000)

      window.onresize = function() {
        wc.resize()
      }
    } else {
      wordcloud.innerHTML = "Unable to construct wordcloud.";
    }
  });
});
// $("#get-own-wordcloud").on("click", function() {
//   $.get('/getWordCloud', function(list) {
//     var ownWordcloud = document.getElementById('ownWordcloud');
//     if (list) {
//       var ctx = ownWordcloud.getContext("2d");
//       var dataURL = ownWordcloud.toDataURL();
//       document.getElementById('ownWordcloud').src = dataURL;
//       for (var i = 0; i < list.length; i++) {
//         var array = list[i];
//         var fontSize = 2;
//         var minFontSize = 1;
//         // Scale factor here is to make sure fillText is not limited by
//         // the minium font size set by browser.
//         // It will always be 1 or 2n.
//         var mu = 1;
//         if (fontSize < minFontSize) {
//           mu = function calculateScaleFactor() {
//             var mu = 2;
//             while (mu * fontSize < minFontSize) {
//               mu += 2;
//             }
//             return mu;
//           }();
//         }
//         ctx.font = array[1] + ' ' + (fontSize * mu).toString(10) + 'px ' + array[3];
//         ctx.fillStyle = array[2];
//         ctx.fillText(array[0], i, i * 20);
//       }
//       // ctx.font = "20px " + list[0][3];
//       // ctx.fillStyle = list[0][2];
//       // ctx.fillText(list[0][0], 10, 10);
//       //
//       // ctx.font = "20px " + list[1][3];
//       // ctx.fillStyle = list[1][2];
//       // ctx.fillText(list[1][0], 10, 30);
//     } else {
//       ownWordcloud.innerHTML = "Unable to construct your own wordcloud.";
//     }
//   });
// });

$("#save-nodes").on("click", function() {
  $.get('/saveGraph', function(graphGlobal) {
    var container = document.getElementById('mynetwork');
    if (graphGlobal) {
      var canvasGraph = document.getElementById('canvasGraph');
      var ctx = canvasGraph.getContext('2d');
      var dataURL = canvasGraph.toDataURL();
      document.getElementById('mynetwork').src = dataURL;
      domtoimage.toJpeg(document.getElementById('mynetwork'), {
          quality: 0.95
        })
        .then(function(dataUrl) {
          var link = document.createElement('a');
          link.download = 'my_network.jpeg';
          link.href = dataUrl;
          link.click();
        });
    } else {
      container.innerHTML = "Unable to download graph.";
    }
  });
});

$("#save-wordcloud").on("click", function() {
  var container = document.getElementById('my_wordcloud');
  var canvasWordcloud = document.getElementById('canvasWordcloud');
  var ctx = canvasWordcloud.getContext('2d');
  var dataURL = canvasWordcloud.toDataURL();
  document.getElementById('my_wordcloud').src = dataURL;
  console.log(dataURL);
  console.log("afterDrawing WordCloud global");
  domtoimage.toJpeg(document.getElementById('my_wordcloud'), {
      quality: 0.95
    })
    .then(function(dataUrl) {
      var link = document.createElement('a');
      link.download = 'my_wordcloud.jpeg';
      link.href = dataUrl;
      link.click();
    });
});
<commit_msg>default options to network.<commit_after>var wordcloudGlobal;
$("#get-nodes").on("click", function() {
  $.get('/getGraph', function(graph) {
    var container = document.getElementById('mynetwork');
    if (graph) {
      var options = {
        nodes: {
          shape: 'dot',
          size: 20,
          font: {
            size: 22
          },
          borderWidth: 2,
          shadow: true,
        },
        edges: {
          width: 2,
          shadow: true
        }
      };
      network = new vis.Network(container, graph, options);
      networkGlobal = network;
    } else {
      container.innerHTML = "Unable to construct graph.";
    }
  });
});
$("#get-wordcloud").on("click", function() {
  $.get('/getWordCloud', function(list) {
    var wordcloud = document.getElementById('my_wordcloud');
    if (list) {
      console.log(list);
      var option = {
        color: '#15a4fa',
        noDataLoadingOption: {
          backgroundColor: '#eee',
          text: '',
          textStyle: {
            color: function(item) {
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    return array[2];
                  }
                }
              }
            },
            fontWeight: function(item) {
              console.log(item);
              var fontWeightList;
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    if (array[4]) {
                      fontWeightList.push('\'' + array[4] + " " + '\'');
                    } else {
                      console.log("Error en fontWeight!");
                    }
                  }
                }
              }
              return fontWeightList;
            },
            fontFamily: function(item) {
              for (var i = 0; i < list.length; i++) {
                var array = list[i];
                for (var j = 0; j < array.length; j++) {
                  if (array[j] == item) {
                    return '\'' + array[3] + '\'';
                  }
                }
              }
              console.log(item);
            },
            fontSize: 1
          }
        }
      }
      var wc = new Js2WordCloud(wordcloud);
      wc.showLoading()
      setTimeout(function() {
        wc.hideLoading()
        wc.setOption(option)
      }, 10)
      var option8 = {
        tooltip: {
          show: true,
          formatter: function(item) {
            var resultFormat = 'Name: ' + item[0] + ', Size: ' + item[1] + ', Color: ' + item[2] + ', Font Family: ' + item[3];
            if (item[4])
              resultFormat += ', Font Weight: ' + item[4];
            resultFormat += '
' + ''
            return resultFormat;
          }
        },
        list: list,
        color: function(item) {
          for (var i = 0; i < list.length; i++) {
            var array = list[i];
            for (var j = 0; j < array.length; j++) {
              if (array[j] == item) {
                return array[2];
              }
            }
          }
        },
        // fontWeight: function(item) {
        //   console.log(item);
        //   for (var i = 0; i < list.length; i++) {
        //     var array = list[i];
        //     for (var j = 0; j < array.length; j++) {
        //       if (array[j] == item) {
        //         console.log("fontWeight: " + array[4]);
        //         if (array[4]) {
        //           return '\'' + array[4] + " " + '\'';
        //         } else {
        //           console.log("Error en fontWeight!");
        //         }
        //       }
        //     }
        //   }
        // },
        // fontFamily: function(item) {
        //   for (var i = 0; i < list.length; i++) {
        //     var array = list[i];
        //     for (var j = 0; j < array.length; j++) {
        //       if (array[j] == item) {
        //         console.log(array[3]);
        //         //return '\'' + array[2] + '\'';
        //         return '\'' + array[3] + '\'';
        //       }
        //     }
        //   }
        //   console.log(item);
        // },
        shape: 'circle',
        ellipticity: 1
      }
      setTimeout(function() {
        wc.setOption(option8)
      }, 4000)

      window.onresize = function() {
        wc.resize()
      }
    } else {
      wordcloud.innerHTML = "Unable to construct wordcloud.";
    }
  });
});
// $("#get-own-wordcloud").on("click", function() {
//   $.get('/getWordCloud', function(list) {
//     var ownWordcloud = document.getElementById('ownWordcloud');
//     if (list) {
//       var ctx = ownWordcloud.getContext("2d");
//       var dataURL = ownWordcloud.toDataURL();
//       document.getElementById('ownWordcloud').src = dataURL;
//       for (var i = 0; i < list.length; i++) {
//         var array = list[i];
//         var fontSize = 2;
//         var minFontSize = 1;
//         // Scale factor here is to make sure fillText is not limited by
//         // the minium font size set by browser.
//         // It will always be 1 or 2n.
//         var mu = 1;
//         if (fontSize < minFontSize) {
//           mu = function calculateScaleFactor() {
//             var mu = 2;
//             while (mu * fontSize < minFontSize) {
//               mu += 2;
//             }
//             return mu;
//           }();
//         }
//         ctx.font = array[1] + ' ' + (fontSize * mu).toString(10) + 'px ' + array[3];
//         ctx.fillStyle = array[2];
//         ctx.fillText(array[0], i, i * 20);
//       }
//       // ctx.font = "20px " + list[0][3];
//       // ctx.fillStyle = list[0][2];
//       // ctx.fillText(list[0][0], 10, 10);
//       //
//       // ctx.font = "20px " + list[1][3];
//       // ctx.fillStyle = list[1][2];
//       // ctx.fillText(list[1][0], 10, 30);
//     } else {
//       ownWordcloud.innerHTML = "Unable to construct your own wordcloud.";
//     }
//   });
// });

$("#save-nodes").on("click", function() {
  $.get('/saveGraph', function(graphGlobal) {
    var container = document.getElementById('mynetwork');
    if (graphGlobal) {
      var canvasGraph = document.getElementById('canvasGraph');
      var ctx = canvasGraph.getContext('2d');
      var dataURL = canvasGraph.toDataURL();
      document.getElementById('mynetwork').src = dataURL;
      domtoimage.toJpeg(document.getElementById('mynetwork'), {
          quality: 0.95
        })
        .then(function(dataUrl) {
          var link = document.createElement('a');
          link.download = 'my_network.jpeg';
          link.href = dataUrl;
          link.click();
        });
    } else {
      container.innerHTML = "Unable to download graph.";
    }
  });
});

$("#save-wordcloud").on("click", function() {
  var container = document.getElementById('my_wordcloud');
  var canvasWordcloud = document.getElementById('canvasWordcloud');
  var ctx = canvasWordcloud.getContext('2d');
  var dataURL = canvasWordcloud.toDataURL();
  document.getElementById('my_wordcloud').src = dataURL;
  console.log(dataURL);
  console.log("afterDrawing WordCloud global");
  domtoimage.toJpeg(document.getElementById('my_wordcloud'), {
      quality: 0.95
    })
    .then(function(dataUrl) {
      var link = document.createElement('a');
      link.download = 'my_wordcloud.jpeg';
      link.href = dataUrl;
      link.click();
    });
});
<|endoftext|>


<commit_before>/*
 * vue-inputmask
 *
 * (C) 2016 Simon Clériot
 * MIT LICENCE
 *
 */

 (function(){
    var Inputmask = require('./3rd/inputmask');

    var inputmaskPlugin = {
        install: function(Vue, options) {
            Vue.directive('mask', {
                bind: function(el, binding){
                    Inputmask(binding.value).mask(el);
                },
                unbind: function(el){
                    Inputmask.remove(el);
                }
            });
        }
    };
    module.exports = inputmaskPlugin;
})()
<commit_msg>Fix inputmask unbind error<commit_after>/*
 * vue-inputmask
 *
 * (C) 2016 Simon Clériot
 * MIT LICENCE
 *
 */

(function(){
    var inputmaskPlugin = {
        InputMask: require('./3rd/inputmask'),
        install: function(Vue, options) {
            Vue.directive('mask', {
                bind: function(el, binding){
                    Inputmask(binding.value).mask(el);
                }
            });
        }
    };
    module.exports = inputmaskPlugin;
})()
<|endoftext|>


<commit_before>window.TimelineView = class TimelineView extends View {
    meta() {
        return {
            title: "Profile Timeline",
            description:
                "The Timeline view is an interactive visualization chart that allows you to zoom and pan through a chronological order of events.",
            docs: "",
        };
    }

    init(selector, person_id) {
        WikiTreeAPI.postToAPI({
            action: "getPerson",
            key: person_id,
            fields: "Parents,Siblings,Derived.ShortName,FirstName,LastNameAtBirth,LastNameCurrent,Name,BirthDate,DeathDate,Children,Spouses,Father,Mother",
        }).then(function (data) {
            var focus = data[0].person;
            var container = document.getElementById(selector.replace("#", ""));
            var list = [];
            var parentIDs = Object.keys(focus.Parents);
            var siblingIDs = Object.keys(focus.Siblings);
            var spouseIDs = Object.keys(focus.Spouses);
            var childIDs = Object.keys(focus.Children);

            /* Here we will call each person to process.
             * We start with our focus profile, and move on to
             * Parents, Siblings, Spouses, and then Children
             */
            buildEvents(focus);
            for (var i = 0; i < Object.keys(focus.Parents).length; i++) {
                buildEvents(focus.Parents[parentIDs[i]]);
            }
            for (var i = 0; i < Object.keys(focus.Siblings).length; i++) {
                buildEvents(focus.Siblings[siblingIDs[i]]);
            }
            for (var i = 0; i < Object.keys(focus.Spouses).length; i++) {
                buildEvents(focus.Spouses[spouseIDs[i]]);
            }
            for (var i = 0; i < Object.keys(focus.Children).length; i++) {
                buildEvents(focus.Children[childIDs[i]]);
            }

            /* This is global function to build our markers and timespans. For each
             * person passed to it, we evaluate the dates and build our content labels.
             *
             * WikiTree stores falsy values when no data is entered, so we have to
             * start with date processing and filtering out those automatic falsy values.
             * This could be a lot simpler, but my brain is not working right now...
             */
            function buildEvents(x) {
                if (x.BirthDate.split("-")[0] != "0000") {
                    var bY = x.BirthDate.split("-")[0];
                    if (x.BirthDate.split("-")[1] != "00") {
                        var bM = `-${x.BirthDate.split("-")[1]}`;
                        if (x.BirthDate.split("-")[2] != "00") {
                            var bD = `-${x.BirthDate.split("-")[2]}`;
                        }
                    }
                }
                if (bM == undefined && bD == undefined) {
                    var birth = bY;
                } else if (bD == undefined) {
                    var birth = `${bY}${bM}`;
                } else {
                    var birth = `${bY}${bM}${bD}`;
                }

                if (x.DeathDate.split("-")[0] != "0000") {
                    var dY = x.DeathDate.split("-")[0];
                    if (x.DeathDate.split("-")[1] != "00") {
                        var dM = `-${x.DeathDate.split("-")[1]}`;
                        if (x.DeathDate.split("-")[2] != "00") {
                            var dD = `-${x.DeathDate.split("-")[2]}`;
                        }
                    }
                } else {
                    var dY = new Date().toISOString().split("T")[0];
                }
                if (dM == undefined && dD == undefined) {
                    var death = dY;
                } else if (dD == undefined) {
                    var death = `${dY}${dM}`;
                } else {
                    var death = `${dY}${dM}${dD}`;
                }

                // Check to make sure birth and death were not the same day
                // if they are, we need to add a marker instead of timespan
                if (birth == death) {
                    list.push({
                        id: x.Name,
                        content: `${x.ShortName} (${birth.split("-")[0]}-${death.split("-")[0]})

${x.Name}
`,
                        start: birth,
                    });
                } else {
                    if (death == new Date().toISOString().split("T")[0]) {
                        var deathLabel = "Living";
                    } else {
                        var deathLabel = death.split("-")[0];
                    }
                    list.push({
                        id: x.Name,
                        content: `${x.ShortName} (${birth.split("-")[0]}-${deathLabel})

${x.Name}
`,
                        start: birth,
                        end: death,
                    });
                }
            }

            // Setup the Timeline items from our list
            var items = new vis.DataSet(list);
            // Set the general Timeline options
            var options = {
                order: function (a, b) {
                    return b.start - a.start;
                },
                zoomMin: 986399999,
            };
            // Create the Timeline
            var timeline = new vis.Timeline(container, items, options);
        });
    }
}
<commit_msg>Add Error Checking<commit_after>window.TimelineView = class TimelineView extends View {
    meta() {
        return {
            title: "Timeline",
            description:
                "The Timeline view is an interactive visualization chart that allows zooming and panning through a family's chronology.",
            docs: "",
        };
    }

    init(selector, person_id) {
        WikiTreeAPI.postToAPI({
            action: "getPerson",
            key: person_id,
            fields: "Parents,Siblings,Derived.ShortName,FirstName,LastNameAtBirth,LastNameCurrent,Name,BirthDate,DeathDate,Children,Spouses,Father,Mother",
        }).then(function (data) {
            var focus = data[0].person;
            var container = document.getElementById(selector.replace("#", ""));
            var list = [];
            var parentIDs = Object.keys(focus.Parents);
            var siblingIDs = Object.keys(focus.Siblings);
            var spouseIDs = Object.keys(focus.Spouses);
            var childIDs = Object.keys(focus.Children);

            /* Here we will call each person to process.
             * We start with our focus profile, and move on to
             * Parents, Siblings, Spouses, and then Children
             */
            buildEvents(focus);
            for (var i = 0; i < Object.keys(focus.Parents).length; i++) {
                if (focus.Parents[parentIDs[i]].BirthDate) {
                    buildEvents(focus.Parents[parentIDs[i]]);
                }
            }
            for (var i = 0; i < Object.keys(focus.Siblings).length; i++) {
                if (focus.Siblings[siblingIDs[i]].BirthDate) {
                    buildEvents(focus.Siblings[siblingIDs[i]]);
                }
            }
            for (var i = 0; i < Object.keys(focus.Spouses).length; i++) {
                if (focus.Spouses[spouseIDs[i]].BirthDate) {
                    buildEvents(focus.Spouses[spouseIDs[i]]);
                }
            }
            for (var i = 0; i < Object.keys(focus.Children).length; i++) {
                if (focus.Children[childIDs[i]].BirthDate) {
                    buildEvents(focus.Children[childIDs[i]]);
                }
            }

            /* This is global function to build our markers and timespans. For each
             * person passed to it, we evaluate the dates and build our content labels.
             *
             * WikiTree stores falsy values when no data is entered, so we have to
             * start with date processing and filtering out those automatic falsy values.
             * This could be a lot simpler, but my brain is not working right now...
             */
            function buildEvents(x) {
                if (x.BirthDate.split("-")[0] != "0000") {
                    var bY = x.BirthDate.split("-")[0];
                    if (x.BirthDate.split("-")[1] != "00") {
                        var bM = `-${x.BirthDate.split("-")[1]}`;
                        if (x.BirthDate.split("-")[2] != "00") {
                            var bD = `-${x.BirthDate.split("-")[2]}`;
                        }
                    }
                }

                if (bM == undefined && bD == undefined) {
                    var birth = bY;
                } else if (bD == undefined) {
                    var birth = `${bY}${bM}`;
                } else {
                    var birth = `${bY}${bM}${bD}`;
                }

                if (x.DeathDate.split("-")[0] != "0000") {
                    var dY = x.DeathDate.split("-")[0];
                    if (x.DeathDate.split("-")[1] != "00") {
                        var dM = `-${x.DeathDate.split("-")[1]}`;
                        if (x.DeathDate.split("-")[2] != "00") {
                            var dD = `-${x.DeathDate.split("-")[2]}`;
                        }
                    }
                } else {
                    var dY = new Date().toISOString().split("T")[0];
                }

                if (dM == undefined && dD == undefined) {
                    var death = dY;
                } else if (dD == undefined) {
                    var death = `${dY}${dM}`;
                } else {
                    var death = `${dY}${dM}${dD}`;
                }

                // Check to make sure birth and death were not the same day
                // if they are, we need to add a marker instead of timespan
                if (birth == death) {
                    list.push({
                        id: x.Name,
                        content: `${x.ShortName} (${birth.split("-")[0]}-${death.split("-")[0]})

${x.Name}
`,
                        start: birth,
                    });
                } else {
                    if (death == new Date().toISOString().split("T")[0]) {
                        var deathLabel = "Living";
                    } else {
                        var deathLabel = death.split("-")[0];
                    }
                    list.push({
                        id: x.Name,
                        content: `${x.ShortName} (${birth.split("-")[0]}-${deathLabel})

${x.Name}
`,
                        start: birth,
                        end: death,
                    });
                }
            }

            // Setup the Timeline items from our list
            var items = new vis.DataSet(list);
            // Set the general Timeline options
            var options = {
                order: function (a, b) {
                    return b.start - a.start;
                },
                zoomMin: 986399999,
            };
            // Create the Timeline
            var timeline = new vis.Timeline(container, items, options);
        });
    }
};
<|endoftext|>


<commit_before>"use strict";

var accumulate = require("../accumulate")
var reducible = require("../reducible")
var end = require("../end")
var isError = require("../is-error")

var write = (function() {
  if (typeof(process) !== "undefined" &&
      typeof(process.stdout) !== "undefined" &&
      typeof(process.stdout.write) === "function")
    return process.stdout.write.bind(process.stdout)
  else
    return console.log.bind(console)
})()

function print(source) {
  var open = false
  accumulate(source, function printAccumulate(value) {
    if (!open) write("< ")
    open = true

    if (value === end) write(">\n")
    else if (isError(value)) write("\u26A1 " + value + " >\n")
    else write(JSON.stringify(value, 2, 2) + " ")
  })
}

module.exports = print
<commit_msg>Improve print to handle circular references properly via `util.inspect` and `console.log` for browsers.<commit_after>"use strict";

var accumulate = require("../accumulate")
var reducible = require("../reducible")
var end = require("../end")
var isError = require("../is-error")

var PREFIX = "\u200B"
var OPEN = PREFIX + "< "
var CLOSE = PREFIX + ">\n"
var ERROR = PREFIX + "\u26A1 "
var DELIMITER = PREFIX + " "

var SPECIALS = [ OPEN, CLOSE, ERROR, DELIMITER ]

var write = (function() {
  if (typeof(process) !== "undefined" &&
      typeof(process.stdout) !== "undefined" &&
      typeof(process.stdout.write) === "function") {
    var inspect = require("util").inspect
    var slicer = Array.prototype.slice
    return function write() {
      var message = slicer.call(arguments).map(function($) {
        return SPECIALS.indexOf($) >= 0 ? $ : inspect($)
      }).join("")
      process.stdout.write(message)
    }
  } else {
    return console.log.bind(console)
  }
})()

function print(source) {
  var open = false
  accumulate(source, function printAccumulate(value) {
    if (!open) write(OPEN)
    open = true

    if (value === end) write(CLOSE)
    else if (isError(value)) write(ERROR, value, DELIMITER, CLOSE)
    else write(value, DELIMITER)
  })
}

module.exports = print
<|endoftext|>


<commit_before>
/**
 * shows a dialog to get the table exported
 * new ExportTableDialog({
 *  table: table_model
 * })
 *
 */
cdb.admin.ExportTableDialog = cdb.admin.BaseDialog.extend({

  // _CSV_FILTER: "SELECT *, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_X(the_geom) ELSE ST_X(ST_PointOnSurface(the_geom)) END as longitude, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_Y(the_geom) ELSE ST_Y(ST_PointOnSurface(the_geom)) END as latitude, ST_AsGeoJSON(the_geom,5) as geojson FROM (%%sql%%) as subq",
  _CSV_FILTER: "SELECT *, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_X(the_geom) WHEN ST_IsEmpty(ST_PointOnSurface(the_geom)) THEN null ELSE ST_X(ST_PointOnSurface(the_geom)) END as longitude, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_Y(the_geom) WHEN ST_IsEmpty(ST_PointOnSurface(the_geom)) THEN null ELSE ST_Y(ST_PointOnSurface(the_geom)) END as latitude, ST_AsGeoJSON(the_geom,5) as geojson FROM (%%sql%%) as subq ",
  _MAX_SQL_GET_LENGTH: 1000,
  events: cdb.core.View.extendEvents({
    'click .export:not(.disabled)': 'export'
  }),

  /**
   * Allowed formats on the exporter
   * @type {Array}
   */
  formats: [
    {format: 'csv', fetcher: 'fetchCSV', geomRequired: false},
    {format: 'shp', fetcher: 'fetch', geomRequired: true},
    {format: 'kml', fetcher: 'fetch', geomRequired: true},
    {format: 'svg', fetcher: 'fetchSVG', geomRequired: true},
    {format: 'geojson', fetcher: 'fetch', geomRequired: true}
  ],

  dataGeoreferenced: null,

  initialize: function() {
    _.extend(this.options, {
      title: "Select your file type",
      description: '',
      template_name: 'common/views/dialog_base',
      clean_on_hide: true,
      ok_button_classes: "button grey",
      ok_title: "",
      modal_type: "",
      width: 510,
      modal_class: 'export_table_dialog',
      include_footer: false,
      table_id: this.model.id
    });
    this.constructor.__super__.initialize.apply(this);
    _.bindAll(this, 'export');
    this.baseUrl = this.options.config.sql_api_protocol + '://' + this.options.config.sql_api_domain
      + ':'
      + this.options.config.sql_api_port
      + '/api/v1/sql';
    this.checkGeoreference();
  },

  checkGeoreference: function() {
    var self = this;
    self.dataGeoreferenced = null;

    this.model.fetchGeoreferenceQueryStatus().done(function(res) {
      self.dataGeoreferenced = res;
      self.refresh();
    }).fail(function(res) {
      // handle error
    })

  },

  /**
   * search a format based on its name in the format array
   * @param  {string} format Format name
   * @return {Object}
   */
  getFormat: function(format) {
    for(var n in this.formats) {
      if(this.formats[n].format === format) {
        return this.formats[n]
      }
    }
  },

  /**
   * Answer to button event and lauchn the export method associated to that format
   * @param  {Event} ev
   */
  export: function(ev) {
    this.killEvent(ev);
    var $button = $(ev.currentTarget);
    var formatName = $button.data('format');
    var format = this.getFormat(formatName);
    this[format.fetcher](formatName);
  },

  /**
   * Create a dictionary with the options shared between all the methods
   * @return {Object}
   */
  getBaseOptions: function() {
    var options = {}
    options.filename = this.model.get('name');
    if(this.model.sqlView) {
      options.filename = 'cartodb_query';
    }

    if(this.options.user_data) {
      options.api_key = this.options.user_data.api_key;
    }
    return options;
  },

  /**
   * Returns the base sql to retrieve the data
   * @return {string}
   */
  getPlainSql: function() {
    if(this.options.sql) {
      sql = this.options.sql;
    } else {
      if(this.model.sqlView) {
        sql = this.model.sqlView.getSQL();
      } else {
        sql = "select * from " + this.model.get('name')
      }
    }
    return sql;
  },

  /**
   * Returns a specific sql filtered by the_geom, used on CSV exports
   * @return {string}
   */
  getGeomFilteredSql: function() {
    var sql = this.getPlainSql();
    var currentSchema = this.model.get('schema');
    // if we have "the_geom" in our current schema, we apply a custom sql
    if(this.dataGeoreferenced) {
      return this._CSV_FILTER.replace(/%%sql%%/g, sql);
    } // if not, we apply regular sql
    return sql;

  },

  /**
   * Populates the hidden form with the format related values and submit them to get the file
   * @param  {Object} options Base options
   * @param  {String} sql Sql of the document to be retrieved
   */
  _fetch: function(options, sql) {
    var self = this;
    this.$('.format').val(options.format);
    this.$('.q').val(sql);
    this.$('.filename').val(options.filename);
    this.$('.api_key').val(options.api_key);
    this.$('.generating').fadeIn();
    this.$('.geospatial').fadeOut();
    // check if the sql is big or not, and send the request as a verb or other. This is a HACK.
    if(sql.length < this._MAX_SQL_GET_LENGTH) {
      var location = this.$('form').attr('action') + '?' + this.$('form').serialize()
      var fetcher = $('<iframe id="fetchHack" src="'+location+'" onload="fetcherSuccess();"/>');
      // I'll burn in hell for this. I'm worst than hitler.
      window.fetcherSuccess = function() {
        this.exportDialog.hide();
        delete window.exportDialog ;
        setTimeout($('iframe#fetchHack').remove,25);
      };
      window.exportDialog = this;

      fetcher.css('display', 'none');
      fetcher.appendTo($('body'))
    } else {
      // I can't find a way of making the iframe trigger load event when its get a form posted,
      // so we need to leave like it was until
      this.submit();
    }

    this.$('.db').attr('disabled', 'disabled');
    this.$('.skipfields').attr('disabled', 'disabled');
    if(this.options.autoClose) {
      this.hide();
      this.trigger('generating', this.$('.generating').html());
    }

  },

  _fetchGET: function(options, sql) {

  },

  /**
   * Submits the form. This method is separated to ease the testing
   */
  submit: function() {
    this.$('form').submit();
  },

  /**
   * Base fetch, for the formats that don't require special threatment
   * @param  {String} formatName
   */
  fetch: function(formatName) {
    var options = this.getBaseOptions();
    options.format = formatName;
    var sql = this.getPlainSql();
    this._fetch(options, sql);
  },
  /**
   * Gets the options needed for csv format and fetch the document
   * @param  {String} formatName
   */
  fetchCSV: function() {
    var options = this.getBaseOptions();
    options.format = 'csv';
    var sql = this.getGeomFilteredSql();
    this.$('.skipfields').removeAttr('disabled');
    this._fetch(options, sql);
  },
  /**
   * Gets the options needed for svg format and fetch the document
   * @param  {String} formatName
   */
  fetchSVG: function(){
    this.$('.db').removeAttr('disabled');
    this.fetch('svg');
  },
  /**
   * Returns the html populated with current data
   * @return {String}
   */
  render_content: function() {
    return this.getTemplate('common/views/export_table_dialog')({
      formats:this.formats,
      url: this.baseUrl,
      isGeoreferenced: this.dataGeoreferenced
    });
  },

  refresh: function() {
    this.$('.content').html(this.render_content());
  }

});
<commit_msg>testability improved<commit_after>
/**
 * shows a dialog to get the table exported
 * new ExportTableDialog({
 *  table: table_model
 * })
 *
 */
cdb.admin.ExportTableDialog = cdb.admin.BaseDialog.extend({

  // _CSV_FILTER: "SELECT *, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_X(the_geom) ELSE ST_X(ST_PointOnSurface(the_geom)) END as longitude, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_Y(the_geom) ELSE ST_Y(ST_PointOnSurface(the_geom)) END as latitude, ST_AsGeoJSON(the_geom,5) as geojson FROM (%%sql%%) as subq",
  _CSV_FILTER: "SELECT *, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_X(the_geom) WHEN ST_IsEmpty(ST_PointOnSurface(the_geom)) THEN null ELSE ST_X(ST_PointOnSurface(the_geom)) END as longitude, CASE WHEN GeometryType(the_geom)='POINT' THEN ST_Y(the_geom) WHEN ST_IsEmpty(ST_PointOnSurface(the_geom)) THEN null ELSE ST_Y(ST_PointOnSurface(the_geom)) END as latitude, ST_AsGeoJSON(the_geom,5) as geojson FROM (%%sql%%) as subq ",
  _MAX_SQL_GET_LENGTH: 1000,
  events: cdb.core.View.extendEvents({
    'click .export:not(.disabled)': 'export'
  }),

  /**
   * Allowed formats on the exporter
   * @type {Array}
   */
  formats: [
    {format: 'csv', fetcher: 'fetchCSV', geomRequired: false},
    {format: 'shp', fetcher: 'fetch', geomRequired: true},
    {format: 'kml', fetcher: 'fetch', geomRequired: true},
    {format: 'svg', fetcher: 'fetchSVG', geomRequired: true},
    {format: 'geojson', fetcher: 'fetch', geomRequired: true}
  ],

  dataGeoreferenced: null,

  initialize: function() {
    _.extend(this.options, {
      title: "Select your file type",
      description: '',
      template_name: 'common/views/dialog_base',
      clean_on_hide: true,
      ok_button_classes: "button grey",
      ok_title: "",
      modal_type: "",
      width: 510,
      modal_class: 'export_table_dialog',
      include_footer: false,
      table_id: this.model.id
    });
    this.constructor.__super__.initialize.apply(this);
    _.bindAll(this, 'export');
    this.baseUrl = this.options.config.sql_api_protocol + '://' + this.options.config.sql_api_domain
      + ':'
      + this.options.config.sql_api_port
      + '/api/v1/sql';
    this.checkGeoreference();
  },

  checkGeoreference: function() {
    var self = this;
    self.dataGeoreferenced = null;

    this.model.fetchGeoreferenceQueryStatus().done(function(res) {
      self.dataGeoreferenced = res;
      self.refresh();
    }).fail(function(res) {
      // handle error
    })

  },

  /**
   * search a format based on its name in the format array
   * @param  {string} format Format name
   * @return {Object}
   */
  getFormat: function(format) {
    for(var n in this.formats) {
      if(this.formats[n].format === format) {
        return this.formats[n]
      }
    }
  },

  /**
   * Answer to button event and lauchn the export method associated to that format
   * @param  {Event} ev
   */
  export: function(ev) {
    this.killEvent(ev);
    var $button = $(ev.currentTarget);
    var formatName = $button.data('format');
    var format = this.getFormat(formatName);
    this[format.fetcher](formatName);
  },

  /**
   * Create a dictionary with the options shared between all the methods
   * @return {Object}
   */
  getBaseOptions: function() {
    var options = {}
    options.filename = this.model.get('name');
    if(this.model.sqlView) {
      options.filename = 'cartodb_query';
    }

    if(this.options.user_data) {
      options.api_key = this.options.user_data.api_key;
    }
    return options;
  },

  /**
   * Returns the base sql to retrieve the data
   * @return {string}
   */
  getPlainSql: function() {
    if(this.options.sql) {
      sql = this.options.sql;
    } else {
      if(this.model.sqlView) {
        sql = this.model.sqlView.getSQL();
      } else {
        sql = "select * from " + this.model.get('name')
      }
    }
    return sql;
  },

  /**
   * Returns a specific sql filtered by the_geom, used on CSV exports
   * @return {string}
   */
  getGeomFilteredSql: function() {
    var sql = this.getPlainSql();
    var currentSchema = this.model.get('schema');
    // if we have "the_geom" in our current schema, we apply a custom sql
    if(this.dataGeoreferenced) {
      return this._CSV_FILTER.replace(/%%sql%%/g, sql);
    } // if not, we apply regular sql
    return sql;

  },

  /**
   * Populates the hidden form with the format related values and submit them to get the file
   * @param  {Object} options Base options
   * @param  {String} sql Sql of the document to be retrieved
   */
  _fetch: function(options, sql) {
    var self = this;
    this.$('.format').val(options.format);
    this.$('.q').val(sql);
    this.$('.filename').val(options.filename);
    this.$('.api_key').val(options.api_key);
    this.$('.generating').fadeIn();
    this.$('.geospatial').fadeOut();
    // check if the sql is big or not, and send the request as a verb or other. This is a HACK.
    if(sql.length < this._MAX_SQL_GET_LENGTH) {
      var location = this.$('form').attr('action') + '?' + this.$('form').serialize()
      this._fetchGET(location);
    } else {
      // I can't find a way of making the iframe trigger load event when its get a form posted,
      // so we need to leave like it was until
      this.submit();
    }

    this.$('.db').attr('disabled', 'disabled');
    this.$('.skipfields').attr('disabled', 'disabled');
    if(this.options.autoClose) {
      this.hide();
      this.trigger('generating', this.$('.generating').html());
    }

  },

  _fetchGET: function(location) {
      var fetcher = $('<iframe id="fetchHack" src="'+location+'" onload="fetcherSuccess();"/>');
      // I'll burn in hell for this. I'm worst than hitler.
      window.fetcherSuccess = function() {
        this.exportDialog.hide();
        delete window.exportDialog ;
        setTimeout($('iframe#fetchHack').remove,25);
      };
      window.exportDialog = this;

      fetcher.css('display', 'none');
      fetcher.appendTo($('body'))
  },

  /**
   * Submits the form. This method is separated to ease the testing
   */
  submit: function() {
    this.$('form').submit();
  },

  /**
   * Base fetch, for the formats that don't require special threatment
   * @param  {String} formatName
   */
  fetch: function(formatName) {
    var options = this.getBaseOptions();
    options.format = formatName;
    var sql = this.getPlainSql();
    this._fetch(options, sql);
  },
  /**
   * Gets the options needed for csv format and fetch the document
   * @param  {String} formatName
   */
  fetchCSV: function() {
    var options = this.getBaseOptions();
    options.format = 'csv';
    var sql = this.getGeomFilteredSql();
    this.$('.skipfields').removeAttr('disabled');
    this._fetch(options, sql);
  },
  /**
   * Gets the options needed for svg format and fetch the document
   * @param  {String} formatName
   */
  fetchSVG: function(){
    this.$('.db').removeAttr('disabled');
    this.fetch('svg');
  },
  /**
   * Returns the html populated with current data
   * @return {String}
   */
  render_content: function() {
    return this.getTemplate('common/views/export_table_dialog')({
      formats:this.formats,
      url: this.baseUrl,
      isGeoreferenced: this.dataGeoreferenced
    });
  },

  refresh: function() {
    this.$('.content').html(this.render_content());
  }

});
<|endoftext|>


<commit_before>
var availableId = 0;
var lazyValidation = false;

	$('.js-load').on('submit', '.add-task-block form', function(e) {
		e.preventDefault();

		var currentSubTasks = [];
		var currentNames = [];
		var currentDate = new Date().getTime() / 1000;
		var descriptionText = $(this).find('.task-description-input').val();
		var selectedNames = $(this).find($('.js-names-input')[1]).val();
		var selectedProject = $(this).find('.js-project-input').val();

		$(this).find('.subtask-list li input').each(function(){
			var subTaskObj = {"task":$(this).val()};
			if ( $(this).val() != '' ) {
				currentSubTasks.push(subTaskObj);
			}
		});

		// console.log($(this).find($('div.js-names-input')[1]).val());

		if ( selectedNames != null ) {
			$.each(selectedNames, function( index, value ) {
			   var namesObj = {user:value};
			   currentNames.push(namesObj);
			});
		}

		var newTask = {
			id: availableId,
	        done: false,
	        project: selectedProject,
	        date: currentDate,
	        subtasks: currentSubTasks,
	        team: selectedNames,
	        content: descriptionText
		}

		console.log(currentSubTasks);
		console.log(descriptionText);
		console.log(selectedProject);
		console.log(currentNames);

		if ( descriptionText !== '' && selectedNames !== [] && selectedProject !== '') {
			lazyValidation = true;
		} else {
			lazyValidation = false;
			$(this).parent().addClass('lazy-val-error');
		}

		if ( lazyValidation == true ) {
			console.log(newTask);
			pushTask(newTask);
			$(this).parent().removeClass('lazy-val-error');
		} else {
			console.log('VAL FAIL');
		}

	});

	$('.js-add-project').on('click', function(e){
		e.preventDefault();

		$('.new-project-overlay').addClass('project-added');

		var projectTitle = $('.project-title-input').val();

		var newProject = {};
		newProject = {text: projectTitle,value: projectTitle};
		theProjects.push(newProject);

		// animateLoad("personal.html",'none');
		// This would wait until ajax complete (adding in the new project and loading the page).
		setTimeout(function(){
			$('.new-project-overlay').removeClass('visible');
			$('.new-project-overlay').removeClass('project-added');
			$('.content-area').removeClass('overlay-on');
		},3000);

	});

	// This is the old implimentation of the subtasks code, need to fix how new projects are added and then this can be removed.
	$(document).on('keydown', '.add-task-block .subtask-input', function(e){
		var code = e.keyCode || e.which;
		if ( code == 13 ) {
			e.preventDefault();
			$(this).parents('.subtask-list').append('
<input type="text" class="subtask-input" placeholder="Add Subtask">
');
			console.log($(this).parent().last());
			$(this).parents('.subtask-list').children().last().children('input').focus();
		} else if ( code == 8  && !$(this).val() && $(this).parents('.subtask-list').children().length > 1) {
			e.preventDefault();
			$(this).parents('.subtask-list').children().last().prev("li").children('input').focus();
			$(this).parent().remove();
		}
	});

$(document).ready(function(){

	// // On load lets grab the "Overview" task list.
	animateLoad();

	// Initialise autogrow on the new project modal description input.
	autosize($('.js-task-description-input'));
	// Initialise the select area on the new project modal.

	// Make this work on the add-project input as well.
	$('.add-task-block .names-input').selectize({
		options: theData.users // use theTeam data source
	});

	// Toggle for the search overlay.

	$('.search-icon').on('click',function(){
		$('.search-icon').toggleClass('expanded');
		$('.search-overlay').toggleClass('visible');
		$('.search input[type="text"]').focus();

		if ( !$('.content-area').hasClass('.overlay-on') ) {
			$('.content-area').addClass('overlay-on');
		} else {
			setTimeout(function(){
				$('.content-area').removeClass('overlay-on');
			},500)
		}
	});

	// Toggle for the new project overlay.

	$('.add-project-link, .close-modal').on('click',function(e){
		e.preventDefault();
		$('.content-area').toggleClass('overlay-on');
		$('.new-project-overlay').toggleClass('visible');
	});

	// Close modal via escape key if its open.

	$(document).on('keydown', function(e){
		if (e.keyCode == 27 ) {
			if ($('.new-project-overlay').hasClass('visible')) {
				$('.close-modal').click();
			}
		}
	});

	// Basic filtering of each list to only show your personal tasks, this persists across projects.
	// This can be done with vue.js if we want to or keep it css based.

	$('.personal-filter').on('click', function(){
		$('.js-load').toggleClass('personal');
	});

	$('.global-filter').on('click', function(){
		$('.js-load').removeClass('personal');
	});

	// Temp code to animate out the login sections of the login page, this needs more attention as it was mainly for demonstration purposes.
	$('.login-area input').on('keydown', function(e){

		var code = e.keyCode || e.which;
		if ( code == 13 ) {
			$('.mr-planet-svg-wrapper').toggleClass('away');
			$('.login-area input').addClass('fade-out-down');
			$('.login-area h2').addClass('fade-out-down');

			setTimeout(function(){
				$('body').addClass('fade-out');
			},2000);

			setTimeout(function(){
				window.location.href = 'http://' + window.location.host;
			},2350);
		}
	});

	// Animate the basic tasks to full height on click revealing additional information.

	$('.js-load').on('click', '.basic-task', function() {

		// Old easing -> cubic-bezier(0.215, 0.610, 0.355, 1.000)
		// $(this).find('.task-description').cssAnimateAuto('height 0.4s cubic-bezier(0.215, 0.610, 0.355, 1.000)');
		$(this).cssAnimateAuto('height 0.4s cubic-bezier(0.215, 0.610, 0.355, 1.000)');

		// Remove the is-opened class applied by cssAnimateAuto slightly early to fix some overflow issues.
		var descriptionWrapper = $(this).find('.task-description-wrapper');

		var maxHeight = $(this).find('.task-description').innerHeight();
		descriptionWrapper.css('maxHeight',maxHeight);

		descriptionWrapper.removeClass('hidden-text');
		descriptionWrapper.addClass('animated-height');
		setTimeout(function(){
			descriptionWrapper.removeClass('animated-height');
		},400);

		if ($(this).hasClass('is-opened')) {
			descriptionWrapper.addClass('hidden-text');
			descriptionWrapper.addClass('animated-height');
			setTimeout(function(){
				descriptionWrapper.removeClass('animated-height');
			},400);

			$(this).removeClass('is-opened');
		}

		// Check if the task has any subtasks, if so add a list icon on close.

		hasList($(this));
	});

	$('.task-description').on("input", function(){
		var maxHeight = $(this).innerHeight();
		$(this).parent().css('maxHeight',maxHeight);
	});

	// Prevent the task list items from closing when you click on the form inputs.

	$('.js-load').on('click', '.js-add-task, .toggle, .subtask-input, .selectize-input, .is-opened .task-description, .is-opened .task-description-input', function(e) {
		e.stopPropagation();
	});

	// Slide out the mobile menu.

	 $('.side-nav').perfectScrollbar();

});

var hasList = function(item) {
	if ( item.find('.subtask input').val() != "" && !item.hasClass('add-task-block')) {
		item.addClass('list');
	} else {
		item.removeClass('list');
	}
}

var animateLoad = function(ajaxUrl,loader) {
	// Hide the current content (fade-out-down)
	$('.js-load').addClass('content-hidden');

	setTimeout(function(){
		$('.content-area').scrollTop(0);
	},400);

	// Check if we want to show the loader.
	if ( loader != 'none') {
		$('.js-load').append('
<svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="path" fill="none" stroke-width="6" stroke="#222A33" stroke-linecap="round" cx="33" cy="33" r="30"></circle></svg>
');
	}

	// This timeout is just to fake a long ajax load time during testing.
	setTimeout(function(){
		$.ajax({
		  url: ajaxUrl,
		  cache: false
		})
		  .done(function( html ) {

		    $('.js-load .basic-task').each(function(){
		    	hasList($(this));
		    	$(this).find('.task-description-input').autoGrow();
		    	// Swap out autogrow with this script - http://www.jacklmoore.com/autosize/
		    	autosize($(this).find('.task-description-input'));
		    });

		    // $(".js-load .task-names select.js-selector#test").each(function(e){
		    // 	var test = $(this);

		    // 	// $(test).each(function(e){
		    // 	// 	console.log($(this));
		    // 	// });
		    // 	console.log( test  + ' ----> ' + $(this).data('theusers'));
		    // 	$(this).selectize({
		    // 		options: theData.users,
		    // 		onChange: function(value) {
		    //            $(this).data('theusers',value);
		    //            console.log($(this).data('theusers'));
			   //      }
		    // 	});
		    // 	var selectize = $(this)[0].selectize;
		    // 	// selectize.setValue('');
		    // });

		  	// http://vuejs.org/guide/transitions.html
		  	// Take a look at transitions and intialise the plugins on each task seperately ?

		    $(".js-load .task-project .js-selector").each(function(){
		    	$(this).selectize({
		    		options: theProjects
		    	});
		    });

		    $('.loader').remove();
		    // Slight delay before removing content-hidden class to prevent popin when plugins are activated.
		    setTimeout(function(){
		    	$(".js-load").removeClass('content-hidden');
		    },50);
		  });
	},2000);
}

<commit_msg>Update the data source for new task project selector.<commit_after>
var availableId = 0;
var lazyValidation = false;

	$('.js-load').on('submit', '.add-task-block form', function(e) {
		e.preventDefault();

		var currentSubTasks = [];
		var currentNames = [];
		var currentDate = new Date().getTime() / 1000;
		var descriptionText = $(this).find('.task-description-input').val();
		var selectedNames = $(this).find($('.js-names-input')[1]).val();
		var selectedProject = $(this).find('.js-project-input').val();

		$(this).find('.subtask-list li input').each(function(){
			var subTaskObj = {"task":$(this).val()};
			if ( $(this).val() != '' ) {
				currentSubTasks.push(subTaskObj);
			}
		});

		// console.log($(this).find($('div.js-names-input')[1]).val());

		console.log(selectedNames);

		if ( selectedNames != [] ) {
			$.each(selectedNames, function( index, value ) {
			   var namesObj = value;
			   currentNames.push(namesObj);
			});
		}

		var newTask = {
			id: availableId,
	        done: false,
	        project: selectedProject,
	        date: currentDate,
	        subtasks: currentSubTasks,
	        team: selectedNames,
	        content: descriptionText
		}

		console.log(currentSubTasks);
		console.log(descriptionText);
		console.log(selectedProject);
		console.log(currentNames);

		if ( descriptionText !== '' && selectedNames !== [] && selectedProject !== '') {
			lazyValidation = true;
		} else {
			lazyValidation = false;
			$(this).parent().addClass('lazy-val-error');
		}

		if ( lazyValidation == true ) {
			console.log(newTask);
			pushTask(newTask);
			$(this).parent().removeClass('lazy-val-error');
		} else {
			console.log('VAL FAIL');
		}

	});

	$('.js-add-project').on('click', function(e){
		e.preventDefault();

		$('.new-project-overlay').addClass('project-added');

		var projectTitle = $('.project-title-input').val();

		var newProject = {};
		newProject = {text: projectTitle,value: projectTitle};
		theProjects.push(newProject);

		// animateLoad("personal.html",'none');
		// This would wait until ajax complete (adding in the new project and loading the page).
		setTimeout(function(){
			$('.new-project-overlay').removeClass('visible');
			$('.new-project-overlay').removeClass('project-added');
			$('.content-area').removeClass('overlay-on');
		},3000);

	});

	// This is the old implimentation of the subtasks code, need to fix how new projects are added and then this can be removed.
	$(document).on('keydown', '.add-task-block .subtask-input', function(e){
		var code = e.keyCode || e.which;
		if ( code == 13 ) {
			e.preventDefault();
			$(this).parents('.subtask-list').append('
<input type="text" class="subtask-input" placeholder="Add Subtask">
');
			console.log($(this).parent().last());
			$(this).parents('.subtask-list').children().last().children('input').focus();
		} else if ( code == 8  && !$(this).val() && $(this).parents('.subtask-list').children().length > 1) {
			e.preventDefault();
			$(this).parents('.subtask-list').children().last().prev("li").children('input').focus();
			$(this).parent().remove();
		}
	});

$(document).ready(function(){

	// // On load lets grab the "Overview" task list.
	animateLoad();

	// Initialise autogrow on the new project modal description input.
	autosize($('.js-task-description-input'));
	// Initialise the select area on the new project modal.

	// Make this work on the add-project input as well.
	$('.add-task-block .names-input').selectize({
		options: theData.users // use theTeam data source
	});

	// Toggle for the search overlay.

	$('.search-icon').on('click',function(){
		$('.search-icon').toggleClass('expanded');
		$('.search-overlay').toggleClass('visible');
		$('.search input[type="text"]').focus();

		if ( !$('.content-area').hasClass('.overlay-on') ) {
			$('.content-area').addClass('overlay-on');
		} else {
			setTimeout(function(){
				$('.content-area').removeClass('overlay-on');
			},500)
		}
	});

	// Toggle for the new project overlay.

	$('.add-project-link, .close-modal').on('click',function(e){
		e.preventDefault();
		$('.content-area').toggleClass('overlay-on');
		$('.new-project-overlay').toggleClass('visible');
	});

	// Close modal via escape key if its open.

	$(document).on('keydown', function(e){
		if (e.keyCode == 27 ) {
			if ($('.new-project-overlay').hasClass('visible')) {
				$('.close-modal').click();
			}
		}
	});

	// Basic filtering of each list to only show your personal tasks, this persists across projects.
	// This can be done with vue.js if we want to or keep it css based.

	$('.personal-filter').on('click', function(){
		$('.js-load').toggleClass('personal');
	});

	$('.global-filter').on('click', function(){
		$('.js-load').removeClass('personal');
	});

	// Temp code to animate out the login sections of the login page, this needs more attention as it was mainly for demonstration purposes.
	$('.login-area input').on('keydown', function(e){

		var code = e.keyCode || e.which;
		if ( code == 13 ) {
			$('.mr-planet-svg-wrapper').toggleClass('away');
			$('.login-area input').addClass('fade-out-down');
			$('.login-area h2').addClass('fade-out-down');

			setTimeout(function(){
				$('body').addClass('fade-out');
			},2000);

			setTimeout(function(){
				window.location.href = 'http://' + window.location.host;
			},2350);
		}
	});

	// Animate the basic tasks to full height on click revealing additional information.

	$('.js-load').on('click', '.basic-task', function() {

		// Old easing -> cubic-bezier(0.215, 0.610, 0.355, 1.000)
		// $(this).find('.task-description').cssAnimateAuto('height 0.4s cubic-bezier(0.215, 0.610, 0.355, 1.000)');
		$(this).cssAnimateAuto('height 0.4s cubic-bezier(0.215, 0.610, 0.355, 1.000)');

		// Remove the is-opened class applied by cssAnimateAuto slightly early to fix some overflow issues.
		var descriptionWrapper = $(this).find('.task-description-wrapper');

		var maxHeight = $(this).find('.task-description').innerHeight();
		descriptionWrapper.css('maxHeight',maxHeight);

		descriptionWrapper.removeClass('hidden-text');
		descriptionWrapper.addClass('animated-height');
		setTimeout(function(){
			descriptionWrapper.removeClass('animated-height');
		},400);

		if ($(this).hasClass('is-opened')) {
			descriptionWrapper.addClass('hidden-text');
			descriptionWrapper.addClass('animated-height');
			setTimeout(function(){
				descriptionWrapper.removeClass('animated-height');
			},400);

			$(this).removeClass('is-opened');
		}

		// Check if the task has any subtasks, if so add a list icon on close.

		hasList($(this));
	});

	$('.task-description').on("input", function(){
		var maxHeight = $(this).innerHeight();
		$(this).parent().css('maxHeight',maxHeight);
	});

	// Prevent the task list items from closing when you click on the form inputs.

	$('.js-load').on('click', '.js-add-task, .toggle, .subtask-input, .selectize-input, .is-opened .task-description, .is-opened .task-description-input', function(e) {
		e.stopPropagation();
	});

	 $('.side-nav').perfectScrollbar();

});

var hasList = function(item) {
	if ( item.find('.subtask input').val() != "" && !item.hasClass('add-task-block')) {
		item.addClass('list');
	} else {
		item.removeClass('list');
	}
}

var animateLoad = function(ajaxUrl,loader) {
	// Hide the current content (fade-out-down)
	$('.js-load').addClass('content-hidden');

	setTimeout(function(){
		$('.content-area').scrollTop(0);
	},400);

	// Check if we want to show the loader.
	if ( loader != 'none') {
		$('.js-load').append('
<svg class="spinner" width="65px" height="65px" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="path" fill="none" stroke-width="6" stroke="#222A33" stroke-linecap="round" cx="33" cy="33" r="30"></circle></svg>
');
	}

	// This timeout is just to fake a long ajax load time during testing.
	setTimeout(function(){
		$.ajax({
		  url: ajaxUrl,
		  cache: false
		})
		  .done(function( html ) {

		    $('.js-load .basic-task').each(function(){
		    	hasList($(this));
		    	// Swap out autogrow with this script - http://www.jacklmoore.com/autosize/
		    	autosize($(this).find('.task-description-input'));
		    });

		    // $(".js-load .task-names select.js-selector#test").each(function(e){
		    // 	var test = $(this);

		    // 	// $(test).each(function(e){
		    // 	// 	console.log($(this));
		    // 	// });
		    // 	console.log( test  + ' ----> ' + $(this).data('theusers'));
		    // 	$(this).selectize({
		    // 		options: theData.users,
		    // 		onChange: function(value) {
		    //            $(this).data('theusers',value);
		    //            console.log($(this).data('theusers'));
			   //      }
		    // 	});
		    // 	var selectize = $(this)[0].selectize;
		    // 	// selectize.setValue('');
		    // });

		  	// http://vuejs.org/guide/transitions.html
		  	// Take a look at transitions and intialise the plugins on each task seperately ?

		    $(".js-load .task-project .js-selector").each(function(){
		    	$(this).selectize({
		    		options: theData.projects
		    	});
		    });

		    $('.loader').remove();
		    // Slight delay before removing content-hidden class to prevent popin when plugins are activated.
		    setTimeout(function(){
		    	$(".js-load").removeClass('content-hidden');
		    },50);
		  });
	},2000);
}

<|endoftext|>


<commit_before>const qs = require('qs')
const Mock = require('mockjs')

const admin = Mock.mock({
  'data|100': [
    {
      'id|+1': 1,
      name: '@cname',
      phone: /^1[34578]\d{9}$/,
      'age|11-99': 1,
      address: '@province()',
      isMale: '@boolean',
      email: '@email',
      status: '@boolean',
      'roleId|1': [1, 2, 3],
      'roleName|1': function() {
        return ["管理员", "教师", "学生"][this.roleId - 1]
      },
      createTime: '@datetime',
      avatar: function () {
        return Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', this.name.substr(0, 1))
      }
    }
  ],
  page: {
    total: 100,
    current: 1
  }
})

let AdminListData = global[admin]

module.exports = {

  'GET /api/adminItem' (req, res) {
    const getItem = qs.parse(req.query)
    const adminItem = AdminListData.data.find(function (item) {
      return item.id == +getItem.id
    })
    res.json({success: true, data: adminItem})
  },

  'GET /api/admin' (req, res) {
    const page = qs.parse(req.query)
    const pageSize = page.pageSize || 10
    const currentPage = page.current || 1

    let data
    let newPage

    let newData = AdminListData.data.concat()

    if (page.field) {
      const d = newData.filter(function (item) {
        return item[page.field].indexOf(decodeURI(page.keyword)) > -1
      })

      data = d.slice((currentPage - 1) * pageSize, currentPage * pageSize)

      newPage = {
        current: currentPage * 1,
        total: d.length
      }
    } else {
      data = AdminListData.data.slice((currentPage - 1) * pageSize, currentPage * pageSize)
      AdminListData.page.current = currentPage * 1
      newPage = AdminListData.page
    }
    res.json({success: true, data, page: {...newPage, pageSize: Number(pageSize)}})
  },

  'POST /api/admin' (req, res) {
    const newData = req.body
    newData.createTime = Mock.mock('@now')
    newData.avatar = Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', newData.name.substr(0, 1))

    const roleListData = global['AccountRoleList'].data
    const roleList = roleListData.map(item => {
      return item.name
    })
    newData.roleName = roleList[newData.roleId - 1]

    newData.id = AdminListData.data.length + 1
    AdminListData.data.unshift(newData)

    AdminListData.page.total = AdminListData.data.length
    AdminListData.page.current = 1

    global[dataKey] = AdminListData

    res.json({success: true, data: AdminListData.data, page: AdminListData.page})
  },

  'DELETE /api/admin' (req, res) {
    const deleteItem = req.body
    AdminListData.data = AdminListData.data.filter(function (item) {
      if (item.id === deleteItem.id) {
        return false
      }
      return true
    })

    AdminListData.page.total = AdminListData.data.length

    global[dataKey] = AdminListData

    res.json({success: true, data: AdminListData.data, page: AdminListData.page})
  },

  'PUT /api/admin' (req, res) {
    const editItem = req.body

    const roleListData = global['AccountRoleList'].data
    const roleList = roleListData.map(item => {
      return item.name
    })

    editItem.createTime = Mock.mock('@now')
    editItem.avatar = Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', editItem.name.substr(0, 1))
    editItem.roleName = roleList[editItem.roleId - 1]

    AdminListData.data = AdminListData.data.map(function (item) {
      if (item.id === editItem.id) {
        return editItem
      }
      return item
    })

    global[dataKey] = AdminListData
    res.json({success: true, data: AdminListData.data, page: AdminListData.page})
  }

}
<commit_msg>fix mock data<commit_after>const qs = require('qs')
const Mock = require('mockjs')

const admin = Mock.mock({
  'data|100': [
    {
      'id|+1': 1,
      name: '@cname',
      phone: /^1[34578]\d{9}$/,
      'age|11-99': 1,
      address: '@province()',
      isMale: '@boolean',
      email: '@email',
      status: '@boolean',
      'roleId|1': [1, 2, 3],
      'roleName|1': function() {
        return ["管理员", "教师", "学生"][this.roleId - 1]
      },
      createTime: '@datetime',
      avatar: function () {
        return Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', this.name.substr(0, 1))
      }
    }
  ],
  page: {
    total: 100,
    current: 1
  }
})

module.exports = {

  'GET /api/adminItem' (req, res) {
    const getItem = qs.parse(req.query)
    const adminItem = admin.data.find(function (item) {
      return item.id == +getItem.id
    })
    res.json({success: true, data: adminItem})
  },

  'GET /api/admin' (req, res) {
    const page = qs.parse(req.query)
    const pageSize = page.pageSize || 10
    const currentPage = page.current || 1

    let data
    let newPage

    let newData = admin.data.concat()

    if (page.field) {
      const d = newData.filter(function (item) {
        return item[page.field].indexOf(decodeURI(page.keyword)) > -1
      })

      data = d.slice((currentPage - 1) * pageSize, currentPage * pageSize)

      newPage = {
        current: currentPage * 1,
        total: d.length
      }
    } else {
      data = admin.data.slice((currentPage - 1) * pageSize, currentPage * pageSize)
      admin.page.current = currentPage * 1
      newPage = admin.page
    }
    res.json({success: true, data, page: {...newPage, pageSize: Number(pageSize)}})
  },

  'POST /api/admin' (req, res) {
    const newData = req.body
    newData.createTime = Mock.mock('@now')
    newData.avatar = Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', newData.name.substr(0, 1))

    const roleListData = global['AccountRoleList'].data
    const roleList = roleListData.map(item => {
      return item.name
    })
    newData.roleName = roleList[newData.roleId - 1]

    newData.id = admin.data.length + 1
    admin.data.unshift(newData)

    admin.page.total = admin.data.length
    admin.page.current = 1

    // global[dataKey] = AdminListData

    res.json({success: true, data: admin.data, page: admin.page})
  },

  'DELETE /api/admin' (req, res) {
    const deleteItem = req.body
    admin.data = admin.data.filter(function (item) {
      if (item.id === deleteItem.id) {
        return false
      }
      return true
    })

    admin.page.total = admin.data.length

    // global[dataKey] = AdminListData

    res.json({success: true, data: admin.data, page: admin.page})
  },

  'PUT /api/admin' (req, res) {
    const editItem = req.body

    const roleListData = global['AccountRoleList'].data
    const roleList = roleListData.map(item => {
      return item.name
    })

    editItem.createTime = Mock.mock('@now')
    editItem.avatar = Mock.Random.image('100x100', Mock.Random.color(), '#757575', 'png', editItem.name.substr(0, 1))
    editItem.roleName = roleList[editItem.roleId - 1]

    admin.data = admin.data.map(function (item) {
      if (item.id === editItem.id) {
        return editItem
      }
      return item
    })

    // global[dataKey] = AdminListData
    res.json({success: true, data: admin.data, page: admin.page})
  }

}
<|endoftext|>


<commit_before>// Constructor for answers
var Answer = function (data) {
    this.name = ko.observable(data.name);
    this.count = ko.observable(0);
};

var ViewModel = function () {

    // This just makes it easier to understand things.
    var self = this;

    // Set up our variables
    self.question = ko.observable("What is your favorite color?");
    self.answers = ko.observableArray([
        new Answer({
            name: "Red"
        }),
        new Answer({
            name: "Blue"
        }),
        new Answer({
            name: "Green"
        })
    ]);
    self.selectedAnswer = ko.observable("");
    self.totalCount = ko.observable(0);

    // Function to handle a user clicking an answer
    self.surveyAnswer = function (answer) {
        self.selectedAnswer(answer.name());
        var thisAnswer = ko.utils.arrayFirst(self.answers(), function (ans) {
            return ans.name() === answer.name();
        });
        thisAnswer.count(thisAnswer.count() + 1);
        self.totalCount(self.totalCount() + 1);
        self.selectedAnswer(answer.name());
        self.currentView("results");
    }
};

// Give some time for libraries to load
setTimeout(function() {
    ko.applyBindings(new ViewModel());
}, 500);<commit_msg>Added README<commit_after>// Constructor for answers
var Answer = function (data) {
    this.name = ko.observable(data.name);
    this.count = ko.observable(0);
};

var ViewModel = function () {

    // This just makes it easier to understand things.
    var self = this;

    // Set up our variables
    self.question = ko.observable("What is your favorite color?");
    self.answers = ko.observableArray([
        new Answer({
            name: "Red"
        }),
        new Answer({
            name: "Blue"
        }),
        new Answer({
            name: "Green"
        })
    ]);
    self.selectedAnswer = ko.observable("");
    self.totalCount = ko.observable(0);

    // Function to handle a user clicking an answer
    self.surveyAnswer = function (answer) {
        self.selectedAnswer(answer.name());
        var thisAnswer = ko.utils.arrayFirst(self.answers(), function (ans) {
            return ans.name() === answer.name();
        });
        thisAnswer.count(thisAnswer.count() + 1);
        self.selectedAnswer(answer.name());
    }
};

// Give some time for libraries to load
setTimeout(function() {
    ko.applyBindings(new ViewModel());
}, 500);<|endoftext|>


<commit_before>function wuvtLive(liveurl) {
    if(typeof EventSource == 'undefined') {
        // cannot use server-sent events, boo
        return;
    }

    var source = new EventSource(liveurl);
    source.onmessage = function(ev) {
        msg = JSON.parse(ev.data);
        if(msg['event'] == "track_change") {
            var track = msg['tracklog']['track'];
            $('#current_track').text(track['artist'] + " - " +
                    track['title']);
            $('#current_dj').text(msg['tracklog']['dj']);

            if($('#trackable')) {
                updateLast15(msg['tracklog']);
            }
        }
    };
}

function updateLast15(tracklog) {
    if($('#tracktable tbody tr').length >= 15) {
        // remove last item if already 15 tracks
        $('#tracktable tbody tr:last-child').remove();
    }

    function pad(value) {
        return ("00" + value).slice(-2);
    }

    var track = tracklog['track'];
    var tr = document.createElement('tr');

    var td = document.createElement('td');
    var played = new Date(tracklog['played']);
    $(td).text("{0}:{1}:{2}".format(pad(played.getHours()),
                                    pad(played.getMinutes()),
                                    pad(played.getSeconds())));
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['new'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-fire new-track";
        $(td).append(span);
    }
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['artist']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['title']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['album']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(tracklog['dj']);
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['request'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-earphone";
        $(td).append(span);
    }
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['vinyl'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-cd";
        $(td).append(span);
    }
    $(tr).append(td);

    $('#tracktable tbody').prepend(tr);
}

function makeAjaxLink(item) {
    var absoluteRegex = new RegExp("^([a-z]+://|//)");
    var domainRegex = new RegExp(location.host);
    var staticRegex = new RegExp("/static/");
    var href = $(item).attr('href');

    if(!href || href.charAt(0) == '#' || staticRegex.test(href) ||
       (absoluteRegex.test(href) && !domainRegex.test(href))) {
        return;
    }

    $(item).click(function(ev) {
        path = ev.target.href;
        window.history.pushState({'path': path}, item.innerText, path);
        loadPage(path);

        return false;
    });
}

function loadPage(path) {
    $.ajax({
        'url': path,
        'dataType': 'html',
    }).done(function(data) {
        var doc = $('<div>').append($.parseHTML(data));
        $('title').text(doc.find('title').text());
        $('#side_primary').html(doc.find('#side_primary > *'));
        $('#content').html(doc.find('#content > *'));

        $.each($('#side_primary a'), function(i, item){makeAjaxLink(item);});
        $.each($('#content a'), function(i, item){makeAjaxLink(item);});

        // build date picker
        if($('#datepicker')) {
            $('#datepicker').datepicker({
                'dateFormat': "yy/mm/dd",
                'minDate': "2007/01/01",
                'maxDate': 0,
                'changeMonth': true,
                'changeYear': true,
                'prevText': "«",
                'nextText': "»",
                'onSelect': function(dt) {
                    loadPage("/playlists/date/" + dt);
                },
            });
        }
    }).fail(function(data) {
        var doc = $('<div>').append($.parseHTML(data.responseText));
        $('title').text(doc.find('title').text());
        $('#side_primary').html(doc.find('#side_primary > *'));
        $('#content').html(doc.find('#content > *'));

        $.each($('#side_primary a'), function(i, item){makeAjaxLink(item);});
        $.each($('#content a'), function(i, item){makeAjaxLink(item);});
    });
}
<commit_msg>reconnect when EventSource hits error<commit_after>var liveReconnectTimer;

function wuvtLive(liveurl) {
    if(typeof EventSource == 'undefined') {
        // cannot use server-sent events, boo
        return;
    }

    var source = new EventSource(liveurl);
    source.onmessage = function(ev) {
        msg = JSON.parse(ev.data);
        if(msg['event'] == "track_change") {
            var track = msg['tracklog']['track'];
            $('#current_track').text(track['artist'] + " - " +
                    track['title']);
            $('#current_dj').text(msg['tracklog']['dj']);

            if($('#tracktable')) {
                updateLast15(msg['tracklog']);
            }
        }
    };
    source.onerror = function(e) {
        if(liveReconnectTimer == null) {
            // attempt to reconnect after 15 seconds
            liveReconnectTimer = setTimeout(function() {
                liveReconnectTimer = null;
                wuvtLive(liveurl);
            }, 15000);
        }
    };
}

function updateLast15(tracklog) {
    if($('#tracktable tbody tr').length >= 15) {
        // remove last item if already 15 tracks
        $('#tracktable tbody tr:last-child').remove();
    }

    function pad(value) {
        return ("00" + value).slice(-2);
    }

    var track = tracklog['track'];
    var tr = document.createElement('tr');

    var td = document.createElement('td');
    var played = new Date(tracklog['played']);
    $(td).text("{0}:{1}:{2}".format(pad(played.getHours()),
                                    pad(played.getMinutes()),
                                    pad(played.getSeconds())));
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['new'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-fire new-track";
        $(td).append(span);
    }
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['artist']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['title']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(track['album']);
    $(tr).append(td);

    var td = document.createElement('td');
    $(td).text(tracklog['dj']);
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['request'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-earphone";
        $(td).append(span);
    }
    $(tr).append(td);

    var td = document.createElement('td');
    if(tracklog['vinyl'] == true) {
        var span = document.createElement('span');
        span.className = "glyphicon glyphicon-cd";
        $(td).append(span);
    }
    $(tr).append(td);

    $('#tracktable tbody').prepend(tr);
}

function makeAjaxLink(item) {
    var absoluteRegex = new RegExp("^([a-z]+://|//)");
    var domainRegex = new RegExp(location.host);
    var staticRegex = new RegExp("/static/");
    var href = $(item).attr('href');

    if(!href || href.charAt(0) == '#' || staticRegex.test(href) ||
       (absoluteRegex.test(href) && !domainRegex.test(href))) {
        return;
    }

    $(item).click(function(ev) {
        path = ev.target.href;
        window.history.pushState({'path': path}, item.innerText, path);
        loadPage(path);

        return false;
    });
}

function loadPage(path) {
    $.ajax({
        'url': path,
        'dataType': 'html',
    }).done(function(data) {
        var doc = $('<div>').append($.parseHTML(data));
        $('title').text(doc.find('title').text());
        $('#side_primary').html(doc.find('#side_primary > *'));
        $('#content').html(doc.find('#content > *'));

        $.each($('#side_primary a'), function(i, item){makeAjaxLink(item);});
        $.each($('#content a'), function(i, item){makeAjaxLink(item);});

        // build date picker
        if($('#datepicker')) {
            $('#datepicker').datepicker({
                'dateFormat': "yy/mm/dd",
                'minDate': "2007/01/01",
                'maxDate': 0,
                'changeMonth': true,
                'changeYear': true,
                'prevText': "«",
                'nextText': "»",
                'onSelect': function(dt) {
                    loadPage("/playlists/date/" + dt);
                },
            });
        }
    }).fail(function(data) {
        var doc = $('<div>').append($.parseHTML(data.responseText));
        $('title').text(doc.find('title').text());
        $('#side_primary').html(doc.find('#side_primary > *'));
        $('#content').html(doc.find('#content > *'));

        $.each($('#side_primary a'), function(i, item){makeAjaxLink(item);});
        $.each($('#content a'), function(i, item){makeAjaxLink(item);});
    });
}
<|endoftext|>


<commit_before>enyo.kind({
	name: "TamTam.Simon",
	components: [
        {classes: "Simon-info", components: [
            {name: "SimonLevel", classes: "Simon-level", content: ""},
            {name: "SimonScroe", classes: "Simon-scroe", content: ""}
        ]},
        {classes: "Simon", components: [
            {classes: "Simon-game", components: [
                {name: "Red", classes: "Simon-button red", ontap: "handlePlayNote"},
                {name: "Green", classes: "Simon-button green", ontap: "handlePlayNote"},
                {name: "Yellow", classes: "Simon-button yellow", ontap: "handlePlayNote"},
                {name: "Blue", classes: "Simon-button blue", ontap: "handlePlayNote"},
                {classes: "Simon-centre Simon-centre-black",
                    components: [{
                        classes: "Simon-centre Simon-centre-white",
                        components: [
                            {name: "SimonStart", id: "SimonStart", classes: "Simon-start", content: "", ontap: "startGame"},
                        ]
                    }]
                }
            ]},
        ]}
    ],

    handlePlayNote: function(s) {
        var colors = ["Red", "Green", "Yellow", "Blue"];
        if(s.repeat || !simonMode) return;

        var fromKeyPress = false;
		if(s.type == "keydown") {
			fromKeyPress = true;
        }

        var keyColourMap = {
            'ArrowUp': 'Red',
            'ArrowDown': 'Blue',
            'ArrowRight': 'Green',
            'ArrowLeft': 'Yellow'
        }

        if (fromKeyPress){
            this.clickColor(keyColourMap[s.key]);
            this.userSequence.push(keyColourMap[s.key]);
        } else {
            this.clickColor(s.name);
            this.userSequence.push(s.name);
        }
        this.$.SimonStart.setContent(this.userSequence.length);
        var correct = this.userSequence[this.userSequence.length-1] === this.correctSequence[this.userSequence.length-1]
        if (!correct){
            this.correctSequence = [];
            this.userSequence = [];
            this.level = 1;
            this.keysEnabled = false;
            this.$.SimonLevel.setContent(this.LEVEL_MSG + " : " + this.level);
            this.$.SimonStart.show();
            this.$.SimonStart.setContent(this.WRONG_MSG);
            this.$.SimonStart.addRemoveClass('wrongRed', true);
            this.showStart();
        }

        if (correct && this.correctSequence.length === this.userSequence.length){
            var steps = this.level + 1;
            // n points for nth step in a level
            this.score += steps*(steps + 1)/2;
            this.userSequence = [];
            this.level++;
            this.keysEnabled = false;
            this.$.SimonLevel.setContent(this.LEVEL_MSG + " : " + this.level);
            this.$.SimonScroe.setContent(this.SCORE_MSG + " : " + this.score);
            this.$.SimonStart.setContent(this.RIGHT_MSG);
            this.$.SimonStart.addRemoveClass('rightGreen', true);
            this.showStart();
        }
    },

    showStart: function(){
        var colors = ["Red", "Green", "Yellow", "Blue"];
        this.timeouts.push(setTimeout(function(){
            this.$.SimonStart.addRemoveClass('rightGreen', false);
            this.$.SimonStart.addRemoveClass('wrongRed', false);
            this.$.SimonStart.addRemoveClass('disableElement', false);
            this.startGame();
        }.bind(this), 2000));
    },

    clickColor(colorName){
        var colorMap = {
            "Red": "A",
            "Green": "E",
            "Blue": "E",
            "Yellow": "C-s"
        }
        this.$[colorName].addRemoveClass('darkenElement', true);
        this.timeouts.push(setTimeout(function(){
            this.$[colorName].addRemoveClass('darkenElement', false);
        }.bind(this), 1000));

        var pitchName = colorMap[colorName];
		var pitchMap = {
			'C-s': 1,
			'E': 4,
			'A': 9,
        };
		tonePlayer.play(pitchMap[pitchName]);
    },

    handlePlayNoteListener: function(event) {
        if (this.keysEnabled){
            this.handlePlayNote(event);
        }
    },

    create: function() {
		this.inherited(arguments);
        this.collection = 0;
        this.level = 1;
        this.correctSequence = [];
        this.userSequence = [];
        this.score = 0;
        this.keysEnabled = false;
        this.timeouts = [];

        var that = this;
        requirejs(["webL10n"], function(webL10n) {
            that.START_MSG = webL10n.get("SimonStartMsg");
            that.SCORE_MSG = webL10n.get("SimonScoreMsg");
            that.LEVEL_MSG = webL10n.get("SimonLevelMsg");
            that.WRONG_MSG = webL10n.get("SimonWrongMsg");
            that.RIGHT_MSG = webL10n.get("SimonRightMsg");
            that.$.SimonStart.setContent(that.START_MSG);
            that.$.SimonLevel.setContent(that.LEVEL_MSG + " : " + that.level);
            that.$.SimonScroe.setContent(that.SCORE_MSG + " : " + that.score);
        });
        that.handlePlayNoteListener = that.handlePlayNoteListener.bind(this);
        document.addEventListener('keydown', that.handlePlayNoteListener, false);
        tonePlayer.load('audio/database/'+currentSimonMode+".mp3");
        this.addRemoveAll(["Red", "Green", "Yellow", "Blue"], 'disableElement', true);
		return;
    },

    startGame: function(){
        this.keysEnabled = false;
        var colors = ["Red", "Green", "Yellow", "Blue"];
        this.addRemoveAll(["SimonStart"].concat(colors), 'disableElement', true);

        var randomColor = colors[Math.floor(Math.random()*4)];
        this.correctSequence.push(randomColor);
        var delay = 1000;
        for(let steps = 0; steps < this.level; steps++){
            this.timeouts.push(setTimeout(function(){
                this.clickColor(this.correctSequence[steps]);
                this.$.SimonStart.setContent(steps + 1);
            }.bind(this), delay));
            delay += 1100;
        }
        this.timeouts.push(setTimeout(function(){
            this.addRemoveAll(colors, 'disableElement', false);
            this.keysEnabled = true;
            this.$.SimonStart.setContent("");
        }.bind(this), delay));
    },

    destroy: function () {
        var that = this;
        that.timeouts.forEach((id)=>clearTimeout(id));
        that.inherited(arguments);
        document.removeEventListener('keydown', that.handlePlayNoteListener, false);
    },

    // adds or removes a class from all elements
    addRemoveAll: function(elements, className, add){
        elements.forEach(function(element){
            this.$[element].addRemoveClass(className, add);
        }.bind(this));
    }
});<commit_msg>some bug fixes<commit_after>enyo.kind({
	name: "TamTam.Simon",
	components: [
        {classes: "Simon-info", components: [
            {name: "SimonLevel", classes: "Simon-level", content: ""},
            {name: "SimonScroe", classes: "Simon-scroe", content: ""}
        ]},
        {classes: "Simon", components: [
            {classes: "Simon-game", components: [
                {name: "Red", classes: "Simon-button red", ontap: "handlePlayNote"},
                {name: "Green", classes: "Simon-button green", ontap: "handlePlayNote"},
                {name: "Yellow", classes: "Simon-button yellow", ontap: "handlePlayNote"},
                {name: "Blue", classes: "Simon-button blue", ontap: "handlePlayNote"},
                {classes: "Simon-centre Simon-centre-black",
                    components: [{
                        classes: "Simon-centre Simon-centre-white",
                        components: [
                            {name: "SimonStart", id: "SimonStart", classes: "Simon-start", content: "", ontap: "startGame"},
                        ]
                    }]
                }
            ]},
        ]}
    ],

    handlePlayNote: function(s) {
        var colors = ["Red", "Green", "Yellow", "Blue"];
        if(s.repeat || !simonMode) return;

        var fromKeyPress = false;
		if(s.type == "keydown") {
			fromKeyPress = true;
        }

        var keyColourMap = {
            'ArrowUp': 'Red',
            'ArrowDown': 'Blue',
            'ArrowRight': 'Green',
            'ArrowLeft': 'Yellow'
        }

        if (fromKeyPress){
            this.clickColor(keyColourMap[s.key]);
            this.userSequence.push(keyColourMap[s.key]);
        } else {
            this.clickColor(s.name);
            this.userSequence.push(s.name);
        }
        this.$.SimonStart.setContent(this.userSequence.length);
        var correct = this.userSequence[this.userSequence.length-1] === this.correctSequence[this.userSequence.length-1]
        if (!correct){
            this.correctSequence = [];
            this.userSequence = [];
            this.level = 1;
            this.keysEnabled = false;
            this.$.SimonLevel.setContent(this.LEVEL_MSG + " : " + this.level);
            this.$.SimonStart.show();
            this.$.SimonStart.setContent(this.WRONG_MSG);
            this.$.SimonStart.addRemoveClass('wrongRed', true);
            this.addRemoveAll(["Red", "Green", "Yellow", "Blue"], 'disableElement', true);
            this.showStart();
        }

        if (correct && this.correctSequence.length === this.userSequence.length){
            // n points for nth step in a level
            this.score += this.level*(this.level + 1)/2;
            this.userSequence = [];
            this.level++;
            this.keysEnabled = false;
            this.$.SimonLevel.setContent(this.LEVEL_MSG + " : " + this.level);
            this.$.SimonScroe.setContent(this.SCORE_MSG + " : " + this.score);
            this.$.SimonStart.setContent(this.RIGHT_MSG);
            this.$.SimonStart.addRemoveClass('rightGreen', true);
            this.addRemoveAll(["Red", "Green", "Yellow", "Blue"], 'disableElement', true);
            this.showStart();
        }
    },

    showStart: function(){
        var colors = ["Red", "Green", "Yellow", "Blue"];
        this.timeouts.push(setTimeout(function(){
            this.$.SimonStart.addRemoveClass('rightGreen', false);
            this.$.SimonStart.addRemoveClass('wrongRed', false);
            this.$.SimonStart.addRemoveClass('disableElement', false);
            this.startGame();
        }.bind(this), 2000));
    },

    clickColor(colorName){
        var colorMap = {
            "Red": "A",
            "Green": "E",
            "Blue": "E",
            "Yellow": "C-s"
        }
        this.$[colorName].addRemoveClass('darkenElement', true);
        this.timeouts.push(setTimeout(function(){
            this.$[colorName].addRemoveClass('darkenElement', false);
        }.bind(this), 1000));

        var pitchName = colorMap[colorName];
		var pitchMap = {
			'C-s': 1,
			'E': 4,
			'A': 9,
        };
		tonePlayer.play(pitchMap[pitchName]);
    },

    handlePlayNoteListener: function(event) {
        if (this.keysEnabled){
            this.handlePlayNote(event);
        }
    },

    create: function() {
		this.inherited(arguments);
        this.collection = 0;
        this.level = 1;
        this.correctSequence = [];
        this.userSequence = [];
        this.score = 0;
        this.keysEnabled = false;
        this.timeouts = [];

        var that = this;
        requirejs(["webL10n"], function(webL10n) {
            that.START_MSG = webL10n.get("SimonStartMsg");
            that.SCORE_MSG = webL10n.get("SimonScoreMsg");
            that.LEVEL_MSG = webL10n.get("SimonLevelMsg");
            that.WRONG_MSG = webL10n.get("SimonWrongMsg");
            that.RIGHT_MSG = webL10n.get("SimonRightMsg");
            that.$.SimonStart.setContent(that.START_MSG);
            that.$.SimonLevel.setContent(that.LEVEL_MSG + " : " + that.level);
            that.$.SimonScroe.setContent(that.SCORE_MSG + " : " + that.score);
        });
        that.handlePlayNoteListener = that.handlePlayNoteListener.bind(this);
        document.addEventListener('keydown', that.handlePlayNoteListener, false);
        tonePlayer.load('audio/database/'+currentSimonMode+".mp3");
        this.addRemoveAll(["Red", "Green", "Yellow", "Blue"], 'disableElement', true);
		return;
    },

    startGame: function(){
        this.keysEnabled = false;
        var colors = ["Red", "Green", "Yellow", "Blue"];
        this.addRemoveAll(["SimonStart"].concat(colors), 'disableElement', true);

        var randomColor = colors[Math.floor(Math.random()*4)];
        this.correctSequence.push(randomColor);
        var delay = 1000;
        for(let steps = 0; steps < this.level; steps++){
            this.timeouts.push(setTimeout(function(){
                this.clickColor(this.correctSequence[steps]);
                this.$.SimonStart.setContent(steps + 1);
            }.bind(this), delay));
            delay += 1100;
        }
        this.timeouts.push(setTimeout(function(){
            this.addRemoveAll(colors, 'disableElement', false);
            this.keysEnabled = true;
            this.$.SimonStart.setContent("");
        }.bind(this), delay));
    },

    destroy: function () {
        var that = this;
        that.timeouts.forEach((id)=>clearTimeout(id));
        that.inherited(arguments);
        document.removeEventListener('keydown', that.handlePlayNoteListener, false);
    },

    // adds or removes a class from all elements
    addRemoveAll: function(elements, className, add){
        elements.forEach(function(element){
            this.$[element].addRemoveClass(className, add);
        }.bind(this));
    }
});<|endoftext|>